Mercurial > hg > monetdb-java
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"; |