Relational testbed

This page demonstrates relational algebra by a simple interactive implementation. The algebra is loosely based on the ISBL language of PRTV, reworked in a javascript environment.

The page has three sections. The first shows the relations and operations. The second very briefly describes the interactive system and the relational language. The third gives some examples of error situations (in relational language use and in the implementation).

basic relations and their operations

You may edit the expressions (green) see their results (blue).


define two relations

r1 = R(['x','y'],
[4, 7],
[5, 9],
[5, 4],
[6, 7])
answer initialization
using selector followed by array values

r2 = R(
{x:4, z:"bill"},
{x:4, z:"bert"},
{x:5, z:"fred"} )
answer initialization
using Object values

natural join

r1.join(r2) answer

difference

r1.diff(r2) answer

union

r2.union(R({x:6, z:"fred"})) answer

basic select

r1.select("x == 4") answer

basic project

r1.project("x") answer

basic rename

r1.rename("rr <- x") answer

basic extend

r1.extend("c := x+4") answer

extend and remove x

r1.extend("c := x+4, ~x") answer

project with compute

r1.project("c := x+4") answer

project with compute

r1.project("c := x+4, x") answer

compute and filter

r1.project("c := x+4, x == 5") answer

empty and zero column relations

This implementation supports the two zero degree relations, {{}} (true) which contains the empty tuple, and {} (false) which is an empty relation.

The table form of HTML naturally generated for TABLE_DUM and TABLE_DEE are logically correctly different. However, (at least on Crome) they render identically on the page. The code therefore inserts the artificial "-" in TABLE_DEE so the empty tuple is visible.

It supports empty relations, but these are not typed. It is argued whether or not empty relations should be typed. I prefer typed empty relations; this implementation does not support them as that keeps the implementation as small as possible.

r1.select("x==7") answer
r1.diff(r1) answer
r1.project() answer
r1.select("x==7").project() answer
TABLE_DUM = R(); answer
TABLE_DEE = R({}); answer

tuple expressions as objects

This shows (embryonic) support for tuple expressions as variables.

tx=TX("c := x+4") answer
r1.extend(tx) answer
tx2 = tx.compose("x == 5") answer
r1.extend(tx2) answer

prepare for nested relations

Nested relations are not fully implemented yet, but we are getting there ....

r3 = R({a:4, nest: r1}) answer
q=r1.group("x", "yg") answer
q=r1.group("", "xyg") answer
q=r1.group("x,y", "zerog") answer

// test here answer

using the system

You may edit the green values. Those are to the left of the blue results; the green is not very clear.

This is part of an experiment for a system that is a combination of 'active' html document editor, calculator and basic spreadsheet. The green/blue pairs are javascript expressions and results. This is not specific to relations; you can enter almost any valid javascript, including loop expressions etc. Functions must be coded as x = function() ..., not as function x(),

relations

A Relation is defined using R() in one of two javascript formats demonstrated above: either javascript Objects, or an array or arrays with the first element being the array of selectors. The operations on relations are:

this.join(b)
natural join of this with b
this.diff(b)
generalized difference of this with b
this.extend(expr)
extend using the string expression (see below)
this.project(expr)
project using the string expression (see below)
this.rename(expr)
same as extend (see below)
this.select(expr)
same as extend (see below)

Typing and error checking is incomplete and much later than it should be in a real system. Some examples of bad things are included below.

extend and project tuple expressions

The EXTEND/PROJECT tuple expression is currently coded as a string, which is converted to a javascript function Tuple->Tuple. I may change the project later to use more properly structured expressions with cleaner semantics.

The tuple expression is a semicolon separated list of terms. Terms can include 'obvious' javascript, and are of the form

x1 = x2
The result of using javascript '=' is undefined (generally error)
selector := jsexpression
selector assignment to output tuple
selector <- selector
rename
selector
include this selector in the output (for project)
~selector
remove this selector from the output (for extend)
*
copy all selector values from input to output tuple
~
empty output tuple
jsexpression
javascript expression used as filter, usual javascript rules if it does not evaluate to a boolean (for filter)

Reference to a selector on the right hand side of the expression refers to the value of that selector in the output tuple if present, and to the value in the input tuple if not.

The only difference between EXTEND and PROJECT is that for EXTEND the output tuple is initialized to the input tuple, and for PROJECT the output tuple is initialized to the empty tuple. The two can be turned into each other by prefixing the expression with "*;" or "~;".

rename and select are included for syntactic reference, and are both identical to extend. There are restrictions that could be put on pure expressions, this implementation does not enforce these.

There are other restrictions that maybe should be applied but are not in this trivial code; for example := assignment should not be allowed to overwrite an already existing selector.


Examples of incorrect things

This section has some examples of wrong things.

union compatibility

R({a:4}).union(R({b:5})) answer

wrong selectors

No complaint that q is not a selector.
R({a:4}).extend("~q") answer

wrong selectors

No complaint that a is being overwritten, though there should be an explicit overwrite operator where that is expressly intended.
R({a:4}).extend("a := a+4") answer

wrong selectors

Correct complaint that b is missing.
R({a:4}).extend("a := b+4") answer

Bad parsing

Our expression 'parser' screws up on the ;.
R({a:"fred"}).extend("a := "re;ed") answer