if (joinTable.getJoinSpecs().isEmpty()) { Table table = joinTable.getTable(); SelectStatement subquery = table.getAsSubquery(orderBy); if (!table.isSubselect()) { List<JoinCompiler.Strategy> strategies = joinTable.getApplicableJoinStrategies(); assert strategies.size() > 0; if (!costBased || strategies.size() == 1) {
JoinTableConstructor constructor = compiler.new JoinTableConstructor(); Pair<Table, List<JoinSpec>> res = select.getFrom().accept(constructor); JoinTable joinTable = res.getSecond() == null ? compiler.new JoinTable(res.getFirst()) : compiler.new JoinTable(res.getFirst(), res.getSecond()); if (select.getWhere() != null) { joinTable.addFilter(select.getWhere()); ColumnRefParseNodeVisitor prefilterRefVisitor = new ColumnRefParseNodeVisitor(resolver, statement.getConnection()); joinTable.pushDownColumnRefVisitors(generalRefVisitor, joinLocalRefVisitor, prefilterRefVisitor);
strategies.add(Strategy.SORT_MERGE); } else { if (getStarJoinVector() != null) { strategies.add(Strategy.HASH_BUILD_RIGHT); JoinType type = lastJoinSpec.getType(); if ((type == JoinType.Right || type == JoinType.Inner) && lastJoinSpec.getJoinTable().getJoinSpecs().isEmpty() && lastJoinSpec.getJoinTable().getTable().isFlat()) { strategies.add(Strategy.HASH_BUILD_LEFT);
protected QueryPlan compileJoinQuery(JoinCompiler.Strategy strategy, StatementContext context, List<Object> binds, JoinTable joinTable, boolean asSubquery, boolean projectPKColumns, List<OrderByNode> orderBy) throws SQLException { byte[] emptyByteArray = new byte[0]; List<JoinSpec> joinSpecs = joinTable.getJoinSpecs(); switch (strategy) { case HASH_BUILD_RIGHT: { boolean[] starJoinVector = joinTable.getStarJoinVector(); Table table = joinTable.getTable(); PTable initialProjectedTable; TableRef tableRef; tableRef = table.getTableRef(); table.projectColumns(context.getScan()); query = joinTable.getAsSingleSubquery(table.getAsSubquery(orderBy), asSubquery); tupleProjector = new TupleProjector(initialProjectedTable); } else { tableRef = plan.getTableRef(); context.getScan().setFamilyMap(plan.getContext().getScan().getFamilyMap()); query = joinTable.getAsSingleSubquery((SelectStatement) plan.getStatement(), asSubquery); tupleProjector = new TupleProjector(plan.getProjector()); subContexts[i] = new StatementContext(statement, context.getResolver(), subScan, new SequenceManager(statement)); subPlans[i] = compileJoinQuery(subContexts[i], binds, joinSpec.getJoinTable(), true, true, null); boolean hasPostReference = joinSpec.getJoinTable().hasPostReference(); if (hasPostReference) { tables[i] = subContexts[i].getResolver().getTables().get(0).getTable(); List<Expression> hashExpressions = joinConditions.getSecond(); Pair<Expression, Expression> keyRangeExpressions = new Pair<Expression, Expression>(null, null); boolean optimized = getKeyExpressionCombinations(keyRangeExpressions, context, joinTable.getStatement(), tableRef, joinSpec.getType(), joinExpressions[i], hashExpressions);
protected QueryPlan compileJoinQuery(JoinCompiler.Strategy strategy, StatementContext context, List<Object> binds, JoinTable joinTable, boolean asSubquery, boolean projectPKColumns, List<OrderByNode> orderBy) throws SQLException { byte[] emptyByteArray = new byte[0]; List<JoinSpec> joinSpecs = joinTable.getJoinSpecs(); switch (strategy) { case HASH_BUILD_RIGHT: { boolean[] starJoinVector = joinTable.getStarJoinVector(); Table table = joinTable.getTable(); PTable initialProjectedTable; TableRef tableRef; tableRef = table.getTableRef(); table.projectColumns(context.getScan()); query = joinTable.getAsSingleSubquery(table.getAsSubquery(orderBy), asSubquery); tupleProjector = new TupleProjector(initialProjectedTable); } else { tableRef = plan.getTableRef(); context.getScan().setFamilyMap(plan.getContext().getScan().getFamilyMap()); query = joinTable.getAsSingleSubquery((SelectStatement) plan.getStatement(), asSubquery); tupleProjector = new TupleProjector(plan.getProjector()); subContexts[i] = new StatementContext(statement, context.getResolver(), subScan, new SequenceManager(statement)); subPlans[i] = compileJoinQuery(subContexts[i], binds, joinSpec.getJoinTable(), true, true, null); boolean hasPostReference = joinSpec.getJoinTable().hasPostReference(); if (hasPostReference) { tables[i] = subContexts[i].getResolver().getTables().get(0).getTable(); List<Expression> hashExpressions = joinConditions.getSecond(); Pair<Expression, Expression> keyRangeExpressions = new Pair<Expression, Expression>(null, null); boolean optimized = getKeyExpressionCombinations(keyRangeExpressions, context, joinTable.getStatement(), tableRef, joinSpec.getType(), joinExpressions[i], hashExpressions);
if (joinTable.getJoinSpecs().isEmpty()) { Table table = joinTable.getTable(); SelectStatement subquery = table.getAsSubquery(orderBy); if (!table.isSubselect()) { List<JoinCompiler.Strategy> strategies = joinTable.getApplicableJoinStrategies(); assert strategies.size() > 0; if (!costBased || strategies.size() == 1) {
if (joinTable.getJoinSpecs().isEmpty()) { Table table = joinTable.getTable(); SelectStatement subquery = table.getAsSubquery(orderBy); if (!table.isSubselect()) { List<JoinCompiler.Strategy> strategies = joinTable.getApplicableJoinStrategies(); assert strategies.size() > 0; if (!costBased || strategies.size() == 1) {
JoinTableConstructor constructor = compiler.new JoinTableConstructor(); Pair<Table, List<JoinSpec>> res = select.getFrom().accept(constructor); JoinTable joinTable = res.getSecond() == null ? compiler.new JoinTable(res.getFirst()) : compiler.new JoinTable(res.getFirst(), res.getSecond()); if (select.getWhere() != null) { joinTable.addFilter(select.getWhere()); ColumnRefParseNodeVisitor prefilterRefVisitor = new ColumnRefParseNodeVisitor(resolver, statement.getConnection()); joinTable.pushDownColumnRefVisitors(generalRefVisitor, joinLocalRefVisitor, prefilterRefVisitor);
JoinTableConstructor constructor = compiler.new JoinTableConstructor(); Pair<Table, List<JoinSpec>> res = select.getFrom().accept(constructor); JoinTable joinTable = res.getSecond() == null ? compiler.new JoinTable(res.getFirst()) : compiler.new JoinTable(res.getFirst(), res.getSecond()); if (select.getWhere() != null) { joinTable.addFilter(select.getWhere()); ColumnRefParseNodeVisitor prefilterRefVisitor = new ColumnRefParseNodeVisitor(resolver, statement.getConnection()); joinTable.pushDownColumnRefVisitors(generalRefVisitor, joinLocalRefVisitor, prefilterRefVisitor);
JoinTable matched = null; for (JoinSpec joinSpec : prefilterAcceptedTables) { if (columnRefVisitor.getContentType(joinSpec.getJoinTable().getTableRefs()) == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY) { matched = joinSpec.getJoinTable(); break; matched.addFilter(node); } else { postFilters.add(node);
strategies.add(Strategy.SORT_MERGE); } else { if (getStarJoinVector() != null) { strategies.add(Strategy.HASH_BUILD_RIGHT); JoinType type = lastJoinSpec.getType(); if ((type == JoinType.Right || type == JoinType.Inner) && lastJoinSpec.getJoinTable().getJoinSpecs().isEmpty() && lastJoinSpec.getJoinTable().getTable().isFlat()) { strategies.add(Strategy.HASH_BUILD_LEFT);
JoinTable matched = null; for (JoinSpec joinSpec : prefilterAcceptedTables) { if (columnRefVisitor.getContentType(joinSpec.getJoinTable().getTableRefs()) == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY) { matched = joinSpec.getJoinTable(); break; matched.addFilter(node); } else { postFilters.add(node);
strategies.add(Strategy.SORT_MERGE); } else { if (getStarJoinVector() != null) { strategies.add(Strategy.HASH_BUILD_RIGHT); JoinType type = lastJoinSpec.getType(); if ((type == JoinType.Right || type == JoinType.Inner) && lastJoinSpec.getJoinTable().getJoinSpecs().isEmpty() && lastJoinSpec.getJoinTable().getTable().isFlat()) { strategies.add(Strategy.HASH_BUILD_LEFT);
@Override public Void visitLeave(ComparisonParseNode node, List<Void> l) throws SQLException { if (!(node instanceof EqualParseNode)) return leaveBooleanNode(node, l); columnRefVisitor.reset(); node.getLHS().accept(columnRefVisitor); ColumnRefParseNodeVisitor.ColumnRefType lhsType = columnRefVisitor.getContentType(joinTable.getTableRefs()); Set<TableRef> lhsTableRefSet = Sets.newHashSet(columnRefVisitor.getTableRefSet()); columnRefVisitor.reset(); node.getRHS().accept(columnRefVisitor); ColumnRefParseNodeVisitor.ColumnRefType rhsType = columnRefVisitor.getContentType(joinTable.getTableRefs()); Set<TableRef> rhsTableRefSet = Sets.newHashSet(columnRefVisitor.getTableRefSet()); if ((lhsType == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY || lhsType == ColumnRefParseNodeVisitor.ColumnRefType.NONE) && (rhsType == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY || rhsType == ColumnRefParseNodeVisitor.ColumnRefType.NONE)) { joinTable.addFilter(node); } else if (lhsType == ColumnRefParseNodeVisitor.ColumnRefType.FOREIGN_ONLY && rhsType == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY) { onConditions.add((EqualParseNode) node); dependencies.addAll(lhsTableRefSet); } else if (rhsType == ColumnRefParseNodeVisitor.ColumnRefType.FOREIGN_ONLY && lhsType == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY) { onConditions.add(NODE_FACTORY.equal(node.getRHS(), node.getLHS())); dependencies.addAll(rhsTableRefSet); } else { throwAmbiguousJoinConditionException(); } return null; }
@Override public Void visitLeave(ComparisonParseNode node, List<Void> l) throws SQLException { if (!(node instanceof EqualParseNode)) return leaveBooleanNode(node, l); columnRefVisitor.reset(); node.getLHS().accept(columnRefVisitor); ColumnRefParseNodeVisitor.ColumnRefType lhsType = columnRefVisitor.getContentType(joinTable.getTableRefs()); Set<TableRef> lhsTableRefSet = Sets.newHashSet(columnRefVisitor.getTableRefSet()); columnRefVisitor.reset(); node.getRHS().accept(columnRefVisitor); ColumnRefParseNodeVisitor.ColumnRefType rhsType = columnRefVisitor.getContentType(joinTable.getTableRefs()); Set<TableRef> rhsTableRefSet = Sets.newHashSet(columnRefVisitor.getTableRefSet()); if ((lhsType == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY || lhsType == ColumnRefParseNodeVisitor.ColumnRefType.NONE) && (rhsType == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY || rhsType == ColumnRefParseNodeVisitor.ColumnRefType.NONE)) { joinTable.addFilter(node); } else if (lhsType == ColumnRefParseNodeVisitor.ColumnRefType.FOREIGN_ONLY && rhsType == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY) { onConditions.add((EqualParseNode) node); dependencies.addAll(lhsTableRefSet); } else if (rhsType == ColumnRefParseNodeVisitor.ColumnRefType.FOREIGN_ONLY && lhsType == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY) { onConditions.add(NODE_FACTORY.equal(node.getRHS(), node.getLHS())); dependencies.addAll(rhsTableRefSet); } else { throwAmbiguousJoinConditionException(); } return null; }
public void pushDownColumnRefVisitors(ColumnRefParseNodeVisitor generalRefVisitor, ColumnRefParseNodeVisitor joinLocalRefVisitor, ColumnRefParseNodeVisitor prefilterRefVisitor) throws SQLException { for (ParseNode node : table.getPreFilters()) { node.accept(prefilterRefVisitor); } for (ParseNode node : table.getPostFilters()) { node.accept(generalRefVisitor); } for (ParseNode node : postFilters) { node.accept(generalRefVisitor); } for (JoinSpec joinSpec : joinSpecs) { JoinTable joinTable = joinSpec.getJoinTable(); boolean hasSubJoin = !joinTable.getJoinSpecs().isEmpty(); for (EqualParseNode node : joinSpec.getOnConditions()) { node.getLHS().accept(generalRefVisitor); if (hasSubJoin) { node.getRHS().accept(generalRefVisitor); } else { node.getRHS().accept(joinLocalRefVisitor); } } joinTable.pushDownColumnRefVisitors(generalRefVisitor, joinLocalRefVisitor, prefilterRefVisitor); } }
public void pushDownColumnRefVisitors(ColumnRefParseNodeVisitor generalRefVisitor, ColumnRefParseNodeVisitor joinLocalRefVisitor, ColumnRefParseNodeVisitor prefilterRefVisitor) throws SQLException { for (ParseNode node : table.getPreFilters()) { node.accept(prefilterRefVisitor); } for (ParseNode node : table.getPostFilters()) { node.accept(generalRefVisitor); } for (ParseNode node : postFilters) { node.accept(generalRefVisitor); } for (JoinSpec joinSpec : joinSpecs) { JoinTable joinTable = joinSpec.getJoinTable(); boolean hasSubJoin = !joinTable.getJoinSpecs().isEmpty(); for (EqualParseNode node : joinSpec.getOnConditions()) { node.getLHS().accept(generalRefVisitor); if (hasSubJoin) { node.getRHS().accept(generalRefVisitor); } else { node.getRHS().accept(joinLocalRefVisitor); } } joinTable.pushDownColumnRefVisitors(generalRefVisitor, joinLocalRefVisitor, prefilterRefVisitor); } }
@Override protected Void leaveBooleanNode(ParseNode node, List<Void> l) throws SQLException { columnRefVisitor.reset(); node.accept(columnRefVisitor); ColumnRefParseNodeVisitor.ColumnRefType type = columnRefVisitor.getContentType(joinTable.getTableRefs()); if (type == ColumnRefParseNodeVisitor.ColumnRefType.NONE || type == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY) { joinTable.addFilter(node); } else { throwAmbiguousJoinConditionException(); } return null; }
@Override protected Void leaveBooleanNode(ParseNode node, List<Void> l) throws SQLException { columnRefVisitor.reset(); node.accept(columnRefVisitor); ColumnRefParseNodeVisitor.ColumnRefType type = columnRefVisitor.getContentType(joinTable.getTableRefs()); if (type == ColumnRefParseNodeVisitor.ColumnRefType.NONE || type == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY) { joinTable.addFilter(node); } else { throwAmbiguousJoinConditionException(); } return null; }