Mercurial > hg > monetdb-java
comparison src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java @ 295:003ae6d881db
Add "final" keyword to method arguments and local variables where possible.
It discovered some bugs in the MonetStatement constructor (changed the argument instead of object variable) which are fixed now.
See also https://en.wikipedia.org/wiki/Final_(Java)
author | Martin van Dinther <martin.van.dinther@monetdbsolutions.com> |
---|---|
date | Thu, 01 Aug 2019 20:18:43 +0200 (2019-08-01) |
parents | b127164342c4 |
children | c5efd6e661e5 |
comparison
equal
deleted
inserted
replaced
294:894abb249de1 | 295:003ae6d881db |
---|---|
10 | 10 |
11 import java.io.File; | 11 import java.io.File; |
12 import java.io.IOException; | 12 import java.io.IOException; |
13 import java.net.SocketException; | 13 import java.net.SocketException; |
14 import java.net.SocketTimeoutException; | 14 import java.net.SocketTimeoutException; |
15 import java.net.UnknownHostException; | |
16 import java.sql.CallableStatement; | 15 import java.sql.CallableStatement; |
17 import java.sql.Connection; | 16 import java.sql.Connection; |
18 import java.sql.DatabaseMetaData; | 17 import java.sql.DatabaseMetaData; |
19 import java.sql.PreparedStatement; | 18 import java.sql.PreparedStatement; |
20 import java.sql.ResultSet; | 19 import java.sql.ResultSet; |
26 import java.sql.Savepoint; | 25 import java.sql.Savepoint; |
27 import java.sql.Statement; | 26 import java.sql.Statement; |
28 import java.util.ArrayList; | 27 import java.util.ArrayList; |
29 import java.util.Calendar; | 28 import java.util.Calendar; |
30 import java.util.HashMap; | 29 import java.util.HashMap; |
31 import java.util.List; | |
32 import java.util.Map; | 30 import java.util.Map; |
33 import java.util.Map.Entry; | 31 import java.util.Map.Entry; |
34 import java.util.Properties; | 32 import java.util.Properties; |
35 import java.util.WeakHashMap; | 33 import java.util.WeakHashMap; |
36 import java.util.concurrent.Executor; | 34 import java.util.concurrent.Executor; |
37 import java.util.concurrent.locks.Condition; | 35 |
38 import java.util.concurrent.locks.Lock; | |
39 import java.util.concurrent.locks.ReentrantLock; | |
40 | |
41 import nl.cwi.monetdb.jdbc.types.INET; | |
42 import nl.cwi.monetdb.jdbc.types.URL; | |
43 import nl.cwi.monetdb.mcl.MCLException; | |
44 import nl.cwi.monetdb.mcl.io.BufferedMCLReader; | 36 import nl.cwi.monetdb.mcl.io.BufferedMCLReader; |
45 import nl.cwi.monetdb.mcl.io.BufferedMCLWriter; | 37 import nl.cwi.monetdb.mcl.io.BufferedMCLWriter; |
46 import nl.cwi.monetdb.mcl.net.MapiSocket; | 38 import nl.cwi.monetdb.mcl.net.MapiSocket; |
47 import nl.cwi.monetdb.mcl.parser.HeaderLineParser; | 39 import nl.cwi.monetdb.mcl.parser.HeaderLineParser; |
48 import nl.cwi.monetdb.mcl.parser.MCLParseException; | 40 import nl.cwi.monetdb.mcl.parser.MCLParseException; |
70 * The current state of this connection is that it nearly implements the | 62 * The current state of this connection is that it nearly implements the |
71 * whole Connection interface. | 63 * whole Connection interface. |
72 * | 64 * |
73 * @author Fabian Groffen | 65 * @author Fabian Groffen |
74 * @author Martin van Dinther | 66 * @author Martin van Dinther |
75 * @version 1.3 | 67 * @version 1.4 |
76 */ | 68 */ |
77 public class MonetConnection | 69 public class MonetConnection |
78 extends MonetWrapper | 70 extends MonetWrapper |
79 implements Connection, AutoCloseable | 71 implements Connection, AutoCloseable |
80 { | 72 { |
97 /** The Reader from the server */ | 89 /** The Reader from the server */ |
98 private final BufferedMCLReader in; | 90 private final BufferedMCLReader in; |
99 /** The Writer to the server */ | 91 /** The Writer to the server */ |
100 private final BufferedMCLWriter out; | 92 private final BufferedMCLWriter out; |
101 | 93 |
102 /** A StartOfHeaderParser declared for reuse. */ | 94 /** A StartOfHeaderParser declared for reuse. */ |
103 private StartOfHeaderParser sohp = new StartOfHeaderParser(); | 95 private StartOfHeaderParser sohp = new StartOfHeaderParser(); |
104 | 96 |
105 /** Whether this Connection is closed (and cannot be used anymore) */ | 97 /** Whether this Connection is closed (and cannot be used anymore) */ |
106 private boolean closed; | 98 private boolean closed; |
107 | 99 |
113 | 105 |
114 /** The Connection specific mapping of user defined types to Java types */ | 106 /** The Connection specific mapping of user defined types to Java types */ |
115 private Map<String,Class<?>> typeMap = new HashMap<String,Class<?>>() { | 107 private Map<String,Class<?>> typeMap = new HashMap<String,Class<?>>() { |
116 private static final long serialVersionUID = 1L; | 108 private static final long serialVersionUID = 1L; |
117 { | 109 { |
118 put("inet", INET.class); | 110 put("inet", nl.cwi.monetdb.jdbc.types.INET.class); |
119 put("url", URL.class); | 111 put("url", nl.cwi.monetdb.jdbc.types.URL.class); |
120 } | 112 } |
121 }; | 113 }; |
122 | 114 |
123 // See javadoc for documentation about WeakHashMap if you don't know what | 115 // See javadoc for documentation about WeakHashMap if you don't know what |
124 // it does !!!NOW!!! (only when you deal with it of course) | 116 // it does !!!NOW!!! (only when you deal with it of course) |
125 /** A Map containing all (active) Statements created from this Connection */ | 117 /** A Map containing all (active) Statements created from this Connection */ |
126 private Map<Statement,?> statements = new WeakHashMap<Statement, Object>(); | 118 private WeakHashMap<Statement,?> statements = new WeakHashMap<Statement, Object>(); |
127 | 119 |
128 /** The number of results we receive from the server at once */ | 120 /** The number of results we receive from the server at once */ |
129 private int curReplySize = -1; // the server by default uses -1 (all) | 121 private int curReplySize = -1; // the server by default uses -1 (all) |
130 | 122 |
131 /** A template to apply to each query (like pre and post fixes), filled in constructor */ | 123 /** A template to apply to each query (like pre and post fixes), filled in constructor */ |
169 * | 161 * |
170 * @param props a Property hashtable holding the properties needed for connecting | 162 * @param props a Property hashtable holding the properties needed for connecting |
171 * @throws SQLException if a database error occurs | 163 * @throws SQLException if a database error occurs |
172 * @throws IllegalArgumentException is one of the arguments is null or empty | 164 * @throws IllegalArgumentException is one of the arguments is null or empty |
173 */ | 165 */ |
174 MonetConnection(Properties props) | 166 MonetConnection(final Properties props) |
175 throws SQLException, IllegalArgumentException | 167 throws SQLException, IllegalArgumentException |
176 { | 168 { |
177 // for debug: System.out.println("New connection object. Received properties are: " + props.toString()); | 169 // for debug: System.out.println("New connection object. Received properties are: " + props.toString()); |
178 // get supported property values from the props argument. | 170 // get supported property values from the props argument. |
179 // When a value is found add it to the internal conn_props list for use by getClientInfo(). | 171 // When a value is found add it to the internal conn_props list for use by getClientInfo(). |
180 this.hostname = props.getProperty("host"); | 172 this.hostname = props.getProperty("host"); |
181 if (this.hostname != null) | 173 if (this.hostname != null) |
182 conn_props.setProperty("host", this.hostname); | 174 conn_props.setProperty("host", this.hostname); |
183 | 175 |
184 String port_prop = props.getProperty("port"); | 176 final String port_prop = props.getProperty("port"); |
185 if (port_prop != null) { | 177 if (port_prop != null) { |
186 try { | 178 try { |
187 this.port = Integer.parseInt(port_prop); | 179 this.port = Integer.parseInt(port_prop); |
188 } catch (NumberFormatException e) { | 180 } catch (NumberFormatException e) { |
189 addWarning("Unable to parse port number from: " + port_prop, "M1M05"); | 181 addWarning("Unable to parse port number from: " + port_prop, "M1M05"); |
212 if (debug_prop != null) { | 204 if (debug_prop != null) { |
213 debug = Boolean.parseBoolean(debug_prop); | 205 debug = Boolean.parseBoolean(debug_prop); |
214 conn_props.setProperty("debug", Boolean.toString(debug)); | 206 conn_props.setProperty("debug", Boolean.toString(debug)); |
215 } | 207 } |
216 | 208 |
217 String hash = props.getProperty("hash"); | 209 final String hash = props.getProperty("hash"); |
218 if (hash != null) | 210 if (hash != null) |
219 conn_props.setProperty("hash", hash); | 211 conn_props.setProperty("hash", hash); |
220 | 212 |
221 String treatBlobAsVarBinary_prop = props.getProperty("treat_blob_as_binary"); | 213 final String treatBlobAsVarBinary_prop = props.getProperty("treat_blob_as_binary"); |
222 if (treatBlobAsVarBinary_prop != null) { | 214 if (treatBlobAsVarBinary_prop != null) { |
223 treatBlobAsVarBinary = Boolean.parseBoolean(treatBlobAsVarBinary_prop); | 215 treatBlobAsVarBinary = Boolean.parseBoolean(treatBlobAsVarBinary_prop); |
224 conn_props.setProperty("treat_blob_as_binary", Boolean.toString(treatBlobAsVarBinary)); | 216 conn_props.setProperty("treat_blob_as_binary", Boolean.toString(treatBlobAsVarBinary)); |
225 if (treatBlobAsVarBinary) | 217 if (treatBlobAsVarBinary) |
226 typeMap.put("blob", Byte[].class); | 218 typeMap.put("blob", Byte[].class); |
227 } | 219 } |
228 | 220 |
229 String treatClobAsVarChar_prop = props.getProperty("treat_clob_as_varchar"); | 221 final String treatClobAsVarChar_prop = props.getProperty("treat_clob_as_varchar"); |
230 if (treatClobAsVarChar_prop != null) { | 222 if (treatClobAsVarChar_prop != null) { |
231 treatClobAsVarChar = Boolean.parseBoolean(treatClobAsVarChar_prop); | 223 treatClobAsVarChar = Boolean.parseBoolean(treatClobAsVarChar_prop); |
232 conn_props.setProperty("treat_clob_as_varchar", Boolean.toString(treatClobAsVarChar)); | 224 conn_props.setProperty("treat_clob_as_varchar", Boolean.toString(treatClobAsVarChar)); |
233 if (treatClobAsVarChar) | 225 if (treatClobAsVarChar) |
234 typeMap.put("clob", String.class); | 226 typeMap.put("clob", String.class); |
235 } | 227 } |
236 | 228 |
237 int sockTimeout = 0; | 229 int sockTimeout = 0; |
238 String so_timeout_prop = props.getProperty("so_timeout"); | 230 final String so_timeout_prop = props.getProperty("so_timeout"); |
239 if (so_timeout_prop != null) { | 231 if (so_timeout_prop != null) { |
240 try { | 232 try { |
241 sockTimeout = Integer.parseInt(so_timeout_prop); | 233 sockTimeout = Integer.parseInt(so_timeout_prop); |
242 if (sockTimeout < 0) { | 234 if (sockTimeout < 0) { |
243 addWarning("Negative socket timeout not allowed. Value ignored", "M1M05"); | 235 addWarning("Negative socket timeout not allowed. Value ignored", "M1M05"); |
272 server.setLanguage(language); | 264 server.setLanguage(language); |
273 | 265 |
274 // we're debugging here... uhm, should be off in real life | 266 // we're debugging here... uhm, should be off in real life |
275 if (debug) { | 267 if (debug) { |
276 try { | 268 try { |
277 String fname = props.getProperty("logfile", "monet_" + System.currentTimeMillis() + ".log"); | 269 final String fname = props.getProperty("logfile", "monet_" + System.currentTimeMillis() + ".log"); |
278 File f = new File(fname); | 270 File f = new File(fname); |
271 | |
279 int ext = fname.lastIndexOf('.'); | 272 int ext = fname.lastIndexOf('.'); |
280 if (ext < 0) | 273 if (ext < 0) |
281 ext = fname.length(); | 274 ext = fname.length(); |
282 String pre = fname.substring(0, ext); | 275 final String pre = fname.substring(0, ext); |
283 String suf = fname.substring(ext); | 276 final String suf = fname.substring(ext); |
284 | 277 |
285 for (int i = 1; f.exists(); i++) { | 278 for (int i = 1; f.exists(); i++) { |
286 f = new File(pre + "-" + i + suf); | 279 f = new File(pre + "-" + i + suf); |
287 } | 280 } |
288 | 281 |
291 throw new SQLNonTransientConnectionException("Opening logfile failed: " + ex.getMessage(), "08M01"); | 284 throw new SQLNonTransientConnectionException("Opening logfile failed: " + ex.getMessage(), "08M01"); |
292 } | 285 } |
293 } | 286 } |
294 | 287 |
295 try { | 288 try { |
296 List<String> warnings = server.connect(hostname, port, username, password); | 289 final java.util.List<String> warnings = server.connect(hostname, port, username, password); |
297 for (String warning : warnings) { | 290 for (String warning : warnings) { |
298 addWarning(warning, "01M02"); | 291 addWarning(warning, "01M02"); |
299 } | 292 } |
300 | 293 |
301 // apply NetworkTimeout value from legacy (pre 4.1) driver | 294 // apply NetworkTimeout value from legacy (pre 4.1) driver |
303 server.setSoTimeout(sockTimeout); | 296 server.setSoTimeout(sockTimeout); |
304 | 297 |
305 in = server.getReader(); | 298 in = server.getReader(); |
306 out = server.getWriter(); | 299 out = server.getWriter(); |
307 | 300 |
308 String error = in.waitForPrompt(); | 301 final String error = in.waitForPrompt(); |
309 if (error != null) | 302 if (error != null) |
310 throw new SQLNonTransientConnectionException((error.length() > 6) ? error.substring(6) : error, "08001"); | 303 throw new SQLNonTransientConnectionException((error.length() > 6) ? error.substring(6) : error, "08001"); |
311 } catch (UnknownHostException e) { | 304 } catch (java.net.UnknownHostException e) { |
312 throw new SQLNonTransientConnectionException("Unknown Host (" + hostname + "): " + e.getMessage(), "08006"); | 305 throw new SQLNonTransientConnectionException("Unknown Host (" + hostname + "): " + e.getMessage(), "08006"); |
313 } catch (IOException e) { | 306 } catch (IOException e) { |
314 throw new SQLNonTransientConnectionException("Unable to connect (" + hostname + ":" + port + "): " + e.getMessage(), "08006"); | 307 throw new SQLNonTransientConnectionException("Unable to connect (" + hostname + ":" + port + "): " + e.getMessage(), "08006"); |
315 } catch (MCLParseException e) { | 308 } catch (MCLParseException e) { |
316 throw new SQLNonTransientConnectionException(e.getMessage(), "08001"); | 309 throw new SQLNonTransientConnectionException(e.getMessage(), "08001"); |
317 } catch (MCLException e) { | 310 } catch (nl.cwi.monetdb.mcl.MCLException e) { |
318 String[] connex = e.getMessage().split("\n"); | 311 final String[] connex = e.getMessage().split("\n"); |
319 SQLException sqle = new SQLNonTransientConnectionException(connex[0], "08001", e); | 312 final SQLException sqle = new SQLNonTransientConnectionException(connex[0], "08001", e); |
320 for (int i = 1; i < connex.length; i++) { | 313 for (int i = 1; i < connex.length; i++) { |
321 sqle.setNextException(new SQLNonTransientConnectionException(connex[1], "08001")); | 314 sqle.setNextException(new SQLNonTransientConnectionException(connex[1], "08001")); |
322 } | 315 } |
323 throw sqle; | 316 throw sqle; |
324 } | 317 } |
353 if (lang == LANG_SQL) { | 346 if (lang == LANG_SQL) { |
354 // enable auto commit | 347 // enable auto commit |
355 setAutoCommit(true); | 348 setAutoCommit(true); |
356 | 349 |
357 // set our time zone on the server | 350 // set our time zone on the server |
358 Calendar cal = Calendar.getInstance(); | 351 final Calendar cal = Calendar.getInstance(); |
359 int offset = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET); | 352 int offset = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET); |
360 offset /= (60 * 1000); // milliseconds to minutes | 353 offset /= (60 * 1000); // milliseconds to minutes |
361 String tz = offset < 0 ? "-" : "+"; | 354 String tz = offset < 0 ? "-" : "+"; |
362 tz += (Math.abs(offset) / 60 < 10 ? "0" : "") + (Math.abs(offset) / 60) + ":"; | 355 tz += (Math.abs(offset) / 60 < 10 ? "0" : "") + (Math.abs(offset) / 60) + ":"; |
363 offset -= (offset / 60) * 60; | 356 offset -= (offset / 60) * 60; |
457 * @return a new Statement object that will generate ResultSet objects with | 450 * @return a new Statement object that will generate ResultSet objects with |
458 * the given type and concurrency | 451 * the given type and concurrency |
459 * @throws SQLException if a database access error occurs | 452 * @throws SQLException if a database access error occurs |
460 */ | 453 */ |
461 @Override | 454 @Override |
462 public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { | 455 public Statement createStatement(final int resultSetType, final int resultSetConcurrency) throws SQLException { |
463 return createStatement(resultSetType, resultSetConcurrency, MonetResultSet.DEF_HOLDABILITY); | 456 return createStatement(resultSetType, resultSetConcurrency, MonetResultSet.DEF_HOLDABILITY); |
464 } | 457 } |
465 | 458 |
466 /** | 459 /** |
467 * Creates a Statement object that will generate ResultSet objects | 460 * Creates a Statement object that will generate ResultSet objects |
485 * @throws SQLException if a database access error occurs or the | 478 * @throws SQLException if a database access error occurs or the |
486 * given parameters are not ResultSet constants indicating type, | 479 * given parameters are not ResultSet constants indicating type, |
487 * concurrency, and holdability | 480 * concurrency, and holdability |
488 */ | 481 */ |
489 @Override | 482 @Override |
490 public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { | 483 public Statement createStatement(final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { |
491 try { | 484 try { |
492 Statement ret = new MonetStatement(this, resultSetType, resultSetConcurrency, resultSetHoldability); | 485 final Statement ret = new MonetStatement(this, resultSetType, resultSetConcurrency, resultSetHoldability); |
493 // store it in the map for when we close... | 486 // store it in the map for when we close... |
494 statements.put(ret, null); | 487 statements.put(ret, null); |
495 return ret; | 488 return ret; |
496 } catch (IllegalArgumentException e) { | 489 } catch (IllegalArgumentException e) { |
497 throw new SQLException(e.toString(), "M0M03"); | 490 throw new SQLException(e.toString(), "M0M03"); |
646 * | 639 * |
647 * @param sql - an SQL statement that may contain one or more '?' parameter placeholders. | 640 * @param sql - an SQL statement that may contain one or more '?' parameter placeholders. |
648 * @return the native form of this statement | 641 * @return the native form of this statement |
649 */ | 642 */ |
650 @Override | 643 @Override |
651 public String nativeSQL(String sql) { | 644 public String nativeSQL(final String sql) { |
652 /* there is currently no way to get the native MonetDB rewritten SQL string back, so just return the original string */ | 645 /* there is currently no way to get the native MonetDB rewritten SQL string back, so just return the original string */ |
653 /* in future we may replace/remove the escape sequences { <escape-type> ...} before sending it to the server */ | 646 /* in future we may replace/remove the escape sequences { <escape-type> ...} before sending it to the server */ |
654 return sql; | 647 return sql; |
655 } | 648 } |
656 | 649 |
670 * | 663 * |
671 * @param sql - an SQL statement that may contain one or more '?' parameter placeholders. | 664 * @param sql - an SQL statement that may contain one or more '?' parameter placeholders. |
672 * Typically this statement is specified using JDBC call escape syntax. | 665 * Typically this statement is specified using JDBC call escape syntax. |
673 * @return a new default CallableStatement object containing the pre-compiled SQL statement | 666 * @return a new default CallableStatement object containing the pre-compiled SQL statement |
674 * @throws SQLException - if a database access error occurs or this method is called on a closed connection | 667 * @throws SQLException - if a database access error occurs or this method is called on a closed connection |
675 * @throws SQLFeatureNotSupportedException - if the JDBC driver does not support this method. | 668 */ |
676 */ | 669 @Override |
677 @Override | 670 public CallableStatement prepareCall(final String sql) throws SQLException { |
678 public CallableStatement prepareCall(String sql) throws SQLException { | |
679 return prepareCall(sql, MonetResultSet.DEF_RESULTSETTYPE, MonetResultSet.DEF_CONCURRENCY, MonetResultSet.DEF_HOLDABILITY); | 671 return prepareCall(sql, MonetResultSet.DEF_RESULTSETTYPE, MonetResultSet.DEF_CONCURRENCY, MonetResultSet.DEF_HOLDABILITY); |
680 } | 672 } |
681 | 673 |
682 /** | 674 /** |
683 * Creates a CallableStatement object that will generate ResultSet objects with the given type and concurrency. | 675 * Creates a CallableStatement object that will generate ResultSet objects with the given type and concurrency. |
690 * @param resultSetConcurrency - a concurrency type; one of ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE | 682 * @param resultSetConcurrency - a concurrency type; one of ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE |
691 * @return a new CallableStatement object containing the pre-compiled SQL statement that | 683 * @return a new CallableStatement object containing the pre-compiled SQL statement that |
692 * will produce ResultSet objects with the given type and concurrency | 684 * will produce ResultSet objects with the given type and concurrency |
693 * @throws SQLException - if a database access error occurs, this method is called on a closed connection or | 685 * @throws SQLException - if a database access error occurs, this method is called on a closed connection or |
694 * the given parameters are not ResultSet constants indicating type and concurrency | 686 * the given parameters are not ResultSet constants indicating type and concurrency |
695 * @throws SQLFeatureNotSupportedException - if the JDBC driver does not support this method or | 687 */ |
696 * this method is not supported for the specified result set type and result set concurrency. | 688 @Override |
697 */ | 689 public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { |
698 @Override | |
699 public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { | |
700 return prepareCall(sql, resultSetType, resultSetConcurrency, MonetResultSet.DEF_HOLDABILITY); | 690 return prepareCall(sql, resultSetType, resultSetConcurrency, MonetResultSet.DEF_HOLDABILITY); |
701 } | 691 } |
702 | 692 |
703 /** | 693 /** |
704 * Creates a CallableStatement object that will generate ResultSet objects with the given type and concurrency. | 694 * Creates a CallableStatement object that will generate ResultSet objects with the given type and concurrency. |
710 * @param resultSetConcurrency - a concurrency type; one of ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE | 700 * @param resultSetConcurrency - a concurrency type; one of ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE |
711 * @param resultSetHoldability - one of the following ResultSet constants: ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT | 701 * @param resultSetHoldability - one of the following ResultSet constants: ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT |
712 * @return a new CallableStatement object, containing the pre-compiled SQL statement, that will generate ResultSet objects with the given type, concurrency, and holdability | 702 * @return a new CallableStatement object, containing the pre-compiled SQL statement, that will generate ResultSet objects with the given type, concurrency, and holdability |
713 * @throws SQLException - if a database access error occurs, this method is called on a closed connection or | 703 * @throws SQLException - if a database access error occurs, this method is called on a closed connection or |
714 * the given parameters are not ResultSet constants indicating type, concurrency, and holdability | 704 * the given parameters are not ResultSet constants indicating type, concurrency, and holdability |
715 * @throws SQLFeatureNotSupportedException - if the JDBC driver does not support this method or | 705 */ |
716 * this method is not supported for the specified result set type, result set holdability and result set concurrency. | 706 @Override |
717 */ | 707 public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) |
718 @Override | |
719 public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) | |
720 throws SQLException | 708 throws SQLException |
721 { | 709 { |
722 try { | 710 try { |
723 CallableStatement ret = new MonetCallableStatement( | 711 final CallableStatement ret = new MonetCallableStatement( |
724 this, | 712 this, |
725 resultSetType, | 713 resultSetType, |
726 resultSetConcurrency, | 714 resultSetConcurrency, |
727 resultSetHoldability, | 715 resultSetHoldability, |
728 sql | 716 sql |
762 * @return a new default PreparedStatement object containing the | 750 * @return a new default PreparedStatement object containing the |
763 * pre-compiled SQL statement | 751 * pre-compiled SQL statement |
764 * @throws SQLException if a database access error occurs | 752 * @throws SQLException if a database access error occurs |
765 */ | 753 */ |
766 @Override | 754 @Override |
767 public PreparedStatement prepareStatement(String sql) throws SQLException { | 755 public PreparedStatement prepareStatement(final String sql) throws SQLException { |
768 return prepareStatement(sql, MonetResultSet.DEF_RESULTSETTYPE, MonetResultSet.DEF_CONCURRENCY, MonetResultSet.DEF_HOLDABILITY); | 756 return prepareStatement(sql, MonetResultSet.DEF_RESULTSETTYPE, MonetResultSet.DEF_CONCURRENCY, MonetResultSet.DEF_HOLDABILITY); |
769 } | 757 } |
770 | 758 |
771 /** | 759 /** |
772 * Creates a PreparedStatement object that will generate ResultSet | 760 * Creates a PreparedStatement object that will generate ResultSet |
787 * @throws SQLException if a database access error occurs or the given | 775 * @throws SQLException if a database access error occurs or the given |
788 * parameters are not ResultSet constants indicating | 776 * parameters are not ResultSet constants indicating |
789 * type and concurrency | 777 * type and concurrency |
790 */ | 778 */ |
791 @Override | 779 @Override |
792 public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { | 780 public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { |
793 return prepareStatement(sql, resultSetType, resultSetConcurrency, MonetResultSet.DEF_HOLDABILITY); | 781 return prepareStatement(sql, resultSetType, resultSetConcurrency, MonetResultSet.DEF_HOLDABILITY); |
794 } | 782 } |
795 | 783 |
796 /** | 784 /** |
797 * Creates a PreparedStatement object that will generate ResultSet | 785 * Creates a PreparedStatement object that will generate ResultSet |
818 * @throws SQLException if a database access error occurs or the | 806 * @throws SQLException if a database access error occurs or the |
819 * given parameters are not ResultSet constants indicating type, | 807 * given parameters are not ResultSet constants indicating type, |
820 * concurrency, and holdability | 808 * concurrency, and holdability |
821 */ | 809 */ |
822 @Override | 810 @Override |
823 public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) | 811 public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) |
824 throws SQLException | 812 throws SQLException |
825 { | 813 { |
826 try { | 814 try { |
827 PreparedStatement ret = new MonetPreparedStatement( | 815 final PreparedStatement ret = new MonetPreparedStatement( |
828 this, | 816 this, |
829 resultSetType, | 817 resultSetType, |
830 resultSetConcurrency, | 818 resultSetConcurrency, |
831 resultSetHoldability, | 819 resultSetHoldability, |
832 sql | 820 sql |
872 * @throws SQLException - if a database access error occurs or the | 860 * @throws SQLException - if a database access error occurs or the |
873 * given parameter is not a Statement constant indicating | 861 * given parameter is not a Statement constant indicating |
874 * whether auto-generated keys should be returned | 862 * whether auto-generated keys should be returned |
875 */ | 863 */ |
876 @Override | 864 @Override |
877 public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { | 865 public PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys) throws SQLException { |
878 if (autoGeneratedKeys != Statement.RETURN_GENERATED_KEYS && | 866 if (autoGeneratedKeys != Statement.RETURN_GENERATED_KEYS && |
879 autoGeneratedKeys != Statement.NO_GENERATED_KEYS) | 867 autoGeneratedKeys != Statement.NO_GENERATED_KEYS) |
880 throw new SQLException("Invalid argument, expected RETURN_GENERATED_KEYS or NO_GENERATED_KEYS", "M1M05"); | 868 throw new SQLException("Invalid argument, expected RETURN_GENERATED_KEYS or NO_GENERATED_KEYS", "M1M05"); |
881 | 869 |
882 /* MonetDB has no way to disable this, so just do the normal thing ;) */ | 870 /* MonetDB has no way to disable this, so just do the normal thing ;) */ |
906 * returning the auto-generated keys designated by the given array of column indexes | 894 * returning the auto-generated keys designated by the given array of column indexes |
907 * @throws SQLException - if a database access error occurs or this method is called on a closed connection | 895 * @throws SQLException - if a database access error occurs or this method is called on a closed connection |
908 * @throws SQLFeatureNotSupportedException - if the JDBC driver does not support this method | 896 * @throws SQLFeatureNotSupportedException - if the JDBC driver does not support this method |
909 */ | 897 */ |
910 @Override | 898 @Override |
911 public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { | 899 public PreparedStatement prepareStatement(final String sql, final int[] columnIndexes) throws SQLException { |
912 throw newSQLFeatureNotSupportedException("prepareStatement(String sql, int[] columnIndexes)"); | 900 throw newSQLFeatureNotSupportedException("prepareStatement(String sql, int[] columnIndexes)"); |
913 } | 901 } |
914 | 902 |
915 /** | 903 /** |
916 * Creates a default PreparedStatement object capable of returning the auto-generated keys designated by the given array. | 904 * Creates a default PreparedStatement object capable of returning the auto-generated keys designated by the given array. |
935 * returning the auto-generated keys designated by the given array of column names | 923 * returning the auto-generated keys designated by the given array of column names |
936 * @throws SQLException - if a database access error occurs or this method is called on a closed connection | 924 * @throws SQLException - if a database access error occurs or this method is called on a closed connection |
937 * @throws SQLFeatureNotSupportedException - if the JDBC driver does not support this method | 925 * @throws SQLFeatureNotSupportedException - if the JDBC driver does not support this method |
938 */ | 926 */ |
939 @Override | 927 @Override |
940 public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { | 928 public PreparedStatement prepareStatement(final String sql, final String[] columnNames) throws SQLException { |
941 throw newSQLFeatureNotSupportedException("prepareStatement(String sql, String[] columnNames)"); | 929 throw newSQLFeatureNotSupportedException("prepareStatement(String sql, String[] columnNames)"); |
942 } | 930 } |
943 | 931 |
944 /** | 932 /** |
945 * Removes the given Savepoint object from the current transaction. | 933 * Removes the given Savepoint object from the current transaction. |
950 * @throws SQLException if a database access error occurs or the given | 938 * @throws SQLException if a database access error occurs or the given |
951 * Savepoint object is not a valid savepoint in the current | 939 * Savepoint object is not a valid savepoint in the current |
952 * transaction | 940 * transaction |
953 */ | 941 */ |
954 @Override | 942 @Override |
955 public void releaseSavepoint(Savepoint savepoint) throws SQLException { | 943 public void releaseSavepoint(final Savepoint savepoint) throws SQLException { |
956 if (!(savepoint instanceof MonetSavepoint)) | 944 if (!(savepoint instanceof MonetSavepoint)) |
957 throw new SQLException("This driver can only handle savepoints it created itself", "M0M06"); | 945 throw new SQLException("This driver can only handle savepoints it created itself", "M0M06"); |
958 | 946 |
959 MonetSavepoint sp = (MonetSavepoint)savepoint; | 947 final MonetSavepoint sp = (MonetSavepoint)savepoint; |
960 | 948 |
961 // note: can't use sendIndependentCommand here because we need | 949 // note: can't use sendIndependentCommand here because we need |
962 // to process the auto_commit state the server gives | 950 // to process the auto_commit state the server gives |
963 sendTransactionCommand("RELEASE SAVEPOINT " + sp.getName()); | 951 sendTransactionCommand("RELEASE SAVEPOINT " + sp.getName()); |
964 } | 952 } |
988 * @throws SQLException if a database access error occurs, the | 976 * @throws SQLException if a database access error occurs, the |
989 * Savepoint object is no longer valid, or this Connection | 977 * Savepoint object is no longer valid, or this Connection |
990 * object is currently in auto-commit mode | 978 * object is currently in auto-commit mode |
991 */ | 979 */ |
992 @Override | 980 @Override |
993 public void rollback(Savepoint savepoint) throws SQLException { | 981 public void rollback(final Savepoint savepoint) throws SQLException { |
994 if (!(savepoint instanceof MonetSavepoint)) | 982 if (!(savepoint instanceof MonetSavepoint)) |
995 throw new SQLException("This driver can only handle savepoints it created itself", "M0M06"); | 983 throw new SQLException("This driver can only handle savepoints it created itself", "M0M06"); |
996 | 984 |
997 MonetSavepoint sp = (MonetSavepoint)savepoint; | 985 final MonetSavepoint sp = (MonetSavepoint)savepoint; |
998 | 986 |
999 // note: can't use sendIndependentCommand here because we need | 987 // note: can't use sendIndependentCommand here because we need |
1000 // to process the auto_commit state the server gives | 988 // to process the auto_commit state the server gives |
1001 sendTransactionCommand("ROLLBACK TO SAVEPOINT " + sp.getName()); | 989 sendTransactionCommand("ROLLBACK TO SAVEPOINT " + sp.getName()); |
1002 } | 990 } |
1024 * @param autoCommit true to enable auto-commit mode; false to disable it | 1012 * @param autoCommit true to enable auto-commit mode; false to disable it |
1025 * @throws SQLException if a database access error occurs | 1013 * @throws SQLException if a database access error occurs |
1026 * @see #getAutoCommit() | 1014 * @see #getAutoCommit() |
1027 */ | 1015 */ |
1028 @Override | 1016 @Override |
1029 public void setAutoCommit(boolean autoCommit) throws SQLException { | 1017 public void setAutoCommit(final boolean autoCommit) throws SQLException { |
1030 if (this.autoCommit != autoCommit) { | 1018 if (this.autoCommit != autoCommit) { |
1031 sendControlCommand("auto_commit " + (autoCommit ? "1" : "0")); | 1019 sendControlCommand("auto_commit " + (autoCommit ? "1" : "0")); |
1032 this.autoCommit = autoCommit; | 1020 this.autoCommit = autoCommit; |
1033 } | 1021 } |
1034 } | 1022 } |
1037 * Sets the given catalog name in order to select a subspace of this | 1025 * Sets the given catalog name in order to select a subspace of this |
1038 * Connection object's database in which to work. If the driver | 1026 * Connection object's database in which to work. If the driver |
1039 * does not support catalogs, it will silently ignore this request. | 1027 * does not support catalogs, it will silently ignore this request. |
1040 */ | 1028 */ |
1041 @Override | 1029 @Override |
1042 public void setCatalog(String catalog) { | 1030 public void setCatalog(final String catalog) { |
1043 // silently ignore this request as MonetDB does not support catalogs | 1031 // silently ignore this request as MonetDB does not support catalogs |
1044 } | 1032 } |
1045 | 1033 |
1046 /** | 1034 /** |
1047 * Changes the default holdability of ResultSet objects created using this | 1035 * Changes the default holdability of ResultSet objects created using this |
1054 * @throws SQLException - if a database access error occurs or this method is called on a closed connection | 1042 * @throws SQLException - if a database access error occurs or this method is called on a closed connection |
1055 * @throws SQLFeatureNotSupportedException - if the JDBC driver does not support this method or argument | 1043 * @throws SQLFeatureNotSupportedException - if the JDBC driver does not support this method or argument |
1056 * @see #getHoldability() | 1044 * @see #getHoldability() |
1057 */ | 1045 */ |
1058 @Override | 1046 @Override |
1059 public void setHoldability(int holdability) throws SQLException { | 1047 public void setHoldability(final int holdability) throws SQLException { |
1060 // we only support ResultSet.HOLD_CURSORS_OVER_COMMIT | 1048 // we only support ResultSet.HOLD_CURSORS_OVER_COMMIT |
1061 if (holdability != ResultSet.HOLD_CURSORS_OVER_COMMIT) | 1049 if (holdability != ResultSet.HOLD_CURSORS_OVER_COMMIT) |
1062 throw newSQLFeatureNotSupportedException("setHoldability(CLOSE_CURSORS_AT_COMMIT)"); | 1050 throw newSQLFeatureNotSupportedException("setHoldability(CLOSE_CURSORS_AT_COMMIT)"); |
1063 } | 1051 } |
1064 | 1052 |
1071 * @param readOnly true enables read-only mode; false disables it | 1059 * @param readOnly true enables read-only mode; false disables it |
1072 * @throws SQLException if a database access error occurs or this | 1060 * @throws SQLException if a database access error occurs or this |
1073 * method is called during a transaction. | 1061 * method is called during a transaction. |
1074 */ | 1062 */ |
1075 @Override | 1063 @Override |
1076 public void setReadOnly(boolean readOnly) throws SQLException { | 1064 public void setReadOnly(final boolean readOnly) throws SQLException { |
1077 if (readOnly == true) | 1065 if (readOnly == true) |
1078 addWarning("cannot setReadOnly(true): read-only Connection mode not supported", "01M08"); | 1066 addWarning("cannot setReadOnly(true): read-only Connection mode not supported", "01M08"); |
1079 } | 1067 } |
1080 | 1068 |
1081 /** | 1069 /** |
1087 * object is currently in auto-commit mode | 1075 * object is currently in auto-commit mode |
1088 */ | 1076 */ |
1089 @Override | 1077 @Override |
1090 public Savepoint setSavepoint() throws SQLException { | 1078 public Savepoint setSavepoint() throws SQLException { |
1091 // create a new Savepoint object | 1079 // create a new Savepoint object |
1092 MonetSavepoint sp = new MonetSavepoint(); | 1080 final MonetSavepoint sp = new MonetSavepoint(); |
1093 | 1081 |
1094 // note: can't use sendIndependentCommand here because we need | 1082 // note: can't use sendIndependentCommand here because we need |
1095 // to process the auto_commit state the server gives | 1083 // to process the auto_commit state the server gives |
1096 sendTransactionCommand("SAVEPOINT " + sp.getName()); | 1084 sendTransactionCommand("SAVEPOINT " + sp.getName()); |
1097 return sp; | 1085 return sp; |
1105 * @return the new Savepoint object | 1093 * @return the new Savepoint object |
1106 * @throws SQLException if a database access error occurs or this Connection | 1094 * @throws SQLException if a database access error occurs or this Connection |
1107 * object is currently in auto-commit mode | 1095 * object is currently in auto-commit mode |
1108 */ | 1096 */ |
1109 @Override | 1097 @Override |
1110 public Savepoint setSavepoint(String name) throws SQLException { | 1098 public Savepoint setSavepoint(final String name) throws SQLException { |
1111 // create a new Savepoint object | 1099 // create a new Savepoint object |
1112 MonetSavepoint sp; | 1100 final MonetSavepoint sp; |
1113 try { | 1101 try { |
1114 sp = new MonetSavepoint(name); | 1102 sp = new MonetSavepoint(name); |
1115 } catch (IllegalArgumentException e) { | 1103 } catch (IllegalArgumentException e) { |
1116 throw new SQLException(e.getMessage(), "M0M03"); | 1104 throw new SQLException(e.getMessage(), "M0M03"); |
1117 } | 1105 } |
1132 * Connection.TRANSACTION_READ_COMMITTED, | 1120 * Connection.TRANSACTION_READ_COMMITTED, |
1133 * Connection.TRANSACTION_REPEATABLE_READ, or | 1121 * Connection.TRANSACTION_REPEATABLE_READ, or |
1134 * Connection.TRANSACTION_SERIALIZABLE. | 1122 * Connection.TRANSACTION_SERIALIZABLE. |
1135 */ | 1123 */ |
1136 @Override | 1124 @Override |
1137 public void setTransactionIsolation(int level) { | 1125 public void setTransactionIsolation(final int level) { |
1138 if (level != TRANSACTION_SERIALIZABLE) { | 1126 if (level != TRANSACTION_SERIALIZABLE) { |
1139 addWarning("MonetDB only supports fully serializable " + | 1127 addWarning("MonetDB only supports fully serializable " + |
1140 "transactions, continuing with transaction level " + | 1128 "transactions, continuing with transaction level " + |
1141 "raised to TRANSACTION_SERIALIZABLE", "01M09"); | 1129 "raised to TRANSACTION_SERIALIZABLE", "01M09"); |
1142 } | 1130 } |
1149 * | 1137 * |
1150 * @param map the java.util.Map object to install as the replacement for | 1138 * @param map the java.util.Map object to install as the replacement for |
1151 * this Connection object's default type map | 1139 * this Connection object's default type map |
1152 */ | 1140 */ |
1153 @Override | 1141 @Override |
1154 public void setTypeMap(Map<String, Class<?>> map) { | 1142 public void setTypeMap(final Map<String, Class<?>> map) { |
1155 typeMap = map; | 1143 typeMap = map; |
1156 } | 1144 } |
1157 | 1145 |
1158 /** | 1146 /** |
1159 * Returns a string identifying this Connection to the MonetDB server. | 1147 * Returns a string identifying this Connection to the MonetDB server. |
1194 * the conversion is not supported, the typeName is null or this method is called on a closed connection | 1182 * the conversion is not supported, the typeName is null or this method is called on a closed connection |
1195 * @throws SQLFeatureNotSupportedException - if the JDBC driver does not support this data type | 1183 * @throws SQLFeatureNotSupportedException - if the JDBC driver does not support this data type |
1196 * @since 1.6 | 1184 * @since 1.6 |
1197 */ | 1185 */ |
1198 @Override | 1186 @Override |
1199 public java.sql.Array createArrayOf(String typeName, Object[] elements) throws SQLException { | 1187 public java.sql.Array createArrayOf(final String typeName, final Object[] elements) throws SQLException { |
1200 throw newSQLFeatureNotSupportedException("createArrayOf"); | 1188 throw newSQLFeatureNotSupportedException("createArrayOf"); |
1201 } | 1189 } |
1202 | 1190 |
1203 | 1191 |
1204 /** | 1192 /** |
1228 * this method is called on a closed connection or a database access error occurs. | 1216 * this method is called on a closed connection or a database access error occurs. |
1229 * @since 1.6 | 1217 * @since 1.6 |
1230 */ | 1218 */ |
1231 @Override | 1219 @Override |
1232 public java.sql.Blob createBlob() throws SQLException { | 1220 public java.sql.Blob createBlob() throws SQLException { |
1233 byte[] buf = new byte[1]; | 1221 return new MonetBlob(new byte[1]); |
1234 return new MonetBlob(buf); | |
1235 } | 1222 } |
1236 | 1223 |
1237 /** | 1224 /** |
1238 * Constructs an object that implements the NClob interface. The | 1225 * Constructs an object that implements the NClob interface. The |
1239 * object returned initially contains no data. The setAsciiStream, | 1226 * object returned initially contains no data. The setAsciiStream, |
1305 * @return true if the connection is valid, false otherwise | 1292 * @return true if the connection is valid, false otherwise |
1306 * @throws SQLException if the value supplied for timeout is less than 0 | 1293 * @throws SQLException if the value supplied for timeout is less than 0 |
1307 * @since 1.6 | 1294 * @since 1.6 |
1308 */ | 1295 */ |
1309 @Override | 1296 @Override |
1310 public boolean isValid(int timeout) throws SQLException { | 1297 public boolean isValid(final int timeout) throws SQLException { |
1311 if (timeout < 0) | 1298 if (timeout < 0) |
1312 throw new SQLException("timeout is less than 0", "M1M05"); | 1299 throw new SQLException("timeout is less than 0", "M1M05"); |
1313 if (closed) | 1300 if (closed) |
1314 return false; | 1301 return false; |
1315 | 1302 |
1318 ResultSet rs = null; | 1305 ResultSet rs = null; |
1319 boolean isValid = false; | 1306 boolean isValid = false; |
1320 try { | 1307 try { |
1321 stmt = createStatement(); | 1308 stmt = createStatement(); |
1322 if (stmt != null) { | 1309 if (stmt != null) { |
1323 int original_timeout = stmt.getQueryTimeout(); | 1310 final int original_timeout = stmt.getQueryTimeout(); |
1324 if (timeout > 0 && original_timeout != timeout) { | 1311 if (timeout > 0 && original_timeout != timeout) { |
1325 // we need to change the requested timeout for this test query | 1312 // we need to change the requested timeout for this test query |
1326 stmt.setQueryTimeout(timeout); | 1313 stmt.setQueryTimeout(timeout); |
1327 } | 1314 } |
1328 rs = stmt.executeQuery("SELECT 1"); | 1315 rs = stmt.executeQuery("SELECT 1"); |
1374 * when fetching the client info value from the database | 1361 * when fetching the client info value from the database |
1375 * or this method is called on a closed connection | 1362 * or this method is called on a closed connection |
1376 * @since 1.6 | 1363 * @since 1.6 |
1377 */ | 1364 */ |
1378 @Override | 1365 @Override |
1379 public String getClientInfo(String name) throws SQLException { | 1366 public String getClientInfo(final String name) throws SQLException { |
1380 if (name == null || name.isEmpty()) | 1367 if (name == null || name.isEmpty()) |
1381 return null; | 1368 return null; |
1382 return conn_props.getProperty(name); | 1369 return conn_props.getProperty(name); |
1383 } | 1370 } |
1384 | 1371 |
1435 * while setting the clientInfo values on the database server | 1422 * while setting the clientInfo values on the database server |
1436 * or this method is called on a closed connection | 1423 * or this method is called on a closed connection |
1437 * @since 1.6 | 1424 * @since 1.6 |
1438 */ | 1425 */ |
1439 @Override | 1426 @Override |
1440 public void setClientInfo(String name, String value) throws SQLClientInfoException { | 1427 public void setClientInfo(final String name, final String value) throws SQLClientInfoException { |
1441 if (name == null || name.isEmpty()) { | 1428 if (name == null || name.isEmpty()) { |
1442 addWarning("setClientInfo: missing property name", "01M07"); | 1429 addWarning("setClientInfo: missing property name", "01M07"); |
1443 return; | 1430 return; |
1444 } | 1431 } |
1445 // If the value is null, the current value of the specified property is cleared. | 1432 // If the value is null, the current value of the specified property is cleared. |
1463 { | 1450 { |
1464 conn_props.setProperty(name, value); | 1451 conn_props.setProperty(name, value); |
1465 } else { | 1452 } else { |
1466 addWarning("setClientInfo: " + name + "is not a recognised property", "01M07"); | 1453 addWarning("setClientInfo: " + name + "is not a recognised property", "01M07"); |
1467 } | 1454 } |
1468 return; | |
1469 } | 1455 } |
1470 | 1456 |
1471 /** | 1457 /** |
1472 * Sets the value of the connection's client info properties. | 1458 * Sets the value of the connection's client info properties. |
1473 * The Properties object contains the names and values of the client info | 1459 * The Properties object contains the names and values of the client info |
1490 * while setting the clientInfo values on the database server | 1476 * while setting the clientInfo values on the database server |
1491 * or this method is called on a closed connection | 1477 * or this method is called on a closed connection |
1492 * @since 1.6 | 1478 * @since 1.6 |
1493 */ | 1479 */ |
1494 @Override | 1480 @Override |
1495 public void setClientInfo(Properties props) throws SQLClientInfoException { | 1481 public void setClientInfo(final Properties props) throws SQLClientInfoException { |
1496 if (props != null) { | 1482 if (props != null) { |
1497 for (Entry<Object, Object> entry : props.entrySet()) { | 1483 for (Entry<Object, Object> entry : props.entrySet()) { |
1498 setClientInfo(entry.getKey().toString(), | 1484 setClientInfo(entry.getKey().toString(), entry.getValue().toString()); |
1499 entry.getValue().toString()); | |
1500 } | 1485 } |
1501 } | 1486 } |
1502 } | 1487 } |
1503 | 1488 |
1504 | 1489 |
1511 * @throws SQLException if a database access error occurs or this | 1496 * @throws SQLException if a database access error occurs or this |
1512 * method is called on a closed connection | 1497 * method is called on a closed connection |
1513 * @since 1.7 | 1498 * @since 1.7 |
1514 */ | 1499 */ |
1515 @Override | 1500 @Override |
1516 public void setSchema(String schema) throws SQLException { | 1501 public void setSchema(final String schema) throws SQLException { |
1517 if (closed) | 1502 if (closed) |
1518 throw new SQLException("Cannot call on closed Connection", "M1M20"); | 1503 throw new SQLException("Cannot call on closed Connection", "M1M20"); |
1519 if (schema == null || schema.isEmpty()) | 1504 if (schema == null || schema.isEmpty()) |
1520 throw new SQLException("Missing schema name", "M1M05"); | 1505 throw new SQLException("Missing schema name", "M1M05"); |
1521 | 1506 |
1595 * @throws SecurityException if a security manager exists and | 1580 * @throws SecurityException if a security manager exists and |
1596 * its checkPermission method denies calling abort | 1581 * its checkPermission method denies calling abort |
1597 * @since 1.7 | 1582 * @since 1.7 |
1598 */ | 1583 */ |
1599 @Override | 1584 @Override |
1600 public void abort(Executor executor) throws SQLException { | 1585 public void abort(final Executor executor) throws SQLException { |
1601 if (closed) | 1586 if (closed) |
1602 return; | 1587 return; |
1603 if (executor == null) | 1588 if (executor == null) |
1604 throw new SQLException("executor is null", "M1M05"); | 1589 throw new SQLException("executor is null", "M1M05"); |
1605 // this is really the simplest thing to do, it destroys | 1590 // this is really the simplest thing to do, it destroys |
1625 * method is called on a closed connection, the executor is | 1610 * method is called on a closed connection, the executor is |
1626 * null, or the value specified for seconds is less than 0. | 1611 * null, or the value specified for seconds is less than 0. |
1627 * @since 1.7 | 1612 * @since 1.7 |
1628 */ | 1613 */ |
1629 @Override | 1614 @Override |
1630 public void setNetworkTimeout(Executor executor, int millis) throws SQLException { | 1615 public void setNetworkTimeout(final Executor executor, final int millis) throws SQLException { |
1631 if (closed) | 1616 if (closed) |
1632 throw new SQLException("Cannot call on closed Connection", "M1M20"); | 1617 throw new SQLException("Cannot call on closed Connection", "M1M20"); |
1633 if (executor == null) | 1618 if (executor == null) |
1634 throw new SQLException("executor is null", "M1M05"); | 1619 throw new SQLException("executor is null", "M1M05"); |
1635 if (millis < 0) | 1620 if (millis < 0) |
1672 /** | 1657 /** |
1673 * @return the MonetDB JDBC Connection URL (without user name and password). | 1658 * @return the MonetDB JDBC Connection URL (without user name and password). |
1674 * Defined as public because it is called from: MonetDatabaseMetaData.java getURL() | 1659 * Defined as public because it is called from: MonetDatabaseMetaData.java getURL() |
1675 */ | 1660 */ |
1676 String getJDBCURL() { | 1661 String getJDBCURL() { |
1677 String language = ""; | 1662 return MonetDriver.MONETURL + hostname + ":" + port + "/" + database + (lang == LANG_MAL ? "?language=mal" : ""); |
1678 if (lang == LANG_MAL) | |
1679 language = "?language=mal"; | |
1680 return MonetDriver.MONETURL + hostname + ":" + port + "/" + database + language; | |
1681 } | 1663 } |
1682 | 1664 |
1683 /** | 1665 /** |
1684 * @return whether the JDBC BLOB type should be mapped to VARBINARY type. | 1666 * @return whether the JDBC BLOB type should be mapped to VARBINARY type. |
1685 * This allows generic JDBC programs to fetch Blob data via getBytes() | 1667 * This allows generic JDBC programs to fetch Blob data via getBytes() |
1727 } | 1709 } |
1728 | 1710 |
1729 /** | 1711 /** |
1730 * Internal utility method to query the server to find out if it has the system table sys.<tablename>. | 1712 * Internal utility method to query the server to find out if it has the system table sys.<tablename>. |
1731 */ | 1713 */ |
1732 private boolean existsSysTable(String tablename) { | 1714 private boolean existsSysTable(final String tablename) { |
1733 boolean exists = false; | 1715 boolean exists = false; |
1734 Statement stmt = null; | 1716 Statement stmt = null; |
1735 ResultSet rs = null; | 1717 ResultSet rs = null; |
1736 try { | 1718 try { |
1737 stmt = createStatement(); | 1719 stmt = createStatement(); |
1767 * Encountered errors are reported. | 1749 * Encountered errors are reported. |
1768 * | 1750 * |
1769 * @param command the exact string to send to MonetDB | 1751 * @param command the exact string to send to MonetDB |
1770 * @throws SQLException if an IO exception or a database error occurs | 1752 * @throws SQLException if an IO exception or a database error occurs |
1771 */ | 1753 */ |
1772 private void sendTransactionCommand(String command) throws SQLException { | 1754 private void sendTransactionCommand(final String command) throws SQLException { |
1773 // create a container for the result | 1755 // create a container for the result |
1774 ResponseList l = new ResponseList(0, 0, ResultSet.FETCH_FORWARD, ResultSet.CONCUR_READ_ONLY); | 1756 final ResponseList l = new ResponseList(0, 0, ResultSet.FETCH_FORWARD, ResultSet.CONCUR_READ_ONLY); |
1775 // send the appropriate query string to the database | 1757 // send the appropriate query string to the database |
1776 try { | 1758 try { |
1777 l.processQuery(command); | 1759 l.processQuery(command); |
1778 } finally { | 1760 } finally { |
1779 l.close(); | 1761 l.close(); |
1812 * | 1794 * |
1813 * @param command the exact string to send to MonetDB | 1795 * @param command the exact string to send to MonetDB |
1814 * @param usequeryTempl send the command using a queryTempl? else it is send using commandTempl | 1796 * @param usequeryTempl send the command using a queryTempl? else it is send using commandTempl |
1815 * @throws SQLException if an IO exception or a database error occurs | 1797 * @throws SQLException if an IO exception or a database error occurs |
1816 */ | 1798 */ |
1817 private void sendCommand(String command, boolean usequeryTempl) throws SQLException { | 1799 private void sendCommand(final String command, final boolean usequeryTempl) throws SQLException { |
1818 String cmd = usequeryTempl ? | 1800 final String cmd = usequeryTempl |
1819 (queryTempl[0] == null ? "" : queryTempl[0]) + command + (queryTempl[1] == null ? "" : queryTempl[1]) | 1801 ? (queryTempl[0] == null ? "" : queryTempl[0]) + command + (queryTempl[1] == null ? "" : queryTempl[1]) |
1820 : | 1802 : (commandTempl[0] == null ? "" : commandTempl[0]) + command + (commandTempl[1] == null ? "" : commandTempl[1]); |
1821 (commandTempl[0] == null ? "" : commandTempl[0]) + command + (commandTempl[1] == null ? "" : commandTempl[1]); | |
1822 | 1803 |
1823 synchronized (server) { | 1804 synchronized (server) { |
1824 try { | 1805 try { |
1825 out.writeLine(cmd); | 1806 out.writeLine(cmd); |
1826 String error = in.waitForPrompt(); | 1807 final String error = in.waitForPrompt(); |
1827 if (error != null) | 1808 if (error != null) |
1828 throw new SQLException(error.substring(6), error.substring(0, 5)); | 1809 throw new SQLException(error.substring(6), error.substring(0, 5)); |
1829 } catch (SocketTimeoutException e) { | 1810 } catch (SocketTimeoutException e) { |
1830 close(); // JDBC 4.1 semantics, abort() | 1811 close(); // JDBC 4.1 semantics, abort() |
1831 throw new SQLNonTransientConnectionException("connection timed out", "08M33"); | 1812 throw new SQLNonTransientConnectionException("connection timed out", "08M33"); |
1841 * this warning will be the first, otherwise this warning will get | 1822 * this warning will be the first, otherwise this warning will get |
1842 * appended to the current warning. | 1823 * appended to the current warning. |
1843 * | 1824 * |
1844 * @param reason the warning message | 1825 * @param reason the warning message |
1845 */ | 1826 */ |
1846 void addWarning(String reason, String sqlstate) { | 1827 private final void addWarning(final String reason, final String sqlstate) { |
1847 SQLWarning warng = new SQLWarning(reason, sqlstate); | 1828 final SQLWarning warng = new SQLWarning(reason, sqlstate); |
1848 if (warnings == null) { | 1829 if (warnings == null) { |
1849 warnings = warng; | 1830 warnings = warng; |
1850 } else { | 1831 } else { |
1851 warnings.setNextWarning(warng); | 1832 warnings.setNextWarning(warng); |
1852 } | 1833 } |
1937 private boolean closed; | 1918 private boolean closed; |
1938 | 1919 |
1939 /** The Connection that we should use when requesting a new block */ | 1920 /** The Connection that we should use when requesting a new block */ |
1940 private final MonetConnection.ResponseList parent; | 1921 private final MonetConnection.ResponseList parent; |
1941 /** Whether the fetchSize was explitly set by the user */ | 1922 /** Whether the fetchSize was explitly set by the user */ |
1942 private boolean cacheSizeSetExplicitly = false; | 1923 private final boolean cacheSizeSetExplicitly; |
1943 /** Whether we should send an Xclose command to the server | 1924 /** Whether we should send an Xclose command to the server |
1944 * if we close this Response */ | 1925 * if we close this Response */ |
1945 private boolean destroyOnClose; | 1926 private boolean destroyOnClose; |
1946 /** the offset to be used on Xexport queries */ | 1927 /** the offset to be used on Xexport queries */ |
1947 private int blockOffset = 0; | 1928 private int blockOffset = 0; |
1948 | 1929 |
1949 /** A parser for header lines */ | 1930 /** A parser for header lines */ |
1950 HeaderLineParser hlp; | 1931 private final HeaderLineParser hlp; |
1951 | 1932 |
1952 /** A boolean array telling whether the headers are set or not */ | 1933 /** A boolean array telling whether the headers are set or not */ |
1953 private final boolean[] isSet; | 1934 private final boolean[] isSet; |
1954 private static final int NAMES = 0; | 1935 private static final int NAMES = 0; |
1955 private static final int TYPES = 1; | 1936 private static final int TYPES = 1; |
1968 * @param parent the parent that created this Response and will | 1949 * @param parent the parent that created this Response and will |
1969 * supply new result blocks when necessary | 1950 * supply new result blocks when necessary |
1970 * @param seq the query sequence number | 1951 * @param seq the query sequence number |
1971 */ | 1952 */ |
1972 ResultSetResponse( | 1953 ResultSetResponse( |
1973 int id, | 1954 final int id, |
1974 int tuplecount, | 1955 final int tuplecount, |
1975 int columncount, | 1956 final int columncount, |
1976 int rowcount, | 1957 final int rowcount, |
1977 MonetConnection.ResponseList parent, | 1958 final MonetConnection.ResponseList parent, |
1978 int seq) | 1959 final int seq) |
1979 throws SQLException | 1960 throws SQLException |
1980 { | 1961 { |
1981 isSet = new boolean[4]; | 1962 isSet = new boolean[4]; |
1982 this.parent = parent; | 1963 this.parent = parent; |
1983 if (parent.cachesize == 0) { | 1964 if (parent.cachesize == 0) { |
2024 * @return a non-null String if the header cannot be parsed or | 2005 * @return a non-null String if the header cannot be parsed or |
2025 * is unknown | 2006 * is unknown |
2026 */ | 2007 */ |
2027 // {{{ addLine | 2008 // {{{ addLine |
2028 @Override | 2009 @Override |
2029 public String addLine(String tmpLine, int linetype) { | 2010 public String addLine(final String tmpLine, final int linetype) { |
2030 if (isSet[LENS] && isSet[TYPES] && isSet[TABLES] && isSet[NAMES]) { | 2011 if (isSet[LENS] && isSet[TYPES] && isSet[TABLES] && isSet[NAMES]) { |
2031 return resultBlocks[0].addLine(tmpLine, linetype); | 2012 return resultBlocks[0].addLine(tmpLine, linetype); |
2032 } | 2013 } |
2033 | 2014 |
2034 if (linetype != BufferedMCLReader.HEADER) | 2015 if (linetype != BufferedMCLReader.HEADER) |
2084 * @param chrLine a character array holding the input data | 2065 * @param chrLine a character array holding the input data |
2085 * @param start where the relevant data starts | 2066 * @param start where the relevant data starts |
2086 * @param stop where the relevant data stops | 2067 * @param stop where the relevant data stops |
2087 * @return an array of Strings | 2068 * @return an array of Strings |
2088 */ | 2069 */ |
2089 private final String[] getValues(char[] chrLine, int start, int stop) { | 2070 private final String[] getValues(final char[] chrLine, int start, final int stop) { |
2090 int elem = 0; | 2071 int elem = 0; |
2091 String[] values = new String[columncount]; | 2072 final String[] values = new String[columncount]; |
2092 | 2073 |
2093 for (int i = start; i < stop; i++) { | 2074 for (int i = start; i < stop; i++) { |
2094 if (chrLine[i] == '\t' && chrLine[i - 1] == ',') { | 2075 if (chrLine[i] == '\t' && chrLine[i - 1] == ',') { |
2095 values[elem++] = | 2076 values[elem++] = |
2096 new String(chrLine, start, i - 1 - start); | 2077 new String(chrLine, start, i - 1 - start); |
2108 * the given block position. | 2089 * the given block position. |
2109 * | 2090 * |
2110 * @param offset the offset number of rows for this block | 2091 * @param offset the offset number of rows for this block |
2111 * @param rr the DataBlockResponse to add | 2092 * @param rr the DataBlockResponse to add |
2112 */ | 2093 */ |
2113 void addDataBlockResponse(int offset, DataBlockResponse rr) { | 2094 void addDataBlockResponse(final int offset, final DataBlockResponse rr) { |
2114 int block = (offset - blockOffset) / cacheSize; | 2095 final int block = (offset - blockOffset) / cacheSize; |
2115 resultBlocks[block] = rr; | 2096 resultBlocks[block] = rr; |
2116 } | 2097 } |
2117 | 2098 |
2118 /** | 2099 /** |
2119 * Marks this Response as being completed. A complete Response | 2100 * Marks this Response as being completed. A complete Response |
2122 * @throws SQLException if the data currently in this Response is not | 2103 * @throws SQLException if the data currently in this Response is not |
2123 * sufficient to be consistant | 2104 * sufficient to be consistant |
2124 */ | 2105 */ |
2125 @Override | 2106 @Override |
2126 public void complete() throws SQLException { | 2107 public void complete() throws SQLException { |
2127 String error = ""; | 2108 final StringBuilder err = new StringBuilder(99); |
2128 if (!isSet[NAMES]) error = "name header missing\n"; | 2109 if (!isSet[NAMES]) err.append("name header missing\n"); |
2129 if (!isSet[TYPES]) error += "type header missing\n"; | 2110 if (!isSet[TYPES]) err.append("type header missing\n"); |
2130 if (!isSet[TABLES]) error += "table name header missing\n"; | 2111 if (!isSet[TABLES]) err.append("table name header missing\n"); |
2131 if (!isSet[LENS]) error += "column width header missing\n"; | 2112 if (!isSet[LENS]) err.append("column width header missing\n"); |
2132 if (!error.isEmpty()) | 2113 if (err.length() > 0) |
2133 throw new SQLException(error, "M0M10"); | 2114 throw new SQLException(err.toString(), "M0M10"); |
2134 } | 2115 } |
2135 | 2116 |
2136 /** | 2117 /** |
2137 * Returns the names of the columns | 2118 * Returns the names of the columns |
2138 * | 2119 * |
2214 * @param row the row in the result set to return | 2195 * @param row the row in the result set to return |
2215 * @return the exact row read as requested or null if the requested row | 2196 * @return the exact row read as requested or null if the requested row |
2216 * is out of the scope of the result set | 2197 * is out of the scope of the result set |
2217 * @throws SQLException if an database error occurs | 2198 * @throws SQLException if an database error occurs |
2218 */ | 2199 */ |
2219 String getLine(int row) throws SQLException { | 2200 String getLine(final int row) throws SQLException { |
2220 if (row >= tuplecount || row < 0) | 2201 if (row >= tuplecount || row < 0) |
2221 return null; | 2202 return null; |
2222 | 2203 |
2223 int block = (row - blockOffset) / cacheSize; | 2204 int block = (row - blockOffset) / cacheSize; |
2224 int blockLine = (row - blockOffset) % cacheSize; | 2205 int blockLine = (row - blockOffset) % cacheSize; |
2343 private final String[] data; | 2324 private final String[] data; |
2344 | 2325 |
2345 /** The counter which keeps the current position in the data array */ | 2326 /** The counter which keeps the current position in the data array */ |
2346 private int pos; | 2327 private int pos; |
2347 /** Whether we can discard lines as soon as we have read them */ | 2328 /** Whether we can discard lines as soon as we have read them */ |
2348 private boolean forwardOnly; | 2329 private final boolean forwardOnly; |
2349 | 2330 |
2350 /** | 2331 /** |
2351 * Constructs a DataBlockResponse object | 2332 * Constructs a DataBlockResponse object |
2352 * @param size the size of the data array to create | 2333 * @param size the size of the data array to create |
2353 * @param forward whether this is a forward only result | 2334 * @param forward whether this is a forward only result |
2354 */ | 2335 */ |
2355 DataBlockResponse(int size, boolean forward) { | 2336 DataBlockResponse(final int size, final boolean forward) { |
2356 pos = -1; | 2337 pos = -1; |
2357 data = new String[size]; | 2338 data = new String[size]; |
2358 forwardOnly = forward; | 2339 forwardOnly = forward; |
2359 } | 2340 } |
2360 | 2341 |
2368 * @param linetype the line type according to the MAPI protocol | 2349 * @param linetype the line type according to the MAPI protocol |
2369 * @return a non-null String if the line is invalid, | 2350 * @return a non-null String if the line is invalid, |
2370 * or additional lines are not allowed. | 2351 * or additional lines are not allowed. |
2371 */ | 2352 */ |
2372 @Override | 2353 @Override |
2373 public String addLine(String line, int linetype) { | 2354 public String addLine(final String line, final int linetype) { |
2374 if (linetype != BufferedMCLReader.RESULT) | 2355 if (linetype != BufferedMCLReader.RESULT) |
2375 return "protocol violation: unexpected line in data block: " + line; | 2356 return "protocol violation: unexpected line in data block: " + line; |
2376 // add to the backing array | 2357 // add to the backing array |
2377 data[++pos] = line; | 2358 data[++pos] = line; |
2378 | 2359 |
2401 * @throws SQLException if not all rows are filled | 2382 * @throws SQLException if not all rows are filled |
2402 */ | 2383 */ |
2403 @Override | 2384 @Override |
2404 public void complete() throws SQLException { | 2385 public void complete() throws SQLException { |
2405 if ((pos + 1) != data.length) | 2386 if ((pos + 1) != data.length) |
2406 throw new SQLException("Inconsistent state detected! Current block capacity: " | 2387 throw new SQLException("Inconsistent state detected! Current block capacity: " |
2407 + data.length + ", block usage: " + (pos + 1) + ". Did MonetDB send what it promised to?", "M0M10"); | 2388 + data.length + ", block usage: " + (pos + 1) |
2389 + ". Did MonetDB send what it promised to?", "M0M10"); | |
2408 } | 2390 } |
2409 | 2391 |
2410 /** | 2392 /** |
2411 * Instructs the Response implementation to close and do the | 2393 * Instructs the Response implementation to close and do the |
2412 * necessary clean up procedures. | 2394 * necessary clean up procedures. |
2413 */ | 2395 */ |
2414 @Override | 2396 @Override |
2415 public void close() { | 2397 public void close() { |
2416 // feed all rows to the garbage collector | 2398 // feed all rows to the garbage collector |
2417 for (int i = 0; i < data.length; i++) data[i] = null; | 2399 for (int i = 0; i < data.length; i++) |
2400 data[i] = null; | |
2418 } | 2401 } |
2419 | 2402 |
2420 /** | 2403 /** |
2421 * Retrieves the required row. Warning: if the requested rows | 2404 * Retrieves the required row. Warning: if the requested rows |
2422 * is out of bounds, an IndexOutOfBoundsException will be | 2405 * is out of bounds, an IndexOutOfBoundsException will be |
2423 * thrown. | 2406 * thrown. |
2424 * | 2407 * |
2425 * @param line the row to retrieve | 2408 * @param line the row to retrieve |
2426 * @return the requested row as String | 2409 * @return the requested row as String |
2427 */ | 2410 */ |
2428 String getRow(int line) { | 2411 String getRow(final int line) { |
2429 if (forwardOnly) { | 2412 if (forwardOnly) { |
2430 String ret = data[line]; | 2413 final String ret = data[line]; |
2431 data[line] = null; | 2414 data[line] = null; |
2432 return ret; | 2415 return ret; |
2433 } else { | 2416 } else { |
2434 return data[line]; | 2417 return data[line]; |
2435 } | 2418 } |
2448 // {{{ UpdateResponse class implementation | 2431 // {{{ UpdateResponse class implementation |
2449 static class UpdateResponse implements Response { | 2432 static class UpdateResponse implements Response { |
2450 public final int count; | 2433 public final int count; |
2451 public final String lastid; | 2434 public final String lastid; |
2452 | 2435 |
2453 public UpdateResponse(int cnt, String id) { | 2436 public UpdateResponse(final int cnt, final String id) { |
2454 // fill the blank finals | 2437 // fill the blank finals |
2455 this.count = cnt; | 2438 this.count = cnt; |
2456 this.lastid = id; | 2439 this.lastid = id; |
2457 } | 2440 } |
2458 | 2441 |
2459 @Override | 2442 @Override |
2460 public String addLine(String line, int linetype) { | 2443 public String addLine(final String line, final int linetype) { |
2461 return "Header lines are not supported for an UpdateResponse"; | 2444 return "Header lines are not supported for an UpdateResponse"; |
2462 } | 2445 } |
2463 | 2446 |
2464 @Override | 2447 @Override |
2465 public boolean wantsMore() { | 2448 public boolean wantsMore() { |
2490 // {{{ SchemaResponse class implementation | 2473 // {{{ SchemaResponse class implementation |
2491 class SchemaResponse implements Response { | 2474 class SchemaResponse implements Response { |
2492 public final int state = Statement.SUCCESS_NO_INFO; | 2475 public final int state = Statement.SUCCESS_NO_INFO; |
2493 | 2476 |
2494 @Override | 2477 @Override |
2495 public String addLine(String line, int linetype) { | 2478 public String addLine(final String line, final int linetype) { |
2496 return "Header lines are not supported for a SchemaResponse"; | 2479 return "Header lines are not supported for a SchemaResponse"; |
2497 } | 2480 } |
2498 | 2481 |
2499 @Override | 2482 @Override |
2500 public boolean wantsMore() { | 2483 public boolean wantsMore() { |
2520 */ | 2503 */ |
2521 // {{{ AutoCommitResponse class implementation | 2504 // {{{ AutoCommitResponse class implementation |
2522 class AutoCommitResponse extends SchemaResponse { | 2505 class AutoCommitResponse extends SchemaResponse { |
2523 public final boolean autocommit; | 2506 public final boolean autocommit; |
2524 | 2507 |
2525 public AutoCommitResponse(boolean ac) { | 2508 public AutoCommitResponse(final boolean ac) { |
2526 // fill the blank final | 2509 // fill the blank final |
2527 this.autocommit = ac; | 2510 this.autocommit = ac; |
2528 } | 2511 } |
2529 } | 2512 } |
2530 // }}} | 2513 // }}} |
2546 private final int rsconcur; | 2529 private final int rsconcur; |
2547 /** The sequence number of this ResponseList */ | 2530 /** The sequence number of this ResponseList */ |
2548 private final int seqnr; | 2531 private final int seqnr; |
2549 /** A list of the Responses associated with the query, | 2532 /** A list of the Responses associated with the query, |
2550 * in the right order */ | 2533 * in the right order */ |
2551 private List<Response> responses; | 2534 private final ArrayList<Response> responses; |
2552 /** A map of ResultSetResponses, used for additional | 2535 /** A map of ResultSetResponses, used for additional |
2553 * DataBlockResponse mapping */ | 2536 * DataBlockResponse mapping */ |
2554 private Map<Integer, ResultSetResponse> rsresponses; | 2537 private HashMap<Integer, ResultSetResponse> rsresponses; |
2555 | 2538 |
2556 /** The current header returned by getNextResponse() */ | 2539 /** The current header returned by getNextResponse() */ |
2557 private int curResponse; | 2540 private int curResponse; |
2558 | 2541 |
2559 /** | 2542 /** |
2565 * @param maxrows maximum number of rows to allow in the set | 2548 * @param maxrows maximum number of rows to allow in the set |
2566 * @param rstype the type of result sets to produce | 2549 * @param rstype the type of result sets to produce |
2567 * @param rsconcur the concurrency of result sets to produce | 2550 * @param rsconcur the concurrency of result sets to produce |
2568 */ | 2551 */ |
2569 ResponseList( | 2552 ResponseList( |
2570 int cachesize, | 2553 final int cachesize, |
2571 int maxrows, | 2554 final int maxrows, |
2572 int rstype, | 2555 final int rstype, |
2573 int rsconcur | 2556 final int rsconcur |
2574 ) throws SQLException { | 2557 ) throws SQLException { |
2575 this.cachesize = cachesize; | 2558 this.cachesize = cachesize; |
2576 this.maxrows = maxrows; | 2559 this.maxrows = maxrows; |
2577 this.rstype = rstype; | 2560 this.rstype = rstype; |
2578 this.rsconcur = rsconcur; | 2561 this.rsconcur = rsconcur; |
2589 */ | 2572 */ |
2590 Response getNextResponse() throws SQLException { | 2573 Response getNextResponse() throws SQLException { |
2591 if (rstype == ResultSet.TYPE_FORWARD_ONLY) { | 2574 if (rstype == ResultSet.TYPE_FORWARD_ONLY) { |
2592 // free resources if we're running forward only | 2575 // free resources if we're running forward only |
2593 if (curResponse >= 0 && curResponse < responses.size()) { | 2576 if (curResponse >= 0 && curResponse < responses.size()) { |
2594 Response tmp = responses.get(curResponse); | 2577 final Response tmp = responses.get(curResponse); |
2595 if (tmp != null) | 2578 if (tmp != null) |
2596 tmp.close(); | 2579 tmp.close(); |
2597 responses.set(curResponse, null); | 2580 responses.set(curResponse, null); |
2598 } | 2581 } |
2599 } | 2582 } |
2611 /** | 2594 /** |
2612 * Closes the Response at index i, if not null. | 2595 * Closes the Response at index i, if not null. |
2613 * | 2596 * |
2614 * @param i the index position of the header to close | 2597 * @param i the index position of the header to close |
2615 */ | 2598 */ |
2616 void closeResponse(int i) { | 2599 void closeResponse(final int i) { |
2617 if (i < 0 || i >= responses.size()) | 2600 if (i < 0 || i >= responses.size()) |
2618 return; | 2601 return; |
2619 Response tmp = responses.set(i, null); | 2602 final Response tmp = responses.set(i, null); |
2620 if (tmp != null) | 2603 if (tmp != null) |
2621 tmp.close(); | 2604 tmp.close(); |
2622 } | 2605 } |
2623 | 2606 |
2624 /** | 2607 /** |
2664 * stores the Responses resulting from this query in this | 2647 * stores the Responses resulting from this query in this |
2665 * ResponseList. | 2648 * ResponseList. |
2666 * | 2649 * |
2667 * @throws SQLException if a database error occurs | 2650 * @throws SQLException if a database error occurs |
2668 */ | 2651 */ |
2669 void processQuery(String query) throws SQLException { | 2652 void processQuery(final String query) throws SQLException { |
2670 executeQuery(queryTempl, query); | 2653 executeQuery(queryTempl, query); |
2671 } | 2654 } |
2672 | 2655 |
2673 /** | 2656 /** |
2674 * Internal executor of queries. | 2657 * Internal executor of queries. |
2676 * @param templ the template to fill in | 2659 * @param templ the template to fill in |
2677 * @param the query to execute | 2660 * @param the query to execute |
2678 * @throws SQLException if a database error occurs | 2661 * @throws SQLException if a database error occurs |
2679 */ | 2662 */ |
2680 @SuppressWarnings("fallthrough") | 2663 @SuppressWarnings("fallthrough") |
2681 void executeQuery(String[] templ, String query) | 2664 void executeQuery(final String[] templ, final String query) |
2682 throws SQLException | 2665 throws SQLException |
2683 { | 2666 { |
2684 String error = null; | 2667 String error = null; |
2685 | 2668 |
2686 try { | 2669 try { |
2726 switch (sohp.parse(tmpLine)) { | 2709 switch (sohp.parse(tmpLine)) { |
2727 case StartOfHeaderParser.Q_PARSE: | 2710 case StartOfHeaderParser.Q_PARSE: |
2728 throw new MCLParseException("Q_PARSE header not allowed here", 1); | 2711 throw new MCLParseException("Q_PARSE header not allowed here", 1); |
2729 case StartOfHeaderParser.Q_TABLE: | 2712 case StartOfHeaderParser.Q_TABLE: |
2730 case StartOfHeaderParser.Q_PREPARE: { | 2713 case StartOfHeaderParser.Q_PREPARE: { |
2731 int id = sohp.getNextAsInt(); | 2714 final int id = sohp.getNextAsInt(); |
2732 int tuplecount = sohp.getNextAsInt(); | 2715 int tuplecount = sohp.getNextAsInt(); |
2733 int columncount = sohp.getNextAsInt(); | 2716 final int columncount = sohp.getNextAsInt(); |
2734 int rowcount = sohp.getNextAsInt(); | 2717 final int rowcount = sohp.getNextAsInt(); |
2735 // enforce the maxrows setting | 2718 // enforce the maxrows setting |
2736 if (maxrows != 0 && tuplecount > maxrows) | 2719 if (maxrows != 0 && tuplecount > maxrows) |
2737 tuplecount = maxrows; | 2720 tuplecount = maxrows; |
2738 res = new ResultSetResponse(id, tuplecount, columncount, rowcount, this, seqnr); | 2721 res = new ResultSetResponse(id, tuplecount, columncount, rowcount, this, seqnr); |
2739 // only add this resultset to the hashmap if it can possibly have an additional datablock | 2722 // only add this resultset to the hashmap if it can possibly have an additional datablock |
2750 break; | 2733 break; |
2751 case StartOfHeaderParser.Q_SCHEMA: | 2734 case StartOfHeaderParser.Q_SCHEMA: |
2752 res = new SchemaResponse(); | 2735 res = new SchemaResponse(); |
2753 break; | 2736 break; |
2754 case StartOfHeaderParser.Q_TRANS: | 2737 case StartOfHeaderParser.Q_TRANS: |
2755 boolean ac = sohp.getNextAsString().equals("t") ? true : false; | 2738 final boolean ac = sohp.getNextAsString().equals("t") ? true : false; |
2756 if (autoCommit && ac) { | 2739 if (autoCommit && ac) { |
2757 addWarning("Server enabled auto commit mode " + | 2740 addWarning("Server enabled auto commit mode " + |
2758 "while local state already was auto commit.", "01M11"); | 2741 "while local state already was auto commit.", "01M11"); |
2759 } | 2742 } |
2760 autoCommit = ac; | 2743 autoCommit = ac; |
2761 res = new AutoCommitResponse(ac); | 2744 res = new AutoCommitResponse(ac); |
2762 break; | 2745 break; |
2763 case StartOfHeaderParser.Q_BLOCK: { | 2746 case StartOfHeaderParser.Q_BLOCK: { |
2764 // a new block of results for a response... | 2747 // a new block of results for a response... |
2765 int id = sohp.getNextAsInt(); | 2748 final int id = sohp.getNextAsInt(); |
2766 sohp.getNextAsInt(); // columncount | 2749 sohp.getNextAsInt(); // columncount |
2767 int rowcount = sohp.getNextAsInt(); | 2750 final int rowcount = sohp.getNextAsInt(); |
2768 int offset = sohp.getNextAsInt(); | 2751 final int offset = sohp.getNextAsInt(); |
2769 ResultSetResponse t = rsresponses.get(Integer.valueOf(id)); | 2752 final ResultSetResponse t = (rsresponses != null) ? rsresponses.get(Integer.valueOf(id)) : null; |
2770 if (t == null) { | 2753 if (t == null) { |
2771 error = "M0M12!no ResultSetResponse with id " + id + " found"; | 2754 error = "M0M12!no ResultSetResponse with id " + id + " found"; |
2772 break; | 2755 break; |
2773 } | 2756 } |
2774 DataBlockResponse r = new DataBlockResponse(rowcount, t.getRSType() == ResultSet.TYPE_FORWARD_ONLY); | 2757 final DataBlockResponse r = new DataBlockResponse(rowcount, t.getRSType() == ResultSet.TYPE_FORWARD_ONLY); |
2775 t.addDataBlockResponse(offset, r); | 2758 t.addDataBlockResponse(offset, r); |
2776 res = r; | 2759 res = r; |
2777 } break; | 2760 } break; |
2778 } // end of switch (sohp.parse(tmpLine)) | 2761 } // end of switch (sohp.parse(tmpLine)) |
2779 } catch (MCLParseException e) { | 2762 } catch (MCLParseException e) { |
2847 } // end of while (linetype != BufferedMCLReader.PROMPT) | 2830 } // end of while (linetype != BufferedMCLReader.PROMPT) |
2848 } // end of synchronized (server) | 2831 } // end of synchronized (server) |
2849 | 2832 |
2850 if (error != null) { | 2833 if (error != null) { |
2851 SQLException ret = null; | 2834 SQLException ret = null; |
2852 String[] errors = error.split("\n"); | 2835 final String[] errors = error.split("\n"); |
2853 for (int i = 0; i < errors.length; i++) { | 2836 for (int i = 0; i < errors.length; i++) { |
2854 SQLException newErr; | 2837 final SQLException newErr; |
2855 if (errors[i].length() >= 6) { | 2838 if (errors[i].length() >= 6) { |
2856 newErr = new SQLException(errors[i].substring(6), errors[i].substring(0, 5)); | 2839 newErr = new SQLException(errors[i].substring(6), errors[i].substring(0, 5)); |
2857 } else { | 2840 } else { |
2858 newErr = new SQLNonTransientConnectionException(errors[i], "08000"); | 2841 newErr = new SQLNonTransientConnectionException(errors[i], "08000"); |
2859 } | 2842 } |