Merge lp:~mmcm/akiban-server/product-nested into lp:~akiban-technologies/akiban-server/trunk

Proposed by Mike McMahon
Status: Merged
Approved by: Mike McMahon
Approved revision: 2723
Merged at revision: 2704
Proposed branch: lp:~mmcm/akiban-server/product-nested
Merge into: lp:~akiban-technologies/akiban-server/trunk
Prerequisite: lp:~mmcm/akiban-server/query-bindings-cancel
Diff against target: 1496 lines (+316/-429)
25 files modified
src/main/java/com/akiban/qp/operator/API.java (+34/-2)
src/main/java/com/akiban/qp/operator/BranchLookup_Nested.java (+23/-15)
src/main/java/com/akiban/qp/operator/Map_NestedLoops.java (+3/-2)
src/main/java/com/akiban/qp/operator/Product_Nested.java (+57/-253)
src/main/java/com/akiban/server/explain/Type.java (+1/-0)
src/main/java/com/akiban/server/explain/format/DefaultFormatter.java (+11/-5)
src/main/java/com/akiban/sql/optimizer/rule/OperatorAssembler.java (+21/-15)
src/test/java/com/akiban/server/test/it/qp/Map_NestedLoopsIT.java (+1/-1)
src/test/java/com/akiban/server/test/it/qp/Product3WayIT.java (+50/-30)
src/test/java/com/akiban/server/test/it/qp/Product_NestedIT.java (+26/-32)
src/test/resources/com/akiban/sql/optimizer/operator/cbo/multiindex-multi-duplicate.expected (+7/-6)
src/test/resources/com/akiban/sql/optimizer/operator/cbo/multiindex-multi-ordered.expected (+7/-6)
src/test/resources/com/akiban/sql/optimizer/operator/cbo/multiple-table-conds-1.expected (+7/-6)
src/test/resources/com/akiban/sql/optimizer/operator/cbo/multiple-table-conds-1.t3expected (+7/-6)
src/test/resources/com/akiban/sql/optimizer/operator/coia-group-index/select-17bu.expected (+6/-5)
src/test/resources/com/akiban/sql/optimizer/operator/coia-text-index/full-text-2.expected (+6/-5)
src/test/resources/com/akiban/sql/optimizer/operator/coia-text-index/full-text-2n.expected (+6/-5)
src/test/resources/com/akiban/sql/optimizer/operator/coia-text-index/full-text-2v.expected (+6/-5)
src/test/resources/com/akiban/sql/optimizer/operator/coia/select-2.expected (+5/-4)
src/test/resources/com/akiban/sql/optimizer/operator/coia/select-5.expected (+5/-4)
src/test/resources/com/akiban/sql/optimizer/operator/coia/select-6.expected (+5/-4)
src/test/resources/com/akiban/sql/optimizer/operator/coia/select-7.expected (+5/-4)
src/test/resources/com/akiban/sql/optimizer/operator/coia/select-8.expected (+6/-5)
src/test/resources/com/akiban/sql/optimizer/rule/operator/full-text-2.expected (+6/-5)
src/test/resources/com/akiban/sql/optimizer/rule/operator/select-5.expected (+5/-4)
To merge this branch: bzr merge lp:~mmcm/akiban-server/product-nested
Reviewer Review Type Date Requested Status
Nathan Williams Approve
Review via email: mp+175519@code.launchpad.net

Description of the change

Replace Product_NestedLoops with Product_Nested.

The new operator is much simpler: it produces a Product row of its input row and a bound row.

There was some subtlety to Product_NestedLoops:

(1) It maintained a cache by common ancestor hkey and didn't re-run the inner loop sometimes. While it's possible for ancestors to just happen to coincide from any secondary index, the cases where they do so reliably are rare, mostly involving GroupScans. Since maintaining this cache means keeping all the inner rows, I'm not sure it's worth it in balance. Presumably database caches will have the inner rows in memory at least.

(2) The row set in the bindings is not the one used for the product, but the common ancestor. This isn't possible with Map_NestedLoops. But it's just as easy to do the ancestor in BranchLookup_Nested, which is about this kind of navigation anyway. So, give that operator both an input row type and a source row type, to be extracted by subRow().

Some notes on the relevant ITs:

Product_NestedLoopsIT was incorrectly specifying KEEP_PARENT to Flatten. This may have been left over from when Product worked as a single row stream.

Product2WayIT had a comment about run ids, which again was from long ago. Also it was reusing binding slots for each loop, which isn't reliable, even if the Maps nest on the outer side, because the second inner row of the outer loop is allowed to assume that the bound value is still there. This worked okay with nested Product_NestedLoops's because the bound row was copied at open time. Rather than make Product_Nested do that, just use different slots, as the optimizer does.

To post a comment you must log in.
2722. By Mike McMahon

Merge from trunk.

Revision history for this message
Nathan Williams (nwilliams) wrote :

Minor nit: The Overview in the Javadoc for Product_Nested still references _NestedLoops.

Otherwise looks pretty good. Feel free to Big-A after.

review: Approve
2723. By Mike McMahon

Missed one.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/main/java/com/akiban/qp/operator/API.java'
2--- src/main/java/com/akiban/qp/operator/API.java 2013-07-13 21:17:31 +0000
3+++ src/main/java/com/akiban/qp/operator/API.java 2013-07-18 16:47:28 +0000
4@@ -210,6 +210,7 @@
5 int inputBindingPosition)
6 {
7 return new BranchLookup_Nested(group,
8+ inputRowType,
9 inputRowType,
10 null,
11 outputRowType,
12@@ -225,6 +226,7 @@
13 int inputBindingPosition)
14 {
15 return new BranchLookup_Nested(group,
16+ inputRowType,
17 inputRowType,
18 ancestorRowType,
19 outputRowType,
20@@ -232,6 +234,23 @@
21 inputBindingPosition);
22 }
23
24+ public static Operator branchLookup_Nested(Group group,
25+ RowType inputRowType,
26+ RowType sourceRowType,
27+ UserTableRowType ancestorRowType,
28+ UserTableRowType outputRowType,
29+ InputPreservationOption flag,
30+ int inputBindingPosition)
31+ {
32+ return new BranchLookup_Nested(group,
33+ inputRowType,
34+ sourceRowType,
35+ ancestorRowType,
36+ outputRowType,
37+ flag,
38+ inputBindingPosition);
39+ }
40+
41 // Limit
42
43 public static Operator limit_Default(Operator inputOperator, int limitRows)
44@@ -448,9 +467,10 @@
45 RowType innerType,
46 int inputBindingPosition)
47 {
48- return new Product_NestedLoops(outerInput, innerInput, outerType, null, innerType, inputBindingPosition);
49+ return product_NestedLoops(outerInput, innerInput, outerType, null, innerType, inputBindingPosition);
50 }
51
52+ /** deprecated */
53 public static Operator product_NestedLoops(Operator outerInput,
54 Operator innerInput,
55 RowType outerType,
56@@ -458,7 +478,19 @@
57 RowType innerType,
58 int inputBindingPosition)
59 {
60- return new Product_NestedLoops(outerInput, innerInput, outerType, branchType, innerType, inputBindingPosition);
61+ return map_NestedLoops(outerInput,
62+ product_Nested(innerInput, outerType, branchType, innerType, inputBindingPosition),
63+ inputBindingPosition,
64+ false, 0);
65+ }
66+
67+ public static Operator product_Nested(Operator input,
68+ RowType outerType,
69+ UserTableRowType branchType,
70+ RowType inputType,
71+ int bindingPosition)
72+ {
73+ return new Product_Nested(input, outerType, branchType, inputType, bindingPosition);
74 }
75
76 // Count
77
78=== modified file 'src/main/java/com/akiban/qp/operator/BranchLookup_Nested.java'
79--- src/main/java/com/akiban/qp/operator/BranchLookup_Nested.java 2013-07-17 18:15:10 +0000
80+++ src/main/java/com/akiban/qp/operator/BranchLookup_Nested.java 2013-07-18 16:47:28 +0000
81@@ -56,7 +56,9 @@
82 <li><b>GroupTable groupTable:</b> The group table containing the
83 ancestors of interest.
84
85- <li><b>RowType inputRowType:</b> Branches will be located for input
86+ <li><b>RowType inputRowType:</b> Bound row will be of this type.
87+
88+ <li><b>RowType sourceRowType:</b> Branches will be located for input
89 rows of this type.
90
91 <li><b>UserTableRowType ancestorRowType:</b> Identifies the table in the group at which branching occurs.
92@@ -136,7 +138,7 @@
93 return String.format("%s(%s %s -> %s)",
94 getClass().getSimpleName(),
95 group.getRoot().getName(),
96- inputRowType,
97+ sourceRowType,
98 outputRowType);
99 }
100
101@@ -163,6 +165,7 @@
102
103 public BranchLookup_Nested(Group group,
104 RowType inputRowType,
105+ RowType sourceRowType,
106 UserTableRowType ancestorRowType,
107 UserTableRowType outputRowType,
108 API.InputPreservationOption flag,
109@@ -170,21 +173,22 @@
110 {
111 ArgumentValidation.notNull("group", group);
112 ArgumentValidation.notNull("inputRowType", inputRowType);
113+ ArgumentValidation.notNull("sourceRowType", sourceRowType);
114 ArgumentValidation.notNull("outputRowType", outputRowType);
115 ArgumentValidation.notNull("flag", flag);
116- ArgumentValidation.isTrue("inputRowType instanceof UserTableRowType || flag == API.InputPreservationOption.DISCARD_INPUT",
117- inputRowType instanceof UserTableRowType || flag == API.InputPreservationOption.DISCARD_INPUT);
118+ ArgumentValidation.isTrue("sourceRowType instanceof UserTableRowType || flag == API.InputPreservationOption.DISCARD_INPUT",
119+ sourceRowType instanceof UserTableRowType || flag == API.InputPreservationOption.DISCARD_INPUT);
120 ArgumentValidation.isGTE("hKeyBindingPosition", inputBindingPosition, 0);
121 UserTableRowType inputTableType = null;
122- if (inputRowType instanceof UserTableRowType) {
123- inputTableType = (UserTableRowType) inputRowType;
124- } else if (inputRowType instanceof IndexRowType) {
125- inputTableType = ((IndexRowType) inputRowType).tableType();
126- } else if (inputRowType instanceof HKeyRowType) {
127+ if (sourceRowType instanceof UserTableRowType) {
128+ inputTableType = (UserTableRowType) sourceRowType;
129+ } else if (sourceRowType instanceof IndexRowType) {
130+ inputTableType = ((IndexRowType) sourceRowType).tableType();
131+ } else if (sourceRowType instanceof HKeyRowType) {
132 Schema schema = outputRowType.schema();
133- inputTableType = schema.userTableRowType(inputRowType.hKey().userTable());
134+ inputTableType = schema.userTableRowType(sourceRowType.hKey().userTable());
135 }
136- assert inputTableType != null : inputRowType;
137+ assert inputTableType != null : sourceRowType;
138 UserTable inputTable = inputTableType.userTable();
139 UserTable outputTable = outputRowType.userTable();
140 ArgumentValidation.isSame("inputTable.getGroup()",
141@@ -193,6 +197,7 @@
142 outputTable.getGroup());
143 this.group = group;
144 this.inputRowType = inputRowType;
145+ this.sourceRowType = sourceRowType;
146 this.outputRowType = outputRowType;
147 this.keepInput = flag == API.InputPreservationOption.KEEP_INPUT;
148 this.inputBindingPosition = inputBindingPosition;
149@@ -262,7 +267,7 @@
150 // Object state
151
152 private final Group group;
153- private final RowType inputRowType;
154+ private final RowType inputRowType, sourceRowType;
155 private final UserTableRowType outputRowType;
156 private final boolean keepInput;
157 // If keepInput is true, inputPrecedesBranch controls whether input row appears before the retrieved branch.
158@@ -278,9 +283,9 @@
159 atts.put(Label.BINDING_POSITION, PrimitiveExplainer.getInstance(inputBindingPosition));
160 atts.put(Label.OUTPUT_TYPE, outputRowType.getExplainer(context));
161 UserTableRowType ancestorRowType = outputRowType.schema().userTableRowType(commonAncestor);
162- if ((ancestorRowType != inputRowType) && (ancestorRowType != outputRowType))
163+ if ((ancestorRowType != sourceRowType) && (ancestorRowType != outputRowType))
164 atts.put(Label.ANCESTOR_TYPE, ancestorRowType.getExplainer(context));
165- return new LookUpOperatorExplainer(getName(), atts, inputRowType, false, null, context);
166+ return new LookUpOperatorExplainer(getName(), atts, sourceRowType, false, null, context);
167 }
168
169 // Inner classes
170@@ -296,10 +301,13 @@
171 try {
172 CursorLifecycle.checkIdle(this);
173 Row rowFromBindings = bindings.getRow(inputBindingPosition);
174+ assert rowFromBindings.rowType() == inputRowType : rowFromBindings;
175+ if (inputRowType != sourceRowType) {
176+ rowFromBindings = rowFromBindings.subRow(sourceRowType);
177+ }
178 if (LOG_EXECUTION) {
179 LOG.debug("BranchLookup_Nested: open using {}", rowFromBindings);
180 }
181- assert rowFromBindings.rowType() == inputRowType : rowFromBindings;
182 computeLookupRowHKey(rowFromBindings);
183 cursor.rebind(hKey, true);
184 cursor.open();
185
186=== modified file 'src/main/java/com/akiban/qp/operator/Map_NestedLoops.java'
187--- src/main/java/com/akiban/qp/operator/Map_NestedLoops.java 2013-07-18 13:05:48 +0000
188+++ src/main/java/com/akiban/qp/operator/Map_NestedLoops.java 2013-07-18 16:47:28 +0000
189@@ -76,7 +76,7 @@
190
191 <h1>Performance</h1>
192
193- Product_NestedLoops does no IO.
194+ Map_NestedLoops does no IO.
195
196 <h1>Memory Requirements</h1>
197
198@@ -135,7 +135,8 @@
199 ArgumentValidation.notNull("outerInputOperator", outerInputOperator);
200 ArgumentValidation.notNull("innerInputOperator", innerInputOperator);
201 ArgumentValidation.isGTE("inputBindingPosition", inputBindingPosition, 0);
202- ArgumentValidation.isGT("depth", depth, 0);
203+ if (pipeline)
204+ ArgumentValidation.isGT("depth", depth, 0);
205 this.outerInputOperator = outerInputOperator;
206 this.innerInputOperator = innerInputOperator;
207 this.inputBindingPosition = inputBindingPosition;
208
209=== renamed file 'src/main/java/com/akiban/qp/operator/Product_NestedLoops.java' => 'src/main/java/com/akiban/qp/operator/Product_Nested.java'
210--- src/main/java/com/akiban/qp/operator/Product_NestedLoops.java 2013-07-18 13:05:48 +0000
211+++ src/main/java/com/akiban/qp/operator/Product_Nested.java 2013-07-18 16:47:28 +0000
212@@ -22,9 +22,7 @@
213 import com.akiban.qp.rowtype.ProductRowType;
214 import com.akiban.qp.rowtype.RowType;
215 import com.akiban.qp.rowtype.UserTableRowType;
216-import com.akiban.server.explain.CompoundExplainer;
217-import com.akiban.server.explain.ExplainContext;
218-import com.akiban.server.explain.std.NestedLoopsExplainer;
219+import com.akiban.server.explain.*;
220 import com.akiban.util.ArgumentValidation;
221 import com.akiban.util.ShareHolder;
222 import com.akiban.util.tap.InOutTap;
223@@ -39,7 +37,7 @@
224
225 <h1>Overview</h1>
226
227- Product_NestedLoops computes the cartesian product of child rows owned by the same parent row. For example, if customer c1 has orders o10 and o11, and addresses a10 and a11; and customer c2 has order o20 and address a20, then Product_NestedLoops computes \{o10, o11\} x \{a10, a11\} for c1, and \{o20\} x \{a20\} for c2.
228+ Product_Nested computes the cartesian product of child rows owned by the same parent row. For example, if customer c1 has orders o10 and o11, and addresses a10 and a11; and customer c2 has order o20 and address a20, then Product_Nested computes \{o10, o11\} x \{a10, a11\} for c1, and \{o20\} x \{a20\} for c2.
229
230 <h1>Arguments</h1>
231
232@@ -48,34 +46,32 @@
233 <li><b>RowType outerType:</b> Type of one child row. parent rows to be
234 flattened.
235
236- <li><b>UserTableRowType branchType:</b> Ancestor type of outerType and innerType. Output will consist
237- of the cartesian product of outer and inner rows that match when projected to the branch type.
238-
239- <li><b>RowType innerType:</b> Type of the other child row.
240-
241- <li><b>int inputBindingPosition:</b> The position in the bindings that
242+ <li><b>UserTableRowType branchType:</b> Ancestor type of outerType and inputType. Output will consist
243+ of the cartesian product of outer and input rows that match when projected to the branch type.
244+
245+ <li><b>RowType inputType:</b> Type of the other child row.
246+
247+ <li><b>int bindingPosition:</b> The position in the bindings that
248 will be used to pass rows from the outer loop to the inner loop.
249
250 </ul>
251
252- The input types must have resulted from Flattens of some common
253+ The row types must have resulted from Flattens of some common
254 ancestor, e.g. Flatten(customer, order) and Flatten(customer,
255 address).
256
257 <h1>Behavior</h1>
258
259 Suppose we have a COA schema (C is the parent of O and A), and that we
260- have flattened C with O, and C with A. Product_NestedLoops has two
261+ have flattened C with O, and C with A. Product_Nested has two
262 input streams, with CO in one and CA in the other. The branch type is C.
263 For this discussion, let's assume that CO is the outer stream, and CA is in the
264- inner stream. The terms "outer" and "inner" reflect the relative
265- positions of the inputs in the nested loops used to compute the
266- product of the inputs.
267+ input stream.
268
269- For each CO row from the outer input stream, a set of matching CA rows,
270+ For each CO row from the outer stream, a set of matching CA rows,
271 (i.e., matching in C)
272- from the inner input stream are retrieved. The CO row and all of the
273- CA rows will have the same customer primary key. Product_NestedLoops
274+ from the input stream are retrieved. The CO row and all of the
275+ CA rows will have the same customer primary key. Product_Nested
276 will write to the output stream product rows for each CO/CA
277 combination.
278
279@@ -93,31 +89,31 @@
280
281 <h1>Performance</h1>
282
283- Product_NestedLoops does no IO.
284-
285- <h1>Memory Requirements</h1>
286-
287- For each outer row, all matching rows from the inner input are kept in
288- memory. This avoids the need to retrieve the inner rows repeatedly in
289- situations where consecutive outer rows match the same inner rows,
290- e.g. for hkey-ordered outer rows.
291+ Product_Nested does no IO.
292
293 */
294
295-class Product_NestedLoops extends Operator
296+class Product_Nested extends Operator
297 {
298 // Object interface
299
300 @Override
301 public String toString()
302 {
303- return String.format("%s(%s x %s)", getClass().getSimpleName(), outerType, innerType);
304+ return String.format("%s(%s x %s)", getClass().getSimpleName(), outerType, inputType);
305 }
306
307 @Override
308 public CompoundExplainer getExplainer(ExplainContext context)
309 {
310- return new NestedLoopsExplainer(getName(), innerInputOperator, outerInputOperator, innerType, outerType, context);
311+ Attributes atts = new Attributes();
312+
313+ atts.put(Label.NAME, PrimitiveExplainer.getInstance(getName()));
314+ atts.put(Label.OUTER_TYPE, outerType.getExplainer(context));
315+ atts.put(Label.INNER_TYPE, inputType.getExplainer(context));
316+ atts.put(Label.INPUT_OPERATOR, inputOperator.getExplainer(context));
317+ atts.put(Label.BINDING_POSITION, PrimitiveExplainer.getInstance(bindingPosition));
318+ return new CompoundExplainer(Type.PRODUCT_OPERATOR, atts);
319 }
320
321 // Operator interface
322@@ -125,7 +121,7 @@
323 @Override
324 protected Cursor cursor(QueryContext context, QueryBindingsCursor bindingsCursor)
325 {
326- return new Execution(context, bindingsCursor);
327+ return new Execution(context, inputOperator.cursor(context, bindingsCursor));
328 }
329
330 @Override
331@@ -137,8 +133,7 @@
332 @Override
333 public void findDerivedTypes(Set<RowType> derivedTypes)
334 {
335- innerInputOperator.findDerivedTypes(derivedTypes);
336- outerInputOperator.findDerivedTypes(derivedTypes);
337+ inputOperator.findDerivedTypes(derivedTypes);
338 derivedTypes.add(productType);
339 }
340
341@@ -146,76 +141,58 @@
342 public List<Operator> getInputOperators()
343 {
344 List<Operator> result = new ArrayList<>(2);
345- result.add(outerInputOperator);
346- result.add(innerInputOperator);
347+ result.add(inputOperator);
348 return result;
349 }
350
351 @Override
352 public String describePlan()
353 {
354- return describePlan(outerInputOperator);
355+ return describePlan(inputOperator);
356 }
357
358- // Product_NestedLoops interface
359+ // Product_Nested interface
360
361- public Product_NestedLoops(Operator outerInputOperator,
362- Operator innerInputOperator,
363- RowType outerType,
364- UserTableRowType branchType,
365- RowType innerType,
366- int inputBindingPosition)
367+ public Product_Nested(Operator inputOperator,
368+ RowType outerType,
369+ UserTableRowType branchType,
370+ RowType inputType,
371+ int bindingPosition)
372 {
373- ArgumentValidation.notNull("outerInputOperator", outerInputOperator);
374- ArgumentValidation.notNull("innerInputOperator", innerInputOperator);
375+ ArgumentValidation.notNull("inputOperator", inputOperator);
376 ArgumentValidation.notNull("outerType", outerType);
377- ArgumentValidation.notNull("innerType", innerType);
378- ArgumentValidation.isGTE("inputBindingPosition", inputBindingPosition, 0);
379- this.outerInputOperator = outerInputOperator;
380- this.innerInputOperator = innerInputOperator;
381+ ArgumentValidation.notNull("inputType", inputType);
382+ ArgumentValidation.isGTE("bindingPosition", bindingPosition, 0);
383+ this.inputOperator = inputOperator;
384 this.outerType = outerType;
385- this.innerType = innerType;
386- this.productType = outerType.schema().newProductType(outerType, branchType, innerType);
387+ this.inputType = inputType;
388+ this.productType = inputType.schema().newProductType(outerType, branchType, inputType);
389 this.branchType = productType.branchType();
390- this.inputBindingPosition = inputBindingPosition;
391+ this.bindingPosition = bindingPosition;
392 }
393
394 // Class state
395
396- private static InOutTap TAP_OPEN = OPERATOR_TAP.createSubsidiaryTap("operator: Product_NestedLoops open");
397- private static InOutTap TAP_NEXT = OPERATOR_TAP.createSubsidiaryTap("operator: Product_NestedLoops next");
398- private static final Logger LOG = LoggerFactory.getLogger(Product_NestedLoops.class);
399+ private static InOutTap TAP_OPEN = OPERATOR_TAP.createSubsidiaryTap("operator: Product_Nested open");
400+ private static InOutTap TAP_NEXT = OPERATOR_TAP.createSubsidiaryTap("operator: Product_Nested next");
401+ private static final Logger LOG = LoggerFactory.getLogger(Product_Nested.class);
402
403 // Object state
404
405- private final Operator outerInputOperator;
406- private final Operator innerInputOperator;
407+ private final Operator inputOperator;
408 private final RowType branchType;
409 private final RowType outerType;
410- private final RowType innerType;
411+ private final RowType inputType;
412 private final ProductRowType productType;
413- private final int inputBindingPosition;
414+ private final int bindingPosition;
415
416 // Inner classes
417
418- private class Execution extends OperatorCursor
419+ private class Execution extends ChainedCursor
420 {
421 // Cursor interface
422
423 @Override
424- public void open()
425- {
426- TAP_OPEN.in();
427- try {
428- CursorLifecycle.checkIdle(this);
429- this.outerInput.open();
430- this.closed = false;
431- } finally {
432- TAP_OPEN.out();
433- }
434- }
435-
436- @Override
437 public Row next()
438 {
439 if (TAP_NEXT_ENABLED) {
440@@ -226,38 +203,14 @@
441 CursorLifecycle.checkIdleOrActive(this);
442 }
443 checkQueryCancelation();
444- Row outputRow = null;
445- while (!closed && outputRow == null) {
446- outputRow = nextProductRow();
447- if (outputRow == null) {
448- Row row = outerInput.next();
449- if (row == null) {
450- close();
451- } else {
452- RowType rowType = row.rowType();
453- if (rowType == outerType) {
454- Row branchRow = row.subRow(branchType);
455- assert branchRow != null : row;
456- if (outerBranchRow.isEmpty() || !branchRow.hKey().equals(outerBranchRow.get().hKey())) {
457- if (LOG_EXECUTION) {
458- LOG.debug("Product_NestedLoops: branch row {}", row);
459- }
460- outerBranchRow.hold(branchRow);
461- innerRows.newBranchRow(branchRow);
462- }
463- outerRow.hold(row);
464- if (LOG_EXECUTION) {
465- LOG.debug("Product_NestedLoops: restart inner loop using current branch row");
466- }
467- innerRows.resetForCurrentBranchRow();
468- }
469- }
470- }
471+ Row row = input.next();
472+ if ((row != null) && (row.rowType() == inputType)) {
473+ row = new ProductRow(productType, bindings.getRow(bindingPosition), row);
474 }
475 if (LOG_EXECUTION) {
476- LOG.debug("Product_NestedLoops: yield {}", outputRow);
477+ LOG.debug("Product_Nested: yield {}", row);
478 }
479- return outputRow;
480+ return row;
481 } finally {
482 if (TAP_NEXT_ENABLED) {
483 TAP_NEXT.out();
484@@ -265,160 +218,11 @@
485 }
486 }
487
488- @Override
489- public void close()
490- {
491- CursorLifecycle.checkIdleOrActive(this);
492- if (!closed) {
493- closeOuter();
494- closed = true;
495- }
496- }
497-
498- @Override
499- public void destroy()
500- {
501- close();
502- outerInput.destroy();
503- innerRows.destroy();
504- }
505-
506- @Override
507- public boolean isIdle()
508- {
509- return closed;
510- }
511-
512- @Override
513- public boolean isActive()
514- {
515- return !closed;
516- }
517-
518- @Override
519- public boolean isDestroyed()
520- {
521- return outerInput.isDestroyed();
522- }
523-
524- @Override
525- public void openBindings() {
526- outerInput.openBindings();
527- }
528-
529- @Override
530- public QueryBindings nextBindings() {
531- outerBindings = outerInput.nextBindings();
532- return outerBindings;
533- }
534-
535- @Override
536- public void closeBindings() {
537- outerInput.closeBindings();
538- }
539-
540- @Override
541- public void cancelBindings(QueryBindings bindings) {
542- closeInner();
543- outerInput.cancelBindings(bindings);
544- closed = true;
545- }
546-
547 // Execution interface
548
549- Execution(QueryContext context, QueryBindingsCursor bindingsCursor)
550- {
551- super(context);
552- this.outerInput = outerInputOperator.cursor(context, bindingsCursor);
553- this.innerRows = new InnerRows(context, bindingsCursor);
554- }
555-
556- // For use by this class
557-
558- private Row nextProductRow()
559- {
560- Row productRow = null;
561- if (outerRow.isHolding()) {
562- Row innerRow = innerRows.next();
563- if (innerRow == null) {
564- closeInner();
565- } else {
566- productRow = new ProductRow(productType, outerRow.get(), innerRow);
567- }
568- }
569- return productRow;
570- }
571-
572- private void closeOuter()
573- {
574- closeInner();
575- outerInput.close();
576- }
577-
578- private void closeInner()
579- {
580- outerRow.release();
581- innerRows.close();
582- }
583-
584- // Object state
585-
586- private final Cursor outerInput;
587- private final ShareHolder<Row> outerRow = new ShareHolder<>();
588- private final ShareHolder<Row> outerBranchRow = new ShareHolder<>();
589- private final InnerRows innerRows;
590- private boolean closed = true;
591- private QueryBindings outerBindings;
592-
593- // Inner classes
594-
595- private class InnerRows
596- {
597- public InnerRows(QueryContext context, QueryBindingsCursor bindingsCursor)
598- {
599- this.innerBindingsCursor = new SingletonQueryBindingsCursor(null);
600- this.innerInput = innerInputOperator.cursor(context, innerBindingsCursor);
601- }
602-
603- public Row next()
604- {
605- return scan.next();
606- }
607-
608- public void resetForCurrentBranchRow()
609- {
610- scan.reset();
611- }
612-
613- public void newBranchRow(Row branchRow)
614- {
615- close();
616- outerBindings.setRow(inputBindingPosition, branchRow);
617- innerBindingsCursor.reset(outerBindings);
618- innerInput.openTopLevel();
619- rows.clear();
620- Row row;
621- while ((row = innerInput.next()) != null) {
622- rows.add(row);
623- }
624- resetForCurrentBranchRow();
625- }
626-
627- public void close()
628- {
629- innerInput.close();
630- }
631-
632- public void destroy()
633- {
634- close();
635- innerInput.destroy();
636- }
637-
638- private final Cursor innerInput;
639- private final RowList rows = new RowList();
640- private final RowList.Scan scan = rows.scan();
641- private final SingletonQueryBindingsCursor innerBindingsCursor;
642+ Execution(QueryContext context, Cursor input)
643+ {
644+ super(context, input);
645 }
646 }
647 }
648
649=== modified file 'src/main/java/com/akiban/server/explain/Type.java'
650--- src/main/java/com/akiban/server/explain/Type.java 2013-03-22 20:05:57 +0000
651+++ src/main/java/com/akiban/server/explain/Type.java 2013-07-18 16:47:28 +0000
652@@ -51,6 +51,7 @@
653 DUI(GeneralType.OPERATOR), // delete/update/insert
654 DISTINCT(GeneralType.OPERATOR),
655 FLATTEN_OPERATOR(GeneralType.OPERATOR),
656+ PRODUCT_OPERATOR(GeneralType.OPERATOR),
657 LIMIT_OPERATOR(GeneralType.OPERATOR),
658 NESTED_LOOPS(GeneralType.OPERATOR),
659 IF_EMPTY(GeneralType.OPERATOR),
660
661=== modified file 'src/main/java/com/akiban/server/explain/format/DefaultFormatter.java'
662--- src/main/java/com/akiban/server/explain/format/DefaultFormatter.java 2013-03-22 20:05:57 +0000
663+++ src/main/java/com/akiban/server/explain/format/DefaultFormatter.java 2013-07-18 16:47:28 +0000
664@@ -233,6 +233,9 @@
665 case FLATTEN_OPERATOR:
666 appendFlattenOperator(name, atts);
667 break;
668+ case PRODUCT_OPERATOR:
669+ appendProductOperator(name, atts);
670+ break;
671 case ORDERED:
672 appendOrderedOperator(name, atts);
673 break;
674@@ -530,6 +533,14 @@
675 }
676 }
677
678+ protected void appendProductOperator(String name, Attributes atts) {
679+ if (levelOfDetail != LevelOfDetail.BRIEF) {
680+ append(atts.getAttribute(Label.OUTER_TYPE));
681+ sb.append(" x ");
682+ append(atts.getAttribute(Label.INNER_TYPE));
683+ }
684+ }
685+
686 protected void appendOrderedOperator(String name, Attributes atts) {
687 if (levelOfDetail != LevelOfDetail.BRIEF) {
688 if (atts.containsKey(Label.UNION_OPTION) &&
689@@ -586,11 +597,6 @@
690 if (name.equals("Map_NestedLoops")) {
691 // Label the loop?
692 }
693- else if (name.equals("Product_NestedLoops")) {
694- append(atts.getAttribute(Label.OUTER_TYPE));
695- sb.append(" x ");
696- append(atts.getAttribute(Label.INNER_TYPE));
697- }
698 }
699 }
700
701
702=== modified file 'src/main/java/com/akiban/sql/optimizer/rule/OperatorAssembler.java'
703--- src/main/java/com/akiban/sql/optimizer/rule/OperatorAssembler.java 2013-07-13 21:17:31 +0000
704+++ src/main/java/com/akiban/sql/optimizer/rule/OperatorAssembler.java 2013-07-18 16:47:28 +0000
705@@ -1472,10 +1472,12 @@
706 RowStream stream;
707 Group group = branchLookup.getSource().getGroup();
708 if (branchLookup.getInput() == null) {
709- // Simple version for Product_NestedLoops.
710+ // Simple version for Product_Nested.
711 stream = new RowStream();
712 API.InputPreservationOption flag = API.InputPreservationOption.KEEP_INPUT;
713+ ColumnExpressionToIndex boundRow = boundRows.get(boundRows.size()-1);
714 stream.operator = API.branchLookup_Nested(group,
715+ boundRow.getRowType(),
716 tableRowType(branchLookup.getSource()),
717 tableRowType(branchLookup.getAncestor()),
718 tableRowType(branchLookup.getBranch()),
719@@ -1491,6 +1493,7 @@
720 ColumnExpressionToIndex boundRow = boundRows.get(rowIndex);
721 stream.operator = API.branchLookup_Nested(group,
722 boundRow.getRowType(),
723+ boundRow.getRowType(),
724 tableRowType(branchLookup.getAncestor()),
725 tableRowType(branchLookup.getBranch()),
726 flag,
727@@ -1546,14 +1549,12 @@
728 ancestorRowType = tableRowType(product.getAncestor());
729 RowStream pstream = new RowStream();
730 Flattened flattened = new Flattened();
731+ pstream.fieldOffsets = flattened;
732 int nbound = 0;
733 for (PlanNode subplan : product.getSubplans()) {
734 if (pstream.operator != null) {
735- // The actual bound row is the branch row, which
736- // we don't access directly. Just give each
737- // product a separate position; nesting doesn't
738- // matter.
739- pushBoundRow(null);
740+ pushBoundRow(flattened);
741+ nestedBindingsDepth++;
742 nbound++;
743 }
744 RowStream stream = assembleStream(subplan);
745@@ -1562,13 +1563,18 @@
746 pstream.rowType = stream.rowType;
747 }
748 else {
749- pstream.operator = API.product_NestedLoops(pstream.operator,
750- stream.operator,
751- pstream.rowType,
752- ancestorRowType,
753- stream.rowType,
754- currentBindingPosition());
755- pstream.rowType = pstream.operator.rowType();
756+ stream.operator = API.product_Nested(stream.operator,
757+ pstream.rowType,
758+ ancestorRowType,
759+ stream.rowType,
760+ currentBindingPosition());
761+ stream.rowType = stream.operator.rowType();
762+ pstream.operator = API.map_NestedLoops(pstream.operator,
763+ stream.operator,
764+ currentBindingPosition(),
765+ rulesContext.getPipelineConfiguration().isMapEnabled(),
766+ nestedBindingsDepth);
767+ pstream.rowType = stream.rowType;
768 }
769 if (stream.fieldOffsets instanceof ColumnSourceFieldOffsets) {
770 TableSource table = ((ColumnSourceFieldOffsets)
771@@ -1578,13 +1584,13 @@
772 else {
773 flattened.product((Flattened)stream.fieldOffsets);
774 }
775+ flattened.setRowType(pstream.rowType);
776 }
777 while (nbound > 0) {
778 popBoundRow();
779+ nestedBindingsDepth--;
780 nbound--;
781 }
782- flattened.setRowType(pstream.rowType);
783- pstream.fieldOffsets = flattened;
784 return pstream;
785 }
786
787
788=== modified file 'src/test/java/com/akiban/server/test/it/qp/Map_NestedLoopsIT.java'
789--- src/test/java/com/akiban/server/test/it/qp/Map_NestedLoopsIT.java 2013-07-15 22:46:16 +0000
790+++ src/test/java/com/akiban/server/test/it/qp/Map_NestedLoopsIT.java 2013-07-18 16:47:28 +0000
791@@ -120,7 +120,7 @@
792 @Test(expected = IllegalArgumentException.class)
793 public void testNonPositiveDepth()
794 {
795- map_NestedLoops(groupScan_Default(coi), groupScan_Default(coi), 0, pipelineMap(),0);
796+ map_NestedLoops(groupScan_Default(coi), groupScan_Default(coi), 0, true,0);
797 }
798
799 // Test operator execution
800
801=== modified file 'src/test/java/com/akiban/server/test/it/qp/Product3WayIT.java'
802--- src/test/java/com/akiban/server/test/it/qp/Product3WayIT.java 2013-07-08 20:48:05 +0000
803+++ src/test/java/com/akiban/server/test/it/qp/Product3WayIT.java 2013-07-18 16:47:28 +0000
804@@ -34,11 +34,6 @@
805 import static com.akiban.qp.operator.API.*;
806 import static org.junit.Assert.assertTrue;
807
808-// Product_ByRun relies on run ids. Here is an explanation of why run ids are needed:
809-// http://akibainc.onconfluence.com/display/db/Implementation+of+the+Product+operator.
810-// But no other operator relies on runs, and run ids can probably be omitted if we implement
811-// a nested-loops form of product. This test uses a 3-way product, the case motivating run ids.
812-
813 public class Product3WayIT extends OperatorITBase
814 {
815 @Override
816@@ -134,28 +129,35 @@
817 flatten_HKeyOrdered(
818 branchLookup_Nested(
819 rabc,
820+ RA.rowType(),
821 rRowType,
822+ null,
823 bRowType,
824 KEEP_INPUT,
825 0),
826 rRowType,
827 bRowType,
828 INNER_JOIN);
829+ Operator RAB = product_Nested(RB, RA.rowType(), null, RB.rowType(), 0);
830 Operator RC =
831 flatten_HKeyOrdered(
832 branchLookup_Nested(
833 rabc,
834+ RAB.rowType(),
835 rRowType,
836+ null,
837 cRowType,
838 KEEP_INPUT,
839- 0),
840+ 1),
841 rRowType,
842 cRowType,
843 INNER_JOIN);
844- Operator RAB = product_NestedLoops(RA, RB, RA.rowType(), RB.rowType(), 0);
845- Operator RABC = product_NestedLoops(RAB, RC, RAB.rowType(), RC.rowType(), 0);
846- Cursor cursor = cursor(RABC, queryContext, queryBindings);
847+ Operator RABC = product_Nested(RC, RAB.rowType(), null, RC.rowType(), 1);
848 RowType rabcRowType = RABC.rowType();
849+ Operator plan = map_NestedLoops(
850+ map_NestedLoops(RA, RAB, 0, pipelineMap(), 1),
851+ RABC, 1, pipelineMap(), 1);
852+ Cursor cursor = cursor(plan, queryContext, queryBindings);
853 RowBase[] expected = new RowBase[]{
854 row(rabcRowType, 1L, "r1", 13L, 1L, "a13", 15L, 1L, "b15", 17L, 1L, "c17"),
855 row(rabcRowType, 1L, "r1", 13L, 1L, "a13", 15L, 1L, "b15", 18L, 1L, "c18"),
856@@ -192,32 +194,39 @@
857 rRowType,
858 aRowType,
859 INNER_JOIN);
860+ Operator RC =
861+ flatten_HKeyOrdered(
862+ branchLookup_Nested(
863+ rabc,
864+ RA.rowType(),
865+ rRowType,
866+ null,
867+ cRowType,
868+ KEEP_INPUT,
869+ 0),
870+ rRowType,
871+ cRowType,
872+ INNER_JOIN);
873+ Operator RAC = product_Nested(RC, RA.rowType(), null, RC.rowType(), 0);
874 Operator RB =
875 flatten_HKeyOrdered(
876 branchLookup_Nested(
877 rabc,
878+ RAC.rowType(),
879 rRowType,
880+ null,
881 bRowType,
882 KEEP_INPUT,
883- 0),
884+ 1),
885 rRowType,
886 bRowType,
887 INNER_JOIN);
888- Operator RC =
889- flatten_HKeyOrdered(
890- branchLookup_Nested(
891- rabc,
892- rRowType,
893- cRowType,
894- KEEP_INPUT,
895- 0),
896- rRowType,
897- cRowType,
898- INNER_JOIN);
899- Operator RAC = product_NestedLoops(RA, RC, RA.rowType(), RC.rowType(), 0);
900- Operator RACB = product_NestedLoops(RAC, RB, RAC.rowType(), RB.rowType(), 0);
901- Cursor cursor = cursor(RACB, queryContext, queryBindings);
902+ Operator RACB = product_Nested(RB, RAC.rowType(), null, RB.rowType(), 1);
903 RowType racbRowType = RACB.rowType();
904+ Operator plan = map_NestedLoops(
905+ map_NestedLoops(RA, RAC, 0, pipelineMap(), 1),
906+ RACB, 1, pipelineMap(), 1);
907+ Cursor cursor = cursor(plan, queryContext, queryBindings);
908 RowBase[] expected = new RowBase[]{
909 row(racbRowType, 1L, "r1", 13L, 1L, "a13", 17L, 1L, "c17", 15L, 1L, "b15"),
910 row(racbRowType, 1L, "r1", 13L, 1L, "a13", 17L, 1L, "c17", 16L, 1L, "b16"),
911@@ -254,39 +263,50 @@
912 branchLookup_Nested(
913 rabc,
914 rRowType,
915+ rRowType,
916+ null,
917 aRowType,
918 KEEP_INPUT,
919 0),
920 rRowType,
921 aRowType,
922 INNER_JOIN);
923+ Operator RA = product_Nested(flattenRA, rRowType, null, flattenRA.rowType(), 0);
924 Operator flattenRB =
925 flatten_HKeyOrdered(
926 branchLookup_Nested(
927 rabc,
928+ RA.rowType(),
929 rRowType,
930+ null,
931 bRowType,
932 KEEP_INPUT,
933- 0),
934+ 1),
935 rRowType,
936 bRowType,
937 INNER_JOIN);
938+ Operator RAB = product_Nested(flattenRB, RA.rowType(), null, flattenRB.rowType(), 1);
939 Operator flattenRC =
940 flatten_HKeyOrdered(
941 branchLookup_Nested(
942 rabc,
943+ RAB.rowType(),
944 rRowType,
945+ null,
946 cRowType,
947 KEEP_INPUT,
948- 0),
949+ 2),
950 rRowType,
951 cRowType,
952 INNER_JOIN);
953- Operator RA = product_NestedLoops(rScan, flattenRA, rRowType, flattenRA.rowType(), 0);
954- Operator RAB = product_NestedLoops(RA, flattenRB, RA.rowType(), flattenRB.rowType(), 0);
955- Operator RABC = product_NestedLoops(RAB, flattenRC, RAB.rowType(), flattenRC.rowType(), 0);
956- Cursor cursor = cursor(RABC, queryContext, queryBindings);
957+ Operator RABC = product_Nested(flattenRC, RAB.rowType(), null, flattenRC.rowType(), 2);
958 RowType rabcRowType = RABC.rowType();
959+ Operator plan = map_NestedLoops(
960+ map_NestedLoops(
961+ map_NestedLoops(rScan, RA, 0, pipelineMap(), 1),
962+ RAB, 1, pipelineMap(), 1),
963+ RABC, 2, pipelineMap(), 1);
964+ Cursor cursor = cursor(plan, queryContext, queryBindings);
965 RowBase[] expected = new RowBase[]{
966 row(rabcRowType, 1L, "r1", 13L, 1L, "a13", 15L, 1L, "b15", 17L, 1L, "c17"),
967 row(rabcRowType, 1L, "r1", 13L, 1L, "a13", 15L, 1L, "b15", 18L, 1L, "c18"),
968
969=== renamed file 'src/test/java/com/akiban/server/test/it/qp/Product_NestedLoopsIT.java' => 'src/test/java/com/akiban/server/test/it/qp/Product_NestedIT.java'
970--- src/test/java/com/akiban/server/test/it/qp/Product_NestedLoopsIT.java 2013-07-08 18:16:50 +0000
971+++ src/test/java/com/akiban/server/test/it/qp/Product_NestedIT.java 2013-07-18 16:47:28 +0000
972@@ -33,14 +33,13 @@
973 import java.util.Set;
974
975 import static com.akiban.qp.operator.API.*;
976-import static com.akiban.qp.operator.API.FlattenOption.KEEP_PARENT;
977 import static com.akiban.qp.operator.API.JoinType.INNER_JOIN;
978 import static com.akiban.qp.rowtype.RowTypeChecks.checkRowTypeFields;
979 import static com.akiban.server.types.AkType.INT;
980 import static com.akiban.server.types.AkType.VARCHAR;
981 import static org.junit.Assert.assertTrue;
982
983-public class Product_NestedLoopsIT extends OperatorITBase
984+public class Product_NestedIT extends OperatorITBase
985 {
986 @Override
987 protected void setupPostCreateSchema()
988@@ -97,33 +96,27 @@
989 // Test argument validation
990
991 @Test(expected = IllegalArgumentException.class)
992- public void testLeftInputNull()
993- {
994- product_NestedLoops(null, groupScan_Default(coi), customerRowType, customerRowType, 0);
995- }
996-
997- @Test(expected = IllegalArgumentException.class)
998- public void testRightInputNull()
999- {
1000- product_NestedLoops(groupScan_Default(coi), null, customerRowType, customerRowType, 0);
1001+ public void testInputNull()
1002+ {
1003+ product_Nested(null, customerRowType, null, customerRowType, 0);
1004 }
1005
1006 @Test(expected = IllegalArgumentException.class)
1007 public void testLeftTypeNull()
1008 {
1009- product_NestedLoops(groupScan_Default(coi), groupScan_Default(coi), null, customerRowType, 0);
1010+ product_Nested(groupScan_Default(coi), null, null, customerRowType, 0);
1011 }
1012
1013 @Test(expected = IllegalArgumentException.class)
1014 public void testRightTypeNull()
1015 {
1016- product_NestedLoops(groupScan_Default(coi), groupScan_Default(coi), customerRowType, null, 0);
1017+ product_Nested(groupScan_Default(coi), customerRowType, null, null, 0);
1018 }
1019
1020 @Test(expected = IllegalArgumentException.class)
1021 public void testNegativeInputBindingPosition()
1022 {
1023- product_NestedLoops(groupScan_Default(coi), groupScan_Default(coi), customerRowType, customerRowType, -1);
1024+ product_Nested(groupScan_Default(coi), customerRowType, null, customerRowType, -1);
1025 }
1026
1027 // Test operator execution
1028@@ -150,17 +143,17 @@
1029 removeDescendentTypes(orderRowType)),
1030 customerRowType,
1031 orderRowType,
1032- INNER_JOIN,
1033- KEEP_PARENT);
1034+ INNER_JOIN);
1035 Operator flattenCA =
1036 flatten_HKeyOrdered(
1037- branchLookup_Nested(coi, customerRowType, addressRowType, InputPreservationOption.KEEP_INPUT, 0),
1038+ branchLookup_Nested(coi, flattenCO.rowType(), customerRowType, null, addressRowType, InputPreservationOption.KEEP_INPUT, 0),
1039 customerRowType,
1040 addressRowType,
1041 INNER_JOIN);
1042- Operator plan = product_NestedLoops(flattenCO, flattenCA, flattenCO.rowType(), flattenCA.rowType(), 0);
1043- RowType coaRowType = plan.rowType();
1044+ Operator product = product_Nested(flattenCA, flattenCO.rowType(), null, flattenCA.rowType(), 0);
1045+ RowType coaRowType = product.rowType();
1046 checkRowTypeFields(coaRowType, INT, VARCHAR, INT, INT, VARCHAR, INT, INT, VARCHAR);
1047+ Operator plan = map_NestedLoops(flattenCO, product, 0, pipelineMap(), 1);
1048 Cursor cursor = cursor(plan, queryContext, queryBindings);
1049 RowBase[] expected = new RowBase[]{
1050 row(coaRowType, 2L, "foundation", 200L, 2L, "david", 2000L, 2L, "222 2000 st"),
1051@@ -191,13 +184,14 @@
1052 INNER_JOIN);
1053 Operator flattenCA =
1054 flatten_HKeyOrdered(
1055- branchLookup_Nested(coi, customerRowType, addressRowType, InputPreservationOption.KEEP_INPUT, 0),
1056+ branchLookup_Nested(coi, flattenCO.rowType(), customerRowType, null, addressRowType, InputPreservationOption.KEEP_INPUT, 0),
1057 customerRowType,
1058 addressRowType,
1059 INNER_JOIN);
1060- Operator plan = product_NestedLoops(flattenCO, flattenCA, flattenCO.rowType(), flattenCA.rowType(), 0);
1061- RowType coaRowType = plan.rowType();
1062+ Operator product = product_Nested(flattenCA, flattenCO.rowType(), null, flattenCA.rowType(), 0);
1063+ RowType coaRowType = product.rowType();
1064 checkRowTypeFields(coaRowType, INT, VARCHAR, INT, INT, VARCHAR, INT, INT, VARCHAR);
1065+ Operator plan = map_NestedLoops(flattenCO, product, 0, pipelineMap(), 1);
1066 Cursor cursor = cursor(plan, queryContext, queryBindings);
1067 RowBase[] expected = new RowBase[]{
1068 row(coaRowType, 2L, "foundation", 200L, 2L, "david", 2000L, 2L, "222 2000 st"),
1069@@ -222,12 +216,12 @@
1070 Arrays.asList(customerRowType, addressRowType)),
1071 customerRowType,
1072 addressRowType,
1073- JoinType.LEFT_JOIN,
1074- FlattenOption.KEEP_PARENT);
1075+ JoinType.LEFT_JOIN);
1076 Operator flattenCAInner =
1077 flatten_HKeyOrdered(
1078 branchLookup_Nested(
1079 coi,
1080+ flattenCAOuter.rowType(),
1081 customerRowType,
1082 customerRowType,
1083 addressRowType,
1084@@ -237,14 +231,14 @@
1085 addressRowType,
1086 JoinType.LEFT_JOIN);
1087 Operator product =
1088- product_NestedLoops(
1089- flattenCAOuter,
1090+ product_Nested(
1091 flattenCAInner,
1092 flattenCAOuter.rowType(),
1093 customerRowType,
1094 flattenCAInner.rowType(),
1095 0);
1096 RowType productRowType = product.rowType();
1097+ Operator plan = map_NestedLoops(flattenCAOuter, product, 0, pipelineMap(), 1);
1098 RowBase[] expected = new RowBase[]{
1099 row(productRowType, 1L, "northbridge", 1000L, 1L, "111 1000 st", 1000L, 1L, "111 1000 st"),
1100 row(productRowType, 1L, "northbridge", 1000L, 1L, "111 1000 st", 1001L, 1L, "111 1001 st"),
1101@@ -262,7 +256,7 @@
1102 row(productRowType, 5L, "highland", 5001L, 5L, "555 5001 st", 5001, 5L, "555 5001 st"),
1103 row(productRowType, 6L, "flybridge", null, null, null, null, null, null),
1104 };
1105- compareRows(expected, cursor(product, queryContext, queryBindings));
1106+ compareRows(expected, cursor(plan, queryContext, queryBindings));
1107 }
1108
1109 @Test
1110@@ -285,16 +279,16 @@
1111 removeDescendentTypes(orderRowType)),
1112 customerRowType,
1113 orderRowType,
1114- INNER_JOIN,
1115- KEEP_PARENT);
1116+ INNER_JOIN);
1117 Operator flattenCA =
1118 flatten_HKeyOrdered(
1119- branchLookup_Nested(coi, customerRowType, addressRowType, InputPreservationOption.KEEP_INPUT, 0),
1120+ branchLookup_Nested(coi, flattenCO.rowType(), customerRowType, null, addressRowType, InputPreservationOption.KEEP_INPUT, 0),
1121 customerRowType,
1122 addressRowType,
1123 INNER_JOIN);
1124- Operator plan = product_NestedLoops(flattenCO, flattenCA, flattenCO.rowType(), flattenCA.rowType(), 0);
1125- final RowType coaRowType = plan.rowType();
1126+ Operator product = product_Nested(flattenCA, flattenCO.rowType(), null, flattenCA.rowType(), 0);
1127+ final RowType coaRowType = product.rowType();
1128+ Operator plan = map_NestedLoops(flattenCO, product, 0, pipelineMap(), 1);
1129 CursorLifecycleTestCase testCase = new CursorLifecycleTestCase()
1130 {
1131 @Override
1132
1133=== modified file 'src/test/resources/com/akiban/sql/optimizer/operator/cbo/multiindex-multi-duplicate.expected'
1134--- src/test/resources/com/akiban/sql/optimizer/operator/cbo/multiindex-multi-duplicate.expected 2012-08-29 13:38:58 +0000
1135+++ src/test/resources/com/akiban/sql/optimizer/operator/cbo/multiindex-multi-duplicate.expected 2013-07-18 16:47:28 +0000
1136@@ -1,14 +1,15 @@
1137 PhysicalSelect[quan:int[INT], quan:int[INT]]
1138 Project_Default(i1.quan, i2.quan)
1139- Product_NestedLoops(customers - orders - items x customers - orders - items)
1140+ Map_NestedLoops()
1141 Flatten_HKeyOrdered(customers - orders INNER items)
1142 Flatten_HKeyOrdered(customers INNER orders)
1143 AncestorLookup_Default(Index(items.sku) -> customers, orders, items)
1144 Intersect_Ordered(skip 1 left, skip 1 right, compare 1)
1145 IndexScan_Default(Index(items.sku), sku = '1234')
1146 IndexScan_Default(Index(items.sku), sku = '4567')
1147- Filter_Default(customers - orders - items)
1148- Flatten_HKeyOrdered(customers - orders INNER items)
1149- Flatten_HKeyOrdered(customers INNER orders)
1150- Select_HKeyOrdered(i2.sku == '4567')
1151- BranchLookup_Nested(customers -> orders)
1152\ No newline at end of file
1153+ Product_Nested(customers - orders - items x customers - orders - items)
1154+ Filter_Default(customers - orders - items)
1155+ Flatten_HKeyOrdered(customers - orders INNER items)
1156+ Flatten_HKeyOrdered(customers INNER orders)
1157+ Select_HKeyOrdered(i2.sku == '4567')
1158+ BranchLookup_Nested(customers -> orders)
1159\ No newline at end of file
1160
1161=== modified file 'src/test/resources/com/akiban/sql/optimizer/operator/cbo/multiindex-multi-ordered.expected'
1162--- src/test/resources/com/akiban/sql/optimizer/operator/cbo/multiindex-multi-ordered.expected 2012-08-29 13:38:58 +0000
1163+++ src/test/resources/com/akiban/sql/optimizer/operator/cbo/multiindex-multi-ordered.expected 2013-07-18 16:47:28 +0000
1164@@ -1,14 +1,15 @@
1165 PhysicalSelect[quan:int[INT], quan:int[INT]]
1166 Project_Default(i1.quan, i2.quan)
1167- Product_NestedLoops(customers - orders - items x customers - orders - items)
1168+ Map_NestedLoops()
1169 Flatten_HKeyOrdered(customers - orders INNER items)
1170 Flatten_HKeyOrdered(customers INNER orders)
1171 AncestorLookup_Default(Index(items.sku) -> customers, orders, items)
1172 Intersect_Ordered(skip 1 left, skip 1 right, compare 1)
1173 IndexScan_Default(Index(items.sku), sku = '1234', orders.cid DESC, oid, iid)
1174 IndexScan_Default(Index(items.sku), sku = '4567', orders.cid DESC, oid, iid)
1175- Filter_Default(customers - orders - items)
1176- Flatten_HKeyOrdered(customers - orders INNER items)
1177- Flatten_HKeyOrdered(customers INNER orders)
1178- Select_HKeyOrdered(i2.sku == '4567')
1179- BranchLookup_Nested(customers -> orders)
1180\ No newline at end of file
1181+ Product_Nested(customers - orders - items x customers - orders - items)
1182+ Filter_Default(customers - orders - items)
1183+ Flatten_HKeyOrdered(customers - orders INNER items)
1184+ Flatten_HKeyOrdered(customers INNER orders)
1185+ Select_HKeyOrdered(i2.sku == '4567')
1186+ BranchLookup_Nested(customers -> orders)
1187\ No newline at end of file
1188
1189=== modified file 'src/test/resources/com/akiban/sql/optimizer/operator/cbo/multiple-table-conds-1.expected'
1190--- src/test/resources/com/akiban/sql/optimizer/operator/cbo/multiple-table-conds-1.expected 2012-10-19 19:07:51 +0000
1191+++ src/test/resources/com/akiban/sql/optimizer/operator/cbo/multiple-table-conds-1.expected 2013-07-18 16:47:28 +0000
1192@@ -3,13 +3,14 @@
1193 AncestorLookup_Default(Index(parent.PRIMARY) -> parent)
1194 IndexScan_Default(Index(parent.PRIMARY), id > 1)
1195 Project_Default(customers.cid)
1196- Product_NestedLoops(customers - items x customers - addresses)
1197+ Map_NestedLoops()
1198 Flatten_HKeyOrdered(customers INNER items)
1199 Select_HKeyOrdered(items.quan > 100)
1200 AncestorLookup_Default(Index(customers.cname_and_sku) -> customers, items)
1201 IndexScan_Default(Index(customers.cname_and_sku), customers.name = parent.name, items.sku = '1234')
1202- Select_HKeyOrdered(addresses.city != customers.name)
1203- Filter_Default(customers - addresses)
1204- Flatten_HKeyOrdered(customers INNER addresses)
1205- Select_HKeyOrdered(parent.state == addresses.state)
1206- BranchLookup_Nested(customers -> addresses)
1207+ Product_Nested(customers - items x customers - addresses)
1208+ Select_HKeyOrdered(addresses.city != customers.name)
1209+ Filter_Default(customers - addresses)
1210+ Flatten_HKeyOrdered(customers INNER addresses)
1211+ Select_HKeyOrdered(parent.state == addresses.state)
1212+ BranchLookup_Nested(customers -> addresses)
1213
1214=== modified file 'src/test/resources/com/akiban/sql/optimizer/operator/cbo/multiple-table-conds-1.t3expected'
1215--- src/test/resources/com/akiban/sql/optimizer/operator/cbo/multiple-table-conds-1.t3expected 2012-10-20 04:06:22 +0000
1216+++ src/test/resources/com/akiban/sql/optimizer/operator/cbo/multiple-table-conds-1.t3expected 2013-07-18 16:47:28 +0000
1217@@ -3,13 +3,14 @@
1218 AncestorLookup_Default(Index(parent.PRIMARY) -> parent)
1219 IndexScan_Default(Index(parent.PRIMARY), id > 1)
1220 Project_Default(customers.cid)
1221- Product_NestedLoops(customers - items x customers - addresses)
1222+ Map_NestedLoops()
1223 Flatten_HKeyOrdered(customers INNER items)
1224 Select_HKeyOrdered(items.quan > 100)
1225 AncestorLookup_Default(Index(customers.cname_and_sku) -> customers, items)
1226 IndexScan_Default(Index(customers.cname_and_sku), customers.name = parent.name, items.sku = '1234')
1227- Select_HKeyOrdered(addresses.city != customers.name)
1228- Filter_Default(customers - addresses)
1229- Flatten_HKeyOrdered(customers INNER addresses)
1230- Select_HKeyOrdered(parent.state == addresses.state)
1231- BranchLookup_Nested(customers -> addresses)
1232\ No newline at end of file
1233+ Product_Nested(customers - items x customers - addresses)
1234+ Select_HKeyOrdered(addresses.city != customers.name)
1235+ Filter_Default(customers - addresses)
1236+ Flatten_HKeyOrdered(customers INNER addresses)
1237+ Select_HKeyOrdered(parent.state == addresses.state)
1238+ BranchLookup_Nested(customers -> addresses)
1239\ No newline at end of file
1240
1241=== modified file 'src/test/resources/com/akiban/sql/optimizer/operator/coia-group-index/select-17bu.expected'
1242--- src/test/resources/com/akiban/sql/optimizer/operator/coia-group-index/select-17bu.expected 2013-06-06 19:56:32 +0000
1243+++ src/test/resources/com/akiban/sql/optimizer/operator/coia-group-index/select-17bu.expected 2013-07-18 16:47:28 +0000
1244@@ -1,7 +1,7 @@
1245 PhysicalSelect[name:varchar(32)[VARCHAR], quan:int[INT]]
1246 Project_Default(customers.name, items.quan)
1247 Sort_General(items.quan DESC)
1248- Product_NestedLoops(customers - addresses x customers - orders - items)
1249+ Map_NestedLoops()
1250 Flatten_HKeyOrdered(customers INNER addresses)
1251 AncestorLookup_Default(Index(addresses.state) -> customers, addresses)
1252 UnionAll_Default()
1253@@ -9,7 +9,8 @@
1254 IndexScan_Default(Index(addresses.state), state = 'MA', cid ASC, aid)
1255 IndexScan_Default(Index(addresses.state), state = 'NY', cid ASC, aid)
1256 IndexScan_Default(Index(addresses.state), state = 'VT', cid ASC, aid)
1257- Filter_Default(customers - orders - items)
1258- Flatten_HKeyOrdered(customers - orders INNER items)
1259- Flatten_HKeyOrdered(customers INNER orders)
1260- BranchLookup_Nested(customers -> orders)
1261\ No newline at end of file
1262+ Product_Nested(customers - addresses x customers - orders - items)
1263+ Filter_Default(customers - orders - items)
1264+ Flatten_HKeyOrdered(customers - orders INNER items)
1265+ Flatten_HKeyOrdered(customers INNER orders)
1266+ BranchLookup_Nested(customers -> orders)
1267\ No newline at end of file
1268
1269=== modified file 'src/test/resources/com/akiban/sql/optimizer/operator/coia-text-index/full-text-2.expected'
1270--- src/test/resources/com/akiban/sql/optimizer/operator/coia-text-index/full-text-2.expected 2013-03-06 16:01:20 +0000
1271+++ src/test/resources/com/akiban/sql/optimizer/operator/coia-text-index/full-text-2.expected 2013-07-18 16:47:28 +0000
1272@@ -1,11 +1,12 @@
1273 PhysicalSelect[cid:int[INT], name:varchar(32)[VARCHAR], oid:int[INT], cid:int[INT], order_date:date[DATE], iid:int[INT], oid:int[INT], sku:varchar(32)[VARCHAR], quan:int[INT], aid:int[INT], cid:int[INT], state:char(2)[VARCHAR], city:varchar(100)[VARCHAR]]
1274 Project_Default(customers.cid, customers.name, orders.oid, orders.cid, orders.order_date, items.iid, items.oid, items.sku, items.quan, addresses.aid, addresses.cid, addresses.state, addresses.city)
1275- Product_NestedLoops(customers - addresses x customers - orders - items)
1276+ Map_NestedLoops()
1277 Filter_Default(customers - addresses)
1278 Flatten_HKeyOrdered(customers INNER addresses)
1279 BranchLookup_Default(HKey -> customers)
1280 IndexScan_FullText(test.customers.cust_ft, +state:MA +sku:1234)
1281- Filter_Default(customers - orders - items)
1282- Flatten_HKeyOrdered(customers - orders INNER items)
1283- Flatten_HKeyOrdered(customers INNER orders)
1284- BranchLookup_Nested(customers -> orders)
1285\ No newline at end of file
1286+ Product_Nested(customers - addresses x customers - orders - items)
1287+ Filter_Default(customers - orders - items)
1288+ Flatten_HKeyOrdered(customers - orders INNER items)
1289+ Flatten_HKeyOrdered(customers INNER orders)
1290+ BranchLookup_Nested(customers -> orders)
1291\ No newline at end of file
1292
1293=== modified file 'src/test/resources/com/akiban/sql/optimizer/operator/coia-text-index/full-text-2n.expected'
1294--- src/test/resources/com/akiban/sql/optimizer/operator/coia-text-index/full-text-2n.expected 2013-03-06 16:01:20 +0000
1295+++ src/test/resources/com/akiban/sql/optimizer/operator/coia-text-index/full-text-2n.expected 2013-07-18 16:47:28 +0000
1296@@ -1,11 +1,12 @@
1297 PhysicalSelect[cid:int[INT], name:varchar(32)[VARCHAR], oid:int[INT], cid:int[INT], order_date:date[DATE], iid:int[INT], oid:int[INT], sku:varchar(32)[VARCHAR], quan:int[INT], aid:int[INT], cid:int[INT], state:char(2)[VARCHAR], city:varchar(100)[VARCHAR]]
1298 Project_Default(customers.cid, customers.name, orders.oid, orders.cid, orders.order_date, items.iid, items.oid, items.sku, items.quan, addresses.aid, addresses.cid, addresses.state, addresses.city)
1299- Product_NestedLoops(customers - addresses x customers - orders - items)
1300+ Map_NestedLoops()
1301 Filter_Default(customers - addresses)
1302 Flatten_HKeyOrdered(customers INNER addresses)
1303 BranchLookup_Default(HKey -> customers)
1304 IndexScan_FullText(test.customers.cust_ft, -state:MA +sku:1234)
1305- Filter_Default(customers - orders - items)
1306- Flatten_HKeyOrdered(customers - orders INNER items)
1307- Flatten_HKeyOrdered(customers INNER orders)
1308- BranchLookup_Nested(customers -> orders)
1309\ No newline at end of file
1310+ Product_Nested(customers - addresses x customers - orders - items)
1311+ Filter_Default(customers - orders - items)
1312+ Flatten_HKeyOrdered(customers - orders INNER items)
1313+ Flatten_HKeyOrdered(customers INNER orders)
1314+ BranchLookup_Nested(customers -> orders)
1315\ No newline at end of file
1316
1317=== modified file 'src/test/resources/com/akiban/sql/optimizer/operator/coia-text-index/full-text-2v.expected'
1318--- src/test/resources/com/akiban/sql/optimizer/operator/coia-text-index/full-text-2v.expected 2013-03-06 16:01:20 +0000
1319+++ src/test/resources/com/akiban/sql/optimizer/operator/coia-text-index/full-text-2v.expected 2013-07-18 16:47:28 +0000
1320@@ -1,11 +1,12 @@
1321 PhysicalSelect[CHAR(2) CHARACTER SET utf8 COLLATE utf8_bin, VARCHAR(32) CHARACTER SET utf8 COLLATE utf8_bin][cid:int[INT], name:varchar(32)[VARCHAR], oid:int[INT], cid:int[INT], order_date:date[DATE], iid:int[INT], oid:int[INT], sku:varchar(32)[VARCHAR], quan:int[INT], aid:int[INT], cid:int[INT], state:char(2)[VARCHAR], city:varchar(100)[VARCHAR]]
1322 Project_Default(customers.cid, customers.name, orders.oid, orders.cid, orders.order_date, items.iid, items.oid, items.sku, items.quan, addresses.aid, addresses.cid, addresses.state, addresses.city)
1323- Product_NestedLoops(customers - addresses x customers - orders - items)
1324+ Map_NestedLoops()
1325 Filter_Default(customers - addresses)
1326 Flatten_HKeyOrdered(customers INNER addresses)
1327 BranchLookup_Default(HKey -> customers)
1328 IndexScan_FullText(test.customers.cust_ft, TERM($1), TERM($2))
1329- Filter_Default(customers - orders - items)
1330- Flatten_HKeyOrdered(customers - orders INNER items)
1331- Flatten_HKeyOrdered(customers INNER orders)
1332- BranchLookup_Nested(customers -> orders)
1333\ No newline at end of file
1334+ Product_Nested(customers - addresses x customers - orders - items)
1335+ Filter_Default(customers - orders - items)
1336+ Flatten_HKeyOrdered(customers - orders INNER items)
1337+ Flatten_HKeyOrdered(customers INNER orders)
1338+ BranchLookup_Nested(customers -> orders)
1339\ No newline at end of file
1340
1341=== modified file 'src/test/resources/com/akiban/sql/optimizer/operator/coia/select-2.expected'
1342--- src/test/resources/com/akiban/sql/optimizer/operator/coia/select-2.expected 2012-08-26 04:29:21 +0000
1343+++ src/test/resources/com/akiban/sql/optimizer/operator/coia/select-2.expected 2013-07-18 16:47:28 +0000
1344@@ -1,9 +1,10 @@
1345 PhysicalSelect[name:varchar(32)[VARCHAR], order_date:date[DATE], city:varchar(100)[VARCHAR]]
1346 Project_Default(customers.name, orders.order_date, addresses.city)
1347- Product_NestedLoops(customers - addresses x customers - orders)
1348+ Map_NestedLoops()
1349 Flatten_HKeyOrdered(customers INNER addresses)
1350 AncestorLookup_Default(Index(addresses.state) -> customers, addresses)
1351 IndexScan_Default(Index(addresses.state), state = 'MA')
1352- Filter_Default(customers - orders)
1353- Flatten_HKeyOrdered(customers INNER orders)
1354- BranchLookup_Nested(customers -> orders)
1355\ No newline at end of file
1356+ Product_Nested(customers - addresses x customers - orders)
1357+ Filter_Default(customers - orders)
1358+ Flatten_HKeyOrdered(customers INNER orders)
1359+ BranchLookup_Nested(customers -> orders)
1360\ No newline at end of file
1361
1362=== modified file 'src/test/resources/com/akiban/sql/optimizer/operator/coia/select-5.expected'
1363--- src/test/resources/com/akiban/sql/optimizer/operator/coia/select-5.expected 2012-08-26 04:29:21 +0000
1364+++ src/test/resources/com/akiban/sql/optimizer/operator/coia/select-5.expected 2013-07-18 16:47:28 +0000
1365@@ -1,10 +1,11 @@
1366 PhysicalSelect[name:varchar(32)[VARCHAR], order_date:date[DATE], state:char(2)[VARCHAR]]
1367 Project_Default(customers.name, orders.order_date, addresses.state)
1368- Product_NestedLoops(customers - addresses x customers - orders)
1369+ Map_NestedLoops()
1370 Filter_Default(customers - addresses)
1371 Flatten_HKeyOrdered(customers INNER addresses)
1372 BranchLookup_Default(Index(customers.name) -> customers)
1373 IndexScan_Default(Index(customers.name), name = 'IBM')
1374- Filter_Default(customers - orders)
1375- Flatten_HKeyOrdered(customers INNER orders)
1376- BranchLookup_Nested(customers -> orders)
1377\ No newline at end of file
1378+ Product_Nested(customers - addresses x customers - orders)
1379+ Filter_Default(customers - orders)
1380+ Flatten_HKeyOrdered(customers INNER orders)
1381+ BranchLookup_Nested(customers -> orders)
1382\ No newline at end of file
1383
1384=== modified file 'src/test/resources/com/akiban/sql/optimizer/operator/coia/select-6.expected'
1385--- src/test/resources/com/akiban/sql/optimizer/operator/coia/select-6.expected 2012-08-26 04:29:21 +0000
1386+++ src/test/resources/com/akiban/sql/optimizer/operator/coia/select-6.expected 2013-07-18 16:47:28 +0000
1387@@ -1,9 +1,10 @@
1388 PhysicalSelect[name:varchar(32)[VARCHAR], order_date:date[DATE], state:char(2)[VARCHAR]]
1389 Project_Default(customers.name, orders.order_date, addresses.state)
1390- Product_NestedLoops(customers - orders x customers - addresses)
1391+ Map_NestedLoops()
1392 Flatten_HKeyOrdered(customers INNER orders)
1393 AncestorLookup_Default(Index(orders.order_date) -> customers, orders)
1394 IndexScan_Default(Index(orders.order_date), order_date > DATE '2011-01-01')
1395- Filter_Default(customers - addresses)
1396- Flatten_HKeyOrdered(customers INNER addresses)
1397- BranchLookup_Nested(customers -> addresses)
1398\ No newline at end of file
1399+ Product_Nested(customers - orders x customers - addresses)
1400+ Filter_Default(customers - addresses)
1401+ Flatten_HKeyOrdered(customers INNER addresses)
1402+ BranchLookup_Nested(customers -> addresses)
1403\ No newline at end of file
1404
1405=== modified file 'src/test/resources/com/akiban/sql/optimizer/operator/coia/select-7.expected'
1406--- src/test/resources/com/akiban/sql/optimizer/operator/coia/select-7.expected 2012-08-26 04:29:21 +0000
1407+++ src/test/resources/com/akiban/sql/optimizer/operator/coia/select-7.expected 2013-07-18 16:47:28 +0000
1408@@ -1,12 +1,13 @@
1409 PhysicalSelect[name:varchar(32)[VARCHAR], order_date:date[DATE], sku:varchar(32)[VARCHAR], state:char(2)[VARCHAR]]
1410 Project_Default(customers.name, orders.order_date, items.sku, addresses.state)
1411- Product_NestedLoops(customers - orders - items x customers - addresses)
1412+ Map_NestedLoops()
1413 Filter_Default(customers - orders - items)
1414 Flatten_HKeyOrdered(customers - orders INNER items)
1415 Flatten_HKeyOrdered(customers INNER orders)
1416 AncestorLookup_Default(orders -> customers)
1417 BranchLookup_Default(Index(orders.order_date) -> orders)
1418 IndexScan_Default(Index(orders.order_date), order_date > DATE '2011-01-01')
1419- Filter_Default(customers - addresses)
1420- Flatten_HKeyOrdered(customers INNER addresses)
1421- BranchLookup_Nested(customers -> addresses)
1422\ No newline at end of file
1423+ Product_Nested(customers - orders - items x customers - addresses)
1424+ Filter_Default(customers - addresses)
1425+ Flatten_HKeyOrdered(customers INNER addresses)
1426+ BranchLookup_Nested(customers -> addresses)
1427\ No newline at end of file
1428
1429=== modified file 'src/test/resources/com/akiban/sql/optimizer/operator/coia/select-8.expected'
1430--- src/test/resources/com/akiban/sql/optimizer/operator/coia/select-8.expected 2012-08-26 04:29:21 +0000
1431+++ src/test/resources/com/akiban/sql/optimizer/operator/coia/select-8.expected 2013-07-18 16:47:28 +0000
1432@@ -1,10 +1,11 @@
1433 PhysicalSelect[name:varchar(32)[VARCHAR], order_date:date[DATE], sku:varchar(32)[VARCHAR], quan:int[INT], state:char(2)[VARCHAR]]
1434 Project_Default(customers.name, orders.order_date, items.sku, items.quan, addresses.state)
1435- Product_NestedLoops(customers - addresses x customers - orders - items)
1436+ Map_NestedLoops()
1437 Filter_Default(customers - addresses)
1438 Flatten_HKeyOrdered(customers INNER addresses)
1439 GroupScan_Default(customers)
1440- Filter_Default(customers - orders - items)
1441- Flatten_HKeyOrdered(customers - orders INNER items)
1442- Flatten_HKeyOrdered(customers INNER orders)
1443- BranchLookup_Nested(customers -> orders)
1444\ No newline at end of file
1445+ Product_Nested(customers - addresses x customers - orders - items)
1446+ Filter_Default(customers - orders - items)
1447+ Flatten_HKeyOrdered(customers - orders INNER items)
1448+ Flatten_HKeyOrdered(customers INNER orders)
1449+ BranchLookup_Nested(customers -> orders)
1450\ No newline at end of file
1451
1452=== modified file 'src/test/resources/com/akiban/sql/optimizer/rule/operator/full-text-2.expected'
1453--- src/test/resources/com/akiban/sql/optimizer/rule/operator/full-text-2.expected 2013-03-06 16:01:20 +0000
1454+++ src/test/resources/com/akiban/sql/optimizer/rule/operator/full-text-2.expected 2013-07-18 16:47:28 +0000
1455@@ -1,11 +1,12 @@
1456 PhysicalSelect@2fc5027d[cid, name, oid, cid, order_date, iid, oid, sku, quan, price, aid, cid, state, city]
1457 Project_Default(Field(0), Field(1), Field(6), Field(7), Field(8), Field(9), Field(10), Field(11), Field(12), Field(13), Field(2), Field(3), Field(4), Field(5))
1458- Product_NestedLoops(test.customers - test.addresses x test.customers - test.orders - test.items)
1459+ Map_NestedLoops()
1460 Filter_Default(test.customers - test.addresses)
1461 Flatten_HKeyOrdered(test.customers INNER test.addresses)
1462 BranchLookup_Default(HKey -> test.customers)
1463 IndexScan_FullText(test.customers.cust_ft, +state:MA +sku:1234)
1464- Filter_Default(test.customers - test.orders - test.items)
1465- Flatten_HKeyOrdered(test.customers - test.orders INNER test.items)
1466- Flatten_HKeyOrdered(test.customers INNER test.orders)
1467- BranchLookup_Nested(test.customers -> test.orders)
1468\ No newline at end of file
1469+ Product_Nested(test.customers - test.addresses x test.customers - test.orders - test.items)
1470+ Filter_Default(test.customers - test.orders - test.items)
1471+ Flatten_HKeyOrdered(test.customers - test.orders INNER test.items)
1472+ Flatten_HKeyOrdered(test.customers INNER test.orders)
1473+ BranchLookup_Nested(test.customers -> test.orders)
1474\ No newline at end of file
1475
1476=== modified file 'src/test/resources/com/akiban/sql/optimizer/rule/operator/select-5.expected'
1477--- src/test/resources/com/akiban/sql/optimizer/rule/operator/select-5.expected 2012-08-26 04:55:19 +0000
1478+++ src/test/resources/com/akiban/sql/optimizer/rule/operator/select-5.expected 2013-07-18 16:47:28 +0000
1479@@ -1,10 +1,11 @@
1480 PhysicalSelect@bd056de[name, order_date, state]
1481 Project_Default(Field(1), Field(8), Field(4))
1482- Product_NestedLoops(test.customers - test.addresses x test.customers - test.orders)
1483+ Map_NestedLoops()
1484 Filter_Default(test.customers - test.addresses)
1485 Flatten_HKeyOrdered(test.customers INNER test.addresses)
1486 BranchLookup_Default(Index(test.customers.name) -> test.customers)
1487 IndexScan_Default(Index(test.customers.name), name = 'IBM', cid ASC)
1488- Filter_Default(test.customers - test.orders)
1489- Flatten_HKeyOrdered(test.customers INNER test.orders)
1490- BranchLookup_Nested(test.customers -> test.orders)
1491\ No newline at end of file
1492+ Product_Nested(test.customers - test.addresses x test.customers - test.orders)
1493+ Filter_Default(test.customers - test.orders)
1494+ Flatten_HKeyOrdered(test.customers INNER test.orders)
1495+ BranchLookup_Nested(test.customers -> test.orders)
1496\ No newline at end of file

Subscribers

People subscribed via source and target branches