Changeset: 6a6c86ac3232 for monetdb-java URL: https://dev.monetdb.org/hg/monetdb-java/rev/6a6c86ac3232 Modified Files: src/main/java/org/monetdb/jdbc/MonetPreparedStatement.java Branch: default Log Message:
Optimised storing, setting and processing of parameter values in MonetPreparedStatement. It used to allocate an array to store parameter values potententially larger than needed. Also it needed to compute the array index position for each set parameter by invoking getParamIdx(int) each time. This overhead is now eliminated as the parameter values array size is in sync with the parameter index numbers. Also made the StringBuilder buffer to construct the exec ###() statement reusable, so much less objects are created. diffs (278 lines): diff --git a/src/main/java/org/monetdb/jdbc/MonetPreparedStatement.java b/src/main/java/org/monetdb/jdbc/MonetPreparedStatement.java --- a/src/main/java/org/monetdb/jdbc/MonetPreparedStatement.java +++ b/src/main/java/org/monetdb/jdbc/MonetPreparedStatement.java @@ -80,7 +80,8 @@ public class MonetPreparedStatement private final int size; private final int rscolcnt; - private final String[] values; + private int paramCount = 0; + private final String[] paramValues; /* placeholders for date/time pattern formats created once (only when needed), used multiple times */ /** Format of a timestamp with RFC822 time zone */ @@ -139,7 +140,6 @@ public class MonetPreparedStatement schema = new String[size]; table = new String[size]; column = new String[size]; - values = new String[size]; // fill the arrays final ResultSet rs = super.getResultSet(); @@ -169,13 +169,17 @@ public class MonetPreparedStatement schema[i] = rs.getString(schema_colnr); table[i] = rs.getString(table_colnr); column[i] = rs.getString(column_colnr); + // System.out.println("column " + i + " has value: " + column[i]); /* when column[i] != null it is a result column of the prepared query, see getColumnIdx(int), when column[i] == null it is a parameter for the prepared statement, see getParamIdx(int). */ - // System.out.println("column " + i + " has value: " + column[i]); + if (column[i] == null) + paramCount++; } rs.close(); } + paramValues = new String[paramCount + 1]; // parameters start from 1 + // PreparedStatements are by default poolable poolable = true; } @@ -212,7 +216,7 @@ public class MonetPreparedStatement schema = null; table = null; column = null; - values = null; + paramValues = null; id = -1; size = -1; rscolcnt = -1; @@ -249,8 +253,8 @@ public class MonetPreparedStatement */ @Override public void clearParameters() { - for (int i = 0; i < size; i++) { - values[i] = null; + for (int param = 1; param <= paramCount; param++) { + paramValues[param] = null; } } @@ -785,17 +789,10 @@ public class MonetPreparedStatement * object contains information. * * @return the number of parameters - * @throws SQLException if a database access error occurs */ @Override - public int getParameterCount() throws SQLException { - int cnt = 0; - - for (int i = 0; i < size; i++) { - if (column[i] == null) - cnt++; - } - return cnt; + public int getParameterCount() { + return paramCount; } /** @@ -809,10 +806,9 @@ public class MonetPreparedStatement * one of ParameterMetaData.parameterNoNulls, * ParameterMetaData.parameterNullable, or * ParameterMetaData.parameterNullableUnknown - * @throws SQLException if a database access error occurs */ @Override - public int isNullable(final int param) throws SQLException { + public int isNullable(final int param) { return ParameterMetaData.parameterNullableUnknown; } @@ -962,10 +958,9 @@ public class MonetPreparedStatement * ParameterMetaData.parameterModeOut, or * ParameterMetaData.parameterModeInOut * ParameterMetaData.parameterModeUnknown. - * @throws SQLException if a database access error occurs */ @Override - public int getParameterMode(final int param) throws SQLException { + public int getParameterMode(final int param) { return ParameterMetaData.parameterModeIn; } }; @@ -1263,7 +1258,7 @@ public class MonetPreparedStatement @Override public void setBytes(final int parameterIndex, final byte[] x) throws SQLException { if (x == null) { - setNull(parameterIndex, -1); + setValue(parameterIndex, "NULL"); return; } @@ -1358,7 +1353,7 @@ public class MonetPreparedStatement @Override public void setClob(final int parameterIndex, final Clob x) throws SQLException { if (x == null) { - setNull(parameterIndex, -1); + setValue(parameterIndex, "NULL"); return; } @@ -1379,7 +1374,7 @@ public class MonetPreparedStatement @Override public void setClob(final int parameterIndex, final Reader reader) throws SQLException { if (reader == null) { - setNull(parameterIndex, -1); + setValue(parameterIndex, "NULL"); return; } @@ -1417,7 +1412,7 @@ public class MonetPreparedStatement @Override public void setClob(final int parameterIndex, final Reader reader, final long length) throws SQLException { if (reader == null) { - setNull(parameterIndex, -1); + setValue(parameterIndex, "NULL"); return; } if (length < 0 || length > Integer.MAX_VALUE) { @@ -1471,7 +1466,7 @@ public class MonetPreparedStatement throws SQLException { if (x == null) { - setNull(parameterIndex, -1); + setValue(parameterIndex, "NULL"); return; } @@ -1780,7 +1775,7 @@ public class MonetPreparedStatement throws SQLException { if (x == null) { - setNull(parameterIndex, -1); + setValue(parameterIndex, "NULL"); return; } @@ -2218,7 +2213,7 @@ public class MonetPreparedStatement @Override public void setString(final int parameterIndex, final String x) throws SQLException { if (x == null) { - setNull(parameterIndex, -1); + setValue(parameterIndex, "NULL"); return; } @@ -2530,7 +2525,7 @@ public class MonetPreparedStatement throws SQLException { if (x == null) { - setNull(parameterIndex, -1); + setValue(parameterIndex, "NULL"); return; } @@ -2600,7 +2595,7 @@ public class MonetPreparedStatement throws SQLException { if (x == null) { - setNull(parameterIndex, -1); + setValue(parameterIndex, "NULL"); return; } @@ -2674,7 +2669,7 @@ public class MonetPreparedStatement @Override public void setURL(final int parameterIndex, final URL x) throws SQLException { if (x == null) { - setNull(parameterIndex, -1); + setValue(parameterIndex, "NULL"); return; } @@ -2725,14 +2720,15 @@ public class MonetPreparedStatement */ @Override public String toString() { - final StringBuilder sb = new StringBuilder(256); + final StringBuilder sb = new StringBuilder(128 + paramCount * 64); sb.append("Prepared SQL: ").append(sqlStatement).append("\n"); int param = 1; for (int i = 0; i < size; i++) { /* when column[i] == null it is a parameter, when column[i] != null it is a result column of the prepared query */ if (column[i] == null) { - sb.append(" parameter ").append(param++).append(" ").append(monetdbType[i]); - sb.append(", set value: ").append((values[i] != null) ? values[i] : "<null>").append("\n"); + sb.append(" parameter ").append(param).append(" ").append(monetdbType[i]); + sb.append(", set value: ").append((paramValues[param] != null) ? paramValues[param] : "<null>").append("\n"); + param++; } } return sb.toString(); @@ -2788,37 +2784,41 @@ public class MonetPreparedStatement * @throws SQLException if the given index is out of bounds */ private final void setValue(final int parameterIndex, final String val) throws SQLException { - values[getParamIdx(parameterIndex)] = (val == null ? "NULL" : val); + if (parameterIndex < 1 || parameterIndex > paramCount) + throw new SQLException("No such parameter with index: " + parameterIndex, "M1M05"); + + if (val != null) + paramValues[parameterIndex] = val; + else + paramValues[parameterIndex] = "NULL"; } /** - * Transforms the prepare query into a simple SQL query by replacing - * the ?'s with the given column contents. - * Mind that the JDBC specs allow `reuse' of a value for a column over - * multiple executes. + * Constructs an "exec ##(paramval, ...)" statement string for the current parameter values. + * Mind that the JDBC specs allow 'reuse' of a value for a parameter over multiple executes. * - * @return the simple SQL string for the prepare query - * @throws SQLException if not all columns are set + * @return the "exec ##(...)" string + * @throws SQLException if not all parameters are set with a value */ + private StringBuilder execStmt; // created once, re-used multiple times so much less objects are created and gc-ed private final String transform() throws SQLException { - final StringBuilder buf = new StringBuilder(8 + 12 * size); - buf.append("exec ").append(id).append('('); - // check if all columns are set and do a replace - int col = 0; - for (int i = 0; i < size; i++) { - if (column[i] != null) - continue; - col++; - if (col > 1) - buf.append(','); - if (values[i] == null) - throw new SQLException("Cannot execute, parameter " + col + " is missing.", "M1M05"); + if (execStmt == null) + // first time use, create it once + execStmt = new StringBuilder(32 + paramCount * 32); + else + execStmt.setLength(0); // clear the buffer - buf.append(values[i]); + execStmt.append("exec ").append(id).append('('); + // check if all parameters are set and add the parameter values + for (int param = 1; param <= paramCount; param++) { + if (paramValues[param] == null) + throw new SQLException("Cannot execute, parameter " + param + " is missing.", "M1M05"); + if (param > 1) + execStmt.append(','); + execStmt.append(paramValues[param]); } - buf.append(')'); - - return buf.toString(); + execStmt.append(')'); + return execStmt.toString(); } /** _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list