Skip to content

Commit a1a5ccd

Browse files
committed
Fix for Bug#95280 (29757140), DATABASEMETADATA.GETIMPORTEDKEYS RETURNS
DOUBLE THE ROWS.
1 parent 10aa4c9 commit a1a5ccd

File tree

4 files changed

+96
-34
lines changed

4 files changed

+96
-34
lines changed

CHANGES

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
Version 8.0.26
55

6+
- Fix for Bug#95280 (29757140), DATABASEMETADATA.GETIMPORTEDKEYS RETURNS DOUBLE THE ROWS.
7+
Thanks to Miron Balcerzak for his contribution.
8+
69
- Fix for Bug#97269 (30438500), POSSIBLE BUG IN COM.MYSQL.CJ.XDEVAPI.STREAMINGDOCRESULTBUILDER.
710

811
- Fix for Bug#103303 (32766143), JAVA.LANG.CLASSCASTEXCEPTION WHEN INSERTING BLOB WITH SERVER PREPARED STATEMENT.

src/main/user-impl/java/com/mysql/cj/jdbc/DatabaseMetaDataUsingInfoSchema.java

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -299,23 +299,24 @@ public java.sql.ResultSet getCrossReference(String primaryCatalog, String primar
299299
primaryDb = this.pedantic ? primaryDb : StringUtils.unQuoteIdentifier(primaryDb, this.quotedId);
300300
foreignDb = this.pedantic ? foreignDb : StringUtils.unQuoteIdentifier(foreignDb, this.quotedId);
301301

302-
StringBuilder sqlBuf = new StringBuilder(
303-
this.databaseTerm.getValue() == DatabaseTerm.SCHEMA ? "SELECT A.CONSTRAINT_CATALOG AS PKTABLE_CAT, A.REFERENCED_TABLE_SCHEMA AS PKTABLE_SCHEM,"
304-
: "SELECT A.REFERENCED_TABLE_SCHEMA AS PKTABLE_CAT,NULL AS PKTABLE_SCHEM,");
302+
StringBuilder sqlBuf = new StringBuilder(this.databaseTerm.getValue() == DatabaseTerm.SCHEMA
303+
? "SELECT DISTINCT A.CONSTRAINT_CATALOG AS PKTABLE_CAT, A.REFERENCED_TABLE_SCHEMA AS PKTABLE_SCHEM,"
304+
: "SELECT DISTINCT A.REFERENCED_TABLE_SCHEMA AS PKTABLE_CAT,NULL AS PKTABLE_SCHEM,");
305305
sqlBuf.append(" A.REFERENCED_TABLE_NAME AS PKTABLE_NAME, A.REFERENCED_COLUMN_NAME AS PKCOLUMN_NAME,");
306306
sqlBuf.append(this.databaseTerm.getValue() == DatabaseTerm.SCHEMA ? " A.TABLE_CATALOG AS FKTABLE_CAT, A.TABLE_SCHEMA AS FKTABLE_SCHEM,"
307307
: " A.TABLE_SCHEMA AS FKTABLE_CAT, NULL AS FKTABLE_SCHEM,");
308308
sqlBuf.append(" A.TABLE_NAME AS FKTABLE_NAME, A.COLUMN_NAME AS FKCOLUMN_NAME, A.ORDINAL_POSITION AS KEY_SEQ,");
309309
sqlBuf.append(generateUpdateRuleClause());
310310
sqlBuf.append(" AS UPDATE_RULE,");
311311
sqlBuf.append(generateDeleteRuleClause());
312-
sqlBuf.append(" AS DELETE_RULE, A.CONSTRAINT_NAME AS FK_NAME,");
313-
sqlBuf.append(" (SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_SCHEMA = A.REFERENCED_TABLE_SCHEMA");
314-
sqlBuf.append(" AND TABLE_NAME = A.REFERENCED_TABLE_NAME AND CONSTRAINT_TYPE IN ('UNIQUE','PRIMARY KEY') LIMIT 1) AS PK_NAME, ");
312+
sqlBuf.append(" AS DELETE_RULE, A.CONSTRAINT_NAME AS FK_NAME, TC.CONSTRAINT_NAME AS PK_NAME,");
315313
sqlBuf.append(importedKeyNotDeferrable);
316314
sqlBuf.append(" AS DEFERRABILITY FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE A");
317315
sqlBuf.append(" JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS B USING (TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_NAME) ");
318316
sqlBuf.append(generateOptionalRefContraintsJoin());
317+
sqlBuf.append(" LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC ON (A.REFERENCED_TABLE_SCHEMA = TC.TABLE_SCHEMA");
318+
sqlBuf.append(" AND A.REFERENCED_TABLE_NAME = TC.TABLE_NAME");
319+
sqlBuf.append(" AND TC.CONSTRAINT_TYPE IN ('UNIQUE', 'PRIMARY KEY'))");
319320
sqlBuf.append("WHERE B.CONSTRAINT_TYPE = 'FOREIGN KEY'");
320321
if (primaryDb != null) {
321322
sqlBuf.append(" AND A.REFERENCED_TABLE_SCHEMA=?");
@@ -363,23 +364,24 @@ public java.sql.ResultSet getExportedKeys(String catalog, String schema, String
363364

364365
db = this.pedantic ? db : StringUtils.unQuoteIdentifier(db, this.quotedId);
365366

366-
StringBuilder sqlBuf = new StringBuilder(
367-
this.databaseTerm.getValue() == DatabaseTerm.SCHEMA ? "SELECT A.CONSTRAINT_CATALOG AS PKTABLE_CAT, A.REFERENCED_TABLE_SCHEMA AS PKTABLE_SCHEM,"
368-
: "SELECT A.REFERENCED_TABLE_SCHEMA AS PKTABLE_CAT,NULL AS PKTABLE_SCHEM,");
367+
StringBuilder sqlBuf = new StringBuilder(this.databaseTerm.getValue() == DatabaseTerm.SCHEMA
368+
? "SELECT DISTINCT A.CONSTRAINT_CATALOG AS PKTABLE_CAT, A.REFERENCED_TABLE_SCHEMA AS PKTABLE_SCHEM,"
369+
: "SELECT DISTINCT A.REFERENCED_TABLE_SCHEMA AS PKTABLE_CAT,NULL AS PKTABLE_SCHEM,");
369370
sqlBuf.append(" A.REFERENCED_TABLE_NAME AS PKTABLE_NAME, A.REFERENCED_COLUMN_NAME AS PKCOLUMN_NAME,");
370371
sqlBuf.append(this.databaseTerm.getValue() == DatabaseTerm.SCHEMA ? " A.TABLE_CATALOG AS FKTABLE_CAT, A.TABLE_SCHEMA AS FKTABLE_SCHEM,"
371372
: " A.TABLE_SCHEMA AS FKTABLE_CAT, NULL AS FKTABLE_SCHEM,");
372373
sqlBuf.append(" A.TABLE_NAME AS FKTABLE_NAME, A.COLUMN_NAME AS FKCOLUMN_NAME, A.ORDINAL_POSITION AS KEY_SEQ,");
373374
sqlBuf.append(generateUpdateRuleClause());
374375
sqlBuf.append(" AS UPDATE_RULE,");
375376
sqlBuf.append(generateDeleteRuleClause());
376-
sqlBuf.append(" AS DELETE_RULE, A.CONSTRAINT_NAME AS FK_NAME, (SELECT CONSTRAINT_NAME FROM");
377-
sqlBuf.append(" INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_SCHEMA = A.REFERENCED_TABLE_SCHEMA AND");
378-
sqlBuf.append(" TABLE_NAME = A.REFERENCED_TABLE_NAME AND CONSTRAINT_TYPE IN ('UNIQUE','PRIMARY KEY') LIMIT 1) AS PK_NAME,");
377+
sqlBuf.append(" AS DELETE_RULE, A.CONSTRAINT_NAME AS FK_NAME, TC.CONSTRAINT_NAME AS PK_NAME,");
379378
sqlBuf.append(importedKeyNotDeferrable);
380379
sqlBuf.append(" AS DEFERRABILITY FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE A");
381380
sqlBuf.append(" JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS B USING (TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_NAME) ");
382381
sqlBuf.append(generateOptionalRefContraintsJoin());
382+
sqlBuf.append(" LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC ON (A.REFERENCED_TABLE_SCHEMA = TC.TABLE_SCHEMA");
383+
sqlBuf.append(" AND A.REFERENCED_TABLE_NAME = TC.TABLE_NAME");
384+
sqlBuf.append(" AND TC.CONSTRAINT_TYPE IN ('UNIQUE', 'PRIMARY KEY'))");
383385
sqlBuf.append(" WHERE B.CONSTRAINT_TYPE = 'FOREIGN KEY'");
384386
if (db != null) {
385387
sqlBuf.append(" AND A.REFERENCED_TABLE_SCHEMA = ?");
@@ -441,23 +443,24 @@ public java.sql.ResultSet getImportedKeys(String catalog, String schema, String
441443

442444
db = this.pedantic ? db : StringUtils.unQuoteIdentifier(db, this.quotedId);
443445

444-
StringBuilder sqlBuf = new StringBuilder(
445-
this.databaseTerm.getValue() == DatabaseTerm.SCHEMA ? "SELECT A.CONSTRAINT_CATALOG AS PKTABLE_CAT, A.REFERENCED_TABLE_SCHEMA AS PKTABLE_SCHEM,"
446-
: "SELECT A.REFERENCED_TABLE_SCHEMA AS PKTABLE_CAT,NULL AS PKTABLE_SCHEM,");
446+
StringBuilder sqlBuf = new StringBuilder(this.databaseTerm.getValue() == DatabaseTerm.SCHEMA
447+
? "SELECT DISTINCT A.CONSTRAINT_CATALOG AS PKTABLE_CAT, A.REFERENCED_TABLE_SCHEMA AS PKTABLE_SCHEM,"
448+
: "SELECT DISTINCT A.REFERENCED_TABLE_SCHEMA AS PKTABLE_CAT,NULL AS PKTABLE_SCHEM,");
447449
sqlBuf.append(" A.REFERENCED_TABLE_NAME AS PKTABLE_NAME, A.REFERENCED_COLUMN_NAME AS PKCOLUMN_NAME,");
448450
sqlBuf.append(this.databaseTerm.getValue() == DatabaseTerm.SCHEMA ? " A.TABLE_CATALOG AS FKTABLE_CAT, A.TABLE_SCHEMA AS FKTABLE_SCHEM,"
449451
: " A.TABLE_SCHEMA AS FKTABLE_CAT, NULL AS FKTABLE_SCHEM,");
450452
sqlBuf.append(" A.TABLE_NAME AS FKTABLE_NAME, A.COLUMN_NAME AS FKCOLUMN_NAME, A.ORDINAL_POSITION AS KEY_SEQ,");
451453
sqlBuf.append(generateUpdateRuleClause());
452454
sqlBuf.append(" AS UPDATE_RULE,");
453455
sqlBuf.append(generateDeleteRuleClause());
454-
sqlBuf.append(" AS DELETE_RULE, A.CONSTRAINT_NAME AS FK_NAME, (SELECT CONSTRAINT_NAME FROM");
455-
sqlBuf.append(" INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_SCHEMA = A.REFERENCED_TABLE_SCHEMA AND");
456-
sqlBuf.append(" TABLE_NAME = A.REFERENCED_TABLE_NAME AND CONSTRAINT_TYPE IN ('UNIQUE','PRIMARY KEY') LIMIT 1) AS PK_NAME,");
456+
sqlBuf.append(" AS DELETE_RULE, A.CONSTRAINT_NAME AS FK_NAME, TC.CONSTRAINT_NAME AS PK_NAME,");
457457
sqlBuf.append(importedKeyNotDeferrable);
458458
sqlBuf.append(" AS DEFERRABILITY FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE A");
459459
sqlBuf.append(" JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS B USING (CONSTRAINT_NAME, TABLE_NAME) ");
460460
sqlBuf.append(generateOptionalRefContraintsJoin());
461+
sqlBuf.append(" LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC ON (A.REFERENCED_TABLE_SCHEMA = TC.TABLE_SCHEMA");
462+
sqlBuf.append(" AND A.REFERENCED_TABLE_NAME = TC.TABLE_NAME");
463+
sqlBuf.append(" AND TC.CONSTRAINT_TYPE IN ('UNIQUE', 'PRIMARY KEY'))");
461464
sqlBuf.append("WHERE B.CONSTRAINT_TYPE = 'FOREIGN KEY'");
462465
if (db != null) {
463466
sqlBuf.append(" AND A.TABLE_SCHEMA = ?");

src/test/java/testsuite/regression/MetaDataRegressionTest.java

Lines changed: 70 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,27 +1063,38 @@ public void testBug11781() throws Exception {
10631063
* this.conn.getCatalog(), null, "app tab", this.conn.getCatalog(),
10641064
* null, "app tab");
10651065
*/
1066-
String db = ((JdbcConnection) this.conn).getPropertySet().<DatabaseTerm>getEnumProperty(PropertyKey.databaseTerm).getValue() == DatabaseTerm.SCHEMA
1067-
? this.conn.getSchema()
1068-
: this.conn.getCatalog();
1069-
this.rs = ((com.mysql.cj.jdbc.DatabaseMetaData) this.conn.getMetaData()).extractForeignKeyFromCreateTable(db, "app tab");
1070-
assertTrue(this.rs.next(), "must return a row");
10711066

1072-
assertEquals(("comment; APPFK(`C1`) REFER `" + db + "`/ `app tab` (`C1`)").toUpperCase(), this.rs.getString(3).toUpperCase());
1067+
Properties props = new Properties();
1068+
for (boolean useIS : new boolean[] { false, true }) {
1069+
for (String databaseTerm : new String[] { "CATALOG", "SCHEMA" }) {
1070+
props.setProperty(PropertyKey.useInformationSchema.getKeyName(), "" + useIS);
1071+
props.setProperty(PropertyKey.databaseTerm.getKeyName(), databaseTerm);
10731072

1074-
this.rs.close();
1073+
System.out.println("useInformationSchema=" + useIS + ", databaseTerm=" + databaseTerm);
10751074

1076-
this.rs = ((JdbcConnection) this.conn).getPropertySet().<DatabaseTerm>getEnumProperty(PropertyKey.databaseTerm).getValue() == DatabaseTerm.SCHEMA
1077-
? this.conn.getMetaData().getImportedKeys(null, this.conn.getCatalog(), "app tab")
1078-
: this.conn.getMetaData().getImportedKeys(this.conn.getCatalog(), null, "app tab");
1075+
Connection con = getConnectionWithProps(props);
10791076

1080-
assertTrue(this.rs.next());
1077+
String db = databaseTerm.contentEquals("SCHEMA") ? con.getSchema() : con.getCatalog();
1078+
this.rs = ((com.mysql.cj.jdbc.DatabaseMetaData) con.getMetaData()).extractForeignKeyFromCreateTable(db, "app tab");
1079+
assertTrue(this.rs.next(), "must return a row");
10811080

1082-
this.rs = ((JdbcConnection) this.conn).getPropertySet().<DatabaseTerm>getEnumProperty(PropertyKey.databaseTerm).getValue() == DatabaseTerm.SCHEMA
1083-
? this.conn.getMetaData().getExportedKeys(null, this.conn.getCatalog(), "app tab")
1084-
: this.conn.getMetaData().getExportedKeys(this.conn.getCatalog(), null, "app tab");
1081+
assertEquals(("comment; APPFK(`C1`) REFER `" + db + "`/ `app tab` (`C1`)").toUpperCase(), this.rs.getString(3).toUpperCase());
1082+
1083+
this.rs.close();
1084+
1085+
this.rs = databaseTerm.contentEquals("SCHEMA") ? con.getMetaData().getImportedKeys(null, con.getSchema(), "app tab")
1086+
: con.getMetaData().getImportedKeys(con.getCatalog(), null, "app tab");
1087+
1088+
assertTrue(this.rs.next());
1089+
1090+
this.rs = databaseTerm.contentEquals("SCHEMA") ? con.getMetaData().getExportedKeys(null, con.getSchema(), "app tab")
1091+
: con.getMetaData().getExportedKeys(con.getCatalog(), null, "app tab");
1092+
1093+
assertTrue(this.rs.next());
1094+
1095+
}
1096+
}
10851097

1086-
assertTrue(this.rs.next());
10871098
}
10881099

10891100
/**
@@ -5146,4 +5157,48 @@ public void testBug102076() throws Exception {
51465157
} while (this.rs.next());
51475158

51485159
}
5160+
5161+
/**
5162+
* Tests fix for Bug#95280 (29757140), DATABASEMETADATA.GETIMPORTEDKEYS RETURNS DOUBLE THE ROWS.
5163+
*
5164+
* @throws Exception
5165+
*/
5166+
@Test
5167+
public void testBug95280() throws Exception {
5168+
String databaseName1 = "dbBug95280_1";
5169+
createDatabase(databaseName1);
5170+
createTable(databaseName1 + ".table1",
5171+
"(cat_id int not null auto_increment primary key, cat_name varchar(255) not null, cat_description text) ENGINE=InnoDB;");
5172+
createTable(databaseName1 + ".table2",
5173+
"(prd_id int not null auto_increment primary key, prd_name varchar(355) not null, prd_price decimal, cat_id int not null,"
5174+
+ " FOREIGN KEY fk_cat(cat_id) REFERENCES table1(cat_id) ON UPDATE CASCADE ON DELETE RESTRICT) ENGINE=InnoDB;");
5175+
5176+
String databaseName2 = "dbBug95280_2";
5177+
createDatabase(databaseName2);
5178+
createTable(databaseName2 + ".table1",
5179+
"(cat_id int not null auto_increment primary key, cat_name varchar(255) not null, cat_description text) ENGINE=InnoDB;");
5180+
createTable(databaseName2 + ".table2",
5181+
"(prd_id int not null auto_increment primary key, prd_name varchar(355) not null, prd_price decimal, cat_id int not null,"
5182+
+ " FOREIGN KEY fk_cat(cat_id) REFERENCES table1(cat_id) ON UPDATE CASCADE ON DELETE RESTRICT) ENGINE=InnoDB;");
5183+
5184+
Properties props = new Properties();
5185+
for (boolean useIS : new boolean[] { false, true }) {
5186+
for (String databaseTerm : new String[] { "CATALOG", "SCHEMA" }) {
5187+
props.setProperty(PropertyKey.useInformationSchema.getKeyName(), "" + useIS);
5188+
props.setProperty(PropertyKey.databaseTerm.getKeyName(), databaseTerm);
5189+
5190+
Connection con = getConnectionWithProps(props);
5191+
DatabaseMetaData meta = con.getMetaData();
5192+
5193+
this.rs = databaseTerm.contentEquals("SCHEMA") ? meta.getImportedKeys(null, databaseName1, "table2")
5194+
: meta.getImportedKeys(databaseName1, null, "table2");
5195+
assertTrue(this.rs.next());
5196+
assertEquals("table2", this.rs.getString("FKTABLE_NAME"));
5197+
assertEquals("cat_id", this.rs.getString("FKCOLUMN_NAME"));
5198+
assertEquals(1, this.rs.getInt("KEY_SEQ"));
5199+
assertFalse(this.rs.next());
5200+
con.close();
5201+
}
5202+
}
5203+
}
51495204
}

src/test/java/testsuite/simple/MetadataTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1366,11 +1366,12 @@ public void testGetCrossReferenceUsingInfoSchema() throws Exception {
13661366
conn1 = getConnectionWithProps(props);
13671367
DatabaseMetaData metaData = conn1.getMetaData();
13681368
this.rs = metaData.getCrossReference(null, null, "parent", null, null, "child");
1369-
this.rs.next();
1369+
assertTrue(this.rs.next());
13701370
assertEquals("parent", this.rs.getString("PKTABLE_NAME"));
13711371
assertEquals("id", this.rs.getString("PKCOLUMN_NAME"));
13721372
assertEquals("child", this.rs.getString("FKTABLE_NAME"));
13731373
assertEquals("parent_id", this.rs.getString("FKCOLUMN_NAME"));
1374+
assertFalse(this.rs.next());
13741375
} finally {
13751376
this.stmt.executeUpdate("DROP TABLE IF EXISTS child");
13761377
this.stmt.executeUpdate("DROP TABLE If EXISTS parent");

0 commit comments

Comments
 (0)