Search in sources :

Example 31 with DataTypeDescriptor

use of org.apache.derby.iapi.types.DataTypeDescriptor in project derby by apache.

the class CreateTableNode method bindStatement.

// We inherit the generate() method from DDLStatementNode.
/**
 * Bind this CreateTableNode.  This means doing any static error checking that can be
 * done before actually creating the base table or declaring the global temporary table.
 * For eg, verifying that the TableElementList does not contain any duplicate column names.
 *
 * @exception StandardException		Thrown on error
 */
@Override
public void bindStatement() throws StandardException {
    DataDictionary dataDictionary = getDataDictionary();
    int numPrimaryKeys;
    int numCheckConstraints;
    int numReferenceConstraints;
    int numUniqueConstraints;
    int numGenerationClauses;
    SchemaDescriptor sd = getSchemaDescriptor(tableType != TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE, true);
    if (queryExpression != null) {
        FromList fromList = new FromList(getOptimizerFactory().doJoinOrderOptimization(), getContextManager());
        CompilerContext cc = getCompilerContext();
        ProviderList prevAPL = cc.getCurrentAuxiliaryProviderList();
        ProviderList apl = new ProviderList();
        try {
            cc.setCurrentAuxiliaryProviderList(apl);
            cc.pushCurrentPrivType(Authorizer.SELECT_PRIV);
            /* Bind the tables in the queryExpression */
            queryExpression = queryExpression.bindNonVTITables(dataDictionary, fromList);
            queryExpression = queryExpression.bindVTITables(fromList);
            /* Bind the expressions under the resultSet */
            queryExpression.bindExpressions(fromList);
            /* Bind the query expression */
            queryExpression.bindResultColumns(fromList);
            /* Reject any untyped nulls in the RCL */
            /* e.g. CREATE TABLE t1 (x) AS VALUES NULL WITH NO DATA */
            queryExpression.bindUntypedNullsToResultColumns(null);
        } finally {
            cc.popCurrentPrivType();
            cc.setCurrentAuxiliaryProviderList(prevAPL);
        }
        /* If there is an RCL for the table definition then copy the
			 * names to the queryExpression's RCL after verifying that
			 * they both have the same size.
			 */
        ResultColumnList qeRCL = queryExpression.getResultColumns();
        if (resultColumns != null) {
            if (resultColumns.size() != qeRCL.visibleSize()) {
                throw StandardException.newException(SQLState.LANG_TABLE_DEFINITION_R_C_L_MISMATCH, getFullName());
            }
            qeRCL.copyResultColumnNames(resultColumns);
        }
        int schemaCollationType = sd.getCollationType();
        /* Create table element list from columns in query expression */
        tableElementList = new TableElementList(getContextManager());
        for (ResultColumn rc : qeRCL) {
            if (rc.isGenerated()) {
                continue;
            }
            /* Raise error if column name is system generated. */
            if (rc.isNameGenerated()) {
                throw StandardException.newException(SQLState.LANG_TABLE_REQUIRES_COLUMN_NAMES);
            }
            DataTypeDescriptor dtd = rc.getExpression().getTypeServices();
            if ((dtd != null) && !dtd.isUserCreatableType()) {
                throw StandardException.newException(SQLState.LANG_INVALID_COLUMN_TYPE_CREATE_TABLE, dtd.getFullSQLTypeName(), rc.getName());
            }
            // a territory based database.
            if (dtd.getTypeId().isStringTypeId() && dtd.getCollationType() != schemaCollationType) {
                throw StandardException.newException(SQLState.LANG_CAN_NOT_CREATE_TABLE, dtd.getCollationName(), DataTypeDescriptor.getCollationName(schemaCollationType));
            }
            ColumnDefinitionNode column = new ColumnDefinitionNode(rc.getName(), null, rc.getType(), null, getContextManager());
            tableElementList.addTableElement(column);
        }
    } else {
        // Set the collation type and collation derivation of all the
        // character type columns. Their collation type will be same as the
        // collation of the schema they belong to. Their collation
        // derivation will be "implicit".
        // Earlier we did this in makeConstantAction but that is little too
        // late (DERBY-2955)
        // eg
        // CREATE TABLE STAFF9 (EMPNAME CHAR(20),
        // CONSTRAINT STAFF9_EMPNAME CHECK (EMPNAME NOT LIKE 'T%'))
        // For the query above, when run in a territory based db, we need
        // to have the correct collation set in bind phase of create table
        // so that when LIKE is handled in LikeEscapeOperatorNode, we have
        // the correct collation set for EMPNAME otherwise it will throw an
        // exception for 'T%' having collation of territory based and
        // EMPNAME having the default collation of UCS_BASIC
        tableElementList.setCollationTypesOnCharacterStringColumns(getSchemaDescriptor(tableType != TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE, true));
    }
    tableElementList.validate(this, dataDictionary, (TableDescriptor) null);
    /* Only 1012 columns allowed per table */
    if (tableElementList.countNumberOfColumns() > Limits.DB2_MAX_COLUMNS_IN_TABLE) {
        throw StandardException.newException(SQLState.LANG_TOO_MANY_COLUMNS_IN_TABLE_OR_VIEW, String.valueOf(tableElementList.countNumberOfColumns()), getRelativeName(), String.valueOf(Limits.DB2_MAX_COLUMNS_IN_TABLE));
    }
    numPrimaryKeys = tableElementList.countConstraints(DataDictionary.PRIMARYKEY_CONSTRAINT);
    /* Only 1 primary key allowed per table */
    if (numPrimaryKeys > 1) {
        throw StandardException.newException(SQLState.LANG_TOO_MANY_PRIMARY_KEY_CONSTRAINTS, getRelativeName());
    }
    /* Check the validity of all check constraints */
    numCheckConstraints = tableElementList.countConstraints(DataDictionary.CHECK_CONSTRAINT);
    numReferenceConstraints = tableElementList.countConstraints(DataDictionary.FOREIGNKEY_CONSTRAINT);
    numUniqueConstraints = tableElementList.countConstraints(DataDictionary.UNIQUE_CONSTRAINT);
    numGenerationClauses = tableElementList.countGenerationClauses();
    // temp tables can't have primary key or check or foreign key or unique constraints defined on them
    if ((tableType == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE) && (numPrimaryKeys > 0 || numCheckConstraints > 0 || numReferenceConstraints > 0 || numUniqueConstraints > 0))
        throw StandardException.newException(SQLState.LANG_NOT_ALLOWED_FOR_DECLARED_GLOBAL_TEMP_TABLE);
    // more than 32767 indexes on it and that is why this check.
    if ((numPrimaryKeys + numReferenceConstraints + numUniqueConstraints) > Limits.DB2_MAX_INDEXES_ON_TABLE) {
        throw StandardException.newException(SQLState.LANG_TOO_MANY_INDEXES_ON_TABLE, String.valueOf(numPrimaryKeys + numReferenceConstraints + numUniqueConstraints), getRelativeName(), String.valueOf(Limits.DB2_MAX_INDEXES_ON_TABLE));
    }
    if ((numCheckConstraints > 0) || (numGenerationClauses > 0) || (numReferenceConstraints > 0)) {
        /* In order to check the validity of the check constraints and
			 * generation clauses
			 * we must goober up a FromList containing a single table,
			 * the table being created, with an RCL containing the
			 * new columns and their types.  This will allow us to
			 * bind the constraint definition trees against that
			 * FromList.  When doing this, we verify that there are
			 * no nodes which can return non-deterministic results.
			 */
        FromList fromList = makeFromList(null, tableElementList, true);
        FormatableBitSet generatedColumns = new FormatableBitSet();
        /* Now that we've finally goobered stuff up, bind and validate
			 * the check constraints and generation clauses.
			 */
        if (numGenerationClauses > 0) {
            tableElementList.bindAndValidateGenerationClauses(sd, fromList, generatedColumns, null);
        }
        if (numCheckConstraints > 0) {
            tableElementList.bindAndValidateCheckConstraints(fromList);
        }
        if (numReferenceConstraints > 0) {
            tableElementList.validateForeignKeysOnGenerationClauses(fromList, generatedColumns);
        }
    }
    if (numPrimaryKeys > 0) {
        tableElementList.validatePrimaryKeyNullability();
    }
}
Also used : SchemaDescriptor(org.apache.derby.iapi.sql.dictionary.SchemaDescriptor) ProviderList(org.apache.derby.iapi.sql.depend.ProviderList) DataTypeDescriptor(org.apache.derby.iapi.types.DataTypeDescriptor) CompilerContext(org.apache.derby.iapi.sql.compile.CompilerContext) FormatableBitSet(org.apache.derby.iapi.services.io.FormatableBitSet) DataDictionary(org.apache.derby.iapi.sql.dictionary.DataDictionary)

Example 32 with DataTypeDescriptor

use of org.apache.derby.iapi.types.DataTypeDescriptor in project derby by apache.

the class CastNode method bindExpression.

/**
 * Bind this expression.  This means binding the sub-expressions,
 * as well as figuring out what the return type is for this expression.
 *
 * @param fromList		The FROM list for the query this
 *				expression is in, for binding columns.
 * @param subqueryList		The subquery list being built as we find SubqueryNodes
 * @param aggregates        The aggregate list being built as we find AggregateNodes
 *
 * @return	The new top of the expression tree.
 *
 * @exception StandardException		Thrown on error
 */
@Override
@SuppressWarnings("fallthrough")
ValueNode bindExpression(FromList fromList, SubqueryList subqueryList, List<AggregateNode> aggregates) throws StandardException {
    castOperand = castOperand.bindExpression(fromList, subqueryList, aggregates);
    // Bind the target UDT.
    if (targetUDT != null) {
        setType(targetUDT);
    }
    if (// CHAR or VARCHAR function without specifying target length
    getTypeServices() == null) {
        DataTypeDescriptor opndType = castOperand.getTypeServices();
        int length = -1;
        TypeId srcTypeId = opndType.getTypeId();
        if (srcTypeId.isNumericTypeId()) {
            // 1 for the sign
            length = opndType.getPrecision() + 1;
            if (opndType.getScale() > 0)
                // 1 for the decimal .
                length += 1;
        } else /*
             * Derby-1132 : The length for the target type was calculated
             * incorrectly while Char & Varchar functions were used. Thus
             * adding the check for Char & Varchar and calculating the
             * length based on the operand type.
             */
        if (srcTypeId.isStringTypeId()) {
            length = opndType.getMaximumWidth();
            // data type
            if (this.targetCharType == Types.CHAR)
                length = Math.min(length, Limits.DB2_CHAR_MAXWIDTH);
            else if (this.targetCharType == Types.VARCHAR)
                length = Math.min(length, Limits.DB2_VARCHAR_MAXWIDTH);
        } else {
            TypeId typeid = opndType.getTypeId();
            if (length < 0) {
                length = DataTypeUtilities.getColumnDisplaySize(typeid.getJDBCTypeId(), -1);
            }
        }
        if (length < 0)
            // same default as in parser
            length = 1;
        setType(DataTypeDescriptor.getBuiltInDataTypeDescriptor(targetCharType, length));
    }
    /* 
		** If castOperand is an untyped null, 
		** then we must set the type.
		*/
    if (castOperand instanceof UntypedNullConstantNode) {
        castOperand.setType(getTypeServices());
    }
    bindCastNodeOnly();
    /* We can't chop out cast above an untyped null because
		 * the store can't handle it.
		 */
    if ((castOperand instanceof ConstantNode) && !(castOperand instanceof UntypedNullConstantNode)) {
        /* If the castOperand is a typed constant then we do the cast at
			 * bind time and return a constant of the correct type.
			 * NOTE: This could return an exception, but we're prepared to 
			 * deal with that. (NumberFormatException, etc.)
			 * We only worry about the easy (and useful)
			 * converions at bind time.
			 * Here's what we support:
			 *			source					destination
			 *			------					-----------
			 *			boolean					boolean
			 *			boolean					char
			 *			char					boolean
			 *			char					date/time/ts
			 *			char					non-decimal numeric
			 *			date/time/ts			char
			 *			numeric					char
			 *			numeric					non-decimal numeric
			 */
        /* RESOLVE - to be filled in. */
        ValueNode retNode = this;
        int sourceJDBCTypeId = sourceCTI.getJDBCTypeId();
        int destJDBCTypeId = getTypeId().getJDBCTypeId();
        switch(sourceJDBCTypeId) {
            case Types.BIT:
            case Types.BOOLEAN:
                // (BIT is boolean)
                if (destJDBCTypeId == Types.BIT || destJDBCTypeId == Types.BOOLEAN) {
                    retNode = castOperand;
                } else if (destJDBCTypeId == Types.CHAR) {
                    BooleanConstantNode bcn = (BooleanConstantNode) castOperand;
                    String booleanString = bcn.getValueAsString();
                    retNode = new CharConstantNode(booleanString, getTypeServices().getMaximumWidth(), getContextManager());
                }
                break;
            case Types.CHAR:
                retNode = getCastFromCharConstant(destJDBCTypeId);
                break;
            case Types.DATE:
            case Types.TIME:
            case Types.TIMESTAMP:
                if (destJDBCTypeId == Types.CHAR) {
                    String castValue = ((UserTypeConstantNode) castOperand).getObjectValue().toString();
                    retNode = new CharConstantNode(castValue, getTypeServices().getMaximumWidth(), getContextManager());
                }
                break;
            case Types.DECIMAL:
                // ignore decimal -> decimal casts for now
                if (destJDBCTypeId == Types.DECIMAL || destJDBCTypeId == Types.NUMERIC)
                    break;
            // fall through
            case Types.TINYINT:
            case Types.SMALLINT:
            case Types.INTEGER:
            case Types.BIGINT:
            case Types.DOUBLE:
            case Types.REAL:
                retNode = getCastFromNumericType(((ConstantNode) castOperand).getValue(), destJDBCTypeId);
                break;
        }
        // Return the new constant if the cast was performed
        return retNode;
    }
    return this;
}
Also used : TypeId(org.apache.derby.iapi.types.TypeId) DataTypeDescriptor(org.apache.derby.iapi.types.DataTypeDescriptor)

Example 33 with DataTypeDescriptor

use of org.apache.derby.iapi.types.DataTypeDescriptor in project derby by apache.

the class ExtractOperatorNode method bindExpression.

/**
 * Bind this operator
 *
 * @param fromList			The query's FROM list
 * @param subqueryList		The subquery list being built as we find SubqueryNodes
 * @param aggregates        The aggregate list being built as we find AggregateNodes
 *
 * @return	The new top of the expression tree.
 *
 * @exception StandardException		Thrown on error
 */
@Override
ValueNode bindExpression(FromList fromList, SubqueryList subqueryList, List<AggregateNode> aggregates) throws StandardException {
    int operandType;
    TypeId opTypeId;
    bindOperand(fromList, subqueryList, aggregates);
    opTypeId = operand.getTypeId();
    operandType = opTypeId.getJDBCTypeId();
    /*
		** Cast the operand, if necessary, - this function is allowed only on
		** date/time types.  By default, we cast to DATE if extracting
		** YEAR, MONTH or DAY and to TIME if extracting HOUR, MINUTE or
		** SECOND.
		*/
    if (opTypeId.isStringTypeId()) {
        TypeCompiler tc = operand.getTypeCompiler();
        int castType = (extractField < 3) ? Types.DATE : Types.TIME;
        operand = new CastNode(operand, DataTypeDescriptor.getBuiltInDataTypeDescriptor(castType, true, tc.getCastToCharWidth(operand.getTypeServices())), getContextManager());
        ((CastNode) operand).bindCastNodeOnly();
        opTypeId = operand.getTypeId();
        operandType = opTypeId.getJDBCTypeId();
    }
    if (!((operandType == Types.DATE) || (operandType == Types.TIME) || (operandType == Types.TIMESTAMP))) {
        throw StandardException.newException(SQLState.LANG_UNARY_FUNCTION_BAD_TYPE, "EXTRACT " + fieldName[extractField], opTypeId.getSQLTypeName());
    }
    /*
			If the type is DATE, ensure the field is okay.
		 */
    if ((operandType == Types.DATE) && (extractField > DateTimeDataValue.DAY_FIELD)) {
        throw StandardException.newException(SQLState.LANG_UNARY_FUNCTION_BAD_TYPE, "EXTRACT " + fieldName[extractField], opTypeId.getSQLTypeName());
    }
    /*
			If the type is TIME, ensure the field is okay.
		 */
    if ((operandType == Types.TIME) && (extractField < DateTimeDataValue.HOUR_FIELD)) {
        throw StandardException.newException(SQLState.LANG_UNARY_FUNCTION_BAD_TYPE, "EXTRACT " + fieldName[extractField], opTypeId.getSQLTypeName());
    }
    /*
		** The result type of extract is int,
		** unless it is TIMESTAMP and SECOND, in which case
		** for now it is DOUBLE but eventually it will need to
		** be DECIMAL(11,9).
		*/
    if ((operandType == Types.TIMESTAMP) && (extractField == DateTimeDataValue.SECOND_FIELD)) {
        setType(new DataTypeDescriptor(TypeId.getBuiltInTypeId(Types.DOUBLE), operand.getTypeServices().isNullable()));
    } else {
        setType(new DataTypeDescriptor(TypeId.INTEGER_ID, operand.getTypeServices().isNullable()));
    }
    return this;
}
Also used : TypeId(org.apache.derby.iapi.types.TypeId) DataTypeDescriptor(org.apache.derby.iapi.types.DataTypeDescriptor) TypeCompiler(org.apache.derby.iapi.sql.compile.TypeCompiler)

Example 34 with DataTypeDescriptor

use of org.apache.derby.iapi.types.DataTypeDescriptor in project derby by apache.

the class BinaryArithmeticOperatorNode method bindExpression.

/**
 * Bind this operator
 *
 * @param fromList			The query's FROM list
 * @param subqueryList		The subquery list being built as we find SubqueryNodes
 * @param aggregates        The aggregate list being built as we find AggregateNodes
 *
 * @return	The new top of the expression tree.
 *
 * @exception StandardException		Thrown on error
 */
@Override
ValueNode bindExpression(FromList fromList, SubqueryList subqueryList, List<AggregateNode> aggregates) throws StandardException {
    super.bindExpression(fromList, subqueryList, aggregates);
    TypeId leftType = leftOperand.getTypeId();
    TypeId rightType = rightOperand.getTypeId();
    DataTypeDescriptor leftDTS = leftOperand.getTypeServices();
    DataTypeDescriptor rightDTS = rightOperand.getTypeServices();
    /* Do any implicit conversions from (long) (var)char. */
    if (leftType.isStringTypeId() && rightType.isNumericTypeId()) {
        boolean nullableResult;
        nullableResult = leftDTS.isNullable() || rightDTS.isNullable();
        /* If other side is decimal/numeric, then we need to diddle
			 * with the precision, scale and max width in order to handle
			 * computations like:  1.1 + '0.111'
			 */
        int precision = rightDTS.getPrecision();
        int scale = rightDTS.getScale();
        int maxWidth = rightDTS.getMaximumWidth();
        if (rightType.isDecimalTypeId()) {
            int charMaxWidth = leftDTS.getMaximumWidth();
            precision += (2 * charMaxWidth);
            scale += charMaxWidth;
            maxWidth = precision + 3;
        }
        leftOperand = new CastNode(leftOperand, new DataTypeDescriptor(rightType, precision, scale, nullableResult, maxWidth), getContextManager());
        ((CastNode) leftOperand).bindCastNodeOnly();
    } else if (rightType.isStringTypeId() && leftType.isNumericTypeId()) {
        boolean nullableResult;
        nullableResult = leftDTS.isNullable() || rightDTS.isNullable();
        /* If other side is decimal/numeric, then we need to diddle
			 * with the precision, scale and max width in order to handle
			 * computations like:  1.1 + '0.111'
			 */
        int precision = leftDTS.getPrecision();
        int scale = leftDTS.getScale();
        int maxWidth = leftDTS.getMaximumWidth();
        if (leftType.isDecimalTypeId()) {
            int charMaxWidth = rightDTS.getMaximumWidth();
            precision += (2 * charMaxWidth);
            scale += charMaxWidth;
            maxWidth = precision + 3;
        }
        rightOperand = new CastNode(rightOperand, new DataTypeDescriptor(leftType, precision, scale, nullableResult, maxWidth), getContextManager());
        ((CastNode) rightOperand).bindCastNodeOnly();
    }
    /*
		** Set the result type of this operator based on the operands.
		** By convention, the left operand gets to decide the result type
		** of a binary operator.
		*/
    setType(leftOperand.getTypeCompiler().resolveArithmeticOperation(leftOperand.getTypeServices(), rightOperand.getTypeServices(), operator));
    return this;
}
Also used : TypeId(org.apache.derby.iapi.types.TypeId) DataTypeDescriptor(org.apache.derby.iapi.types.DataTypeDescriptor)

Example 35 with DataTypeDescriptor

use of org.apache.derby.iapi.types.DataTypeDescriptor in project derby by apache.

the class BinaryComparisonOperatorNode method bindComparisonOperator.

/**
 * Test the type compatability of the operands and set the type info
 * for this node.  This method is useful both during binding and
 * when we generate nodes within the language module outside of the parser.
 *
 * @exception StandardException		Thrown on error
 */
void bindComparisonOperator() throws StandardException {
    boolean nullableResult;
    /*
		** Can the types be compared to each other?  If not, throw an
		** exception.
		*/
    boolean forEquals = operator.equals("=") || operator.equals("<>");
    boolean cmp = leftOperand.getTypeServices().comparable(rightOperand.getTypeServices(), forEquals, getClassFactory());
    // optimizer.  We will assume Mr. Optimizer knows what he is doing.
    if (!cmp && !forQueryRewrite) {
        throw StandardException.newException(SQLState.LANG_NOT_COMPARABLE, leftOperand.getTypeServices().getSQLTypeNameWithCollation(), rightOperand.getTypeServices().getSQLTypeNameWithCollation());
    }
    /*
		** Set the result type of this comparison operator based on the
		** operands.  The result type is always SQLBoolean - the only question
		** is whether it is nullable or not.  If either of the operands is
		** nullable, the result of the comparison must be nullable, too, so
		** we can represent the unknown truth value.
		*/
    nullableResult = leftOperand.getTypeServices().isNullable() || rightOperand.getTypeServices().isNullable();
    setType(new DataTypeDescriptor(TypeId.BOOLEAN_ID, nullableResult));
}
Also used : DataTypeDescriptor(org.apache.derby.iapi.types.DataTypeDescriptor)

Aggregations

DataTypeDescriptor (org.apache.derby.iapi.types.DataTypeDescriptor)99 TypeId (org.apache.derby.iapi.types.TypeId)32 ColumnDescriptor (org.apache.derby.iapi.sql.dictionary.ColumnDescriptor)14 DataValueDescriptor (org.apache.derby.iapi.types.DataValueDescriptor)14 CompilerContext (org.apache.derby.iapi.sql.compile.CompilerContext)9 SchemaDescriptor (org.apache.derby.iapi.sql.dictionary.SchemaDescriptor)8 ExecRow (org.apache.derby.iapi.sql.execute.ExecRow)8 TypeDescriptor (org.apache.derby.catalog.TypeDescriptor)7 UUID (org.apache.derby.catalog.UUID)5 ClassFactory (org.apache.derby.iapi.services.loader.ClassFactory)5 ResultColumnDescriptor (org.apache.derby.iapi.sql.ResultColumnDescriptor)5 TypeCompiler (org.apache.derby.iapi.sql.compile.TypeCompiler)5 StandardException (org.apache.derby.shared.common.error.StandardException)5 Properties (java.util.Properties)4 UserDefinedTypeIdImpl (org.apache.derby.catalog.types.UserDefinedTypeIdImpl)4 FormatableBitSet (org.apache.derby.iapi.services.io.FormatableBitSet)4 AliasDescriptor (org.apache.derby.iapi.sql.dictionary.AliasDescriptor)3 ColumnDescriptorList (org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList)3 DataDictionary (org.apache.derby.iapi.sql.dictionary.DataDictionary)3 ExecIndexRow (org.apache.derby.iapi.sql.execute.ExecIndexRow)3