Changeset: 6b097e37cf90 for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=6b097e37cf90 Modified Files: java/ChangeLog java/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java Branch: default Log Message:
Improved performance of following JDBC ResultSet and ResultSetMetaData methods: - ResultSet.getBoolean(column) - ResultSet.getBinaryStream(column) - ResultSet.getBytes(column) - ResultSet.getObject(column) - ResultSet.getObject(column, map) - ResultSet.getDate(column) - ResultSet.getTime(column) - ResultSet.getTimestamp(column) - ResultSet.getDate(column, calendar) - ResultSet.getTime(column, calendar) - ResultSet.getTimestamp(column, calendar) - ResultSetMetaData.getColumnClassName(column) - ResultSetMetaData.getColumnType(column) - ResultSetMetaData.isCaseSensitive(column) - ResultSetMetaData.isSigned(column) - ResultSetMetaData.getPrecision(column) This done by storing the mapping of the MonetDB type (string) to JDBC SQL type (int) in an int array and use it in all getXyz() methods instead of calling the (relatively expensive) utility method MonetDriver.getJavaType() again and again. The resultset column datatypes are static after creation of the resultset, hence we can safely derive them once (in the constructor) and store the JDBC SQL types in the internal array for fast internal use. diffs (229 lines): diff --git a/java/ChangeLog b/java/ChangeLog --- a/java/ChangeLog +++ b/java/ChangeLog @@ -1,6 +1,26 @@ # ChangeLog file for java # This file is updated with Maddlog +* Thu Sep 15 2016 Martin van Dinther <[email protected]> +- Improved performance of following JDBC ResultSet and ResultSetMetaData + methods: + - ResultSet.getBoolean(column) + - ResultSet.getBinaryStream(column) + - ResultSet.getBytes(column) + - ResultSet.getObject(column) + - ResultSet.getObject(column, map) + - ResultSet.getDate(column) + - ResultSet.getTime(column) + - ResultSet.getTimestamp(column) + - ResultSet.getDate(column, calendar) + - ResultSet.getTime(column, calendar) + - ResultSet.getTimestamp(column, calendar) + - ResultSetMetaData.getColumnClassName(column) + - ResultSetMetaData.getColumnType(column) + - ResultSetMetaData.isCaseSensitive(column) + - ResultSetMetaData.isSigned(column) + - ResultSetMetaData.getPrecision(column) + * Thu Sep 8 2016 Martin van Dinther <[email protected]> - Improved JdbcClient program by fixing some resource leaks. - Extended JdbcClient program by showing elapsed time information for each diff --git a/java/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java b/java/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java --- a/java/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java +++ b/java/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java @@ -83,6 +83,8 @@ public class MonetResultSet extends Mone private final String[] columns; /** The MonetDB types of the columns in this ResultSet */ private final String[] types; + /** The JDBC SQL types of the columns in this ResultSet. The content will be derived from the MonetDB types[] */ + private final int[] JdbcSQLTypes; /** The number of rows in this ResultSet */ final int tupleCount; // default for the MonetVirtualResultSet @@ -136,6 +138,9 @@ public class MonetResultSet extends Mone // create result array tlp = new TupleLineParser(columns.length); + + JdbcSQLTypes = new int[types.length]; + populateJdbcSQLtypesArray(); } /** @@ -178,8 +183,30 @@ public class MonetResultSet extends Mone this.tupleCount = results; this.tlp = new TupleLineParser(columns.length); + + JdbcSQLTypes = new int[types.length]; + populateJdbcSQLtypesArray(); } + /** + * Internal utility method to fill the JdbcSQLTypes array with derivable values. + * By doing it once (in the constructor) we can avoid doing this in many getXyz() methods again and again + * thereby improving getXyz() method performance. + */ + private void populateJdbcSQLtypesArray() { + for (int i = 0; i < types.length; i++) { + int javaSQLtype = MonetDriver.getJavaType(types[i]); + JdbcSQLTypes[i] = javaSQLtype; + if (javaSQLtype == Types.BLOB) { + try { + if (((MonetConnection)statement.getConnection()).getBlobAsBinary()) + JdbcSQLTypes[i] = Types.BINARY; + } catch (SQLException se) { /* ignore it */ } + } + } + } + + //== methods of interface ResultSet // Chapter 14.2.2 Sun JDBC 3.0 Specification @@ -382,7 +409,7 @@ public class MonetResultSet extends Mone @Override public InputStream getBinaryStream(int columnIndex) throws SQLException { try { - switch (getJavaType(types[columnIndex - 1])) { + switch (JdbcSQLTypes[columnIndex - 1]) { case Types.BLOB: Blob blob = getBlob(columnIndex); if (blob == null) @@ -745,7 +772,7 @@ public class MonetResultSet extends Mone return true; // match type specific values - switch (getJavaType(types[columnIndex - 1])) { + switch (JdbcSQLTypes[columnIndex - 1]) { case Types.BOOLEAN: case Types.CHAR: case Types.VARCHAR: @@ -865,7 +892,7 @@ public class MonetResultSet extends Mone lastReadWasNull = false; // According to Table B-6, getBytes() only operates on BINARY types - switch (getJavaType(types[columnIndex - 1])) { + switch (JdbcSQLTypes[columnIndex - 1]) { case Types.BLOB: case Types.BINARY: case Types.VARBINARY: @@ -1652,26 +1679,29 @@ public class MonetResultSet extends Mone */ @Override public String getColumnClassName(int column) throws SQLException { - final String MonetDBtype = getColumnTypeName(column); - Class<?> type = null; if (conn == null) { // first time, get a Connection object and cache it for all next columns conn = getStatement().getConnection(); } - if (conn != null) { - Map<String,Class<?>> map = conn.getTypeMap(); - if (map != null && map.containsKey(MonetDBtype)) { - type = (Class)map.get(MonetDBtype); + try { + Class<?> type = null; + if (conn != null) { + Map<String,Class<?>> map = conn.getTypeMap(); + if (map != null && map.containsKey(types[column - 1])) { + type = (Class)map.get(types[column - 1]); + } } + if (type == null) { + // fallback to the standard SQL type Class mappings + type = getClassForType(JdbcSQLTypes[column - 1]); + } + if (type != null) { + return type.getName(); + } + throw new SQLException("column type mapping null: " + types[column - 1], "M0M03"); + } catch (IndexOutOfBoundsException e) { + throw newSQLInvalidColumnIndexException(column); } - if (type == null) { - // fallback to the standard Class mappings - type = getClassForType(getJavaType(MonetDBtype)); - } - if (type != null) { - return type.getName(); - } - throw new SQLException("column type mapping null: " + MonetDBtype, "M0M03"); } /** @@ -1713,7 +1743,11 @@ public class MonetResultSet extends Mone */ @Override public int getColumnType(int column) throws SQLException { - return getJavaType(getColumnTypeName(column)); + try { + return JdbcSQLTypes[column - 1]; + } catch (IndexOutOfBoundsException e) { + throw newSQLInvalidColumnIndexException(column); + } } /** @@ -1772,7 +1806,7 @@ public class MonetResultSet extends Mone } lastReadWasNull = false; MonetDBType = types[columnIndex - 1]; - JdbcType = getJavaType(MonetDBType); + JdbcType = JdbcSQLTypes[columnIndex - 1]; } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } @@ -1963,7 +1997,7 @@ public class MonetResultSet extends Mone } if (type == null) { // fallback to the standard Class mappings - type = getClassForType(getJavaType(MonetDBtype)); + type = getClassForType(JdbcSQLTypes[columnIndex - 1]); } if (type == null || type == String.class) { @@ -2566,12 +2600,13 @@ public class MonetResultSet extends Mone } lastReadWasNull = false; MonetDBType = types[columnIndex - 1]; - JdbcType = getJavaType(MonetDBType); + JdbcType = JdbcSQLTypes[columnIndex - 1]; // If we got a string type, set the JdbcType to the given type // so we attempt to parse it as the caller thinks it is. if (JdbcType == Types.CHAR || JdbcType == Types.VARCHAR || - JdbcType == Types.LONGVARCHAR) + JdbcType == Types.LONGVARCHAR || + JdbcType == Types.CLOB) { JdbcType = type; } @@ -3686,27 +3721,6 @@ public class MonetResultSet extends Mone } /** - * Wrapper function to map a BLOB as BINARY. Some applications - * require a BINARY type that maps into a byte array, that - * MonetDB/SQL lacks. With the treat_blob_as_binary flag from the - * MonetDriver, we can "fake" the BINARY type, as replacement of the - * BLOB type. This functions calls the getJavaType functions of the - * MonetDriver, but changes BLOB to BINARY if necessary afterwards. - * - * @param sqltype the string sqltype that the server knows - * @return a java.sql.Types constant matching sqltype, with BLOB - * mapped to BINARY if requested. - */ - private int getJavaType(String sqltype) throws SQLException { - int type = MonetDriver.getJavaType(sqltype); - if (type == Types.BLOB) { - if (statement != null && ((MonetConnection)statement.getConnection()).getBlobAsBinary()) - type = Types.BINARY; - } - return type; - } - - /** * Small helper method that formats the "Invalid Column Index number ..." message * and creates a new SQLException object whose SQLState is set to "M1M05". * _______________________________________________ checkin-list mailing list [email protected] https://www.monetdb.org/mailman/listinfo/checkin-list
