56
<li><b>GroupTable groupTable:</b> The group table containing the
57
ancestors of interest.
62
<li><b>Group group:</b> The group containing the ancestors of interest.
59
64
<li><b>RowType inputRowType:</b> Bound row will be of this type.
61
66
<li><b>RowType sourceRowType:</b> Branches will be located for input
67
rows of this type. Possibly a subrow of inputRowType.
64
69
<li><b>UserTableRowType ancestorRowType:</b> Identifies the table in the group at which branching occurs.
65
Must be an ancestor of both inputRowType's table and outputRowType's table.
70
Must be an ancestor of both inputRowType's table and outputRowTypes' tables.
67
<li><b>UserTableRowType outputRowType:</b> Type at the root of the branch to be
72
<li><b>UserTableRowType outputRowTypes:</b> Types within the branch to be
70
75
<li><b>API.InputPreservationOption flag:</b> Indicates whether rows of type rowType
74
79
<li><b>int inputBindingPosition:</b> Indicates input row's position in the query context. The hkey
75
80
of this row will be used to locate ancestors.
82
<li><b>int lookaheadQuantum:</b> Number of cursors to try to keep open by looking
83
ahead in bindings stream.
79
87
inputRowType may be an index row type, a user table row type, or an hkey row type. flag = KEEP_INPUT is permitted
80
88
only for user table row types.
82
The groupTable, inputRowType, and outputRowType must belong to the
90
The groupTable, inputRowType, and outputRowTypes must belong to the
85
93
ancestorRowType's table must be an ancestor of
86
inputRowType's table and outputRowType's table. outputRowType's table must be the parent
87
of outputRowType's table.
94
inputRowType's table and outputRowTypes' tables.
167
181
RowType inputRowType,
168
182
RowType sourceRowType,
169
183
UserTableRowType ancestorRowType,
170
UserTableRowType outputRowType,
184
Collection<UserTableRowType> outputRowTypes,
171
185
API.InputPreservationOption flag,
172
int inputBindingPosition)
186
int inputBindingPosition,
187
int lookaheadQuantum)
174
189
ArgumentValidation.notNull("group", group);
175
190
ArgumentValidation.notNull("inputRowType", inputRowType);
176
191
ArgumentValidation.notNull("sourceRowType", sourceRowType);
177
ArgumentValidation.notNull("outputRowType", outputRowType);
192
ArgumentValidation.notEmpty("outputRowTypes", outputRowTypes);
178
193
ArgumentValidation.notNull("flag", flag);
179
194
ArgumentValidation.isTrue("sourceRowType instanceof UserTableRowType || flag == API.InputPreservationOption.DISCARD_INPUT",
180
195
sourceRowType instanceof UserTableRowType || flag == API.InputPreservationOption.DISCARD_INPUT);
185
200
} else if (sourceRowType instanceof IndexRowType) {
186
201
inputTableType = ((IndexRowType) sourceRowType).tableType();
187
202
} else if (sourceRowType instanceof HKeyRowType) {
188
Schema schema = outputRowType.schema();
203
Schema schema = outputRowTypes.iterator().next().schema();
189
204
inputTableType = schema.userTableRowType(sourceRowType.hKey().userTable());
191
206
assert inputTableType != null : sourceRowType;
192
207
UserTable inputTable = inputTableType.userTable();
193
UserTable outputTable = outputRowType.userTable();
194
ArgumentValidation.isSame("inputTable.getGroup()",
195
inputTable.getGroup(),
196
"outputTable.getGroup()",
197
outputTable.getGroup());
208
ArgumentValidation.isSame("inputTable.getGroup()", inputTable.getGroup(),
210
UserTable commonAncestor;
211
if (ancestorRowType == null) {
212
commonAncestor = inputTable;
214
commonAncestor = ancestorRowType.userTable();
215
ArgumentValidation.isTrue("ancestorRowType.ancestorOf(inputTableType)",
216
ancestorRowType.ancestorOf(inputTableType));
218
for (UserTableRowType outputRowType : outputRowTypes) {
219
UserTable outputTable = outputRowType.userTable();
220
ArgumentValidation.isSame("outputTable.getGroup()", outputTable.getGroup(),
222
if (ancestorRowType == null) {
223
commonAncestor = commonAncestor(commonAncestor, outputTable);
226
ArgumentValidation.isTrue("ancestorRowType.ancestorOf(outputRowType)",
227
ancestorRowType.ancestorOf(outputRowType));
198
230
this.group = group;
199
231
this.inputRowType = inputRowType;
200
232
this.sourceRowType = sourceRowType;
201
this.outputRowType = outputRowType;
233
this.outputRowTypes = new ArrayList<>(outputRowTypes);
234
Collections.sort(this.outputRowTypes,
235
new Comparator<UserTableRowType>()
238
public int compare(UserTableRowType x, UserTableRowType y)
240
return x.userTable().getDepth() - y.userTable().getDepth();
243
this.commonAncestor = commonAncestor;
202
244
this.keepInput = flag == API.InputPreservationOption.KEEP_INPUT;
203
245
this.inputBindingPosition = inputBindingPosition;
204
if (ancestorRowType == null) {
205
this.commonAncestor = commonAncestor(inputTable, outputTable);
207
this.commonAncestor = ancestorRowType.userTable();
208
ArgumentValidation.isTrue("ancestorRowType.ancestorOf(inputTableType)",
209
ancestorRowType.ancestorOf(inputTableType));
210
ArgumentValidation.isTrue("ancestorRowType.ancestorOf(outputRowType)",
211
ancestorRowType.ancestorOf(outputRowType));
213
switch (outputTable.getDepth() - commonAncestor.getDepth()) {
215
branchRootOrdinal = -1;
218
branchRootOrdinal = ordinal(outputTable);
221
branchRootOrdinal = -1;
222
ArgumentValidation.isTrue("false", false);
246
this.lookaheadQuantum = lookaheadQuantum;
247
// See whether there is a single branch beneath commonAncestor
248
// with all output row types.
249
UserTable outputTable = this.outputRowTypes.get(0).userTable();
250
boolean allOneBranch;
251
if (outputTable == commonAncestor) {
252
allOneBranch = false;
255
while (outputTable.parentTable() != commonAncestor) {
256
outputTable = outputTable.parentTable();
258
UserTableRowType outputTableRowType = this.outputRowTypes.get(0).schema().userTableRowType(outputTable);
260
for (int i = 1; i < this.outputRowTypes.size(); i++) {
261
if (!outputTableRowType.ancestorOf(this.outputRowTypes.get(i))) {
262
allOneBranch = false;
268
branchRootOrdinal = ordinal(outputTable);
271
branchRootOrdinal = -1;
225
273
// branchRootOrdinal = -1 means that outputTable is an ancestor of inputTable. In this case, inputPrecedesBranch
226
274
// is false. Otherwise, branchRoot's parent is the common ancestor. Find inputTable's ancestor that is also
269
317
private final Group group;
270
318
private final RowType inputRowType, sourceRowType;
271
private final UserTableRowType outputRowType;
319
private final List<UserTableRowType> outputRowTypes;
272
320
private final boolean keepInput;
273
321
// If keepInput is true, inputPrecedesBranch controls whether input row appears before the retrieved branch.
274
322
private final boolean inputPrecedesBranch;
275
323
private final int inputBindingPosition;
324
private final int lookaheadQuantum;
276
325
private final UserTable commonAncestor;
277
326
private final int branchRootOrdinal;
282
331
Attributes atts = new Attributes();
283
332
atts.put(Label.BINDING_POSITION, PrimitiveExplainer.getInstance(inputBindingPosition));
284
atts.put(Label.OUTPUT_TYPE, outputRowType.getExplainer(context));
333
for (UserTableRowType outputRowType : outputRowTypes) {
334
atts.put(Label.OUTPUT_TYPE, outputRowType.getExplainer(context));
336
UserTableRowType outputRowType = outputRowTypes.get(0);
285
337
UserTableRowType ancestorRowType = outputRowType.schema().userTableRowType(commonAncestor);
286
if ((ancestorRowType != sourceRowType) && (ancestorRowType != outputRowType))
338
if ((ancestorRowType != sourceRowType) && (ancestorRowType != outputRowType)) {
287
339
atts.put(Label.ANCESTOR_TYPE, ancestorRowType.getExplainer(context));
341
atts.put(Label.PIPELINE, PrimitiveExplainer.getInstance(lookaheadQuantum));
288
342
return new LookUpOperatorExplainer(getName(), atts, sourceRowType, false, null, context);
416
472
private ShareHolder<Row> inputRow = new ShareHolder<>();
417
473
private boolean idle = true;
476
private class BranchCursor implements BindingsAwareCursor
478
// BindingsAwareCursor interface
482
Row rowFromBindings = bindings.getRow(inputBindingPosition);
483
assert rowFromBindings.rowType() == inputRowType : rowFromBindings;
484
if (inputRowType != sourceRowType) {
485
rowFromBindings = rowFromBindings.subRow(sourceRowType);
487
computeLookupRowHKey(rowFromBindings);
488
cursor.rebind(hKey, true);
490
inputRow.hold(rowFromBindings);
496
if (keepInput && inputPrecedesBranch && inputRow.isHolding()) {
497
row = inputRow.get();
502
} while ((row != null) && !outputRowTypes.contains(row.rowType()));
504
if (keepInput && !inputPrecedesBranch) {
505
assert inputRow.isHolding();
506
row = inputRow.get();
516
public void jump(Row row, ColumnSelector columnSelector) {
517
cursor.jump(row, columnSelector);
521
public void close() {
527
public void destroy() {
533
public boolean isIdle() {
534
return cursor.isIdle();
538
public boolean isActive() {
539
return cursor.isActive();
543
public boolean isDestroyed() {
544
return cursor.isDestroyed();
548
public void rebind(QueryBindings bindings) {
549
this.bindings = bindings;
552
// BranchCursor interface
553
public BranchCursor(StoreAdapter adapter) {
554
this.cursor = adapter.newGroupCursor(group);
555
this.hKey = adapter.newHKey(outputRowTypes.get(0).hKey());
558
// For use by this class
560
private void computeLookupRowHKey(Row row)
562
HKey ancestorHKey = row.ancestorHKey(commonAncestor);
563
ancestorHKey.copyTo(hKey);
564
if (branchRootOrdinal != -1) {
565
hKey.extendWithOrdinal(branchRootOrdinal);
571
private final GroupCursor cursor;
572
private final HKey hKey;
573
private ShareHolder<Row> inputRow = new ShareHolder<>();
574
private QueryBindings bindings;
577
private class LookaheadExecution extends LookaheadLeafCursor<BranchCursor>
593
if (TAP_NEXT_ENABLED) {
597
Row row = super.next();
599
LOG.debug("BranchLookup_Nested: yield {}", row);
603
if (TAP_NEXT_ENABLED) {
609
// LookaheadLeafCursor interface
612
protected BranchCursor newCursor(QueryContext context, StoreAdapter adapter) {
613
return new BranchCursor(adapter);
617
protected BranchCursor openACursor(QueryBindings bindings, boolean lookahead) {
618
BranchCursor cursor = super.openACursor(bindings, lookahead);
620
LOG.debug("BranchLookup_Nested: open{} using {}", lookahead ? " lookahead" : "", cursor.inputRow.get());
625
// LookaheadExecution interface
627
LookaheadExecution(QueryContext context, QueryBindingsCursor bindingsCursor,
628
StoreAdapter adapter, int quantum) {
629
super(context, bindingsCursor, adapter, quantum);