use of org.apache.derby.iapi.sql.compile.TypeCompiler in project derby by apache.
the class MethodCallNode method parseValidateSignature.
/**
* Parse the user supplied signature for a method and validate
* it, need to match the number of parameters passed in and match
* the valid types for the parameter.
* @param offset Character offset of first paren
* @param hasDynamicResultSets Can ResultSet[] parameters be specified.
* @return The valid array of types for resolution.
* @throws StandardException
*/
private String[] parseValidateSignature(String externalName, int offset, boolean hasDynamicResultSets) throws StandardException {
int siglen = externalName.length();
// character and that the last character is a close paren
if (((offset + 1) == siglen) || (externalName.charAt(siglen - 1) != ')'))
// invalid
throw StandardException.newException(SQLState.SQLJ_SIGNATURE_INVALID);
StringTokenizer st = new StringTokenizer(externalName.substring(offset + 1, siglen - 1), ",", true);
String[] signatureTypes = new String[signature.length];
int count;
boolean seenClass = false;
for (count = 0; st.hasMoreTokens(); ) {
String type = st.nextToken().trim();
// check sequence is <class><comma>class> etc.
if (",".equals(type)) {
if (!seenClass)
// invalid
throw StandardException.newException(SQLState.SQLJ_SIGNATURE_INVALID);
seenClass = false;
continue;
} else {
if (type.length() == 0)
// invalid
throw StandardException.newException(SQLState.SQLJ_SIGNATURE_INVALID);
seenClass = true;
count++;
}
if (count > signature.length) {
if (hasDynamicResultSets) {
// Allow any number of dynamic result set holders
// but they must match the exact type.
String rsType = signature[signature.length - 1].getSQLType().getTypeId().getCorrespondingJavaTypeName();
if (!type.equals(rsType))
throw StandardException.newException(SQLState.LANG_DATA_TYPE_GET_MISMATCH, type, rsType);
if (signatureTypes.length == signature.length) {
// expand once
String[] sigs = new String[st.countTokens()];
System.arraycopy(signatureTypes, 0, sigs, 0, signatureTypes.length);
signatureTypes = sigs;
}
signatureTypes[count - 1] = type;
continue;
}
throw StandardException.newException(SQLState.SQLJ_SIGNATURE_PARAMETER_COUNT, Integer.toString(count), // too many types
Integer.toString(signature.length));
}
TypeId paramTypeId = signature[count - 1].getSQLType().getTypeId();
// Does it match the object name
if (type.equals(paramTypeId.getCorrespondingJavaTypeName())) {
signatureTypes[count - 1] = type;
continue;
}
// how about the primitive name
if ((paramTypeId.isNumericTypeId() && !paramTypeId.isDecimalTypeId()) || paramTypeId.isBooleanTypeId()) {
TypeCompiler tc = getTypeCompiler(paramTypeId);
if (type.equals(tc.getCorrespondingPrimitiveTypeName())) {
signatureTypes[count - 1] = type;
continue;
}
}
throw StandardException.newException(SQLState.LANG_DATA_TYPE_GET_MISMATCH, type, // type conversion error
paramTypeId.getSQLTypeName());
}
// Did signature end with trailing comma?
if (count != 0 && !seenClass)
// invalid
throw StandardException.newException(SQLState.SQLJ_SIGNATURE_INVALID);
if (count < signatureTypes.length) {
if (hasDynamicResultSets) {
// dynamic results at runtime
if (count == (signature.length - 1)) {
String[] sigs = new String[count];
System.arraycopy(signatureTypes, 0, sigs, 0, count);
return sigs;
}
}
throw StandardException.newException(SQLState.SQLJ_SIGNATURE_PARAMETER_COUNT, Integer.toString(count), // too few types
Integer.toString(signature.length));
}
return signatureTypes;
}
use of org.apache.derby.iapi.sql.compile.TypeCompiler in project derby by apache.
the class ConcatenationOperatorNode method bindExpression.
/**
* overrides BindOperatorNode.bindExpression because concatenation has
* special requirements for parameter binding.
*
* @exception StandardException
* thrown on failure
*/
@Override
ValueNode bindExpression(FromList fromList, SubqueryList subqueryList, List<AggregateNode> aggregates) throws StandardException {
// deal with binding operands
leftOperand = leftOperand.bindExpression(fromList, subqueryList, aggregates);
rightOperand = rightOperand.bindExpression(fromList, subqueryList, aggregates);
if (leftOperand.requiresTypeFromContext()) {
if (rightOperand.requiresTypeFromContext()) {
throw StandardException.newException(SQLState.LANG_BINARY_OPERANDS_BOTH_PARMS, operator);
}
TypeId leftType;
/*
* * A ? on the left gets its type from the right. There are eight *
* legal types for the concatenation operator: CHAR, VARCHAR, * LONG
* VARCHAR, CLOB, BIT, BIT VARYING, LONG BIT VARYING, and BLOB. * If
* the right type is BLOB, set the parameter type to BLOB with max
* length. * If the right type is one of the other bit types, set
* the parameter type to * BIT VARYING with maximum length. * * If
* the right type is CLOB, set parameter type to CLOB with max
* length. * If the right type is anything else, set it to VARCHAR
* with * maximum length. We count on the resolveConcatOperation
* method to * catch an illegal type. * * NOTE: When I added the
* long types, I could have changed the * resulting parameter types
* to LONG VARCHAR and LONG BIT VARYING, * but they were already
* VARCHAR and BIT VARYING, and it wasn't * clear to me what effect
* it would have to change it. - Jeff
*/
if (rightOperand.getTypeId().isBitTypeId()) {
if (rightOperand.getTypeId().isBlobTypeId())
leftType = TypeId.getBuiltInTypeId(Types.BLOB);
else
leftType = TypeId.getBuiltInTypeId(Types.VARBINARY);
} else {
if (rightOperand.getTypeId().isClobTypeId())
leftType = TypeId.getBuiltInTypeId(Types.CLOB);
else
leftType = TypeId.getBuiltInTypeId(Types.VARCHAR);
}
leftOperand.setType(new DataTypeDescriptor(leftType, true));
if (rightOperand.getTypeId().isStringTypeId()) {
// collation of ? operand should be picked from the context
leftOperand.setCollationInfo(rightOperand.getTypeServices());
}
}
/*
* Is there a ? parameter on the right?
*/
if (rightOperand.requiresTypeFromContext()) {
TypeId rightType;
/*
* * A ? on the right gets its type from the left. There are eight *
* legal types for the concatenation operator: CHAR, VARCHAR, * LONG
* VARCHAR, CLOB, BIT, BIT VARYING, LONG BIT VARYING, and BLOB. * If
* the left type is BLOB, set the parameter type to BLOB with max
* length. * If the left type is one of the other bit types, set the
* parameter type to * BIT VARYING with maximum length. * * If the
* left type is CLOB, set parameter type to CLOB with max length. *
* If the left type is anything else, set it to VARCHAR with *
* maximum length. We count on the resolveConcatOperation method to *
* catch an illegal type. * * NOTE: When I added the long types, I
* could have changed the * resulting parameter types to LONG
* VARCHAR and LONG BIT VARYING, * but they were already VARCHAR and
* BIT VARYING, and it wasn't * clear to me what effect it would
* have to change it. - Jeff
*/
if (leftOperand.getTypeId().isBitTypeId()) {
if (leftOperand.getTypeId().isBlobTypeId())
rightType = TypeId.getBuiltInTypeId(Types.BLOB);
else
rightType = TypeId.getBuiltInTypeId(Types.VARBINARY);
} else {
if (leftOperand.getTypeId().isClobTypeId())
rightType = TypeId.getBuiltInTypeId(Types.CLOB);
else
rightType = TypeId.getBuiltInTypeId(Types.VARCHAR);
}
rightOperand.setType(new DataTypeDescriptor(rightType, true));
if (leftOperand.getTypeId().isStringTypeId()) {
// collation of ? operand should be picked from the context
rightOperand.setCollationInfo(leftOperand.getTypeServices());
}
}
/*
* If the left operand is not a built-in type, then generate a bound
* conversion tree to a built-in type.
*/
if (leftOperand.getTypeId().userType()) {
leftOperand = leftOperand.genSQLJavaSQLTree();
}
/*
* If the right operand is not a built-in type, then generate a bound
* conversion tree to a built-in type.
*/
if (rightOperand.getTypeId().userType()) {
rightOperand = rightOperand.genSQLJavaSQLTree();
}
/*
* If either the left or right operands are non-string, non-bit types,
* then we generate an implicit cast to VARCHAR.
*/
TypeCompiler tc = leftOperand.getTypeCompiler();
if (!(leftOperand.getTypeId().isStringTypeId() || leftOperand.getTypeId().isBitTypeId())) {
DataTypeDescriptor dtd = DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.VARCHAR, true, tc.getCastToCharWidth(leftOperand.getTypeServices()));
leftOperand = new CastNode(leftOperand, dtd, getContextManager());
// DERBY-2910 - Match current schema collation for implicit cast as we do for
// explicit casts per SQL Spec 6.12 (10)
leftOperand.setCollationUsingCompilationSchema();
((CastNode) leftOperand).bindCastNodeOnly();
}
tc = rightOperand.getTypeCompiler();
if (!(rightOperand.getTypeId().isStringTypeId() || rightOperand.getTypeId().isBitTypeId())) {
DataTypeDescriptor dtd = DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.VARCHAR, true, tc.getCastToCharWidth(rightOperand.getTypeServices()));
rightOperand = new CastNode(rightOperand, dtd, getContextManager());
// DERBY-2910 - Match current schema collation for implicit cast as we do for
// explicit casts per SQL Spec 6.12 (10)
rightOperand.setCollationUsingCompilationSchema();
((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.
*/
tc = leftOperand.getTypeCompiler();
setType(resolveConcatOperation(leftOperand.getTypeServices(), rightOperand.getTypeServices()));
/*
* * Make sure the maximum width set for the result doesn't exceed the
* result type's maximum width
*/
if (SanityManager.DEBUG) {
if (getTypeServices().getMaximumWidth() > getTypeId().getMaximumMaximumWidth()) {
SanityManager.THROWASSERT("The maximum length " + getTypeServices().getMaximumWidth() + " for the result type " + getTypeId().getSQLTypeName() + " can't be greater than it's maximum width of result's typeid" + getTypeId().getMaximumMaximumWidth());
}
}
/*
* * Now that we know the target interface type, set it. This assumes *
* that both operands have the same interface type, which is a safe *
* assumption for the concatenation operator.
*/
this.setLeftRightInterfaceType(tc.interfaceName());
// able to take advantage of concatenated literals like 'ab' || '%'.
return this.evaluateConstantExpressions();
}
use of org.apache.derby.iapi.sql.compile.TypeCompiler 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.sql.compile.TypeCompiler in project derby by apache.
the class ValueNodeList method compatible.
/**
* Make sure that passed ValueNode's type is compatible with the non-parameter elements in the ValueNodeList.
*
* @param leftOperand Check for compatibility against this parameter's type
*/
void compatible(ValueNode leftOperand) throws StandardException {
TypeId leftType = leftOperand.getTypeId();
TypeCompiler leftTC = leftOperand.getTypeCompiler();
for (ValueNode valueNode : this) {
if (valueNode.requiresTypeFromContext()) {
continue;
}
/*
** Are the types compatible to each other? If not, throw an exception.
*/
if (!leftTC.compatible(valueNode.getTypeId())) {
throw StandardException.newException(SQLState.LANG_DB2_COALESCE_DATATYPE_MISMATCH, leftType.getSQLTypeName(), valueNode.getTypeId().getSQLTypeName());
}
}
}
use of org.apache.derby.iapi.sql.compile.TypeCompiler in project derby by apache.
the class SumAvgAggregateDefinition method getAggregator.
/**
* Determines the result datatype. Accept NumberDataValues
* only.
* <P>
* <I>Note</I>: In the future you should be able to do
* a sum user data types. One option would be to run
* sum on anything that implements plus(). In which
* case avg() would need divide().
*
* @param inputType the input type, either a user type or a java.lang object
*
* @return the output Class (null if cannot operate on
* value expression of this type.
*/
public final DataTypeDescriptor getAggregator(DataTypeDescriptor inputType, StringBuffer aggregatorClass) {
try {
TypeId compType = inputType.getTypeId();
CompilerContext cc = (CompilerContext) QueryTreeNode.getContext(CompilerContext.CONTEXT_ID);
TypeCompilerFactory tcf = cc.getTypeCompilerFactory();
TypeCompiler tc = tcf.getTypeCompiler(compType);
/*
** If the class implements NumberDataValue, then we
** are in business. Return type is same as input
** type.
*/
if (compType.isNumericTypeId()) {
aggregatorClass.append(getAggregatorClassName());
DataTypeDescriptor outDts = tc.resolveArithmeticOperation(inputType, inputType, getOperator());
/*
** SUM and AVG may return null
*/
return outDts.getNullabilityType(true);
}
} catch (StandardException e) {
if (SanityManager.DEBUG) {
SanityManager.THROWASSERT("Unexpected exception", e);
}
}
return null;
}
Aggregations