...
a. there is a join (let's call it J1.) in the nested plan,
b. if J1 is an inner join, one input pipeline of J1 has a NestedTupleSource descendant (let's call it N1),
c. if J1 is a left outer join, the left branch of J1 has a NestedTupleSource descendant (let's call it N1),
d. there is no tuple dropping from N1 to J1
...
R4'. For every left join from N1 to J1 transformed from an inner join, a variable vi indicating non-match tuples is assigned to TRUE in its right branch;
R4R5'. On top of J1, a GroupByOperaptor G1 is added where the group-by key is the primary key of O1 and the nested query plan for aggregation is the nested pipeline on top of J1 with an added not-null-filter to check all vi are not null.
R5R6'. All other NestedTupleSourceOperators in the subplan is inlined with deep copies (with new variables) of the query plan rooted at O1.
...
--NestedOp
– Inner Join (J1)
– – (Right branch) ..... (L1)
– (Left branch) ..... (R1)
--Nested-Tuple-Source
– ..... (R1) }
--InputOp
.....
(Note that pipeline L1 R1 must satisfy the condition that it does not drop any tuples.)
...
--LeftOuterJoin (J1)
(left branch) – Assign v_new=TRUE
– ...... (L1R1)
– InputOp
.....
(right branch)
– Assign v_new=TRUE
– ..... (R1L1)
In the plan, v_lc_1, ..., v_lc_n are live "covering" variables at InputOp and v_l1, ....v_ln in the decoration part of the added group-by operator are all live variables at InputOp except the covering variables v_lc_1, ..., v_lc_n. In the current implementation, we use "covering" variables as primary key variables. In the next version, we will use the real primary key variables, which will fix ASTERIXDB-1168.
...