Java Code Examples for org.apache.calcite.linq4j.tree.Expressions#list()

The following examples show how to use org.apache.calcite.linq4j.tree.Expressions#list() . 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: RelToSqlConverter.java    From dremio-oss with Apache License 2.0 6 votes vote down vote up
/**
 * @see #dispatch
 */
public Result visit(Sort e) {
  Result x = visitChild(0, e.getInput());
  Builder builder = x.builder(e, Clause.ORDER_BY);
  List<SqlNode> orderByList = Expressions.list();
  for (RelFieldCollation field : e.getCollation().getFieldCollations()) {
    builder.addOrderItem(orderByList, field);
  }
  if (!orderByList.isEmpty()) {
    builder.setOrderBy(new SqlNodeList(orderByList, POS));
    x = builder.result();
  }
  if (e.fetch != null) {
    builder = x.builder(e, Clause.FETCH);
    builder.setFetch(builder.context.toSql(null, e.fetch));
    x = builder.result();
  }
  if (e.offset != null) {
    builder = x.builder(e, Clause.OFFSET);
    builder.setOffset(builder.context.toSql(null, e.offset));
    x = builder.result();
  }
  return x;
}
 
Example 2
Source File: DremioRelToSqlConverter.java    From dremio-oss with Apache License 2.0 6 votes vote down vote up
protected void generateGroupBy(DremioRelToSqlConverter.Builder builder, Aggregate e) {
  List<SqlNode> groupByList = Expressions.list();
  final List<SqlNode> selectList = new ArrayList<>();
  for (int group : e.getGroupSet()) {
    final SqlNode field = builder.context.field(group);
    addSelect(selectList, field, e.getRowType());
    addGroupBy(groupByList, field);
  }

  for (AggregateCall aggCall : e.getAggCallList()) {
    SqlNode aggCallSqlNode = ((DremioContext) builder.context).toSql(aggCall, e);

    if (aggCall.getAggregation() instanceof SqlSingleValueAggFunction) {
      aggCallSqlNode = dialect.
        rewriteSingleValueExpr(aggCallSqlNode);
    }
    addSelect(selectList, aggCallSqlNode, e.getRowType());
  }
  builder.setSelect(new SqlNodeList(selectList, POS));
  if (!groupByList.isEmpty() || e.getAggCallList().isEmpty()) {
    // Some databases don't support "GROUP BY ()". We can omit it as long
    // as there is at least one aggregate function.
    builder.setGroupBy(new SqlNodeList(groupByList, POS));
  }
}
 
Example 3
Source File: SqlImplementor.java    From dremio-oss with Apache License 2.0 5 votes vote down vote up
/**
 * Converts a call to an aggregate function to an expression.
 */
public SqlNode toSql(AggregateCall aggCall) {
  SqlOperator op = aggCall.getAggregation();
  if (op instanceof SqlSumEmptyIsZeroAggFunction) {
    op = SqlStdOperatorTable.SUM;
  }
  final List<SqlNode> operands = Expressions.list();
  for (int arg : aggCall.getArgList()) {
    operands.add(field(arg));
  }
  return op.createCall(
    aggCall.isDistinct() ? SqlSelectKeyword.DISTINCT.symbol(POS) : null,
    POS, operands.toArray(new SqlNode[0]));
}
 
Example 4
Source File: SqlImplementor.java    From calcite with Apache License 2.0 5 votes vote down vote up
private Result(SqlNode node, Collection<Clause> clauses, String neededAlias,
    RelDataType neededType, Map<String, RelDataType> aliases,
    boolean anon) {
  this.node = node;
  this.neededAlias = neededAlias;
  this.neededType = neededType;
  this.aliases = aliases;
  this.clauses = Expressions.list(clauses);
  this.anon = anon;
}
 
Example 5
Source File: SqlImplementor.java    From calcite with Apache License 2.0 5 votes vote down vote up
private SqlCall toSql(RexProgram program, RexOver rexOver) {
  final RexWindow rexWindow = rexOver.getWindow();
  final SqlNodeList partitionList = new SqlNodeList(
      toSql(program, rexWindow.partitionKeys), POS);

  List<SqlNode> orderNodes = Expressions.list();
  if (rexWindow.orderKeys != null) {
    for (RexFieldCollation rfc : rexWindow.orderKeys) {
      addOrderItem(orderNodes, program, rfc);
    }
  }
  final SqlNodeList orderList =
      new SqlNodeList(orderNodes, POS);

  final SqlLiteral isRows =
      SqlLiteral.createBoolean(rexWindow.isRows(), POS);

  // null defaults to true.
  // During parsing the allowPartial == false (e.g. disallow partial)
  // is expand into CASE expression and is handled as a such.
  // Not sure if we can collapse this CASE expression back into
  // "disallow partial" and set the allowPartial = false.
  final SqlLiteral allowPartial = null;

  SqlAggFunction sqlAggregateFunction = rexOver.getAggOperator();

  SqlNode lowerBound = null;
  SqlNode upperBound = null;

  if (sqlAggregateFunction.allowsFraming()) {
    lowerBound = createSqlWindowBound(rexWindow.getLowerBound());
    upperBound = createSqlWindowBound(rexWindow.getUpperBound());
  }

  final SqlWindow sqlWindow = SqlWindow.create(null, null, partitionList,
      orderList, isRows, lowerBound, upperBound, allowPartial, POS);

  final List<SqlNode> nodeList = toSql(program, rexOver.getOperands());
  return createOverCall(sqlAggregateFunction, nodeList, sqlWindow);
}
 
Example 6
Source File: SqlImplementor.java    From calcite with Apache License 2.0 5 votes vote down vote up
/** Creates a result based on a join. (Each join could contain one or more
 * relational expressions.) */
public Result result(SqlNode join, Result leftResult, Result rightResult) {
  final ImmutableMap.Builder<String, RelDataType> builder =
      ImmutableMap.builder();
  if (join.getKind() == SqlKind.JOIN) {
    collectAliases(builder, join,
        Iterables.concat(leftResult.aliases.values(),
            rightResult.aliases.values()).iterator());
    return new Result(join, Expressions.list(Clause.FROM), null, null,
        builder.build());
  } else {
    return new Result(join, Expressions.list(Clause.FROM), null, null,
        leftResult.aliases);
  }
}
 
Example 7
Source File: SqlImplementor.java    From calcite with Apache License 2.0 5 votes vote down vote up
public Result setOpToSql(SqlSetOperator operator, RelNode rel) {
  SqlNode node = null;
  for (Ord<RelNode> input : Ord.zip(rel.getInputs())) {
    final Result result = visitChild(input.i, input.e);
    if (node == null) {
      node = result.asSelect();
    } else {
      node = operator.createCall(POS, node, result.asSelect());
    }
  }
  final List<Clause> clauses =
      Expressions.list(Clause.SET_OP);
  return result(node, clauses, rel, null);
}
 
Example 8
Source File: RelToSqlConverter.java    From quark with Apache License 2.0 5 votes vote down vote up
private Result(SqlNode node, Collection<Clause> clauses, String neededAlias,
               List<Pair<String, RelDataType>> aliases) {
  this.node = node;
  this.neededAlias = neededAlias;
  this.aliases = aliases;
  this.clauses = Expressions.list(clauses);
}
 
Example 9
Source File: RelToSqlConverter.java    From quark with Apache License 2.0 5 votes vote down vote up
/**
 * Converts a call to an aggregate function to an expression.
 */
public SqlNode toSql(AggregateCall aggCall) {
  SqlOperator op = (SqlAggFunction) aggCall.getAggregation();
  if (op instanceof SqlSumEmptyIsZeroAggFunction) {
    op = SqlStdOperatorTable.SUM;
  }
  final List<SqlNode> operands = Expressions.list();
  for (int arg : aggCall.getArgList()) {
    operands.add(field(arg));
  }
  return op.createCall(
      aggCall.isDistinct() ? SqlSelectKeyword.DISTINCT.symbol(POS) : null,
      POS, operands.toArray(new SqlNode[operands.size()]));
}
 
Example 10
Source File: RelToSqlConverter.java    From quark with Apache License 2.0 5 votes vote down vote up
private Result setOpToSql(SqlSetOperator operator, RelNode rel) {
  List<SqlNode> list = Expressions.list();
  for (Ord<RelNode> input : Ord.zip(rel.getInputs())) {
    final Result result = this.visitChild(input.i, input.e);
    list.add(result.asSelect());
  }
  final SqlCall node = operator.createCall(new SqlNodeList(list, POS));
  final List<Clause> clauses =
      Expressions.list(Clause.SET_OP);
  return result(node, clauses, rel);
}
 
Example 11
Source File: RelToSqlConverter.java    From quark with Apache License 2.0 5 votes vote down vote up
public Result visitAggregate(Aggregate e) {
  // "select a, b, sum(x) from ( ... ) group by a, b"
  final Result x = visitChild(0, e.getInput());
  final Builder builder =
      x.builder(e, Clause.GROUP_BY);
  List<SqlNode> groupByList = Expressions.list();
  final List<SqlNode> selectList = new ArrayList<>();
  for (int group : e.getGroupSet()) {
    final SqlNode field = builder.context.field(group);
    addSelect(selectList, field, e.getRowType());
    groupByList.add(field);
  }
  for (AggregateCall aggCall : e.getAggCallList()) {
    SqlNode aggCallSqlNode = builder.context.toSql(aggCall);
    if (aggCall.getAggregation() instanceof SqlSingleValueAggFunction) {
      aggCallSqlNode =
          rewriteSingleValueExpr(aggCallSqlNode, dialect);
    }
    addSelect(selectList, aggCallSqlNode, e.getRowType());
  }
  builder.setSelect(new SqlNodeList(selectList, POS));
  if (!groupByList.isEmpty() || e.getAggCallList().isEmpty()) {
    // Some databases don't support "GROUP BY ()". We can omit it as long
    // as there is at least one aggregate function.
    builder.setGroupBy(new SqlNodeList(groupByList, POS));
  }
  return builder.result();
}
 
Example 12
Source File: RelToSqlConverter.java    From quark with Apache License 2.0 5 votes vote down vote up
/**
 * Creates a result based on a join. (Each join could contain one or more
 * relational expressions.)
 */
public Result result(SqlNode join, Result leftResult, Result rightResult) {
  final List<Pair<String, RelDataType>> list =
      new ArrayList<Pair<String, RelDataType>>();
  list.addAll(leftResult.aliases);
  list.addAll(rightResult.aliases);
  return new Result(join, Expressions.list(Clause.FROM), null, list);
}
 
Example 13
Source File: SqlImplementor.java    From dremio-oss with Apache License 2.0 5 votes vote down vote up
public Result(SqlNode node, Collection<Clause> clauses, String neededAlias,
              RelDataType neededType, Map<String, RelDataType> aliases) {
  this.node = node;
  this.neededAlias = neededAlias;
  this.neededType = neededType;
  this.aliases = aliases;
  this.clauses = Expressions.list(clauses);
}
 
Example 14
Source File: SqlImplementor.java    From dremio-oss with Apache License 2.0 5 votes vote down vote up
public Result setOpToSql(SqlSetOperator operator, RelNode rel) {
  SqlNode node = null;
  for (Ord<RelNode> input : Ord.zip(rel.getInputs())) {
    final Result result = visitChild(input.i, input.e);
    if (node == null) {
      node = result.asSelect();
    } else {
      node = operator.createCall(POS, node, result.asSelect());
    }
  }
  final List<Clause> clauses =
    Expressions.list(Clause.SET_OP);
  return result(node, clauses, rel, null);
}
 
Example 15
Source File: DremioRelToSqlConverter.java    From dremio-oss with Apache License 2.0 4 votes vote down vote up
/**
 * Once you have a Result of implementing a child relational expression,
 * call this method to create a Builder to implement the current relational
 * expression by adding additional clauses to the SQL query.
 *
 * <p>You need to declare which clauses you intend to add. If the clauses
 * are "later", you can add to the same query. For example, "GROUP BY" comes
 * after "WHERE". But if they are the same or earlier, this method will
 * start a new SELECT that wraps the previous result.
 *
 * <p>When you have called
 * {@link Builder#setSelect(SqlNodeList)},
 * {@link Builder#setWhere(SqlNode)} etc. call
 * {@link Builder#result(SqlNode, Collection, RelNode, Map)}
 * to fix the new query.
 *
 * @param rel      Relational expression being implemented
 * @param forceNew Forces the query the result to be wrapped in a sub-query.
 * @param clauses  Clauses that will be generated to implement current
 *                 relational expression
 * @return A builder
 */
public Builder builder(RelNode rel, boolean forceNew, Clause... clauses) {
  final Clause maxClause = maxClause();
  boolean needNew = forceNew;

  // If old and new clause are equal and belong to below set,
  // then new SELECT wrap is not required
  if (!needNew) {
    Set<Clause> nonWrapSet = ImmutableSet.of(Clause.SELECT);
    for (Clause clause : clauses) {
      if (maxClause.ordinal() > clause.ordinal()
        || (maxClause == clause && !nonWrapSet.contains(clause))) {
        needNew = true;
      }
    }
  }

  if (rel instanceof LogicalAggregate
    && !dialect.supportsNestedAggregations()
    && hasNestedAggregations((LogicalAggregate) rel)) {
    needNew = true;
  }

  SqlSelect select;
  Expressions.FluentList<Clause> clauseList = Expressions.list();
  if (needNew) {
    select = subSelect();
  } else {
    select = asSelect();
    clauseList.addAll(this.clauses);
  }
  clauseList.appendAll(clauses);
  Context newContext;
  final SqlNodeList selectList = select.getSelectList();
  if (selectList != null) {
    newContext = getDremioRelToSqlConverter().selectListContext(selectList);
  } else {
    final boolean qualified = !dialect.hasImplicitTableAlias()
      || aliases.size() > 1 || getDremioRelToSqlConverter().isSubQuery();

    // basically, we did a subSelect() since needNew is set and neededAlias is not null
    // now, we need to make sure that we need to update the alias context.
    // if our aliases map has a single element:  <neededAlias, rowType>,
    // then we don't need to rewrite the alias but otherwise, it should be updated.
    if (needNew
      && neededAlias != null
      && (aliases.size() != 1 || !aliases.containsKey(neededAlias)
      || !aliases.get(neededAlias).equals(rel.getInput(0).getRowType()))) {
      final Map<String, RelDataType> newAliases =
        ImmutableMap.of(neededAlias, rel.getInput(0).getRowType());
      newContext = getDremioRelToSqlConverter().aliasContext(newAliases, qualified);
      return new Builder(rel, clauseList, select, newContext, rel.getRowType(), newAliases);
    } else {
      newContext = getDremioRelToSqlConverter().aliasContext(aliases, qualified);
    }
  }
  return new Builder(rel, clauseList, select, newContext, rel.getRowType(), aliases);
}
 
Example 16
Source File: RelToSqlConverter.java    From quark with Apache License 2.0 4 votes vote down vote up
/**
 * Once you have a Result of implementing a child relational expression,
 * call this method to create a Builder to implement the current relational
 * expression by adding additional clauses to the SQL query.
 * <p></p>
 * <p>You need to declare which clauses you intend to add. If the clauses
 * are "later", you can add to the same query. For example, "GROUP BY" comes
 * after "WHERE". But if they are the same or earlier, this method will
 * start a new SELECT that wraps the previous result.</p>
 * <p>When you have called
 * {@link Builder#setSelect(org.apache.calcite.sql.SqlNodeList)},
 * {@link Builder#setWhere(org.apache.calcite.sql.SqlNode)} etc. call
 * {@link Builder#result(org.apache.calcite.sql.SqlNode, java.util.Collection, org.apache.calcite.rel.RelNode)}
 * to fix the new query.</p>
 *
 * @param rel     Relational expression being implemented
 * @param clauses Clauses that will be generated to implement current
 *                relational expression
 * @return A builder
 */
public Builder builder(RelNode rel, Clause... clauses) {
  final Clause maxClause = maxClause();
  boolean needNew = false;
  for (Clause clause : clauses) {
    if (maxClause.ordinal() >= clause.ordinal()) {
      needNew = true;
    }
  }
  SqlSelect select;
  Expressions.FluentList<Clause> clauseList = Expressions.list();
  if (needNew) {
    select = subSelect();
  } else {
    select = asSelect();
    clauseList.addAll(this.clauses);
  }
  clauseList.appendAll(clauses);
  Context newContext;
  final SqlNodeList selectList = select.getSelectList();
  if (selectList != null) {
    newContext = new Context(selectList.size()) {

      @Override
      public SqlNode field(int ordinal) {
        return field(ordinal, false);
      }

      @Override
      public SqlNode field(int ordinal, boolean useAlias) {
        final SqlNode selectItem = selectList.get(ordinal);
        switch (selectItem.getKind()) {
          case AS:
            if (useAlias) {
              return ((SqlCall) selectItem).operand(1);
            } else {
              return ((SqlCall) selectItem).operand(0);
            }
        }
        return selectItem;
      }
    };
  } else {
    newContext = new AliasContext(aliases, aliases.size() > 1);
  }
  return new Builder(rel, clauseList, select, newContext);
}
 
Example 17
Source File: PigRelToSqlConverter.java    From calcite with Apache License 2.0 4 votes vote down vote up
/** @see #dispatch */
public Result visit(Window e) {
  final Result x = visitChild(0, e.getInput());
  final Builder builder = x.builder(e, Clause.SELECT);
  final List<SqlNode> selectList =
      new ArrayList<>(builder.context.fieldList());

  for (Window.Group winGroup : e.groups) {
    final List<SqlNode> partitionList = Expressions.list();
    for (int i : winGroup.keys) {
      partitionList.add(builder.context.field(i));
    }

    final List<SqlNode> orderList = Expressions.list();
    for (RelFieldCollation orderKey : winGroup.collation().getFieldCollations()) {
      orderList.add(builder.context.toSql(orderKey));
    }

    final SqlNode sqlWindow =  SqlWindow.create(
        null, // Window declaration name
        null, // Window reference name
        new SqlNodeList(partitionList, POS),
        new SqlNodeList(orderList, POS),
        SqlLiteral.createBoolean(winGroup.isRows, POS),
        builder.context.toSql(winGroup.lowerBound),
        builder.context.toSql(winGroup.upperBound),
        null, // allowPartial
        POS);

    for (Window.RexWinAggCall winFunc : winGroup.aggCalls) {
      final List<SqlNode> winFuncOperands = Expressions.list();
      for (RexNode operand : winFunc.getOperands()) {
        winFuncOperands.add(builder.context.toSql(null, operand));
      }
      SqlNode aggFunc = winFunc.getOperator().createCall(new SqlNodeList(winFuncOperands, POS));
      selectList.add(SqlStdOperatorTable.OVER.createCall(POS, aggFunc, sqlWindow));
    }
    builder.setSelect(new SqlNodeList(selectList, POS));
  }
  return builder.result();
}
 
Example 18
Source File: PhysTypeImpl.java    From calcite with Apache License 2.0 4 votes vote down vote up
public Expression generateComparator(RelCollation collation) {
  // int c;
  // c = Utilities.compare(v0, v1);
  // if (c != 0) return c; // or -c if descending
  // ...
  // return 0;
  BlockBuilder body = new BlockBuilder();
  final Type javaRowClass = Primitive.box(this.javaRowClass);
  final ParameterExpression parameterV0 =
      Expressions.parameter(javaRowClass, "v0");
  final ParameterExpression parameterV1 =
      Expressions.parameter(javaRowClass, "v1");
  final ParameterExpression parameterC =
      Expressions.parameter(int.class, "c");
  final int mod =
      collation.getFieldCollations().size() == 1 ? Modifier.FINAL : 0;
  body.add(Expressions.declare(mod, parameterC, null));
  for (RelFieldCollation fieldCollation : collation.getFieldCollations()) {
    final int index = fieldCollation.getFieldIndex();
    final RelDataType fieldType = rowType.getFieldList().get(index).getType();
    final Expression fieldComparator = generateCollatorExpression(fieldType.getCollation());
    Expression arg0 = fieldReference(parameterV0, index);
    Expression arg1 = fieldReference(parameterV1, index);
    switch (Primitive.flavor(fieldClass(index))) {
    case OBJECT:
      arg0 = EnumUtils.convert(arg0, Comparable.class);
      arg1 = EnumUtils.convert(arg1, Comparable.class);
    }
    final boolean nullsFirst =
        fieldCollation.nullDirection
            == RelFieldCollation.NullDirection.FIRST;
    final boolean descending =
        fieldCollation.getDirection()
            == RelFieldCollation.Direction.DESCENDING;
    body.add(
        Expressions.statement(
            Expressions.assign(
                parameterC,
                Expressions.call(
                    Utilities.class,
                    fieldNullable(index)
                        ? (nullsFirst != descending
                        ? "compareNullsFirst"
                        : "compareNullsLast")
                        : "compare",
                    Expressions.list(
                        arg0,
                        arg1)
                        .appendIfNotNull(fieldComparator)))));
    body.add(
        Expressions.ifThen(
            Expressions.notEqual(
                parameterC, Expressions.constant(0)),
            Expressions.return_(
                null,
                descending
                    ? Expressions.negate(parameterC)
                    : parameterC)));
  }
  body.add(
      Expressions.return_(null, Expressions.constant(0)));

  final List<MemberDeclaration> memberDeclarations =
      Expressions.list(
          Expressions.methodDecl(
              Modifier.PUBLIC,
              int.class,
              "compare",
              ImmutableList.of(parameterV0, parameterV1),
              body.toBlock()));

  if (EnumerableRules.BRIDGE_METHODS) {
    final ParameterExpression parameterO0 =
        Expressions.parameter(Object.class, "o0");
    final ParameterExpression parameterO1 =
        Expressions.parameter(Object.class, "o1");
    BlockBuilder bridgeBody = new BlockBuilder();
    bridgeBody.add(
        Expressions.return_(
            null,
            Expressions.call(
                Expressions.parameter(
                    Comparable.class, "this"),
                BuiltInMethod.COMPARATOR_COMPARE.method,
                Expressions.convert_(
                    parameterO0,
                    javaRowClass),
                Expressions.convert_(
                    parameterO1,
                    javaRowClass))));
    memberDeclarations.add(
        overridingMethodDecl(
            BuiltInMethod.COMPARATOR_COMPARE.method,
            ImmutableList.of(parameterO0, parameterO1),
            bridgeBody.toBlock()));
  }
  return Expressions.new_(
      Comparator.class,
      ImmutableList.of(),
      memberDeclarations);
}
 
Example 19
Source File: SqlImplementor.java    From dremio-oss with Apache License 2.0 4 votes vote down vote up
/**
 * Once you have a Result of implementing a child relational expression,
 * call this method to create a Builder to implement the current relational
 * expression by adding additional clauses to the SQL query.
 *
 * <p>You need to declare which clauses you intend to add. If the clauses
 * are "later", you can add to the same query. For example, "GROUP BY" comes
 * after "WHERE". But if they are the same or earlier, this method will
 * start a new SELECT that wraps the previous result.
 *
 * <p>When you have called
 * {@link Builder#setSelect(SqlNodeList)},
 * {@link Builder#setWhere(SqlNode)} etc. call
 * {@link Builder#result(SqlNode, Collection, RelNode, Map)}
 * to fix the new query.
 *
 * @param rel     Relational expression being implemented
 * @param clauses Clauses that will be generated to implement current
 *                relational expression
 * @return A builder
 */
public Builder builder(RelNode rel, Clause... clauses) {
  final Clause maxClause = maxClause();
  boolean needNew = false;
  // If old and new clause are equal and belong to below set,
  // then new SELECT wrap is not required
  Set<Clause> nonWrapSet = ImmutableSet.of(Clause.SELECT);
  for (Clause clause : clauses) {
    if (maxClause.ordinal() > clause.ordinal()
      || (maxClause == clause && !nonWrapSet.contains(clause))) {
      needNew = true;
    }
  }
  if (rel instanceof LogicalAggregate
    && !dialect.supportsNestedAggregations()
    && hasNestedAggregations((LogicalAggregate) rel)) {
    needNew = true;
  }

  SqlSelect select;
  Expressions.FluentList<Clause> clauseList = Expressions.list();
  if (needNew) {
    select = subSelect();
  } else {
    select = asSelect();
    clauseList.addAll(this.clauses);
  }
  clauseList.appendAll(clauses);
  Context newContext;
  final SqlNodeList selectList = select.getSelectList();
  if (selectList != null) {
    newContext = new Context(selectList.size()) {
      @Override
      public SqlNode field(int ordinal) {
        final SqlNode selectItem = selectList.get(ordinal);
        switch (selectItem.getKind()) {
          case AS:
            return ((SqlCall) selectItem).operand(0);
        }
        return selectItem;
      }
    };
  } else {
    boolean qualified =
      !dialect.hasImplicitTableAlias() || aliases.size() > 1;
    // basically, we did a subSelect() since needNew is set and neededAlias is not null
    // now, we need to make sure that we need to update the alias context.
    // if our aliases map has a single element:  <neededAlias, rowType>,
    // then we don't need to rewrite the alias but otherwise, it should be updated.
    if (needNew
      && neededAlias != null
      && (aliases.size() != 1 || !aliases.containsKey(neededAlias))) {
      final Map<String, RelDataType> newAliases =
        ImmutableMap.of(neededAlias, rel.getInput(0).getRowType());
      newContext = aliasContext(newAliases, qualified);
    } else {
      newContext = aliasContext(aliases, qualified);
    }
  }
  return new Builder(rel, clauseList, select, newContext,
    needNew ? null : aliases);
}
 
Example 20
Source File: SqlImplementor.java    From calcite with Apache License 2.0 4 votes vote down vote up
/** Once you have a Result of implementing a child relational expression,
 * call this method to create a Builder to implement the current relational
 * expression by adding additional clauses to the SQL query.
 *
 * <p>You need to declare which clauses you intend to add. If the clauses
 * are "later", you can add to the same query. For example, "GROUP BY" comes
 * after "WHERE". But if they are the same or earlier, this method will
 * start a new SELECT that wraps the previous result.
 *
 * <p>When you have called
 * {@link Builder#setSelect(SqlNodeList)},
 * {@link Builder#setWhere(SqlNode)} etc. call
 * {@link Builder#result(SqlNode, Collection, RelNode, Map)}
 * to fix the new query.
 *
 * @param rel Relational expression being implemented
 * @param clauses Clauses that will be generated to implement current
 *                relational expression
 * @return A builder
 */
public Builder builder(RelNode rel, Clause... clauses) {
  final boolean needNew = needNewSubQuery(rel, clauses);
  SqlSelect select;
  Expressions.FluentList<Clause> clauseList = Expressions.list();
  if (needNew) {
    select = subSelect();
  } else {
    select = asSelect();
    clauseList.addAll(this.clauses);
  }
  clauseList.appendAll(clauses);
  final Context newContext;
  Map<String, RelDataType> newAliases = null;
  final SqlNodeList selectList = select.getSelectList();
  if (selectList != null) {
    newContext = new Context(dialect, selectList.size()) {
      public SqlNode field(int ordinal) {
        final SqlNode selectItem = selectList.get(ordinal);
        switch (selectItem.getKind()) {
        case AS:
          return ((SqlCall) selectItem).operand(0);
        }
        return selectItem;
      }

      @Override public SqlNode orderField(int ordinal) {
        // If the field expression is an unqualified column identifier
        // and matches a different alias, use an ordinal.
        // For example, given
        //    SELECT deptno AS empno, empno AS x FROM emp ORDER BY emp.empno
        // we generate
        //    SELECT deptno AS empno, empno AS x FROM emp ORDER BY 2
        // "ORDER BY empno" would give incorrect result;
        // "ORDER BY x" is acceptable but is not preferred.
        final SqlNode node = field(ordinal);
        if (node instanceof SqlIdentifier
            && ((SqlIdentifier) node).isSimple()) {
          final String name = ((SqlIdentifier) node).getSimple();
          for (Ord<SqlNode> selectItem : Ord.zip(selectList)) {
            if (selectItem.i != ordinal) {
              final String alias =
                  SqlValidatorUtil.getAlias(selectItem.e, -1);
              if (name.equalsIgnoreCase(alias)) {
                return SqlLiteral.createExactNumeric(
                    Integer.toString(ordinal + 1), SqlParserPos.ZERO);
              }
            }
          }
        }
        return node;
      }
    };
  } else {
    boolean qualified =
        !dialect.hasImplicitTableAlias() || aliases.size() > 1;
    // basically, we did a subSelect() since needNew is set and neededAlias is not null
    // now, we need to make sure that we need to update the alias context.
    // if our aliases map has a single element:  <neededAlias, rowType>,
    // then we don't need to rewrite the alias but otherwise, it should be updated.
    if (needNew
        && neededAlias != null
        && (aliases.size() != 1 || !aliases.containsKey(neededAlias))) {
      newAliases =
          ImmutableMap.of(neededAlias, rel.getInput(0).getRowType());
      newContext = aliasContext(newAliases, qualified);
    } else {
      newContext = aliasContext(aliases, qualified);
    }
  }
  return new Builder(rel, clauseList, select, newContext, isAnon(),
      needNew && !aliases.containsKey(neededAlias) ? newAliases : aliases);
}