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 rh...@apache.org on 2010/06/07 17:12:22 UTC
svn commit: r952263 - in /db/derby/code/trunk/java:
engine/org/apache/derby/impl/sql/compile/ResultColumnList.java
testing/org/apache/derbyTesting/functionTests/tests/lang/BooleanValuesTest.java
Author: rhillegas
Date: Mon Jun 7 15:12:21 2010
New Revision: 952263
URL: http://svn.apache.org/viewvc?rev=952263&view=rev
Log:
DERBY-4692: Forbid UNIONs between BOOLEAN and non-BOOLEAN types, per the SQL Standard.
Modified:
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ResultColumnList.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/BooleanValuesTest.java
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ResultColumnList.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ResultColumnList.java?rev=952263&r1=952262&r2=952263&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ResultColumnList.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ResultColumnList.java Mon Jun 7 15:12:21 2010
@@ -2373,14 +2373,10 @@ public class ResultColumnList extends Qu
continue;
/*
- ** Check type compatability. We want to make sure that
- ** the types are assignable in either direction
- ** and they are comparable.
+ ** Check type compatability.
*/
ClassFactory cf = getClassFactory();
- if (
- !thisExpr.getTypeCompiler().storable(otherTypeId, cf) &&
- !otherExpr.getTypeCompiler().storable(thisTypeId, cf))
+ if ( !unionCompatible( thisExpr, otherExpr ) )
{
throw StandardException.newException(SQLState.LANG_NOT_UNION_COMPATIBLE,
thisTypeId.getSQLTypeName(),
@@ -2440,6 +2436,35 @@ public class ResultColumnList extends Qu
}
}
+ /**
+ * Return true if the types of two expressions are union compatible. The rules for union
+ * compatibility are found in the SQL Standard, part 2, section 7.3 (<query expression>),
+ * syntax rule 20.b.ii. That in turn, refers you to section 9.3 (Result of data type combinations).
+ * See, for instance, <a href="https://issues.apache.org/jira/browse/DERBY-4692">DERBY-4692</a>.
+ *
+ * This logic may enforce only a weaker set of rules. Here is the original comment
+ * on the original logic: "We want to make sure that the types are assignable in either direction
+ * and they are comparable." We may need to revisit this code to make it conform to the
+ * Standard.
+ */
+ private boolean unionCompatible( ValueNode left, ValueNode right )
+ throws StandardException
+ {
+ TypeId leftTypeId = left.getTypeId();
+ TypeId rightTypeId = right.getTypeId();
+ ClassFactory cf = getClassFactory();
+
+ if (
+ !left.getTypeCompiler().storable(rightTypeId, cf) &&
+ !right.getTypeCompiler().storable(leftTypeId, cf)
+ )
+ { return false; }
+
+ if ( leftTypeId.isBooleanTypeId() != rightTypeId.isBooleanTypeId() ) { return false; }
+
+ return true;
+ }
+
/**
* Do the 2 RCLs have the same type & length.
* This is useful for UNIONs when deciding whether a NormalizeResultSet is required.
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/BooleanValuesTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/BooleanValuesTest.java?rev=952263&r1=952262&r2=952263&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/BooleanValuesTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/BooleanValuesTest.java Mon Jun 7 15:12:21 2010
@@ -321,7 +321,7 @@ public class BooleanValuesTest extends
* <ul>
* <li>Add a new column to ALL_TYPES and corresponding rows (see setUp())</li>
* <li>Add the new datatype to one of the tests below</li>
- * <li>Add a new bad implicit cast to test_06_implicitCasts()</li>
+ * <li>Add a new bad union case to test_06_unions()</li>
* </ul>
*/
public void test_01_datatypeCount() throws Exception
@@ -495,98 +495,36 @@ public class BooleanValuesTest extends
/**
* <p>
- * Test that values are implicitly cast to boolean according to the rules in the SQL Standard,
- * part 2, section 6.12 (<cast specification>), general rule 20. Other than booleans themselves,
- * the only legal casts are from string types to boolean. The following transformations are applied
- * to the strings:
- * </p>
- *
- * <ul>
- * <li>Trim whitespace off the string</li>
- * <li>Then apply the rules in section 5.3 (<literal>). This means that the trimmed string must be 'TRUE', 'FALSE', or 'UNKNOWN', regardless of case.</li>
- * <li>Otherwise, raise an exception.</li>
- * </ul>
- *
- * <p>
- * See <a href="https://issues.apache.org/jira/browse/DERBY-4658">DERBY-4658</a>.
+ * Test that unions fail if one but not both sides of the union is BOOLEAN. The rules for union
+ * compatibility are found in the SQL Standard, part 2, section 7.3 (<query expression>),
+ * syntax rule 20.b.ii. That in turn, refers you to section 9.3 (Result of data type combinations).
+ * See, for instance, <a href="https://issues.apache.org/jira/browse/DERBY-4692">DERBY-4692</a>.This enforces the rules found
* </p>
*/
- public void test_06_implicitCasts() throws Exception
+ public void test_06_unions() throws Exception
{
Connection conn = getConnection();
- vetGoodImplicitCastFromString( conn, "'true'", Boolean.TRUE );
- vetGoodImplicitCastFromString( conn, "'false'", Boolean.FALSE );
- vetGoodImplicitCastFromString( conn, "'TRUE'", Boolean.TRUE );
- vetGoodImplicitCastFromString( conn, "'FALSE'", Boolean.FALSE );
- vetGoodImplicitCastFromString( conn, "' true '", Boolean.TRUE );
- vetGoodImplicitCastFromString( conn, "' false '", Boolean.FALSE );
-
- vetGoodImplicitCastFromString( conn, "cast (null as char( 10 ) )", null );
- vetGoodImplicitCastFromString( conn, "cast (null as clob )", null );
- vetGoodImplicitCastFromString( conn, "cast (null as long varchar )", null );
- vetGoodImplicitCastFromString( conn, "cast (null as varchar( 10 ) )", null );
-
- vetGoodImplicitCastFromString( conn, "cast ('true' as char( 10 ) )", Boolean.TRUE );
- vetGoodImplicitCastFromString( conn, "cast ('true' as clob )", Boolean.TRUE );
- vetGoodImplicitCastFromString( conn, "cast ('true' as long varchar)", Boolean.TRUE );
- vetGoodImplicitCastFromString( conn, "cast ('true' as varchar( 10 ) )", Boolean.TRUE );
-
- vetGoodImplicitCastFromString( conn, "cast ('false' as char( 10 ) )", Boolean.FALSE );
- vetGoodImplicitCastFromString( conn, "cast ('false' as clob )", Boolean.FALSE );
- vetGoodImplicitCastFromString( conn, "cast ('false' as long varchar)", Boolean.FALSE );
- vetGoodImplicitCastFromString( conn, "cast ('false' as varchar( 10 ) )", Boolean.FALSE );
-
- expectExecutionError( conn, BAD_CAST, makeImplicitCast( "'neither'" ) );
-
- expectExecutionError( conn, BAD_CAST, makeImplicitCast( "cast ('neither' as char(10))" ) );
- expectExecutionError( conn, BAD_CAST, makeImplicitCast( "cast ('neither' as clob)" ) );
- expectExecutionError( conn, BAD_CAST, makeImplicitCast( "cast ('neither' as long varchar)" ) );
- expectExecutionError( conn, BAD_CAST, makeImplicitCast( "cast ('neither' as varchar(10))" ) );
-
vetBadImplicitCasts( conn, "bigint_col" );
vetBadImplicitCasts( conn, "blob_col" );
- // char type ok
+ vetBadImplicitCasts( conn, "char_col" );
vetBadImplicitCasts( conn, "char_for_bit_data_col" );
- // clob type ok
+ vetBadImplicitCasts( conn, "clob_col" );
vetBadImplicitCasts( conn, "date_col" );
vetBadImplicitCasts( conn, "decimal_col" );
vetBadImplicitCasts( conn, "real_col" );
vetBadImplicitCasts( conn, "double_col" );
vetBadImplicitCasts( conn, "int_col" );
- // long varchar type ok
+ vetBadImplicitCasts( conn, "long_varchar_col" );
vetBadImplicitCasts( conn, "long_varchar_for_bit_data_col" );
vetBadImplicitCasts( conn, "numeric_col" );
vetBadImplicitCasts( conn, "smallint_col" );
vetBadImplicitCasts( conn, "time_col" );
vetBadImplicitCasts( conn, "timestamp_col" );
- // varchar type ok
+ vetBadImplicitCasts( conn, "varchar_col" );
vetBadImplicitCasts( conn, "varchar_for_bit_data_col" );
if ( _supportsXML ) { vetBadImplicitCasts( conn, "xml_col" ); }
}
- private void vetGoodImplicitCastFromString( Connection conn, String text, Boolean booleanValue ) throws Exception
- {
- String expectedValue = null;
- if ( booleanValue != null ) { expectedValue = booleanValue.toString(); }
-
- assertResults
- (
- conn,
- makeImplicitCast( text ),
- new String[][]
- {
- { expectedValue },
- },
- false
- );
- }
- private String makeImplicitCast( String text )
- {
- return
- "select isindex from sys.sysconglomerates where conglomeratename = 'foo'\n" +
- "union\n" +
- "values ( " + text + " )\n";
- }
private void vetBadImplicitCasts( Connection conn, String columnName ) throws Exception
{
vetBadImplicitCastToBoolean( conn, columnName );