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 ma...@apache.org on 2012/07/23 17:55:23 UTC

svn commit: r1364690 - in /db/derby/code/trunk/java: engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java testing/org/apache/derbyTesting/functionTests/tests/lang/SystemCatalogTest.java

Author: mamta
Date: Mon Jul 23 15:55:23 2012
New Revision: 1364690

URL: http://svn.apache.org/viewvc?rev=1364690&view=rev
Log:
DERBY-5407 When run across the network, dblook produces unusable DDL for VARCHAR FOR BIT DATA columns. 

The serialization of UDT associated with SYSCOLUMNS.COLUMNBDATATYPE on the wire from the network server end happens correctly. The same serialized data is received by the client but when we try to instantiate the UDT's TypeDescriptor based on this serialized data, we get confused between "VARCHAR () FOR BIT DATA" and "VARCHAR FOR BIT DATA". The deserialization on the client side happens through BaseTypeIdImpl.getTypeFormatId(). Here, we look at the string representation of the type descriptor that we received on the wire and choose the appropriate format id based on that string. The problem is in this 
BaseTypeIdImpl.getTypeFormatId() code, where the code looks for "VARCHAR FOR BIT DATA" rather than "VARCHAR () FOR BIT DATA" (notice the missing parentheses) 
            else if ( "VARCHAR FOR BIT DATA".equals( unqualifiedName ) ) { return StoredFormatIds.VARBIT_TYPE_ID_IMPL; } 
Since "VARCHAR FOR BIT DATA" and "VARCHAR () FOR BIT DATA" do not match, we do not use format id VARBIT_TYPE_ID_IMPL.
 
Later, we go through a switch statement based on the format id in BaseTypeIdlImpl.toParsableString(TypeDescriptor). In the switch statement, we are supposed to stuff in the width of the varchar for bit data into the parentheses ie string "VARCHAR () FOR BIT DATA" should get converted into "VARCHAR (NUMBER) FOR BIT DATA" but we don't do it because of getTypeFormatd() code problem explained earlier.

To fix this, the patch has added check for 
If there might be dependencies on the original "VARCHAR FOR BIT DATA" check, then we can add additional check for "VARCHAR () FOR BIT DATA" in addition to the existing check for "VARCHAR FOR BIT DATA" as shown below and that fixes the problem
            else if ( "VARCHAR FOR BIT DATA".equals( unqualifiedName ) ) { return StoredFormatIds.VARBIT_TYPE_ID_IMPL; } 
            else if ( "VARCHAR () FOR BIT DATA".equals( unqualifiedName ) ) { return StoredFormatIds.VARBIT_TYPE_ID_IMPL; } 
This commit does similar thing for "CHAR FOR BIT DATA", ie in addition to the existing test for "CHAR FOR BIT DATA", it adds a check for "CHAR () FOR BIT DATA". 

Keeping the existing checks will not break any dependencies that might exist on "VARCHAR FOR BIT DATA" check and "CHAR FOR BIT DATA" check.

Have added a test for SYSCOLUMNS.COLUMNBDATATYPE for all the supported data types. This test will be run in both embedded and network server mode.


Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SystemCatalogTest.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java?rev=1364690&r1=1364689&r2=1364690&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java Mon Jul 23 15:55:23 2012
@@ -255,29 +255,37 @@ public class BaseTypeIdImpl implements F
             // will lose the format id. This can happen if you pass one of these
             // objects across the network. Here we recover the format id.
             //
-            if ( "BOOLEAN".equals( unqualifiedName ) ) { return StoredFormatIds.BOOLEAN_TYPE_ID_IMPL; }
-            else if ( "BIGINT".equals( unqualifiedName ) ) { return StoredFormatIds.LONGINT_TYPE_ID_IMPL; }
-            else if ( "INTEGER".equals( unqualifiedName ) ) { return StoredFormatIds.INT_TYPE_ID_IMPL; }
-            else if ( "SMALLINT".equals( unqualifiedName ) ) { return StoredFormatIds.SMALLINT_TYPE_ID_IMPL; }
-            else if ( "TINYINT".equals( unqualifiedName ) ) { return StoredFormatIds.TINYINT_TYPE_ID_IMPL; }
-            else if ( "LONGINT".equals( unqualifiedName ) ) { return StoredFormatIds.LONGINT_TYPE_ID_IMPL; }
-            else if ( "DECIMAL".equals( unqualifiedName ) ) { return StoredFormatIds.DECIMAL_TYPE_ID_IMPL; }
-            else if ( "NUMERIC".equals( unqualifiedName ) ) { return StoredFormatIds.DECIMAL_TYPE_ID_IMPL; }
-            else if ( "DOUBLE".equals( unqualifiedName ) ) { return StoredFormatIds.DOUBLE_TYPE_ID_IMPL; }
-            else if ( "REAL".equals( unqualifiedName ) ) { return StoredFormatIds.REAL_TYPE_ID_IMPL; }
-            else if ( "REF".equals( unqualifiedName ) ) { return StoredFormatIds.REF_TYPE_ID_IMPL; }
-            else if ( "CHAR".equals( unqualifiedName ) ) { return StoredFormatIds.CHAR_TYPE_ID_IMPL; }
-            else if ( "VARCHAR".equals( unqualifiedName ) ) { return StoredFormatIds.VARCHAR_TYPE_ID_IMPL; }
-            else if ( "LONG VARCHAR".equals( unqualifiedName ) ) { return StoredFormatIds.LONGVARCHAR_TYPE_ID_IMPL; }
-            else if ( "CLOB".equals( unqualifiedName ) ) { return StoredFormatIds.CLOB_TYPE_ID_IMPL; }
+            if ( TypeId.BOOLEAN_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.BOOLEAN_TYPE_ID_IMPL; }
+            else if ( TypeId.LONGINT_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.LONGINT_TYPE_ID_IMPL; }
+            else if ( TypeId.INTEGER_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.INT_TYPE_ID_IMPL; }
+            else if ( TypeId.SMALLINT_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.SMALLINT_TYPE_ID_IMPL; }
+            else if ( TypeId.TINYINT_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.TINYINT_TYPE_ID_IMPL; }
+            else if ( TypeId.LONGINT_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.LONGINT_TYPE_ID_IMPL; }
+            else if ( TypeId.DECIMAL_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.DECIMAL_TYPE_ID_IMPL; }
+            else if ( TypeId.NUMERIC_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.DECIMAL_TYPE_ID_IMPL; }
+            else if ( TypeId.DOUBLE_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.DOUBLE_TYPE_ID_IMPL; }
+            else if ( TypeId.REAL_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.REAL_TYPE_ID_IMPL; }
+            else if ( TypeId.REF_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.REF_TYPE_ID_IMPL; }
+            else if ( TypeId.CHAR_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.CHAR_TYPE_ID_IMPL; }
+            else if ( TypeId.VARCHAR_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.VARCHAR_TYPE_ID_IMPL; }
+            else if ( TypeId.LONGVARCHAR_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.LONGVARCHAR_TYPE_ID_IMPL; }
+            else if ( TypeId.CLOB_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.CLOB_TYPE_ID_IMPL; }
+            //DERBY-5407 Network Server on wire sends CHAR () FOR BIT DATA 
+            // not CHAR FOR BIT DATA. Keeping the check for CHAR FOR BIT
+            // DATA just in case if there is any dependency on that check
+            else if ( TypeId.BIT_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.BIT_TYPE_ID_IMPL; }
             else if ( "CHAR FOR BIT DATA".equals( unqualifiedName ) ) { return StoredFormatIds.BIT_TYPE_ID_IMPL; }
+            //DERBY-5407 Network Server on wire sends VARCHAR () FOR BIT DATA 
+            // not VARCHAR FOR BIT DATA. Keeping the check for VARCHAR FOR BIT
+            // DATA just in case if there is any dependency on that check
+            else if ( TypeId.VARBIT_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.VARBIT_TYPE_ID_IMPL; }
             else if ( "VARCHAR FOR BIT DATA".equals( unqualifiedName ) ) { return StoredFormatIds.VARBIT_TYPE_ID_IMPL; }
-            else if ( "LONG VARCHAR FOR BIT DATA".equals( unqualifiedName ) ) { return StoredFormatIds.LONGVARBIT_TYPE_ID_IMPL; }
-            else if ( "BLOB".equals( unqualifiedName ) ) { return StoredFormatIds.BLOB_TYPE_ID_IMPL; }
-            else if ( "DATE".equals( unqualifiedName ) ) { return StoredFormatIds.DATE_TYPE_ID_IMPL; }
-            else if ( "TIME".equals( unqualifiedName ) ) { return StoredFormatIds.TIME_TYPE_ID_IMPL; }
-            else if ( "TIMESTAMP".equals( unqualifiedName ) ) { return StoredFormatIds.TIMESTAMP_TYPE_ID_IMPL; }
-            else if ( "XML".equals( unqualifiedName ) ) { return StoredFormatIds.XML_TYPE_ID_IMPL; }
+            else if ( TypeId.LONGVARBIT_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.LONGVARBIT_TYPE_ID_IMPL; }
+            else if ( TypeId.BLOB_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.BLOB_TYPE_ID_IMPL; }
+            else if ( TypeId.DATE_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.DATE_TYPE_ID_IMPL; }
+            else if ( TypeId.TIME_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.TIME_TYPE_ID_IMPL; }
+            else if ( TypeId.TIMESTAMP_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.TIMESTAMP_TYPE_ID_IMPL; }
+            else if ( TypeId.XML_NAME.equals( unqualifiedName ) ) { return StoredFormatIds.XML_TYPE_ID_IMPL; }
             else { return 0; }
         }
     }

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SystemCatalogTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SystemCatalogTest.java?rev=1364690&r1=1364689&r2=1364690&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SystemCatalogTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SystemCatalogTest.java Mon Jul 23 15:55:23 2012
@@ -25,7 +25,12 @@ import java.sql.Connection;
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.sql.ResultSet;
+import java.sql.Types;
+
+import org.apache.derby.iapi.services.io.StoredFormatIds;
+import org.apache.derbyTesting.functionTests.tests.compatibility.JDBCDriverTest.TypeDescriptor;
 import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.DerbyVersion;
 import org.apache.derbyTesting.junit.JDBC;
 import org.apache.derbyTesting.junit.TestConfiguration;
 import junit.framework.Test;
@@ -40,7 +45,7 @@ import junit.framework.TestSuite;
  */
 public class SystemCatalogTest extends BaseJDBCTestCase {
 
-	public SystemCatalogTest(String name) {
+    public SystemCatalogTest(String name) {
 		super(name);
 	}
 	
@@ -561,6 +566,117 @@ public class SystemCatalogTest extends B
 		s.execute("drop table uniquekey3");
 		s.close();
 	}
+
+	/**
+	 * This test creates a table with all supported datatypes aqnd ensures 
+	 * that bound embedded and network server return the identical datatypes
+	 * for those datatypes. DERBY-5407
+	 * @throws SQLException
+	 */
+	public void testColumnDatatypesOfAllDataTypesInSystemCatalogs() throws SQLException {
+		int totalNumOfColumnDatatypes = 21;
+		Statement s = createStatement();
+		s.execute("create table allTypesTable (" +
+			"    a01 bigint," +
+			"    a02 blob,\n" +
+			"    a03 char( 1 ),\n" +
+			"    a04 char( 1 ) for bit data ,\n" +
+			"    a05 clob,\n" +
+			"    a06 date,\n" +
+			"    a07 decimal,\n" +
+			"    a08 double,\n" +
+			"    a09 float,\n" +
+			"    a10 int,\n" +
+			"    a11 long varchar,\n" +
+			"    a12 long varchar for bit data,\n" +
+			"    a13 numeric,\n" +
+			"    a14 real,\n" +
+			"    a15 smallint,\n" +
+			"    a16 time,\n" +
+			"    a17 timestamp,\n" +
+			"    a18 varchar(10),\n" +
+			"    a19 varchar(10) for bit data,\n" +
+			"    a20 xml,\n" +
+			"    a21 boolean\n" +
+        	")");
+		ResultSet rs = s.executeQuery("select columndatatype "+
+			"from sys.systables, sys.syscolumns "+
+			"where tablename='ALLTYPESTABLE' "+
+			"and tableid=referenceid "+
+			"order by columnname");
+		for (int i=1; i<=totalNumOfColumnDatatypes; i++)
+		{
+			rs.next();
+			switch(i)
+			{
+			case 1 :
+				assertTrue(rs.getString(1).startsWith("BIGINT"));
+				break;
+			case 2 :
+				assertTrue(rs.getString(1).startsWith("BLOB(2147483647)"));
+				break;
+			case 3 :
+				assertTrue(rs.getString(1).startsWith("CHAR(1)"));
+				break;
+			case 4 :
+				assertTrue(rs.getString(1).startsWith("CHAR (1) FOR BIT DATA"));
+				break;
+			case 5 :
+				assertTrue(rs.getString(1).startsWith("CLOB(2147483647)"));
+				break;
+			case 6 :
+				assertTrue(rs.getString(1).startsWith("DATE"));
+				break;
+			case 7 :
+				assertTrue(rs.getString(1).startsWith("DECIMAL(5,0)"));
+				break;
+			case 8 :
+				assertTrue(rs.getString(1).startsWith("DOUBLE"));
+				break;
+			case 9 :
+				assertTrue(rs.getString(1).startsWith("DOUBLE"));
+				break;
+			case 10 :
+				assertTrue(rs.getString(1).startsWith("INTEGER"));
+				break;
+			case 11 :
+				assertTrue(rs.getString(1).startsWith("LONG VARCHAR"));
+				break;
+			case 12 :
+				assertTrue(rs.getString(1).startsWith("LONG VARCHAR FOR BIT DATA"));
+				break;
+			case 13 :
+				assertTrue(rs.getString(1).startsWith("NUMERIC(5,0)"));
+				break;
+			case 14 :
+				assertTrue(rs.getString(1).startsWith("REAL"));
+				break;
+			case 15 :
+				assertTrue(rs.getString(1).startsWith("SMALLINT"));
+				break;
+			case 16 :
+				assertTrue(rs.getString(1).startsWith("TIME"));
+				break;
+			case 17 :
+				assertTrue(rs.getString(1).startsWith("TIMESTAMP"));
+				break;
+			case 18 :
+				assertTrue(rs.getString(1).startsWith("VARCHAR(10)"));
+				break;
+			case 19 :
+				assertTrue(rs.getString(1).startsWith("VARCHAR (10) FOR BIT DATA"));
+				break;
+			case 20 :
+				assertTrue(rs.getString(1).startsWith("XML"));
+				break;
+			case 21 :
+				assertTrue(rs.getString(1).startsWith("BOOLEAN"));
+				break;
+			}
+		}
+		rs.close();
+		s.execute("drop table ALLTYPESTABLE");
+	}
 	
 	/**
 	 * Check that column datatypes are reported correctly, both in