Merge lp:~mmcm/akiban-server/query-bindings-cancel into lp:~akiban-technologies/akiban-server/trunk

Proposed by Mike McMahon
Status: Merged
Approved by: Nathan Williams
Approved revision: 2706
Merged at revision: 2703
Proposed branch: lp:~mmcm/akiban-server/query-bindings-cancel
Merge into: lp:~akiban-technologies/akiban-server/trunk
Diff against target: 601 lines (+266/-33)
20 files modified
src/main/java/com/akiban/qp/operator/Aggregate_Partial.java (+6/-0)
src/main/java/com/akiban/qp/operator/AncestorLookup_Default.java (+29/-0)
src/main/java/com/akiban/qp/operator/ChainedCursor.java (+6/-0)
src/main/java/com/akiban/qp/operator/HKeyUnion_Ordered.java (+7/-0)
src/main/java/com/akiban/qp/operator/IndexScan_Default.java (+28/-0)
src/main/java/com/akiban/qp/operator/Intersect_Ordered.java (+7/-0)
src/main/java/com/akiban/qp/operator/LeafCursor.java (+6/-0)
src/main/java/com/akiban/qp/operator/Map_NestedLoops.java (+54/-33)
src/main/java/com/akiban/qp/operator/MultipleQueryBindingsCursor.java (+19/-0)
src/main/java/com/akiban/qp/operator/Product_NestedLoops.java (+7/-0)
src/main/java/com/akiban/qp/operator/QueryBindings.java (+5/-0)
src/main/java/com/akiban/qp/operator/QueryBindingsCursor.java (+3/-0)
src/main/java/com/akiban/qp/operator/Select_BloomFilter.java (+6/-0)
src/main/java/com/akiban/qp/operator/SingletonQueryBindingsCursor.java (+7/-0)
src/main/java/com/akiban/qp/operator/SparseArrayQueryBindings.java (+10/-0)
src/main/java/com/akiban/qp/operator/UnionAll_Default.java (+8/-0)
src/main/java/com/akiban/qp/operator/Union_Ordered.java (+7/-0)
src/test/java/com/akiban/qp/operator/QueryBindingsTest.java (+3/-0)
src/test/java/com/akiban/server/test/it/qp/Map_NestedLoopsIT.java (+43/-0)
src/test/java/com/akiban/server/test/pt/AggregatePT.java (+5/-0)
To merge this branch: bzr merge lp:~mmcm/akiban-server/query-bindings-cancel
Reviewer Review Type Date Requested Status
Nathan Williams Approve
Review via email: mp+175222@code.launchpad.net

Description of the change

Enhance query bindings stream to address early close.

When Map output is closed before end-of-stream, it must advance query bindings until the next one at a higher level than the depth it is collapsing. It can do this by actually calling nextBindings(), but that requires upstream operators to continue to process the depth that is actually being skipped. For instance, in the new test added to the Map IT, the 20 and 30 rows would still flow through even after Limit has closed the Map. Also query cancel of, say, a 10-way cross-product would not stop because the level that happened to detect the cancel, which is not likely to be near the leaf, will try to advance.

The new cancelBindings methods advances past the given query bindings. As with open() and close(), trivial operators can assume that their neighbors are taking care of binding complexity and just do like close(), except that they pass along cancel to their input. Operators that do lookahead for pipelining should discard any lookahead state that is under the given bindings.

To post a comment you must log in.
Revision history for this message
Nathan Williams (nwilliams) wrote :

Looks as expected.

review: Approve

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/Aggregate_Partial.java'
2--- src/main/java/com/akiban/qp/operator/Aggregate_Partial.java 2013-07-09 17:26:33 +0000
3+++ src/main/java/com/akiban/qp/operator/Aggregate_Partial.java 2013-07-17 08:37:29 +0000
4@@ -503,6 +503,12 @@
5 inputCursor.closeBindings();
6 }
7
8+ @Override
9+ public void cancelBindings(QueryBindings bindings) {
10+ inputCursor.cancelBindings(bindings);
11+ cursorState = CursorState.CLOSED;
12+ }
13+
14 // for use in this class
15
16 private void aggregate(Row input) {
17
18=== modified file 'src/main/java/com/akiban/qp/operator/AncestorLookup_Default.java'
19--- src/main/java/com/akiban/qp/operator/AncestorLookup_Default.java 2013-07-13 21:17:31 +0000
20+++ src/main/java/com/akiban/qp/operator/AncestorLookup_Default.java 2013-07-17 08:37:29 +0000
21@@ -578,6 +578,35 @@
22 clearBindings();
23 }
24
25+ @Override
26+ public void cancelBindings(QueryBindings bindings) {
27+ while (true) {
28+ QueryBindings pending = pendingBindings.peek();
29+ if (pending == null) break;
30+ if (!pending.isAncestor(bindings)) break;
31+ pendingBindings.remove();
32+ }
33+ int nancestors = ancestors.size();
34+ while ((inputRowBindings[currentIndex] != null) &&
35+ inputRowBindings[currentIndex].isAncestor(bindings)) {
36+ inputRows[currentIndex].release();
37+ inputRowBindings[currentIndex] = null;
38+ for (int i = 0; i < nancestors; i++) {
39+ int index = currentIndex * nancestors + i;
40+ ancestorCursors[index].close();
41+ ancestorHKeys[index] = null;
42+ }
43+ currentIndex = (currentIndex + 1) % quantum;
44+ }
45+ currentBindings = null;
46+ newBindings = false;
47+ input.cancelBindings(bindings);
48+ if ((nextBindings != null) && nextBindings.isAncestor(bindings)) {
49+ nextBindings = null;
50+ }
51+ closed = true;
52+ }
53+
54 // LookaheadExecution interface
55
56 LookaheadExecution(QueryContext context, Cursor input, int quantum) {
57
58=== modified file 'src/main/java/com/akiban/qp/operator/ChainedCursor.java'
59--- src/main/java/com/akiban/qp/operator/ChainedCursor.java 2013-07-09 17:26:33 +0000
60+++ src/main/java/com/akiban/qp/operator/ChainedCursor.java 2013-07-17 08:37:29 +0000
61@@ -91,4 +91,10 @@
62 public void closeBindings() {
63 input.closeBindings();
64 }
65+
66+ @Override
67+ public void cancelBindings(QueryBindings ancestor) {
68+ input.cancelBindings(ancestor);
69+ close(); // In case override maintains some additional state.
70+ }
71 }
72
73=== modified file 'src/main/java/com/akiban/qp/operator/HKeyUnion_Ordered.java'
74--- src/main/java/com/akiban/qp/operator/HKeyUnion_Ordered.java 2013-07-09 19:53:07 +0000
75+++ src/main/java/com/akiban/qp/operator/HKeyUnion_Ordered.java 2013-07-17 08:37:29 +0000
76@@ -332,6 +332,13 @@
77 rightInput.closeBindings();
78 }
79
80+ @Override
81+ public void cancelBindings(QueryBindings bindings) {
82+ leftInput.cancelBindings(bindings);
83+ rightInput.cancelBindings(bindings);
84+ bindingsCursor.cancelBindings(bindings);
85+ }
86+
87 // Execution interface
88
89 Execution(QueryContext context, QueryBindingsCursor bindingsCursor)
90
91=== modified file 'src/main/java/com/akiban/qp/operator/IndexScan_Default.java'
92--- src/main/java/com/akiban/qp/operator/IndexScan_Default.java 2013-07-13 21:03:15 +0000
93+++ src/main/java/com/akiban/qp/operator/IndexScan_Default.java 2013-07-17 08:37:29 +0000
94@@ -537,6 +537,34 @@
95 recyclePending();
96 }
97
98+ @Override
99+ public void cancelBindings(QueryBindings bindings) {
100+ if ((currentBindings != null) && currentBindings.isAncestor(bindings)) {
101+ if (currentCursor != null) {
102+ currentCursor.close();
103+ cursorPool.add(currentCursor);
104+ currentCursor = null;
105+ }
106+ if (pendingCursor != null) {
107+ pendingCursor.close();
108+ cursorPool.add(pendingCursor);
109+ pendingCursor = null;
110+ }
111+ currentBindings = null;
112+ }
113+ while (true) {
114+ BindingsAndCursor bandc = pendingBindings.peek();
115+ if (bandc == null) break;
116+ if (!bandc.bindings.isAncestor(bindings)) break;
117+ bandc = pendingBindings.remove();
118+ if (bandc.cursor != null) {
119+ bandc.cursor.close();
120+ cursorPool.add(bandc.cursor);
121+ }
122+ }
123+ bindingsCursor.cancelBindings(bindings);
124+ }
125+
126 // LookaheadExecution interface
127
128 LookaheadExecution(QueryContext context, QueryBindingsCursor bindingsCursor,
129
130=== modified file 'src/main/java/com/akiban/qp/operator/Intersect_Ordered.java'
131--- src/main/java/com/akiban/qp/operator/Intersect_Ordered.java 2013-07-09 19:53:07 +0000
132+++ src/main/java/com/akiban/qp/operator/Intersect_Ordered.java 2013-07-17 08:37:29 +0000
133@@ -431,6 +431,13 @@
134 rightInput.closeBindings();
135 }
136
137+ @Override
138+ public void cancelBindings(QueryBindings bindings) {
139+ leftInput.cancelBindings(bindings);
140+ rightInput.cancelBindings(bindings);
141+ bindingsCursor.cancelBindings(bindings);
142+ }
143+
144 // Execution interface
145
146 Execution(QueryContext context, QueryBindingsCursor bindingsCursor)
147
148=== modified file 'src/main/java/com/akiban/qp/operator/LeafCursor.java'
149--- src/main/java/com/akiban/qp/operator/LeafCursor.java 2013-07-09 17:26:33 +0000
150+++ src/main/java/com/akiban/qp/operator/LeafCursor.java 2013-07-17 08:37:29 +0000
151@@ -42,4 +42,10 @@
152 public void closeBindings() {
153 bindingsCursor.closeBindings();
154 }
155+
156+ @Override
157+ public void cancelBindings(QueryBindings bindings) {
158+ close();
159+ bindingsCursor.cancelBindings(bindings);
160+ }
161 }
162
163=== modified file 'src/main/java/com/akiban/qp/operator/Map_NestedLoops.java'
164--- src/main/java/com/akiban/qp/operator/Map_NestedLoops.java 2013-07-13 20:10:49 +0000
165+++ src/main/java/com/akiban/qp/operator/Map_NestedLoops.java 2013-07-17 08:37:29 +0000
166@@ -219,6 +219,17 @@
167 }
168 input.closeBindings();
169 }
170+
171+ @Override
172+ public void cancelBindings(QueryBindings bindings) {
173+ if ((baseBindings != null) && baseBindings.isAncestor(bindings)) {
174+ baseBindings = null;
175+ input.close();
176+ }
177+ if (bindings.getDepth() < depth) {
178+ input.cancelBindings(bindings);
179+ }
180+ }
181 }
182
183 // Other end of pipeline: remove the extra binding levels that we
184@@ -228,8 +239,7 @@
185 {
186 private final Cursor input;
187 private final int depth;
188- private QueryBindings pendingBindings;
189- private boolean open, inputOpen;
190+ private QueryBindings currentBindings, pendingBindings, openBindings, inputOpenBindings;
191
192 public CollapseBindingsCursor(QueryContext context, Cursor input, int depth) {
193 super(context);
194@@ -240,8 +250,8 @@
195 @Override
196 public void open() {
197 CursorLifecycle.checkIdle(this);
198- open = true;
199- inputOpen = false;
200+ openBindings = currentBindings;
201+ inputOpenBindings = null;
202 }
203
204 @Override
205@@ -256,25 +266,25 @@
206 checkQueryCancelation();
207 Row row = null;
208 while (true) {
209- if (inputOpen) {
210+ if (inputOpenBindings != null) {
211 row = input.next();
212 if (row != null) break;
213 input.close();
214- inputOpen = false;
215+ inputOpenBindings = null;
216 }
217 QueryBindings bindings = input.nextBindings();
218 if (bindings == null) {
219- open = false;
220+ openBindings = null;
221 break;
222 }
223 if (bindings.getDepth() == depth) {
224 input.open();
225- inputOpen = true;
226+ inputOpenBindings = bindings;
227 }
228 else if (bindings.getDepth() < depth) {
229 // End of this binding's rowset. Arrange for this to be next one.
230 pendingBindings = bindings;
231- open = false;
232+ openBindings = null;
233 break;
234 }
235 else {
236@@ -301,20 +311,10 @@
237 @Override
238 public void close() {
239 CursorLifecycle.checkIdleOrActive(this);
240- if (open) {
241- if (inputOpen) {
242- input.close();
243- inputOpen = false;
244- }
245- // Advance bindings to where stream would have ended.
246- while (pendingBindings == null) {
247- QueryBindings bindings = input.nextBindings();
248- if (bindings == null) break;
249- if (bindings.getDepth() < depth) {
250- pendingBindings = bindings;
251- }
252- }
253- open = false;
254+ if (openBindings != null) {
255+ cancelBindings(openBindings);
256+ assert (inputOpenBindings == null);
257+ assert (openBindings == null);
258 }
259 }
260
261@@ -326,12 +326,12 @@
262
263 @Override
264 public boolean isIdle() {
265- return !input.isDestroyed() && !open;
266+ return !input.isDestroyed() && (openBindings == null);
267 }
268
269 @Override
270 public boolean isActive() {
271- return open;
272+ return (openBindings != null);
273 }
274
275 @Override
276@@ -341,23 +341,23 @@
277
278 @Override
279 public void openBindings() {
280- pendingBindings = null;
281+ pendingBindings = currentBindings = null;
282 input.openBindings();
283 }
284
285 @Override
286 public QueryBindings nextBindings() {
287- QueryBindings bindings = pendingBindings;
288- if (bindings != null) {
289+ currentBindings = pendingBindings;
290+ if (currentBindings != null) {
291 pendingBindings = null;
292- return bindings;
293+ return currentBindings;
294 }
295 while (true) {
296 // Skip over any that we would elide.
297- bindings = input.nextBindings();
298- if ((bindings == null) || (bindings.getDepth() < depth))
299- return bindings;
300- assert (bindings.getDepth() == depth);
301+ currentBindings = input.nextBindings();
302+ if ((currentBindings == null) || (currentBindings.getDepth() < depth))
303+ return currentBindings;
304+ assert (currentBindings.getDepth() == depth);
305 }
306 }
307
308@@ -365,6 +365,20 @@
309 public void closeBindings() {
310 input.closeBindings();
311 }
312+
313+ @Override
314+ public void cancelBindings(QueryBindings bindings) {
315+ input.cancelBindings(bindings);
316+ if ((inputOpenBindings != null) && inputOpenBindings.isAncestor(bindings)) {
317+ inputOpenBindings = null;
318+ }
319+ if ((openBindings != null) && openBindings.isAncestor(bindings)) {
320+ openBindings = null;
321+ }
322+ if ((pendingBindings != null) && pendingBindings.isAncestor(bindings)) {
323+ pendingBindings = null;
324+ }
325+ }
326 }
327
328 // Old-style execution: bind outer row into existing context and
329@@ -477,6 +491,13 @@
330 outerInput.closeBindings();
331 }
332
333+ @Override
334+ public void cancelBindings(QueryBindings bindings) {
335+ innerInput.close();
336+ outerInput.cancelBindings(bindings);
337+ closed = true;
338+ }
339+
340 // Execution interface
341
342 Execution(QueryContext context, QueryBindingsCursor bindingsCursor)
343
344=== modified file 'src/main/java/com/akiban/qp/operator/MultipleQueryBindingsCursor.java'
345--- src/main/java/com/akiban/qp/operator/MultipleQueryBindingsCursor.java 2013-07-09 21:47:07 +0000
346+++ src/main/java/com/akiban/qp/operator/MultipleQueryBindingsCursor.java 2013-07-17 08:37:29 +0000
347@@ -58,6 +58,11 @@
348 cursors.get(0).closeBindings();
349 }
350
351+ @Override
352+ public void cancelBindings(QueryBindings bindings) {
353+ input.cancelBindings(bindings);
354+ }
355+
356 public QueryBindingsCursor newCursor() {
357 assert (offset == 0);
358 SubCursor cursor = new SubCursor();
359@@ -117,5 +122,19 @@
360 public void closeBindings() {
361 open = false;
362 }
363+
364+ @Override
365+ public void cancelBindings(QueryBindings ancestor) {
366+ while (index - offset < buffer.size()) {
367+ QueryBindings bindings = buffer.get(index - offset);
368+ if (bindings.isAncestor(ancestor)) {
369+ index++;
370+ }
371+ else {
372+ break;
373+ }
374+ }
375+ shrink();
376+ }
377 }
378 }
379
380=== modified file 'src/main/java/com/akiban/qp/operator/Product_NestedLoops.java'
381--- src/main/java/com/akiban/qp/operator/Product_NestedLoops.java 2013-07-09 18:29:49 +0000
382+++ src/main/java/com/akiban/qp/operator/Product_NestedLoops.java 2013-07-17 08:37:29 +0000
383@@ -317,6 +317,13 @@
384 outerInput.closeBindings();
385 }
386
387+ @Override
388+ public void cancelBindings(QueryBindings bindings) {
389+ closeInner();
390+ outerInput.cancelBindings(bindings);
391+ closed = true;
392+ }
393+
394 // Execution interface
395
396 Execution(QueryContext context, QueryBindingsCursor bindingsCursor)
397
398=== modified file 'src/main/java/com/akiban/qp/operator/QueryBindings.java'
399--- src/main/java/com/akiban/qp/operator/QueryBindings.java 2013-07-10 17:31:42 +0000
400+++ src/main/java/com/akiban/qp/operator/QueryBindings.java 2013-07-17 08:37:29 +0000
401@@ -114,6 +114,11 @@
402 public QueryBindings getParent();
403
404 /**
405+ * Is this bindings an descendant of the given bindings?
406+ */
407+ public boolean isAncestor(QueryBindings ancestor);
408+
409+ /**
410 * Get the inheritance depth.
411 */
412 public int getDepth();
413
414=== modified file 'src/main/java/com/akiban/qp/operator/QueryBindingsCursor.java'
415--- src/main/java/com/akiban/qp/operator/QueryBindingsCursor.java 2013-07-09 21:47:07 +0000
416+++ src/main/java/com/akiban/qp/operator/QueryBindingsCursor.java 2013-07-17 08:37:29 +0000
417@@ -30,4 +30,7 @@
418
419 /** Close stream of bindings. */
420 public void closeBindings();
421+
422+ /** Advance stream past given bindings. */
423+ public void cancelBindings(QueryBindings bindings);
424 }
425
426=== modified file 'src/main/java/com/akiban/qp/operator/Select_BloomFilter.java'
427--- src/main/java/com/akiban/qp/operator/Select_BloomFilter.java 2013-07-09 18:29:49 +0000
428+++ src/main/java/com/akiban/qp/operator/Select_BloomFilter.java 2013-07-17 08:37:29 +0000
429@@ -338,6 +338,12 @@
430 inputCursor.closeBindings();
431 }
432
433+ @Override
434+ public void cancelBindings(QueryBindings bindings) {
435+ inputCursor.cancelBindings(bindings);
436+ idle = true;
437+ }
438+
439 // Execution interface
440
441 <EXPR> Execution(QueryContext context, QueryBindingsCursor bindingsCursor,
442
443=== modified file 'src/main/java/com/akiban/qp/operator/SingletonQueryBindingsCursor.java'
444--- src/main/java/com/akiban/qp/operator/SingletonQueryBindingsCursor.java 2013-07-09 00:11:30 +0000
445+++ src/main/java/com/akiban/qp/operator/SingletonQueryBindingsCursor.java 2013-07-17 08:37:29 +0000
446@@ -54,6 +54,13 @@
447 state = State.CLOSED;
448 }
449
450+ @Override
451+ public void cancelBindings(QueryBindings ancestor) {
452+ if ((state == State.PENDING) && bindings.isAncestor(ancestor)) {
453+ state = State.EXHAUSTED;
454+ }
455+ }
456+
457 public void reset(QueryBindings bindings) {
458 this.bindings = bindings;
459 this.state = State.CLOSED;
460
461=== modified file 'src/main/java/com/akiban/qp/operator/SparseArrayQueryBindings.java'
462--- src/main/java/com/akiban/qp/operator/SparseArrayQueryBindings.java 2013-07-12 20:53:41 +0000
463+++ src/main/java/com/akiban/qp/operator/SparseArrayQueryBindings.java 2013-07-17 08:37:29 +0000
464@@ -246,6 +246,16 @@
465 }
466
467 @Override
468+ public boolean isAncestor(QueryBindings ancestor) {
469+ for (QueryBindings descendant = this; descendant != null; descendant = descendant.getParent()) {
470+ if (descendant == ancestor) {
471+ return true;
472+ }
473+ }
474+ return false;
475+ }
476+
477+ @Override
478 public int getDepth() {
479 return depth;
480 }
481
482=== modified file 'src/main/java/com/akiban/qp/operator/UnionAll_Default.java'
483--- src/main/java/com/akiban/qp/operator/UnionAll_Default.java 2013-07-09 19:53:07 +0000
484+++ src/main/java/com/akiban/qp/operator/UnionAll_Default.java 2013-07-17 08:37:29 +0000
485@@ -327,6 +327,14 @@
486 }
487 }
488
489+ @Override
490+ public void cancelBindings(QueryBindings bindings) {
491+ for (int i = 0; i < cursors.length; i++) {
492+ cursors[i].cancelBindings(bindings);
493+ }
494+ bindingsCursor.cancelBindings(bindings);
495+ }
496+
497 private Execution(QueryContext context, QueryBindingsCursor bindingsCursor)
498 {
499 super(context);
500
501=== modified file 'src/main/java/com/akiban/qp/operator/Union_Ordered.java'
502--- src/main/java/com/akiban/qp/operator/Union_Ordered.java 2013-07-09 19:53:07 +0000
503+++ src/main/java/com/akiban/qp/operator/Union_Ordered.java 2013-07-17 08:37:29 +0000
504@@ -333,6 +333,13 @@
505 rightInput.closeBindings();
506 }
507
508+ @Override
509+ public void cancelBindings(QueryBindings bindings) {
510+ leftInput.cancelBindings(bindings);
511+ rightInput.cancelBindings(bindings);
512+ bindingsCursor.cancelBindings(bindings);
513+ }
514+
515 // Execution interface
516
517 Execution(QueryContext context, QueryBindingsCursor bindingsCursor)
518
519=== modified file 'src/test/java/com/akiban/qp/operator/QueryBindingsTest.java'
520--- src/test/java/com/akiban/qp/operator/QueryBindingsTest.java 2013-07-10 18:06:04 +0000
521+++ src/test/java/com/akiban/qp/operator/QueryBindingsTest.java 2013-07-17 08:37:29 +0000
522@@ -77,6 +77,9 @@
523 parent.setPValue(0, value);
524 QueryBindings child = parent.createBindings();
525 assertEquals(1, child.getDepth());
526+ assertTrue(parent.isAncestor(parent));
527+ assertTrue(child.isAncestor(parent));
528+ assertFalse(parent.isAncestor(child));
529 Deque<Row> rows = new RowsBuilder(MNumeric.INT.instance(false))
530 .row(100)
531 .row(101)
532
533=== modified file 'src/test/java/com/akiban/server/test/it/qp/Map_NestedLoopsIT.java'
534--- src/test/java/com/akiban/server/test/it/qp/Map_NestedLoopsIT.java 2013-07-13 19:25:25 +0000
535+++ src/test/java/com/akiban/server/test/it/qp/Map_NestedLoopsIT.java 2013-07-17 08:37:29 +0000
536@@ -303,6 +303,49 @@
537 compareRows(expected, cursor(plan, queryContext, queryBindings));
538 }
539
540+ @Test
541+ public void testDeepMapLimit()
542+ {
543+ RowType intRowType = schema.newValuesType(AkType.INT);
544+ List<ExpressionGenerator> expressions = Arrays.asList(boundField(intRowType, 0, 0), boundField(intRowType, 1, 0), field(intRowType, 0));
545+ Operator inside =
546+ project_Default(
547+ valuesScan_Default(
548+ bindableExpressions(intRow(intRowType, 1),
549+ intRow(intRowType, 2),
550+ intRow(intRowType, 3)),
551+ intRowType),
552+ intRowType, expressions);
553+ RowType insideRowType = inside.rowType();
554+ Operator plan =
555+ map_NestedLoops(
556+ valuesScan_Default(
557+ bindableExpressions(intRow(intRowType, 100),
558+ intRow(intRowType, 200),
559+ intRow(intRowType, 300)),
560+ intRowType),
561+ limit_Default(
562+ map_NestedLoops(
563+ valuesScan_Default(
564+ bindableExpressions(intRow(intRowType, 10),
565+ intRow(intRowType, 20),
566+ intRow(intRowType, 30)),
567+ intRowType),
568+ inside,
569+ 1, pipelineMap(), 2),
570+ 2),
571+ 0, pipelineMap(), 1);
572+ RowBase[] expected = new RowBase[]{
573+ row(insideRowType, 100L, 10L, 1L),
574+ row(insideRowType, 100L, 10L, 2L),
575+ row(insideRowType, 200L, 10L, 1L),
576+ row(insideRowType, 200L, 10L, 2L),
577+ row(insideRowType, 300L, 10L, 1L),
578+ row(insideRowType, 300L, 10L, 2L),
579+ };
580+ compareRows(expected, cursor(plan, queryContext, queryBindings));
581+ }
582+
583 private Row intRow(RowType rowType, int x)
584 {
585 List<Expression> expressions;
586
587=== modified file 'src/test/java/com/akiban/server/test/pt/AggregatePT.java'
588--- src/test/java/com/akiban/server/test/pt/AggregatePT.java 2013-07-13 17:24:25 +0000
589+++ src/test/java/com/akiban/server/test/pt/AggregatePT.java 2013-07-17 08:37:29 +0000
590@@ -390,6 +390,11 @@
591 public void closeBindings() {
592 inputCursor.closeBindings();
593 }
594+
595+ @Override
596+ public void cancelBindings(QueryBindings bindings) {
597+ inputCursor.cancelBindings(bindings);
598+ }
599 }
600
601 static final AkType[] TYPES = {

Subscribers

People subscribed via source and target branches