/** * Resolves a multi-part identifier such as "SCHEMA.EMP.EMPNO" to a namespace. The returned * namespace may represent a schema, table, column, etc. * * @pre names.size() > 0 * @post return != null */ public static SqlValidatorNamespace lookup(SqlValidatorScope scope, List<String> names) { Util.pre(names.size() > 0, "names.size() > 0"); SqlValidatorNamespace namespace = null; for (int i = 0; i < names.size(); i++) { String name = names.get(i); if (i == 0) { namespace = scope.resolve(name, null, null); } else { namespace = namespace.lookupChild(name); } } Util.permAssert(namespace != null, "post: namespace != null"); return namespace; }
public RelNode convertSqlToRel(String sql) { Util.pre(sql != null, "sql != null"); final SqlNode sqlQuery; try { sqlQuery = parseQuery(sql); } catch (Exception e) { throw Util.newInternal(e); // todo: better handling } final RelDataTypeFactory typeFactory = getTypeFactory(); final Prepare.CatalogReader catalogReader = createCatalogReader(typeFactory); final SqlValidator validator = createValidator(catalogReader, typeFactory); final SqlToRelConverter converter = createSqlToRelConverter(validator, catalogReader, typeFactory); converter.setTrimUnusedFields(true); final SqlNode validatedQuery = validator.validate(sqlQuery); final RelNode rel = converter.convertQuery(validatedQuery, false, true); Util.post(rel != null, "return != null"); return rel; }
/** Returns whether an array of expressions has any common sub-expressions. */ public static boolean containCommonExprs(RexNode[] exprs, boolean fail) { final ExpressionNormalizer visitor = new ExpressionNormalizer(false); for (int i = 0; i < exprs.length; i++) { try { exprs[i].accept(visitor); } catch (ExpressionNormalizer.SubExprExistsException e) { Util.swallow(e, null); assert !fail; } } return false; }
/** * Replaces the operands of a call. The new operands' types must match the old operands' types. */ public static RexCall replaceOperands(RexCall call, RexNode[] operands) { if (call.operands == operands) { return call; } for (int i = 0; i < operands.length; i++) { RelDataType oldType = call.operands[i].getType(); RelDataType newType = operands[i].getType(); if (!oldType.isNullable() && newType.isNullable()) { throw Util.newInternal("invalid nullability"); } assert (oldType.toString().equals(newType.toString())); } return new RexCall(call.getType(), call.getOperator(), operands); }
/** * Returns whether a given tree contains any {@link org.eigenbase.rex.RexFieldAccess} nodes. * * @param node a RexNode tree */ public static boolean containsFieldAccess(RexNode node) { try { RexVisitor<Void> visitor = new RexVisitorImpl<Void>(true) { public Void visitFieldAccess(RexFieldAccess fieldAccess) { throw new Util.FoundOne(fieldAccess); } }; node.accept(visitor); return false; } catch (Util.FoundOne e) { Util.swallow(e, null); return true; } }
/** * Returns whether a given tree contains any {link RexInputRef} nodes. * * @param node a RexNode tree */ public static boolean containsInputRef(RexNode node) { try { RexVisitor<Void> visitor = new RexVisitorImpl<Void>(true) { public Void visitInputRef(RexInputRef inputRef) { throw new Util.FoundOne(inputRef); } }; node.accept(visitor); return false; } catch (Util.FoundOne e) { Util.swallow(e, null); return true; } }
public static void getSchemaObjectMonikers( SqlValidatorCatalogReader catalogReader, List<String> names, List<SqlMoniker> hints) { // Assume that the last name is 'dummy' or similar. List<String> subNames = Util.skipLast(names); hints.addAll(catalogReader.getAllSchemaObjectNames(subNames)); // If the name has length 0, try prepending the name of the default // schema. So, the empty name would yield a list of tables in the // default schema, as well as a list of schemas from the above code. if (subNames.size() == 0) { hints.addAll( catalogReader.getAllSchemaObjectNames( Collections.singletonList(catalogReader.getSchemaName()))); } }
/** * Returns whether an array of expressions contains a forward reference. That is, if expression #i * contains a {@link RexInputRef} referencing field i or greater. * * @param exprs Array of expressions * @param inputRowType Input row type * @param fail Whether to assert if there is a forward reference * @return Whether there is a forward reference */ public static boolean containForwardRefs( RexNode[] exprs, RelDataType inputRowType, boolean fail) { final ForwardRefFinder visitor = new ForwardRefFinder(inputRowType); for (int i = 0; i < exprs.length; i++) { RexNode expr = exprs[i]; visitor.setLimit(i); // field cannot refer to self or later field try { expr.accept(visitor); } catch (ForwardRefFinder.IllegalForwardRefException e) { Util.swallow(e, null); assert !fail : "illegal forward reference in " + expr; return true; } } return false; }
/** * Returns whether a given node contains a RexCall with a specified operator * * @param operator to look for * @param node a RexNode tree */ public static RexCall findOperatorCall(final SqlOperator operator, RexNode node) { try { RexVisitor<Void> visitor = new RexVisitorImpl<Void>(true) { public Void visitCall(RexCall call) { if (call.getOperator().equals(operator)) { throw new Util.FoundOne(call); } return super.visitCall(call); } }; node.accept(visitor); return null; } catch (Util.FoundOne e) { Util.swallow(e, null); return (RexCall) e.getNode(); } }
/** * 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); } } }
SubExprExistsException(RexNode expr) { Util.discard(expr); }
public String apply(String original, int attempt, int size) { return Util.first(original, "$f") + size; }
public String apply(String original, int attempt, int size) { return Util.first(original, "EXPR$") + attempt; }
public String getSignatureTemplate(int operandsCount) { Util.discard(operandsCount); return "{0}({1} FROM {2})"; }
/** * Reduces a list of operators and arguments according to the rules of precedence and * associativity. Returns the ordinal of the node which replaced the expression. * * <p>The default implementation throws {@link UnsupportedOperationException}. * * @param ordinal indicating the ordinal of the current operator in the list on which a possible * reduction can be made * @param list List of alternating {@link org.eigenbase.sql.parser.SqlParserUtil.ToTreeListItem} * and {@link SqlNode} * @return ordinal of the node which replaced the expression */ public int reduceExpr(int ordinal, List<Object> list) { throw Util.needToImplement(this); }
public String getSignatureTemplate(final int operandsCount) { Util.discard(operandsCount); return "{1} {0} {2} AND {3}"; }