Search in sources :

Example 1 with TypeCompiler

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;
}
Also used : TypeId(org.apache.derby.iapi.types.TypeId) StringTokenizer(java.util.StringTokenizer) TypeCompiler(org.apache.derby.iapi.sql.compile.TypeCompiler)

Example 2 with TypeCompiler

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();
}
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 3 with TypeCompiler

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;
}
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 4 with TypeCompiler

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());
        }
    }
}
Also used : TypeId(org.apache.derby.iapi.types.TypeId) TypeCompiler(org.apache.derby.iapi.sql.compile.TypeCompiler)

Example 5 with TypeCompiler

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;
}
Also used : TypeId(org.apache.derby.iapi.types.TypeId) StandardException(org.apache.derby.shared.common.error.StandardException) TypeCompilerFactory(org.apache.derby.iapi.sql.compile.TypeCompilerFactory) DataTypeDescriptor(org.apache.derby.iapi.types.DataTypeDescriptor) CompilerContext(org.apache.derby.iapi.sql.compile.CompilerContext) TypeCompiler(org.apache.derby.iapi.sql.compile.TypeCompiler)

Aggregations

TypeCompiler (org.apache.derby.iapi.sql.compile.TypeCompiler)10 TypeId (org.apache.derby.iapi.types.TypeId)8 DataTypeDescriptor (org.apache.derby.iapi.types.DataTypeDescriptor)5 LocalField (org.apache.derby.iapi.services.compiler.LocalField)2 ResultSet (java.sql.ResultSet)1 StringTokenizer (java.util.StringTokenizer)1 TypeDescriptorImpl (org.apache.derby.catalog.types.TypeDescriptorImpl)1 UserDefinedTypeIdImpl (org.apache.derby.catalog.types.UserDefinedTypeIdImpl)1 ClassInspector (org.apache.derby.iapi.services.loader.ClassInspector)1 CompilerContext (org.apache.derby.iapi.sql.compile.CompilerContext)1 TypeCompilerFactory (org.apache.derby.iapi.sql.compile.TypeCompilerFactory)1 JSQLType (org.apache.derby.iapi.types.JSQLType)1 StandardException (org.apache.derby.shared.common.error.StandardException)1