The Plan That Meant the Same Thing

Conversation 1.3 — From Conjunctive Queries to Named Relational Algebra

The plan that meant the same thing

Ada · 01

We have discussed the logical meaning of

two_hop(from, to) :-
    road(from, via),
    road(via, to).

Quick recap?

Alice

Its result is the set of head tuples produced by valuations that make every body atom true at the same time.

Ada · 02

In computer science, a program can have several useful accounts of its meaning. So far we have used the logical, or model-theoretic, account of a CQ.

It tells us what the correct result must be. But as programmers, knowing the required output is only the first step. We also want to implement it.

Alice

Algorithm!!!

Ada · 03

First inspect what the logical account does not say. A valuation for two_hop has the form

{from -> a, via -> b, to -> c}.

Which variable does the logical semantics assign first?

Alice

None. A valuation is one complete function. The semantics only asks whether all body atoms are true under that function.

That leaves an implementation question: code must choose an order even though the logical semantics does not.

Ada · 04

Let

C1 = road(from, via)
C2 = road(via, to)

and recall that the instance contains

road("Logan", "Salt Lake City")
road("Salt Lake City", "Provo")
road("Logan", "Provo").

It contains no road whose source is "Provo".

The valuation

v = {
    from = "Logan",
    via  = "Salt Lake City",
    to   = "Provo"
}

satisfies \(C_1\land C_2\). Its restrictions are

$$v_1=v|_{\{\mathit{from},\mathit{via}\}} $$

and

$$v_2=v|_{\{\mathit{via},\mathit{to}\}}. $$

They agree on via, and \(v_1\cup v_2=v\). How should we classify \(v_1\) relative to the local schema {from, via}, and relative to the full body schema {from, via, to}?

Alice

It is total on the schema of \(C_1\), so it is a complete local valuation for that atom. It is partial only relative to the full body schema {from, via, to}. The same distinction applies to \(v_2\).

Ada · 05

One successful \(v\) gives only local matches that extend to that full valuation. To collect every local match, for any sub-body \(C\) let

$$\operatorname{Val}_I(C)= \left\{ t:\operatorname{vars}(C)\to D \mid I\models C[t] \right\}. $$

For example,

d = {from = "Logan", via = "Provo"}

belongs to \(\operatorname{Val}_I(C_1)\), but no tuple in \(\operatorname{Val}_I(C_2)\) assigns "Provo" to via. Must \(d\) extend to a valuation satisfying the full body?

Alice

No. It satisfies \(C_1\) locally, but it has no compatible \(C_2\) match. It is a dangling local match.

Ada · 06

At tuple level, the restrictions of a complete valuation agree on shared variables and recombine by union. Natural join lifts that operation to sets: it keeps compatible tuple pairs and emits their unions.

Forward, every valuation satisfying \(C_1\land C_2\) restricts uniquely to compatible members of \(\operatorname{Val}_I(C_1)\) and \(\operatorname{Val}_I(C_2)\). Conversely, compatible members have one well-defined union, and that union satisfies both sub-bodies. Is join merely an analogy for conjunction here?

Alice

No. The two directions show that compatible union produces exactly the valuations satisfying the conjunction.

Ada · 07

What if \(C_1\) and \(C_2\) share no variables?

Alice

Then their valuation-relation schemas are disjoint. Every left tuple is compatible with every right tuple, so the join contains every pairwise union.

Ada · 08

Use the concrete query

three_hop(from, to) :-
    road(from, x),
    road(x, y),
    road(y, to).

Let

$$E_1=\operatorname{Val}_I \bigl(\operatorname{road}(\mathit{from},x)\bigr), $$
$$E_2=\operatorname{Val}_I \bigl(\operatorname{road}(x,y)\bigr), $$

and

$$E_3=\operatorname{Val}_I \bigl(\operatorname{road}(y,\mathit{to})\bigr). $$

Because natural join is binary, give two fully parenthesized expressions that combine all three atom relations.

Alice

Each expression needs two joins. Two possible groupings are

$$(E_1\bowtie E_2)\bowtie E_3 $$

and

$$E_1\bowtie(E_2\bowtie E_3). $$
Ada · 09

Expand either expression using the natural-join definition. Both contain exactly the unions \(e_1\cup e_2\cup e_3\), where \(e_i\in E_i\) and the three tuples agree on every shared variable. Therefore

$$(E_1\bowtie E_2)\bowtie E_3 = E_1\bowtie(E_2\bowtie E_3). $$

This is associativity. The compatible-pair condition is also symmetric in its two inputs, which gives commutativity. What changes between the two three_hop expressions?

Alice

Only their grouping changes. The complete valuation relation stays the same.

Ada · 10

This is the reason relational algebra is a useful bridge. Logic does not choose an order. The algebra does not choose one either, but its laws permit a compiler to choose parentheses while preserving meaning.

Alice

And the parentheses expose different partial valuation relations, even though the final relation is equal.

Ada · 11

Both atoms read the same road relation, whose attributes are src and dst, but their variables need the schemas {from, via} and {via, to}. We relabel the input attributes for each occurrence. This operation is renaming:

E1 := δ[src→from, dst→via](road)
E2 := δ[src→via, dst→to](road).
Alice

One stored relation can therefore provide two differently named atom relations.

Ada · 12

A constant or repeated variable imposes a local condition within one atom:

road("Logan", to)
edge(x, x).

Should those equalities be enforced by joining two atom relations?

Alice

No. Each condition checks positions of one input tuple.

Ada · 13

The one-relation filtering operation is called selection.

Alice

Unlike join, it keeps the relation's existing schema.

Ada · 14

So shared variables across distinct atom relations cause joins; equalities inside one atom cause selections.

Now consider

edge_from_capital(a, b) :-
    edge(a, b),
    capital_city(a).

Let

$$E=\operatorname{Val}_I(\operatorname{edge}(a,b)) \quad\text{and}\quad C=\operatorname{Val}_I(\operatorname{capital\_city}(a)). $$

Their schemas are {a, b} and {a}. What does joining with \(C\) add?

Alice

No attribute. It only tests whether a is a capital city.

Ada · 15

A join whose right input only filters existing tuples without adding attributes has a useful narrower form called semijoin.

Alice

So its result keeps the left relation's schema.

Ada · 16

Because the schema {a} of \(C\) is already contained in the schema {a, b} of \(E\),

$$E\bowtie C=E\ltimes C. $$

Both expressions denote exactly the edges whose first endpoint is a capital city.

Alice

The semijoin spelling records that \(C\) filters edges without extending their schema.

Ada · 17

Return to two_hop. Its complete body-valuation relation has schema {from, via, to}. The separate result relation has schema {from, to}.

New answers accumulate there by set union. If the same answer is derived twice, should the destination contain it twice?

Alice

No. A relation is a set, so adding an existing tuple changes nothing.

Ada · 18

Then try

two_hop := two_hop ∪ (E1 ⋈ E2).
Alice

It is undefined. The destination lacks via, so the two union operands have different schemas.

Ada · 19

Union exposed the problem. Projection keeps the requested attributes, here from and to, while discarding via.

Alice

Then projection can make the body result schema-compatible with the head.

Ada · 20

Now state the result and its accumulation.

Alice
$$two\_hop(I)= \pi_{\mathit{from},\mathit{to}}(E_1\bowtie E_2), $$

and, for a separate destination \(H\),

$$H\leftarrow H\cup two\_hop(I). $$
Ada · 21

This changes \(H\), not road. For a standalone CQ, \(H\) begins empty and remains separate from the input. The same union form will later accumulate rule consequences in Datalog.

Alice

So the CQ derives a separate result without modifying its input instance.

Ada · 22

Complete the two local atom translations now that projection is available.

Alice
leaves_logan(to) :- road("Logan", to).

δ[dst→to](π[dst](σ[src="Logan"](road)))
self_loop(x) :- edge(x, x).

δ[src→x](π[src](σ[src=dst](edge)))
Ada · 23

The examples expose the general pattern. For an atom \(A=r(t_1,\ldots,t_k)\), select constants and equal repeated positions. Project one representative position for each distinct variable, then rename those representatives with the variable names. The resulting expression \(E_A\) denotes exactly \(\operatorname{Val}_I(A)\).

Alice

So each source atom becomes a relation of precisely its satisfying valuations.

Ada · 24

For three_hop, let \(E_1,E_2,E_3\) be the three atom expressions. The CQ body is one conjunction, but the algebra has no three-input join constructor. What must its syntax record?

Alice

A binary tree. For example,

$$(E_1\bowtie E_2)\bowtie E_3 \qquad\text{or}\qquad E_1\bowtie(E_2\bowtie E_3). $$

Each join occurrence has exactly two operands.

Ada · 25

Because each \(E_i\) denotes \(\operatorname{Val}_I(A_i)\), the conjunction-as- join law proves by induction on \(T\) that every \(J_T\) denotes the complete body-valuation relation. Projection then keeps the head variables. Thus every permitted tree \(T\) satisfies

$$[\![E_{q,T}]\!]_I=q(I) $$

for every permitted input instance \(I\).

Alice

So the CQ fixes the result, while \(T\) makes one equivalent binary relational-algebra expression explicit.

Ada · 26

What has the equivalence proof deliberately left open?

Alice

It does not choose the tree \(T\) from among the equivalent logical join plans. That administrative choice is the next conversation.

Recap

The plan that meant the same thing

Let \(B=A_1\land\cdots\land A_n\) be the full CQ body, the conjunction of its original atoms. Its logical semantics defines complete successful valuations,

$$\operatorname{Val}_I(B)= \left\{ v:\operatorname{vars}(B)\to D \mid I\models B[v] \right\}, $$

but no variable-assignment order or body-atom evaluation order. Those orders are irrelevant to which complete valuations satisfy the body.

For \(B=C_1\land C_2\), every complete \(v\in\operatorname{Val}_I(B)\) restricts uniquely to valuations that are total on the schemas of \(C_1\) and \(C_2\), though partial relative to \(B\). The two restrictions agree on their overlap, and their union reconstructs \(v\).

For any sub-body \(C\)—a conjunction of selected original atoms of \(B\) that retains their original variable names—\(\operatorname{Val}_I(C)\) contains all locally satisfying named tuples on the fixed schema \(\operatorname{vars}(C)\). Some may be dangling local matches that do not extend to a complete valuation of \(B\). Natural join composes these relations by compatible union:

$$R\bowtie S= \left\{ r\cup s \mid r\in R,\ s\in S, \ r\text{ and }s\text{ agree on shared attributes} \right\}, $$

and therefore

$$\operatorname{Val}_I(C_1\land C_2)= \operatorname{Val}_I(C_1)\bowtie\operatorname{Val}_I(C_2). $$

When the two schemas are disjoint, compatibility is vacuous and natural join is Cartesian product:

$$R\bowtie S=R\times S, \qquad |R\times S|=|R|\,|S|. $$

Shared variables across atom relations are enforced by join. Constants and repeated variables within one atom are enforced by selection. If a right relation only tests whether a left valuation can be extended, semijoin retains exactly the compatible left tuples.

When answers are accumulated in a separate relation \(H\), set union requires a schema compatible with \(H\). For the fragment used here, the head contains distinct body variables and \(H\) uses those variable names as attributes. Projection therefore removes body-only variables and forms union-compatible tuples:

$$H\leftarrow H\cup \pi_{\operatorname{vars}(\operatorname{head}(q))} \bigl(\operatorname{Val}_I(B)\bigr). $$

Renaming, selection, natural join, and projection give an SPJR expression \(E_q\) satisfying

$$[\![E_q]\!]_I=q(I). $$

Natural join is a binary primitive, while associativity and commutativity prove that different binary groupings preserve this denotation. Polyadic join notation hides the parentheses; a logical plan makes them explicit. Relational algebra therefore does not prescribe an evaluation order: it mathematically licenses an administrative choice of order.