Search in sources :

Example 11 with DataTypeDescriptor

use of org.apache.derby.iapi.types.DataTypeDescriptor in project derby by apache.

the class InListOperatorNode method getDominantType.

/**
 * Get the dominant type of all the operands in this IN list.
 * @return the type descriptor for the dominant type
 * @see DataTypeDescriptor#getDominantType(DataTypeDescriptor, ClassFactory)
 */
private DataTypeDescriptor getDominantType() {
    DataTypeDescriptor targetType = leftOperand.getTypeServices();
    TypeId judgeTypeId = targetType.getTypeId();
    if (!rightOperandList.allSamePrecendence(judgeTypeId.typePrecedence())) {
        // Iterate through the entire list of values to find out
        // what the dominant type is.
        ClassFactory cf = getClassFactory();
        for (ValueNode vn : rightOperandList) {
            targetType = targetType.getDominantType(vn.getTypeServices(), cf);
        }
    }
    return targetType;
}
Also used : TypeId(org.apache.derby.iapi.types.TypeId) ClassFactory(org.apache.derby.iapi.services.loader.ClassFactory) DataTypeDescriptor(org.apache.derby.iapi.types.DataTypeDescriptor)

Example 12 with DataTypeDescriptor

use of org.apache.derby.iapi.types.DataTypeDescriptor in project derby by apache.

the class InListOperatorNode method preprocess.

/**
 * Preprocess an expression tree.  We do a number of transformations
 * here (including subqueries, IN lists, LIKE and BETWEEN) plus
 * subquery flattening.
 * NOTE: This is done before the outer ResultSetNode is preprocessed.
 *
 * @param	numTables			Number of tables in the DML Statement
 * @param	outerFromList		FromList from outer query block
 * @param	outerSubqueryList	SubqueryList from outer query block
 * @param	outerPredicateList	PredicateList from outer query block
 *
 * @return		The modified expression
 *
 * @exception StandardException		Thrown on error
 */
@Override
ValueNode preprocess(int numTables, FromList outerFromList, SubqueryList outerSubqueryList, PredicateList outerPredicateList) throws StandardException {
    super.preprocess(numTables, outerFromList, outerSubqueryList, outerPredicateList);
    /* Check for the degenerate case of a single element in the IN list.
		 * If found, then convert to "=".
		 */
    if (rightOperandList.size() == 1) {
        BinaryComparisonOperatorNode equal = new BinaryRelationalOperatorNode(BinaryRelationalOperatorNode.K_EQUALS, leftOperand, rightOperandList.elementAt(0), false, getContextManager());
        /* Set type info for the operator node */
        equal.bindComparisonOperator();
        return equal;
    }
    // DERBY-6017: All comparisons have to be performed using the dominant
    // type of *all* the values in the left operand and the right operand.
    // If either the left operand is of the dominant type, or all of the
    // values in the right operand are of the dominant type, we know that
    // each comparison will be performed using the dominant type.
    // Otherwise, cast the left operand to the dominant type to ensure
    // that each comparison operation will use the dominant type.
    DataTypeDescriptor targetType = getDominantType();
    int targetTypePrecedence = targetType.getTypeId().typePrecedence();
    if ((leftOperand.getTypeServices().getTypeId().typePrecedence() != targetTypePrecedence) && !rightOperandList.allSamePrecendence(targetTypePrecedence)) {
        CastNode cn = new CastNode(leftOperand, targetType, getContextManager());
        cn.bindCastNodeOnly();
        leftOperand = cn;
    }
    if ((leftOperand instanceof ColumnReference) && rightOperandList.containsOnlyConstantAndParamNodes()) {
        /* At this point we have an IN-list made up of constant and/or
			 * parameter values.  Ex.:
			 *
			 *  select id, name from emp where id in (34, 28, ?)
			 *
			 * Since the optimizer does not recognize InListOperatorNodes
			 * as potential start/stop keys for indexes, it (the optimizer)
			 * may estimate that the cost of using any of the indexes would
			 * be too high.  So we could--and probably would--end up doing
			 * a table scan on the underlying base table. But if the number
			 * of rows in the base table is significantly greater than the
			 * number of values in the IN-list, scanning the base table can
			 * be overkill and can lead to poor performance.  And further,
			 * choosing to use an index but then scanning the entire index
			 * can be slow, too. DERBY-47.
			 *
			 * What we do, then, is create an "IN-list probe predicate",
			 * which is an internally generated equality predicate with a
			 * parameter value on the right.  So for the query shown above
			 * the probe predicate would be "id = ?".  We then replace
			 * this InListOperatorNode with the probe predicate during
			 * optimization.  The optimizer in turn recognizes the probe
			 * predicate, which is disguised to look like a typical binary
			 * equality, as a potential start/stop key for any indexes.
			 * This start/stop key potential then factors into the estimated
			 * cost of probing the indexes, which leads to a more reasonable
			 * estimate and thus makes it more likely that the optimizer
			 * will choose to use an index vs a table scan.  That done, we
			 * then use the probe predicate to perform multiple execution-
			 * time "probes" on the index--instead of doing a range index
			 * scan--which eliminates unnecessary scanning. For more see
			 * execute/MultiProbeTableScanResultSet.java.
			 *
			 * With this approach we know that regardless of how large the
			 * base table is, we'll only have to probe the index a max of
			 * N times, where "N" is the size of the IN-list. If N is
			 * significantly less than the number of rows in the table, or
			 * is significantly less than the number of rows between the
			 * min value and the max value in the IN-list, this selective
			 * probing can save us a lot of time.
			 *
			 * Note: We will do fewer than N probes if there are duplicates
			 * in the list.
			 *
			 * Note also that, depending on the relative size of the IN-list
			 * verses the number of rows in the table, it may actually be
			 * better to just do a table scan--especially if there are fewer
			 * rows in the table than there are in the IN-list.  So even though
			 * we create a "probe predicate" and pass it to the optimizer, it
			 * (the optimizer) may still choose to do a table scan.  If that
			 * happens then we'll "revert" the probe predicate back to its
			 * original form (i.e. to this InListOperatorNode) during code
			 * generation, and then we'll use it as a regular IN-list
			 * restriction when it comes time to execute.
			 */
        boolean allConstants = rightOperandList.containsAllConstantNodes();
        /* If we have all constants then sort them now.  This allows us to
			 * skip the sort at execution time (we have to sort them so that
			 * we can eliminate duplicate IN-list values).  If we have one
			 * or more parameter nodes then we do *not* sort the values here
			 * because we do not (and cannot) know what values the parameter(s)
			 * will have.  In that case we'll sort the values at execution
			 * time. 
			 */
        if (allConstants) {
            /* When sorting or choosing min/max in the list, if types
				 * are not an exact match then we have to use the *dominant*
				 * type across all values, where "all values" includes the
				 * left operand.  Otherwise we can end up with incorrect
				 * results.
				 *
				 * Note that it is *not* enough to just use the left operand's
				 * type as the judge because we have no guarantee that the
				 * left operand has the dominant type.  If, for example, the
				 * left operand has type INTEGER and all (or any) values in
				 * the IN list have type DECIMAL, use of the left op's type
				 * would lead to comparisons with truncated values and could
				 * therefore lead to an incorrect sort order. DERBY-2256.
				 */
            /* Now sort the list in ascending order using the dominant
				 * type found above.
				 */
            DataValueDescriptor judgeODV = targetType.getNull();
            rightOperandList.sortInAscendingOrder(judgeODV);
            isOrdered = true;
            ValueNode minValue = rightOperandList.elementAt(0);
            ValueNode maxValue = rightOperandList.elementAt(rightOperandList.size() - 1);
            /* Handle the degenerate case where the min and the max
				 * are the same value.  Note (again) that we need to do
				 * this comparison using the dominant type found above.
				 */
            DataValueDescriptor minODV = ((ConstantNode) minValue).getValue();
            DataValueDescriptor maxODV = ((ConstantNode) maxValue).getValue();
            if (judgeODV.equals(minODV, maxODV).equals(true)) {
                BinaryComparisonOperatorNode equal = new BinaryRelationalOperatorNode(BinaryRelationalOperatorNode.K_EQUALS, leftOperand, minValue, false, getContextManager());
                /* Set type info for the operator node */
                equal.bindComparisonOperator();
                return equal;
            }
        }
        /* Create a parameter node to serve as the right operand of
			 * the probe predicate.  We intentionally use a parameter node
			 * instead of a constant node because the IN-list has more than
			 * one value (some of which may be unknown at compile time, i.e.
			 * if they are parameters), so we don't want an estimate based
			 * on any single literal.  Instead we want a generic estimate
			 * of the cost to retrieve the rows matching some _unspecified_
			 * value (namely, one of the values in the IN-list, but we
			 * don't know which one).  That's exactly what a parameter
			 * node gives us.
			 *
			 * Note: If the IN-list only had a single value then we would
			 * have taken the "if (rightOperandList.size() == 1)" branch
			 * above and thus would not be here.
			 *
			 * We create the parameter node based on the first value in
			 * the list.  This is arbitrary and should not matter in the
			 * big picture.
			 */
        ValueNode srcVal = rightOperandList.elementAt(0);
        ParameterNode pNode = new ParameterNode(0, // default value
        null, getContextManager());
        DataTypeDescriptor pType = srcVal.getTypeServices();
        pNode.setType(pType);
        /* If we choose to use the new predicate for execution-time
			 * probing then the right operand will function as a start-key
			 * "place-holder" into which we'll store the different IN-list
			 * values as we iterate through them.  This means we have to
			 * generate a valid value for the parameter node--i.e. for the
			 * right side of the probe predicate--in order to have a valid
			 * execution-time placeholder.  To do that we pass the source
			 * value from which we found the type down to the new, "fake"
			 * parameter node.  Then, when it comes time to generate the
			 * parameter node, we'll just generate the source value as our
			 * place-holder.  See ParameterNode.generateExpression().
			 *
			 * Note: the actual value of the "place-holder" does not matter
			 * because it will be clobbered by the various IN-list values
			 * (which includes "srcVal" itself) as we iterate through them
			 * during execution.
			 */
        pNode.setValueToGenerate(srcVal);
        /* Finally, create the "column = ?" equality that serves as the
			 * basis for the probe predicate.  We store a reference to "this"
			 * node inside the probe predicate so that, if we later decide
			 * *not* to use the probe predicate for execution time index
			 * probing, we can revert it back to its original form (i.e.
			 * to "this").
			 */
        BinaryComparisonOperatorNode equal = new BinaryRelationalOperatorNode(BinaryRelationalOperatorNode.K_EQUALS, leftOperand, pNode, this, false, getContextManager());
        /* Set type info for the operator node */
        equal.bindComparisonOperator();
        return equal;
    } else {
        return this;
    }
}
Also used : DataTypeDescriptor(org.apache.derby.iapi.types.DataTypeDescriptor) DataValueDescriptor(org.apache.derby.iapi.types.DataValueDescriptor)

Example 13 with DataTypeDescriptor

use of org.apache.derby.iapi.types.DataTypeDescriptor in project derby by apache.

the class JavaToSQLValueNode 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
ValueNode bindExpression(FromList fromList, SubqueryList subqueryList, List<AggregateNode> aggregates) throws StandardException {
    // method invocations are not allowed in ADD TABLE clauses.
    // And neither are field references.
    javaNode.checkReliability(this);
    /* Bind the expression under us */
    javaNode = javaNode.bindExpression(fromList, subqueryList, aggregates);
    if (javaNode instanceof StaticMethodCallNode) {
        AggregateNode agg = ((StaticMethodCallNode) javaNode).getResolvedAggregate();
        if (agg != null) {
            return agg.bindExpression(fromList, subqueryList, aggregates);
        }
    }
    DataTypeDescriptor dts = javaNode.getDataType();
    if (dts == null) {
        throw StandardException.newException(SQLState.LANG_NO_CORRESPONDING_S_Q_L_TYPE, javaNode.getJavaTypeName());
    }
    TypeDescriptor catalogType = dts.getCatalogType();
    if (catalogType.isRowMultiSet() || (catalogType.getTypeName().equals("java.sql.ResultSet"))) {
        throw StandardException.newException(SQLState.LANG_TABLE_FUNCTION_NOT_ALLOWED);
    }
    setType(dts);
    // RoutineAliasInfo to javaNode.
    if (dts.getTypeId().isStringTypeId()) {
        this.setCollationInfo(javaNode.getCollationType(), StringDataValue.COLLATION_DERIVATION_IMPLICIT);
    }
    return this;
}
Also used : TypeDescriptor(org.apache.derby.catalog.TypeDescriptor) DataTypeDescriptor(org.apache.derby.iapi.types.DataTypeDescriptor) DataTypeDescriptor(org.apache.derby.iapi.types.DataTypeDescriptor)

Example 14 with DataTypeDescriptor

use of org.apache.derby.iapi.types.DataTypeDescriptor in project derby by apache.

the class NumericTypeCompiler method resolveArithmeticOperation.

/**
 * @see TypeCompiler#resolveArithmeticOperation
 *
 * @exception StandardException		Thrown on error
 */
@Override
public DataTypeDescriptor resolveArithmeticOperation(DataTypeDescriptor leftType, DataTypeDescriptor rightType, String operator) throws StandardException {
    NumericTypeCompiler higherTC;
    DataTypeDescriptor higherType;
    boolean nullable;
    int precision, scale, maximumWidth;
    /*
		** Check the right type to be sure it's a number.  By convention,
		** we call this method off the TypeId of the left operand, so if
		** we get here, we know the left operand is a number.
		*/
    if (SanityManager.DEBUG)
        SanityManager.ASSERT(leftType.getTypeId().isNumericTypeId(), "The left type is supposed to be a number because we're resolving an arithmetic operator");
    TypeId leftTypeId = leftType.getTypeId();
    TypeId rightTypeId = rightType.getTypeId();
    boolean supported = true;
    if (!(rightTypeId.isNumericTypeId())) {
        supported = false;
    }
    if (TypeCompiler.MOD_OP.equals(operator)) {
        switch(leftTypeId.getJDBCTypeId()) {
            case java.sql.Types.TINYINT:
            case java.sql.Types.SMALLINT:
            case java.sql.Types.INTEGER:
            case java.sql.Types.BIGINT:
                break;
            default:
                supported = false;
                break;
        }
        switch(rightTypeId.getJDBCTypeId()) {
            case java.sql.Types.TINYINT:
            case java.sql.Types.SMALLINT:
            case java.sql.Types.INTEGER:
            case java.sql.Types.BIGINT:
                break;
            default:
                supported = false;
                break;
        }
    }
    if (!supported) {
        throw StandardException.newException(SQLState.LANG_BINARY_OPERATOR_NOT_SUPPORTED, operator, leftType.getTypeId().getSQLTypeName(), rightType.getTypeId().getSQLTypeName());
    }
    /*
		** Take left as the higher precedence if equal
		*/
    if (rightTypeId.typePrecedence() > leftTypeId.typePrecedence()) {
        higherType = rightType;
        higherTC = (NumericTypeCompiler) getTypeCompiler(rightTypeId);
    } else {
        higherType = leftType;
        higherTC = (NumericTypeCompiler) getTypeCompiler(leftTypeId);
    }
    /* The calculation of precision and scale should be based upon
		 * the type with higher precedence, which is going to be the result
		 * type, this is also to be consistent with maximumWidth.  Beetle 3906.
		 */
    precision = higherTC.getPrecision(operator, leftType, rightType);
    if (higherType.getTypeId().isDecimalTypeId()) {
        scale = higherTC.getScale(operator, leftType, rightType);
        maximumWidth = (scale > 0) ? precision + 3 : precision + 1;
        /*
			** Be careful not to overflow
			*/
        if (maximumWidth < precision) {
            maximumWidth = Integer.MAX_VALUE;
        }
    } else {
        scale = 0;
        maximumWidth = higherType.getMaximumWidth();
    }
    /* The result is nullable if either side is nullable */
    nullable = leftType.isNullable() || rightType.isNullable();
    /*
		** The higher type does not have the right nullability.  Create a
		** new DataTypeDescriptor that has the correct type and nullability.
		**
		** It's OK to call the implementation of the DataTypeDescriptorFactory
		** here, because we're in the same package.
		*/
    return new DataTypeDescriptor(higherType.getTypeId(), precision, scale, nullable, maximumWidth);
}
Also used : TypeId(org.apache.derby.iapi.types.TypeId) DataTypeDescriptor(org.apache.derby.iapi.types.DataTypeDescriptor)

Example 15 with DataTypeDescriptor

use of org.apache.derby.iapi.types.DataTypeDescriptor in project derby by apache.

the class ResultColumnList method buildEmptyRow.

/**
 *	Build an empty row with the size and shape of the ResultColumnList.
 *
 *	@return	an empty row of the correct size and shape.
 * @exception StandardException		Thrown on error
 */
public ExecRow buildEmptyRow() throws StandardException {
    int columnCount = size();
    ExecRow row = getExecutionFactory().getValueRow(columnCount);
    int position = 1;
    for (ResultColumn rc : this) {
        DataTypeDescriptor dataType = rc.getTypeServices();
        DataValueDescriptor dataValue = dataType.getNull();
        row.setColumn(position++, dataValue);
    }
    return row;
}
Also used : DataTypeDescriptor(org.apache.derby.iapi.types.DataTypeDescriptor) ExecRow(org.apache.derby.iapi.sql.execute.ExecRow) DataValueDescriptor(org.apache.derby.iapi.types.DataValueDescriptor)

Aggregations

DataTypeDescriptor (org.apache.derby.iapi.types.DataTypeDescriptor)99 TypeId (org.apache.derby.iapi.types.TypeId)32 ColumnDescriptor (org.apache.derby.iapi.sql.dictionary.ColumnDescriptor)14 DataValueDescriptor (org.apache.derby.iapi.types.DataValueDescriptor)14 CompilerContext (org.apache.derby.iapi.sql.compile.CompilerContext)9 SchemaDescriptor (org.apache.derby.iapi.sql.dictionary.SchemaDescriptor)8 ExecRow (org.apache.derby.iapi.sql.execute.ExecRow)8 TypeDescriptor (org.apache.derby.catalog.TypeDescriptor)7 UUID (org.apache.derby.catalog.UUID)5 ClassFactory (org.apache.derby.iapi.services.loader.ClassFactory)5 ResultColumnDescriptor (org.apache.derby.iapi.sql.ResultColumnDescriptor)5 TypeCompiler (org.apache.derby.iapi.sql.compile.TypeCompiler)5 StandardException (org.apache.derby.shared.common.error.StandardException)5 Properties (java.util.Properties)4 UserDefinedTypeIdImpl (org.apache.derby.catalog.types.UserDefinedTypeIdImpl)4 FormatableBitSet (org.apache.derby.iapi.services.io.FormatableBitSet)4 AliasDescriptor (org.apache.derby.iapi.sql.dictionary.AliasDescriptor)3 ColumnDescriptorList (org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList)3 DataDictionary (org.apache.derby.iapi.sql.dictionary.DataDictionary)3 ExecIndexRow (org.apache.derby.iapi.sql.execute.ExecIndexRow)3