use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.core.Join in project beam by apache.
the class BeamSideInputJoinRule method onMatch.
@Override
public void onMatch(RelOptRuleCall call) {
Join join = (Join) call.rel(0);
BeamSideInputJoinRel rel = new BeamSideInputJoinRel(join.getCluster(), join.getTraitSet().replace(BeamLogicalConvention.INSTANCE), convert(join.getLeft(), join.getLeft().getTraitSet().replace(BeamLogicalConvention.INSTANCE)), convert(join.getRight(), join.getRight().getTraitSet().replace(BeamLogicalConvention.INSTANCE)), join.getCondition(), join.getVariablesSet(), join.getJoinType());
call.transformTo(rel);
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.core.Join in project druid by druid-io.
the class DruidJoinRule method onMatch.
@Override
public void onMatch(RelOptRuleCall call) {
final Join join = call.rel(0);
final DruidRel<?> left = call.rel(1);
final DruidRel<?> right = call.rel(2);
final RexBuilder rexBuilder = join.getCluster().getRexBuilder();
final DruidRel<?> newLeft;
final DruidRel<?> newRight;
final Filter leftFilter;
final List<RexNode> newProjectExprs = new ArrayList<>();
// Already verified to be present in "matches", so just call "get".
// Can't be final, because we're going to reassign it up to a couple of times.
ConditionAnalysis conditionAnalysis = analyzeCondition(join.getCondition(), join.getLeft().getRowType(), right).get();
final boolean isLeftDirectAccessPossible = enableLeftScanDirect && (left instanceof DruidQueryRel);
if (left.getPartialDruidQuery().stage() == PartialDruidQuery.Stage.SELECT_PROJECT && (isLeftDirectAccessPossible || left.getPartialDruidQuery().getWhereFilter() == null)) {
// Swap the left-side projection above the join, so the left side is a simple scan or mapping. This helps us
// avoid subqueries.
final RelNode leftScan = left.getPartialDruidQuery().getScan();
final Project leftProject = left.getPartialDruidQuery().getSelectProject();
leftFilter = left.getPartialDruidQuery().getWhereFilter();
// Left-side projection expressions rewritten to be on top of the join.
newProjectExprs.addAll(leftProject.getProjects());
newLeft = left.withPartialQuery(PartialDruidQuery.create(leftScan));
conditionAnalysis = conditionAnalysis.pushThroughLeftProject(leftProject);
} else {
// Leave left as-is. Write input refs that do nothing.
for (int i = 0; i < left.getRowType().getFieldCount(); i++) {
newProjectExprs.add(rexBuilder.makeInputRef(join.getRowType().getFieldList().get(i).getType(), i));
}
newLeft = left;
leftFilter = null;
}
if (right.getPartialDruidQuery().stage() == PartialDruidQuery.Stage.SELECT_PROJECT && right.getPartialDruidQuery().getWhereFilter() == null && !right.getPartialDruidQuery().getSelectProject().isMapping() && conditionAnalysis.onlyUsesMappingsFromRightProject(right.getPartialDruidQuery().getSelectProject())) {
// Swap the right-side projection above the join, so the right side is a simple scan or mapping. This helps us
// avoid subqueries.
final RelNode rightScan = right.getPartialDruidQuery().getScan();
final Project rightProject = right.getPartialDruidQuery().getSelectProject();
// Right-side projection expressions rewritten to be on top of the join.
for (final RexNode rexNode : RexUtil.shift(rightProject.getProjects(), newLeft.getRowType().getFieldCount())) {
if (join.getJoinType().generatesNullsOnRight()) {
newProjectExprs.add(makeNullableIfLiteral(rexNode, rexBuilder));
} else {
newProjectExprs.add(rexNode);
}
}
newRight = right.withPartialQuery(PartialDruidQuery.create(rightScan));
conditionAnalysis = conditionAnalysis.pushThroughRightProject(rightProject);
} else {
// Leave right as-is. Write input refs that do nothing.
for (int i = 0; i < right.getRowType().getFieldCount(); i++) {
newProjectExprs.add(rexBuilder.makeInputRef(join.getRowType().getFieldList().get(left.getRowType().getFieldCount() + i).getType(), newLeft.getRowType().getFieldCount() + i));
}
newRight = right;
}
// Druid join written on top of the new left and right sides.
final DruidJoinQueryRel druidJoin = DruidJoinQueryRel.create(join.copy(join.getTraitSet(), conditionAnalysis.getCondition(rexBuilder), newLeft, newRight, join.getJoinType(), join.isSemiJoinDone()), leftFilter, left.getPlannerContext());
final RelBuilder relBuilder = call.builder().push(druidJoin).project(RexUtil.fixUp(rexBuilder, newProjectExprs, RelOptUtil.getFieldTypeList(druidJoin.getRowType())));
call.transformTo(relBuilder.build());
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.core.Join in project hive by apache.
the class ASTConverter method convertSource.
private QueryBlockInfo convertSource(RelNode r) throws CalciteSemanticException {
Schema s = null;
ASTNode ast = null;
if (r instanceof TableScan) {
TableScan f = (TableScan) r;
s = new Schema(f);
ast = ASTBuilder.table(f);
planMapper.link(ast, f);
} else if (r instanceof HiveJdbcConverter) {
HiveJdbcConverter f = (HiveJdbcConverter) r;
s = new Schema(f);
ast = ASTBuilder.table(f);
} else if (r instanceof DruidQuery) {
DruidQuery f = (DruidQuery) r;
s = new Schema(f);
ast = ASTBuilder.table(f);
} else if (r instanceof Join) {
Join join = (Join) r;
QueryBlockInfo left = convertSource(join.getLeft());
QueryBlockInfo right = convertSource(join.getRight());
s = new Schema(left.schema, right.schema);
ASTNode cond = join.getCondition().accept(new RexVisitor(s, false, r.getCluster().getRexBuilder()));
boolean semiJoin = join.isSemiJoin() || join.getJoinType() == JoinRelType.ANTI;
if (join.getRight() instanceof Join && !semiJoin) {
// should not be done for semijoin since it will change the semantics
// Invert join inputs; this is done because otherwise the SemanticAnalyzer
// methods to merge joins will not kick in
JoinRelType type;
if (join.getJoinType() == JoinRelType.LEFT) {
type = JoinRelType.RIGHT;
} else if (join.getJoinType() == JoinRelType.RIGHT) {
type = JoinRelType.LEFT;
} else {
type = join.getJoinType();
}
ast = ASTBuilder.join(right.ast, left.ast, type, cond);
addPkFkInfoToAST(ast, join, true);
} else {
ast = ASTBuilder.join(left.ast, right.ast, join.getJoinType(), cond);
addPkFkInfoToAST(ast, join, false);
}
if (semiJoin) {
s = left.schema;
}
} else if (r instanceof Union) {
Union u = ((Union) r);
ASTNode left = new ASTConverter(((Union) r).getInput(0), this.derivedTableCount, planMapper).convert();
for (int ind = 1; ind < u.getInputs().size(); ind++) {
left = getUnionAllAST(left, new ASTConverter(((Union) r).getInput(ind), this.derivedTableCount, planMapper).convert());
String sqAlias = nextAlias();
ast = ASTBuilder.subQuery(left, sqAlias);
s = new Schema((Union) r, sqAlias);
}
} else {
ASTConverter src = new ASTConverter(r, this.derivedTableCount, planMapper);
ASTNode srcAST = src.convert();
String sqAlias = nextAlias();
s = src.getRowSchema(sqAlias);
ast = ASTBuilder.subQuery(srcAST, sqAlias);
}
return new QueryBlockInfo(s, ast);
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.core.Join in project hive by apache.
the class MaterializedViewRewritingRelVisitor method check.
private void check(Union union) {
// We found the Union
if (union.getInputs().size() != 2) {
// Bail out
throw new ReturnedValue(false);
}
// First branch should have the query (with write ID filter conditions)
new RelVisitor() {
@Override
public void visit(RelNode node, int ordinal, RelNode parent) {
if (node instanceof TableScan || node instanceof Filter || node instanceof Project || node instanceof Join) {
// We can continue
super.visit(node, ordinal, parent);
} else if (node instanceof Aggregate && containsAggregate) {
Aggregate aggregate = (Aggregate) node;
for (int i = 0; i < aggregate.getAggCallList().size(); ++i) {
AggregateCall aggregateCall = aggregate.getAggCallList().get(i);
if (aggregateCall.getAggregation().getKind() == SqlKind.COUNT && aggregateCall.getArgList().size() == 0) {
countIndex = i + aggregate.getGroupCount();
break;
}
}
// We can continue
super.visit(node, ordinal, parent);
} else {
throw new ReturnedValue(false);
}
}
}.go(union.getInput(0));
// Second branch should only have the MV
new RelVisitor() {
@Override
public void visit(RelNode node, int ordinal, RelNode parent) {
if (node instanceof TableScan) {
// We can continue
// TODO: Need to check that this is the same MV that we are rebuilding
RelOptHiveTable hiveTable = (RelOptHiveTable) node.getTable();
if (!hiveTable.getHiveTableMD().isMaterializedView()) {
// If it is not a materialized view, we do not rewrite it
throw new ReturnedValue(false);
}
if (containsAggregate && !AcidUtils.isFullAcidTable(hiveTable.getHiveTableMD())) {
// we do not rewrite it (we need MERGE support)
throw new ReturnedValue(false);
}
} else if (node instanceof Project) {
// We can continue
super.visit(node, ordinal, parent);
} else {
throw new ReturnedValue(false);
}
}
}.go(union.getInput(1));
// We pass all the checks, we can rewrite
throw new ReturnedValue(true);
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.core.Join in project hive by apache.
the class HiveRelDecorrelator method decorrelateRel.
public Frame decorrelateRel(Filter rel) {
//
// Rewrite logic:
//
// 1. If a Filter references a correlated field in its filter
// condition, rewrite the Filter to be
// Filter
// Join(cross product)
// OriginalFilterInput
// ValueGenerator(produces distinct sets of correlated variables)
// and rewrite the correlated fieldAccess in the filter condition to
// reference the Join output.
//
// 2. If Filter does not reference correlated variables, simply
// rewrite the filter condition using new input.
//
final RelNode oldInput = rel.getInput();
Frame frame = getInvoke(oldInput, rel);
if (frame == null) {
// If input has not been rewritten, do not rewrite this rel.
return null;
}
Frame oldInputFrame = frame;
// and produce the correlated variables in the new output.
if (cm.mapRefRelToCorRef.containsKey(rel)) {
frame = decorrelateInputWithValueGenerator(rel);
}
boolean valueGenerator = true;
if (frame.r == oldInputFrame.r) {
// this means correated value generator wasn't generated
valueGenerator = false;
}
boolean isSemiJoin = false;
if (oldInput instanceof LogicalCorrelate) {
isSemiJoin = ((LogicalCorrelate) oldInput).getJoinType() == JoinRelType.SEMI || ((LogicalCorrelate) oldInput).getJoinType() == JoinRelType.ANTI;
}
if (isSemiJoin && !cm.mapRefRelToCorRef.containsKey(rel)) {
// this conditions need to be pushed into semi-join since this condition
// corresponds to IN
Join join = ((Join) frame.r);
final List<RexNode> conditions = new ArrayList<>();
RexNode joinCond = join.getCondition();
conditions.add(joinCond);
conditions.add(decorrelateExpr(rel.getCondition(), valueGenerator));
final RexNode condition = RexUtil.composeConjunction(rexBuilder, conditions, false);
RelNode newRel;
if (((LogicalCorrelate) oldInput).getJoinType() == JoinRelType.SEMI) {
newRel = HiveSemiJoin.getSemiJoin(frame.r.getCluster(), frame.r.getTraitSet(), join.getLeft(), join.getRight(), condition);
} else {
newRel = HiveAntiJoin.getAntiJoin(frame.r.getCluster(), frame.r.getTraitSet(), join.getLeft(), join.getRight(), condition);
}
return register(rel, newRel, frame.oldToNewOutputs, frame.corDefOutputs);
}
// Replace the filter expression to reference output of the join
// Map filter to the new filter over join
relBuilder.push(frame.r).filter((decorrelateExpr(rel.getCondition(), valueGenerator)));
// input rel.
return register(rel, relBuilder.build(), frame.oldToNewOutputs, frame.corDefOutputs);
}
Aggregations