Example #1
0
 public SqlNode visit(SqlNodeList list) {
   SqlNodeList copy = new SqlNodeList(list.getParserPosition());
   for (SqlNode node : list) {
     copy.add(node.accept(this));
   }
   return copy;
 }
Example #2
0
 void commaList(SqlWriter writer) {
   // The precedence of the comma operator if low but not zero. For
   // instance, this ensures parentheses in
   //    select x, (select * from foo order by z), y from t
   for (SqlNode node : list) {
     writer.sep(",");
     node.unparse(writer, 2, 3);
   }
 }
 public static SqlNode[] cloneArray(SqlNode[] nodes) {
   SqlNode[] clones = (SqlNode[]) nodes.clone();
   for (int i = 0; i < clones.length; i++) {
     SqlNode node = clones[i];
     if (node != null) {
       clones[i] = (SqlNode) node.clone();
     }
   }
   return clones;
 }
Example #4
0
 /** Tests that Hive dialect does not generate "AS". */
 @Test
 public void testHiveDialect() throws SqlParseException {
   Planner planner = getPlanner();
   SqlNode parse =
       planner.parse(
           "select * from (select * from \"emps\") as t\n" + "where \"name\" like '%e%'");
   final SqlDialect hiveDialect = new SqlDialect(SqlDialect.DatabaseProduct.HIVE, "Hive", null);
   assertThat(
       parse.toSqlString(hiveDialect).getSql(),
       equalTo("SELECT *\n" + "FROM (SELECT *\n" + "FROM emps) T\n" + "WHERE name LIKE '%e%'"));
 }
Example #5
0
 public SqlNode findAgg(List<SqlNode> nodes) {
   try {
     for (SqlNode node : nodes) {
       node.accept(this);
     }
     return null;
   } catch (Util.FoundOne e) {
     Util.swallow(e, null);
     return (SqlNode) e.getNode();
   }
 }
Example #6
0
  @Test
  public void testValidateFails() throws SqlParseException {
    Planner planner = getPlanner();
    SqlNode parse = planner.parse("select * from \"emps\" where \"Xname\" like '%e%'");
    assertThat(
        parse.toString(), equalTo("SELECT *\n" + "FROM `emps`\n" + "WHERE `Xname` LIKE '%e%'"));

    try {
      SqlNode validate = planner.validate(parse);
      fail("expected error, got " + validate);
    } catch (ValidationException e) {
      assertThat(Util.getStackTrace(e), containsString("Column 'Xname' not found in any table"));
      // ok
    }
  }
Example #7
0
  @Test
  public void testParseAndConvert() throws Exception {
    Planner planner = getPlanner();
    SqlNode parse = planner.parse("select * from \"emps\" where \"name\" like '%e%'");
    assertThat(
        parse.toString(), equalTo("SELECT *\n" + "FROM `emps`\n" + "WHERE `name` LIKE '%e%'"));

    SqlNode validate = planner.validate(parse);
    RelNode rel = planner.convert(validate);
    assertThat(
        toString(rel),
        equalTo(
            "ProjectRel(empid=[$0], deptno=[$1], name=[$2], salary=[$3], commission=[$4])\n"
                + "  FilterRel(condition=[LIKE($2, '%e%')])\n"
                + "    EnumerableTableAccessRel(table=[[hr, emps]])\n"));
  }
 boolean containsAnd(SqlNode node) {
   try {
     node.accept(this);
     return false;
   } catch (AndFinder.Found e) {
     return true;
   }
 }
Example #9
0
  public void validateExpr(SqlValidator validator, SqlValidatorScope scope) {
    // While a SqlNodeList is not always a valid expression, this
    // implementation makes that assumption. It just validates the members
    // of the list.
    //
    // One example where this is valid is the IN operator. The expression
    //
    //    empno IN (10, 20)
    //
    // results in a call with operands
    //
    //    {  SqlIdentifier({"empno"}),
    //       SqlNodeList(SqlLiteral(10), SqlLiteral(20))  }

    for (SqlNode node : list) {
      node.validateExpr(validator, scope);
    }
  }
Example #10
0
  void andOrList(SqlWriter writer, SqlKind sepKind) {
    SqlBinaryOperator sepOp =
        sepKind == SqlKind.AND ? SqlStdOperatorTable.AND : SqlStdOperatorTable.OR;
    for (int i = 0; i < list.size(); i++) {
      SqlNode node = list.get(i);
      writer.sep(sepKind.name(), false);

      // The precedence pulling on the LHS of a node is the
      // right-precedence of the separator operator, except at the start
      // of the list; similarly for the RHS of a node. If the operator
      // has left precedence 4 and right precedence 5, the precedences
      // in a 3-node list will look as follows:
      //   0 <- node1 -> 4  5 <- node2 -> 4  5 <- node3 -> 0
      int lprec = (i == 0) ? 0 : sepOp.getRightPrec();
      int rprec = (i == (list.size() - 1)) ? 0 : sepOp.getLeftPrec();
      node.unparse(writer, lprec, rprec);
    }
  }
 /**
  * Returns whether two nodes are equal (using {@link #equalsDeep(SqlNode,boolean)}) or are both
  * null.
  *
  * @param node1 First expression
  * @param node2 Second expression
  * @param fail Whether to throw {@link AssertionError} if expressions are not equal
  */
 public static boolean equalDeep(SqlNode node1, SqlNode node2, boolean fail) {
   if (node1 == null) {
     return node2 == null;
   } else if (node2 == null) {
     return false;
   } else {
     return node1.equalsDeep(node2, fail);
   }
 }
Example #12
0
 public boolean equalsDeep(SqlNode node, boolean fail) {
   if (!(node instanceof SqlNodeList)) {
     assert !fail : this + "!=" + node;
     return false;
   }
   SqlNodeList that = (SqlNodeList) node;
   if (this.size() != that.size()) {
     assert !fail : this + "!=" + node;
     return false;
   }
   for (int i = 0; i < list.size(); i++) {
     SqlNode thisChild = list.get(i);
     final SqlNode thatChild = that.list.get(i);
     if (!thisChild.equalsDeep(thatChild, fail)) {
       return false;
     }
   }
   return true;
 }
 public void unparse(SqlWriter writer, SqlNode[] operands, int leftPrec, int rightPrec) {
   assert operands.length >= 2;
   final SqlWriter.Frame frame = writer.startList(SqlWriter.FrameTypeEnum.Simple);
   operands[0].unparse(writer, leftPrec, getLeftPrec());
   final boolean needsSpace = true;
   writer.setNeedWhitespace(needsSpace);
   writer.sep("AS");
   writer.setNeedWhitespace(needsSpace);
   operands[1].unparse(writer, getRightPrec(), rightPrec);
   if (operands.length > 2) {
     final SqlWriter.Frame frame1 = writer.startList(SqlWriter.FrameTypeEnum.Simple, "(", ")");
     for (int i = 2; i < operands.length; i++) {
       SqlNode operand = operands[i];
       writer.sep(",", false);
       operand.unparse(writer, 0, 0);
     }
     writer.endList(frame1);
   }
   writer.endList(frame);
 }
Example #14
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);
        }
    }
  }
  private RelDataType deriveType(
      SqlValidator validator,
      SqlValidatorScope scope,
      SqlCall call,
      boolean convertRowArgToColumnList) {
    final SqlNode[] operands = call.operands;
    RelDataType[] argTypes = new RelDataType[operands.length];

    // Scope for operands. Usually the same as 'scope'.
    final SqlValidatorScope operandScope = scope.getOperandScope(call);

    // Indicate to the validator that we're validating a new function call
    validator.pushFunctionCall();

    try {
      boolean containsRowArg = false;
      for (int i = 0; i < operands.length; ++i) {
        RelDataType nodeType;

        // for row arguments that should be converted to ColumnList
        // types, set the nodeType to a ColumnList type but defer
        // validating the arguments of the row constructor until we know
        // for sure that the row argument maps to a ColumnList type
        if (operands[i].getKind() == SqlKind.ROW && convertRowArgToColumnList) {
          containsRowArg = true;
          RelDataTypeFactory typeFactory = validator.getTypeFactory();
          nodeType = typeFactory.createSqlType(SqlTypeName.COLUMN_LIST);
        } else {
          nodeType = validator.deriveType(operandScope, operands[i]);
        }
        validator.setValidatedNodeType(operands[i], nodeType);
        argTypes[i] = nodeType;
      }

      SqlFunction function =
          SqlUtil.lookupRoutine(
              validator.getOperatorTable(), getNameAsId(), argTypes, getFunctionType());

      // if we have a match on function name and parameter count, but
      // couldn't find a function with  a COLUMN_LIST type, retry, but
      // this time, don't convert the row argument to a COLUMN_LIST type;
      // if we did find a match, go back and revalidate the row operands
      // (corresponding to column references), now that we can set the
      // scope to that of the source cursor referenced by that ColumnList
      // type
      if (containsRowArg) {
        if ((function == null)
            && SqlUtil.matchRoutinesByParameterCount(
                validator.getOperatorTable(), getNameAsId(), argTypes, getFunctionType())) {
          // remove the already validated node types corresponding to
          // row arguments before revalidating
          for (SqlNode operand : operands) {
            if (operand.getKind() == SqlKind.ROW) {
              validator.removeValidatedNodeType(operand);
            }
          }
          return deriveType(validator, scope, call, false);
        } else if (function != null) {
          validator.validateColumnListParams(function, argTypes, operands);
        }
      }

      if (getFunctionType() == SqlFunctionCategory.UserDefinedConstructor) {
        return validator.deriveConstructorType(scope, call, this, function, argTypes);
      }
      if (function == null) {
        validator.handleUnresolvedFunction(call, this, argTypes);
      }

      // REVIEW jvs 25-Mar-2005:  This is, in a sense, expanding
      // identifiers, but we ignore shouldExpandIdentifiers()
      // because otherwise later validation code will
      // choke on the unresolved function.
      call.setOperator(function);
      return function.validateOperands(validator, operandScope, call);
    } finally {
      validator.popFunctionCall();
    }
  }
Example #16
0
 public void validate(SqlValidator validator, SqlValidatorScope scope) {
   for (SqlNode child : list) {
     child.validate(validator, scope);
   }
 }
Example #17
0
 /** Converts an expression "expr" into "expr AS alias". */
 public static SqlNode addAlias(SqlNode expr, String alias) {
   final SqlParserPos pos = expr.getParserPosition();
   final SqlIdentifier id = new SqlIdentifier(alias, pos);
   return SqlStdOperatorTable.AS.createCall(pos, expr, id);
 }