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 }