@Test
 public void testExplainAsXml() {
   String sql = "select 1 + 2, 3 from (values (true))";
   final RelNode rel = tester.convertSqlToRel(sql).rel;
   StringWriter sw = new StringWriter();
   PrintWriter pw = new PrintWriter(sw);
   RelXmlWriter planWriter = new RelXmlWriter(pw, SqlExplainLevel.EXPPLAN_ATTRIBUTES);
   rel.explain(planWriter);
   pw.flush();
   TestUtil.assertEqualsVerbose(
       "<RelNode type=\"LogicalProject\">\n"
           + "\t<Property name=\"EXPR$0\">\n"
           + "\t\t+(1, 2)\t</Property>\n"
           + "\t<Property name=\"EXPR$1\">\n"
           + "\t\t3\t</Property>\n"
           + "\t<Inputs>\n"
           + "\t\t<RelNode type=\"LogicalValues\">\n"
           + "\t\t\t<Property name=\"tuples\">\n"
           + "\t\t\t\t[{ true }]\t\t\t</Property>\n"
           + "\t\t\t<Inputs/>\n"
           + "\t\t</RelNode>\n"
           + "\t</Inputs>\n"
           + "</RelNode>\n",
       Util.toLinux(sw.toString()));
 }
예제 #2
0
  /** Add the Filter condition to the pulledPredicates list from the input. */
  public RelOptPredicateList getPredicates(Filter filter, RelMetadataQuery mq) {
    final RelNode input = filter.getInput();
    final RelOptPredicateList inputInfo = mq.getPulledUpPredicates(input);

    return Util.first(inputInfo, RelOptPredicateList.EMPTY)
        .union(RelOptPredicateList.of(RelOptUtil.conjunctions(filter.getCondition())));
  }
예제 #3
0
  public void unparse(SqlWriter writer, int leftPrec, int rightPrec) {
    switch (typeName) {
      case BOOLEAN:
        writer.keyword(value == null ? "UNKNOWN" : (Boolean) value ? "TRUE" : "FALSE");
        break;
      case NULL:
        writer.keyword("NULL");
        break;
      case CHAR:
      case DECIMAL:
      case DOUBLE:
      case BINARY:

        // should be handled in subtype
        throw Util.unexpected(typeName);

      case SYMBOL:
        if (value instanceof Enum) {
          Enum enumVal = (Enum) value;
          writer.keyword(enumVal.toString());
        } else {
          writer.keyword(String.valueOf(value));
        }
        break;
      default:
        writer.literal(value.toString());
    }
  }
예제 #4
0
 /** @return whether value is appropriate for its type (we have rules about these things) */
 public static boolean valueMatchesType(Object value, SqlTypeName typeName) {
   switch (typeName) {
     case BOOLEAN:
       return (value == null) || (value instanceof Boolean);
     case NULL:
       return value == null;
     case DECIMAL:
     case DOUBLE:
       return value instanceof BigDecimal;
     case DATE:
     case TIME:
     case TIMESTAMP:
       return value instanceof Calendar;
     case INTERVAL_DAY_TIME:
     case INTERVAL_YEAR_MONTH:
       return value instanceof SqlIntervalLiteral.IntervalValue;
     case BINARY:
       return value instanceof BitString;
     case CHAR:
       return value instanceof NlsString;
     case SYMBOL:
       return (value instanceof SqlSymbol)
           || (value instanceof SqlSampleSpec)
           || (value instanceof TimeUnitRange);
     case MULTISET:
       return true;
     case INTEGER: // not allowed -- use Decimal
     case VARCHAR: // not allowed -- use Char
     case VARBINARY: // not allowed -- use Binary
     default:
       throw Util.unexpected(typeName);
   }
 }
예제 #5
0
 private static Comparable zeroValue(RelDataType type) {
   switch (type.getSqlTypeName()) {
     case CHAR:
       return new NlsString(Spaces.of(type.getPrecision()), null, null);
     case VARCHAR:
       return new NlsString("", null, null);
     case BINARY:
       return new ByteString(new byte[type.getPrecision()]);
     case VARBINARY:
       return ByteString.EMPTY;
     case TINYINT:
     case SMALLINT:
     case INTEGER:
     case BIGINT:
     case DECIMAL:
     case FLOAT:
     case REAL:
     case DOUBLE:
       return BigDecimal.ZERO;
     case BOOLEAN:
       return false;
     case TIME:
     case DATE:
     case TIMESTAMP:
       return DateTimeUtils.ZERO_CALENDAR;
     default:
       throw Util.unexpected(type.getSqlTypeName());
   }
 }
예제 #6
0
 @Override
 public String visitLiteral(RexLiteral rexLiteral) {
   Object v = rexLiteral.getValue();
   RelDataType ty = rexLiteral.getType();
   switch (rexLiteral.getTypeName()) {
     case BOOLEAN:
       return v.toString();
     case CHAR:
       return CompilerUtil.escapeJavaString(((NlsString) v).getValue(), true);
     case NULL:
       return "((" + ((Class<?>) typeFactory.getJavaClass(ty)).getCanonicalName() + ")null)";
     case DOUBLE:
     case BIGINT:
     case DECIMAL:
       switch (ty.getSqlTypeName()) {
         case TINYINT:
         case SMALLINT:
         case INTEGER:
           return Long.toString(((BigDecimal) v).longValueExact());
         case BIGINT:
           return Long.toString(((BigDecimal) v).longValueExact()) + 'L';
         case DECIMAL:
         case FLOAT:
         case REAL:
         case DOUBLE:
           return Util.toScientificNotation((BigDecimal) v);
       }
       break;
     default:
       throw new UnsupportedOperationException();
   }
   return null;
 }
예제 #7
0
 /**
  * Creates an expression accessing a given named field from a record.
  *
  * <p>NOTE: Be careful choosing the value of {@code caseSensitive}. If the field name was supplied
  * by an end-user (e.g. as a column alias in SQL), use your session's case-sensitivity setting.
  * Only hard-code {@code true} if you are sure that the field name is internally generated.
  * Hard-coding {@code false} is almost certainly wrong.
  *
  * @param expr Expression yielding a record
  * @param fieldName Name of field in record
  * @param caseSensitive Whether match is case-sensitive
  * @return Expression accessing a given named field
  */
 public RexNode makeFieldAccess(RexNode expr, String fieldName, boolean caseSensitive) {
   final RelDataType type = expr.getType();
   final RelDataTypeField field = type.getField(fieldName, caseSensitive, false);
   if (field == null) {
     throw Util.newInternal("Type '" + type + "' has no field '" + fieldName + "'");
   }
   return makeFieldAccessInternal(expr, field);
 }
예제 #8
0
 /**
  * Creates an expression accessing a field with a given ordinal from a record.
  *
  * @param expr Expression yielding a record
  * @param i Ordinal of field
  * @return Expression accessing given field
  */
 public RexNode makeFieldAccess(RexNode expr, int i) {
   final RelDataType type = expr.getType();
   final List<RelDataTypeField> fields = type.getFieldList();
   if ((i < 0) || (i >= fields.size())) {
     throw Util.newInternal("Field ordinal " + i + " is invalid for " + " type '" + type + "'");
   }
   return makeFieldAccessInternal(expr, fields.get(i));
 }
예제 #9
0
  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);

    // Try successively with catalog.schema, catalog and no prefix
    List<String> x = catalogReader.getSchemaName();
    for (; ; ) {
      final List<String> names2 =
          ImmutableList.<String>builder().addAll(x).addAll(subNames).build();
      hints.addAll(catalogReader.getAllSchemaObjectNames(names2));
      if (x.isEmpty()) {
        break;
      }
      x = Util.skipLast(x);
    }
  }
예제 #10
0
 /** Returns a numeric literal's value as a {@link BigDecimal}. */
 public BigDecimal bigDecimalValue() {
   switch (typeName) {
     case DECIMAL:
     case DOUBLE:
       return (BigDecimal) value;
     default:
       throw Util.unexpected(typeName);
   }
 }
예제 #11
0
 /**
  * Converts a chained string literals into regular literals; returns regular literals unchanged.
  */
 public static SqlLiteral unchain(SqlNode node) {
   if (node instanceof SqlLiteral) {
     return (SqlLiteral) node;
   } else if (SqlUtil.isLiteralChain(node)) {
     return SqlLiteralChainOperator.concatenateOperands((SqlCall) node);
   } else {
     throw Util.newInternal("invalid literal: " + node);
   }
 }
 protected RelDataType validateImpl() {
   final RelDataTypeFactory.FieldInfoBuilder builder = validator.getTypeFactory().builder();
   for (SqlMoniker moniker : validator.catalogReader.getAllSchemaObjectNames(names)) {
     final List<String> names1 = moniker.getFullyQualifiedNames();
     final SqlValidatorTable table = validator.catalogReader.getTable(names1);
     builder.add(Util.last(names1), table.getRowType());
   }
   return builder.build();
 }
예제 #13
0
 @Deprecated // to be removed before 2.0
 public JdbcProject(
     RelOptCluster cluster,
     RelTraitSet traitSet,
     RelNode input,
     List<RexNode> projects,
     RelDataType rowType,
     int flags) {
   this(cluster, traitSet, input, projects, rowType);
   Util.discard(flags);
 }
예제 #14
0
  /** Creates a call to a windowed agg. */
  public RexNode makeOver(
      RelDataType type,
      SqlAggFunction operator,
      List<RexNode> exprs,
      List<RexNode> partitionKeys,
      ImmutableList<RexFieldCollation> orderKeys,
      RexWindowBound lowerBound,
      RexWindowBound upperBound,
      boolean physical,
      boolean allowPartial,
      boolean nullWhenCountZero) {
    assert operator != null;
    assert exprs != null;
    assert partitionKeys != null;
    assert orderKeys != null;
    final RexWindow window = makeWindow(partitionKeys, orderKeys, lowerBound, upperBound, physical);
    final RexOver over = new RexOver(type, operator, exprs, window);
    RexNode result = over;

    // This should be correct but need time to go over test results.
    // Also want to look at combing with section below.
    if (nullWhenCountZero) {
      final RelDataType bigintType = getTypeFactory().createSqlType(SqlTypeName.BIGINT);
      result =
          makeCall(
              SqlStdOperatorTable.CASE,
              makeCall(
                  SqlStdOperatorTable.GREATER_THAN,
                  new RexOver(bigintType, SqlStdOperatorTable.COUNT, exprs, window),
                  makeLiteral(BigDecimal.ZERO, bigintType, SqlTypeName.DECIMAL)),
              ensureType(
                  type, // SUM0 is non-nullable, thus need a cast
                  new RexOver(
                      typeFactory.createTypeWithNullability(type, false), operator, exprs, window),
                  false),
              makeCast(type, constantNull()));
    }
    if (!allowPartial) {
      Util.permAssert(physical, "DISALLOW PARTIAL over RANGE");
      final RelDataType bigintType = getTypeFactory().createSqlType(SqlTypeName.BIGINT);
      // todo: read bound
      result =
          makeCall(
              SqlStdOperatorTable.CASE,
              makeCall(
                  SqlStdOperatorTable.GREATER_THAN_OR_EQUAL,
                  new RexOver(
                      bigintType, SqlStdOperatorTable.COUNT, ImmutableList.<RexNode>of(), window),
                  makeLiteral(BigDecimal.valueOf(2), bigintType, SqlTypeName.DECIMAL)),
              result,
              constantNull);
    }
    return result;
  }
예제 #15
0
 /**
  * Resolves a multi-part identifier such as "SCHEMA.EMP.EMPNO" to a namespace. The returned
  * namespace, never null, may represent a schema, table, column, etc.
  */
 public static SqlValidatorNamespace lookup(SqlValidatorScope scope, List<String> names) {
   assert names.size() > 0;
   final SqlValidatorScope.ResolvedImpl resolved = new SqlValidatorScope.ResolvedImpl();
   scope.resolve(ImmutableList.of(names.get(0)), false, resolved);
   assert resolved.count() == 1;
   SqlValidatorNamespace namespace = resolved.only().namespace;
   for (String name : Util.skip(names)) {
     namespace = namespace.lookupChild(name);
     assert namespace != null;
   }
   return namespace;
 }
예제 #16
0
 /** @see RelMetadataQuery#getPulledUpPredicates(RelNode) */
 public RelOptPredicateList getPredicates(RelSubset r, RelMetadataQuery mq) {
   if (!Bug.CALCITE_1048_FIXED) {
     return RelOptPredicateList.EMPTY;
   }
   RelOptPredicateList list = null;
   for (RelNode r2 : r.getRels()) {
     RelOptPredicateList list2 = mq.getPulledUpPredicates(r2);
     if (list2 != null) {
       list = list == null ? list2 : list.union(list2);
     }
   }
   return Util.first(list, RelOptPredicateList.EMPTY);
 }
예제 #17
0
  public Double getMaxRowCount(RelSubset rel, RelMetadataQuery mq) {
    // FIXME This is a short-term fix for [CALCITE-1018]. A complete
    // solution will come with [CALCITE-1048].
    Util.discard(Bug.CALCITE_1048_FIXED);
    for (RelNode node : rel.getRels()) {
      if (node instanceof Sort) {
        Sort sort = (Sort) node;
        if (sort.fetch != null) {
          return (double) RexLiteral.intValue(sort.fetch);
        }
      }
    }

    return Double.POSITIVE_INFINITY;
  }
예제 #18
0
 /**
  * Extracts the string value from a string literal, a chain of string literals, or a CAST of a
  * string literal.
  *
  * @deprecated Use {@link #value(SqlNode)}
  */
 @Deprecated // to be removed before 2.0
 public static String stringValue(SqlNode node) {
   if (node instanceof SqlLiteral) {
     SqlLiteral literal = (SqlLiteral) node;
     assert SqlTypeUtil.inCharFamily(literal.getTypeName());
     return literal.toValue();
   } else if (SqlUtil.isLiteralChain(node)) {
     final SqlLiteral literal = SqlLiteralChainOperator.concatenateOperands((SqlCall) node);
     assert SqlTypeUtil.inCharFamily(literal.getTypeName());
     return literal.toValue();
   } else if (node instanceof SqlCall
       && ((SqlCall) node).getOperator() == SqlStdOperatorTable.CAST) {
     return stringValue(((SqlCall) node).operand(0));
   } else {
     throw Util.newInternal("invalid string literal: " + node);
   }
 }
예제 #19
0
 /**
  * Extracts the value from a literal.
  *
  * <p>Cases:
  *
  * <ul>
  *   <li>If the node is a character literal, a chain of string literals, or a CAST of a character
  *       literal, returns the value as a {@link NlsString}.
  *   <li>If the node is a numeric literal, or a negated numeric literal, returns the value as a
  *       {@link BigDecimal}.
  *   <li>If the node is a {@link SqlIntervalQualifier}, returns its {@link TimeUnitRange}.
  *   <li>If the node is INTERVAL_DAY_TIME in {@link SqlTypeFamily}, returns its sign multiplied by
  *       its millisecond equivalent value
  *   <li>If the node is INTERVAL_YEAR_MONTH in {@link SqlTypeFamily}, returns its sign multiplied
  *       by its months equivalent value
  *   <li>Otherwise the behavior is not specified.
  * </ul>
  */
 public static Comparable value(SqlNode node) {
   if (node instanceof SqlLiteral) {
     SqlLiteral literal = (SqlLiteral) node;
     switch (literal.getTypeName().getFamily()) {
       case CHARACTER:
         return (NlsString) literal.value;
       case NUMERIC:
         return (BigDecimal) literal.value;
       case INTERVAL_YEAR_MONTH:
         final SqlIntervalLiteral.IntervalValue valMonth =
             (SqlIntervalLiteral.IntervalValue) literal.value;
         return valMonth.getSign() * SqlParserUtil.intervalToMonths(valMonth);
       case INTERVAL_DAY_TIME:
         final SqlIntervalLiteral.IntervalValue valTime =
             (SqlIntervalLiteral.IntervalValue) literal.value;
         return valTime.getSign() * SqlParserUtil.intervalToMillis(valTime);
     }
   }
   if (SqlUtil.isLiteralChain(node)) {
     assert node instanceof SqlCall;
     final SqlLiteral literal = SqlLiteralChainOperator.concatenateOperands((SqlCall) node);
     assert SqlTypeUtil.inCharFamily(literal.getTypeName());
     return (NlsString) literal.value;
   }
   if (node instanceof SqlIntervalQualifier) {
     SqlIntervalQualifier qualifier = (SqlIntervalQualifier) node;
     return qualifier.timeUnitRange;
   }
   switch (node.getKind()) {
     case CAST:
       assert node instanceof SqlCall;
       return value(((SqlCall) node).operand(0));
     case MINUS_PREFIX:
       assert node instanceof SqlCall;
       Comparable o = value(((SqlCall) node).operand(0));
       if (o instanceof BigDecimal) {
         BigDecimal bigDecimal = (BigDecimal) o;
         return bigDecimal.negate();
       }
       // fall through
     default:
       throw Util.newInternal("invalid literal: " + node);
   }
 }
예제 #20
0
 /**
  * Returns the long value of this literal.
  *
  * @param exact Whether the value has to be exact. If true, and the literal is a fraction (e.g.
  *     3.14), throws. If false, discards the fractional part of the value.
  * @return Long value of this literal
  */
 public long longValue(boolean exact) {
   switch (typeName) {
     case DECIMAL:
     case DOUBLE:
       BigDecimal bd = (BigDecimal) value;
       if (exact) {
         try {
           return bd.longValueExact();
         } catch (ArithmeticException e) {
           throw SqlUtil.newContextException(
               getParserPosition(), RESOURCE.numberLiteralOutOfRange(bd.toString()));
         }
       } else {
         return bd.longValue();
       }
     default:
       throw Util.unexpected(typeName);
   }
 }
예제 #21
0
  public RelDataType createSqlType(RelDataTypeFactory typeFactory) {
    BitString bitString;
    switch (typeName) {
      case NULL:
      case BOOLEAN:
        RelDataType ret = typeFactory.createSqlType(typeName);
        ret = typeFactory.createTypeWithNullability(ret, null == value);
        return ret;
      case BINARY:
        bitString = (BitString) value;
        int bitCount = bitString.getBitCount();
        return typeFactory.createSqlType(SqlTypeName.BINARY, bitCount / 8);
      case CHAR:
        NlsString string = (NlsString) value;
        Charset charset = string.getCharset();
        if (null == charset) {
          charset = typeFactory.getDefaultCharset();
        }
        SqlCollation collation = string.getCollation();
        if (null == collation) {
          collation = SqlCollation.COERCIBLE;
        }
        RelDataType type = typeFactory.createSqlType(SqlTypeName.CHAR, string.getValue().length());
        type = typeFactory.createTypeWithCharsetAndCollation(type, charset, collation);
        return type;

      case INTERVAL_YEAR_MONTH:
      case INTERVAL_DAY_TIME:
        SqlIntervalLiteral.IntervalValue intervalValue = (SqlIntervalLiteral.IntervalValue) value;
        return typeFactory.createSqlIntervalType(intervalValue.getIntervalQualifier());

      case SYMBOL:
        return typeFactory.createSqlType(SqlTypeName.SYMBOL);

      case INTEGER: // handled in derived class
      case TIME: // handled in derived class
      case VARCHAR: // should never happen
      case VARBINARY: // should never happen

      default:
        throw Util.needToImplement(toString() + ", operand=" + value);
    }
  }
예제 #22
0
  /**
   * 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
   *     &lt; 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).operand(1).toString();

      case OVER:
        // E.g. "bids over w" --> "bids"
        return getAlias(((SqlCall) node).operand(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);
        }
    }
  }
예제 #23
0
 /**
  * Runs with query #i.
  *
  * @param i Ordinal of query, per the benchmark, 1-based
  * @param enable Whether to enable query execution. If null, use the value of {@link #ENABLE}.
  *     Pass true only for 'fast' tests that do not read any data.
  */
 private CalciteAssert.AssertQuery query(int i, Boolean enable) {
   return with(Util.first(enable, ENABLE))
       .query(QUERIES.get(i - 1).replaceAll("tpch\\.", "tpch_01."));
 }
예제 #24
0
/**
 * Validates the parse tree of a SQL statement, and provides semantic information about the parse
 * tree.
 *
 * <p>To create an instance of the default validator implementation, call {@link
 * SqlValidatorUtil#newValidator}.
 *
 * <h2>Visitor pattern</h2>
 *
 * <p>The validator interface is an instance of the {@link
 * org.apache.calcite.util.Glossary#VISITOR_PATTERN visitor pattern}. Implementations of the {@link
 * SqlNode#validate} method call the <code>validateXxx</code> method appropriate to the kind of
 * node:
 *
 * <ul>
 *   <li>{@link SqlLiteral#validate(SqlValidator, SqlValidatorScope)} calls {@link
 *       #validateLiteral(org.apache.calcite.sql.SqlLiteral)};
 *   <li>{@link SqlCall#validate(SqlValidator, SqlValidatorScope)} calls {@link
 *       #validateCall(SqlCall, SqlValidatorScope)};
 *   <li>and so forth.
 * </ul>
 *
 * <p>The {@link SqlNode#validateExpr(SqlValidator, SqlValidatorScope)} method is as {@link
 * SqlNode#validate(SqlValidator, SqlValidatorScope)} but is called when the node is known to be a
 * scalar expression.
 *
 * <h2>Scopes and namespaces</h2>
 *
 * <p>In order to resolve names to objects, the validator builds a map of the structure of the
 * query. This map consists of two types of objects. A {@link SqlValidatorScope} describes the
 * tables and columns accessible at a particular point in the query; and a {@link
 * SqlValidatorNamespace} is a description of a data source used in a query.
 *
 * <p>There are different kinds of namespace for different parts of the query. for example {@link
 * IdentifierNamespace} for table names, {@link SelectNamespace} for SELECT queries, {@link
 * SetopNamespace} for UNION, EXCEPT and INTERSECT. A validator is allowed to wrap namespaces in
 * other objects which implement {@link SqlValidatorNamespace}, so don't try to cast your namespace
 * or use <code>instanceof</code>; use {@link SqlValidatorNamespace#unwrap(Class)} and {@link
 * SqlValidatorNamespace#isWrapperFor(Class)} instead.
 *
 * <p>The validator builds the map by making a quick scan over the query when the root {@link
 * SqlNode} is first provided. Thereafter, it supplies the correct scope or namespace object when it
 * calls validation methods.
 *
 * <p>The methods {@link #getSelectScope}, {@link #getFromScope}, {@link #getWhereScope}, {@link
 * #getGroupScope}, {@link #getHavingScope}, {@link #getOrderScope} and {@link #getJoinScope} get
 * the correct scope to resolve names in a particular clause of a SQL statement.
 */
public interface SqlValidator {
  /** Whether to follow the SQL standard strictly. */
  boolean STRICT = Util.getBooleanProperty("calcite.strict.sql");

  // ~ Methods ----------------------------------------------------------------

  /**
   * Returns the dialect of SQL (SQL:2003, etc.) this validator recognizes. Default is {@link
   * SqlConformance#DEFAULT}.
   *
   * @return dialect of SQL this validator recognizes
   */
  SqlConformance getConformance();

  /**
   * Returns the catalog reader used by this validator.
   *
   * @return catalog reader
   */
  SqlValidatorCatalogReader getCatalogReader();

  /**
   * Returns the operator table used by this validator.
   *
   * @return operator table
   */
  SqlOperatorTable getOperatorTable();

  /**
   * Validates an expression tree. You can call this method multiple times, but not reentrantly.
   *
   * @param topNode top of expression tree to be validated
   * @return validated tree (possibly rewritten)
   */
  SqlNode validate(SqlNode topNode);

  /**
   * Validates an expression tree. You can call this method multiple times, but not reentrantly.
   *
   * @param topNode top of expression tree to be validated
   * @param nameToTypeMap map of simple name to {@link RelDataType}; used to resolve {@link
   *     SqlIdentifier} references
   * @return validated tree (possibly rewritten)
   */
  SqlNode validateParameterizedExpression(SqlNode topNode, Map<String, RelDataType> nameToTypeMap);

  /**
   * Checks that a query is valid.
   *
   * <p>Valid queries include:
   *
   * <ul>
   *   <li><code>SELECT</code> statement,
   *   <li>set operation (<code>UNION</code>, <code>INTERSECT</code>, <code>
   * EXCEPT</code>)
   *   <li>identifier (e.g. representing use of a table in a FROM clause)
   *   <li>query aliased with the <code>AS</code> operator
   * </ul>
   *
   * @param node Query node
   * @param scope Scope in which the query occurs
   * @param targetRowType Desired row type, must not be null, may be the data type 'unknown'.
   * @throws RuntimeException if the query is not valid
   */
  void validateQuery(SqlNode node, SqlValidatorScope scope, RelDataType targetRowType);

  /**
   * Returns the type assigned to a node by validation.
   *
   * @param node the node of interest
   * @return validated type, never null
   */
  RelDataType getValidatedNodeType(SqlNode node);

  /**
   * Returns the type assigned to a node by validation, or null if unknown. This allows for queries
   * against nodes such as aliases, which have no type of their own. If you want to assert that the
   * node of interest must have a type, use {@link #getValidatedNodeType} instead.
   *
   * @param node the node of interest
   * @return validated type, or null if unknown or not applicable
   */
  RelDataType getValidatedNodeTypeIfKnown(SqlNode node);

  /**
   * Resolves an identifier to a fully-qualified name.
   *
   * @param id Identifier
   * @param scope Naming scope
   */
  void validateIdentifier(SqlIdentifier id, SqlValidatorScope scope);

  /**
   * Validates a literal.
   *
   * @param literal Literal
   */
  void validateLiteral(SqlLiteral literal);

  /**
   * Validates a {@link SqlIntervalQualifier}
   *
   * @param qualifier Interval qualifier
   */
  void validateIntervalQualifier(SqlIntervalQualifier qualifier);

  /**
   * Validates an INSERT statement.
   *
   * @param insert INSERT statement
   */
  void validateInsert(SqlInsert insert);

  /**
   * Validates an UPDATE statement.
   *
   * @param update UPDATE statement
   */
  void validateUpdate(SqlUpdate update);

  /**
   * Validates a DELETE statement.
   *
   * @param delete DELETE statement
   */
  void validateDelete(SqlDelete delete);

  /**
   * Validates a MERGE statement.
   *
   * @param merge MERGE statement
   */
  void validateMerge(SqlMerge merge);

  /**
   * Validates a data type expression.
   *
   * @param dataType Data type
   */
  void validateDataType(SqlDataTypeSpec dataType);

  /**
   * Validates a dynamic parameter.
   *
   * @param dynamicParam Dynamic parameter
   */
  void validateDynamicParam(SqlDynamicParam dynamicParam);

  /**
   * Validates the right-hand side of an OVER expression. It might be either an {@link SqlIdentifier
   * identifier} referencing a window, or an {@link SqlWindow inline window specification}.
   *
   * @param windowOrId SqlNode that can be either SqlWindow with all the components of a window spec
   *     or a SqlIdentifier with the name of a window spec.
   * @param scope Naming scope
   * @param call the SqlNode if a function call if the window is attached to one.
   */
  void validateWindow(SqlNode windowOrId, SqlValidatorScope scope, SqlCall call);

  /**
   * Validates a call to an operator.
   *
   * @param call Operator call
   * @param scope Naming scope
   */
  void validateCall(SqlCall call, SqlValidatorScope scope);

  /**
   * Validates parameters for aggregate function.
   *
   * @param aggCall Function containing COLUMN_LIST parameter
   * @param filter Filter, or null
   * @param scope Syntactic scope
   */
  void validateAggregateParams(SqlCall aggCall, SqlNode filter, SqlValidatorScope scope);

  /**
   * Validates a COLUMN_LIST parameter
   *
   * @param function function containing COLUMN_LIST parameter
   * @param argTypes function arguments
   * @param operands operands passed into the function call
   */
  void validateColumnListParams(
      SqlFunction function, List<RelDataType> argTypes, List<SqlNode> operands);

  /**
   * Derives the type of a node in a given scope. If the type has already been inferred, returns the
   * previous type.
   *
   * @param scope Syntactic scope
   * @param operand Parse tree node
   * @return Type of the SqlNode. Should never return <code>NULL</code>
   */
  RelDataType deriveType(SqlValidatorScope scope, SqlNode operand);

  /**
   * Adds "line x, column y" context to a validator exception.
   *
   * <p>Note that the input exception is checked (it derives from {@link Exception}) and the output
   * exception is unchecked (it derives from {@link RuntimeException}). This is intentional -- it
   * should remind code authors to provide context for their validation errors.
   *
   * @param node The place where the exception occurred, not null
   * @param e The validation error
   * @return Exception containing positional information, never null
   */
  CalciteContextException newValidationError(
      SqlNode node, Resources.ExInst<SqlValidatorException> e);

  /**
   * Returns whether a SELECT statement is an aggregation. Criteria are: (1) contains GROUP BY, or
   * (2) contains HAVING, or (3) SELECT or ORDER BY clause contains aggregate functions. (Windowed
   * aggregate functions, such as <code>SUM(x) OVER w</code>, don't count.)
   *
   * @param select SELECT statement
   * @return whether SELECT statement is an aggregation
   */
  boolean isAggregate(SqlSelect select);

  /**
   * Returns whether a select list expression is an aggregate function.
   *
   * @param selectNode Expression in SELECT clause
   * @return whether expression is an aggregate function
   */
  @Deprecated // to be removed before 2.0
  boolean isAggregate(SqlNode selectNode);

  /**
   * Converts a window specification or window name into a fully-resolved window specification. For
   * example, in <code>SELECT sum(x) OVER (PARTITION
   * BY x ORDER BY y), sum(y) OVER w1, sum(z) OVER (w ORDER BY y) FROM t
   * WINDOW w AS (PARTITION BY x)</code> all aggregations have the same resolved window
   * specification <code>(PARTITION BY x ORDER BY y)</code>.
   *
   * @param windowOrRef Either the name of a window (a {@link SqlIdentifier}) or a window
   *     specification (a {@link SqlWindow}).
   * @param scope Scope in which to resolve window names
   * @param populateBounds Whether to populate bounds. Doing so may alter the definition of the
   *     window. It is recommended that populate bounds when translating to physical algebra, but
   *     not when validating.
   * @return A window
   * @throws RuntimeException Validation exception if window does not exist
   */
  SqlWindow resolveWindow(SqlNode windowOrRef, SqlValidatorScope scope, boolean populateBounds);

  /**
   * Finds the namespace corresponding to a given node.
   *
   * <p>For example, in the query <code>SELECT * FROM (SELECT * FROM t), t1 AS
   * alias</code>, the both items in the FROM clause have a corresponding namespace.
   *
   * @param node Parse tree node
   * @return namespace of node
   */
  SqlValidatorNamespace getNamespace(SqlNode node);

  /**
   * Derives an alias for an expression. If no alias can be derived, returns null if <code>ordinal
   * </code> is less than zero, otherwise generates an alias <code>EXPR$<i>ordinal</i></code>.
   *
   * @param node Expression
   * @param ordinal Ordinal of expression
   * @return derived alias, or null if no alias can be derived and ordinal is less than zero
   */
  String deriveAlias(SqlNode node, int ordinal);

  /**
   * Returns a list of expressions, with every occurrence of "&#42;" or "TABLE.&#42;" expanded.
   *
   * @param selectList Select clause to be expanded
   * @param query Query
   * @param includeSystemVars Whether to include system variables
   * @return expanded select clause
   */
  SqlNodeList expandStar(SqlNodeList selectList, SqlSelect query, boolean includeSystemVars);

  /**
   * Returns the scope that expressions in the WHERE and GROUP BY clause of this query should use.
   * This scope consists of the tables in the FROM clause, and the enclosing scope.
   *
   * @param select Query
   * @return naming scope of WHERE clause
   */
  SqlValidatorScope getWhereScope(SqlSelect select);

  /**
   * Returns the type factory used by this validator.
   *
   * @return type factory
   */
  RelDataTypeFactory getTypeFactory();

  /**
   * Saves the type of a {@link SqlNode}, now that it has been validated.
   *
   * @param node A SQL parse tree node, never null
   * @param type Its type; must not be null
   * @deprecated This method should not be in the {@link SqlValidator} interface. The validator
   *     should drive the type-derivation process, and store nodes' types when they have been
   *     derived.
   */
  void setValidatedNodeType(SqlNode node, RelDataType type);

  /**
   * Removes a node from the set of validated nodes
   *
   * @param node node to be removed
   */
  void removeValidatedNodeType(SqlNode node);

  /**
   * Returns an object representing the "unknown" type.
   *
   * @return unknown type
   */
  RelDataType getUnknownType();

  /**
   * Returns the appropriate scope for validating a particular clause of a SELECT statement.
   *
   * <p>Consider
   *
   * <blockquote>
   *
   * <pre><code>SELECT *
   * FROM foo
   * WHERE EXISTS (
   *    SELECT deptno AS x
   *    FROM emp
   *       JOIN dept ON emp.deptno = dept.deptno
   *    WHERE emp.deptno = 5
   *    GROUP BY deptno
   *    ORDER BY x)</code></pre>
   *
   * </blockquote>
   *
   * <p>What objects can be seen in each part of the sub-query?
   *
   * <ul>
   *   <li>In FROM ({@link #getFromScope} , you can only see 'foo'.
   *   <li>In WHERE ({@link #getWhereScope}), GROUP BY ({@link #getGroupScope}), SELECT ({@code
   *       getSelectScope}), and the ON clause of the JOIN ({@link #getJoinScope}) you can see
   *       'emp', 'dept', and 'foo'.
   *   <li>In ORDER BY ({@link #getOrderScope}), you can see the column alias 'x'; and tables 'emp',
   *       'dept', and 'foo'.
   * </ul>
   *
   * @param select SELECT statement
   * @return naming scope for SELECT statement
   */
  SqlValidatorScope getSelectScope(SqlSelect select);

  /**
   * Returns the scope for resolving the SELECT, GROUP BY and HAVING clauses. Always a {@link
   * SelectScope}; if this is an aggregation query, the {@link AggregatingScope} is stripped away.
   *
   * @param select SELECT statement
   * @return naming scope for SELECT statement, sans any aggregating scope
   */
  SelectScope getRawSelectScope(SqlSelect select);

  /**
   * Returns a scope containing the objects visible from the FROM clause of a query.
   *
   * @param select SELECT statement
   * @return naming scope for FROM clause
   */
  SqlValidatorScope getFromScope(SqlSelect select);

  /**
   * Returns a scope containing the objects visible from the ON and USING sections of a JOIN clause.
   *
   * @param node The item in the FROM clause which contains the ON or USING expression
   * @return naming scope for JOIN clause
   * @see #getFromScope
   */
  SqlValidatorScope getJoinScope(SqlNode node);

  /**
   * Returns a scope containing the objects visible from the GROUP BY clause of a query.
   *
   * @param select SELECT statement
   * @return naming scope for GROUP BY clause
   */
  SqlValidatorScope getGroupScope(SqlSelect select);

  /**
   * Returns a scope containing the objects visible from the HAVING clause of a query.
   *
   * @param select SELECT statement
   * @return naming scope for HAVING clause
   */
  SqlValidatorScope getHavingScope(SqlSelect select);

  /**
   * Returns the scope that expressions in the SELECT and HAVING clause of this query should use.
   * This scope consists of the FROM clause and the enclosing scope. If the query is aggregating,
   * only columns in the GROUP BY clause may be used.
   *
   * @param select SELECT statement
   * @return naming scope for ORDER BY clause
   */
  SqlValidatorScope getOrderScope(SqlSelect select);

  /**
   * Declares a SELECT expression as a cursor.
   *
   * @param select select expression associated with the cursor
   * @param scope scope of the parent query associated with the cursor
   */
  void declareCursor(SqlSelect select, SqlValidatorScope scope);

  /** Pushes a new instance of a function call on to a function call stack. */
  void pushFunctionCall();

  /** Removes the topmost entry from the function call stack. */
  void popFunctionCall();

  /**
   * Retrieves the name of the parent cursor referenced by a column list parameter.
   *
   * @param columnListParamName name of the column list parameter
   * @return name of the parent cursor
   */
  String getParentCursor(String columnListParamName);

  /**
   * Enables or disables expansion of identifiers other than column references.
   *
   * @param expandIdentifiers new setting
   */
  void setIdentifierExpansion(boolean expandIdentifiers);

  /**
   * Enables or disables expansion of column references. (Currently this does not apply to the ORDER
   * BY clause; may be fixed in the future.)
   *
   * @param expandColumnReferences new setting
   */
  void setColumnReferenceExpansion(boolean expandColumnReferences);

  /** @return whether column reference expansion is enabled */
  boolean getColumnReferenceExpansion();

  /**
   * Sets how NULL values should be collated if an ORDER BY item does not contain NULLS FIRST or
   * NULLS LAST.
   */
  void setDefaultNullCollation(NullCollation nullCollation);

  /**
   * Returns how NULL values should be collated if an ORDER BY item does not contain NULLS FIRST or
   * NULLS LAST.
   */
  NullCollation getDefaultNullCollation();

  /**
   * Returns expansion of identifiers.
   *
   * @return whether this validator should expand identifiers
   */
  boolean shouldExpandIdentifiers();

  /**
   * Enables or disables rewrite of "macro-like" calls such as COALESCE.
   *
   * @param rewriteCalls new setting
   */
  void setCallRewrite(boolean rewriteCalls);

  /**
   * Derives the type of a constructor.
   *
   * @param scope Scope
   * @param call Call
   * @param unresolvedConstructor TODO
   * @param resolvedConstructor TODO
   * @param argTypes Types of arguments
   * @return Resolved type of constructor
   */
  RelDataType deriveConstructorType(
      SqlValidatorScope scope,
      SqlCall call,
      SqlFunction unresolvedConstructor,
      SqlFunction resolvedConstructor,
      List<RelDataType> argTypes);

  /**
   * Handles a call to a function which cannot be resolved. Returns a an appropriately descriptive
   * error, which caller must throw.
   *
   * @param call Call
   * @param unresolvedFunction Overloaded function which is the target of the call
   * @param argTypes Types of arguments
   * @param argNames Names of arguments, or null if call by position
   */
  CalciteException handleUnresolvedFunction(
      SqlCall call,
      SqlFunction unresolvedFunction,
      List<RelDataType> argTypes,
      List<String> argNames);

  /**
   * Expands an expression in the ORDER BY clause into an expression with the same semantics as
   * expressions in the SELECT clause.
   *
   * <p>This is made necessary by a couple of dialect 'features':
   *
   * <ul>
   *   <li><b>ordinal expressions</b>: In "SELECT x, y FROM t ORDER BY 2", the expression "2" is
   *       shorthand for the 2nd item in the select clause, namely "y".
   *   <li><b>alias references</b>: In "SELECT x AS a, y FROM t ORDER BY a", the expression "a" is
   *       shorthand for the item in the select clause whose alias is "a"
   * </ul>
   *
   * @param select Select statement which contains ORDER BY
   * @param orderExpr Expression in the ORDER BY clause.
   * @return Expression translated into SELECT clause semantics
   */
  SqlNode expandOrderExpr(SqlSelect select, SqlNode orderExpr);

  /**
   * Expands an expression.
   *
   * @param expr Expression
   * @param scope Scope
   * @return Expanded expression
   */
  SqlNode expand(SqlNode expr, SqlValidatorScope scope);

  /**
   * Returns whether a field is a system field. Such fields may have particular properties such as
   * sortedness and nullability.
   *
   * <p>In the default implementation, always returns {@code false}.
   *
   * @param field Field
   * @return whether field is a system field
   */
  boolean isSystemField(RelDataTypeField field);

  /**
   * Returns a description of how each field in the row type maps to a catalog, schema, table and
   * column in the schema.
   *
   * <p>The returned list is never null, and has one element for each field in the row type. Each
   * element is a list of four elements (catalog, schema, table, column), or may be null if the
   * column is an expression.
   *
   * @param sqlQuery Query
   * @return Description of how each field in the row type maps to a schema object
   */
  List<List<String>> getFieldOrigins(SqlNode sqlQuery);

  /**
   * Returns a record type that contains the name and type of each parameter. Returns a record type
   * with no fields if there are no parameters.
   *
   * @param sqlQuery Query
   * @return Record type
   */
  RelDataType getParameterRowType(SqlNode sqlQuery);

  /**
   * Returns the scope of an OVER or VALUES node.
   *
   * @param node Node
   * @return Scope
   */
  SqlValidatorScope getOverScope(SqlNode node);

  /**
   * Validates that a query is capable of producing a return of given modality (relational or
   * streaming).
   *
   * @param select Query
   * @param modality Modality (streaming or relational)
   * @param fail Whether to throw a user error if does not support required modality
   * @return whether query supports the given modality
   */
  boolean validateModality(SqlSelect select, SqlModality modality, boolean fail);

  void validateWith(SqlWith with, SqlValidatorScope scope);

  void validateWithItem(SqlWithItem withItem);

  void validateSequenceValue(SqlValidatorScope scope, SqlIdentifier id);

  SqlValidatorScope getWithScope(SqlNode withItem);
}
예제 #25
0
 @Override
 public double estimateRowCount(RelMetadataQuery mq) {
   return Util.first(RelMdUtil.getSemiJoinRowCount(mq, left, right, joinType, condition), 1D);
 }
  /**
   * Checks whether an exception matches the expected pattern. If <code>
   * sap</code> contains an error location, checks this too.
   *
   * @param ex Exception thrown
   * @param expectedMsgPattern Expected pattern
   * @param sap Query and (optional) position in query
   */
  public static void checkEx(
      Throwable ex, String expectedMsgPattern, SqlParserUtil.StringAndPos sap) {
    if (null == ex) {
      if (expectedMsgPattern == null) {
        // No error expected, and no error happened.
        return;
      } else {
        throw new AssertionError(
            "Expected query to throw exception, "
                + "but it did not; query ["
                + sap.sql
                + "]; expected ["
                + expectedMsgPattern
                + "]");
      }
    }
    Throwable actualException = ex;
    String actualMessage = actualException.getMessage();
    int actualLine = -1;
    int actualColumn = -1;
    int actualEndLine = 100;
    int actualEndColumn = 99;

    // Search for an CalciteContextException somewhere in the stack.
    CalciteContextException ece = null;
    for (Throwable x = ex; x != null; x = x.getCause()) {
      if (x instanceof CalciteContextException) {
        ece = (CalciteContextException) x;
        break;
      }
      if (x.getCause() == x) {
        break;
      }
    }

    // Search for a SqlParseException -- with its position set -- somewhere
    // in the stack.
    SqlParseException spe = null;
    for (Throwable x = ex; x != null; x = x.getCause()) {
      if ((x instanceof SqlParseException) && (((SqlParseException) x).getPos() != null)) {
        spe = (SqlParseException) x;
        break;
      }
      if (x.getCause() == x) {
        break;
      }
    }

    if (ece != null) {
      actualLine = ece.getPosLine();
      actualColumn = ece.getPosColumn();
      actualEndLine = ece.getEndPosLine();
      actualEndColumn = ece.getEndPosColumn();
      if (ece.getCause() != null) {
        actualException = ece.getCause();
        actualMessage = actualException.getMessage();
      }
    } else if (spe != null) {
      actualLine = spe.getPos().getLineNum();
      actualColumn = spe.getPos().getColumnNum();
      actualEndLine = spe.getPos().getEndLineNum();
      actualEndColumn = spe.getPos().getEndColumnNum();
      if (spe.getCause() != null) {
        actualException = spe.getCause();
        actualMessage = actualException.getMessage();
      }
    } else {
      final String message = ex.getMessage();
      if (message != null) {
        Matcher matcher = LINE_COL_TWICE_PATTERN.matcher(message);
        if (matcher.matches()) {
          actualLine = Integer.parseInt(matcher.group(1));
          actualColumn = Integer.parseInt(matcher.group(2));
          actualEndLine = Integer.parseInt(matcher.group(3));
          actualEndColumn = Integer.parseInt(matcher.group(4));
          actualMessage = matcher.group(5);
        } else {
          matcher = LINE_COL_PATTERN.matcher(message);
          if (matcher.matches()) {
            actualLine = Integer.parseInt(matcher.group(1));
            actualColumn = Integer.parseInt(matcher.group(2));
          }
        }
      }
    }

    if (null == expectedMsgPattern) {
      if (null != actualException) {
        actualException.printStackTrace();
        fail(
            "Validator threw unexpected exception"
                + "; query ["
                + sap.sql
                + "]; exception ["
                + actualMessage
                + "]; class ["
                + actualException.getClass()
                + "]; pos [line "
                + actualLine
                + " col "
                + actualColumn
                + " thru line "
                + actualLine
                + " col "
                + actualColumn
                + "]");
      }
    } else {
      if (null == actualException) {
        fail(
            "Expected validator to throw "
                + "exception, but it did not; query ["
                + sap.sql
                + "]; expected ["
                + expectedMsgPattern
                + "]");
      } else {
        String sqlWithCarets;
        if ((actualColumn <= 0)
            || (actualLine <= 0)
            || (actualEndColumn <= 0)
            || (actualEndLine <= 0)) {
          if (sap.pos != null) {
            AssertionError e =
                new AssertionError(
                    "Expected error to have position,"
                        + " but actual error did not: "
                        + " actual pos [line "
                        + actualLine
                        + " col "
                        + actualColumn
                        + " thru line "
                        + actualEndLine
                        + " col "
                        + actualEndColumn
                        + "]");
            e.initCause(actualException);
            throw e;
          }
          sqlWithCarets = sap.sql;
        } else {
          sqlWithCarets =
              SqlParserUtil.addCarets(
                  sap.sql, actualLine, actualColumn, actualEndLine, actualEndColumn + 1);
          if (sap.pos == null) {
            throw new AssertionError(
                "Actual error had a position, but expected error"
                    + " did not. Add error position carets to sql:\n"
                    + sqlWithCarets);
          }
        }
        if (actualMessage != null) {
          actualMessage = Util.toLinux(actualMessage);
        }
        if ((actualMessage == null) || !actualMessage.matches(expectedMsgPattern)) {
          actualException.printStackTrace();
          final String actualJavaRegexp =
              (actualMessage == null)
                  ? "null"
                  : TestUtil.quoteForJava(TestUtil.quotePattern(actualMessage));
          fail(
              "Validator threw different "
                  + "exception than expected; query ["
                  + sap.sql
                  + "];\n"
                  + " expected pattern ["
                  + expectedMsgPattern
                  + "];\n"
                  + " actual ["
                  + actualMessage
                  + "];\n"
                  + " actual as java regexp ["
                  + actualJavaRegexp
                  + "]; pos ["
                  + actualLine
                  + " col "
                  + actualColumn
                  + " thru line "
                  + actualEndLine
                  + " col "
                  + actualEndColumn
                  + "]; sql ["
                  + sqlWithCarets
                  + "]");
        } else if ((sap.pos != null)
            && ((actualLine != sap.pos.getLineNum())
                || (actualColumn != sap.pos.getColumnNum())
                || (actualEndLine != sap.pos.getEndLineNum())
                || (actualEndColumn != sap.pos.getEndColumnNum()))) {
          fail(
              "Validator threw expected "
                  + "exception ["
                  + actualMessage
                  + "];\nbut at pos [line "
                  + actualLine
                  + " col "
                  + actualColumn
                  + " thru line "
                  + actualEndLine
                  + " col "
                  + actualEndColumn
                  + "];\nsql ["
                  + sqlWithCarets
                  + "]");
        }
      }
    }
  }
예제 #27
0
 public String apply(String original, int attempt, int size) {
   return Util.first(original, "EXPR$") + attempt;
 }
예제 #28
0
 /**
  * Creates a literal of a given type. The value is assumed to be compatible with the type.
  *
  * @param value Value
  * @param type Type
  * @param allowCast Whether to allow a cast. If false, value is always a {@link RexLiteral} but
  *     may not be the exact type
  * @return Simple literal, or cast simple literal
  */
 public RexNode makeLiteral(Object value, RelDataType type, boolean allowCast) {
   if (value == null) {
     return makeCast(type, constantNull);
   }
   if (type.isNullable()) {
     final RelDataType typeNotNull = typeFactory.createTypeWithNullability(type, false);
     RexNode literalNotNull = makeLiteral(value, typeNotNull, allowCast);
     return makeAbstractCast(type, literalNotNull);
   }
   value = clean(value, type);
   RexLiteral literal;
   final List<RexNode> operands;
   switch (type.getSqlTypeName()) {
     case CHAR:
       return makeCharLiteral(padRight((NlsString) value, type.getPrecision()));
     case VARCHAR:
       literal = makeCharLiteral((NlsString) value);
       if (allowCast) {
         return makeCast(type, literal);
       } else {
         return literal;
       }
     case BINARY:
       return makeBinaryLiteral(padRight((ByteString) value, type.getPrecision()));
     case VARBINARY:
       literal = makeBinaryLiteral((ByteString) value);
       if (allowCast) {
         return makeCast(type, literal);
       } else {
         return literal;
       }
     case TINYINT:
     case SMALLINT:
     case INTEGER:
     case BIGINT:
     case DECIMAL:
       return makeExactLiteral((BigDecimal) value, type);
     case FLOAT:
     case REAL:
     case DOUBLE:
       return makeApproxLiteral((BigDecimal) value, type);
     case BOOLEAN:
       return (Boolean) value ? booleanTrue : booleanFalse;
     case TIME:
       return makeTimeLiteral((Calendar) value, type.getPrecision());
     case DATE:
       return makeDateLiteral((Calendar) value);
     case TIMESTAMP:
       return makeTimestampLiteral((Calendar) value, type.getPrecision());
     case INTERVAL_YEAR_MONTH:
     case INTERVAL_DAY_TIME:
       return makeIntervalLiteral((BigDecimal) value, type.getIntervalQualifier());
     case MAP:
       final MapSqlType mapType = (MapSqlType) type;
       @SuppressWarnings("unchecked")
       final Map<Object, Object> map = (Map) value;
       operands = new ArrayList<RexNode>();
       for (Map.Entry<Object, Object> entry : map.entrySet()) {
         operands.add(makeLiteral(entry.getKey(), mapType.getKeyType(), allowCast));
         operands.add(makeLiteral(entry.getValue(), mapType.getValueType(), allowCast));
       }
       return makeCall(SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR, operands);
     case ARRAY:
       final ArraySqlType arrayType = (ArraySqlType) type;
       @SuppressWarnings("unchecked")
       final List<Object> listValue = (List) value;
       operands = new ArrayList<RexNode>();
       for (Object entry : listValue) {
         operands.add(makeLiteral(entry, arrayType.getComponentType(), allowCast));
       }
       return makeCall(SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR, operands);
     case ANY:
       return makeLiteral(value, guessType(value), allowCast);
     default:
       throw Util.unexpected(type.getSqlTypeName());
   }
 }
예제 #29
0
 public String apply(String original, int attempt, int size) {
   return Util.first(original, "$f") + Math.max(size, attempt);
 }
예제 #30
0
 @Deprecated // to be removed before 2.0
 public JdbcCalc(
     RelOptCluster cluster, RelTraitSet traitSet, RelNode input, RexProgram program, int flags) {
   this(cluster, traitSet, input, program);
   Util.discard(flags);
 }