@Override public Void visit(SqlCall call) { for (int i = 0; i < call.getOperandList().size(); i++) { call.getOperandList().get(i).accept(this); } return null; }
private boolean isRowWithDefault(SqlNode operand, int column) { switch (operand.getKind()) { case ROW: final SqlCall row = (SqlCall) operand; return row.getOperandList().size() >= column && row.getOperandList().get(column).getKind() == SqlKind.DEFAULT; } return false; }
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 SqlNode stripOver(SqlNode node) { switch (node.getKind()) { case OVER: return ((SqlCall) node).getOperandList().get(0); default: return node; } }
private void validateGroupingSets(SqlValidatorScope groupScope, AggregatingSelectScope aggregatingScope, SqlCall groupItem) { for (SqlNode node : groupItem.getOperandList()) { validateGroupItem(groupScope, aggregatingScope, node); } }
@Override public Map<Integer, SqlNode> getParamNodes() { Map<Integer, SqlNode> sqlNodes = new HashMap<>(); List<SqlNode> sqlNodeList = sqlCall.getOperandList(); SqlNode firstParam = ((SqlCall) sqlNodeList.get(0)).getOperandList().get(0); SqlNode secondParam = (SqlCall) sqlNodeList.get(1); sqlNodes.put(0, firstParam); sqlNodes.put(1, secondParam); return sqlNodes; } };
private SqlNode getParamNode(List<Integer> path, SqlNode sqlNode, int level) { if (level == path.size() - 1) { return ((SqlCall) sqlNode).getOperandList().get(path.get(level)); } else { return getParamNode(path, ((SqlCall) sqlNode).getOperandList().get(path.get(level)), ++level); } }
/** 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 SqlNode visit(SqlCall call) { SqlKind kind = call.getKind(); if (isLogicalNavigation(kind) || isAggregation(kind) || isRunningOrFinal(kind)) { return call; } switch (kind) { case PREV: final List<SqlNode> operands = call.getOperandList(); if (operands.get(0) instanceof SqlIdentifier) { String name = ((SqlIdentifier) operands.get(0)).names.get(0); return name.equals(alpha) ? call : SqlStdOperatorTable.LAST.createCall(SqlParserPos.ZERO, operands); } } return super.visit(call); }
@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 genParamPath(SqlNode sqlNode, List<Integer> path) { if (sqlNode instanceof SqlIdentifier) { int paramIdx = ParamNodeParser.parseParamIdx(sqlNode.toString()); if (paramIdx >= 0 && path.size() > 0) { paramPath.put(paramIdx, path); } } else if (sqlNode instanceof SqlCall) { List<SqlNode> operands = ((SqlCall) sqlNode).getOperandList(); for (int i = 0; i < operands.size(); i++) { List<Integer> copiedPath = Lists.newArrayList(path); copiedPath.add(i); genParamPath(operands.get(i), copiedPath); } } }
SqlCall values, SqlValidatorScope scope) { final List<SqlNode> rows = values.getOperandList(); assert rows.size() >= 1; final List<RelDataType> rowTypes = new ArrayList<>(); for (Ord<SqlNode> column : Ord.zip(rowConstructor.getOperandList())) { final String alias = deriveAlias(column.e, column.i); aliasList.add(alias);
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; } }
private void registerSetop( SqlValidatorScope parentScope, SqlValidatorScope usingScope, SqlNode node, SqlNode enclosingNode, String alias, boolean forceNullable) { SqlCall call = (SqlCall) node; final SetopNamespace setopNamespace = createSetopNamespace(call, enclosingNode); registerNamespace(usingScope, alias, setopNamespace, forceNullable); // A setop is in the same scope as its parent. scopes.put(call, parentScope); for (SqlNode operand : call.getOperandList()) { registerQuery( parentScope, null, operand, operand, null, 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 SqlValidatorNamespace getNamespace(SqlNode node, SqlValidatorScope scope) { if (node instanceof SqlIdentifier && scope instanceof DelegatingScope) { final SqlIdentifier id = (SqlIdentifier) node; final DelegatingScope idScope = (DelegatingScope) ((DelegatingScope) scope).getParent(); return getNamespace(id, idScope); } else if (node instanceof SqlCall) { // Handle extended identifiers. final SqlCall call = (SqlCall) node; switch (call.getOperator().getKind()) { case EXTEND: final SqlIdentifier id = (SqlIdentifier) call.getOperandList().get(0); final DelegatingScope idScope = (DelegatingScope) scope; return getNamespace(id, idScope); case AS: final SqlNode nested = call.getOperandList().get(0); switch (nested.getKind()) { case EXTEND: return getNamespace(nested, scope); } break; } } return getNamespace(node); }
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 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); } } }
public void validateQuery(SqlNode node, SqlValidatorScope scope, RelDataType targetRowType) { final SqlValidatorNamespace ns = getNamespace(node, scope); if (node.getKind() == SqlKind.TABLESAMPLE) { List<SqlNode> operands = ((SqlCall) node).getOperandList(); SqlSampleSpec sampleSpec = SqlLiteral.sampleValue(operands.get(1)); if (sampleSpec instanceof SqlSampleSpec.SqlTableSampleSpec) { validateFeature(RESOURCE.sQLFeature_T613(), node.getParserPosition()); } else if (sampleSpec instanceof SqlSampleSpec.SqlSubstitutionSampleSpec) { validateFeature(RESOURCE.sQLFeatureExt_T613_Substitution(), node.getParserPosition()); } } validateNamespace(ns, targetRowType); switch (node.getKind()) { case EXTEND: // Until we have a dedicated namespace for EXTEND deriveType(scope, node); } if (node == top) { validateModality(node); } validateAccess( node, ns.getTable(), SqlAccessEnum.SELECT); }
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)); } } } }