db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From abr...@apache.org
Subject svn commit: r545321 - in /db/derby/code/trunk/java: build/org/apache/derbyBuild/ODBCMetadataGenerator.java engine/org/apache/derby/catalog/SystemProcedures.java engine/org/apache/derby/impl/jdbc/EmbedDatabaseMetaData.java
Date Thu, 07 Jun 2007 21:35:38 GMT
Author: abrown
Date: Thu Jun  7 14:35:37 2007
New Revision: 545321

URL: http://svn.apache.org/viewvc?view=rev&rev=545321
Log:
DERBY-2758: Update ODBCMetadataGenerator to create an ODBC version of the
getCrossReference metadata query.  This is required because, as of DERBY-2610,
the JDBC version of that query no longer allows pattern matching on table
names.  Since the ODBC SQLForeignKeys function, which is mapped onto the
getCrossReference metadata query, depends on pattern matching for correct
behavior, we now create an ODBC-version of getCrossReference that allows
pattern matching as in pre-10.3 releases.  The SQLForeignKeys function is
then mapped to the new, ODBC-specific version of the query.

Contributed by: Jorgen Loland (jorgen.loland@sun.com)

Modified:
    db/derby/code/trunk/java/build/org/apache/derbyBuild/ODBCMetadataGenerator.java
    db/derby/code/trunk/java/engine/org/apache/derby/catalog/SystemProcedures.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedDatabaseMetaData.java

Modified: db/derby/code/trunk/java/build/org/apache/derbyBuild/ODBCMetadataGenerator.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/build/org/apache/derbyBuild/ODBCMetadataGenerator.java?view=diff&rev=545321&r1=545320&r2=545321
==============================================================================
--- db/derby/code/trunk/java/build/org/apache/derbyBuild/ODBCMetadataGenerator.java (original)
+++ db/derby/code/trunk/java/build/org/apache/derbyBuild/ODBCMetadataGenerator.java Thu Jun
 7 14:35:37 2007
@@ -56,23 +56,30 @@
  */
 public class ODBCMetadataGenerator {
 
-	// Types of changes that are possible.  There are three
+	// Types of changes that are possible.  There are four
 	// types that we handle here:
 	//
 	//	1. Column rename:
 	//		Rename a column to have an ODBC-specified name.
 	//		For ex. change "SCALE" to "DECIMAL_DIGITS"
-	//	2. Type and/or value change:
+	//	2. Where clause:
+	//		Change the where clause of the query. For ex. 
+	//		used to change getCrossReference "T.TABLENAME=?"
+	//		to "T.TABLENAME LIKE ?" since JDBC and ODBC specs
+	//		differ on whether table name must be set or not
+	//	3. Type and/or value change:
 	//		Cast a column to an OBDC-specified type.  At time
 	//		of writing, this was just for casting INTs to
 	//		SMALLINTs; OR modify an existing JDBC value
 	//		to match the ODBC specification.
-	//	3. Additional column(s):
+	//	4. Additional column(s):
 	//		Add a new, ODBC-specified column to an existing
 	//		result set.
+
 	private final byte COL_RENAME_CHANGE = 0x01;
 	private final byte TYPE_VALUE_CHANGE = 0x02;
 	private final byte ADD_COLUMN_CHANGE = 0x04;
+	private final byte WHERE_CLAUSE_CHANGE = 0x08;
 
 	// Notice written before each generated ODBC statement.
 	private final String ODBC_QUERY_NOTICE =
@@ -211,6 +218,9 @@
 		changeMap.put("getIndexInfo",
 			new Byte(TYPE_VALUE_CHANGE));
 
+		changeMap.put("getCrossReference",
+			new Byte(WHERE_CLAUSE_CHANGE));
+
 		return;
 
 	}
@@ -351,6 +361,9 @@
 		StringBuffer outerQueryText = new StringBuffer();
 		boolean haveODBCChanges = renameColsForODBC(queryName, queryText);
 
+		// -- #2: Change WHERE clause.
+		if (changeWhereClause(queryName, queryText)) haveODBCChanges = true;
+
 		// Get a list of the column definitions in the subquery, for
 		// use by subsequent operations.
 		ArrayList colDefs = new ArrayList();
@@ -361,7 +374,7 @@
 		// the outer query.
 		addHelperColsToSubquery(queryName, queryText, pos);
 
-		// -- #2.A: Prep to add new ODBC columns.  Note: we need
+		// -- #3.A: Prep to add new ODBC columns.  Note: we need
 		// to do this BEFORE we generate the outer SELECT statement.
 		markNewColPosition(queryName, colDefs);
 
@@ -370,10 +383,10 @@
 		// types (via CAST) if needed.
 		generateSELECTClause(queryName, colDefs, outerQueryText);
 
-		// -- #3: Alter column values, where needed.
+		// -- #4: Alter column values, where needed.
 		changeValuesForODBC(queryName, outerQueryText);
 
-		// -- #2.B: Add new ODBC columns.
+		// -- #3.B: Add new ODBC columns.
 		addNewColumnsForODBC(queryName, outerQueryText);
 
 		haveODBCChanges = (haveODBCChanges || (outerQueryText.length() > 0));
@@ -392,6 +405,12 @@
 		// all we did was change column names, so just write out the
 		// original query with the new column names.
 			odbcMetaFile.write(queryText.toString());
+
+			if (orderBy.length() != 0) {
+				// re-attach ORDER BY clause.
+				odbcMetaFile.write(orderBy);
+			}
+
 			odbcMetaFile.write("\n\n");
 			return;
 		}
@@ -1067,6 +1086,69 @@
 		}
 
 	}
+
+    /**
+     * changeWhereClause
+     * Substitutes patterns in the WHERE clause
+     * @param queryName The name of the JDBC query; found in
+     * metadata.properties
+     * @param queryText The buffer in which we are going to do
+     * the substitution.
+     * @return the substitution is performed IN PLACE. If no changes
+     * are needed on this query, the queryText buffer remains
+     * unchanged.
+     */
+    private boolean changeWhereClause(String queryName,
+                                      StringBuffer queryText) {
+
+        if (!stmtNeedsChange(queryName, WHERE_CLAUSE_CHANGE))
+            return false;
+
+        if (queryName.equals("getCrossReference")) {
+            substitutePatternWhere("T.TABLENAME=",
+                                   "T.TABLENAME LIKE ",
+                                   queryText);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Replaces a single occurrence of the received old pattern with
+     * the text in the new pattern
+     * @param oldPattern the text we want to remove
+     * @param newPattern the text we want to replace the oldPattern
+     * with
+     * @param queryText The buffer in which we are going to do the
+     * substitution.
+     * @return the old pattern is substituted with the new pattern (IN
+     * PLACE). If the old pattern could not be found, the queryText
+     * buffer remains unchanged.
+     */
+    private void substitutePatternWhere(String oldPattern, String newPattern,
+                                        StringBuffer queryText){
+        String queryTextString = queryText.toString();
+        int queryLength = queryTextString.length();
+        int wherePos = queryTextString.indexOf("WHERE");
+
+        //only look for the pattern after the WHERE keyword. There may
+        //actually be more than one where clause, in which case we do
+        //not know if this is the right one. Since the pattern
+        //substitution is only performed at compile time (on specified
+        //queries), more rigorous checks are not performed her.
+        //Rather, verify that
+        //classes/org/apache/derby/impl/jdbc/metadata.properties is
+        //updated correctly when you add new where-clause
+        //substitutions.
+        int posSubString = queryTextString.substring(wherePos, queryLength).
+                                           indexOf(oldPattern);
+        if (posSubString != -1)
+            //posSubString is the position in the query *after* the
+            //word WHERE. Have to add
+            queryText.replace(wherePos + posSubString,
+                              wherePos + posSubString + oldPattern.length(),
+                              newPattern);
+    }
 
 	/* ****
 	 * trimIgnorable

Modified: db/derby/code/trunk/java/engine/org/apache/derby/catalog/SystemProcedures.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/catalog/SystemProcedures.java?view=diff&rev=545321&r1=545320&r2=545321
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/catalog/SystemProcedures.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/catalog/SystemProcedures.java Thu Jun
 7 14:35:37 2007
@@ -341,12 +341,14 @@
 			rs[0] = getDMD().getExportedKeys(pkCatalogName,
 										pkSchemaName,pkTableName);
 		else
-			rs[0] = getDMD().getCrossReference (pkCatalogName,
-										   pkSchemaName,
-										   pkTableName,
-										   fkCatalogName,
-										   fkSchemaName,
-										   fkTableName);
+			//ODBC allows table name value 'null'. JDBC does not
+			rs[0] = isForODBC(options)
+				? ((EmbedDatabaseMetaData)getDMD()).getCrossReferenceForODBC(
+										pkCatalogName, pkSchemaName, pkTableName,
+										fkCatalogName, fkSchemaName, fkTableName)
+				: getDMD().getCrossReference (
+										pkCatalogName, pkSchemaName, pkTableName,
+										fkCatalogName, fkSchemaName, fkTableName);
 	}
 
 	/**

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedDatabaseMetaData.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedDatabaseMetaData.java?view=diff&rev=545321&r1=545320&r2=545321
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedDatabaseMetaData.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedDatabaseMetaData.java
Thu Jun  7 14:35:37 2007
@@ -2602,15 +2602,40 @@
 		String primaryCatalog, String primarySchema, String primaryTable,
 		String foreignCatalog, String foreignSchema, String foreignTable
 		) throws SQLException {
+
+		if (primaryTable == null || foreignTable == null) {
+			throw Util.generateCsSQLException(
+							SQLState.TABLE_NAME_CANNOT_BE_NULL);
+		}
+
 		PreparedStatement s = getPreparedQuery("getCrossReference");
 		s.setString(1, swapNull(primaryCatalog));
 		s.setString(2, swapNull(primarySchema));
-		s.setString(3, swapNull(primaryTable));
+		s.setString(3, primaryTable); //JDBC spec: must match table name as stored
 		s.setString(4, swapNull(foreignCatalog));
 		s.setString(5, swapNull(foreignSchema));
-		s.setString(6, swapNull(foreignTable));
+		s.setString(6, foreignTable); //JDBC spec: must match table name as stored
 		return s.executeQuery();
 	}
+
+    /**
+     * In contrast to the JDBC version of getCrossReference, this
+     * method allows null values for table names.
+     */
+    public ResultSet getCrossReferenceForODBC(
+        String primaryCatalog, String primarySchema, String primaryTable,
+        String foreignCatalog, String foreignSchema, String foreignTable)
+        throws SQLException {
+
+        PreparedStatement s = getPreparedQuery("odbc_getCrossReference");
+        s.setString(1, swapNull(primaryCatalog));
+        s.setString(2, swapNull(primarySchema));
+        s.setString(3, swapNull(primaryTable));
+        s.setString(4, swapNull(foreignCatalog));
+        s.setString(5, swapNull(foreignSchema));
+        s.setString(6, swapNull(foreignTable));
+        return s.executeQuery();
+    }
 
     /**
      * Get a description of all the standard SQL types supported by



Mime
View raw message