예제 #1
0
 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);
 }
예제 #2
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()]));
 }
예제 #3
0
 public RexNode toRex(Expression expression) {
   switch (expression.getNodeType()) {
     case MemberAccess:
       return rexBuilder.makeFieldAccess(
           toRex(((MemberExpression) expression).expression),
           ((MemberExpression) expression).field.getName());
     case GreaterThan:
       return binary(expression, SqlStdOperatorTable.greaterThanOperator);
     case LessThan:
       return binary(expression, SqlStdOperatorTable.lessThanOperator);
     case Parameter:
       return parameter((ParameterExpression) expression);
     case Call:
       MethodCallExpression call = (MethodCallExpression) expression;
       SqlOperator operator = RexToLixTranslator.JAVA_TO_SQL_METHOD_MAP.get(call.method);
       if (operator != null) {
         return rexBuilder.makeCall(
             operator,
             toRex(
                 Expressions.<Expression>list()
                     .appendIfNotNull(call.targetExpression)
                     .appendAll(call.expressions)));
       }
       throw new RuntimeException("Could translate call to method " + call.method);
     case Constant:
       final ConstantExpression constant = (ConstantExpression) expression;
       Object value = constant.value;
       if (value instanceof Number) {
         Number number = (Number) value;
         if (value instanceof Double || value instanceof Float) {
           return rexBuilder.makeApproxLiteral(BigDecimal.valueOf(number.doubleValue()));
         } else if (value instanceof BigDecimal) {
           return rexBuilder.makeExactLiteral((BigDecimal) value);
         } else {
           return rexBuilder.makeExactLiteral(BigDecimal.valueOf(number.longValue()));
         }
       } else if (value instanceof Boolean) {
         return rexBuilder.makeLiteral((Boolean) value);
       } else {
         return rexBuilder.makeLiteral(constant.toString());
       }
     default:
       throw new UnsupportedOperationException(
           "unknown expression type " + expression.getNodeType() + " " + expression);
   }
 }
예제 #4
0
 /**
  * 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(org.eigenbase.sql.SqlNodeList)}, {@link
  * Builder#setWhere(org.eigenbase.sql.SqlNode)} etc. call {@link
  * Builder#result(org.eigenbase.sql.SqlNode, java.util.Collection, org.eigenbase.rel.RelNode)}
  * 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(JdbcRel 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.addAll(Arrays.asList(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 {
     newContext = new AliasContext(aliases, aliases.size() > 1);
   }
   return new Builder(rel, clauseList, select, newContext);
 }
예제 #5
0
 /**
  * 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);
 }
예제 #6
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);
   }
 }