Bug #664 JDBC Driver Connector/J DatabaseMetaData.getImportedKeys Error

Submitted: 17 Jun 2003 22:08 Modified: 18 Jun 2003 8:09
Reporter: Roby Joehanes Email Updates:
Status: Duplicate Impact on me:
None 
Category:Connector / J Severity:S1 (Critical)
Version:3.1.0-alpha, 3.0 OS:Windows (Windows XP)
Assigned to: Mark Matthews CPU Architecture:Any

[17 Jun 2003 22:08] Roby Joehanes
Description:
DatabaseMetaData.getImportedKeys doesn't return the correct foreign key under InnoDB tables. The error is at com.mysql.jdbc.DatabaseMetaData.java
at method extractForeignKeyForTable(ArrayList, ResultSet, String)

The summary of getting foreign key is basically as follows:
* Invoke query "SHOW CREATE TABLE TABLE_NAME".
* Fetch the second column, which is basically the clause that create the table
* Parse it and look for the line that starts with "FOREIGN KEY".

The problem is:
* With InnoDB, "FOREIGN KEY" clause may not be the first two words. Rather, the declaration would look something like this:
  CONSTRAINT '0_33' FOREIGN KEY ('COL_NAME') REFERENCE OTHER_TABLE ('OTHER_COL')

So, the parser in extractForeignKeyForTable failed to detect this situation.

How to repeat:
See above

Suggested fix:
Build a more robust parser.
Change the:
if (line.startsWith("FOREIGN KEY")) {
line with:
something that will detect CONSTRAINT stuff.

For me, since I'm only interested in reference key name, other table name, and other table's primary key, I did it this way:

--------------------------------------------------------
StringTokenizer tok = new StringTokenizer(createTableString,"\n");
while (tok.hasMoreTokens()) {
    String lineToken = tok.nextToken().trim();
    StringTokenizer lineTok = new StringTokenizer(lineToken, " ");
    int state = 0;
    String[] triplet = new String[3];
    while (lineTok.hasMoreTokens()) {
        String token = lineTok.nextToken();
        switch (state) {
            case 0:
                if (token.equals("CONSTRAINT")) state = 1;
                    else if (token.equals("FOREIGN")) state = 3;
                        else state = -1; // INVALID
                break;
            case 1:
                state = 2; // Skip constraint name, we're not interested
                break;
            case 2:
                if (token.equals("FOREIGN")) state = 3;
                    else state = -1; // INVALID
                break;
            case 3:
                if (token.equals("KEY")) state = 4;
                    else state = -1; // INVALID
                break;
            case 4:
                // This is the foreign key name
                token = token.substring(2, token.length()-2);
                triplet[0] = token;
                state = 5;
                break;
            case 5:
                if (token.equals("REFERENCES")) state = 6;
                    else state = -1; // INVALID
                break;
            case 6:
                // This is the primary referencing table
                token = token.substring(1, token.length()-1);
                triplet[1] = token;
                state = 7;
                break;
            case 7:
                // This is the primary referencing column
                // Cut of trailling commas, if present
                if (token.endsWith(","))
                    token = token.substring(0, token.length()-1);
                token = token.substring(2, token.length()-2);
                triplet[2] = token;
                state = 8;
                break;
            case 8:
            default:
                state = -1; break;
        } // end switch
        if (state == -1) break;
    } // end while (lineTok.hasMoreTokens())

    if (state != -1) { // If no errors, then take care of the triplet
        rows.add(triplet)
    }
} // end while
--------------------------------------------------------

Note that: I'm not familiar with variations of Create table clauses. My suggestion is to build a custom parser like above to take care of all combinations.

Good luck.
[18 Jun 2003 8:09] Mark Matthews
This is a duplicate of #517

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.039 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.