You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by km...@apache.org on 2013/08/07 14:45:56 UTC
svn commit: r1511288 - in /db/derby/code/branches/10.8: ./
java/engine/org/apache/derby/iapi/types/
java/engine/org/apache/derby/impl/sql/compile/
java/testing/org/apache/derbyTesting/functionTests/tests/lang/
Author: kmarsden
Date: Wed Aug 7 12:45:55 2013
New Revision: 1511288
URL: http://svn.apache.org/r1511288
Log:
DERBY-6017 IN lists with mixed types may return wrong results
merged from trunk 1424889, 1448025, 1450695
Contrubuted by Knut Anders Hatlen
Added:
db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/tests/lang/InPredicateTest.java
- copied, changed from r1424889, db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/InPredicateTest.java
Modified:
db/derby/code/branches/10.8/ (props changed)
db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/DataType.java
db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/DataTypeDescriptor.java
db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/InListOperatorNode.java
db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/ValueNodeList.java
db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java
Propchange: db/derby/code/branches/10.8/
------------------------------------------------------------------------------
Reverse-merged /db/derby/code/trunk:r1430735,1431259
Merged /db/derby/code/trunk:r1424889,1448025,1450695
Modified: db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/DataType.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/DataType.java?rev=1511288&r1=1511287&r2=1511288&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/DataType.java (original)
+++ db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/DataType.java Wed Aug 7 12:45:55 2013
@@ -1146,6 +1146,13 @@ public abstract class DataType
* compare using the dominant type of the two values being compared.
* Otherwise we can end up with wrong results when doing the binary
* search (ex. as caused by incorrect truncation). DERBY-2256.
+ *
+ * DERBY-6017: Actually, it's not good enough to compare using the
+ * dominant type of the two values being compared. It has to be the
+ * dominant type of *all* the values in the left operand and the right
+ * operand. Therefore, InListOperatorNode.preprocess() inserts a
+ * cast if necessary to ensure that either the left side or the right
+ * side of each comparison is of the overall dominating type.
*/
int leftPrecedence = left.typePrecedence();
DataValueDescriptor comparator = null;
Modified: db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/DataTypeDescriptor.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/DataTypeDescriptor.java?rev=1511288&r1=1511287&r2=1511288&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/DataTypeDescriptor.java (original)
+++ db/derby/code/branches/10.8/java/engine/org/apache/derby/iapi/types/DataTypeDescriptor.java Wed Aug 7 12:45:55 2013
@@ -700,11 +700,8 @@ public final class DataTypeDescriptor im
* @param cf A ClassFactory
*
* @return DataTypeDescriptor DTS for dominant type
- *
- * @exception StandardException Thrown on error
*/
public DataTypeDescriptor getDominantType(DataTypeDescriptor otherDTS, ClassFactory cf)
- throws StandardException
{
boolean nullable;
TypeId thisType;
Modified: db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/InListOperatorNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/InListOperatorNode.java?rev=1511288&r1=1511287&r2=1511288&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/InListOperatorNode.java (original)
+++ db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/InListOperatorNode.java Wed Aug 7 12:45:55 2013
@@ -151,7 +151,29 @@ public final class InListOperatorNode ex
equal.bindComparisonOperator();
return equal;
}
- else if ((leftOperand instanceof ColumnReference) &&
+
+ // 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 = (CastNode) getNodeFactory().getNode(
+ C_NodeTypes.CAST_NODE,
+ 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
@@ -236,27 +258,8 @@ public final class InListOperatorNode ex
* would lead to comparisons with truncated values and could
* therefore lead to an incorrect sort order. DERBY-2256.
*/
- 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();
- int sz = rightOperandList.size();
- for (int i = 0; i < sz; i++)
- {
- ValueNode vn = (ValueNode)rightOperandList.elementAt(i);
- targetType =
- targetType.getDominantType(
- vn.getTypeServices(), cf);
- }
- }
- /* Now wort the list in ascending order using the dominant
+ /* Now sort the list in ascending order using the dominant
* type found above.
*/
DataValueDescriptor judgeODV = targetType.getNull();
@@ -369,6 +372,31 @@ public final class InListOperatorNode ex
}
/**
+ * 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();
+ int sz = rightOperandList.size();
+ for (int i = 0; i < sz; i++) {
+ ValueNode vn = (ValueNode) rightOperandList.elementAt(i);
+ targetType = targetType.getDominantType(
+ vn.getTypeServices(), cf);
+ }
+ }
+
+ return targetType;
+ }
+
+ /**
* Eliminate NotNodes in the current query block. We traverse the tree,
* inverting ANDs and ORs and eliminating NOTs as we go. We stop at
* ComparisonOperators and boolean expressions. We invert
Modified: db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/ValueNodeList.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/ValueNodeList.java?rev=1511288&r1=1511287&r2=1511288&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/ValueNodeList.java (original)
+++ db/derby/code/branches/10.8/java/engine/org/apache/derby/impl/sql/compile/ValueNodeList.java Wed Aug 7 12:45:55 2013
@@ -260,7 +260,6 @@ public class ValueNodeList extends Query
* type precendence as the specified value.
*/
boolean allSamePrecendence(int precedence)
- throws StandardException
{
boolean allSame = true;
int size = size();
Copied: db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/tests/lang/InPredicateTest.java (from r1424889, db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/InPredicateTest.java)
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/tests/lang/InPredicateTest.java?p2=db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/tests/lang/InPredicateTest.java&p1=db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/InPredicateTest.java&r1=1424889&r2=1511288&rev=1511288&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/InPredicateTest.java (original)
+++ db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/tests/lang/InPredicateTest.java Wed Aug 7 12:45:55 2013
@@ -118,4 +118,72 @@ public class InPredicateTest extends Bas
" 9223372036854775807, 9.223372036854776E18)"),
allRows);
}
+
+ /**
+ * Another test case for DERBY-6017. Derby used to evaluate IN lists by
+ * using the semantics of the dominant type of the two values being
+ * compared. It should use the dominant type of all the values in the
+ * left operand and in the IN list. Verify that it works as expected now.
+ */
+ public void testMixedTypes() throws SQLException {
+ setAutoCommit(false);
+
+ // Test an IN predicate that mixes BIGINT and DOUBLE.
+
+ Statement s = createStatement();
+ s.executeUpdate("create table t2(b1 bigint, b2 bigint, d double)");
+ s.executeUpdate("insert into t2 values " +
+ "(9223372036854775805, 9223372036854775806, 1)");
+
+ // The first query used to return zero rows. However, the next two
+ // queries used to return one row, and SQL:2003, 8.4 <in predicate>
+ // says that the three queries are equivalent. Now, they all return
+ // one row.
+
+ JDBC.assertSingleValueResultSet(
+ s.executeQuery("select true from t2 where b1 in (b2, d)"),
+ "true");
+
+ JDBC.assertSingleValueResultSet(
+ s.executeQuery("select true from t2 where b1 in (values b2, d)"),
+ "true");
+
+ JDBC.assertSingleValueResultSet(
+ s.executeQuery("select true from t2 where b1 = any (values b2, d)"),
+ "true");
+
+ // Test an IN predicate that mixes INT and REAL. They are supposed
+ // to be compared using DOUBLE semantics, but used to be compared as
+ // REALs.
+
+ s.executeUpdate("create table t3 (i1 int, r1 real, r2 real)");
+ s.executeUpdate("insert into t3 values " +
+ "(2147483645, 2147483645, 2147483645), " +
+ "(2147483645, 2147483645, 0)");
+
+ Object[][] expectedRows = {
+ {
+ new Integer(2147483645),
+ new Float(2.14748365E9f),
+ new Float(2.14748365E9f),
+ }
+ };
+
+ // The first query used to return two rows. However, the next two
+ // queries used to return one row, and SQL:2003, 8.4 <in predicate>
+ // says that the three queries are equivalent. Now, they all return
+ // one row.
+
+ JDBC.assertFullResultSet(
+ s.executeQuery("select * from t3 where r1 in (i1, r2)"),
+ expectedRows, false);
+
+ JDBC.assertFullResultSet(
+ s.executeQuery("select * from t3 where r1 in (values i1, r2)"),
+ expectedRows, false);
+
+ JDBC.assertFullResultSet(
+ s.executeQuery("select * from t3 where r1 = any (values i1, r2)"),
+ expectedRows, false);
+ }
}
Modified: db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java?rev=1511288&r1=1511287&r2=1511288&view=diff
==============================================================================
--- db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java (original)
+++ db/derby/code/branches/10.8/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java Wed Aug 7 12:45:55 2013
@@ -106,6 +106,7 @@ public class _Suite extends BaseTestCase
suite.addTest(ScrollCursors2Test.suite());
suite.addTest(NullIfTest.suite());
suite.addTest(InListMultiProbeTest.suite());
+ suite.addTest(InPredicateTest.suite());
suite.addTest(SecurityPolicyReloadingTest.suite());
suite.addTest(CurrentOfTest.suite());
suite.addTest(UnaryArithmeticParameterTest.suite());