org.apache.calcite.plan.RelOptUtil Java Examples

The following examples show how to use org.apache.calcite.plan.RelOptUtil. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: FlinkJoinToMultiJoinRule.java    From flink with Apache License 2.0 6 votes vote down vote up
/**
 * Shifts a filter originating from the right child of the LogicalJoin to the
 * right, to reflect the filter now being applied on the resulting
 * MultiJoin.
 *
 * @param joinRel     the original LogicalJoin
 * @param left        the left child of the LogicalJoin
 * @param right       the right child of the LogicalJoin
 * @param rightFilter the filter originating from the right child
 * @return the adjusted right filter
 */
private RexNode shiftRightFilter(
		Join joinRel,
		RelNode left,
		MultiJoin right,
		RexNode rightFilter) {
	if (rightFilter == null) {
		return null;
	}

	int nFieldsOnLeft = left.getRowType().getFieldList().size();
	int nFieldsOnRight = right.getRowType().getFieldList().size();
	int[] adjustments = new int[nFieldsOnRight];
	for (int i = 0; i < nFieldsOnRight; i++) {
		adjustments[i] = nFieldsOnLeft;
	}
	rightFilter =
			rightFilter.accept(
					new RelOptUtil.RexInputConverter(
							joinRel.getCluster().getRexBuilder(),
							right.getRowType().getFieldList(),
							joinRel.getRowType().getFieldList(),
							adjustments));
	return rightFilter;
}
 
Example #2
Source File: RexSimplify.java    From Bats with Apache License 2.0 6 votes vote down vote up
RexNode simplifyAnd(RexCall e, RexUnknownAs unknownAs) {
    List<RexNode> operands = RelOptUtil.conjunctions(e);

    if (unknownAs == FALSE && predicateElimination) {
        simplifyAndTerms(operands, FALSE);
    } else {
        simplifyList(operands, unknownAs);
    }

    final List<RexNode> terms = new ArrayList<>();
    final List<RexNode> notTerms = new ArrayList<>();

    for (RexNode o : operands) {
        RelOptUtil.decomposeConjunction(o, terms, notTerms);
    }

    switch (unknownAs) {
    case FALSE:
        return simplifyAnd2ForUnknownAsFalse(terms, notTerms, Comparable.class);
    }
    return simplifyAnd2(terms, notTerms);
}
 
Example #3
Source File: LoptOptimizeJoinRule.java    From Bats with Apache License 2.0 6 votes vote down vote up
/**
 * Determines whether any additional filters are applicable to a join tree.
 * If there are any, creates a filter node on top of the join tree with the
 * additional filters.
 *
 * @param relBuilder Builder holding current join tree
 * @param multiJoin join factors being optimized
 * @param left left side of join tree
 * @param right right side of join tree
 * @param filtersToAdd remaining filters
 */
private void addAdditionalFilters(
    RelBuilder relBuilder,
    LoptMultiJoin multiJoin,
    LoptJoinTree left,
    LoptJoinTree right,
    List<RexNode> filtersToAdd) {
  RexNode filterCond =
      addFilters(multiJoin, left, -1, right, filtersToAdd, false);
  if (!filterCond.isAlwaysTrue()) {
    // adjust the filter to reflect the outer join output
    int [] adjustments = new int[multiJoin.getNumTotalFields()];
    if (needsAdjustment(multiJoin, adjustments, left, right, false)) {
      RexBuilder rexBuilder =
          multiJoin.getMultiJoinRel().getCluster().getRexBuilder();
      filterCond =
          filterCond.accept(
              new RelOptUtil.RexInputConverter(
                  rexBuilder,
                  multiJoin.getMultiJoinFields(),
                  relBuilder.peek().getRowType().getFieldList(),
                  adjustments));
      relBuilder.filter(filterCond);
    }
  }
}
 
Example #4
Source File: Lattice.java    From calcite with Apache License 2.0 6 votes vote down vote up
private static boolean populate(List<RelNode> nodes, List<int[][]> tempLinks,
    RelNode rel) {
  if (nodes.isEmpty() && rel instanceof LogicalProject) {
    return populate(nodes, tempLinks, ((LogicalProject) rel).getInput());
  }
  if (rel instanceof TableScan) {
    nodes.add(rel);
    return true;
  }
  if (rel instanceof LogicalJoin) {
    LogicalJoin join = (LogicalJoin) rel;
    if (join.getJoinType().isOuterJoin()) {
      throw new RuntimeException("only non nulls-generating join allowed, but got "
          + join.getJoinType());
    }
    populate(nodes, tempLinks, join.getLeft());
    populate(nodes, tempLinks, join.getRight());
    for (RexNode rex : RelOptUtil.conjunctions(join.getCondition())) {
      tempLinks.add(grab(nodes, rex));
    }
    return true;
  }
  throw new RuntimeException("Invalid node type "
      + rel.getClass().getSimpleName() + " in lattice query");
}
 
Example #5
Source File: MaterializedViewFilterScanRule.java    From Bats with Apache License 2.0 6 votes vote down vote up
protected void apply(RelOptRuleCall call, Filter filter, TableScan scan) {
  final RelOptPlanner planner = call.getPlanner();
  final List<RelOptMaterialization> materializations =
      planner.getMaterializations();
  if (!materializations.isEmpty()) {
    RelNode root = filter.copy(filter.getTraitSet(),
        Collections.singletonList((RelNode) scan));
    List<RelOptMaterialization> applicableMaterializations =
        RelOptMaterializations.getApplicableMaterializations(root, materializations);
    for (RelOptMaterialization materialization : applicableMaterializations) {
      if (RelOptUtil.areRowTypesEqual(scan.getRowType(),
          materialization.queryRel.getRowType(), false)) {
        RelNode target = materialization.queryRel;
        final HepPlanner hepPlanner =
            new HepPlanner(program, planner.getContext());
        hepPlanner.setRoot(target);
        target = hepPlanner.findBestExp();
        List<RelNode> subs = new MaterializedViewSubstitutionVisitor(target, root)
            .go(materialization.tableRel);
        for (RelNode s : subs) {
          call.transformTo(s);
        }
      }
    }
  }
}
 
Example #6
Source File: MultiJoinProjectTransposeRule.java    From Bats with Apache License 2.0 6 votes vote down vote up
protected RelNode getProjectChild(
    RelOptRuleCall call,
    LogicalProject project,
    boolean leftChild) {
  // locate the appropriate MultiJoin based on which rule was fired
  // and which projection we're dealing with
  MultiJoin multiJoin;
  if (leftChild) {
    multiJoin = call.rel(2);
  } else if (call.rels.length == 4) {
    multiJoin = call.rel(3);
  } else {
    multiJoin = call.rel(4);
  }

  // create a new MultiJoin that reflects the columns in the projection
  // above the MultiJoin
  return RelOptUtil.projectMultiJoin(multiJoin, project);
}
 
Example #7
Source File: Prepare.java    From calcite with Apache License 2.0 6 votes vote down vote up
public final RelOptTable extend(List<RelDataTypeField> extendedFields) {
  final Table table = unwrap(Table.class);

  // Get the set of extended columns that do not have the same name as a column
  // in the base table.
  final List<RelDataTypeField> baseColumns = getRowType().getFieldList();
  final List<RelDataTypeField> dedupedFields =
      RelOptUtil.deduplicateColumns(baseColumns, extendedFields);
  final List<RelDataTypeField> dedupedExtendedFields =
      dedupedFields.subList(baseColumns.size(), dedupedFields.size());

  if (table instanceof ExtensibleTable) {
    final Table extendedTable =
            ((ExtensibleTable) table).extend(dedupedExtendedFields);
    return extend(extendedTable);
  } else if (table instanceof ModifiableViewTable) {
    final ModifiableViewTable modifiableViewTable =
            (ModifiableViewTable) table;
    final ModifiableViewTable extendedView =
        modifiableViewTable.extend(dedupedExtendedFields,
            getRelOptSchema().getTypeFactory());
    return extend(extendedView);
  }
  throw new RuntimeException("Cannot extend " + table);
}
 
Example #8
Source File: ElasticsearchJoin.java    From dk-fitting with Apache License 2.0 6 votes vote down vote up
public void implement(Implementor implementor) {
    implementor.visitChild(0, getLeft());
    implementor.visitChild(0, getRight());
    if (!getCondition().isA(SqlKind.EQUALS)) {
        throw new IllegalArgumentException("Only equi-join are supported");
    }
    List<RexNode> operands = ((RexCall) getCondition()).getOperands();
    if (operands.size() != 2) {
        throw new IllegalArgumentException("Only equi-join are supported");
    }
    List<Integer> leftKeys = new ArrayList<Integer>(1);
    List<Integer> rightKeys = new ArrayList<Integer>(1);
    List<Boolean> filterNulls = new ArrayList<Boolean>(1);
    RexNode rexNode = RelOptUtil.splitJoinCondition(getLeft(), getRight(), getCondition(), leftKeys, rightKeys,
            filterNulls);
    String leftRelAlias = implementor.getElasticsearchRelationAlias((ElasticsearchRelNode) getLeft());
    String rightRelAlias = implementor.getElasticsearchRelationAlias((ElasticsearchRelNode) getRight());
    String leftJoinFieldName = implementor.getFieldName((ElasticsearchRelNode) getLeft(), leftKeys.get(0));
    String rightJoinFieldName = implementor.getFieldName((ElasticsearchRelNode) getRight(), rightKeys.get(0));
    String result = implementor.getElasticsearchRelationAlias((ElasticsearchRelNode) getLeft())
            + " = JOIN " + leftRelAlias + " BY "+ leftJoinFieldName + ' ' + getElasticsearchJoinType() + ", " +
            rightRelAlias + " BY "+ rightJoinFieldName + ';';
    System.out.println("implementor = " + result);
}
 
Example #9
Source File: JoinCommuteRule.java    From Bats with Apache License 2.0 6 votes vote down vote up
/**
 * Returns a relational expression with the inputs switched round. Does not
 * modify <code>join</code>. Returns null if the join cannot be swapped (for
 * example, because it is an outer join).
 *
 * @param join              join to be swapped
 * @param swapOuterJoins    whether outer joins should be swapped
 * @param relBuilder        Builder for relational expressions
 * @return swapped join if swapping possible; else null
 */
public static RelNode swap(Join join, boolean swapOuterJoins, RelBuilder relBuilder) {
    final JoinRelType joinType = join.getJoinType();
    if (!swapOuterJoins && joinType != JoinRelType.INNER) {
        return null;
    }
    final RexBuilder rexBuilder = join.getCluster().getRexBuilder();
    final RelDataType leftRowType = join.getLeft().getRowType();
    final RelDataType rightRowType = join.getRight().getRowType();
    final VariableReplacer variableReplacer = new VariableReplacer(rexBuilder, leftRowType, rightRowType);
    final RexNode oldCondition = join.getCondition();
    RexNode condition = variableReplacer.go(oldCondition);

    // NOTE jvs 14-Mar-2006: We preserve attribute semiJoinDone after the
    // swap. This way, we will generate one semijoin for the original
    // join, and one for the swapped join, and no more. This
    // doesn't prevent us from seeing any new combinations assuming
    // that the planner tries the desired order (semijoins after swaps).
    Join newJoin = join.copy(join.getTraitSet(), condition, join.getRight(), join.getLeft(), joinType.swap(),
            join.isSemiJoinDone());
    final List<RexNode> exps = RelOptUtil.createSwappedJoinExprs(newJoin, join, true);
    return relBuilder.push(newJoin).project(exps, join.getRowType().getFieldNames()).build();
}
 
Example #10
Source File: JoinPrel.java    From Bats with Apache License 2.0 6 votes vote down vote up
/**
 * Build the list of join conditions for this join.
 * A join condition is built only for equality and IS NOT DISTINCT FROM comparisons. The difference is:
 * null == null is FALSE whereas null IS NOT DISTINCT FROM null is TRUE
 * For a use case of the IS NOT DISTINCT FROM comparison, see
 * {@link org.apache.calcite.rel.rules.AggregateRemoveRule}
 * @param conditions populated list of join conditions
 * @param leftFields join fields from the left input
 * @param rightFields join fields from the right input
 */
protected void buildJoinConditions(List<JoinCondition> conditions,
    List<String> leftFields,
    List<String> rightFields,
    List<Integer> leftKeys,
    List<Integer> rightKeys) {
  List<RexNode> conjuncts = RelOptUtil.conjunctions(this.getCondition());
  short i=0;

  for (Pair<Integer, Integer> pair : Pair.zip(leftKeys, rightKeys)) {
    final RexNode conditionExpr = conjuncts.get(i++);
    final SqlKind kind  = conditionExpr.getKind();
    if (kind != SqlKind.EQUALS && kind != SqlKind.IS_NOT_DISTINCT_FROM) {
      throw UserException.unsupportedError()
          .message("Unsupported comparator in join condition %s", conditionExpr)
          .build(logger);
    }

    conditions.add(new JoinCondition(kind.toString(),
        FieldReference.getWithQuotedRef(leftFields.get(pair.left)),
        FieldReference.getWithQuotedRef(rightFields.get(pair.right))));
  }
}
 
Example #11
Source File: RelMdPredicates.java    From Bats with Apache License 2.0 6 votes vote down vote up
private void infer(RexNode predicates, Set<RexNode> allExprs,
    List<RexNode> inferredPredicates, boolean includeEqualityInference,
    ImmutableBitSet inferringFields) {
  for (RexNode r : RelOptUtil.conjunctions(predicates)) {
    if (!includeEqualityInference
        && equalityPredicates.contains(r)) {
      continue;
    }
    for (Mapping m : mappings(r)) {
      RexNode tr = r.accept(
          new RexPermuteInputsShuttle(m, joinRel.getInput(0),
              joinRel.getInput(1)));
      // Filter predicates can be already simplified, so we should work with
      // simplified RexNode versions as well. It also allows prevent of having
      // some duplicates in in result pulledUpPredicates
      RexNode simplifiedTarget =
          simplify.simplifyFilterPredicates(RelOptUtil.conjunctions(tr));
      if (checkTarget(inferringFields, allExprs, tr)
          && checkTarget(inferringFields, allExprs, simplifiedTarget)) {
        inferredPredicates.add(simplifiedTarget);
        allExprs.add(simplifiedTarget);
      }
    }
  }
}
 
Example #12
Source File: RelFieldTrimmer.java    From calcite with Apache License 2.0 6 votes vote down vote up
/** Creates a project with a dummy column, to protect the parts of the system
 * that cannot handle a relational expression with no columns.
 *
 * @param fieldCount Number of fields in the original relational expression
 * @param input Trimmed input
 * @param originalRelNode Source RelNode for hint propagation (or null if no propagation needed)
 * @return Dummy project
 */
protected TrimResult dummyProject(int fieldCount, RelNode input, RelNode originalRelNode) {
  final RelOptCluster cluster = input.getCluster();
  final Mapping mapping =
      Mappings.create(MappingType.INVERSE_SURJECTION, fieldCount, 1);
  if (input.getRowType().getFieldCount() == 1) {
    // Input already has one field (and may in fact be a dummy project we
    // created for the child). We can't do better.
    return result(input, mapping);
  }
  final RexLiteral expr =
      cluster.getRexBuilder().makeExactLiteral(BigDecimal.ZERO);
  relBuilder.push(input);
  relBuilder.project(ImmutableList.of(expr), ImmutableList.of("DUMMY"));
  RelNode newProject = relBuilder.build();
  if (originalRelNode != null) {
    newProject = RelOptUtil.propagateRelHints(originalRelNode, newProject);
  }
  return result(newProject, mapping);
}
 
Example #13
Source File: RexProgramTest.java    From calcite with Apache License 2.0 6 votes vote down vote up
@Test void testIsDeterministic() {
  SqlOperator ndc = new SqlSpecialOperator(
          "NDC",
          SqlKind.OTHER_FUNCTION,
          0,
          false,
          ReturnTypes.BOOLEAN,
          null, null) {
    @Override public boolean isDeterministic() {
      return false;
    }
  };
  RexNode n = rexBuilder.makeCall(ndc);
  assertFalse(RexUtil.isDeterministic(n));
  assertEquals(0,
          RexUtil.retainDeterministic(RelOptUtil.conjunctions(n)).size());
}
 
Example #14
Source File: DruidRules.java    From calcite with Apache License 2.0 6 votes vote down vote up
private static Pair<List<RexNode>, List<RexNode>> splitProjects(
    final RexBuilder rexBuilder, final RelNode input, List<RexNode> nodes) {
  final RelOptUtil.InputReferencedVisitor visitor =
      new RelOptUtil.InputReferencedVisitor();
  visitor.visitEach(nodes);
  if (visitor.inputPosReferenced.size() == input.getRowType().getFieldCount()) {
    // All inputs are referenced
    return null;
  }
  final List<RexNode> belowNodes = new ArrayList<>();
  final List<RelDataType> belowTypes = new ArrayList<>();
  final List<Integer> positions = Lists.newArrayList(visitor.inputPosReferenced);
  for (int i : positions) {
    final RexNode node = rexBuilder.makeInputRef(input, i);
    belowNodes.add(node);
    belowTypes.add(node.getType());
  }
  final List<RexNode> aboveNodes = new RexShuttle() {
    @Override public RexNode visitInputRef(RexInputRef ref) {
      final int index = positions.indexOf(ref.getIndex());
      return rexBuilder.makeInputRef(belowTypes.get(index), index);
    }
  }.visitList(nodes);
  return Pair.of(aboveNodes, belowNodes);
}
 
Example #15
Source File: BatsOptimizerTest.java    From Bats with Apache License 2.0 6 votes vote down vote up
static void testVolcanoPlanner() throws Exception {
    VolcanoPlanner volcanoPlanner = createVolcanoPlanner();
    volcanoPlanner.addRelTraitDef(ConventionTraitDef.INSTANCE);
    // volcanoPlanner.addRelTraitDef(RelCollationTraitDef.INSTANCE);
    // addRules(volcanoPlanner);
    volcanoPlanner.addRule(ReduceExpressionsRule.PROJECT_INSTANCE);
    // volcanoPlanner.addRule(EnumerableRules.ENUMERABLE_PROJECT_RULE);

    RelNode relNode = testSqlToRelConverter(volcanoPlanner);
    volcanoPlanner.setRoot(relNode);
    relNode = volcanoPlanner.findBestExp(); // 在这一步出错

    String plan = RelOptUtil.toString(relNode);
    System.out.println("Volcano Plan:");
    System.out.println("------------------------------------------------------------------");
    System.out.println(plan);
}
 
Example #16
Source File: SqlToRelConverterTest.java    From calcite with Apache License 2.0 5 votes vote down vote up
@Test void testLarge() {
  // Size factor used to be 400, but lambdas use a lot of stack
  final int x = 300;
  SqlValidatorTest.checkLarge(x, input -> {
    final RelRoot root = tester.convertSqlToRel(input);
    final String s = RelOptUtil.toString(root.project());
    assertThat(s, notNullValue());
  });
}
 
Example #17
Source File: IndexConditionInfo.java    From Bats with Apache License 2.0 5 votes vote down vote up
/**
 * Given a list of Index Expressions(usually indexed fields/functions from one or a set of indexes),
 * separate a filter condition into
 *     1), relevant subset of conditions (by relevant, it means at least one given index Expression was found) and,
 *     2), the rest in remainderCondition
 * @param relevantPaths
 * @param condition
 * @return
 */
public IndexConditionInfo indexConditionRelatedToFields(List<LogicalExpression> relevantPaths, RexNode condition) {
  // Use the same filter analyzer that is used for partitioning columns
  RewriteCombineBinaryOperators reverseVisitor =
      new RewriteCombineBinaryOperators(true, builder);

  condition = condition.accept(reverseVisitor);

  RexSeparator separator = new RexSeparator(relevantPaths, scan, builder);
  RexNode indexCondition = separator.getSeparatedCondition(condition);

  if (indexCondition == null) {
    return new IndexConditionInfo(null, null, false);
  }

  List<RexNode> conjuncts = RelOptUtil.conjunctions(condition);
  List<RexNode> indexConjuncts = RelOptUtil.conjunctions(indexCondition);
  for (RexNode indexConjunction: indexConjuncts) {
    RexUtil.removeAll(conjuncts, indexConjunction);
  }

  RexNode remainderCondition = RexUtil.composeConjunction(builder, conjuncts, false);

  indexCondition = indexCondition.accept(reverseVisitor);

  return new IndexConditionInfo(indexCondition, remainderCondition, true);
}
 
Example #18
Source File: JoinUtils.java    From dremio-oss with Apache License 2.0 5 votes vote down vote up
/**
   * Check if the given RelNode contains any Cartesian join.
   * Return true if find one. Otherwise, return false.
   *
   * @param relNode   the RelNode to be inspected.
   * @param leftKeys  a list used for the left input into the join which has
   *                  equi-join keys. It can be empty or not (but not null),
   *                  this method will clear this list before using it.
   * @param rightKeys a list used for the right input into the join which has
   *                  equi-join keys. It can be empty or not (but not null),
   *                  this method will clear this list before using it.
   * @param filterNulls   The join key positions for which null values will not
   *                      match. null values only match for the "is not distinct
   *                      from" condition.
   * @return          Return true if the given relNode contains Cartesian join.
   *                  Otherwise, return false
   */
public static boolean checkCartesianJoin(RelNode relNode, List<Integer> leftKeys, List<Integer> rightKeys, List<Boolean> filterNulls) {
  if (relNode instanceof Join) {
    leftKeys.clear();
    rightKeys.clear();

    Join joinRel = (Join) relNode;
    RelNode left = joinRel.getLeft();
    RelNode right = joinRel.getRight();

    RexNode remaining = RelOptUtil.splitJoinCondition(left, right, joinRel.getCondition(), leftKeys, rightKeys, filterNulls);
    if(joinRel.getJoinType() == JoinRelType.INNER) {
      if(leftKeys.isEmpty() || rightKeys.isEmpty()) {
        return true;
      }
    } else {
      if(!remaining.isAlwaysTrue() || leftKeys.isEmpty() || rightKeys.isEmpty()) {
        return true;
      }
    }
  }

  for (RelNode child : relNode.getInputs()) {
    if(checkCartesianJoin(child, leftKeys, rightKeys, filterNulls)) {
      return true;
    }
  }

  return false;
}
 
Example #19
Source File: SqlValidatorImpl.java    From flink with Apache License 2.0 5 votes vote down vote up
/**
 * Validates updates against the constraint of a modifiable view.
 *
 * @param validatorTable A {@link SqlValidatorTable} that may wrap a
 *                       ModifiableViewTable
 * @param update         The UPDATE parse tree node
 * @param targetRowType  The target type
 */
private void checkConstraint(
	SqlValidatorTable validatorTable,
	SqlUpdate update,
	RelDataType targetRowType) {
	final ModifiableViewTable modifiableViewTable =
		validatorTable.unwrap(ModifiableViewTable.class);
	if (modifiableViewTable != null) {
		final Table table = modifiableViewTable.unwrap(Table.class);
		final RelDataType tableRowType = table.getRowType(typeFactory);

		final Map<Integer, RexNode> projectMap =
			RelOptUtil.getColumnConstraints(modifiableViewTable, targetRowType,
				typeFactory);
		final Map<String, Integer> nameToIndex =
			SqlValidatorUtil.mapNameToIndex(tableRowType.getFieldList());

		// Validate update values against the view constraint.
		final List<SqlNode> targets = update.getTargetColumnList().getList();
		final List<SqlNode> sources = update.getSourceExpressionList().getList();
		for (final Pair<SqlNode, SqlNode> column : Pair.zip(targets, sources)) {
			final String columnName = ((SqlIdentifier) column.left).getSimple();
			final Integer columnIndex = nameToIndex.get(columnName);
			if (projectMap.containsKey(columnIndex)) {
				final RexNode columnConstraint = projectMap.get(columnIndex);
				final ValidationError validationError =
					new ValidationError(column.right,
						RESOURCE.viewConstraintNotSatisfied(columnName,
							Util.last(validatorTable.getQualifiedName())));
				RelOptUtil.validateValueAgainstConstraint(column.right,
					columnConstraint, validationError);
			}
		}
	}
}
 
Example #20
Source File: RexSubQuery.java    From calcite with Apache License 2.0 5 votes vote down vote up
@Override protected @Nonnull String computeDigest(boolean withType) {
  final StringBuilder sb = new StringBuilder(op.getName());
  sb.append("(");
  for (RexNode operand : operands) {
    sb.append(operand);
    sb.append(", ");
  }
  sb.append("{\n");
  sb.append(RelOptUtil.toString(rel));
  sb.append("})");
  return sb.toString();
}
 
Example #21
Source File: ProjectMultiJoinMergeRule.java    From calcite with Apache License 2.0 5 votes vote down vote up
public void onMatch(RelOptRuleCall call) {
  Project project = call.rel(0);
  MultiJoin multiJoin = call.rel(1);

  // if all inputs have their projFields set, then projection information
  // has already been pushed into each input
  boolean allSet = true;
  for (int i = 0; i < multiJoin.getInputs().size(); i++) {
    if (multiJoin.getProjFields().get(i) == null) {
      allSet = false;
      break;
    }
  }
  if (allSet) {
    return;
  }

  // create a new MultiJoin that reflects the columns in the projection
  // above the MultiJoin
  final RelBuilder relBuilder = call.builder();
  MultiJoin newMultiJoin =
      RelOptUtil.projectMultiJoin(multiJoin, project);
  relBuilder.push(newMultiJoin)
      .project(project.getProjects(), project.getRowType().getFieldNames());

  call.transformTo(relBuilder.build());
}
 
Example #22
Source File: JoinCommuteRule.java    From calcite with Apache License 2.0 5 votes vote down vote up
public void onMatch(final RelOptRuleCall call) {
  Join join = call.rel(0);

  final RelNode swapped = swap(join, this.swapOuter, call.builder());
  if (swapped == null) {
    return;
  }

  // The result is either a Project or, if the project is trivial, a
  // raw Join.
  final Join newJoin =
      swapped instanceof Join
          ? (Join) swapped
          : (Join) swapped.getInput(0);

  call.transformTo(swapped);

  // We have converted join='a join b' into swapped='select
  // a0,a1,a2,b0,b1 from b join a'. Now register that project='select
  // b0,b1,a0,a1,a2 from (select a0,a1,a2,b0,b1 from b join a)' is the
  // same as 'b join a'. If we didn't do this, the swap join rule
  // would fire on the new join, ad infinitum.
  final RelBuilder relBuilder = call.builder();
  final List<RexNode> exps =
      RelOptUtil.createSwappedJoinExprs(newJoin, join, false);
  relBuilder.push(swapped)
      .project(exps, newJoin.getRowType().getFieldNames());

  call.getPlanner().ensureRegistered(relBuilder.build(), newJoin);
}
 
Example #23
Source File: JoinCommuteRule.java    From calcite with Apache License 2.0 5 votes vote down vote up
/**
 * Returns a relational expression with the inputs switched round. Does not
 * modify <code>join</code>. Returns null if the join cannot be swapped (for
 * example, because it is an outer join).
 *
 * @param join              join to be swapped
 * @param swapOuterJoins    whether outer joins should be swapped
 * @param relBuilder        Builder for relational expressions
 * @return swapped join if swapping possible; else null
 */
public static RelNode swap(Join join, boolean swapOuterJoins,
    RelBuilder relBuilder) {
  final JoinRelType joinType = join.getJoinType();
  if (!swapOuterJoins && joinType != JoinRelType.INNER) {
    return null;
  }
  final RexBuilder rexBuilder = join.getCluster().getRexBuilder();
  final RelDataType leftRowType = join.getLeft().getRowType();
  final RelDataType rightRowType = join.getRight().getRowType();
  final VariableReplacer variableReplacer =
      new VariableReplacer(rexBuilder, leftRowType, rightRowType);
  final RexNode oldCondition = join.getCondition();
  RexNode condition = variableReplacer.apply(oldCondition);

  // NOTE jvs 14-Mar-2006: We preserve attribute semiJoinDone after the
  // swap.  This way, we will generate one semijoin for the original
  // join, and one for the swapped join, and no more.  This
  // doesn't prevent us from seeing any new combinations assuming
  // that the planner tries the desired order (semijoins after swaps).
  Join newJoin =
      join.copy(join.getTraitSet(), condition, join.getRight(),
          join.getLeft(), joinType.swap(), join.isSemiJoinDone());
  final List<RexNode> exps =
      RelOptUtil.createSwappedJoinExprs(newJoin, join, true);
  return relBuilder.push(newJoin)
      .project(exps, join.getRowType().getFieldNames())
      .build();
}
 
Example #24
Source File: LoptOptimizeJoinRule.java    From calcite with Apache License 2.0 5 votes vote down vote up
/**
 * Adjusts a filter to reflect swapping of join inputs
 *
 * @param rexBuilder rexBuilder
 * @param multiJoin join factors being optimized
 * @param origLeft original LHS of the join tree (before swap)
 * @param origRight original RHS of the join tree (before swap)
 * @param condition original join condition
 *
 * @return join condition reflect swap of join inputs
 */
private RexNode swapFilter(
    RexBuilder rexBuilder,
    LoptMultiJoin multiJoin,
    LoptJoinTree origLeft,
    LoptJoinTree origRight,
    RexNode condition) {
  int nFieldsOnLeft =
      origLeft.getJoinTree().getRowType().getFieldCount();
  int nFieldsOnRight =
      origRight.getJoinTree().getRowType().getFieldCount();
  int [] adjustments = new int[nFieldsOnLeft + nFieldsOnRight];

  for (int i = 0; i < nFieldsOnLeft; i++) {
    adjustments[i] = nFieldsOnRight;
  }
  for (int i = nFieldsOnLeft; i < (nFieldsOnLeft + nFieldsOnRight); i++) {
    adjustments[i] = -nFieldsOnLeft;
  }

  condition =
      condition.accept(
          new RelOptUtil.RexInputConverter(
              rexBuilder,
              multiJoin.getJoinFields(origLeft, origRight),
              multiJoin.getJoinFields(origRight, origLeft),
              adjustments));

  return condition;
}
 
Example #25
Source File: TpchTest.java    From calcite with Apache License 2.0 5 votes vote down vote up
@Disabled("Infinite planning")
@Test void testQuery02Conversion() {
  query(2)
      .convertMatches(relNode -> {
        String s = RelOptUtil.toString(relNode);
        assertThat(s, not(containsString("Correlator")));
        return null;
      });
}
 
Example #26
Source File: QuarkTileTable.java    From quark with Apache License 2.0 5 votes vote down vote up
public RelNode toRel(
    RelOptTable.ToRelContext context,
    RelOptTable relOptTable) {
  // Request all fields.
  RelNode rel = new QuarkTileScan(context.getCluster(),
      this.relOptTable, this.quarkTile, this.backingTable);

  //Create a filter

  RexBuilder rexBuilder = rel.getCluster().getRexBuilder();
  List<RexNode> filterArgs = Lists.newArrayList();
  filterArgs.add(rexBuilder.makeInputRef(rel, this.quarkTile.groupingColumn));
  filterArgs.add(rexBuilder.makeLiteral(bitSetToString(this.quarkTile.groupingValue)));

  rel = LogicalFilter.create(rel, rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, filterArgs));

  //Create a project list
  List<Integer> posList = Lists.newArrayList();
  for (QuarkTile.Column quarkColumn : this.quarkTile.cubeColumns) {
    posList.add(quarkColumn.cubeOrdinal);
  }

  for (Lattice.Measure measure : this.quarkTile.measures) {
    posList.add(((QuarkTile.Measure) measure).ordinal);
  }

  return RelOptUtil.createProject(rel, posList);

}
 
Example #27
Source File: FilterRemoveIsNotDistinctFromRule.java    From calcite with Apache License 2.0 5 votes vote down vote up
public RexNode visitCall(RexCall call) {
  RexNode newCall = super.visitCall(call);

  if (call.getOperator()
      == SqlStdOperatorTable.IS_NOT_DISTINCT_FROM) {
    RexCall tmpCall = (RexCall) newCall;
    newCall =
        RelOptUtil.isDistinctFrom(
            rexBuilder,
            tmpCall.operands.get(0),
            tmpCall.operands.get(1),
            true);
  }
  return newCall;
}
 
Example #28
Source File: LogicalProjectDigestTest.java    From calcite with Apache License 2.0 5 votes vote down vote up
@Test void testProjectDigestWithOneTrivialField() {
  final FrameworkConfig config = RelBuilderTest.config().build();
  final RelBuilder builder = RelBuilder.create(config);
  final RelNode rel = builder
      .scan("EMP")
      .project(builder.field("EMPNO"))
      .build();
  String digest = RelOptUtil.toString(rel, SqlExplainLevel.DIGEST_ATTRIBUTES);
  final String expected = ""
      + "LogicalProject(inputs=[0])\n"
      + "  LogicalTableScan(table=[[scott, EMP]])\n";
  assertThat(digest, isLinux(expected));
}
 
Example #29
Source File: Aggregate.java    From Bats with Apache License 2.0 5 votes vote down vote up
/**
 * Returns whether the inferred type of an {@link AggregateCall} matches the
 * type it was given when it was created.
 *
 * @param aggCall Aggregate call
 * @param litmus What to do if an error is detected (types do not match)
 * @return Whether the inferred and declared types match
 */
private boolean typeMatchesInferred(
    final AggregateCall aggCall,
    final Litmus litmus) {
  SqlAggFunction aggFunction = aggCall.getAggregation();
  AggCallBinding callBinding = aggCall.createBinding(this);
  RelDataType type = aggFunction.inferReturnType(callBinding);
  RelDataType expectedType = aggCall.type;
  return RelOptUtil.eq("aggCall type",
      expectedType,
      "inferred type",
      type,
      litmus);
}
 
Example #30
Source File: Programs.java    From calcite with Apache License 2.0 5 votes vote down vote up
/** Creates a program that invokes heuristic join-order optimization
 * (via {@link org.apache.calcite.rel.rules.JoinToMultiJoinRule},
 * {@link org.apache.calcite.rel.rules.MultiJoin} and
 * {@link org.apache.calcite.rel.rules.LoptOptimizeJoinRule})
 * if there are 6 or more joins (7 or more relations). */
public static Program heuristicJoinOrder(
    final Iterable<? extends RelOptRule> rules,
    final boolean bushy, final int minJoinCount) {
  return (planner, rel, requiredOutputTraits, materializations, lattices) -> {
    final int joinCount = RelOptUtil.countJoins(rel);
    final Program program;
    if (joinCount < minJoinCount) {
      program = ofRules(rules);
    } else {
      // Create a program that gathers together joins as a MultiJoin.
      final HepProgram hep = new HepProgramBuilder()
          .addRuleInstance(FilterJoinRule.FILTER_ON_JOIN)
          .addMatchOrder(HepMatchOrder.BOTTOM_UP)
          .addRuleInstance(JoinToMultiJoinRule.INSTANCE)
          .build();
      final Program program1 =
          of(hep, false, DefaultRelMetadataProvider.INSTANCE);

      // Create a program that contains a rule to expand a MultiJoin
      // into heuristically ordered joins.
      // We use the rule set passed in, but remove JoinCommuteRule and
      // JoinPushThroughJoinRule, because they cause exhaustive search.
      final List<RelOptRule> list = Lists.newArrayList(rules);
      list.removeAll(
          ImmutableList.of(JoinCommuteRule.INSTANCE,
              JoinAssociateRule.INSTANCE,
              JoinPushThroughJoinRule.LEFT,
              JoinPushThroughJoinRule.RIGHT));
      list.add(bushy
          ? MultiJoinOptimizeBushyRule.INSTANCE
          : LoptOptimizeJoinRule.INSTANCE);
      final Program program2 = ofRules(list);

      program = sequence(program1, program2);
    }
    return program.run(
        planner, rel, requiredOutputTraits, materializations, lattices);
  };
}