예제 #1
0
  private List<Expression> translate(List<Statement> list, List<RexLocalRef> rexList) {
    // First pass. Count how many times each sub-expression is used.
    this.list = null;
    for (RexNode rexExpr : rexList) {
      translate(rexExpr);
    }

    // Mark expressions as inline if they are not used more than once.
    for (Map.Entry<RexNode, Slot> entry : map.entrySet()) {
      if (entry.getValue().count < 2 || entry.getKey() instanceof RexLiteral) {
        inlineRexSet.add(entry.getKey());
      }
    }

    // Second pass. When translating each expression, if it is used more
    // than once, the first time it is encountered, add a declaration to the
    // list and set its usage count to 0.
    this.list = list;
    this.map.clear();
    List<Expression> translateds = new ArrayList<Expression>();
    for (RexNode rexExpr : rexList) {
      translateds.add(translate(rexExpr));
    }
    return translateds;
  }
예제 #2
0
 public RexNode parameter(ParameterExpression param) {
   int i = parameterList.indexOf(param);
   if (i >= 0) {
     return values.get(i);
   }
   throw new RuntimeException("unknown parameter " + param);
 }
예제 #3
0
 private List<Expression> translateList(List<RexNode> operandList) {
   final List<Expression> list = new ArrayList<Expression>();
   for (RexNode rex : operandList) {
     list.add(translate(rex));
   }
   return list;
 }
예제 #4
0
 public List<RexNode> toRexList(BlockExpression expression) {
   final List<Expression> simpleList = simpleList(expression);
   final List<RexNode> list = new ArrayList<RexNode>();
   for (Expression expression1 : simpleList) {
     list.add(toRex(expression1));
   }
   return list;
 }
예제 #5
0
 public static Expression translateCondition(
     List<Expression> inputs,
     RexProgram program,
     JavaTypeFactory typeFactory,
     List<Statement> list) {
   List<Expression> x =
       new RexToLixTranslator(program, typeFactory, inputs)
           .translate(list, Collections.singletonList(program.getCondition()));
   assert x.size() == 1;
   return x.get(0);
 }
예제 #6
0
 /**
  * Gets the expression for an input and counts it.
  *
  * @param index Input ordinal
  * @return Expression to which an input should be translated
  */
 private Expression getInput(int index) {
   Slot slot = inputSlots.get(index);
   if (list == null) {
     slot.count++;
   } else {
     if (slot.count > 1 && slot.parameterExpression == null) {
       slot.parameterExpression = Expressions.parameter(slot.expression.type, "current" + index);
       list.add(Expressions.declare(Modifier.FINAL, slot.parameterExpression, slot.expression));
     }
   }
   return slot.parameterExpression != null ? slot.parameterExpression : slot.expression;
 }
예제 #7
0
 public List<SqlOperator> lookupOperatorOverloads(
     SqlIdentifier opName, SqlFunctionCategory category, SqlSyntax syntax) {
   if (syntax != SqlSyntax.Function) {
     return Collections.emptyList();
   }
   // FIXME: ignoring prefix of opName
   String name = opName.names[opName.names.length - 1];
   List<TableFunction> tableFunctions = rootSchema.getTableFunctions(name);
   if (tableFunctions.isEmpty()) {
     return Collections.emptyList();
   }
   return toOps(name, tableFunctions);
 }
예제 #8
0
 /** Returns the path of a schema, appending the name of a table if not null. */
 public static List<String> path(Schema schema, String name) {
   final List<String> list = new ArrayList<String>();
   if (name != null) {
     list.add(name);
   }
   for (Schema s = schema; s != null; s = s.getParentSchema()) {
     if (s.getParentSchema() != null || !s.getName().equals("")) {
       // Omit the root schema's name from the path if it's the empty string,
       // which it usually is.
       list.add(s.getName());
     }
   }
   return ImmutableList.copyOf(Lists.reverse(list));
 }
예제 #9
0
 private RexToLixTranslator(
     RexProgram program, JavaTypeFactory typeFactory, List<Expression> inputs) {
   this.program = program;
   this.typeFactory = typeFactory;
   for (Expression input : inputs) {
     inputSlots.add(new Slot(null, input));
   }
 }
예제 #10
0
  public static TableFunction methodMember(final Method method, final JavaTypeFactory typeFactory) {
    final List<Parameter> parameters = new ArrayList<Parameter>();
    for (final Class<?> parameterType : method.getParameterTypes()) {
      parameters.add(
          new Parameter() {
            final int ordinal = parameters.size();
            final RelDataType type = typeFactory.createType(parameterType);

            public int getOrdinal() {
              return ordinal;
            }

            public String getName() {
              return "a" + ordinal;
            }

            public RelDataType getType(RelDataTypeFactory typeFactory) {
              return type;
            }
          });
    }
    return new TableFunction() {
      public List<Parameter> getParameters() {
        return parameters;
      }

      public Table apply(List<Object> arguments) {
        try {
          //noinspection unchecked
          return (Table) method.invoke(null, arguments.toArray());
        } catch (IllegalAccessException e) {
          throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
          throw new RuntimeException(e);
        }
      }

      public RelDataType getRowType(RelDataTypeFactory typeFactory) {
        final Class<?> returnType = method.getReturnType();
        return ((JavaTypeFactory) typeFactory).createType(returnType);
      }
    };
  }
예제 #11
0
  private Expression translate0(RexNode expr) {
    if (expr instanceof RexInputRef) {
      // TODO: multiple inputs, e.g. joins
      final Expression input = getInput(0);
      final int index = ((RexInputRef) expr).getIndex();
      final List<RelDataTypeField> fields = program.getInputRowType().getFieldList();
      final RelDataTypeField field = fields.get(index);
      if (fields.size() == 1) {
        return input;
      } else if (input.getType() == Object[].class) {
        return Expressions.convert_(
            Expressions.arrayIndex(input, Expressions.constant(field.getIndex())),
            Types.box(JavaRules.EnumUtil.javaClass(typeFactory, field.getType())));
      } else {
        return Expressions.field(input, field.getName());
      }
    }
    if (expr instanceof RexLocalRef) {
      return translate(program.getExprList().get(((RexLocalRef) expr).getIndex()));
    }
    if (expr instanceof RexLiteral) {
      return Expressions.constant(
          ((RexLiteral) expr).getValue(), typeFactory.getJavaClass(expr.getType()));
    }
    if (expr instanceof RexCall) {
      final RexCall call = (RexCall) expr;
      final SqlOperator operator = call.getOperator();
      final ExpressionType expressionType = SQL_TO_LINQ_OPERATOR_MAP.get(operator);
      if (expressionType != null) {
        switch (operator.getSyntax()) {
          case Binary:
            return Expressions.makeBinary(
                expressionType, translate(call.getOperands()[0]), translate(call.getOperands()[1]));
          case Postfix:
          case Prefix:
            return Expressions.makeUnary(expressionType, translate(call.getOperands()[0]));
          default:
            throw new RuntimeException("unknown syntax " + operator.getSyntax());
        }
      }

      Method method = SQL_OP_TO_JAVA_METHOD_MAP.get(operator);
      if (method != null) {
        List<Expression> exprs = translateList(Arrays.asList(call.operands));
        return !Modifier.isStatic(method.getModifiers())
            ? Expressions.call(exprs.get(0), method, exprs.subList(1, exprs.size()))
            : Expressions.call(method, exprs);
      }

      switch (expr.getKind()) {
        default:
          throw new RuntimeException("cannot translate expression " + expr);
      }
    }
    throw new RuntimeException("cannot translate expression " + expr);
  }
예제 #12
0
 public static OptiqSchema.TableFunctionEntry resolve(
     RelDataTypeFactory typeFactory,
     String name,
     Collection<OptiqSchema.TableFunctionEntry> tableFunctions,
     List<RelDataType> argumentTypes) {
   final List<OptiqSchema.TableFunctionEntry> matches =
       new ArrayList<OptiqSchema.TableFunctionEntry>();
   for (OptiqSchema.TableFunctionEntry member : tableFunctions) {
     if (matches(typeFactory, member.getTableFunction(), argumentTypes)) {
       matches.add(member);
     }
   }
   switch (matches.size()) {
     case 0:
       return null;
     case 1:
       return matches.get(0);
     default:
       throw new RuntimeException(
           "More than one match for " + name + " with arguments " + argumentTypes);
   }
 }
예제 #13
0
 private SqlOperator toOp(String name, TableFunction fun) {
   List<RelDataType> argTypes = new ArrayList<RelDataType>();
   List<SqlTypeFamily> typeFamilies = new ArrayList<SqlTypeFamily>();
   Parameter p;
   for (net.hydromatic.optiq.Parameter o :
       (List<net.hydromatic.optiq.Parameter>) fun.getParameters()) {
     argTypes.add(o.getType());
     typeFamilies.add(SqlTypeFamily.ANY);
   }
   return new SqlFunction(
       name,
       SqlKind.OTHER_FUNCTION,
       new ExplicitReturnTypeInference(typeFactory.createType(fun.getElementType())),
       new ExplicitOperandTypeInference(argTypes.toArray(new RelDataType[argTypes.size()])),
       new FamilyOperandTypeChecker(
           typeFamilies.toArray(new SqlTypeFamily[typeFamilies.size()])),
       null);
 }
예제 #14
0
 private Expression translate(RexNode expr) {
   Slot slot = map.get(expr);
   if (slot == null) {
     Expression expression = translate0(expr);
     assert expression != null;
     final ParameterExpression parameter;
     if (!inlineRexSet.contains(expr) && !(expr instanceof RexLocalRef)) {
       parameter = Expressions.parameter(expression.getType(), "v" + map.size());
     } else {
       parameter = null;
     }
     slot = new Slot(parameter, expression);
     if (parameter != null && list != null) {
       list.add(Expressions.declare(Modifier.FINAL, slot.parameterExpression, slot.expression));
     }
     map.put(expr, slot);
   }
   slot.count++;
   return slot.parameterExpression != null ? slot.parameterExpression : slot.expression;
 }
예제 #15
0
 private static boolean matches(
     RelDataTypeFactory typeFactory, TableFunction member, List<RelDataType> argumentTypes) {
   List<Parameter> parameters = member.getParameters();
   if (parameters.size() != argumentTypes.size()) {
     return false;
   }
   for (int i = 0; i < argumentTypes.size(); i++) {
     RelDataType argumentType = argumentTypes.get(i);
     Parameter parameter = parameters.get(i);
     if (!canConvert(argumentType, parameter.getType(typeFactory))) {
       return false;
     }
   }
   return true;
 }
예제 #16
0
  <T> PrepareResult<T> prepare_(
      Context context, String sql, Queryable<T> queryable, Type elementType) {
    final JavaTypeFactory typeFactory = context.getTypeFactory();
    OptiqCatalogReader catalogReader = new OptiqCatalogReader(context.getRootSchema(), typeFactory);
    final OptiqPreparingStmt preparingStmt =
        new OptiqPreparingStmt(catalogReader, typeFactory, context.getRootSchema());
    preparingStmt.setResultCallingConvention(CallingConvention.ENUMERABLE);

    final RelDataType x;
    final PreparedResult preparedResult;
    if (sql != null) {
      assert queryable == null;
      SqlParser parser = new SqlParser(sql);
      SqlNode sqlNode;
      try {
        sqlNode = parser.parseQuery();
      } catch (SqlParseException e) {
        throw new RuntimeException("parse failed", e);
      }
      final Schema rootSchema = context.getRootSchema();
      SqlValidator validator =
          new SqlValidatorImpl(
              new ChainedSqlOperatorTable(
                  Arrays.<SqlOperatorTable>asList(
                      SqlStdOperatorTable.instance(),
                      new MySqlOperatorTable(rootSchema, typeFactory))),
              catalogReader,
              typeFactory,
              SqlConformance.Default) {};
      preparedResult = preparingStmt.prepareSql(sqlNode, Object.class, validator, true);
      x = validator.getValidatedNodeType(sqlNode);
    } else {
      assert queryable != null;
      x = context.getTypeFactory().createType(elementType);
      preparedResult = preparingStmt.prepareQueryable(queryable, x);
    }

    // TODO: parameters
    final List<Parameter> parameters = Collections.emptyList();
    // TODO: column meta data
    final List<ColumnMetaData> columns = new ArrayList<ColumnMetaData>();
    RelDataType jdbcType = makeStruct(typeFactory, x);
    for (RelDataTypeField field : jdbcType.getFields()) {
      RelDataType type = field.getType();
      SqlTypeName sqlTypeName = type.getSqlTypeName();
      columns.add(
          new ColumnMetaData(
              columns.size(),
              false,
              true,
              false,
              false,
              type.isNullable() ? 1 : 0,
              true,
              0,
              field.getName(),
              field.getName(),
              null,
              sqlTypeName.allowsPrec() && false ? type.getPrecision() : -1,
              sqlTypeName.allowsScale() ? type.getScale() : -1,
              null,
              null,
              sqlTypeName.getJdbcOrdinal(),
              sqlTypeName.getName(),
              true,
              false,
              false,
              null));
    }
    return new PrepareResult<T>(sql, parameters, columns, (Enumerable<T>) preparedResult.execute());
  }