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();
}
}
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;
}
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;
}
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;
}
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));
}
Aggregations