public SqlValidatorScope getWithScope(SqlNode withItem) { assert withItem.getKind() == SqlKind.WITH_ITEM; return scopes.get(withItem); }
private boolean shouldCheckForRollUp(SqlNode from) { if (from != null) { SqlKind kind = stripAs(from).getKind(); return kind != SqlKind.VALUES && kind != SqlKind.SELECT; } return false; }
private static SqlNode stripOver(SqlNode node) { switch (node.getKind()) { case OVER: return ((SqlCall) node).getOperandList().get(0); default: return node; } }
private SqlWindow getWindowInOver(SqlNode over) { if (over.getKind() == SqlKind.OVER) { SqlNode window = ((SqlCall) over).getOperandList().get(1); if (window instanceof SqlWindow) { return (SqlWindow) window; } // SqlIdentifier, gets validated elsewhere return null; } return null; }
private static boolean isLateral(SqlNode node) { switch (node.getKind()) { case LATERAL: case UNNEST: // Per SQL std, UNNEST is implicitly LATERAL. return true; case AS: return isLateral(((SqlCall) node).operand(0)); default: return false; } }
private SqlNode stripDot(SqlNode node) { if (node != null && node.getKind() == SqlKind.DOT) { return stripDot(((SqlCall) node).operand(0)); } return node; }
/** Returns the alias of a "expr AS alias" expression. */ private static String alias(SqlNode item) { assert item instanceof SqlCall; assert item.getKind() == SqlKind.AS; final SqlIdentifier identifier = ((SqlCall) item).operand(1); return identifier.getSimple(); }
public SqlValidatorNamespace getNamespace(SqlNode node) { switch (node.getKind()) { case AS: // AS has a namespace if it has a column list 'AS t (c1, c2, ...)' final SqlValidatorNamespace ns = namespaces.get(node); if (ns != null) { return ns; } // fall through case OVER: case COLLECTION_TABLE: case ORDER_BY: case TABLESAMPLE: return getNamespace(((SqlCall) node).operand(0)); default: return namespaces.get(node); } }
/** Returns whether a query uses {@code DEFAULT} to populate a given * column. */ private boolean isValuesWithDefault(SqlNode source, int column) { switch (source.getKind()) { case VALUES: for (SqlNode operand : ((SqlCall) source).getOperandList()) { if (!isRowWithDefault(operand, column)) { return false; } } return true; } return false; }
@Override public SqlRexConvertlet get(SqlCall call) { if (call.getKind() == SqlKind.EXTRACT && call.getOperandList().get(1).getKind() != SqlKind.LITERAL) { // Avoid using the standard convertlet for EXTRACT(TIMEUNIT FROM col), since we want to handle it directly // in ExtractOperationConversion. return BYPASS_CONVERTLET; } else { final SqlRexConvertlet convertlet = table.get(call.getOperator()); return convertlet != null ? convertlet : StandardConvertletTable.INSTANCE.get(call); } }
private void validateNodeFeature(SqlNode node) { switch (node.getKind()) { case MULTISET_VALUE_CONSTRUCTOR: validateFeature(RESOURCE.sQLFeature_S271(), node.getParserPosition()); break; } }
private boolean isSortCompatible(SelectScope scope, SqlNode node, boolean descending) { switch (node.getKind()) { case DESCENDING: return isSortCompatible(scope, ((SqlCall) node).getOperandList().get(0), true); } final SqlMonotonicity monotonicity = scope.getMonotonicity(node); switch (monotonicity) { case INCREASING: case STRICTLY_INCREASING: return !descending; case DECREASING: case STRICTLY_DECREASING: return descending; default: return false; } }
/** Return the intended modality of a SELECT or set-op. */ private SqlModality deduceModality(SqlNode query) { if (query instanceof SqlSelect) { SqlSelect select = (SqlSelect) query; return select.getModifierNode(SqlSelectKeyword.STREAM) != null ? SqlModality.STREAM : SqlModality.RELATION; } else if (query.getKind() == SqlKind.VALUES) { return SqlModality.RELATION; } else { assert query.isA(SqlKind.SET_QUERY); final SqlCall call = (SqlCall) query; return deduceModality(call.getOperandList().get(0)); } }
private void validateGroupItem(SqlValidatorScope groupScope, AggregatingSelectScope aggregatingScope, SqlNode groupItem) { switch (groupItem.getKind()) { case GROUPING_SETS: case ROLLUP: case CUBE: validateGroupingSets(groupScope, aggregatingScope, (SqlCall) groupItem); break; default: if (groupItem instanceof SqlNodeList) { break; } final RelDataType type = deriveType(groupScope, groupItem); setValidatedNodeType(groupItem, type); } }
private SqlNode navigationInMeasure(SqlNode node, boolean allRows) { final Set<String> prefix = node.accept(new PatternValidator(true)); Util.discard(prefix); final List<SqlNode> ops = ((SqlCall) node).getOperandList(); final SqlOperator defaultOp = allRows ? SqlStdOperatorTable.RUNNING : SqlStdOperatorTable.FINAL; final SqlNode op0 = ops.get(0); if (!isRunningOrFinal(op0.getKind()) || !allRows && op0.getKind() == SqlKind.RUNNING) { SqlNode newNode = defaultOp.createCall(SqlParserPos.ZERO, op0); node = SqlStdOperatorTable.AS.createCall(SqlParserPos.ZERO, newNode, ops.get(1)); } node = new NavigationExpander().go(node); return node; }
/** * Validates an item in the ORDER BY clause of a SELECT statement. * * @param select Select statement * @param orderItem ORDER BY clause item */ private void validateOrderItem(SqlSelect select, SqlNode orderItem) { switch (orderItem.getKind()) { case DESCENDING: validateFeature(RESOURCE.sQLConformance_OrderByDesc(), orderItem.getParserPosition()); validateOrderItem(select, ((SqlCall) orderItem).operand(0)); return; } final SqlValidatorScope orderScope = getOrderScope(select); validateExpr(orderItem, orderScope); }
public PlannerResult plan(final String sql) throws SqlParseException, ValidationException, RelConversionException { SqlExplain explain = null; SqlNode parsed = planner.parse(sql); if (parsed.getKind() == SqlKind.EXPLAIN) { explain = (SqlExplain) parsed; parsed = explain.getExplicandum(); } final SqlNode validated = planner.validate(parsed); final RelRoot root = planner.rel(validated); try { return planWithDruidConvention(explain, root); } catch (RelOptPlanner.CannotPlanException e) { // Try again with BINDABLE convention. Used for querying Values, metadata tables, and fallback. try { return planWithBindableConvention(explain, root); } catch (Exception e2) { e.addSuppressed(e2); throw e; } } }
private void checkRollUp(SqlNode grandParent, SqlNode parent, SqlNode current, SqlValidatorScope scope, String optionalClause) { current = stripAs(current); if (current instanceof SqlCall && !(current instanceof SqlSelect)) { // Validate OVER separately checkRollUpInWindow(getWindowInOver(current), scope); current = stripOver(current); List<SqlNode> children = ((SqlCall) stripDot(current)).getOperandList(); for (SqlNode child : children) { checkRollUp(parent, current, child, scope, optionalClause); } } else if (current instanceof SqlIdentifier) { SqlIdentifier id = (SqlIdentifier) current; if (!id.isStar() && isRolledUpColumn(id, scope)) { if (!isAggregation(parent.getKind()) || !isRolledUpColumnAllowedInAgg(id, scope, (SqlCall) parent, grandParent)) { String context = optionalClause != null ? optionalClause : parent.getKind().toString(); throw newValidationError(id, RESOURCE.rolledUpNotAllowed(deriveAlias(id, 0), context)); } } } }
/** Validates that a query can deliver the modality it promises. Only called * on the top-most SELECT or set operator in the tree. */ private void validateModality(SqlNode query) { final SqlModality modality = deduceModality(query); if (query instanceof SqlSelect) { final SqlSelect select = (SqlSelect) query; validateModality(select, modality, true); } else if (query.getKind() == SqlKind.VALUES) { switch (modality) { case STREAM: throw newValidationError(query, Static.RESOURCE.cannotStreamValues()); } } else { assert query.isA(SqlKind.SET_QUERY); final SqlCall call = (SqlCall) query; for (SqlNode operand : call.getOperandList()) { if (deduceModality(operand) != modality) { throw newValidationError(operand, Static.RESOURCE.streamSetOpInconsistentInputs()); } validateModality(operand); } } }