Skip to content

Commit

Permalink
[CONJ-401] metadata regression with MySQL 5.5 for timestamp precision…
Browse files Browse the repository at this point in the history
… + MySQL 5.5 add to travis
  • Loading branch information
rusher committed Dec 20, 2016
1 parent 4e78ea5 commit 0445d70
Show file tree
Hide file tree
Showing 11 changed files with 198 additions and 101 deletions.
9 changes: 1 addition & 8 deletions .travis.yml
Expand Up @@ -11,11 +11,7 @@ jdk:
env:
- AURORA=true
- MARIA=5.5 PACKET=8M
- MARIA=5.5 PACKET=20M
- MARIA=5.5 PACKET=40M
- MARIA=10.0 PACKET=8M
- MARIA=10.0 PACKET=20M
- MARIA=10.0 PACKET=40M
- MARIA=10.1 PACKET=8M
- MARIA=10.1 PACKET=20M
- MARIA=10.1 PACKET=40M
Expand All @@ -32,9 +28,6 @@ env:
- TYPE=NO_BULK_SERVER MARIA=10.2 PACKET=40M
- COMPRESSION=false MARIA=10.2 PACKET=40M
- MYSQL=5.7 PACKET=8M
- MYSQL=5.7 PACKET=20M
- MYSQL=5.7 PACKET=40M
- MYSQL=5.6 PACKET=8M
- MYSQL=5.6 PACKET=20M
- MYSQL=5.6 PACKET=40M
- MYSQL=5.5 PACKET=8M
script: .travis/script.sh
163 changes: 90 additions & 73 deletions src/main/java/org/mariadb/jdbc/MariaDbDatabaseMetaData.java
Expand Up @@ -69,6 +69,7 @@ public class MariaDbDatabaseMetaData implements DatabaseMetaData {
private MariaDbConnection connection;
private String databaseProductName = "MySQL";
private String username;
private boolean datePrecisionColumnExist = true;

/**
* Constructor.
Expand Down Expand Up @@ -614,35 +615,42 @@ public ResultSet getTables(String catalog, String schemaPattern, String tableNam
*/
public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)
throws SQLException {
String sql = "SELECT TABLE_SCHEMA TABLE_CAT, NULL TABLE_SCHEM, TABLE_NAME, COLUMN_NAME,"
+ dataTypeClause("COLUMN_TYPE") + " DATA_TYPE,"
+ columnTypeClause("COLUMN_TYPE") + " TYPE_NAME, "
+ " CASE DATA_TYPE"
+ " WHEN 'time' THEN " + (datePrecisionColumnExist ? "IF(DATETIME_PRECISION = 0, 10, CAST(11 + DATETIME_PRECISION as signed integer))" : "10")
+ " WHEN 'date' THEN 10"
+ " WHEN 'datetime' THEN " + (datePrecisionColumnExist ? "IF(DATETIME_PRECISION = 0, 19, CAST(20 + DATETIME_PRECISION as signed integer))" : "19")
+ " WHEN 'timestamp' THEN " + (datePrecisionColumnExist ? "IF(DATETIME_PRECISION = 0, 19, CAST(20 + DATETIME_PRECISION as signed integer))" : "19")
+ " ELSE "
+ " IF(NUMERIC_PRECISION IS NULL, LEAST(CHARACTER_MAXIMUM_LENGTH," + Integer.MAX_VALUE + "), NUMERIC_PRECISION) "
+ " END"
+ " COLUMN_SIZE, 65535 BUFFER_LENGTH, NUMERIC_SCALE DECIMAL_DIGITS,"
+ " 10 NUM_PREC_RADIX, IF(IS_NULLABLE = 'yes',1,0) NULLABLE,COLUMN_COMMENT REMARKS,"
+ " COLUMN_DEFAULT COLUMN_DEF, 0 SQL_DATA_TYPE, 0 SQL_DATETIME_SUB, "
+ " LEAST(CHARACTER_OCTET_LENGTH," + Integer.MAX_VALUE + ") CHAR_OCTET_LENGTH,"
+ " ORDINAL_POSITION, IS_NULLABLE, NULL SCOPE_CATALOG, NULL SCOPE_SCHEMA, NULL SCOPE_TABLE, NULL SOURCE_DATA_TYPE,"
+ " IF(EXTRA = 'auto_increment','YES','NO') IS_AUTOINCREMENT, "
+ " IF(EXTRA in ('VIRTUAL', 'PERSISTENT', 'VIRTUAL GENERATED', 'STORED GENERATED') ,'YES','NO') IS_GENERATEDCOLUMN "
+ " FROM INFORMATION_SCHEMA.COLUMNS WHERE "
+ catalogCond("TABLE_SCHEMA", catalog)
+ " AND "
+ patternCond("TABLE_NAME", tableNamePattern)
+ " AND "
+ patternCond("COLUMN_NAME", columnNamePattern)
+ " ORDER BY TABLE_CAT, TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION";

String sql =
"SELECT TABLE_SCHEMA TABLE_CAT, NULL TABLE_SCHEM, TABLE_NAME, COLUMN_NAME,"
+ dataTypeClause("COLUMN_TYPE") + " DATA_TYPE,"
+ columnTypeClause("COLUMN_TYPE") + " TYPE_NAME, "
+ " CASE DATA_TYPE"
+ " WHEN 'time' THEN IF(DATETIME_PRECISION = 0, 10, CAST(11 + DATETIME_PRECISION as signed integer))"
+ " WHEN 'date' THEN 10"
+ " WHEN 'datetime' THEN IF(DATETIME_PRECISION = 0, 19, CAST(20 + DATETIME_PRECISION as signed integer))"
+ " WHEN 'timestamp' THEN IF(DATETIME_PRECISION = 0, 19, CAST(20 + DATETIME_PRECISION as signed integer))"
+ " ELSE "
+ " IF(NUMERIC_PRECISION IS NULL, LEAST(CHARACTER_MAXIMUM_LENGTH," + Integer.MAX_VALUE + "), NUMERIC_PRECISION) "
+ " END"
+ " COLUMN_SIZE, 65535 BUFFER_LENGTH, NUMERIC_SCALE DECIMAL_DIGITS,"
+ " 10 NUM_PREC_RADIX, IF(IS_NULLABLE = 'yes',1,0) NULLABLE,COLUMN_COMMENT REMARKS,"
+ " COLUMN_DEFAULT COLUMN_DEF, 0 SQL_DATA_TYPE, 0 SQL_DATETIME_SUB, "
+ " LEAST(CHARACTER_OCTET_LENGTH," + Integer.MAX_VALUE + ") CHAR_OCTET_LENGTH,"
+ " ORDINAL_POSITION, IS_NULLABLE, NULL SCOPE_CATALOG, NULL SCOPE_SCHEMA, NULL SCOPE_TABLE, NULL SOURCE_DATA_TYPE,"
+ " IF(EXTRA = 'auto_increment','YES','NO') IS_AUTOINCREMENT, "
+ " IF(EXTRA in ('VIRTUAL', 'PERSISTENT', 'VIRTUAL GENERATED', 'STORED GENERATED') ,'YES','NO') IS_GENERATEDCOLUMN "
+ " FROM INFORMATION_SCHEMA.COLUMNS WHERE "
+ catalogCond("TABLE_SCHEMA", catalog)
+ " AND "
+ patternCond("TABLE_NAME", tableNamePattern)
+ " AND "
+ patternCond("COLUMN_NAME", columnNamePattern)
+ " ORDER BY TABLE_CAT, TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION";
try {
return executeQuery(sql);
} catch (SQLException sqlException) {
if (sqlException.getMessage().contains("Unknown column 'DATETIME_PRECISION'")) {
datePrecisionColumnExist = false;
return getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern);
}
throw sqlException;
}

return executeQuery(sql);
}

/**
Expand Down Expand Up @@ -1619,51 +1627,51 @@ public ResultSet getProcedureColumns(String catalog, String schemaPattern, Strin
/*
* Get info from information_schema.parameters
*/
sql =
"SELECT SPECIFIC_SCHEMA PROCEDURE_CAT, NULL PROCEDURE_SCHEM, SPECIFIC_NAME PROCEDURE_NAME,"
+ " PARAMETER_NAME COLUMN_NAME, "
+ " CASE PARAMETER_MODE "
+ " WHEN 'IN' THEN " + procedureColumnIn
+ " WHEN 'OUT' THEN " + procedureColumnOut
+ " WHEN 'INOUT' THEN " + procedureColumnInOut
+ " ELSE IF(PARAMETER_MODE IS NULL," + procedureColumnReturn + "," + procedureColumnUnknown + ")"
+ " END COLUMN_TYPE,"
+ dataTypeClause("DTD_IDENTIFIER") + " DATA_TYPE,"
+ "DATA_TYPE TYPE_NAME,"
+ " CASE DATA_TYPE"
+ " WHEN 'time' THEN IF(DATETIME_PRECISION = 0, 10, CAST(11 + DATETIME_PRECISION as signed integer))"
+ " WHEN 'date' THEN 10"
+ " WHEN 'datetime' THEN IF(DATETIME_PRECISION = 0, 19, CAST(20 + DATETIME_PRECISION as signed integer))"
+ " WHEN 'timestamp' THEN IF(DATETIME_PRECISION = 0, 19, CAST(20 + DATETIME_PRECISION as signed integer))"
+ " ELSE "
+ " IF(NUMERIC_PRECISION IS NULL, LEAST(CHARACTER_MAXIMUM_LENGTH," + Integer.MAX_VALUE + "), NUMERIC_PRECISION) "
+ " END `PRECISION`,"

+ " CASE DATA_TYPE"
+ " WHEN 'time' THEN IF(DATETIME_PRECISION = 0, 10, CAST(11 + DATETIME_PRECISION as signed integer))"
+ " WHEN 'date' THEN 10"
+ " WHEN 'datetime' THEN IF(DATETIME_PRECISION = 0, 19, CAST(20 + DATETIME_PRECISION as signed integer))"
+ " WHEN 'timestamp' THEN IF(DATETIME_PRECISION = 0, 19, CAST(20 + DATETIME_PRECISION as signed integer))"
+ " ELSE "
+ " IF(NUMERIC_PRECISION IS NULL, LEAST(CHARACTER_MAXIMUM_LENGTH," + Integer.MAX_VALUE + "), NUMERIC_PRECISION) "
+ " END `LENGTH`,"

+ " CASE DATA_TYPE"
+ " WHEN 'time' THEN CAST(DATETIME_PRECISION as signed integer)"
+ " WHEN 'datetime' THEN CAST(DATETIME_PRECISION as signed integer)"
+ " WHEN 'timestamp' THEN CAST(DATETIME_PRECISION as signed integer)"
+ " ELSE NUMERIC_SCALE "
+ " END `SCALE`,"
+ "10 RADIX,"
+ procedureNullableUnknown + " NULLABLE,NULL REMARKS,NULL COLUMN_DEF,0 SQL_DATA_TYPE,0 SQL_DATETIME_SUB,"
+ "CHARACTER_OCTET_LENGTH CHAR_OCTET_LENGTH ,ORDINAL_POSITION, '' IS_NULLABLE, SPECIFIC_NAME "
+ " FROM INFORMATION_SCHEMA.PARAMETERS "
+ " WHERE "
+ catalogCond("SPECIFIC_SCHEMA", catalog)
+ " AND " + patternCond("SPECIFIC_NAME", procedureNamePattern)
+ " AND " + patternCond("PARAMETER_NAME", columnNamePattern)
+ " /* AND ROUTINE_TYPE='PROCEDURE' */ "
+ " ORDER BY SPECIFIC_SCHEMA, SPECIFIC_NAME, ORDINAL_POSITION";
sql = "SELECT SPECIFIC_SCHEMA PROCEDURE_CAT, NULL PROCEDURE_SCHEM, SPECIFIC_NAME PROCEDURE_NAME,"
+ " PARAMETER_NAME COLUMN_NAME, "
+ " CASE PARAMETER_MODE "
+ " WHEN 'IN' THEN " + procedureColumnIn
+ " WHEN 'OUT' THEN " + procedureColumnOut
+ " WHEN 'INOUT' THEN " + procedureColumnInOut
+ " ELSE IF(PARAMETER_MODE IS NULL," + procedureColumnReturn + "," + procedureColumnUnknown + ")"
+ " END COLUMN_TYPE,"
+ dataTypeClause("DTD_IDENTIFIER") + " DATA_TYPE,"
+ "DATA_TYPE TYPE_NAME,"
+ " CASE DATA_TYPE"
+ " WHEN 'time' THEN " + (datePrecisionColumnExist ? "IF(DATETIME_PRECISION = 0, 10, CAST(11 + DATETIME_PRECISION as signed integer))" : "10")
+ " WHEN 'date' THEN 10"
+ " WHEN 'datetime' THEN " + (datePrecisionColumnExist ? "IF(DATETIME_PRECISION = 0, 19, CAST(20 + DATETIME_PRECISION as signed integer))" : "19")
+ " WHEN 'timestamp' THEN " + (datePrecisionColumnExist ? "IF(DATETIME_PRECISION = 0, 19, CAST(20 + DATETIME_PRECISION as signed integer))" : "19")
+ " ELSE "
+ " IF(NUMERIC_PRECISION IS NULL, LEAST(CHARACTER_MAXIMUM_LENGTH," + Integer.MAX_VALUE + "), NUMERIC_PRECISION) "
+ " END `PRECISION`,"

+ " CASE DATA_TYPE"
+ " WHEN 'time' THEN " + (datePrecisionColumnExist ? "IF(DATETIME_PRECISION = 0, 10, CAST(11 + DATETIME_PRECISION as signed integer))" : "10")
+ " WHEN 'date' THEN 10"
+ " WHEN 'datetime' THEN " + (datePrecisionColumnExist ? "IF(DATETIME_PRECISION = 0, 19, CAST(20 + DATETIME_PRECISION as signed integer))" : "19")
+ " WHEN 'timestamp' THEN " + (datePrecisionColumnExist ? "IF(DATETIME_PRECISION = 0, 19, CAST(20 + DATETIME_PRECISION as signed integer))" : "19")
+ " ELSE "
+ " IF(NUMERIC_PRECISION IS NULL, LEAST(CHARACTER_MAXIMUM_LENGTH," + Integer.MAX_VALUE + "), NUMERIC_PRECISION) "
+ " END `LENGTH`,"

+ (datePrecisionColumnExist ? " CASE DATA_TYPE"
+ " WHEN 'time' THEN CAST(DATETIME_PRECISION as signed integer)"
+ " WHEN 'datetime' THEN CAST(DATETIME_PRECISION as signed integer)"
+ " WHEN 'timestamp' THEN CAST(DATETIME_PRECISION as signed integer)"
+ " ELSE NUMERIC_SCALE "
+ " END `SCALE`," : " NUMERIC_SCALE `SCALE`,")

+ "10 RADIX,"
+ procedureNullableUnknown + " NULLABLE,NULL REMARKS,NULL COLUMN_DEF,0 SQL_DATA_TYPE,0 SQL_DATETIME_SUB,"
+ "CHARACTER_OCTET_LENGTH CHAR_OCTET_LENGTH ,ORDINAL_POSITION, '' IS_NULLABLE, SPECIFIC_NAME "
+ " FROM INFORMATION_SCHEMA.PARAMETERS "
+ " WHERE "
+ catalogCond("SPECIFIC_SCHEMA", catalog)
+ " AND " + patternCond("SPECIFIC_NAME", procedureNamePattern)
+ " AND " + patternCond("PARAMETER_NAME", columnNamePattern)
+ " /* AND ROUTINE_TYPE='PROCEDURE' */ "
+ " ORDER BY SPECIFIC_SCHEMA, SPECIFIC_NAME, ORDINAL_POSITION";
} else {

/* No information_schema.parameters
Expand All @@ -1678,7 +1686,16 @@ public ResultSet getProcedureColumns(String catalog, String schemaPattern, Strin
+ " FROM DUAL "
+ " WHERE 1=0 ";
}
return executeQuery(sql);

try {
return executeQuery(sql);
} catch (SQLException sqlException) {
if (sqlException.getMessage().contains("Unknown column 'DATETIME_PRECISION'")) {
datePrecisionColumnExist = false;
return getProcedureColumns(catalog, schemaPattern, procedureNamePattern, columnNamePattern);
}
throw sqlException;
}
}

/**
Expand Down
7 changes: 6 additions & 1 deletion src/test/java/org/mariadb/jdbc/BaseTest.java
Expand Up @@ -44,6 +44,7 @@ public class BaseTest {
private static TcpProxy proxy = null;
private static UrlParser urlParser;
protected static boolean runLongTest = false;
protected static boolean doPrecisionTest = true;

@Rule
public TestRule watcher = new TestWatcher() {
Expand Down Expand Up @@ -149,6 +150,7 @@ public static void beforeClassBaseTest() throws SQLException {
String url = System.getProperty("dbUrl", mDefUrl);
runLongTest = Boolean.getBoolean(System.getProperty("runLongTest", "false"));
testSingleHost = Boolean.parseBoolean(System.getProperty("testSingleHost", "true"));

if (testSingleHost) {
urlParser = UrlParser.parse(url);
if (urlParser.getHostAddresses().size() > 0) {
Expand Down Expand Up @@ -191,6 +193,9 @@ public static void beforeClassBaseTest() throws SQLException {
setUri();

sharedConnection = DriverManager.getConnection(url);

String dbVersion = sharedConnection.getMetaData().getDatabaseProductVersion();
doPrecisionTest = isMariadbServer() || !dbVersion.startsWith("5.5"); //MySQL 5.5 doesn't support precision
}
}

Expand Down Expand Up @@ -648,7 +653,7 @@ void requireMinimumVersion(int major, int minor) throws SQLException {
* @return true if DB is mariadb
* @throws SQLException exception
*/
boolean isMariadbServer() throws SQLException {
static boolean isMariadbServer() throws SQLException {
DatabaseMetaData md = sharedConnection.getMetaData();
return md.getDatabaseProductVersion().indexOf("MariaDB") != -1;
}
Expand Down
23 changes: 17 additions & 6 deletions src/test/java/org/mariadb/jdbc/ConnectionTest.java
Expand Up @@ -37,12 +37,23 @@ public void testAccessDeniedErrorCode() throws SQLException {
DriverManager.getConnection("jdbc:mysql://" + ((hostname != null) ? hostname : "localhost") + ":" + port + "/" + database + "?user=foo");
Assert.fail();
} catch (SQLException e) {
if (1524 == e.getErrorCode()) {
//GSSAPI plugin not loaded
Assert.assertTrue("HY000".equals(e.getSQLState()));
} else {
Assert.assertTrue("28000".equals(e.getSQLState()));
Assert.assertEquals(1045, e.getErrorCode());
switch (e.getErrorCode()) {
case (1524) :
//GSSAPI plugin not loaded
Assert.assertTrue("HY000".equals(e.getSQLState()));
break;

case (1045) :
Assert.assertTrue("28000".equals(e.getSQLState()));
break;

case (1044) :
//mysql
Assert.assertTrue("42000".equals(e.getSQLState()));
break;

default:
fail("Wrong error code : " + e.getErrorCode());
}
}
}
Expand Down
47 changes: 47 additions & 0 deletions src/test/java/org/mariadb/jdbc/DatabaseMetadataTest.java
Expand Up @@ -975,6 +975,7 @@ public void getPrecision() throws SQLException {

@Test
public void getTimePrecision() throws SQLException {
Assume.assumeTrue(doPrecisionTest);
createTable("getTimePrecision", "d date, "
+ "t1 datetime(0),"
+ "t2 datetime(6),"
Expand Down Expand Up @@ -1011,6 +1012,7 @@ public void getTimePrecision() throws SQLException {

@Test
public void metaTimeResultSet() throws SQLException {
Assume.assumeTrue(doPrecisionTest);
createTable("getTimePrecision", "d date, "
+ "t1 datetime(0),"
+ "t2 datetime(6),"
Expand Down Expand Up @@ -1048,12 +1050,57 @@ public void metaTimeResultSet() throws SQLException {
assertFalse(rs.next());
}


/**
* CONJ-401 - getProcedureColumns precision when server doesn't support precision
* @throws SQLException if connection error occur
*/
@Test
public void metaTimeNoPrecisionProcedureResultSet() throws SQLException {
createProcedure("getProcTimePrecision2", "(IN I date, "
+ "IN t1 DATETIME,"
+ "IN t3 timestamp,"
+ "IN t5 time) BEGIN SELECT I; END");

final int precisionField = 8;
final int lengthField = 9;
final int scaleField = 10;

DatabaseMetaData dmd = sharedConnection.getMetaData();
ResultSet rs = dmd.getProcedureColumns(null, null, "getProcTimePrecision2", null);
//date
assertTrue(rs.next());
assertEquals(10, rs.getInt(precisionField));
assertEquals(10, rs.getInt(lengthField));
assertEquals(0, rs.getInt(scaleField));
assertTrue(rs.wasNull());
//datetime(0)
assertTrue(rs.next());
assertEquals(19, rs.getInt(precisionField));
assertEquals(19, rs.getInt(lengthField));
assertEquals(0, rs.getInt(scaleField));
//timestamp(0)
assertTrue(rs.next());
assertEquals(19, rs.getInt(precisionField));
assertEquals(19, rs.getInt(lengthField));
assertEquals(0, rs.getInt(scaleField));
//time(0)
assertTrue(rs.next());
assertEquals(10, rs.getInt(precisionField));
assertEquals(10, rs.getInt(lengthField));
assertEquals(0, rs.getInt(scaleField));

assertFalse(rs.next());
}


/**
* CONJ-381 - getProcedureColumns returns NULL as TIMESTAMP/DATETIME precision instead of 19.
* @throws SQLException if connection error occur
*/
@Test
public void metaTimeProcedureResultSet() throws SQLException {
Assume.assumeTrue(doPrecisionTest);
createProcedure("getProcTimePrecision", "(IN I date, "
+ "IN t1 DATETIME(0),"
+ "IN t2 DATETIME(6),"
Expand Down

0 comments on commit 0445d70

Please sign in to comment.