} else if (sourceRowType instanceof HKeyRowType) {
Schema schema = outputRowTypes.iterator().next().schema();
inputTableType = schema.tableRowType(sourceRowType.hKey().table());
}
assert inputTableType != null : sourceRowType;
Table inputTable = inputTableType.table();
ArgumentValidation.isSame("inputTable.getGroup()", inputTable.getGroup(),
"group", group);
Table commonAncestor;
if (ancestorRowType == null) {
commonAncestor = inputTable;
} else {
commonAncestor = ancestorRowType.table();
ArgumentValidation.isTrue("ancestorRowType.ancestorOf(inputTableType)",
ancestorRowType.ancestorOf(inputTableType));
}
for (TableRowType outputRowType : outputRowTypes) {
Table outputTable = outputRowType.table();
ArgumentValidation.isSame("outputTable.getGroup()", outputTable.getGroup(),
"group", group);
if (ancestorRowType == null) {
commonAncestor = commonAncestor(commonAncestor, outputTable);
}
else {
ArgumentValidation.isTrue("ancestorRowType.ancestorOf(outputRowType)",
ancestorRowType.ancestorOf(outputRowType));
}
}
this.group = group;
this.inputRowType = inputRowType;
this.sourceRowType = sourceRowType;
this.outputRowTypes = new ArrayList<>(outputRowTypes);
Collections.sort(this.outputRowTypes,
new Comparator<TableRowType>()
{
@Override
public int compare(TableRowType x, TableRowType y)
{
return x.table().getDepth() - y.table().getDepth();
}
});
this.commonAncestor = commonAncestor;
this.keepInput = flag == API.InputPreservationOption.KEEP_INPUT;
this.inputBindingPosition = inputBindingPosition;
this.lookaheadQuantum = lookaheadQuantum;
// See whether there is a single branch beneath commonAncestor
// with all output row types.
Table outputTable = this.outputRowTypes.get(0).table();
boolean allOneBranch;
if (outputTable == commonAncestor) {
allOneBranch = false;
}
else {
while (outputTable.getParentTable() != commonAncestor) {
outputTable = outputTable.getParentTable();
}
TableRowType outputTableRowType = this.outputRowTypes.get(0).schema().tableRowType(outputTable);
allOneBranch = true;
for (int i = 1; i < this.outputRowTypes.size(); i++) {
if (!outputTableRowType.ancestorOf(this.outputRowTypes.get(i))) {
allOneBranch = false;
break;
}
}
}
if (allOneBranch) {
branchRootOrdinal = ordinal(outputTable);
}
else {
branchRootOrdinal = -1;
}
// branchRootOrdinal = -1 means that outputTable is an ancestor of inputTable. In this case, inputPrecedesBranch
// is false. Otherwise, branchRoot's parent is the common ancestor. Find inputTable's ancestor that is also
// a child of the common ancestor. Then compare these ordinals to determine whether input precedes branch.
if (this.branchRootOrdinal == -1) {
this.inputPrecedesBranch = false;
} else if (inputTable == commonAncestor) {
this.inputPrecedesBranch = true;
} else {
Table ancestorOfInputAndChildOfCommon = inputTable;
while (ancestorOfInputAndChildOfCommon.getParentTable() != commonAncestor) {
ancestorOfInputAndChildOfCommon = ancestorOfInputAndChildOfCommon.getParentTable();
}
this.inputPrecedesBranch = ordinal(ancestorOfInputAndChildOfCommon) < branchRootOrdinal;
}
}