comparison src/main/java/org/monetdb/jdbc/MonetPreparedStatement.java @ 873:90e9d216b232

Optimised internal method getParamIdx(). Instead of going through a loop each time (for all result columns and parameters), we now calculate the internal array index value directly, which is much faster. Also moved the getParamIdx() method to the end where all other non-JDBC API methods are listed.
author Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
date Thu, 22 Feb 2024 19:36:42 +0100 (14 months ago)
parents 5a59910e8f87
children 333bbac1e3e8
comparison
equal deleted inserted replaced
872:aa30a3be8787 873:90e9d216b232
64 * [ "int", 9, 0 ] 64 * [ "int", 9, 0 ]
65 *</pre> 65 *</pre>
66 * 66 *
67 * @author Fabian Groffen 67 * @author Fabian Groffen
68 * @author Martin van Dinther 68 * @author Martin van Dinther
69 * @version 0.7 69 * @version 0.8
70 */ 70 */
71 public class MonetPreparedStatement 71 public class MonetPreparedStatement
72 extends MonetStatement 72 extends MonetStatement
73 implements PreparedStatement, AutoCloseable 73 implements PreparedStatement, AutoCloseable
74 { 74 {
81 private final String[] table; 81 private final String[] table;
82 private final String[] column; 82 private final String[] column;
83 private final int id; 83 private final int id;
84 private final int size; 84 private final int size;
85 85
86 private int paramCount = 0; 86 private final int paramCount;
87 private final int paramStartIndex;
87 private final String[] paramValues; 88 private final String[] paramValues;
88 89
89 /** A cache to reduce the number of ResultSetMetaData objects created 90 /** A cache to reduce the number of ResultSetMetaData objects created
90 * by getMetaData() to maximum 1 per PreparedStatement */ 91 * by getMetaData() to maximum 1 per PreparedStatement */
91 private ResultSetMetaData rsmd; 92 private ResultSetMetaData rsmd;
137 if (prepareQuery == null) 138 if (prepareQuery == null)
138 throw new SQLException("Missing SQL statement", "M1M05"); 139 throw new SQLException("Missing SQL statement", "M1M05");
139 140
140 /** 141 /**
141 * For a PREPARE statement the server sends back a result set 142 * For a PREPARE statement the server sends back a result set
142 * with info on all the parameters and/or result columns of a 143 * with info on all the result columns and parameters of a
143 * parameterized query. This result set however needs to be 144 * parameterized query. This result set however needs to be
144 * read in one DataBlockResponse due to protocol limitations. 145 * read in one DataBlockResponse due to protocol limitations.
145 * This requires the fetchSize needs to be set large enough 146 * This requires the fetchSize needs to be set large enough
146 * to retrieve all rows in one go, else we get eror: 147 * to retrieve all rows in one go, else we get eror:
147 * <pre>resultBlocks[1] should have been fetched by now</pre> 148 * <pre>resultBlocks[1] should have been fetched by now</pre>
159 160
160 sqlStatement = prepareQuery; 161 sqlStatement = prepareQuery;
161 // cheat a bit to get the ID and the number of columns 162 // cheat a bit to get the ID and the number of columns
162 id = ((MonetConnection.ResultSetResponse)header).id; 163 id = ((MonetConnection.ResultSetResponse)header).id;
163 size = (int)((MonetConnection.ResultSetResponse)header).tuplecount; 164 size = (int)((MonetConnection.ResultSetResponse)header).tuplecount;
165
166 int countParam = 0;
167 int firstParamOffset = 0;
164 168
165 // initialise blank finals 169 // initialise blank finals
166 monetdbType = new String[size]; 170 monetdbType = new String[size];
167 javaType = new int[size]; 171 javaType = new int[size];
168 digits = new int[size]; 172 digits = new int[size];
197 schema[i] = rs.getString(schema_colnr); 201 schema[i] = rs.getString(schema_colnr);
198 table[i] = rs.getString(table_colnr); 202 table[i] = rs.getString(table_colnr);
199 column[i] = rs.getString(column_colnr); 203 column[i] = rs.getString(column_colnr);
200 // System.out.println("column " + i + " has value: " + column[i]); 204 // System.out.println("column " + i + " has value: " + column[i]);
201 /* when column[i] != null it is a result column of the prepared query, 205 /* when column[i] != null it is a result column of the prepared query,
202 when column[i] == null it is a parameter for the prepared statement, see getParamIdx(int). */ 206 * when column[i] == null it is a parameter for the prepared statement.
203 if (column[i] == null) 207 * Note that we always get the result columns (if any) first and
204 paramCount++; 208 * next the parameters (if any) in the columns[].
209 */
210 if (column[i] == null) {
211 countParam++;
212 if (countParam == 1)
213 firstParamOffset = i; // remember where the first parameter is stored
214 }
205 } 215 }
206 rs.close(); 216 rs.close();
207 } 217 }
218 paramCount = countParam;
219 paramStartIndex = firstParamOffset;
220 // System.out.println("paramCount= " + paramCount + " paramStartIndex= " + paramStartIndex + "\n");
208 221
209 paramValues = new String[paramCount + 1]; // parameters start from 1 222 paramValues = new String[paramCount + 1]; // parameters start from 1
210 223
211 // PreparedStatements are by default poolable 224 // PreparedStatements are by default poolable
212 poolable = true; 225 poolable = true;
213 } 226 }
227
214 228
215 //== methods interface PreparedStatement 229 //== methods interface PreparedStatement
216 230
217 /** 231 /**
218 * Adds a set of parameters to this PreparedStatement object's batch 232 * Adds a set of parameters to this PreparedStatement object's batch
318 332
319 /** override the executeUpdate from the Statement to throw an SQLException */ 333 /** override the executeUpdate from the Statement to throw an SQLException */
320 @Override 334 @Override
321 public int executeUpdate(final String q) throws SQLException { 335 public int executeUpdate(final String q) throws SQLException {
322 throw new SQLException("This method is not available in a PreparedStatement!", "M1M05"); 336 throw new SQLException("This method is not available in a PreparedStatement!", "M1M05");
323 }
324
325 /**
326 * Returns the index (0..size-1) in the backing arrays for the given
327 * parameter number or an SQLException when not found
328 *
329 * @param paramnr the parameter number
330 * @return the internal column array index number
331 * @throws SQLException if parameter number can not be found in the internal array
332 */
333 private final int getParamIdx(final int paramnr) throws SQLException {
334 int curparam = 0;
335 for (int i = 0; i < size; i++) {
336 /* when column[i] == null it is a parameter, when column[i] != null it is a result column of the prepared query */
337 if (column[i] != null)
338 continue;
339 curparam++;
340 if (curparam == paramnr)
341 return i;
342 }
343 throw new SQLException("No such parameter with index: " + paramnr, "M1M05");
344 } 337 }
345 338
346 /** 339 /**
347 * Retrieves a ResultSetMetaData object that contains information 340 * Retrieves a ResultSetMetaData object that contains information
348 * about the columns of the ResultSet object that will be returned 341 * about the columns of the ResultSet object that will be returned
2303 2296
2304 2297
2305 //== internal helper methods which do not belong to the JDBC interface 2298 //== internal helper methods which do not belong to the JDBC interface
2306 2299
2307 /** 2300 /**
2301 * Returns the index (0..size-1) in the backing arrays for the given
2302 * parameter number or an SQLException when not valid
2303 *
2304 * @param paramnr the parameter number
2305 * @return the internal column array index number
2306 * @throws SQLException if parameter number is out of bounds
2307 */
2308 private final int getParamIdx(final int paramnr) throws SQLException {
2309 if (paramnr < 1 || paramnr > paramCount || (paramnr + paramStartIndex > size))
2310 throw new SQLException("No parameter with index: " + paramnr, "M1M05");
2311
2312 return paramnr + paramStartIndex -1;
2313 }
2314
2315 /**
2308 * Sets the given index with the supplied value. If the given index is 2316 * Sets the given index with the supplied value. If the given index is
2309 * out of bounds, and SQLException is thrown. The given value should 2317 * out of bounds, and SQLException is thrown. The given value should
2310 * never be null. 2318 * never be null.
2311 * 2319 *
2312 * @param parameterIndex the parameter index 2320 * @param parameterIndex the parameter index
2313 * @param val the exact String representation to set 2321 * @param val the exact String representation to set
2314 * @throws SQLException if the given index is out of bounds 2322 * @throws SQLException if the given index is out of bounds
2315 */ 2323 */
2316 private final void setValue(final int parameterIndex, final String val) throws SQLException { 2324 private final void setValue(final int parameterIndex, final String val) throws SQLException {
2317 if (parameterIndex < 1 || parameterIndex > paramCount) 2325 if (parameterIndex < 1 || parameterIndex > paramCount)
2318 throw new SQLException("No such parameter with index: " + parameterIndex, "M1M05"); 2326 throw new SQLException("No parameter with index: " + parameterIndex, "M1M05");
2319 2327
2320 if (val != null) 2328 if (val != null)
2321 paramValues[parameterIndex] = val; 2329 paramValues[parameterIndex] = val;
2322 else 2330 else
2323 paramValues[parameterIndex] = "NULL"; 2331 paramValues[parameterIndex] = "NULL";