use of org.apache.derby.iapi.types.DataTypeDescriptor in project derby by apache.
the class TableElementList method setCollationTypeOnCharacterStringColumn.
/**
* Use the passed schema descriptor's collation type to set the collation
* of a character string column.
* @param sd
*/
void setCollationTypeOnCharacterStringColumn(SchemaDescriptor sd, ColumnDefinitionNode cdn) throws StandardException {
int collationType = sd.getCollationType();
//
// Only generated columns can omit the datatype specification during the
// early phases of binding--before we have been able to bind the
// generation clause.
//
DataTypeDescriptor dtd = cdn.getType();
if (dtd == null) {
if (!cdn.hasGenerationClause()) {
throw StandardException.newException(SQLState.LANG_NEEDS_DATATYPE, cdn.getColumnName());
}
} else {
if (dtd.getTypeId().isStringTypeId()) {
cdn.setCollationType(collationType);
}
}
}
use of org.apache.derby.iapi.types.DataTypeDescriptor in project derby by apache.
the class TableElementList method bindAndValidateGenerationClauses.
/**
* Bind and validate all of the generation clauses in this list against
* the specified FromList.
*
* @param sd Schema where the table lives.
* @param fromList The FromList in question.
* @param generatedColumns Bitmap of generated columns in the table. Vacuous for CREATE TABLE, but may be non-trivial for ALTER TABLE. This routine may set bits for new generated columns.
* @param baseTable Table descriptor if this is an ALTER TABLE statement.
*
* @exception StandardException Thrown on error
*/
void bindAndValidateGenerationClauses(SchemaDescriptor sd, FromList fromList, FormatableBitSet generatedColumns, TableDescriptor baseTable) throws StandardException {
FromBaseTable table = (FromBaseTable) fromList.elementAt(0);
ResultColumnList tableColumns = table.getResultColumns();
int columnCount = table.getResultColumns().size();
// complain if a generation clause references another generated column
findIllegalGenerationReferences(fromList, baseTable);
generatedColumns.grow(columnCount + 1);
CompilerContext cc = getCompilerContext();
ArrayList<AggregateNode> aggregates = new ArrayList<AggregateNode>();
for (TableElementNode element : this) {
ColumnDefinitionNode cdn;
GenerationClauseNode generationClauseNode;
ValueNode generationTree;
if (!(element instanceof ColumnDefinitionNode)) {
continue;
}
cdn = (ColumnDefinitionNode) element;
if (!cdn.hasGenerationClause()) {
continue;
}
generationClauseNode = cdn.getGenerationClauseNode();
// bind the generation clause
final int previousReliability = cc.getReliability();
ProviderList prevAPL = cc.getCurrentAuxiliaryProviderList();
try {
/* Each generation clause can have its own set of dependencies.
* These dependencies need to be shared with the prepared
* statement as well. We create a new auxiliary provider list
* for the generation clause, "push" it on the compiler context
* by swapping it with the current auxiliary provider list
* and the "pop" it when we're done by restoring the old
* auxiliary provider list.
*/
ProviderList apl = new ProviderList();
cc.setCurrentAuxiliaryProviderList(apl);
// Tell the compiler context to forbid subqueries and
// non-deterministic functions.
cc.setReliability(CompilerContext.GENERATION_CLAUSE_RESTRICTION);
generationTree = generationClauseNode.bindExpression(fromList, (SubqueryList) null, aggregates);
SelectNode.checkNoWindowFunctions(generationClauseNode, "generation clause");
//
// If the user did not declare a type for this column, then the column type defaults
// to the type of the generation clause.
// However, if the user did declare a type for this column, then the
// type of the generation clause must be assignable to the declared
// type.
//
DataTypeDescriptor generationClauseType = generationTree.getTypeServices();
DataTypeDescriptor declaredType = cdn.getType();
if (declaredType == null) {
cdn.setType(generationClauseType);
//
// Poke the type into the FromTable so that constraints will
// compile.
//
tableColumns.getResultColumn(cdn.getColumnName(), false).setType(generationClauseType);
//
// We skipped these steps earlier on because we didn't have
// a datatype. Now that we have a datatype, revisit these
// steps.
//
setCollationTypeOnCharacterStringColumn(sd, cdn);
cdn.checkUserType(table.getTableDescriptor());
} else {
TypeId declaredTypeId = declaredType.getTypeId();
TypeId resolvedTypeId = generationClauseType.getTypeId();
if (!getTypeCompiler(resolvedTypeId).convertible(declaredTypeId, false)) {
throw StandardException.newException(SQLState.LANG_UNASSIGNABLE_GENERATION_CLAUSE, cdn.getName(), resolvedTypeId.getSQLTypeName());
}
}
// no aggregates, please
if (!aggregates.isEmpty()) {
throw StandardException.newException(SQLState.LANG_AGGREGATE_IN_GENERATION_CLAUSE, cdn.getName());
}
/* Save the APL off in the constraint node */
if (apl.size() > 0) {
generationClauseNode.setAuxiliaryProviderList(apl);
}
} finally {
// Restore previous compiler state
cc.setCurrentAuxiliaryProviderList(prevAPL);
cc.setReliability(previousReliability);
}
/* We have a valid generation clause, now build an array of
* 1-based columnIds that the clause references.
*/
ResultColumnList rcl = table.getResultColumns();
int numReferenced = rcl.countReferencedColumns();
int[] generationClauseColumnReferences = new int[numReferenced];
int position = rcl.getPosition(cdn.getColumnName(), 1);
generatedColumns.set(position);
rcl.recordColumnReferences(generationClauseColumnReferences, 1);
String[] referencedColumnNames = new String[numReferenced];
for (int i = 0; i < numReferenced; i++) {
referencedColumnNames[i] = rcl.elementAt(generationClauseColumnReferences[i] - 1).getName();
}
String currentSchemaName = getLanguageConnectionContext().getCurrentSchemaName();
DefaultInfoImpl dii = new DefaultInfoImpl(generationClauseNode.getExpressionText(), referencedColumnNames, currentSchemaName);
cdn.setDefaultInfo(dii);
/* Clear the column references in the RCL so each generation clause
* starts with a clean list.
*/
rcl.clearColumnReferences();
}
}
use of org.apache.derby.iapi.types.DataTypeDescriptor in project derby by apache.
the class UnaryArithmeticOperatorNode method bindSQRTABS.
/**
* Bind SQRT or ABS
*
* @exception StandardException Thrown on error
*/
private void bindSQRTABS() throws StandardException {
TypeId operandType;
int jdbcType;
/*
** Check the type of the operand
*/
operandType = operand.getTypeId();
/*
* If the operand is not a build-in type, generate a bound conversion
* tree to build-in types.
*/
if (operandType.userType()) {
operand = operand.genSQLJavaSQLTree();
}
/* DB2 doesn't cast string types to numeric types for numeric functions */
jdbcType = operandType.getJDBCTypeId();
/* Both SQRT and ABS are only allowed on numeric types */
if (!operandType.isNumericTypeId())
throw StandardException.newException(SQLState.LANG_UNARY_FUNCTION_BAD_TYPE, getOperatorString(), operandType.getSQLTypeName());
/* For SQRT, if operand is not a DOUBLE, convert it to DOUBLE */
if (kind == K_SQRT && jdbcType != Types.DOUBLE) {
operand = new CastNode(operand, new DataTypeDescriptor(TypeId.getBuiltInTypeId(Types.DOUBLE), true), getContextManager());
((CastNode) operand).bindCastNodeOnly();
}
}
use of org.apache.derby.iapi.types.DataTypeDescriptor in project derby by apache.
the class SimpleStringOperatorNode 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 {
TypeId operandType;
bindOperand(fromList, subqueryList, aggregates);
/*
** Check the type of the operand - this function is allowed only on
** string value (char and bit) types.
*/
operandType = operand.getTypeId();
switch(operandType.getJDBCTypeId()) {
case Types.CHAR:
case Types.VARCHAR:
case Types.LONGVARCHAR:
case Types.CLOB:
break;
case Types.JAVA_OBJECT:
case Types.OTHER:
{
throw StandardException.newException(SQLState.LANG_UNARY_FUNCTION_BAD_TYPE, methodName, operandType.getSQLTypeName());
}
default:
DataTypeDescriptor dtd = DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.VARCHAR, true, operand.getTypeCompiler().getCastToCharWidth(operand.getTypeServices()));
operand = new CastNode(operand, dtd, getContextManager());
// DERBY-2910 - Match current schema collation for implicit cast as we do for
// explicit casts per SQL Spec 6.12 (10)
operand.setCollationUsingCompilationSchema();
((CastNode) operand).bindCastNodeOnly();
operandType = operand.getTypeId();
}
/*
** The result type of upper()/lower() is the type of the operand.
*/
setType(new DataTypeDescriptor(operandType, operand.getTypeServices().isNullable(), operand.getTypeCompiler().getCastToCharWidth(operand.getTypeServices())));
// Result of upper()/lower() will have the same collation as the
// argument to upper()/lower().
setCollationInfo(operand.getTypeServices());
return this;
}
use of org.apache.derby.iapi.types.DataTypeDescriptor in project derby by apache.
the class ResultColumn method columnTypeAndLengthMatch.
boolean columnTypeAndLengthMatch(ResultColumn otherColumn) throws StandardException {
ValueNode otherExpression = otherColumn.getExpression();
DataTypeDescriptor resultColumnType = getTypeServices();
DataTypeDescriptor otherResultColumnType = otherColumn.getTypeServices();
if (SanityManager.DEBUG) {
SanityManager.ASSERT(resultColumnType != null, "Type is null for column " + this);
SanityManager.ASSERT(otherResultColumnType != null, "Type is null for column " + otherColumn);
}
/*
** We can never make any assumptions about
** parameters. So don't even bother in this
** case.
*/
if ((otherExpression != null) && (otherExpression.requiresTypeFromContext()) || (_expression.requiresTypeFromContext())) {
return false;
}
// method in org.apache.derby.iapi.types.XML for more.
if (resultColumnType.getTypeId().isXMLTypeId())
return false;
/* Are they the same type? */
if (!resultColumnType.getTypeId().equals(otherResultColumnType.getTypeId())) {
/* If the source is a constant of a different type then
* we try to convert that constant to a constant of our
* type. (The initial implementation only does the conversion
* to string types because the most common problem is a char
* constant with a varchar column.)
* NOTE: We do not attempt any conversion here if the source
* is a string type and the target is not or vice versa in
* order to avoid problems with implicit varchar conversions.
* Anyway, we will check if the "converted" constant has the
* same type as the original constant. If not, then the conversion
* happened. In that case, we will reuse the ConstantNode, for simplicity,
* and reset the type to match the desired type.
*/
if (otherExpression instanceof ConstantNode) {
ConstantNode constant = (ConstantNode) otherColumn.getExpression();
DataValueDescriptor oldValue = constant.getValue();
DataValueDescriptor newValue = convertConstant(resultColumnType.getTypeId(), resultColumnType.getMaximumWidth(), oldValue);
if ((oldValue != newValue) && (oldValue instanceof StringDataValue == newValue instanceof StringDataValue)) {
constant.setValue(newValue);
constant.setType(getTypeServices());
otherColumn.bindResultColumnToExpression();
otherResultColumnType = otherColumn.getType();
}
// depending on the collation type.
if (newValue instanceof StringDataValue) {
constant.setCollationInfo(resultColumnType);
DataValueFactory dvf = getDataValueFactory();
newValue = ((StringDataValue) newValue).getValue(dvf.getCharacterCollator(constant.getTypeServices().getCollationType()));
constant.setValue(newValue);
}
}
if (!resultColumnType.getTypeId().equals(otherResultColumnType.getTypeId())) {
return false;
}
}
/* Are they the same precision? */
if (resultColumnType.getPrecision() != otherResultColumnType.getPrecision()) {
return false;
}
/* Are they the same scale? */
if (resultColumnType.getScale() != otherResultColumnType.getScale()) {
return false;
}
/* Are they the same width? */
if (resultColumnType.getMaximumWidth() != otherResultColumnType.getMaximumWidth()) {
return false;
}
/* Is the source nullable and the target non-nullable?
* The source is nullable if it is nullable or if the target is generated
* for an unmatched column in an insert with a column list.
* This additional check is needed because when we generate any additional
* source RCs for an insert with a column list the generated RCs for any
* non-specified columns get the type info from the column. Thus,
* for t1(non_nullable, nullable)
* insert into t2 (nullable) values 1;
* RCType.isNullable() returns false for the generated source RC for
* non_nullable. In this case, we want to see it as
*/
if ((!resultColumnType.isNullable()) && (otherResultColumnType.isNullable() || otherColumn.isGeneratedForUnmatchedColumnInInsert())) {
return false;
}
return true;
}
Aggregations