Exemplo n.º 1
0
  /**
   * Derives an alias for a node, and invents a mangled identifier if it cannot.
   *
   * <p>Examples:
   *
   * <ul>
   *   <li>Alias: "1 + 2 as foo" yields "foo"
   *   <li>Identifier: "foo.bar.baz" yields "baz"
   *   <li>Anything else yields "expr$<i>ordinal</i>"
   * </ul>
   *
   * @return An alias, if one can be derived; or a synthetic alias "expr$<i>ordinal</i>" if ordinal
   *     >= 0; otherwise null
   */
  public static String getAlias(SqlNode node, int ordinal) {
    switch (node.getKind()) {
      case AS:
        // E.g. "1 + 2 as foo" --> "foo"
        return ((SqlCall) node).getOperands()[1].toString();

      case OVER:
        // E.g. "bids over w" --> "bids"
        return getAlias(((SqlCall) node).getOperands()[0], ordinal);

      case IDENTIFIER:
        // E.g. "foo.bar" --> "bar"
        return Util.last(((SqlIdentifier) node).names);

      default:
        if (ordinal < 0) {
          return null;
        } else {
          return SqlUtil.deriveAliasFromOrdinal(ordinal);
        }
    }
  }
  public int reduceExpr(int opOrdinal, List<Object> list) {
    final SqlParserUtil.ToTreeListItem betweenNode =
        (SqlParserUtil.ToTreeListItem) list.get(opOrdinal);
    SqlOperator op = betweenNode.getOperator();
    assert op == this;

    // Break the expression up into expressions. For example, a simple
    // expression breaks down as follows:
    //
    //            opOrdinal   endExp1
    //            |           |
    //     a + b BETWEEN c + d AND e + f
    //    |_____|       |_____|   |_____|
    //     exp0          exp1      exp2
    // Create the expression between 'BETWEEN' and 'AND'.
    final SqlParserPos pos = ((SqlNode) list.get(opOrdinal + 1)).getParserPosition();
    SqlNode exp1 = SqlParserUtil.toTreeEx(list, opOrdinal + 1, 0, SqlKind.AND);
    if ((opOrdinal + 2) >= list.size()) {
      SqlParserPos lastPos = ((SqlNode) list.get(list.size() - 1)).getParserPosition();
      final int line = lastPos.getEndLineNum();
      final int col = lastPos.getEndColumnNum() + 1;
      SqlParserPos errPos = new SqlParserPos(line, col, line, col);
      throw SqlUtil.newContextException(
          errPos, EigenbaseResource.instance().BetweenWithoutAnd.ex());
    }
    final Object o = list.get(opOrdinal + 2);
    if (!(o instanceof SqlParserUtil.ToTreeListItem)) {
      SqlParserPos errPos = ((SqlNode) o).getParserPosition();
      throw SqlUtil.newContextException(
          errPos, EigenbaseResource.instance().BetweenWithoutAnd.ex());
    }
    if (((SqlParserUtil.ToTreeListItem) o).getOperator().getKind() != SqlKind.AND) {
      SqlParserPos errPos = ((SqlParserUtil.ToTreeListItem) o).getPos();
      throw SqlUtil.newContextException(
          errPos, EigenbaseResource.instance().BetweenWithoutAnd.ex());
    }

    // Create the expression after 'AND', but stopping if we encounter an
    // operator of lower precedence.
    //
    // For example,
    //   a BETWEEN b AND c + d OR e
    // becomes
    //   (a BETWEEN b AND c + d) OR e
    // because OR has lower precedence than BETWEEN.
    SqlNode exp2 = SqlParserUtil.toTreeEx(list, opOrdinal + 3, getRightPrec(), SqlKind.OTHER);

    // Create the call.
    SqlNode exp0 = (SqlNode) list.get(opOrdinal - 1);
    SqlCall newExp =
        createCall(
            betweenNode.getPos(),
            exp0,
            exp1,
            exp2,
            SqlLiteral.createSymbol(flag, SqlParserPos.ZERO));

    // Replace all of the matched nodes with the single reduced node.
    SqlParserUtil.replaceSublist(list, opOrdinal - 1, opOrdinal + 4, newExp);

    // Return the ordinal of the new current node.
    return opOrdinal - 1;
  }