int[] fieldPositions = new int[count];
QueryPlan[] joinPlans = new QueryPlan[count];
fieldPositions[0] = projectedTable.getTable().getColumns().size() - projectedTable.getTable().getPKColumns().size();
boolean needsProject = asSubquery;
for (int i = 0; i < count; i++) {
JoinTable joinTable = joinTables.get(i);
SelectStatement subStatement = joinTable.getAsSubquery();
if (subStatement.getFrom().size() > 1)
throw new SQLFeatureNotSupportedException("Sub queries not supported.");
ProjectedPTableWrapper subProjTable = join.createProjectedTable(joinTable.getTable(), false);
ColumnResolver resolver = join.getColumnResolver(subProjTable);
Scan subScan = ScanUtil.newScan(originalScan);
ScanProjector.serializeProjectorIntoScan(subScan, JoinCompiler.getScanProjector(subProjTable));
StatementContext subContext = new StatementContext(statement, resolver, subScan);
subContext.setCurrentTable(joinTable.getTable());
join.projectColumns(subScan, joinTable.getTable());
joinPlans[i] = compileSingleQuery(subContext, subStatement, binds, null);
boolean hasPostReference = join.hasPostReference(joinTable.getTable());
if (hasPostReference) {
tables[i] = subProjTable.getTable();
projectedTable = JoinCompiler.mergeProjectedTables(projectedTable, subProjTable, joinTable.getType() == JoinType.Inner);
needsProject = true;
} else {
tables[i] = null;
}
if (!starJoinVector[i]) {
needsProject = true;
}
ColumnResolver leftResolver = starJoinVector[i] ? join.getOriginalResolver() : join.getColumnResolver(projectedTable);
joinIds[i] = new ImmutableBytesPtr(emptyByteArray); // place-holder
Pair<List<Expression>, List<Expression>> joinConditions = joinTable.compileJoinConditions(context, leftResolver, resolver);
joinExpressions[i] = joinConditions.getFirst();
hashExpressions[i] = joinConditions.getSecond();
joinTypes[i] = joinTable.getType();
if (i < count - 1) {
fieldPositions[i + 1] = fieldPositions[i] + (tables[i] == null ? 0 : (tables[i].getColumns().size() - tables[i].getPKColumns().size()));
}
}
if (needsProject) {
ScanProjector.serializeProjectorIntoScan(context.getScan(), JoinCompiler.getScanProjector(initialProjectedTable));
}
context.setCurrentTable(join.getMainTable());
context.setResolver(needsProject ? join.getColumnResolver(projectedTable) : join.getOriginalResolver());
join.projectColumns(context.getScan(), join.getMainTable());
BasicQueryPlan plan = compileSingleQuery(context, JoinCompiler.getSubqueryWithoutJoin(select, join), binds, parallelIteratorFactory);
Expression postJoinFilterExpression = join.compilePostFilterExpression(context);
HashJoinInfo joinInfo = new HashJoinInfo(projectedTable.getTable(), joinIds, joinExpressions, joinTypes, starJoinVector, tables, fieldPositions, postJoinFilterExpression);
return new HashJoinPlan(plan, joinInfo, hashExpressions, joinPlans);
}
JoinTable lastJoinTable = joinTables.get(joinTables.size() - 1);
JoinType type = lastJoinTable.getType();
if (type == JoinType.Full)
throw new SQLFeatureNotSupportedException("Full joins not supported.");
if (type == JoinType.Right || type == JoinType.Inner) {
SelectStatement lhs = JoinCompiler.getSubQueryWithoutLastJoin(select, join);
SelectStatement rhs = JoinCompiler.getSubqueryForLastJoinTable(select, join);
JoinSpec lhsJoin = JoinCompiler.getSubJoinSpecWithoutPostFilters(join);
Scan subScan = ScanUtil.newScan(originalScan);
StatementContext lhsCtx = new StatementContext(statement, context.getResolver(), subScan);
QueryPlan lhsPlan = compileJoinQuery(lhsCtx, lhs, binds, lhsJoin, true);
ColumnResolver lhsResolver = lhsCtx.getResolver();
PTableWrapper lhsProjTable = ((JoinedTableColumnResolver) (lhsResolver)).getPTableWrapper();
ProjectedPTableWrapper rhsProjTable = join.createProjectedTable(lastJoinTable.getTable(), !asSubquery);
ColumnResolver rhsResolver = join.getOriginalResolver();
ImmutableBytesPtr[] joinIds = new ImmutableBytesPtr[] {new ImmutableBytesPtr(emptyByteArray)};
Pair<List<Expression>, List<Expression>> joinConditions = lastJoinTable.compileJoinConditions(context, lhsResolver, rhsResolver);
List<Expression> joinExpressions = joinConditions.getSecond();
List<Expression> hashExpressions = joinConditions.getFirst();
int fieldPosition = rhsProjTable.getTable().getColumns().size() - rhsProjTable.getTable().getPKColumns().size();
PTableWrapper projectedTable = JoinCompiler.mergeProjectedTables(rhsProjTable, lhsProjTable, type == JoinType.Inner);
ScanProjector.serializeProjectorIntoScan(context.getScan(), JoinCompiler.getScanProjector(rhsProjTable));
context.setCurrentTable(lastJoinTable.getTable());
context.setResolver(join.getColumnResolver(projectedTable));
join.projectColumns(context.getScan(), lastJoinTable.getTable());
BasicQueryPlan rhsPlan = compileSingleQuery(context, rhs, binds, parallelIteratorFactory);
Expression postJoinFilterExpression = join.compilePostFilterExpression(context);
HashJoinInfo joinInfo = new HashJoinInfo(projectedTable.getTable(), joinIds, new List[] {joinExpressions}, new JoinType[] {type == JoinType.Inner ? type : JoinType.Left}, new boolean[] {true}, new PTable[] {lhsProjTable.getTable()}, new int[] {fieldPosition}, postJoinFilterExpression);
return new HashJoinPlan(rhsPlan, joinInfo, new List[] {hashExpressions}, new QueryPlan[] {lhsPlan});
}