use of org.apache.derby.iapi.types.TypeId 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.TypeId 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.TypeId 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.TypeId in project derby by apache.
the class CreateAliasNode method bindStatement.
// We inherit the generate() method from DDLStatementNode.
/**
* Bind this CreateAliasNode. This means doing any static error
* checking that can be done before actually creating the table.
* For example, verifying that the column name list does not
* contain any duplicate column names.
*
* @exception StandardException Thrown on error
*/
@Override
public void bindStatement() throws StandardException {
// Are we dealing with user defined function or procedure?
if (aliasType == AliasInfo.ALIAS_TYPE_FUNCTION_AS_CHAR || aliasType == AliasInfo.ALIAS_TYPE_PROCEDURE_AS_CHAR) {
RoutineAliasInfo rai = (RoutineAliasInfo) aliasInfo;
// Set the collation for all string types in parameters
// and return types including row multi-sets to be that of
// the schema the routine is being defined in.
rai.setCollationTypeForAllStringTypes(getSchemaDescriptor().getCollationType());
bindParameterTypes((RoutineAliasInfo) aliasInfo);
if (rai.hasVarargs()) {
switch(rai.getParameterStyle()) {
case RoutineAliasInfo.PS_DERBY_JDBC_RESULT_SET:
case RoutineAliasInfo.PS_DERBY:
break;
default:
throw StandardException.newException(SQLState.LANG_VARARGS_PARAMETER_STYLE);
}
if (rai.getMaxDynamicResultSets() > 0) {
throw StandardException.newException(SQLState.LANG_VARARGS_RETURN_RESULT_SETS);
}
}
if ((rai.getParameterStyle() == RoutineAliasInfo.PS_DERBY) && !rai.hasVarargs()) {
throw StandardException.newException(SQLState.LANG_DERBY_PARAMETER_STYLE);
}
}
// validity checking for UDTs
if (aliasType == AliasInfo.ALIAS_TYPE_UDT_AS_CHAR) {
//
// Make sure that the java class name is not the name of a builtin
// type. This skirts problems caused by logic across the system
// which assumes a tight association between the builtin SQL types
// and the Java classes which implement them.
//
// For security reasons we do not allow the user to bind a UDT
// to a Derby class.
//
TypeId[] allSystemTypeIds = TypeId.getAllBuiltinTypeIds();
int systemTypeCount = allSystemTypeIds.length;
boolean foundConflict = javaClassName.startsWith("org.apache.derby.");
if (!foundConflict) {
for (int i = 0; i < systemTypeCount; i++) {
TypeId systemType = allSystemTypeIds[i];
String systemTypeName = systemType.getCorrespondingJavaTypeName();
if (systemTypeName.equals(javaClassName)) {
foundConflict = true;
break;
}
}
}
if (foundConflict) {
throw StandardException.newException(SQLState.LANG_UDT_BUILTIN_CONFLICT, javaClassName);
}
return;
}
// validity checking for aggregates
if (aliasType == AliasInfo.ALIAS_TYPE_AGGREGATE_AS_CHAR) {
bindAggregate();
}
// runtime execution. Synonyms do need some validity checks.
if (aliasType != AliasInfo.ALIAS_TYPE_SYNONYM_AS_CHAR)
return;
// a temporary table is created later with same name.
if (isSessionSchema(getSchemaDescriptor().getSchemaName()))
throw StandardException.newException(SQLState.LANG_OPERATION_NOT_ALLOWED_ON_SESSION_SCHEMA_TABLES);
String targetSchema = ((SynonymAliasInfo) aliasInfo).getSynonymSchema();
String targetTable = ((SynonymAliasInfo) aliasInfo).getSynonymTable();
if (this.getObjectName().equals(targetSchema, targetTable))
throw StandardException.newException(SQLState.LANG_SYNONYM_CIRCULAR, this.getFullName(), targetSchema + "." + targetTable);
SchemaDescriptor targetSD = getSchemaDescriptor(targetSchema, false);
if ((targetSD != null) && isSessionSchema(targetSD))
throw StandardException.newException(SQLState.LANG_OPERATION_NOT_ALLOWED_ON_SESSION_SCHEMA_TABLES);
}
use of org.apache.derby.iapi.types.TypeId in project derby by apache.
the class StaticMethodCallNode method bindExpressionMinion.
private JavaValueNode bindExpressionMinion(FromList fromList, SubqueryList subqueryList, List<AggregateNode> aggregates) throws StandardException {
bindParameters(fromList, subqueryList, aggregates);
/* If javaClassName is null then we assume that the current methodName
* is an alias and we must go to sysmethods to
* get the real method and java class names for this alias.
*/
if (javaClassName == null) {
CompilerContext cc = getCompilerContext();
// look for a routine
String schemaName = procedureName.getSchemaName();
boolean noSchema = schemaName == null;
SchemaDescriptor sd = getSchemaDescriptor(schemaName, schemaName != null);
// The field methodName is used by resolveRoutine and
// is set to the name of the routine (procedureName.getTableName()).
resolveRoutine(fromList, subqueryList, aggregates, sd, noSchema);
if ((ad != null) && (ad.getAliasType() == AliasInfo.ALIAS_TYPE_AGGREGATE_AS_CHAR)) {
resolvedAggregate = new AggregateNode(((SQLToJavaValueNode) methodParms[0]).getSQLValueNode(), new UserAggregateDefinition(ad), procedureName, false, ad.getJavaClassName(), getContextManager());
// Propagate tags used to flag nodes which need privilege checks. See DERBY-6429.
resolvedAggregate.copyTagsFrom(this);
// GROUP BY clause. That is not allowed.
if (appearsInGroupBy) {
throw StandardException.newException(SQLState.LANG_AGGREGATE_IN_GROUPBY_LIST);
}
return this;
}
SchemaDescriptor savedSd = sd;
if (ad == null && noSchema && !forCallStatement) {
// Resolve to a built-in SYSFUN function but only
// if this is a function call and the call
// was not qualified. E.g. COS(angle). The
// SYSFUN functions are not in SYSALIASES but
// an in-memory table, set up in DataDictioanryImpl.
sd = getSchemaDescriptor("SYSFUN", true);
resolveRoutine(fromList, subqueryList, aggregates, sd, noSchema);
}
if (ad == null) {
// DERBY-2927. Check if a procedure is being used as a
// function, or vice versa.
sd = savedSd;
if (!forCallStatement) {
// Procedure as function. We have JDBC escape syntax which
// may entice users to try that:
// "{? = CALL <proc>}"
//
// but we don't currently support it (it's not std SQL
// either). By resolving it as a procedure we can give a
// better error message.
//
// Note that with the above escape syntax one *can* CALL a
// function, though:
// "{? = CALL <func>}"
//
// but such cases have already been resolved above.
// temporarily: resolve
forCallStatement = true;
// as procedure
resolveRoutine(fromList, subqueryList, aggregates, sd, noSchema);
// restore it
forCallStatement = false;
if (ad != null) {
throw StandardException.newException(SQLState.LANG_PROC_USED_AS_FUNCTION, procedureName);
}
} else {
// Maybe a function is being CALLed ?
// temporarily: resolve
forCallStatement = false;
// as function
resolveRoutine(fromList, subqueryList, aggregates, sd, noSchema);
// restore it
forCallStatement = true;
if (ad != null) {
throw StandardException.newException(SQLState.LANG_FUNCTION_USED_AS_PROC, procedureName);
}
}
}
/* Throw exception if no routine found */
if (ad == null) {
throw StandardException.newException(SQLState.LANG_NO_SUCH_METHOD_ALIAS, procedureName);
}
if (noSchema) {
// If no schema was specified, register where we found the
// routine.
procedureName.setSchemaName(sd.getSchemaName());
}
if (!routineInfo.isDeterministic()) {
checkReliability(getMethodName(), CompilerContext.NON_DETERMINISTIC_ILLEGAL);
}
if (permitsSQL(routineInfo)) {
checkReliability(getMethodName(), CompilerContext.SQL_IN_ROUTINES_ILLEGAL);
}
/* Query is dependent on the AliasDescriptor */
cc.createDependency(ad);
methodName = ad.getAliasInfo().getMethodName();
javaClassName = ad.getJavaClassName();
// A special exception is made for the optional tools methods.
if (javaClassName.startsWith("org.apache.derby.") && !javaClassName.startsWith("org.apache.derby.impl.tools.optional.") && !javaClassName.startsWith("org.apache.derby.optional.lucene.") && !javaClassName.startsWith("org.apache.derby.optional.json.") && !javaClassName.startsWith("org.apache.derby.optional.api.") && !javaClassName.startsWith("org.apache.derby.optional.dump.") && !javaClassName.startsWith("org.apache.derby.vti.")) {
if (!sd.isSystemSchema())
throw StandardException.newException(SQLState.LANG_TYPE_DOESNT_EXIST2, (Throwable) null, javaClassName);
}
}
verifyClassExist(javaClassName);
/* Resolve the method call */
resolveMethodCall(javaClassName, true);
if (isPrivilegeCollectionRequired())
getCompilerContext().addRequiredRoutinePriv(ad);
// return type, then we need to push a CAST node.
if (routineInfo != null) {
if (methodParms != null)
optimizeDomainValueConversion();
TypeDescriptor returnType = routineInfo.getReturnType();
// create type dependency if return type is an ANSI UDT
if (returnType != null) {
createTypeDependency(DataTypeDescriptor.getType(returnType));
}
if (returnType != null && !returnType.isRowMultiSet() && !returnType.isUserDefinedType()) {
TypeId returnTypeId = TypeId.getBuiltInTypeId(returnType.getJDBCTypeId());
if (returnTypeId.variableLength()) {
// Cast the return using a cast node, but have to go
// into the SQL domain, and back to the Java domain.
DataTypeDescriptor returnValueDtd = new DataTypeDescriptor(returnTypeId, returnType.getPrecision(), returnType.getScale(), returnType.isNullable(), returnType.getMaximumWidth());
ValueNode returnValueToSQL = new JavaToSQLValueNode(this, getContextManager());
ValueNode returnValueCastNode = new CastNode(returnValueToSQL, returnValueDtd, getContextManager());
// DERBY-2972 Match the collation of the RoutineAliasInfo
returnValueCastNode.setCollationInfo(returnType.getCollationType(), StringDataValue.COLLATION_DERIVATION_IMPLICIT);
JavaValueNode returnValueToJava = new SQLToJavaValueNode(returnValueCastNode, getContextManager());
returnValueToJava.setCollationType(returnType.getCollationType());
return returnValueToJava.bindExpression(fromList, subqueryList, aggregates);
}
}
}
return this;
}
Aggregations