Changeset: 15f11c880d5c for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=15f11c880d5c Added Files: sql/test/BugTracker-2016/Tests/RELEASE_SAVEPOINT_after_UPDATE_crash.Bug-4010.sql sql/test/BugTracker-2016/Tests/RELEASE_SAVEPOINT_after_UPDATE_crash.Bug-4010.stable.err sql/test/BugTracker-2016/Tests/RELEASE_SAVEPOINT_after_UPDATE_crash.Bug-4010.stable.out Modified Files: java/ChangeLog.Jun2016 java/src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java sql/test/BugTracker-2016/Tests/All Branch: default Log Message:
Merge with Jun2016 branch. diffs (truncated from 579 to 300 lines): diff --git a/java/ChangeLog.Jun2016 b/java/ChangeLog.Jun2016 --- a/java/ChangeLog.Jun2016 +++ b/java/ChangeLog.Jun2016 @@ -1,6 +1,12 @@ # ChangeLog file for java # This file is updated with Maddlog +* Thu May 19 2016 Martin van Dinther <martin.van.dint...@monetdbsolutions.com> +- Implemented MonetDatabaseMetaData.supportsConvert() and + MonetDatabaseMetaData.supportsConvert(int fromType, int toType) methods. + It used to always return false. Now it returns true for the supported conversions. + This fixes Bug 3460. + * Sun May 8 2016 Jennie Zhang <y.zh...@cwi.nl> - ResultSet.setFetchSize(): added a dummy implementation to get rid of the SQLFeatureNotSupportedException. In MonetDB, it does not diff --git a/java/src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java b/java/src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java --- a/java/src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java +++ b/java/src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java @@ -396,48 +396,16 @@ public class MonetDatabaseMetaData exten /** * Get a comma separated list of all a database's SQL keywords that * are NOT also SQL:2003 keywords. - * * * @return a comma separated list of MonetDB keywords */ @Override public String getSQLKeywords() { - StringBuilder sb = new StringBuilder(1000); - Statement st = null; - ResultSet rs = null; - try { - st = con.createStatement(); - rs = st.executeQuery("SELECT \"keyword\" FROM \"sys\".\"keywords\" ORDER BY 1"); - // Fetch the keywords and concatenate them into a StringBuffer separated by comma's - boolean isfirst = true; - while (rs.next()) { - String keyword = rs.getString(1); - if (keyword != null) { - if (isfirst) { - isfirst = false; - } else { - sb.append(","); - } - sb.append(keyword); - } - } - } catch (SQLException e) { - /* This may occur for old (before Jul2015 release) MonetDB servers which do not have the sys.keywords table. */ - } finally { - if (rs != null) { - try { - rs.close(); - } catch (SQLException e) { /* ignore */ } - } - if (st != null) { - try { - st.close(); - } catch (SQLException e) { /* ignore */ } - } - } - - return (sb.length() > 0) ? sb.toString() : - /* else fallback and return old static list (as returned in clients/odbc/driver/SQLGetInfo.c case SQL_KEYWORDS:) */ + String keywords = getConcatenatedStringFromQuery("SELECT \"keyword\" FROM \"sys\".\"keywords\" ORDER BY 1"); + + /* An old MonetDB server (pre Jul2015 release) will not have a table sys.keywords and return an empty String */ + return (keywords.length() > 0) ? keywords : + /* for old servers return static list (as returned in clients/odbc/driver/SQLGetInfo.c case SQL_KEYWORDS:) */ "ADMIN,AFTER,AGGREGATE,ALWAYS,ASYMMETRIC,ATOMIC," + "AUTO_INCREMENT,BEFORE,BIGINT,BIGSERIAL,BINARY,BLOB," + "CALL,CHAIN,CLOB,COMMITTED,COPY,CORR,CUME_DIST," + @@ -460,68 +428,32 @@ public class MonetDatabaseMetaData exten } /** - * getMonetDBSysFunctions(int kind) - * args: int kind, value must be 1 or 2 or 3 or 4. - * internal utility method to query the MonetDB sys.functions table - * to dynamically get the function names (for a specific kind) and - * concatenate the function names into a comma separated list. + * Internal utility method getConcatenatedStringFromQuery(String query) + * args: query: SQL SELECT query. Only the output of the first column is concatenated. + * @return a String of query result values concatenated into one string, and values separated by comma's */ - private String getMonetDBSysFunctions(int kind) { - // where clause part (for num/str/timedate to match only functions whose 1 arg exists and is of a certain type - String part1 = "WHERE \"id\" IN (SELECT \"func_id\" FROM \"sys\".\"args\" WHERE \"number\" = 1 AND \"name\" = 'arg_1' AND \"type\" IN "; - String whereClause = ""; - switch (kind) { - case 1: /* numeric functions */ - whereClause = part1 + - "('tinyint', 'smallint', 'int', 'bigint', 'decimal', 'real', 'double') )" + - // exclude 2 functions which take an int as arg but returns a char or str - " AND \"name\" NOT IN ('code', 'space')"; - break; - case 2: /* string functions */ - whereClause = part1 + - "('char', 'varchar', 'clob') )" + - // include 2 functions which take an int as arg but returns a char or str - " OR \"name\" IN ('code', 'space')"; - break; - case 3: /* system functions */ - whereClause = "WHERE \"id\" NOT IN (SELECT \"func_id\" FROM \"sys\".\"args\" WHERE \"number\" = 1)" + - " AND \"func\" NOT LIKE '%function%(% %)%'" + - " AND \"func\" NOT LIKE '%procedure%(% %)%'" + - " AND \"func\" NOT LIKE '%CREATE FUNCTION%RETURNS TABLE(% %)%'" + - // the next names are also not usable so exclude them - " AND \"name\" NOT LIKE 'querylog_%'" + - " AND \"name\" NOT IN ('analyze', 'count', 'count_no_nil', 'initializedictionary', 'times')"; - break; - case 4: /* time date functions */ - whereClause = part1 + - "('date', 'time', 'timestamp', 'timetz', 'timestamptz', 'sec_interval', 'month_interval') )"; - break; - default: /* internal function called with an invalid kind value */ - return ""; - } - - StringBuilder sb = new StringBuilder(400); + private String getConcatenatedStringFromQuery(String query) { + StringBuilder sb = new StringBuilder(1024); Statement st = null; ResultSet rs = null; try { - String select = "SELECT DISTINCT \"name\" FROM \"sys\".\"functions\" " + whereClause + " ORDER BY 1"; st = con.createStatement(); - rs = st.executeQuery(select); - // Fetch the function names and concatenate them into a StringBuffer separated by comma's + rs = st.executeQuery(query); + // Fetch the first column output and concatenate the values into a StringBuffer separated by comma's boolean isfirst = true; while (rs.next()) { - String name = rs.getString(1); - if (name != null) { + String value = rs.getString(1); + if (value != null) { if (isfirst) { isfirst = false; } else { - sb.append(","); + sb.append(','); } - sb.append(name); + sb.append(value); } } } catch (SQLException e) { - // ignore + /* ignore */ } finally { if (rs != null) { try { @@ -534,28 +466,50 @@ public class MonetDatabaseMetaData exten } catch (SQLException e) { /* ignore */ } } } - + // for debug: System.out.println("SQL query: " + query + "\nResult string: " + sb.toString()); return sb.toString(); } + // SQL query parts shared in below four getXxxxFunctions() methods + private final static String FunctionsSelect = "SELECT DISTINCT \"name\" FROM \"sys\".\"functions\" "; + private final static String FunctionsWhere = "WHERE \"id\" IN (SELECT \"func_id\" FROM \"sys\".\"args\" WHERE \"number\" = 1 AND \"name\" = 'arg_1' AND \"type\" IN "; + @Override public String getNumericFunctions() { - return getMonetDBSysFunctions(1); + String match = + "('tinyint', 'smallint', 'int', 'bigint', 'hugeint', 'decimal', 'double', 'real') )" + + // exclude functions which belong to the 'str' module + " AND \"mod\" <> 'str'"; + return getConcatenatedStringFromQuery(FunctionsSelect + FunctionsWhere + match + " ORDER BY 1"); } @Override public String getStringFunctions() { - return getMonetDBSysFunctions(2); + String match = + "('char', 'varchar', 'clob', 'json') )" + + // include functions which belong to the 'str' module + " OR \"mod\" = 'str'"; + return getConcatenatedStringFromQuery(FunctionsSelect + FunctionsWhere + match + " ORDER BY 1"); } @Override public String getSystemFunctions() { - return getMonetDBSysFunctions(3); + String wherePart = + "WHERE \"id\" NOT IN (SELECT \"func_id\" FROM \"sys\".\"args\" WHERE \"number\" = 1)" + + " AND \"func\" NOT LIKE '%function%(% %)%'" + + " AND \"func\" NOT LIKE '%procedure%(% %)%'" + + " AND \"func\" NOT LIKE '%CREATE FUNCTION%RETURNS TABLE(% %)%'" + + // the next names are also not usable so exclude them + " AND \"name\" NOT LIKE 'querylog_%'" + + " AND \"name\" NOT IN ('analyze', 'count', 'count_no_nil', 'initializedictionary', 'times')"; + return getConcatenatedStringFromQuery(FunctionsSelect + wherePart + " ORDER BY 1"); } @Override public String getTimeDateFunctions() { - return getMonetDBSysFunctions(4); + String match = + "('date', 'time', 'timestamp', 'timetz', 'timestamptz', 'sec_interval', 'month_interval') )"; + return getConcatenatedStringFromQuery(FunctionsSelect + FunctionsWhere + match + " ORDER BY 1"); } /** @@ -634,13 +588,158 @@ public class MonetDatabaseMetaData exten return true; } + /** + * Retrieves whether this database supports the JDBC scalar function + * CONVERT for the conversion of one JDBC type to another. + * The JDBC types are the generic SQL data types defined in java.sql.Types. + * + * @return true if so; false otherwise + */ @Override public boolean supportsConvert() { - return false; + return true; } + /** + * Retrieves whether this database supports the JDBC scalar function + * CONVERT for conversions between the JDBC types fromType and toType. + * The JDBC types are the generic SQL data types defined in java.sql.Types. + * + * @return true if so; false otherwise + */ @Override public boolean supportsConvert(int fromType, int toType) { + switch (fromType) { + case Types.BOOLEAN: + switch (toType) { + case Types.BOOLEAN: + /* case Types.BIT: is not supported by MonetDB and will fail */ + case Types.TINYINT: + case Types.SMALLINT: + case Types.INTEGER: + case Types.BIGINT: + /* conversion to FLOAT, REAL, DOUBLE, NUMERIC and DECIMAL is not supported by MonetDB */ + case Types.CHAR: + case Types.VARCHAR: + /* case Types.LONGVARCHAR: is not supported by MonetDB and will fail */ + case Types.CLOB: + return true; + } + // conversion to all other types is not supported + return false; + /* case Types.BIT: is not supported by MonetDB and will fail */ + /* case Types.BINARY: is not supported by MonetDB and will fail */ + /* case Types.VARBINARY: is not supported by MonetDB and will fail */ + /* case Types.LONGVARBINARY: is not supported by MonetDB and will fail */ + case Types.BLOB: + switch (toType) { + /* case Types.BINARY: is not supported by MonetDB and will fail */ + /* case Types.VARBINARY: is not supported by MonetDB and will fail */ + /* case Types.LONGVARBINARY: is not supported by MonetDB and will fail */ + case Types.BLOB: + case Types.VARCHAR: + /* case Types.LONGVARCHAR: is not supported by MonetDB and will fail */ + case Types.CLOB: + return true; + } + // conversion to all other types is not supported + return false; + case Types.TINYINT: + case Types.SMALLINT: + case Types.INTEGER: + case Types.BIGINT: + case Types.FLOAT: + case Types.REAL: + case Types.DOUBLE: + case Types.NUMERIC: + case Types.DECIMAL: + switch (toType) { + case Types.BOOLEAN: + /* case Types.BIT: is not supported by MonetDB and will fail */ + case Types.TINYINT: + case Types.SMALLINT: + case Types.INTEGER: + case Types.BIGINT: + case Types.FLOAT: + case Types.REAL: + case Types.DOUBLE: + case Types.NUMERIC: + case Types.DECIMAL: + case Types.CHAR: + case Types.VARCHAR: + /* case Types.LONGVARCHAR: is not supported by MonetDB and will fail */ + case Types.CLOB: + return true; + } + // conversion to all other types is not supported + return false; _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list