public SqlRexConvertlet get(SqlCall call) {
    SqlRexConvertlet convertlet;
    final SqlOperator op = call.getOperator();

    // Is there a convertlet for this operator
    // (e.g. SqlStdOperatorTable.plusOperator)?
    convertlet = (SqlRexConvertlet) map.get(op);
    if (convertlet != null) {
      return convertlet;
    }

    // Is there a convertlet for this class of operator
    // (e.g. SqlBinaryOperator)?
    Class<? extends Object> clazz = op.getClass();
    while (clazz != null) {
      convertlet = (SqlRexConvertlet) map.get(clazz);
      if (convertlet != null) {
        return convertlet;
      }
      clazz = clazz.getSuperclass();
    }

    // Is there a convertlet for this class of expression
    // (e.g. SqlCall)?
    clazz = call.getClass();
    while (clazz != null) {
      convertlet = (SqlRexConvertlet) map.get(clazz);
      if (convertlet != null) {
        return convertlet;
      }
      clazz = clazz.getSuperclass();
    }
    return null;
  }
예제 #2
0
 public Void visit(SqlCall call) {
   final SqlOperator operator = call.getOperator();
   if (operator.isAggregator()) {
     throw new Util.FoundOne(call);
   }
   // User-defined function may not be resolved yet.
   if (operator instanceof SqlFunction
       && ((SqlFunction) operator).getFunctionType()
           == SqlFunctionCategory.USER_DEFINED_FUNCTION) {
     final List<SqlOperator> list = Lists.newArrayList();
     opTab.lookupOperatorOverloads(
         ((SqlFunction) operator).getSqlIdentifier(),
         SqlFunctionCategory.USER_DEFINED_FUNCTION,
         SqlSyntax.FUNCTION,
         list);
     for (SqlOperator sqlOperator : list) {
       if (sqlOperator.isAggregator()) {
         throw new Util.FoundOne(call);
       }
     }
   }
   if (call.isA(SqlKind.QUERY)) {
     // don't traverse into queries
     return null;
   }
   if (call.getKind() == SqlKind.OVER) {
     if (over) {
       throw new Util.FoundOne(call);
     } else {
       // an aggregate function over a window is not an aggregate!
       return null;
     }
   }
   return super.visit(call);
 }
예제 #3
0
 private SqlNode createLeftCall(SqlOperator op, List<SqlNode> nodeList) {
   if (nodeList.size() == 2) {
     return op.createCall(new SqlNodeList(nodeList, POS));
   }
   final List<SqlNode> butLast = Util.skipLast(nodeList);
   final SqlNode last = nodeList.get(nodeList.size() - 1);
   final SqlNode call = createLeftCall(op, butLast);
   return op.createCall(new SqlNodeList(ImmutableList.of(call, last), POS));
 }
예제 #4
0
 /** Converts a call to an aggregate function to an expression. */
 public SqlNode toSql(AggregateCall aggCall) {
   SqlOperator op = (SqlAggFunction) aggCall.getAggregation();
   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()]));
 }
  public void validateCall(
      SqlCall call,
      SqlValidator validator,
      SqlValidatorScope scope,
      SqlValidatorScope operandScope) {
    // This implementation looks for the quantifier keywords DISTINCT or
    // ALL as the first operand in the list.  If found then the literal is
    // not called to validate itself.  Further the function is checked to
    // make sure that a quantifier is valid for that particular function.
    //
    // If the first operand does not appear to be a quantifier then the
    // parent ValidateCall is invoked to do normal function validation.

    super.validateCall(call, validator, scope, operandScope);
    validateQuantifier(validator, call);
  }
예제 #6
0
 public void unparse(
     SqlWriter writer, SqlOperator operator, SqlCall call, int leftPrec, int rightPrec) {
   assert call.operandCount() == 1;
   call.operand(0).unparse(writer, operator.getLeftPrec(), operator.getRightPrec());
   writer.keyword(operator.getName());
 }
예제 #7
0
 /** Converts an expression from {@link RexNode} to {@link SqlNode} format. */
 SqlNode toSql(RexProgram program, RexNode rex) {
   if (rex instanceof RexLocalRef) {
     final int index = ((RexLocalRef) rex).getIndex();
     return toSql(program, program.getExprList().get(index));
   } else if (rex instanceof RexInputRef) {
     return field(((RexInputRef) rex).getIndex());
   } else if (rex instanceof RexLiteral) {
     final RexLiteral literal = (RexLiteral) rex;
     switch (literal.getTypeName().getFamily()) {
       case CHARACTER:
         return SqlLiteral.createCharString((String) literal.getValue2(), POS);
       case NUMERIC:
       case EXACT_NUMERIC:
         return SqlLiteral.createExactNumeric(literal.getValue().toString(), POS);
       case APPROXIMATE_NUMERIC:
         return SqlLiteral.createApproxNumeric(literal.getValue().toString(), POS);
       case BOOLEAN:
         return SqlLiteral.createBoolean((Boolean) literal.getValue(), POS);
       case DATE:
         return SqlLiteral.createDate((Calendar) literal.getValue(), POS);
       case TIME:
         return SqlLiteral.createTime(
             (Calendar) literal.getValue(), literal.getType().getPrecision(), POS);
       case TIMESTAMP:
         return SqlLiteral.createTimestamp(
             (Calendar) literal.getValue(), literal.getType().getPrecision(), POS);
       case ANY:
         switch (literal.getTypeName()) {
           case NULL:
             return SqlLiteral.createNull(POS);
             // fall through
         }
       default:
         throw new AssertionError(literal + ": " + literal.getTypeName());
     }
   } else if (rex instanceof RexCall) {
     final RexCall call = (RexCall) rex;
     final SqlOperator op = call.getOperator();
     final List<SqlNode> nodeList = toSql(program, call.getOperands());
     if (op == SqlStdOperatorTable.CAST) {
       RelDataType type = call.getType();
       if (type.getSqlTypeName() == SqlTypeName.VARCHAR
           && dialect.getDatabaseProduct() == SqlDialect.DatabaseProduct.MYSQL) {
         // MySQL doesn't have a VARCHAR type, only CHAR.
         nodeList.add(
             new SqlDataTypeSpec(
                 new SqlIdentifier("CHAR", POS), type.getPrecision(), -1, null, null, POS));
       } else {
         nodeList.add(toSql(type));
       }
     }
     if (op == SqlStdOperatorTable.CASE) {
       final SqlNode valueNode;
       final List<SqlNode> whenList = Expressions.list();
       final List<SqlNode> thenList = Expressions.list();
       final SqlNode elseNode;
       if (nodeList.size() % 2 == 0) {
         // switched:
         //   "case x when v1 then t1 when v2 then t2 ... else e end"
         valueNode = nodeList.get(0);
         for (int i = 1; i < nodeList.size() - 1; i += 2) {
           whenList.add(nodeList.get(i));
           thenList.add(nodeList.get(i + 1));
         }
       } else {
         // other: "case when w1 then t1 when w2 then t2 ... else e end"
         valueNode = null;
         for (int i = 0; i < nodeList.size() - 1; i += 2) {
           whenList.add(nodeList.get(i));
           thenList.add(nodeList.get(i + 1));
         }
       }
       elseNode = nodeList.get(nodeList.size() - 1);
       return op.createCall(
           POS,
           valueNode,
           new SqlNodeList(whenList, POS),
           new SqlNodeList(thenList, POS),
           elseNode);
     }
     if (op instanceof SqlBinaryOperator && nodeList.size() > 2) {
       // In RexNode trees, OR and AND have any number of children;
       // SqlCall requires exactly 2. So, convert to a left-deep binary tree.
       return createLeftCall(op, nodeList);
     }
     return op.createCall(new SqlNodeList(nodeList, POS));
   } else {
     throw new AssertionError(rex);
   }
 }