/** Throws a validation error if a DISTINCT or ALL quantifier is present but not allowed. */ protected void validateQuantifier(SqlValidator validator, SqlCall call) { if ((null != call.getFunctionQuantifier()) && !isQuantifierAllowed()) { throw validator.newValidationError( call.getFunctionQuantifier(), EigenbaseResource.instance() .FunctionQuantifierNotAllowed .ex(call.getOperator().getName())); } }
public Void visit(SqlCall call) { final SqlOperator operator = call.getOperator(); if (operator == SqlStdOperatorTable.andOperator) { throw new Found(); } return super.visit(call); }
/** * Constructs a FarragoReentrantSubquery. * * @param subq the subquery to evaluate * @param parentConverter sqlToRelConverter associated with the parent query * @param isExists whether the subquery is part of an EXISTS expression * @param isExplain whether the subquery is part of an EXPLAIN PLAN statement * @param results the resulting evaluated expressions */ FarragoReentrantSubquery( SqlCall subq, SqlToRelConverter parentConverter, boolean isExists, boolean isExplain, List<RexNode> results) { super( FennelRelUtil.getPreparingStmt(parentConverter.getCluster()).getRootStmtContext(), parentConverter.getRexBuilder(), results); FarragoSessionStmtContext rootContext = getRootStmtContext(); if (rootContext != null) { rootContext.setSaveFirstTxnCsn(); } if (!isExists) { assert subq.getKind() == SqlKind.SCALAR_QUERY; } this.subq = subq; this.parentConverter = parentConverter; this.isExists = isExists; this.isExplain = isExplain; }
public SqlMonotonicity getMonotonicity(SqlCall call, SqlValidatorScope scope) { return scope.getMonotonicity(call.operand(0)).unstrict(); }
private RelDataType deriveType( SqlValidator validator, SqlValidatorScope scope, SqlCall call, boolean convertRowArgToColumnList) { final SqlNode[] operands = call.operands; RelDataType[] argTypes = new RelDataType[operands.length]; // Scope for operands. Usually the same as 'scope'. final SqlValidatorScope operandScope = scope.getOperandScope(call); // Indicate to the validator that we're validating a new function call validator.pushFunctionCall(); try { boolean containsRowArg = false; for (int i = 0; i < operands.length; ++i) { RelDataType nodeType; // for row arguments that should be converted to ColumnList // types, set the nodeType to a ColumnList type but defer // validating the arguments of the row constructor until we know // for sure that the row argument maps to a ColumnList type if (operands[i].getKind() == SqlKind.ROW && convertRowArgToColumnList) { containsRowArg = true; RelDataTypeFactory typeFactory = validator.getTypeFactory(); nodeType = typeFactory.createSqlType(SqlTypeName.COLUMN_LIST); } else { nodeType = validator.deriveType(operandScope, operands[i]); } validator.setValidatedNodeType(operands[i], nodeType); argTypes[i] = nodeType; } SqlFunction function = SqlUtil.lookupRoutine( validator.getOperatorTable(), getNameAsId(), argTypes, getFunctionType()); // if we have a match on function name and parameter count, but // couldn't find a function with a COLUMN_LIST type, retry, but // this time, don't convert the row argument to a COLUMN_LIST type; // if we did find a match, go back and revalidate the row operands // (corresponding to column references), now that we can set the // scope to that of the source cursor referenced by that ColumnList // type if (containsRowArg) { if ((function == null) && SqlUtil.matchRoutinesByParameterCount( validator.getOperatorTable(), getNameAsId(), argTypes, getFunctionType())) { // remove the already validated node types corresponding to // row arguments before revalidating for (SqlNode operand : operands) { if (operand.getKind() == SqlKind.ROW) { validator.removeValidatedNodeType(operand); } } return deriveType(validator, scope, call, false); } else if (function != null) { validator.validateColumnListParams(function, argTypes, operands); } } if (getFunctionType() == SqlFunctionCategory.UserDefinedConstructor) { return validator.deriveConstructorType(scope, call, this, function, argTypes); } if (function == null) { validator.handleUnresolvedFunction(call, this, argTypes); } // REVIEW jvs 25-Mar-2005: This is, in a sense, expanding // identifiers, but we ignore shouldExpandIdentifiers() // because otherwise later validation code will // choke on the unresolved function. call.setOperator(function); return function.validateOperands(validator, operandScope, call); } finally { validator.popFunctionCall(); } }
protected void executeImpl() throws Exception { SqlCall call = (SqlCall) subq; SqlSelect select = (SqlSelect) call.getOperands()[0]; // Convert the SqlNode tree to a RelNode tree; we need to do this // here so the RelNode tree is associated with the new preparing // stmt. FarragoPreparingStmt preparingStmt = (FarragoPreparingStmt) getPreparingStmt(); SqlValidator validator = preparingStmt.getSqlValidator(); SqlToRelConverter sqlConverter = preparingStmt.getSqlToRelConverter(validator, preparingStmt); preparingStmt.setParentStmt(FennelRelUtil.getPreparingStmt(parentConverter.getCluster())); // Add to the new converter any subqueries that have already been // converted by the parent so we can avoid re-executing them sqlConverter.addConvertedNonCorrSubqs(parentConverter.getMapConvertedNonCorrSubqs()); RelNode plan = sqlConverter.convertQuery(select, true, true); // The subquery cannot have dynamic parameters if (sqlConverter.getDynamicParamCount() > 0) { failed = true; return; } List<RexNode> exprs = new ArrayList<RexNode>(); RelDataType resultType = null; if (!isExists) { // Non-EXISTS subqueries need to be converted to single-value // subqueries plan = sqlConverter.convertToSingleValueSubq(select, plan); // Create a dummy expression to store the type of the result. // When setting the type, derive the type based on what a // scalar subquery should return and create the type from the // type factory of the parent query. resultType = call.getOperator().deriveType(validator, validator.getFromScope(select), call); resultType = rexBuilder.getTypeFactory().copyType(resultType); exprs.add(rexBuilder.makeInputRef(resultType, 0)); } plan = sqlConverter.decorrelate(select, plan); // If the subquery is part of an EXPLAIN PLAN statement, don't // execute the subquery, but instead just return a dynamic parameter // as a placeholder for the subquery result. Otherwise, execute // the query to produce the constant expression. Cast the expression // as needed so the type matches the expected result type. RexNode constExpr; if (isExplain) { if (isExists) { resultType = rexBuilder.getTypeFactory().createSqlType(SqlTypeName.BOOLEAN); } constExpr = rexBuilder.makeDynamicParam( resultType, parentConverter.getDynamicParamCountInExplain(true)); results.add(constExpr); } else { executePlan(plan, exprs, isExists, false); if (!failed && !isExists) { constExpr = results.get(0); if (constExpr.getType() != resultType) { constExpr = rexBuilder.makeCast(resultType, constExpr); results.set(0, constExpr); } } } }