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); }
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); } }
/** * 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(); } }); }
/** 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); }
public void onRegister(RelDataTypeFactory typeFactory) { rowType = typeFactory.createStructType(columnList); collationList = deduceMonotonicity(this); }