Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for TableDum and TableDee (Tutorial D) #212

Open
wants to merge 3 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/calc2/views/help.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,38 @@ export class Help extends React.Component<Props> {
<li>Thus, <code className="">S ∪ S</code> ≠ <code className="">S</code> in general.</li>
</ul>

<h4 id="tutorial-user-dum-dee">dum and dee</h4>

<p><a href="https://dn-uni.com/wp-content/uploads/2018/12/An-Introduction-to-Relational-Database-Theory.pdf">
Tutorial D</a> proposes two special relations, which have been given the pet names
TableDum and TableDee (abbreviated to just Dum and Dee, respectively). TableDum
denotes a relation of degree zero (no attributes) and cardinality zero (no tuples),
whereas TableDee represents a relation of degree zero and cardinality one (there is
one single tuple!).</p>

<p>A predicate represented by a relation of degree zero is <i>niladic</i> (has no
parameters). In other words, it must be a proposition, <i>p</i>. If TableDee
represents <i>p</i>, then <i>p</i> is true (identity relation under join operators);
otherwise TableDum represents <i>p</i> and <i>p</i> is false. People often ask,
<i>"What purpose can relations of degree zero possibly serve? They seem to be
of little or no value."</i> The answer is that they represent answers to queries
of the form <i>"Is it true that ...?"</i> or <i>"Are there any ...?</i> where the
answer is just yes or no.</p>

<p>Dum and Dee relations can be represented as follows:</p>

<code className="example block">
Dum = {`{}`} -- inline relation with empty heading and no tuples<br/>
Dee = {`{()}`} -- inline relation with empty heading but one tuple of degree zero<br/>
</code>

<p>Given a relation R with <i>n</i> (<i>n</i> {'> 0'}) attributes and <i>t</i> (<i>t</i> {'> 0'}) tuples</p>

<code className="example block">
R x Dum -- returns a relation with the same schema of R but no tuples<br/>
R x Dee -- returns the very same relation R<br/>
</code>

<h3 id="tutorial-user-plain-text-notation">Alternative plain text notation</h3>

<p>Before we introduce how to use the operators this should be a quick introduction of a very handy feature
Expand Down
29 changes: 28 additions & 1 deletion src/db/parser/grammar_bags.pegjs
Original file line number Diff line number Diff line change
Expand Up @@ -1241,9 +1241,36 @@ tableRow
return t;
}

tableDum
= '{' _ '}' // relation of degree zero and cardinality zero
{
return {
type: 'table',
name: '_inlineRelation'+(inlineTableNum++),
columns: [],
rows: [],

codeInfo: getCodeInfo()
};
}

tableDee
= '{' _ '(' _ ')' _ '}' // relation of degree zero and cardinality one
{
return {
type: 'table',
name: '_inlineRelation'+(inlineTableNum++),
columns: [],
rows: [[]],

codeInfo: getCodeInfo()
};
}

table
= '{' _ cols:tableHeader _sl trows:(endOfLine _ tableRow _sl)* _ '}'
= tableDum
/ tableDee
/ '{' _ cols:tableHeader _sl trows:(endOfLine _ tableRow _sl)* _ '}'
{
var numCols = cols.length;

Expand Down
29 changes: 28 additions & 1 deletion src/db/parser/grammar_ra.pegjs
Original file line number Diff line number Diff line change
Expand Up @@ -1224,9 +1224,36 @@ tableRow
return t;
}

tableDum
= '{' _ '}' // relation of degree zero and cardinality zero
{
return {
type: 'table',
name: '_inlineRelation'+(inlineTableNum++),
columns: [],
rows: [],

codeInfo: getCodeInfo()
};
}

tableDee
= '{' _ '(' _ ')' _ '}' // relation of degree zero and cardinality one
{
return {
type: 'table',
name: '_inlineRelation'+(inlineTableNum++),
columns: [],
rows: [[]],

codeInfo: getCodeInfo()
};
}

table
= '{' _ cols:tableHeader _sl trows:(endOfLine _ tableRow _sl)* _ '}'
= tableDum
/ tableDee
/ '{' _ cols:tableHeader _sl trows:(endOfLine _ tableRow _sl)* _ '}'
{
var numCols = cols.length;

Expand Down
84 changes: 84 additions & 0 deletions src/db/tests/translate_tests_bags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,90 @@ QUnit.test('test bag R', function (assert) {
assert.deepEqual(root.getResult(false), relations.R.getResult(false));
});

QUnit.test('test dum bag 1', function (assert) {
const relations = getTestBags();
const root = exec_ra(`pi 1->a {}`, relations);

const ref = exec_ra(`sigma a<1 {
a

10
}`, relations);

assert.deepEqual(root.getResult(false), ref.getResult(false));
});

QUnit.test('test dum bag 2', function (assert) {
const relations = getTestBags();
const root = exec_ra(`gamma count(*)->n {}`, relations);

const ref = exec_ra(`{
n

0
}`, relations);

assert.deepEqual(root.getResult(false), ref.getResult(false));
});

QUnit.test('test dum bag 3', function (assert) {
const relations = getTestBags();
const root = exec_ra(`R x {}`, relations);

const ref = exec_ra(`R - R`, relations);

assert.deepEqual(root.getResult(false), ref.getResult(false));
});

QUnit.test('test dum bag 4', function (assert) {
const relations = getTestBags();
const root = exec_ra(`{} x R`, relations);

const ref = exec_ra(`R - R`, relations);

assert.deepEqual(root.getResult(false), ref.getResult(false));
});

QUnit.test('test dee bag 1', function (assert) {
const relations = getTestBags();
const root = exec_ra(`pi 1->a {()}`, relations);

const ref = exec_ra(`{
a

1
}`, relations);

assert.deepEqual(root.getResult(false), ref.getResult(false));
});

QUnit.test('test dee bag 2', function (assert) {
const relations = getTestBags();
const root = exec_ra(`gamma count(*)->n {()}`, relations);

const ref = exec_ra(`{
n

1
}`, relations);

assert.deepEqual(root.getResult(false), ref.getResult(false));
});

QUnit.test('test dee bag 3', function (assert) {
const relations = getTestBags();
const root = exec_ra(`R x {()}`, relations);

assert.deepEqual(root.getResult(false), relations.R.getResult(false));
});

QUnit.test('test dee bag 4', function (assert) {
const relations = getTestBags();
const root = exec_ra(`{()} x R`, relations);

assert.deepEqual(root.getResult(false), relations.R.getResult(false));
});

QUnit.test('test inline-bag R', function (assert) {
const relations = getTestBags();
const root = exec_ra(`{
Expand Down
84 changes: 84 additions & 0 deletions src/db/tests/translate_tests_ra.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,90 @@ QUnit.test('test relation', function (assert) {
assert.deepEqual(root.getResult(), relations.R.getResult());
});

QUnit.test('test dum relation 1', function (assert) {
const relations = getTestRelations();
const root = exec_ra(`pi 1->a {}`, relations);

const ref = exec_ra(`sigma a<1 {
a

10
}`, relations);

assert.deepEqual(root.getResult(), ref.getResult());
});

QUnit.test('test dum relation 2', function (assert) {
const relations = getTestRelations();
const root = exec_ra(`gamma count(*)->n {}`, relations);

const ref = exec_ra(`{
n

0
}`, relations);

assert.deepEqual(root.getResult(), ref.getResult());
});

QUnit.test('test dum relation 3', function (assert) {
const relations = getTestRelations();
const root = exec_ra(`R x {}`, relations);

const ref = exec_ra(`R - R`, relations);

assert.deepEqual(root.getResult(), ref.getResult());
});

QUnit.test('test dum relation 4', function (assert) {
const relations = getTestRelations();
const root = exec_ra(`{} x R`, relations);

const ref = exec_ra(`R - R`, relations);

assert.deepEqual(root.getResult(), ref.getResult());
});

QUnit.test('test dee relation 1', function (assert) {
const relations = getTestRelations();
const root = exec_ra(`pi 1->a {()}`, relations);

const ref = exec_ra(`{
a

1
}`, relations);

assert.deepEqual(root.getResult(), ref.getResult());
});

QUnit.test('test dee relation 2', function (assert) {
const relations = getTestRelations();
const root = exec_ra(`gamma count(*)->n {()}`, relations);

const ref = exec_ra(`{
n

1
}`, relations);

assert.deepEqual(root.getResult(), ref.getResult());
});

QUnit.test('test dee relation 3', function (assert) {
const relations = getTestRelations();
const root = exec_ra(`R x {()}`, relations);

assert.deepEqual(root.getResult(), relations.R.getResult());
});

QUnit.test('test dee relation 4', function (assert) {
const relations = getTestRelations();
const root = exec_ra(`{()} x R`, relations);

assert.deepEqual(root.getResult(), relations.R.getResult());
});

QUnit.test('test inline-relation', function (assert) {
const relations = getTestRelations();
const root = exec_ra(`{
Expand Down