Ejemplo n.º 1
0
 /**
  * Given "INTEGER", returns BasicSqlType(INTEGER). Given "VARCHAR(10)", returns
  * BasicSqlType(VARCHAR, 10). Given "NUMERIC(10, 2)", returns BasicSqlType(NUMERIC, 10, 2).
  */
 private RelDataType parseTypeString(RelDataTypeFactory typeFactory, String typeString) {
   int precision = -1;
   int scale = -1;
   int open = typeString.indexOf("(");
   if (open >= 0) {
     int close = typeString.indexOf(")", open);
     if (close >= 0) {
       String rest = typeString.substring(open + 1, close);
       typeString = typeString.substring(0, open);
       int comma = rest.indexOf(",");
       if (comma >= 0) {
         precision = Integer.parseInt(rest.substring(0, comma));
         scale = Integer.parseInt(rest.substring(comma));
       } else {
         precision = Integer.parseInt(rest);
       }
     }
   }
   try {
     final SqlTypeName typeName = SqlTypeName.valueOf(typeString);
     return typeName.allowsPrecScale(true, true)
         ? typeFactory.createSqlType(typeName, precision, scale)
         : typeName.allowsPrecScale(true, false)
             ? typeFactory.createSqlType(typeName, precision)
             : typeFactory.createSqlType(typeName);
   } catch (IllegalArgumentException e) {
     return typeFactory.createSqlType(SqlTypeName.ANY);
   }
 }
Ejemplo n.º 2
0
 private RelDataType sqlType(
     RelDataTypeFactory typeFactory, int dataType, int precision, int scale, String typeString) {
   SqlTypeName sqlTypeName = SqlTypeName.getNameForJdbcType(dataType);
   switch (sqlTypeName) {
     case ARRAY:
       RelDataType component = null;
       if (typeString != null && typeString.endsWith(" ARRAY")) {
         // E.g. hsqldb gives "INTEGER ARRAY", so we deduce the component type
         // "INTEGER".
         final String remaining = typeString.substring(0, typeString.length() - " ARRAY".length());
         component = parseTypeString(typeFactory, remaining);
       }
       if (component == null) {
         component = typeFactory.createSqlType(SqlTypeName.ANY);
       }
       return typeFactory.createArrayType(component, -1);
   }
   if (precision >= 0 && scale >= 0 && sqlTypeName.allowsPrecScale(true, true)) {
     return typeFactory.createSqlType(sqlTypeName, precision, scale);
   } else if (precision >= 0 && sqlTypeName.allowsPrecNoScale()) {
     return typeFactory.createSqlType(sqlTypeName, precision);
   } else {
     assert sqlTypeName.allowsNoPrecNoScale();
     return typeFactory.createSqlType(sqlTypeName);
   }
 }
Ejemplo n.º 3
0
 public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
   assert opBinding.getOperandCount() == 1;
   final RelDataType multisetType = opBinding.getOperandType(0);
   RelDataType componentType = multisetType.getComponentType();
   assert componentType != null : "expected a multiset type: " + multisetType;
   final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
   final RelDataType type =
       typeFactory.builder().add(SqlUtil.deriveAliasFromOrdinal(0), componentType).build();
   return typeFactory.createMultisetType(type, -1);
 }
  public Boolean areColumnsUnique(ProjectRelBase rel, BitSet columns, boolean ignoreNulls) {
    // ProjectRel maps a set of rows to a different set;
    // Without knowledge of the mapping function(whether it
    // preserves uniqueness), it is only safe to derive uniqueness
    // info from the child of a project when the mapping is f(a) => a.
    //
    // Also need to map the input column set to the corresponding child
    // references

    List<RexNode> projExprs = rel.getProjects();
    BitSet childColumns = new BitSet();
    for (int bit : BitSets.toIter(columns)) {
      RexNode projExpr = projExprs.get(bit);
      if (projExpr instanceof RexInputRef) {
        childColumns.set(((RexInputRef) projExpr).getIndex());
      } else if (projExpr instanceof RexCall && ignoreNulls) {
        // If the expression is a cast such that the types are the same
        // except for the nullability, then if we're ignoring nulls,
        // it doesn't matter whether the underlying column reference
        // is nullable.  Check that the types are the same by making a
        // nullable copy of both types and then comparing them.
        RexCall call = (RexCall) projExpr;
        if (call.getOperator() != SqlStdOperatorTable.CAST) {
          continue;
        }
        RexNode castOperand = call.getOperands().get(0);
        if (!(castOperand instanceof RexInputRef)) {
          continue;
        }
        RelDataTypeFactory typeFactory = rel.getCluster().getTypeFactory();
        RelDataType castType = typeFactory.createTypeWithNullability(projExpr.getType(), true);
        RelDataType origType = typeFactory.createTypeWithNullability(castOperand.getType(), true);
        if (castType.equals(origType)) {
          childColumns.set(((RexInputRef) castOperand).getIndex());
        }
      } else {
        // If the expression will not influence uniqueness of the
        // projection, then skip it.
        continue;
      }
    }

    // If no columns can affect uniqueness, then return unknown
    if (childColumns.cardinality() == 0) {
      return null;
    }

    return RelMetadataQuery.areColumnsUnique(rel.getChild(), childColumns, ignoreNulls);
  }
Ejemplo n.º 5
0
  RelProtoDataType getRelDataType(
      DatabaseMetaData metaData, String catalogName, String schemaName, String tableName)
      throws SQLException {
    final ResultSet resultSet = metaData.getColumns(catalogName, schemaName, tableName, null);

    // Temporary type factory, just for the duration of this method. Allowable
    // because we're creating a proto-type, not a type; before being used, the
    // proto-type will be copied into a real type factory.
    final RelDataTypeFactory typeFactory = new SqlTypeFactoryImpl();
    final RelDataTypeFactory.FieldInfoBuilder fieldInfo = typeFactory.builder();
    while (resultSet.next()) {
      final String columnName = resultSet.getString(4);
      final int dataType = resultSet.getInt(5);
      final String typeString = resultSet.getString(6);
      final int size = resultSet.getInt(7);
      final int scale = resultSet.getInt(9);
      RelDataType sqlType = sqlType(typeFactory, dataType, size, scale, typeString);
      boolean nullable = resultSet.getBoolean(11);
      fieldInfo.add(columnName, sqlType).nullable(nullable);
    }
    resultSet.close();
    return RelDataTypeImpl.proto(fieldInfo.build());
  }
    private void reduceCasts(RexCall outerCast) {
      RexNode[] operands = outerCast.getOperands();
      if (operands.length != 1) {
        return;
      }
      RelDataType outerCastType = outerCast.getType();
      RelDataType operandType = operands[0].getType();
      if (operandType.equals(outerCastType)) {
        removableCasts.add(outerCast);
        return;
      }

      // See if the reduction
      // CAST((CAST x AS type) AS type NOT NULL)
      // -> CAST(x AS type NOT NULL)
      // applies.  TODO jvs 15-Dec-2008:  consider
      // similar cases for precision changes.
      if (!(operands[0] instanceof RexCall)) {
        return;
      }
      RexCall innerCast = (RexCall) operands[0];
      if (innerCast.getOperator() != SqlStdOperatorTable.castFunc) {
        return;
      }
      if (innerCast.getOperands().length != 1) {
        return;
      }
      RelDataTypeFactory typeFactory = preparingStmt.getFarragoTypeFactory();
      RelDataType outerTypeNullable = typeFactory.createTypeWithNullability(outerCastType, true);
      RelDataType innerTypeNullable = typeFactory.createTypeWithNullability(operandType, true);
      if (outerTypeNullable != innerTypeNullable) {
        return;
      }
      if (operandType.isNullable()) {
        removableCasts.add(innerCast);
      }
    }
Ejemplo n.º 7
0
 public static RelDataType createTypeFromProjection(
     RelDataType type,
     List<String> columnNameList,
     RelDataTypeFactory typeFactory,
     boolean caseSensitive) {
   // If the names in columnNameList and type have case-sensitive differences,
   // the resulting type will use those from type. These are presumably more
   // canonical.
   final List<RelDataTypeField> fields = new ArrayList<RelDataTypeField>(columnNameList.size());
   for (String name : columnNameList) {
     RelDataTypeField field = type.getField(name, caseSensitive);
     fields.add(type.getFieldList().get(field.getIndex()));
   }
   return typeFactory.createStructType(fields);
 }
Ejemplo n.º 8
0
  /**
   * Creates a record type with specified field names.
   *
   * <p>The array of field names may be null, or any of the names within it can be null. We
   * recommend using explicit names where possible, because it makes it much easier to figure out
   * the intent of fields when looking at planner output.
   *
   * @param typeFactory Type factory
   * @param exprs Expressions
   * @param names Field names, may be null, or elements may be null
   * @return Record type
   */
  public static RelDataType createStructType(
      RelDataTypeFactory typeFactory, final RexNode[] exprs, final String[] names) {
    return typeFactory.createStructType(
        new RelDataTypeFactory.FieldInfo() {
          public int getFieldCount() {
            return exprs.length;
          }

          public String getFieldName(int index) {
            if (names == null) {
              return "$f" + index;
            }
            final String name = names[index];
            if (name == null) {
              return "$f" + index;
            }
            return name;
          }

          public RelDataType getFieldType(int index) {
            return exprs[index].getType();
          }
        });
  }
Ejemplo n.º 9
0
  /** Initializes this catalog reader. */
  protected void init() {
    final RelDataType intType = typeFactory.createSqlType(SqlTypeName.INTEGER);
    final RelDataType varchar10Type = typeFactory.createSqlType(SqlTypeName.VARCHAR, 10);
    final RelDataType varchar20Type = typeFactory.createSqlType(SqlTypeName.VARCHAR, 20);
    final RelDataType timestampType = typeFactory.createSqlType(SqlTypeName.TIMESTAMP);
    final RelDataType booleanType = typeFactory.createSqlType(SqlTypeName.BOOLEAN);
    final RelDataType rectilinearCoordType =
        typeFactory.createStructType(new RelDataType[] {intType, intType}, new String[] {"X", "Y"});

    // TODO jvs 12-Feb-2005: register this canonical instance with type
    // factory
    addressType =
        new ObjectSqlType(
            SqlTypeName.STRUCTURED,
            new SqlIdentifier("ADDRESS", SqlParserPos.ZERO),
            false,
            Arrays.asList(
                new RelDataTypeFieldImpl("STREET", 0, varchar20Type),
                new RelDataTypeFieldImpl("CITY", 1, varchar20Type),
                new RelDataTypeFieldImpl("ZIP", 1, intType),
                new RelDataTypeFieldImpl("STATE", 1, varchar20Type)),
            RelDataTypeComparability.None);

    // Register "SALES" schema.
    MockSchema salesSchema = new MockSchema("SALES");
    registerSchema(salesSchema);

    // Register "EMP" table.
    MockTable empTable = new MockTable(this, salesSchema, "EMP");
    empTable.addColumn("EMPNO", intType);
    empTable.addColumn("ENAME", varchar20Type);
    empTable.addColumn("JOB", varchar10Type);
    empTable.addColumn("MGR", intType);
    empTable.addColumn("HIREDATE", timestampType);
    empTable.addColumn("SAL", intType);
    empTable.addColumn("COMM", intType);
    empTable.addColumn("DEPTNO", intType);
    empTable.addColumn("SLACKER", booleanType);
    registerTable(empTable);

    // Register "DEPT" table.
    MockTable deptTable = new MockTable(this, salesSchema, "DEPT");
    deptTable.addColumn("DEPTNO", intType);
    deptTable.addColumn("NAME", varchar10Type);
    registerTable(deptTable);

    // Register "BONUS" table.
    MockTable bonusTable = new MockTable(this, salesSchema, "BONUS");
    bonusTable.addColumn("ENAME", varchar20Type);
    bonusTable.addColumn("JOB", varchar10Type);
    bonusTable.addColumn("SAL", intType);
    bonusTable.addColumn("COMM", intType);
    registerTable(bonusTable);

    // Register "SALGRADE" table.
    MockTable salgradeTable = new MockTable(this, salesSchema, "SALGRADE");
    salgradeTable.addColumn("GRADE", intType);
    salgradeTable.addColumn("LOSAL", intType);
    salgradeTable.addColumn("HISAL", intType);
    registerTable(salgradeTable);

    // Register "EMP_ADDRESS" table
    MockTable contactAddressTable = new MockTable(this, salesSchema, "EMP_ADDRESS");
    contactAddressTable.addColumn("EMPNO", intType);
    contactAddressTable.addColumn("HOME_ADDRESS", addressType);
    contactAddressTable.addColumn("MAILING_ADDRESS", addressType);
    registerTable(contactAddressTable);

    // Register "CUSTOMER" schema.
    MockSchema customerSchema = new MockSchema("CUSTOMER");
    registerSchema(customerSchema);

    // Register "CONTACT" table.
    MockTable contactTable = new MockTable(this, customerSchema, "CONTACT");
    contactTable.addColumn("CONTACTNO", intType);
    contactTable.addColumn("FNAME", varchar10Type);
    contactTable.addColumn("LNAME", varchar10Type);
    contactTable.addColumn("EMAIL", varchar20Type);
    contactTable.addColumn("COORD", rectilinearCoordType);
    registerTable(contactTable);

    // Register "ACCOUNT" table.
    MockTable accountTable = new MockTable(this, customerSchema, "ACCOUNT");
    accountTable.addColumn("ACCTNO", intType);
    accountTable.addColumn("TYPE", varchar20Type);
    accountTable.addColumn("BALANCE", intType);
    registerTable(accountTable);
  }
Ejemplo n.º 10
0
 public void onRegister(RelDataTypeFactory typeFactory) {
   rowType = typeFactory.createStructType(columnList);
   collationList = deduceMonotonicity(this);
 }
Ejemplo n.º 11
0
 public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
   RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
   RelDataType type1 = opBinding.getOperandType(0);
   RelDataType type2 = opBinding.getOperandType(1);
   return typeFactory.createDecimalQuotient(type1, type2);
 }
  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();
    }
  }