/** 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()));
   }
 }
Example #2
0
 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;
 }
 public void validateCall(
     SqlCall call,
     SqlValidator validator,
     SqlValidatorScope scope,
     SqlValidatorScope operandScope) {
   // The base method validates all operands. We override because
   // we don't want to validate the identifier.
   final SqlNode[] operands = call.operands;
   assert operands.length == 2;
   assert operands[1] instanceof SqlIdentifier;
   operands[0].validateExpr(validator, scope);
   SqlIdentifier id = (SqlIdentifier) operands[1];
   if (!id.isSimple()) {
     throw validator.newValidationError(
         id, EigenbaseResource.instance().AliasMustBeSimpleIdentifier.ex());
   }
 }
  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);
        }
      }
    }
  }
 public RelDataType deriveType(SqlValidator validator, SqlValidatorScope scope, SqlCall call) {
   // special case for AS:  never try to derive type for alias
   RelDataType nodeType = validator.deriveType(scope, call.operands[0]);
   assert nodeType != null;
   return validateOperands(validator, scope, call);
 }