Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[CONJ-812] DatabaseMetadata getBestRowIdentifier and getMaxProcedureN…
…ameLength correction

* getBestRowIdentifier:
** Pseudo-code good value
** only return "best" column, so primary or if no primary unique cols depending on nullable parameter

* getMaxProcedureNameLength() now return 64 in place of 256 (https://mariadb.com/kb/en/identifier-names/#maximum-length)
  • Loading branch information
rusher committed Aug 25, 2020
1 parent 7363e25 commit f3055c7
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 19 deletions.
33 changes: 23 additions & 10 deletions src/main/java/org/mariadb/jdbc/MariaDbDatabaseMetaData.java
Expand Up @@ -1070,19 +1070,29 @@ public ResultSet getBestRowIdentifier(

String sql =
"SELECT "
+ DatabaseMetaData.bestRowUnknown
+ bestRowSession
+ " SCOPE, COLUMN_NAME,"
+ dataTypeClause("COLUMN_TYPE")
+ " DATA_TYPE, DATA_TYPE TYPE_NAME,"
+ " IF(NUMERIC_PRECISION IS NULL, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION) COLUMN_SIZE, 0 BUFFER_LENGTH,"
+ " NUMERIC_SCALE DECIMAL_DIGITS,"
+ " 1 PSEUDO_COLUMN"
+ " if(IS_GENERATED='NEVER',"
+ bestRowNotPseudo
+ ","
+ bestRowPseudo
+ ") PSEUDO_COLUMN"
+ " FROM INFORMATION_SCHEMA.COLUMNS"
+ " WHERE COLUMN_KEY IN('PRI', 'MUL', 'UNI')"
+ " AND "
+ " WHERE (COLUMN_KEY = 'PRI'"
+ " OR (COLUMN_KEY = 'UNI' AND NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_KEY = "
+ "'PRI' AND "
+ catalogCond("TABLE_SCHEMA", catalog)
+ " AND TABLE_NAME = "
+ escapeQuote(table)
+ " ))) AND "
+ catalogCond("TABLE_SCHEMA", catalog)
+ " AND TABLE_NAME = "
+ escapeQuote(table);
+ escapeQuote(table)
+ (nullable ? "" : " AND IS_NULLABLE = 'NO'");

return executeQuery(sql);
}
Expand Down Expand Up @@ -1800,7 +1810,7 @@ public int getMaxSchemaNameLength() {
}

public int getMaxProcedureNameLength() {
return 256;
return 64;
}

public int getMaxCatalogNameLength() {
Expand Down Expand Up @@ -2533,15 +2543,16 @@ public ResultSet getVersionColumns(String catalog, String schema, String table)
* @param parentSchema a schema name; must match the schema name as it is stored in the database;
* "" retrieves those without a schema; <code>null</code> means drop schema name from the
* selection criteria
* @param parentTable the name of the table that exports the key; pattern, or null (means any table) value
* @param parentTable the name of the table that exports the key; pattern, or null (means any
* table) value
* @param foreignCatalog a catalog name; must match the catalog name as it is stored in the
* database; "" retrieves those without a catalog; <code>null</code> means drop catalog name
* from the selection criteria
* @param foreignSchema a schema name; must match the schema name as it is stored in the database;
* "" retrieves those without a schema; <code>null</code> means drop schema name from the
* selection criteria
* @param foreignTable the name of the table that imports the key; pattern, or null (means any table) value
* is stored in the database
* @param foreignTable the name of the table that imports the key; pattern, or null (means any
* table) value is stored in the database
* @return <code>ResultSet</code> - each row is a foreign key column description
* @throws SQLException if a database access error occurs
* @see #getImportedKeys
Expand Down Expand Up @@ -3366,7 +3377,9 @@ public ResultSet getIndexInfo(

String sql =
"SELECT TABLE_SCHEMA TABLE_CAT, NULL TABLE_SCHEM, TABLE_NAME, NON_UNIQUE, "
+ " TABLE_SCHEMA INDEX_QUALIFIER, INDEX_NAME, 3 TYPE,"
+ " TABLE_SCHEMA INDEX_QUALIFIER, INDEX_NAME, "
+ tableIndexOther
+ " TYPE,"
+ " SEQ_IN_INDEX ORDINAL_POSITION, COLUMN_NAME, COLLATION ASC_OR_DESC,"
+ " CARDINALITY, NULL PAGES, NULL FILTER_CONDITION"
+ " FROM INFORMATION_SCHEMA.STATISTICS"
Expand Down
122 changes: 113 additions & 9 deletions src/test/java/org/mariadb/jdbc/DatabaseMetadataTest.java
Expand Up @@ -123,6 +123,13 @@ public static void initClass() throws SQLException {
"create table cross3 (id int not null primary key, "
+ "id_ref1 int, id_ref2 int, foreign key fk_my_name (id_ref1, id_ref2) references cross2(id, id2) on "
+ "update cascade)");
stmt.execute(
"create table getBestRowIdentifier1(i int not null primary key auto_increment, id int, "
+ "id_ref1 int, id_ref2 int, foreign key fk_my_name_1 (id_ref1, id_ref2) references cross2(id, id2) on "
+ "update cascade, UNIQUE getBestRowIdentifier_unik (id))");
stmt.execute(
"create table getBestRowIdentifier2(id_ref0 int not null, "
+ "id_ref1 int, id_ref2 int not null, UNIQUE (id_ref1, id_ref2) , UNIQUE (id_ref0, id_ref2))");
}

/**
Expand All @@ -133,6 +140,8 @@ public static void initClass() throws SQLException {
@AfterClass
public static void afterClass() throws SQLException {
Statement stmt = sharedConnection.createStatement();
stmt.execute("drop table if exists getBestRowIdentifier1");
stmt.execute("drop table if exists getBestRowIdentifier2");
stmt.execute("drop table if exists cross3");
stmt.execute("drop table if exists cross2");
stmt.execute("drop table if exists cross1");
Expand Down Expand Up @@ -370,7 +379,7 @@ public void exportedKeysTest() throws SQLException {
assertEquals("cross2", rs.getString("FKTABLE_NAME"));
assertEquals("id_ref0", rs.getString("FKCOLUMN_NAME"));
assertEquals(1, rs.getInt("KEY_SEQ"));
if (!isMariadbServer() && minVersion(8,0)) {
if (!isMariadbServer() && minVersion(8, 0)) {
assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getInt("UPDATE_RULE"));
assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getInt("DELETE_RULE"));
} else {
Expand All @@ -392,7 +401,7 @@ public void exportedKeysTest() throws SQLException {
assertEquals("id_ref1", rs.getString("FKCOLUMN_NAME"));
assertEquals(1, rs.getInt("KEY_SEQ"));
assertEquals(DatabaseMetaData.importedKeyCascade, rs.getInt("UPDATE_RULE"));
if (!isMariadbServer() && minVersion(8,0)) {
if (!isMariadbServer() && minVersion(8, 0)) {
assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getInt("DELETE_RULE"));
} else {
assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("DELETE_RULE"));
Expand All @@ -416,7 +425,7 @@ public void exportedKeysTest() throws SQLException {
assertEquals("id_ref2", rs.getString("FKCOLUMN_NAME"));
assertEquals(2, rs.getInt("KEY_SEQ"));
assertEquals(DatabaseMetaData.importedKeyCascade, rs.getInt("UPDATE_RULE"));
if (!isMariadbServer() && minVersion(8,0)) {
if (!isMariadbServer() && minVersion(8, 0)) {
assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getInt("DELETE_RULE"));
} else {
assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("DELETE_RULE"));
Expand All @@ -428,8 +437,6 @@ public void exportedKeysTest() throws SQLException {
assertEquals("fk_my_name", rs.getString("FK_NAME"));
}
assertEquals("unik_name", rs.getString("PK_NAME"));

assertFalse(rs.next());
}

@Test
Expand Down Expand Up @@ -848,12 +855,103 @@ public void identifierCaseSensitivity() throws Exception {
}

@Test
public void getBestRowIdentifierBasic() throws SQLException {
public void getBestRowIdentifier() throws SQLException {
testResultSetColumns(
sharedConnection.getMetaData().getBestRowIdentifier(null, null, "", 0, true),
"SCOPE short,COLUMN_NAME String,DATA_TYPE int, TYPE_NAME String,"
+ "COLUMN_SIZE int,BUFFER_LENGTH int,"
+ "DECIMAL_DIGITS short,PSEUDO_COLUMN short");

ResultSet rs =
sharedConnection.getMetaData().getBestRowIdentifier(null, null, "cross1", 0, true);
assertTrue(rs.next());

assertEquals(DatabaseMetaData.bestRowSession, rs.getInt(1));
assertEquals("id", rs.getString(2));
assertEquals(Types.INTEGER, rs.getInt(3));
assertEquals("int", rs.getString(4));
assertEquals(10, rs.getInt(5));
assertEquals(0, rs.getInt(6));
assertEquals(0, rs.getInt(7));
assertEquals(DatabaseMetaData.bestRowNotPseudo, rs.getInt(8));
assertFalse(rs.next());

rs = sharedConnection.getMetaData().getBestRowIdentifier(null, null, "cross2", 0, true);
assertTrue(rs.next());
assertEquals(DatabaseMetaData.bestRowSession, rs.getInt(1));
assertEquals("id", rs.getString(2));
assertEquals(Types.INTEGER, rs.getInt(3));
assertEquals("int", rs.getString(4));
assertEquals(10, rs.getInt(5));
assertEquals(0, rs.getInt(6));
assertEquals(0, rs.getInt(7));
assertEquals(DatabaseMetaData.bestRowNotPseudo, rs.getInt(8));
assertTrue(rs.next());
assertEquals(DatabaseMetaData.bestRowSession, rs.getInt(1));
assertEquals("id2", rs.getString(2));
assertEquals(Types.INTEGER, rs.getInt(3));
assertEquals("int", rs.getString(4));
assertEquals(10, rs.getInt(5));
assertEquals(0, rs.getInt(6));
assertEquals(0, rs.getInt(7));
assertEquals(DatabaseMetaData.bestRowNotPseudo, rs.getInt(8));
assertFalse(rs.next());

rs = sharedConnection.getMetaData().getBestRowIdentifier(null, null, "cross3", 0, true);
assertTrue(rs.next());

assertEquals(DatabaseMetaData.bestRowSession, rs.getInt(1));
assertEquals("id", rs.getString(2));
assertEquals(Types.INTEGER, rs.getInt(3));
assertEquals("int", rs.getString(4));
assertEquals(10, rs.getInt(5));
assertEquals(0, rs.getInt(6));
assertEquals(0, rs.getInt(7));
assertEquals(DatabaseMetaData.bestRowNotPseudo, rs.getInt(8));
assertFalse(rs.next());

// CHECK using PRI even if exist UNI

rs =
sharedConnection
.getMetaData()
.getBestRowIdentifier(null, null, "getBestRowIdentifier1", 0, true);
assertTrue(rs.next());

assertEquals(DatabaseMetaData.bestRowSession, rs.getInt(1));
assertEquals("i", rs.getString(2));
assertEquals(Types.INTEGER, rs.getInt(3));
assertEquals("int", rs.getString(4));
assertEquals(10, rs.getInt(5));
assertEquals(0, rs.getInt(6));
assertEquals(0, rs.getInt(7));
assertEquals(DatabaseMetaData.bestRowNotPseudo, rs.getInt(8));
assertFalse(rs.next());

rs =
sharedConnection
.getMetaData()
.getBestRowIdentifier(null, null, "getBestRowIdentifier2", 0, true);
assertTrue(rs.next());
assertEquals(DatabaseMetaData.bestRowSession, rs.getInt(1));
assertEquals("id_ref0", rs.getString(2));
assertEquals(Types.INTEGER, rs.getInt(3));
assertEquals("int", rs.getString(4));
assertEquals(10, rs.getInt(5));
assertEquals(0, rs.getInt(6));
assertEquals(0, rs.getInt(7));
assertEquals(DatabaseMetaData.bestRowNotPseudo, rs.getInt(8));
assertTrue(rs.next());

assertEquals(DatabaseMetaData.bestRowSession, rs.getInt(1));
assertEquals("id_ref2", rs.getString(2));
assertEquals(Types.INTEGER, rs.getInt(3));
assertEquals("int", rs.getString(4));
assertEquals(10, rs.getInt(5));
assertEquals(0, rs.getInt(6));
assertEquals(0, rs.getInt(7));
assertEquals(DatabaseMetaData.bestRowNotPseudo, rs.getInt(8));
assertFalse(rs.next());
}

@Test
Expand Down Expand Up @@ -1016,7 +1114,7 @@ public void getCrossReferenceResults() throws SQLException {
assertEquals("cross2", rs.getString(7));
assertEquals("id_ref0", rs.getString(8));
assertEquals(1, rs.getInt(9));
if (!isMariadbServer() && minVersion(8,0)) {
if (!isMariadbServer() && minVersion(8, 0)) {
assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getInt("UPDATE_RULE"));
assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getInt("DELETE_RULE"));
} else {
Expand All @@ -1036,7 +1134,7 @@ public void getCrossReferenceResults() throws SQLException {
assertEquals("id_ref1", rs.getString(8));
assertEquals(1, rs.getInt(9));
assertEquals(DatabaseMetaData.importedKeyCascade, rs.getInt(10));
if (!isMariadbServer() && minVersion(8,0)) {
if (!isMariadbServer() && minVersion(8, 0)) {
assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getInt("DELETE_RULE"));
} else {
assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("DELETE_RULE"));
Expand All @@ -1059,7 +1157,7 @@ public void getCrossReferenceResults() throws SQLException {
assertEquals("id_ref2", rs.getString(8));
assertEquals(2, rs.getInt(9));
assertEquals(DatabaseMetaData.importedKeyCascade, rs.getInt(10));
if (!isMariadbServer() && minVersion(8,0)) {
if (!isMariadbServer() && minVersion(8, 0)) {
assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getInt("DELETE_RULE"));
} else {
assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("DELETE_RULE"));
Expand Down Expand Up @@ -1494,4 +1592,10 @@ public void metaTimeProcedureResultSet() throws SQLException {

assertFalse(rs.next());
}

@Test
public void various() throws SQLException {
DatabaseMetaData meta = sharedConnection.getMetaData();
assertEquals(64, meta.getMaxProcedureNameLength());
}
}

0 comments on commit f3055c7

Please sign in to comment.