[ 
https://issues.apache.org/jira/browse/DERBY-2758?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

A B updated DERBY-2758:
-----------------------

    Attachment: d2758_junit_test.patch

I started looking at the JUnit aspect of this test case last Friday so even 
though the odbc_metadata changes have gone in (thanks Jørgen for the patch, and 
Knut Anders for the commit)), I decided to commit another test case for JUnit, 
as well.  The patch d2758_junit_test.patch has the new test fixture, which is 
in DatabaseMetaDataTest.java.

I verified that the new test fixture runs cleanly in the current trunk and 
fails if the fix for this issue is backed out.  So committed with svn # 546312:

  URL: http://svn.apache.org/viewvc?view=rev&rev=546312

Thanks again for resolving this issue, Jørgen.

> ODBC metadata function "SQLForeignKeys" returns different results in 10.3.
> --------------------------------------------------------------------------
>
>                 Key: DERBY-2758
>                 URL: https://issues.apache.org/jira/browse/DERBY-2758
>             Project: Derby
>          Issue Type: Bug
>          Components: JDBC, Miscellaneous
>    Affects Versions: 10.3.0.0
>         Environment: DB2 Runtime Client running against Derby network server.
>            Reporter: A B
>            Assignee: Jørgen Løland
>             Fix For: 10.3.0.0
>
>         Attachments: d2758_junit_test.patch, DERBY-2758-1.diff, 
> DERBY-2758-1.stat, DERBY-2758-test.diff, DERBY-2758-test.stat
>
>
> In Derby 10.2 and earlier an ODBC application which called the SQLForeignKeys 
> function would return a set of "imported" and/or "exported" keys depending on 
> the arguments passed in.  For more on that function and its arguments, see:
>   
> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/odbcsqlforeignkeys.asp
> In particular we have the following (pasted from the above link):
> <begin paste>
> If *PKTableName contains a table name, SQLForeignKeys returns a result set 
> containing the primary key of the specified table and all of the foreign keys 
> that refer to it. The list of foreign keys in other tables does not include 
> foreign keys that point to unique constraints in the specified table.
> If *FKTableName contains a table name, SQLForeignKeys returns a result set 
> containing all of the foreign keys in the specified table that point to 
> primary keys in others tables, and the primary keys in the other tables to 
> which they refer. The list of foreign keys in the specified table does not 
> contain foreign keys that refer to unique constraints in other tables.
> If both *PKTableName and *FKTableName contain table names, SQLForeignKeys 
> returns the foreign keys in the table specified in *FKTableName that refer to 
> the primary key of the table specified in *PKTableName. This should be one 
> key at most.
> <end paste>
> Note that either PKTableName or FKTableName could be missing, i.e. could be 
> null.
> Now, in org/apache/derby/catalog/SystemProcedures.java, there is a static 
> method called "SQLFOREIGNKEYS" which, to quote the javadoc, "map[s] 
> SQLForeignKeys to EmbedDatabaseMetaData.getImportedKeys, getExportedKeys, and 
> getCrossReference".
> That method looks at some "options" that it receives from the client and 
> makes a call to the corresponding method on EmbedDatabaseMetaData:
>         String exportedKeyProp = getOption("EXPORTEDKEY", options);
>         String importedKeyProp = getOption("IMPORTEDKEY", options);
>         if (importedKeyProp != null && importedKeyProp.trim().equals("1"))
>             rs[0] = getDMD().getImportedKeys(fkCatalogName,
>                                         fkSchemaName,fkTableName);
>         else if (exportedKeyProp != null && 
> exportedKeyProp.trim().equals("1"))
>             rs[0] = getDMD().getExportedKeys(pkCatalogName,
>                                         pkSchemaName,pkTableName);
>         else
>             rs[0] = getDMD().getCrossReference (pkCatalogName,
>                                            pkSchemaName,
>                                            pkTableName,
>                                            fkCatalogName,
>                                            fkSchemaName,
>                                            fkTableName);
> That said, when running with the DB2 Runtime Client the "options" argument 
> only contains "ODBC"; it does not (appear to) contain "IMPORTEDKEY" nor 
> "EXPORTEDKEY".  So with that client we ultimately end up calling 
> "getCrossReference()" every time.  And in 
> EmbedDatabaseMetaData.getCrossReference(), we see:
>     PreparedStatement s = getPreparedQuery("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();
> That is to say, if either primaryTable or foreignTable is null, we swap it 
> with a "%" to be used for pattern matching.  Prior to the 10.3, that worked 
> fine.  With DERBY-2610, though, the getCrossReference query in 
> metadata.properties was changed to disallow pattern matching for the primary 
> key:
> @@ -532,11 +532,15 @@
>  #
>  #param1 = pattern for the PRIMARY CATALOG name 
>  #param2 = pattern for the PRIMARY SCHEMA name 
> -#param3 = pattern for the PRIMARY TABLE name 
> +#param3 = PRIMARY TABLE name 
>  #
>  #param4 = pattern for the FOREIGN CATALOG name ('%' for getExportedKeys())
>  #param5 = pattern for the FOREIGN SCHEMA name ('%' for getExportedKeys())
>  #param6 = pattern for the FOREIGN TABLE name ('%' for getExportedKeys())
> +#  DERBY-2610: did not change from pattern matching to "T2.TABLENAME=?" 
> +#          because getExportedKeys uses this query with '%' for foreign table
> +#  Future: may want to add a new query for getExportedKeys to remove the
> +#          "T2.TABLENAME LIKE ?" pattern
>  getCrossReference=\
>  SELECT CAST ('' AS VARCHAR(128)) AS PKTABLE_CAT, \
>          PKTABLE_SCHEM, \
> @@ -587,7 +591,7 @@
>                           WHERE \
>                              ((1=1) OR ? IS NOT NULL) \
>                              AND S.SCHEMANAME LIKE ? \
>                              AND T.TABLENAME LIKE ? \     <-- removed w/ 
> DERBY-2610
>                              AND T.TABLENAME=? \  <-- added with DERBY-2610
>                              AND S.SCHEMAID = T.SCHEMAID \
> As a result, the ODBC "SQLForeignKeys" function now returns zero rows because 
> there is no table whose name equals the "%" that we swapped in for the null.
> I'm not sure what the best fix for this should be.  The JDBC API for 
> getCrossReference() indicates that both primaryTable and foreignTable "must 
> match the table name as it is stored in the database", so perhaps the bug is 
> in SystemProcedures.java, where the SQLForeignKeys function is mapped to a 
> getCrossReference() call that passes nulls.  But one could argue that, given 
> the lack of information in the "options" string received from the client 
> (esp. the missing "IMPORTEDKEY" or "EXPORTEDKEY" keywords), 
> SystemProcedures.java is actually doing the right thing.  Either way, it's 
> not immediately clear to me how this should best be resolved...
> I'm marking this as a 10.3 regression (with 10.3 fixin) since the behavior in 
> the 10.3 trunk is different than what it was in previous releases.  If anyone 
> disagrees with this, please feel free to say so and/or update accordingly.
> Note: I don't think this behavior is technically covered by the release note 
> for DERBY-2610 because a) the release note does not mention 
> getCrossReference() (should it??), and b) the call to "getCrossReference()" 
> is made internally; a user's ODBC app would be calling SQLForeignKeys, for 
> which a null primary/foreign table name are in fact perfectly legal.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to