comparison src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java @ 45:c2bf983dc79b

Implemented Connection methods: getClientInfo(name) and getClientInfo(). They used to return null and empty Properties object. Improved robustness and error reporting when processing property values in Connection constructor. Added @since 1.6 and @since 1.7 tags for methods introduced in those java versions. Rearranged place of 1.6 and 1.7 methods implementation code to match the order as used in http://docs.oracle.com/javase/7/docs/api/java/sql/Connection.html The 1.6 (JDBC 4.0) and 1.7 (JDBC 4.1) methods are now listed at the end of the source file. Removed unneeded trailing spaces (mostly in comment lines)
author Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
date Thu, 10 Nov 2016 18:07:59 +0100 (2016-11-10)
parents 5ec116ba7d71
children 562dbfb2fee8
comparison
equal deleted inserted replaced
29:c26213e86442 45:c2bf983dc79b
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.sql.Array;
16 import java.sql.Blob;
17 import java.sql.CallableStatement; 15 import java.sql.CallableStatement;
18 import java.sql.Clob;
19 import java.sql.Connection; 16 import java.sql.Connection;
20 import java.sql.DatabaseMetaData; 17 import java.sql.DatabaseMetaData;
21 import java.sql.NClob;
22 import java.sql.PreparedStatement; 18 import java.sql.PreparedStatement;
23 import java.sql.ResultSet; 19 import java.sql.ResultSet;
24 import java.sql.SQLException; 20 import java.sql.SQLException;
25 import java.sql.SQLFeatureNotSupportedException; 21 import java.sql.SQLFeatureNotSupportedException;
26 import java.sql.SQLWarning; 22 import java.sql.SQLWarning;
27 import java.sql.SQLXML;
28 import java.sql.Savepoint; 23 import java.sql.Savepoint;
29 import java.sql.Statement; 24 import java.sql.Statement;
30 import java.sql.Struct;
31 import java.util.ArrayList; 25 import java.util.ArrayList;
32 import java.util.Calendar; 26 import java.util.Calendar;
33 import java.util.HashMap; 27 import java.util.HashMap;
34 import java.util.List; 28 import java.util.List;
35 import java.util.Map; 29 import java.util.Map;
51 import nl.cwi.monetdb.mcl.parser.MCLParseException; 45 import nl.cwi.monetdb.mcl.parser.MCLParseException;
52 import nl.cwi.monetdb.mcl.parser.StartOfHeaderParser; 46 import nl.cwi.monetdb.mcl.parser.StartOfHeaderParser;
53 47
54 /** 48 /**
55 * A {@link Connection} suitable for the MonetDB database. 49 * A {@link Connection} suitable for the MonetDB database.
56 * 50 *
57 * This connection represents a connection (session) to a MonetDB 51 * This connection represents a connection (session) to a MonetDB
58 * database. SQL statements are executed and results are returned within 52 * database. SQL statements are executed and results are returned within
59 * the context of a connection. This Connection object holds a physical 53 * the context of a connection. This Connection object holds a physical
60 * connection to the MonetDB database. 54 * connection to the MonetDB database.
61 * 55 *
62 * A Connection object's database should able to provide information 56 * A Connection object's database should able to provide information
63 * describing its tables, its supported SQL grammar, its stored 57 * describing its tables, its supported SQL grammar, its stored
64 * procedures, the capabilities of this connection, and so on. This 58 * procedures, the capabilities of this connection, and so on. This
65 * information is obtained with the getMetaData method. 59 * information is obtained with the getMetaData method.
66 * 60 *
67 * Note: By default a Connection object is in auto-commit mode, which 61 * Note: By default a Connection object is in auto-commit mode, which
68 * means that it automatically commits changes after executing each 62 * means that it automatically commits changes after executing each
69 * statement. If auto-commit mode has been disabled, the method commit 63 * statement. If auto-commit mode has been disabled, the method commit
70 * must be called explicitly in order to commit changes; otherwise, 64 * must be called explicitly in order to commit changes; otherwise,
71 * database changes will not be saved. 65 * database changes will not be saved.
72 * 66 *
73 * The current state of this connection is that it nearly implements the 67 * The current state of this connection is that it nearly implements the
74 * whole Connection interface. 68 * whole Connection interface.
75 * 69 *
76 * @author Fabian Groffen 70 * @author Fabian Groffen
77 * @version 1.2 71 * @author Martin van Dinther
72 * @version 1.3
78 */ 73 */
79 public class MonetConnection extends MonetWrapper implements Connection { 74 public class MonetConnection extends MonetWrapper implements Connection {
75 /** the successful processed input properties */
76 private final Properties conn_props = new Properties();
77
80 /** The hostname to connect to */ 78 /** The hostname to connect to */
81 private final String hostname; 79 private final String hostname;
82 /** The port to connect on the host to */ 80 /** The port to connect on the host to */
83 private final int port; 81 private int port = 0;
84 /** The database to use (currently not used) */ 82 /** The database to use (currently not used) */
85 private final String database; 83 private final String database;
86 /** The username to use when authenticating */ 84 /** The username to use when authenticating */
87 private final String username; 85 private final String username;
88 /** The password to use when authenticating */ 86 /** The password to use when authenticating */
89 private final String password; 87 private final String password;
88
90 /** A connection to mserver5 using a TCP socket */ 89 /** A connection to mserver5 using a TCP socket */
91 private final MapiSocket server; 90 private final MapiSocket server;
92 /** The Reader from the server */ 91 /** The Reader from the server */
93 private final BufferedMCLReader in; 92 private final BufferedMCLReader in;
94 /** The Writer to the server */ 93 /** The Writer to the server */
105 104
106 /** The stack of warnings for this Connection object */ 105 /** The stack of warnings for this Connection object */
107 private SQLWarning warnings = null; 106 private SQLWarning warnings = null;
108 /** The Connection specific mapping of user defined types to Java 107 /** The Connection specific mapping of user defined types to Java
109 * types */ 108 * types */
110 private Map<String,Class<?>> typeMap = new HashMap<String,Class<?>>() {/** 109 private Map<String,Class<?>> typeMap = new HashMap<String,Class<?>>() {
111 *
112 */
113 private static final long serialVersionUID = 1L; 110 private static final long serialVersionUID = 1L;
114 { 111 {
115 put("inet", INET.class); 112 put("inet", INET.class);
116 put("url", URL.class); 113 put("url", URL.class);
117 } 114 }
123 private Map<Statement,?> statements = new WeakHashMap<Statement, Object>(); 120 private Map<Statement,?> statements = new WeakHashMap<Statement, Object>();
124 121
125 /** The number of results we receive from the server at once */ 122 /** The number of results we receive from the server at once */
126 private int curReplySize = -1; // the server by default uses -1 (all) 123 private int curReplySize = -1; // the server by default uses -1 (all)
127 124
128 /** A template to apply to each query (like pre and post fixes) */ 125 /** A template to apply to each query (like pre and post fixes), filled in constructor */
129 String[] queryTempl; 126 final String[] queryTempl = new String[3]; // pre, post, sep
130 /** A template to apply to each command (like pre and post fixes) */ 127
131 String[] commandTempl; 128 /** A template to apply to each command (like pre and post fixes), filled in constructor */
129 final String[] commandTempl = new String[3]; // pre, post, sep
132 130
133 /** the SQL language */ 131 /** the SQL language */
134 final static int LANG_SQL = 0; 132 final static int LANG_SQL = 0;
135 /** the MAL language (officially *NOT* supported) */ 133 /** the MAL language (officially *NOT* supported) */
136 final static int LANG_MAL = 3; 134 final static int LANG_MAL = 3;
147 * current implementation limits itself to storing the given host, 145 * current implementation limits itself to storing the given host,
148 * database, username and password for later use by the 146 * database, username and password for later use by the
149 * createStatement() call. This constructor is only accessible to 147 * createStatement() call. This constructor is only accessible to
150 * classes from the jdbc package. 148 * classes from the jdbc package.
151 * 149 *
152 * @param props a Property hashtable holding the properties needed for 150 * @param props a Property hashtable holding the properties needed for connecting
153 * connecting
154 * @throws SQLException if a database error occurs 151 * @throws SQLException if a database error occurs
155 * @throws IllegalArgumentException is one of the arguments is null or empty 152 * @throws IllegalArgumentException is one of the arguments is null or empty
156 */ 153 */
157 MonetConnection(Properties props) 154 MonetConnection(Properties props)
158 throws SQLException, IllegalArgumentException 155 throws SQLException, IllegalArgumentException
159 { 156 {
157 // get supported property values from the props argument.
158 // When a value is found add it to the internal conn_props list for use by getClientInfo().
160 this.hostname = props.getProperty("host"); 159 this.hostname = props.getProperty("host");
161 int port; 160 if (this.hostname != null)
162 try { 161 conn_props.setProperty("host", this.hostname);
163 port = Integer.parseInt(props.getProperty("port")); 162
164 } catch (NumberFormatException e) { 163 String port_prop = props.getProperty("port");
165 port = 0; 164 if (port_prop != null) {
166 } 165 try {
167 this.port = port; 166 this.port = Integer.parseInt(port_prop);
167 } catch (NumberFormatException e) {
168 addWarning("Unable to parse port number from: " + port_prop, "M1M05");
169 }
170 conn_props.setProperty("port", Integer.toString(this.port));
171 }
172
168 this.database = props.getProperty("database"); 173 this.database = props.getProperty("database");
174 if (this.database != null)
175 conn_props.setProperty("database", this.database);
176
169 this.username = props.getProperty("user"); 177 this.username = props.getProperty("user");
178 if (this.username != null)
179 conn_props.setProperty("user", this.username);
180
170 this.password = props.getProperty("password"); 181 this.password = props.getProperty("password");
182 if (this.password != null)
183 conn_props.setProperty("password", this.password);
184
171 String language = props.getProperty("language"); 185 String language = props.getProperty("language");
172 boolean debug = Boolean.valueOf(props.getProperty("debug")).booleanValue(); 186 if (language != null)
187 conn_props.setProperty("language", language);
188
189 boolean debug = false;
190 String debug_prop = props.getProperty("debug");
191 if (debug_prop != null) {
192 debug = Boolean.parseBoolean(debug_prop);
193 conn_props.setProperty("debug", Boolean.toString(debug));
194 }
195
173 String hash = props.getProperty("hash"); 196 String hash = props.getProperty("hash");
174 blobIsBinary = Boolean.valueOf(props.getProperty("treat_blob_as_binary")).booleanValue(); 197 if (hash != null)
198 conn_props.setProperty("hash", hash);
199
200 String blobIsBinary_prop = props.getProperty("treat_blob_as_binary");
201 if (blobIsBinary_prop != null) {
202 blobIsBinary = Boolean.parseBoolean(blobIsBinary_prop);
203 conn_props.setProperty("treat_blob_as_binary", Boolean.toString(blobIsBinary));
204 } else {
205 blobIsBinary = false;
206 }
207
175 int sockTimeout = 0; 208 int sockTimeout = 0;
176 try { 209 String so_timeout_prop = props.getProperty("so_timeout");
177 sockTimeout = Integer.parseInt(props.getProperty("so_timeout")); 210 if (so_timeout_prop != null) {
178 } catch (NumberFormatException e) { 211 try {
179 sockTimeout = 0; 212 sockTimeout = Integer.parseInt(so_timeout_prop);
180 } 213 if (sockTimeout < 0) {
181 // check input arguments 214 addWarning("Negative socket timeout not allowed. Value ignored", "M1M05");
182 if (hostname == null || hostname.trim().isEmpty()) 215 sockTimeout = 0;
183 throw new IllegalArgumentException("hostname should not be null or empty"); 216 }
184 if (port == 0) 217 } catch (NumberFormatException e) {
185 throw new IllegalArgumentException("port should not be 0"); 218 addWarning("Unable to parse socket timeout number from: " + so_timeout_prop, "M1M05");
186 if (username == null || username.trim().isEmpty()) 219 }
187 throw new IllegalArgumentException("user should not be null or empty"); 220 conn_props.setProperty("so_timeout", Integer.toString(sockTimeout));
188 if (password == null || password.trim().isEmpty()) 221 }
189 throw new IllegalArgumentException("password should not be null or empty"); 222
190 if (language == null || language.trim().isEmpty()) { 223 // check mandatory input arguments
224 if (hostname == null || hostname.isEmpty())
225 throw new IllegalArgumentException("Missing or empty host name");
226 if (port <= 0)
227 throw new IllegalArgumentException("Invalid port number. It should not be " + (port < 0 ? "negative" : "0"));
228 if (username == null || username.isEmpty())
229 throw new IllegalArgumentException("Missing or empty user name");
230 if (password == null || password.isEmpty())
231 throw new IllegalArgumentException("Missing or empty password");
232 if (language == null || language.isEmpty()) {
233 // fallback to default language: sql
191 language = "sql"; 234 language = "sql";
192 addWarning("No language given, defaulting to 'sql'", "M1M05"); 235 addWarning("No language specified, defaulting to 'sql'", "M1M05");
193 } 236 }
194
195 // initialise query templates (filled later, but needed below)
196 queryTempl = new String[3]; // pre, post, sep
197 commandTempl = new String[3]; // pre, post, sep
198 237
199 server = new MapiSocket(); 238 server = new MapiSocket();
200 239 if (hash != null)
201 if (hash != null) server.setHash(hash); 240 server.setHash(hash);
202 if (database != null) server.setDatabase(database); 241 if (database != null)
242 server.setDatabase(database);
203 server.setLanguage(language); 243 server.setLanguage(language);
204 244
205 // we're debugging here... uhm, should be off in real life 245 // we're debugging here... uhm, should be off in real life
206 if (debug) { 246 if (debug) {
207 try { 247 try {
208 String fname = props.getProperty("logfile", "monet_" + 248 String fname = props.getProperty("logfile", "monet_" +
209 System.currentTimeMillis() + ".log"); 249 System.currentTimeMillis() + ".log");
210 File f = new File(fname); 250 File f = new File(fname);
211 int ext = fname.lastIndexOf('.'); 251 int ext = fname.lastIndexOf('.');
212 if (ext < 0) ext = fname.length(); 252 if (ext < 0)
253 ext = fname.length();
213 String pre = fname.substring(0, ext); 254 String pre = fname.substring(0, ext);
214 String suf = fname.substring(ext); 255 String suf = fname.substring(ext);
215 256
216 for (int i = 1; f.exists(); i++) { 257 for (int i = 1; f.exists(); i++) {
217 f = new File(pre + "-" + i + suf); 258 f = new File(pre + "-" + i + suf);
222 throw new SQLException("Opening logfile failed: " + ex.getMessage(), "08M01"); 263 throw new SQLException("Opening logfile failed: " + ex.getMessage(), "08M01");
223 } 264 }
224 } 265 }
225 266
226 try { 267 try {
227 List<String> warnings = 268 List<String> warnings = server.connect(hostname, port, username, password);
228 server.connect(hostname, port, username, password);
229 for (String warning : warnings) { 269 for (String warning : warnings) {
230 addWarning(warning, "01M02"); 270 addWarning(warning, "01M02");
231 } 271 }
232 272
233 // apply NetworkTimeout value from legacy (pre 4.1) driver 273 // apply NetworkTimeout value from legacy (pre 4.1) driver
234 // so_timeout calls 274 // so_timeout calls
235 server.setSoTimeout(sockTimeout); 275 server.setSoTimeout(sockTimeout);
236 276
237 in = server.getReader(); 277 in = server.getReader();
238 out = server.getWriter(); 278 out = server.getWriter();
239 279
240 String error = in.waitForPrompt(); 280 String error = in.waitForPrompt();
241 if (error != null) 281 if (error != null)
242 throw new SQLException(error.substring(6), "08001"); 282 throw new SQLException((error.length() > 6) ? error.substring(6) : error, "08001");
243 } catch (IOException e) { 283 } catch (IOException e) {
244 throw new SQLException("Unable to connect (" + hostname + ":" + port + "): " + e.getMessage(), "08006"); 284 throw new SQLException("Unable to connect (" + hostname + ":" + port + "): " + e.getMessage(), "08006");
245 } catch (MCLParseException e) { 285 } catch (MCLParseException e) {
246 throw new SQLException(e.getMessage(), "08001"); 286 throw new SQLException(e.getMessage(), "08001");
247 } catch (MCLException e) { 287 } catch (MCLException e) {
252 } 292 }
253 throw sqle; 293 throw sqle;
254 } 294 }
255 295
256 // we seem to have managed to log in, let's store the 296 // we seem to have managed to log in, let's store the
257 // language used 297 // language used and language specific query templates
258 if ("sql".equals(language)) { 298 if ("sql".equals(language)) {
259 lang = LANG_SQL; 299 lang = LANG_SQL;
260 } else if ("mal".equals(language)) { 300
261 lang = LANG_MAL;
262 } else {
263 lang = LANG_UNKNOWN;
264 }
265
266 // fill the query templates
267 if (lang == LANG_SQL) {
268 queryTempl[0] = "s"; // pre 301 queryTempl[0] = "s"; // pre
269 queryTempl[1] = "\n;"; // post 302 queryTempl[1] = "\n;"; // post
270 queryTempl[2] = "\n;\n"; // separator 303 queryTempl[2] = "\n;\n"; // separator
271 304
272 commandTempl[0] = "X"; // pre 305 commandTempl[0] = "X"; // pre
273 commandTempl[1] = null; // post 306 commandTempl[1] = null; // post
274 commandTempl[2] = "\nX"; // separator 307 commandTempl[2] = "\nX"; // separator
275 } else if (lang == LANG_MAL) { 308 } else if ("mal".equals(language)) {
309 lang = LANG_MAL;
310
276 queryTempl[0] = null; 311 queryTempl[0] = null;
277 queryTempl[1] = ";\n"; 312 queryTempl[1] = ";\n";
278 queryTempl[2] = ";\n"; 313 queryTempl[2] = ";\n";
279 314
280 commandTempl[0] = null; // pre 315 commandTempl[0] = null; // pre
281 commandTempl[1] = null; // post 316 commandTempl[1] = null; // post
282 commandTempl[2] = null; // separator 317 commandTempl[2] = null; // separator
283 } 318 } else {
284 319 lang = LANG_UNKNOWN;
285 // the following initialisers are only valid when the language 320 }
286 // is SQL... 321
322 // the following initialisers are only valid when the language is SQL...
287 if (lang == LANG_SQL) { 323 if (lang == LANG_SQL) {
288 // enable auto commit 324 // enable auto commit
289 setAutoCommit(true); 325 setAutoCommit(true);
326
290 // set our time zone on the server 327 // set our time zone on the server
291 Calendar cal = Calendar.getInstance(); 328 Calendar cal = Calendar.getInstance();
292 int offset = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET); 329 int offset = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET);
293 offset /= (60 * 1000); // milliseconds to minutes 330 offset /= (60 * 1000); // milliseconds to minutes
294 String tz = offset < 0 ? "-" : "+"; 331 String tz = offset < 0 ? "-" : "+";
317 /** 354 /**
318 * Releases this Connection object's database and JDBC resources 355 * Releases this Connection object's database and JDBC resources
319 * immediately instead of waiting for them to be automatically 356 * immediately instead of waiting for them to be automatically
320 * released. All Statements created from this Connection will be 357 * released. All Statements created from this Connection will be
321 * closed when this method is called. 358 * closed when this method is called.
322 * 359 *
323 * Calling the method close on a Connection object that is already 360 * Calling the method close on a Connection object that is already
324 * closed is a no-op. 361 * closed is a no-op.
325 */ 362 */
326 @Override 363 @Override
327 public void close() { 364 public void close() {
374 l.close(); 411 l.close();
375 } 412 }
376 } 413 }
377 414
378 /** 415 /**
379 * Factory method for creating Array objects.
380 *
381 * Note: When createArrayOf is used to create an array object that
382 * maps to a primitive data type, then it is implementation-defined
383 * whether the Array object is an array of that primitive data type
384 * or an array of Object.
385 *
386 * Note: The JDBC driver is responsible for mapping the elements
387 * Object array to the default JDBC SQL type defined in
388 * java.sql.Types for the given class of Object. The default mapping
389 * is specified in Appendix B of the JDBC specification. If the
390 * resulting JDBC type is not the appropriate type for the given
391 * typeName then it is implementation defined whether an
392 * SQLException is thrown or the driver supports the resulting
393 * conversion.
394 *
395 * @param typeName the SQL name of the type the elements of the
396 * array map to. The typeName is a database-specific name
397 * which may be the name of a built-in type, a user-defined
398 * type or a standard SQL type supported by this database.
399 * This is the value returned by Array.getBaseTypeName
400 * @return an Array object whose elements map to the specified SQL
401 * type
402 * @throws SQLException if a database error occurs, the JDBC type
403 * is not appropriate for the typeName and the conversion is
404 * not supported, the typeName is null or this method is
405 * called on a closed connection
406 * @throws SQLFeatureNotSupportedException the JDBC driver does
407 * not support this data type
408 */
409 @Override
410 public Array createArrayOf(String typeName, Object[] elements)
411 throws SQLException
412 {
413 throw new SQLFeatureNotSupportedException("createArrayOf(String, Object[]) not supported", "0A000");
414 }
415
416 /**
417 * Creates a Statement object for sending SQL statements to the 416 * Creates a Statement object for sending SQL statements to the
418 * database. SQL statements without parameters are normally 417 * database. SQL statements without parameters are normally
419 * executed using Statement objects. If the same SQL statement is 418 * executed using Statement objects. If the same SQL statement is
420 * executed many times, it may be more efficient to use a 419 * executed many times, it may be more efficient to use a
421 * PreparedStatement object. 420 * PreparedStatement object.
422 * 421 *
423 * Result sets created using the returned Statement object will by 422 * Result sets created using the returned Statement object will by
424 * default be type TYPE_FORWARD_ONLY and have a concurrency level of 423 * default be type TYPE_FORWARD_ONLY and have a concurrency level of
425 * CONCUR_READ_ONLY. 424 * CONCUR_READ_ONLY.
426 * 425 *
427 * @return a new default Statement object 426 * @return a new default Statement object
475 * @param resultSetConcurrency one of the following ResultSet 474 * @param resultSetConcurrency one of the following ResultSet
476 * constants: ResultSet.CONCUR_READ_ONLY or 475 * constants: ResultSet.CONCUR_READ_ONLY or
477 * ResultSet.CONCUR_UPDATABLE 476 * ResultSet.CONCUR_UPDATABLE
478 * @param resultSetHoldability one of the following ResultSet 477 * @param resultSetHoldability one of the following ResultSet
479 * constants: ResultSet.HOLD_CURSORS_OVER_COMMIT or 478 * constants: ResultSet.HOLD_CURSORS_OVER_COMMIT or
480 * ResultSet.CLOSE_CURSORS_AT_COMMIT 479 * ResultSet.CLOSE_CURSORS_AT_COMMIT
481 * 480 *
482 * @return a new Statement object that will generate ResultSet 481 * @return a new Statement object that will generate ResultSet
483 * objects with the given type, concurrency, and holdability 482 * objects with the given type, concurrency, and holdability
484 * @throws SQLException if a database access error occurs or the 483 * @throws SQLException if a database access error occurs or the
485 * given parameters are not ResultSet constants indicating type, 484 * given parameters are not ResultSet constants indicating type,
486 * concurrency, and holdability 485 * concurrency, and holdability
487 */ 486 */
488 @Override 487 @Override
509 // we don't have to catch SQLException because that is declared to 508 // we don't have to catch SQLException because that is declared to
510 // be thrown 509 // be thrown
511 } 510 }
512 511
513 /** 512 /**
514 * Constructs an object that implements the Clob interface. The
515 * object returned initially contains no data. The setAsciiStream,
516 * setCharacterStream and setString methods of the Clob interface
517 * may be used to add data to the Clob.
518 *
519 * @return a MonetClob instance
520 * @throws SQLFeatureNotSupportedException the JDBC driver does
521 * not support MonetClob objects that can be filled in
522 */
523 @Override
524 public Clob createClob() throws SQLException {
525 throw new SQLFeatureNotSupportedException("createClob() not supported", "0A000");
526 }
527
528 /**
529 * Constructs an object that implements the Blob interface. The
530 * object returned initially contains no data. The setBinaryStream
531 * and setBytes methods of the Blob interface may be used to add
532 * data to the Blob.
533 *
534 * @return a MonetBlob instance
535 * @throws SQLFeatureNotSupportedException the JDBC driver does
536 * not support MonetBlob objects that can be filled in
537 */
538 @Override
539 public Blob createBlob() throws SQLException {
540 throw new SQLFeatureNotSupportedException("createBlob() not supported", "0A000");
541 }
542
543 /**
544 * Constructs an object that implements the NClob interface. The
545 * object returned initially contains no data. The setAsciiStream,
546 * setCharacterStream and setString methods of the NClob interface
547 * may be used to add data to the NClob.
548 *
549 * @return an NClob instance
550 * @throws SQLFeatureNotSupportedException the JDBC driver does
551 * not support MonetClob objects that can be filled in
552 */
553 @Override
554 public NClob createNClob() throws SQLException {
555 throw new SQLFeatureNotSupportedException("createNClob() not supported", "0A000");
556 }
557
558 /**
559 * Factory method for creating Struct objects.
560 *
561 * @param typeName the SQL type name of the SQL structured type that
562 * this Struct object maps to. The typeName is the name of a
563 * user-defined type that has been defined for this database.
564 * It is the value returned by Struct.getSQLTypeName.
565 * @param attributes the attributes that populate the returned
566 * object
567 * @return a Struct object that maps to the given SQL type and is
568 * populated with the given attributes
569 * @throws SQLException if a database error occurs, the typeName
570 * is null or this method is called on a closed connection
571 * @throws SQLFeatureNotSupportedException the JDBC driver does
572 * not support this data type
573 */
574 @Override
575 public Struct createStruct(String typeName, Object[] attributes)
576 throws SQLException
577 {
578 throw new SQLFeatureNotSupportedException("createStruct() not supported", "0A000");
579 }
580
581 /**
582 * Constructs an object that implements the SQLXML interface. The
583 * object returned initially contains no data. The
584 * createXmlStreamWriter object and setString method of the SQLXML
585 * interface may be used to add data to the SQLXML object.
586 *
587 * @return An object that implements the SQLXML interface
588 * @throws SQLFeatureNotSupportedException the JDBC driver does
589 * not support this data type
590 */
591 @Override
592 public SQLXML createSQLXML() throws SQLException {
593 throw new SQLFeatureNotSupportedException("createSQLXML() not supported", "0A000");
594 }
595
596 /**
597 * Retrieves the current auto-commit mode for this Connection 513 * Retrieves the current auto-commit mode for this Connection
598 * object. 514 * object.
599 * 515 *
600 * @return the current state of this Connection object's auto-commit 516 * @return the current state of this Connection object's auto-commit
601 * mode 517 * mode
618 // MonetDB does NOT support catalogs 534 // MonetDB does NOT support catalogs
619 return null; 535 return null;
620 } 536 }
621 537
622 /** 538 /**
623 * Not implemented by MonetDB's JDBC driver.
624 *
625 * @param name The name of the client info property to retrieve
626 * @return The value of the client info property specified
627 */
628 @Override
629 public String getClientInfo(String name) {
630 // This method will also return null if the specified client
631 // info property name is not supported by the driver.
632 return null;
633 }
634
635 /**
636 * Not implemented by MonetDB's JDBC driver.
637 *
638 * @return A Properties object that contains the name and current
639 * value of each of the client info properties supported by
640 * the driver.
641 */
642 @Override
643 public Properties getClientInfo() {
644 return new Properties();
645 }
646
647 /**
648 * Retrieves the current holdability of ResultSet objects created 539 * Retrieves the current holdability of ResultSet objects created
649 * using this Connection object. 540 * using this Connection object.
650 * 541 *
651 * @return the holdability, one of 542 * @return the holdability, one of
652 * ResultSet.HOLD_CURSORS_OVER_COMMIT or 543 * ResultSet.HOLD_CURSORS_OVER_COMMIT or
653 * ResultSet.CLOSE_CURSORS_AT_COMMIT 544 * ResultSet.CLOSE_CURSORS_AT_COMMIT
545 * @see #setHoldability()
654 */ 546 */
655 @Override 547 @Override
656 public int getHoldability() { 548 public int getHoldability() {
657 // TODO: perhaps it is better to have the server implement 549 // TODO: perhaps it is better to have the server implement
658 // CLOSE_CURSORS_AT_COMMIT 550 // CLOSE_CURSORS_AT_COMMIT
706 * Retrieves the first warning reported by calls on this Connection 598 * Retrieves the first warning reported by calls on this Connection
707 * object. If there is more than one warning, subsequent warnings 599 * object. If there is more than one warning, subsequent warnings
708 * will be chained to the first one and can be retrieved by calling 600 * will be chained to the first one and can be retrieved by calling
709 * the method SQLWarning.getNextWarning on the warning that was 601 * the method SQLWarning.getNextWarning on the warning that was
710 * retrieved previously. 602 * retrieved previously.
711 * 603 *
712 * This method may not be called on a closed connection; doing so 604 * This method may not be called on a closed connection; doing so
713 * will cause an SQLException to be thrown. 605 * will cause an SQLException to be thrown.
714 * 606 *
715 * Note: Subsequent warnings will be chained to this SQLWarning. 607 * Note: Subsequent warnings will be chained to this SQLWarning.
716 * 608 *
717 * @return the first SQLWarning object or null if there are none 609 * @return the first SQLWarning object or null if there are none
718 * @throws SQLException if a database access error occurs or this method is 610 * @throws SQLException if a database access error occurs or this method is
719 * called on a closed connection 611 * called on a closed connection
732 * Retrieves whether this Connection object has been closed. A 624 * Retrieves whether this Connection object has been closed. A
733 * connection is closed if the method close has been called on it or 625 * connection is closed if the method close has been called on it or
734 * if certain fatal errors have occurred. This method is guaranteed 626 * if certain fatal errors have occurred. This method is guaranteed
735 * to return true only when it is called after the method 627 * to return true only when it is called after the method
736 * Connection.close has been called. 628 * Connection.close has been called.
737 * 629 *
738 * This method generally cannot be called to determine whether a 630 * This method generally cannot be called to determine whether a
739 * connection to a database is valid or invalid. A typical client 631 * connection to a database is valid or invalid. A typical client
740 * can determine that a connection is invalid by catching any 632 * can determine that a connection is invalid by catching any
741 * exceptions that might be thrown when an operation is attempted. 633 * exceptions that might be thrown when an operation is attempted.
742 * 634 *
759 @Override 651 @Override
760 public boolean isReadOnly() { 652 public boolean isReadOnly() {
761 return false; 653 return false;
762 } 654 }
763 655
764 /**
765 * Returns true if the connection has not been closed and is still
766 * valid. The driver shall submit a query on the connection or use
767 * some other mechanism that positively verifies the connection is
768 * still valid when this method is called.
769 *
770 * The query submitted by the driver to validate the connection
771 * shall be executed in the context of the current transaction.
772 *
773 * @param timeout The time in seconds to wait for the database
774 * operation used to validate the connection to complete. If
775 * the timeout period expires before the operation completes,
776 * this method returns false. A value of 0 indicates a
777 * timeout is not applied to the database operation.
778 * @return true if the connection is valid, false otherwise
779 * @throws SQLException if the value supplied for timeout is less
780 * than 0
781 */
782 @Override
783 public boolean isValid(int timeout) throws SQLException {
784 if (timeout < 0)
785 throw new SQLException("timeout is less than 0", "M1M05");
786 if (closed)
787 return false;
788 // ping db using select 1;
789 Statement stmt = null;
790 try {
791 stmt = createStatement();
792 // the timeout parameter is ignored here, since
793 // MonetStatement.setQueryTimeout(timeout) is not supported.
794 stmt.executeQuery("SELECT 1");
795 stmt.close();
796 return true;
797 } catch (Exception e) {
798 if (stmt != null) {
799 try {
800 stmt.close();
801 } catch (Exception e2) {}
802 }
803 }
804 return false;
805 }
806
807 @Override 656 @Override
808 public String nativeSQL(String sql) {return sql;} 657 public String nativeSQL(String sql) {return sql;}
658
809 @Override 659 @Override
810 public CallableStatement prepareCall(String sql) {return null;} 660 public CallableStatement prepareCall(String sql) {return null;}
661
811 @Override 662 @Override
812 public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) {return null;} 663 public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) {return null;}
664
813 @Override 665 @Override
814 public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) {return null;} 666 public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) {return null;}
815 667
816 /** 668 /**
817 * Creates a PreparedStatement object for sending parameterized SQL 669 * Creates a PreparedStatement object for sending parameterized SQL
818 * statements to the database. 670 * statements to the database.
819 * 671 *
820 * A SQL statement with or without IN parameters can be pre-compiled 672 * A SQL statement with or without IN parameters can be pre-compiled
821 * and stored in a PreparedStatement object. This object can then be 673 * and stored in a PreparedStatement object. This object can then be
822 * used to efficiently execute this statement multiple times. 674 * used to efficiently execute this statement multiple times.
823 * 675 *
824 * Note: This method is optimized for handling parametric SQL 676 * Note: This method is optimized for handling parametric SQL
825 * statements that benefit from precompilation. If the driver 677 * statements that benefit from precompilation. If the driver
826 * supports precompilation, the method prepareStatement will send 678 * supports precompilation, the method prepareStatement will send
827 * the statement to the database for precompilation. Some drivers 679 * the statement to the database for precompilation. Some drivers
828 * may not support precompilation. In this case, the statement may 680 * may not support precompilation. In this case, the statement may
829 * not be sent to the database until the PreparedStatement object is 681 * not be sent to the database until the PreparedStatement object is
830 * executed. This has no direct effect on users; however, it does 682 * executed. This has no direct effect on users; however, it does
831 * affect which methods throw certain SQLException objects. 683 * affect which methods throw certain SQLException objects.
832 * 684 *
833 * Result sets created using the returned PreparedStatement object 685 * Result sets created using the returned PreparedStatement object
834 * will by default be type TYPE_FORWARD_ONLY and have a concurrency 686 * will by default be type TYPE_FORWARD_ONLY and have a concurrency
835 * level of CONCUR_READ_ONLY. 687 * level of CONCUR_READ_ONLY.
836 * 688 *
837 * @param sql an SQL statement that may contain one or more '?' IN 689 * @param sql an SQL statement that may contain one or more '?' IN
886 } 738 }
887 739
888 /** 740 /**
889 * Creates a PreparedStatement object that will generate ResultSet 741 * Creates a PreparedStatement object that will generate ResultSet
890 * objects with the given type, concurrency, and holdability. 742 * objects with the given type, concurrency, and holdability.
891 * 743 *
892 * This method is the same as the prepareStatement method above, but 744 * This method is the same as the prepareStatement method above, but
893 * it allows the default result set type, concurrency, and 745 * it allows the default result set type, concurrency, and
894 * holdability to be overridden. 746 * holdability to be overridden.
895 * 747 *
896 * @param sql a String object that is the SQL statement to be sent 748 * @param sql a String object that is the SQL statement to be sent
901 * @param resultSetConcurrency one of the following ResultSet 753 * @param resultSetConcurrency one of the following ResultSet
902 * constants: ResultSet.CONCUR_READ_ONLY or 754 * constants: ResultSet.CONCUR_READ_ONLY or
903 * ResultSet.CONCUR_UPDATABLE 755 * ResultSet.CONCUR_UPDATABLE
904 * @param resultSetHoldability one of the following ResultSet 756 * @param resultSetHoldability one of the following ResultSet
905 * constants: ResultSet.HOLD_CURSORS_OVER_COMMIT or 757 * constants: ResultSet.HOLD_CURSORS_OVER_COMMIT or
906 * ResultSet.CLOSE_CURSORS_AT_COMMIT 758 * ResultSet.CLOSE_CURSORS_AT_COMMIT
907 * @return a new PreparedStatement object, containing the 759 * @return a new PreparedStatement object, containing the
908 * pre-compiled SQL statement, that will generate ResultSet objects 760 * pre-compiled SQL statement, that will generate ResultSet objects
909 * with the given type, concurrency, and holdability 761 * with the given type, concurrency, and holdability
910 * @throws SQLException if a database access error occurs or the 762 * @throws SQLException if a database access error occurs or the
911 * given parameters are not ResultSet constants indicating type, 763 * given parameters are not ResultSet constants indicating type,
912 * concurrency, and holdability 764 * concurrency, and holdability
913 */ 765 */
914 @Override 766 @Override
941 * Creates a default PreparedStatement object that has the 793 * Creates a default PreparedStatement object that has the
942 * capability to retrieve auto-generated keys. The given constant 794 * capability to retrieve auto-generated keys. The given constant
943 * tells the driver whether it should make auto-generated keys 795 * tells the driver whether it should make auto-generated keys
944 * available for retrieval. This parameter is ignored if the SQL 796 * available for retrieval. This parameter is ignored if the SQL
945 * statement is not an INSERT statement. 797 * statement is not an INSERT statement.
946 * 798 *
947 * Note: This method is optimized for handling parametric SQL 799 * Note: This method is optimized for handling parametric SQL
948 * statements that benefit from precompilation. If the driver 800 * statements that benefit from precompilation. If the driver
949 * supports precompilation, the method prepareStatement will send 801 * supports precompilation, the method prepareStatement will send
950 * the statement to the database for precompilation. Some drivers 802 * the statement to the database for precompilation. Some drivers
951 * may not support precompilation. In this case, the statement may 803 * may not support precompilation. In this case, the statement may
952 * not be sent to the database until the PreparedStatement object is 804 * not be sent to the database until the PreparedStatement object is
953 * executed. This has no direct effect on users; however, it does 805 * executed. This has no direct effect on users; however, it does
954 * affect which methods throw certain SQLExceptions. 806 * affect which methods throw certain SQLExceptions.
955 * 807 *
956 * Result sets created using the returned PreparedStatement object 808 * Result sets created using the returned PreparedStatement object
957 * will by default be type TYPE_FORWARD_ONLY and have a concurrency 809 * will by default be type TYPE_FORWARD_ONLY and have a concurrency
958 * level of CONCUR_READ_ONLY. 810 * level of CONCUR_READ_ONLY.
959 * 811 *
960 * @param sql an SQL statement that may contain one or more '?' IN 812 * @param sql an SQL statement that may contain one or more '?' IN
989 ); 841 );
990 } 842 }
991 843
992 @Override 844 @Override
993 public PreparedStatement prepareStatement(String sql, int[] columnIndexes) {return null;} 845 public PreparedStatement prepareStatement(String sql, int[] columnIndexes) {return null;}
846
994 @Override 847 @Override
995 public PreparedStatement prepareStatement(String sql, String[] columnNames) {return null;} 848 public PreparedStatement prepareStatement(String sql, String[] columnNames) {return null;}
996 849
997 /** 850 /**
998 * Removes the given Savepoint object from the current transaction. 851 * Removes the given Savepoint object from the current transaction.
1004 * Savepoint object is not a valid savepoint in the current 857 * Savepoint object is not a valid savepoint in the current
1005 * transaction 858 * transaction
1006 */ 859 */
1007 @Override 860 @Override
1008 public void releaseSavepoint(Savepoint savepoint) throws SQLException { 861 public void releaseSavepoint(Savepoint savepoint) throws SQLException {
1009 if (!(savepoint instanceof MonetSavepoint)) throw 862 if (!(savepoint instanceof MonetSavepoint))
1010 new SQLException("This driver can only handle savepoints it created itself", "M0M06"); 863 throw new SQLException("This driver can only handle savepoints it created itself", "M0M06");
1011 864
1012 MonetSavepoint sp = (MonetSavepoint)savepoint; 865 MonetSavepoint sp = (MonetSavepoint)savepoint;
1013 866
1014 // note: can't use sendIndependentCommand here because we need 867 // note: can't use sendIndependentCommand here because we need
1015 // to process the auto_commit state the server gives 868 // to process the auto_commit state the server gives
1029 } 882 }
1030 } 883 }
1031 884
1032 /** 885 /**
1033 * Undoes all changes made in the current transaction and releases 886 * Undoes all changes made in the current transaction and releases
1034 * any database locks currently held by this Connection object. This 887 * any database locks currently held by this Connection object.
1035 * method should be used only when auto-commit mode has been 888 * This method should be used only when auto-commit mode has been disabled.
1036 * disabled.
1037 * 889 *
1038 * @throws SQLException if a database access error occurs or this 890 * @throws SQLException if a database access error occurs or this
1039 * Connection object is in auto-commit mode 891 * Connection object is in auto-commit mode
1040 * @see #setAutoCommit(boolean) 892 * @see #setAutoCommit(boolean)
1041 */ 893 */
1059 } 911 }
1060 } 912 }
1061 913
1062 /** 914 /**
1063 * Undoes all changes made after the given Savepoint object was set. 915 * Undoes all changes made after the given Savepoint object was set.
1064 * 916 *
1065 * This method should be used only when auto-commit has been 917 * This method should be used only when auto-commit has been disabled.
1066 * disabled.
1067 * 918 *
1068 * @param savepoint the Savepoint object to roll back to 919 * @param savepoint the Savepoint object to roll back to
1069 * @throws SQLException if a database access error occurs, the 920 * @throws SQLException if a database access error occurs, the
1070 * Savepoint object is no longer valid, or this Connection 921 * Savepoint object is no longer valid, or this Connection
1071 * object is currently in auto-commit mode 922 * object is currently in auto-commit mode
1072 */ 923 */
1073 @Override 924 @Override
1074 public void rollback(Savepoint savepoint) throws SQLException { 925 public void rollback(Savepoint savepoint) throws SQLException {
1075 if (!(savepoint instanceof MonetSavepoint)) throw 926 if (!(savepoint instanceof MonetSavepoint))
1076 new SQLException("This driver can only handle savepoints it created itself", "M0M06"); 927 throw new SQLException("This driver can only handle savepoints it created itself", "M0M06");
1077 928
1078 MonetSavepoint sp = (MonetSavepoint)savepoint; 929 MonetSavepoint sp = (MonetSavepoint)savepoint;
1079 930
1080 // note: can't use sendIndependentCommand here because we need 931 // note: can't use sendIndependentCommand here because we need
1081 // to process the auto_commit state the server gives 932 // to process the auto_commit state the server gives
1099 * Sets this connection's auto-commit mode to the given state. If a 950 * Sets this connection's auto-commit mode to the given state. If a
1100 * connection is in auto-commit mode, then all its SQL statements 951 * connection is in auto-commit mode, then all its SQL statements
1101 * will be executed and committed as individual transactions. 952 * will be executed and committed as individual transactions.
1102 * Otherwise, its SQL statements are grouped into transactions that 953 * Otherwise, its SQL statements are grouped into transactions that
1103 * are terminated by a call to either the method commit or the 954 * are terminated by a call to either the method commit or the
1104 * method rollback. By default, new connections are in auto-commit 955 * method rollback. By default, new connections are in auto-commit mode.
1105 * mode. 956 *
1106 *
1107 * The commit occurs when the statement completes or the next 957 * The commit occurs when the statement completes or the next
1108 * execute occurs, whichever comes first. In the case of statements 958 * execute occurs, whichever comes first. In the case of statements
1109 * returning a ResultSet object, the statement completes when the 959 * returning a ResultSet object, the statement completes when the
1110 * last row of the ResultSet object has been retrieved or the 960 * last row of the ResultSet object has been retrieved or the
1111 * ResultSet object has been closed. In advanced cases, a single 961 * ResultSet object has been closed. In advanced cases, a single
1112 * statement may return multiple results as well as output parameter 962 * statement may return multiple results as well as output parameter
1113 * values. In these cases, the commit occurs when all results and 963 * values. In these cases, the commit occurs when all results and
1114 * output parameter values have been retrieved. 964 * output parameter values have been retrieved.
1115 * 965 *
1116 * NOTE: If this method is called during a transaction, the 966 * NOTE: If this method is called during a transaction, the
1117 * transaction is committed. 967 * transaction is committed.
1118 * 968 *
1119 * @param autoCommit true to enable auto-commit mode; false to disable it 969 * @param autoCommit true to enable auto-commit mode; false to disable it
1120 * @throws SQLException if a database access error occurs 970 * @throws SQLException if a database access error occurs
1129 } 979 }
1130 980
1131 /** 981 /**
1132 * Sets the given catalog name in order to select a subspace of this 982 * Sets the given catalog name in order to select a subspace of this
1133 * Connection object's database in which to work. If the driver 983 * Connection object's database in which to work. If the driver
1134 * does not support catalogs, it will silently ignore this request. 984 * does not support catalogs, it will silently ignore this request.
1135 */ 985 */
1136 @Override 986 @Override
1137 public void setCatalog(String catalog) throws SQLException { 987 public void setCatalog(String catalog) throws SQLException {
1138 // silently ignore this request as MonetDB does not support catalogs 988 // silently ignore this request as MonetDB does not support catalogs
1139 } 989 }
1140 990
1141 /** 991 /**
1142 * Not implemented by MonetDB's JDBC driver. 992 * Changes the default holdability of ResultSet objects created using this
1143 * 993 * Connection object to the given holdability. The default holdability of
1144 * @param name The name of the client info property to set 994 * ResultSet objects can be be determined by invoking DatabaseMetaData.getResultSetHoldability().
1145 * @param value The value to set the client info property to. If the 995 *
1146 * value is null, the current value of the specified property 996 * @param holdability - a ResultSet holdability constant; one of
1147 * is cleared. 997 * ResultSet.HOLD_CURSORS_OVER_COMMIT or
1148 */ 998 * ResultSet.CLOSE_CURSORS_AT_COMMIT
1149 @Override 999 * @see #getHoldability()
1150 public void setClientInfo(String name, String value) { 1000 */
1151 addWarning("clientInfo: " + name + "is not a recognised property", "01M07"); 1001 @Override
1152 } 1002 public void setHoldability(int holdability) throws SQLException {
1153 1003 // we only support ResultSet.HOLD_CURSORS_OVER_COMMIT
1154 /** 1004 if (holdability != ResultSet.HOLD_CURSORS_OVER_COMMIT)
1155 * Not implemented by MonetDB's JDBC driver. 1005 throw new SQLFeatureNotSupportedException("setHoldability(CLOSE_CURSORS_AT_COMMIT) not supported", "0A000");
1156 * 1006 }
1157 * @param props The list of client info properties to set
1158 */
1159 @Override
1160 public void setClientInfo(Properties props) {
1161 for (Entry<Object, Object> entry : props.entrySet()) {
1162 setClientInfo(entry.getKey().toString(),
1163 entry.getValue().toString());
1164 }
1165 }
1166
1167 @Override
1168 public void setHoldability(int holdability) {}
1169 1007
1170 /** 1008 /**
1171 * Puts this connection in read-only mode as a hint to the driver to 1009 * Puts this connection in read-only mode as a hint to the driver to
1172 * enable database optimizations. MonetDB doesn't support any mode 1010 * enable database optimizations. MonetDB doesn't support any mode
1173 * here, hence an SQLWarning is generated if attempted to set 1011 * here, hence an SQLWarning is generated if attempted to set
1215 1053
1216 return sp; 1054 return sp;
1217 } 1055 }
1218 1056
1219 /** 1057 /**
1220 * Creates a savepoint with the given name in the current 1058 * Creates a savepoint with the given name in the current transaction
1221 * transaction and returns the new Savepoint object that represents 1059 * and returns the new Savepoint object that represents it.
1222 * it.
1223 * 1060 *
1224 * @param name a String containing the name of the savepoint 1061 * @param name a String containing the name of the savepoint
1225 * @return the new Savepoint object 1062 * @return the new Savepoint object
1226 * @throws SQLException if a database access error occurs or this Connection 1063 * @throws SQLException if a database access error occurs or this Connection
1227 * object is currently in auto-commit mode 1064 * object is currently in auto-commit mode
1257 } 1094 }
1258 1095
1259 /** 1096 /**
1260 * Attempts to change the transaction isolation level for this 1097 * Attempts to change the transaction isolation level for this
1261 * Connection object to the one given. The constants defined in the 1098 * Connection object to the one given. The constants defined in the
1262 * interface Connection are the possible transaction isolation 1099 * interface Connection are the possible transaction isolation levels.
1263 * levels.
1264 * 1100 *
1265 * @param level one of the following Connection constants: 1101 * @param level one of the following Connection constants:
1266 * Connection.TRANSACTION_READ_UNCOMMITTED, 1102 * Connection.TRANSACTION_READ_UNCOMMITTED,
1267 * Connection.TRANSACTION_READ_COMMITTED, 1103 * Connection.TRANSACTION_READ_COMMITTED,
1268 * Connection.TRANSACTION_REPEATABLE_READ, or 1104 * Connection.TRANSACTION_REPEATABLE_READ, or
1270 */ 1106 */
1271 @Override 1107 @Override
1272 public void setTransactionIsolation(int level) { 1108 public void setTransactionIsolation(int level) {
1273 if (level != TRANSACTION_SERIALIZABLE) { 1109 if (level != TRANSACTION_SERIALIZABLE) {
1274 addWarning("MonetDB only supports fully serializable " + 1110 addWarning("MonetDB only supports fully serializable " +
1275 "transactions, continuing with transaction level " + 1111 "transactions, continuing with transaction level " +
1276 "raised to TRANSACTION_SERIALIZABLE", "01M09"); 1112 "raised to TRANSACTION_SERIALIZABLE", "01M09");
1277 } 1113 }
1278 } 1114 }
1279 1115
1280 /** 1116 /**
1281 * Installs the given TypeMap object as the type map for this 1117 * Installs the given TypeMap object as the type map for this
1289 public void setTypeMap(Map<String, Class<?>> map) { 1125 public void setTypeMap(Map<String, Class<?>> map) {
1290 typeMap = map; 1126 typeMap = map;
1291 } 1127 }
1292 1128
1293 /** 1129 /**
1294 * Returns a string identifying this Connection to the MonetDB 1130 * Returns a string identifying this Connection to the MonetDB server.
1295 * server.
1296 * 1131 *
1297 * @return a String representing this Object 1132 * @return a String representing this Object
1298 */ 1133 */
1299 @Override 1134 @Override
1300 public String toString() { 1135 public String toString() {
1301 return "MonetDB Connection (" + getJDBCURL() + ") " + 1136 return "MonetDB Connection (" + getJDBCURL() + ") " +
1302 (closed ? "connected" : "disconnected"); 1137 (closed ? "connected" : "disconnected");
1303 } 1138 }
1304 1139
1305 //== 1.7 methods (JDBC 4.1) 1140 //== Java 1.6 methods (JDBC 4.0)
1141
1142 /**
1143 * Factory method for creating Array objects.
1144 *
1145 * Note: When createArrayOf is used to create an array object that
1146 * maps to a primitive data type, then it is implementation-defined
1147 * whether the Array object is an array of that primitive data type
1148 * or an array of Object.
1149 *
1150 * Note: The JDBC driver is responsible for mapping the elements
1151 * Object array to the default JDBC SQL type defined in
1152 * java.sql.Types for the given class of Object. The default mapping
1153 * is specified in Appendix B of the JDBC specification. If the
1154 * resulting JDBC type is not the appropriate type for the given
1155 * typeName then it is implementation defined whether an
1156 * SQLException is thrown or the driver supports the resulting conversion.
1157 *
1158 * @param typeName the SQL name of the type the elements of the
1159 * array map to. The typeName is a database-specific name
1160 * which may be the name of a built-in type, a user-defined
1161 * type or a standard SQL type supported by this database.
1162 * This is the value returned by Array.getBaseTypeName
1163 * @return an Array object whose elements map to the specified SQL type
1164 * @throws SQLException if a database error occurs, the JDBC type
1165 * is not appropriate for the typeName and the conversion is
1166 * not supported, the typeName is null or this method is
1167 * called on a closed connection
1168 * @throws SQLFeatureNotSupportedException the JDBC driver does
1169 * not support this data type
1170 * @since 1.6
1171 */
1172 @Override
1173 public java.sql.Array createArrayOf(String typeName, Object[] elements)
1174 throws SQLException
1175 {
1176 throw new SQLFeatureNotSupportedException("createArrayOf() not supported", "0A000");
1177 }
1178
1179
1180 /**
1181 * Constructs an object that implements the Clob interface. The
1182 * object returned initially contains no data. The setAsciiStream,
1183 * setCharacterStream and setString methods of the Clob interface
1184 * may be used to add data to the Clob.
1185 *
1186 * @return a MonetClob instance
1187 * @throws SQLFeatureNotSupportedException the JDBC driver does
1188 * not support MonetClob objects that can be filled in
1189 * @since 1.6
1190 */
1191 @Override
1192 public java.sql.Clob createClob() throws SQLException {
1193 return new MonetClob("");
1194 }
1195
1196 /**
1197 * Constructs an object that implements the Blob interface. The
1198 * object returned initially contains no data. The setBinaryStream
1199 * and setBytes methods of the Blob interface may be used to add
1200 * data to the Blob.
1201 *
1202 * @return a MonetBlob instance
1203 * @throws SQLFeatureNotSupportedException the JDBC driver does
1204 * not support MonetBlob objects that can be filled in
1205 * @since 1.6
1206 */
1207 @Override
1208 public java.sql.Blob createBlob() throws SQLException {
1209 byte[] buf = new byte[1];
1210 return new MonetBlob(buf);
1211 }
1212
1213 /**
1214 * Constructs an object that implements the NClob interface. The
1215 * object returned initially contains no data. The setAsciiStream,
1216 * setCharacterStream and setString methods of the NClob interface
1217 * may be used to add data to the NClob.
1218 *
1219 * @return an NClob instance
1220 * @throws SQLFeatureNotSupportedException the JDBC driver does
1221 * not support MonetNClob objects that can be filled in
1222 * @since 1.6
1223 */
1224 @Override
1225 public java.sql.NClob createNClob() throws SQLException {
1226 throw new SQLFeatureNotSupportedException("createNClob() not supported", "0A000");
1227 }
1228
1229 /**
1230 * Factory method for creating Struct objects.
1231 *
1232 * @param typeName the SQL type name of the SQL structured type that
1233 * this Struct object maps to. The typeName is the name of a
1234 * user-defined type that has been defined for this database.
1235 * It is the value returned by Struct.getSQLTypeName.
1236 * @param attributes the attributes that populate the returned object
1237 * @return a Struct object that maps to the given SQL type and is
1238 * populated with the given attributes
1239 * @throws SQLException if a database error occurs, the typeName
1240 * is null or this method is called on a closed connection
1241 * @throws SQLFeatureNotSupportedException the JDBC driver does
1242 * not support this data type
1243 * @since 1.6
1244 */
1245 @Override
1246 public java.sql.Struct createStruct(String typeName, Object[] attributes)
1247 throws SQLException
1248 {
1249 throw new SQLFeatureNotSupportedException("createStruct() not supported", "0A000");
1250 }
1251
1252 /**
1253 * Constructs an object that implements the SQLXML interface. The
1254 * object returned initially contains no data. The
1255 * createXmlStreamWriter object and setString method of the SQLXML
1256 * interface may be used to add data to the SQLXML object.
1257 *
1258 * @return An object that implements the SQLXML interface
1259 * @throws SQLFeatureNotSupportedException the JDBC driver does
1260 * not support this data type
1261 * @since 1.6
1262 */
1263 @Override
1264 public java.sql.SQLXML createSQLXML() throws SQLException {
1265 throw new SQLFeatureNotSupportedException("createSQLXML() not supported", "0A000");
1266 }
1267
1268 /**
1269 * Returns true if the connection has not been closed and is still
1270 * valid. The driver shall submit a query on the connection or use
1271 * some other mechanism that positively verifies the connection is
1272 * still valid when this method is called.
1273 *
1274 * The query submitted by the driver to validate the connection
1275 * shall be executed in the context of the current transaction.
1276 *
1277 * @param timeout The time in seconds to wait for the database
1278 * operation used to validate the connection to complete. If
1279 * the timeout period expires before the operation completes,
1280 * this method returns false. A value of 0 indicates a
1281 * timeout is not applied to the database operation.
1282 * @return true if the connection is valid, false otherwise
1283 * @throws SQLException if the value supplied for timeout is less than 0
1284 * @since 1.6
1285 */
1286 @Override
1287 public boolean isValid(int timeout) throws SQLException {
1288 if (timeout < 0)
1289 throw new SQLException("timeout is less than 0", "M1M05");
1290 if (closed)
1291 return false;
1292
1293 // ping db using query: select 1;
1294 Statement stmt = null;
1295 ResultSet rs = null;
1296 try {
1297 stmt = createStatement();
1298 stmt.setQueryTimeout(timeout);
1299 rs = stmt.executeQuery("SELECT 1");
1300 rs.close();
1301 rs = null;
1302 stmt.close();
1303 return true;
1304 } catch (Exception e) {
1305 if (rs != null) {
1306 try {
1307 rs.close();
1308 } catch (Exception e2) {}
1309 }
1310 if (stmt != null) {
1311 try {
1312 stmt.close();
1313 } catch (Exception e2) {}
1314 }
1315 }
1316 return false;
1317 }
1318
1319 /**
1320 * Returns the value of the client info property specified by name.
1321 * This method may return null if the specified client info property
1322 * has not been set and does not have a default value.
1323 * This method will also return null if the specified client info
1324 * property name is not supported by the driver.
1325 * Applications may use the DatabaseMetaData.getClientInfoProperties method
1326 * to determine the client info properties supported by the driver.
1327 *
1328 * @param name - The name of the client info property to retrieve
1329 * @return The value of the client info property specified or null
1330 * @throws SQLException - if the database server returns an error
1331 * when fetching the client info value from the database
1332 * or this method is called on a closed connection
1333 * @since 1.6
1334 */
1335 @Override
1336 public String getClientInfo(String name) throws SQLException {
1337 if (name == null || name.isEmpty())
1338 return null;
1339 return conn_props.getProperty(name);
1340 }
1341
1342 /**
1343 * Returns a list containing the name and current value of each client info
1344 * property supported by the driver. The value of a client info property may
1345 * be null if the property has not been set and does not have a default value.
1346 *
1347 * @return A Properties object that contains the name and current value
1348 * of each of the client info properties supported by the driver.
1349 * @throws SQLException - if the database server returns an error
1350 * when fetching the client info value from the database
1351 * or this method is called on a closed connection
1352 * @since 1.6
1353 */
1354 @Override
1355 public Properties getClientInfo() throws SQLException {
1356 // return a clone of the connection properties object
1357 return new Properties(conn_props);
1358 }
1359
1360 /**
1361 * Sets the value of the client info property specified by name to the value specified by value.
1362 * Applications may use the DatabaseMetaData.getClientInfoProperties method to determine
1363 * the client info properties supported by the driver and the maximum length that may be specified
1364 * for each property.
1365 *
1366 * The driver stores the value specified in a suitable location in the database. For example
1367 * in a special register, session parameter, or system table column. For efficiency the driver
1368 * may defer setting the value in the database until the next time a statement is executed
1369 * or prepared. Other than storing the client information in the appropriate place in the
1370 * database, these methods shall not alter the behavior of the connection in anyway.
1371 * The values supplied to these methods are used for accounting, diagnostics and debugging purposes only.
1372 *
1373 * The driver shall generate a warning if the client info name specified is not recognized by the driver.
1374 *
1375 * If the value specified to this method is greater than the maximum length for the property
1376 * the driver may either truncate the value and generate a warning or generate a SQLClientInfoException.
1377 * If the driver generates a SQLClientInfoException, the value specified was not set on the connection.
1378 *
1379 * The following are standard client info properties. Drivers are not required to support these
1380 * properties however if the driver supports a client info property that can be described by one
1381 * of the standard properties, the standard property name should be used.
1382 *
1383 * ApplicationName - The name of the application currently utilizing the connection
1384 * ClientUser - The name of the user that the application using the connection is performing work for.
1385 * This may not be the same as the user name that was used in establishing the connection.
1386 * ClientHostname - The hostname of the computer the application using the connection is running on.
1387 *
1388 * @param name - The name of the client info property to set
1389 * @param value - The value to set the client info property to. If the
1390 * value is null, the current value of the specified property is cleared.
1391 * @throws SQLClientInfoException - if the database server returns an error
1392 * while setting the clientInfo values on the database server
1393 * or this method is called on a closed connection
1394 * @since 1.6
1395 */
1396 @Override
1397 public void setClientInfo(String name, String value) throws java.sql.SQLClientInfoException {
1398 if (name == null || name.isEmpty()) {
1399 addWarning("setClientInfo: missing property name", "01M07");
1400 return;
1401 }
1402 // If the value is null, the current value of the specified property is cleared.
1403 if (value == null) {
1404 if (conn_props.containsKey(name))
1405 conn_props.remove(name);
1406 return;
1407 }
1408 // only set value for supported property names
1409 if (name.equals("host") ||
1410 name.equals("port") ||
1411 name.equals("user") ||
1412 name.equals("password") ||
1413 name.equals("database") ||
1414 name.equals("language") ||
1415 name.equals("so_timeout") ||
1416 name.equals("debug") ||
1417 name.equals("hash") ||
1418 name.equals("treat_blob_as_binary")) {
1419 conn_props.setProperty(name, value);
1420 } else {
1421 addWarning("setClientInfo: " + name + "is not a recognised property", "01M07");
1422 }
1423 return;
1424 }
1425
1426 /**
1427 * Sets the value of the connection's client info properties.
1428 * The Properties object contains the names and values of the client info
1429 * properties to be set. The set of client info properties contained in the
1430 * properties list replaces the current set of client info properties on the connection.
1431 * If a property that is currently set on the connection is not present in the
1432 * properties list, that property is cleared. Specifying an empty properties list
1433 * will clear all of the properties on the connection.
1434 * See setClientInfo (String, String) for more information.
1435 *
1436 * If an error occurs in setting any of the client info properties, a
1437 * SQLClientInfoException is thrown. The SQLClientInfoException contains information
1438 * indicating which client info properties were not set. The state of the client
1439 * information is unknown because some databases do not allow multiple client info
1440 * properties to be set atomically. For those databases, one or more properties may
1441 * have been set before the error occurred.
1442 *
1443 * @param props - The list of client info properties to set
1444 * @throws SQLClientInfoException - if the database server returns an error
1445 * while setting the clientInfo values on the database server
1446 * or this method is called on a closed connection
1447 * @since 1.6
1448 */
1449 @Override
1450 public void setClientInfo(Properties props) throws java.sql.SQLClientInfoException {
1451 for (Entry<Object, Object> entry : props.entrySet()) {
1452 setClientInfo(entry.getKey().toString(),
1453 entry.getValue().toString());
1454 }
1455 }
1456
1457
1458 //== Java 1.7 methods (JDBC 4.1)
1306 1459
1307 /** 1460 /**
1308 * Sets the given schema name to access. 1461 * Sets the given schema name to access.
1309 * 1462 *
1310 * @param schema the name of a schema in which to work 1463 * @param schema the name of a schema in which to work
1311 * @throws SQLException if a database access error occurs or this 1464 * @throws SQLException if a database access error occurs or this
1312 * method is called on a closed connection 1465 * method is called on a closed connection
1466 * @since 1.7
1313 */ 1467 */
1314 @Override 1468 @Override
1315 public void setSchema(String schema) throws SQLException { 1469 public void setSchema(String schema) throws SQLException {
1316 if (closed) 1470 if (closed)
1317 throw new SQLException("Cannot call on closed Connection", "M1M20"); 1471 throw new SQLException("Cannot call on closed Connection", "M1M20");
1318 if (schema != null) 1472 if (schema == null)
1319 createStatement().execute("SET SCHEMA \"" + schema + "\""); 1473 throw new SQLException("Missing schema name", "M1M05");
1474
1475 Statement st = createStatement();
1476 try {
1477 st.execute("SET SCHEMA \"" + schema + "\"");
1478 } finally {
1479 st.close();
1480 }
1320 } 1481 }
1321 1482
1322 /** 1483 /**
1323 * Retrieves this Connection object's current schema name. 1484 * Retrieves this Connection object's current schema name.
1324 * 1485 *
1325 * @return the current schema name or null if there is none 1486 * @return the current schema name or null if there is none
1326 * @throws SQLException if a database access error occurs or this 1487 * @throws SQLException if a database access error occurs or this
1327 * method is called on a closed connection 1488 * method is called on a closed connection
1489 * @since 1.7
1328 */ 1490 */
1329 @Override 1491 @Override
1330 public String getSchema() throws SQLException { 1492 public String getSchema() throws SQLException {
1331 if (closed) 1493 if (closed)
1332 throw new SQLException("Cannot call on closed Connection", "M1M20"); 1494 throw new SQLException("Cannot call on closed Connection", "M1M20");
1352 * * The connection marked as closed 1514 * * The connection marked as closed
1353 * * Closes any physical connection to the database 1515 * * Closes any physical connection to the database
1354 * * Releases resources used by the connection 1516 * * Releases resources used by the connection
1355 * * Insures that any thread that is currently accessing the 1517 * * Insures that any thread that is currently accessing the
1356 * connection will either progress to completion or throw an 1518 * connection will either progress to completion or throw an
1357 * SQLException. 1519 * SQLException.
1358 * Calling abort marks the connection closed and releases any 1520 * Calling abort marks the connection closed and releases any
1359 * resources. Calling abort on a closed connection is a no-op. 1521 * resources. Calling abort on a closed connection is a no-op.
1360 * 1522 *
1361 * @param executor The Executor implementation which will be used by 1523 * @param executor The Executor implementation which will be used by
1362 * abort 1524 * abort
1363 * @throws SQLException if a database access error occurs or the 1525 * @throws SQLException if a database access error occurs or the
1364 * executor is null 1526 * executor is null
1365 * @throws SecurityException if a security manager exists and 1527 * @throws SecurityException if a security manager exists and
1366 * its checkPermission method denies calling abort 1528 * its checkPermission method denies calling abort
1529 * @since 1.7
1367 */ 1530 */
1368 @Override 1531 @Override
1369 public void abort(Executor executor) throws SQLException { 1532 public void abort(Executor executor) throws SQLException {
1370 if (closed) 1533 if (closed)
1371 return; 1534 return;
1391 * @param millis The time in milliseconds to wait for the 1554 * @param millis The time in milliseconds to wait for the
1392 * database operation to complete 1555 * database operation to complete
1393 * @throws SQLException if a database access error occurs, this 1556 * @throws SQLException if a database access error occurs, this
1394 * method is called on a closed connection, the executor is 1557 * method is called on a closed connection, the executor is
1395 * null, or the value specified for seconds is less than 0. 1558 * null, or the value specified for seconds is less than 0.
1559 * @since 1.7
1396 */ 1560 */
1397 @Override 1561 @Override
1398 public void setNetworkTimeout(Executor executor, int millis) 1562 public void setNetworkTimeout(Executor executor, int millis)
1399 throws SQLException 1563 throws SQLException
1400 { 1564 {
1419 * 1583 *
1420 * @return the current timeout limit in milliseconds; zero means 1584 * @return the current timeout limit in milliseconds; zero means
1421 * there is no limit 1585 * there is no limit
1422 * @throws SQLException if a database access error occurs or 1586 * @throws SQLException if a database access error occurs or
1423 * this method is called on a closed Connection 1587 * this method is called on a closed Connection
1588 * @since 1.7
1424 */ 1589 */
1425 @Override 1590 @Override
1426 public int getNetworkTimeout() throws SQLException { 1591 public int getNetworkTimeout() throws SQLException {
1427 if (closed) 1592 if (closed)
1428 throw new SQLException("Cannot call on closed Connection", "M1M20"); 1593 throw new SQLException("Cannot call on closed Connection", "M1M20");
1432 } catch (SocketException e) { 1597 } catch (SocketException e) {
1433 throw new SQLException(e.getMessage(), "08000"); 1598 throw new SQLException(e.getMessage(), "08000");
1434 } 1599 }
1435 } 1600 }
1436 1601
1437 //== end methods of interface Connection 1602
1438 1603 //== end methods of interface java.sql.Connection
1604
1605
1606 /**
1607 * Returns the MonetDB JDBC Connection URL (without user name and password).
1608 * Defined as public because it is called from: MonetDatabaseMetaData.java getURL()
1609 */
1439 public String getJDBCURL() { 1610 public String getJDBCURL() {
1440 String language = ""; 1611 String language = "";
1441 if (lang == LANG_MAL) 1612 if (lang == LANG_MAL)
1442 language = "?language=mal"; 1613 language = "?language=mal";
1443 return "jdbc:monetdb://" + hostname + ":" + port + "/" + 1614 return "jdbc:monetdb://" + hostname + ":" + port + "/" +
1540 */ 1711 */
1541 // {{{ interface Response 1712 // {{{ interface Response
1542 interface Response { 1713 interface Response {
1543 /** 1714 /**
1544 * Adds a line to the underlying Response implementation. 1715 * Adds a line to the underlying Response implementation.
1545 * 1716 *
1546 * @param line the header line as String 1717 * @param line the header line as String
1547 * @param linetype the line type according to the MAPI protocol 1718 * @param linetype the line type according to the MAPI protocol
1548 * @return a non-null String if the line is invalid, 1719 * @return a non-null String if the line is invalid,
1549 * or additional lines are not allowed. 1720 * or additional lines are not allowed.
1550 */ 1721 */
1559 public abstract boolean wantsMore(); 1730 public abstract boolean wantsMore();
1560 1731
1561 /** 1732 /**
1562 * Indicates that no more header lines will be added to this 1733 * Indicates that no more header lines will be added to this
1563 * Response implementation. 1734 * Response implementation.
1564 * 1735 *
1565 * @throws SQLException if the contents of the Response is not 1736 * @throws SQLException if the contents of the Response is not
1566 * consistent or sufficient. 1737 * consistent or sufficient.
1567 */ 1738 */
1568 public abstract void complete() throws SQLException; 1739 public abstract void complete() throws SQLException;
1569 1740
1806 * sufficient to be consistant 1977 * sufficient to be consistant
1807 */ 1978 */
1808 @Override 1979 @Override
1809 public void complete() throws SQLException { 1980 public void complete() throws SQLException {
1810 String error = ""; 1981 String error = "";
1811 if (!isSet[NAMES]) error += "name header missing\n"; 1982 if (!isSet[NAMES]) error += "name header missing\n";
1812 if (!isSet[TYPES]) error += "type header missing\n"; 1983 if (!isSet[TYPES]) error += "type header missing\n";
1813 if (!isSet[TABLES]) error += "table name header missing\n"; 1984 if (!isSet[TABLES]) error += "table name header missing\n";
1814 if (!isSet[LENS]) error += "column width header missing\n"; 1985 if (!isSet[LENS]) error += "column width header missing\n";
1815 if (error != "") throw new SQLException(error, "M0M10"); 1986 if (error != "") throw new SQLException(error, "M0M10");
1816 } 1987 }
1817 1988
1818 /** 1989 /**
1819 * Returns the names of the columns 1990 * Returns the names of the columns
1952 } 2123 }
1953 } 2124 }
1954 2125
1955 // ok, need to fetch cache block first 2126 // ok, need to fetch cache block first
1956 parent.executeQuery( 2127 parent.executeQuery(
1957 commandTempl, 2128 commandTempl,
1958 "export " + id + " " + ((block * cacheSize) + blockOffset) + " " + cacheSize 2129 "export " + id + " " + ((block * cacheSize) + blockOffset) + " " + cacheSize
1959 ); 2130 );
1960 rawr = resultBlocks[block]; 2131 rawr = resultBlocks[block];
1961 if (rawr == null) throw 2132 if (rawr == null)
1962 new AssertionError("block " + block + " should have been fetched by now :("); 2133 throw new AssertionError("block " + block + " should have been fetched by now :(");
1963 } 2134 }
1964 2135
1965 return rawr.getRow(blockLine); 2136 return rawr.getRow(blockLine);
1966 } 2137 }
1967 2138
1970 * that the result can be closed at the server side as well. 2141 * that the result can be closed at the server side as well.
1971 */ 2142 */
1972 @Override 2143 @Override
1973 public void close() { 2144 public void close() {
1974 if (closed) return; 2145 if (closed) return;
2146
1975 // send command to server indicating we're done with this 2147 // send command to server indicating we're done with this
1976 // result only if we had an ID in the header and this result 2148 // result only if we had an ID in the header and this result
1977 // was larger than the reply size 2149 // was larger than the reply size
1978 try { 2150 try {
1979 if (destroyOnClose) sendControlCommand("close " + id); 2151 if (destroyOnClose)
2152 sendControlCommand("close " + id);
1980 } catch (SQLException e) { 2153 } catch (SQLException e) {
1981 // probably a connection error... 2154 // probably a connection error...
1982 } 2155 }
1983 2156
1984 // close the data block associated with us 2157 // close the data block associated with us
1985 for (int i = 1; i < resultBlocks.length; i++) { 2158 for (int i = 1; i < resultBlocks.length; i++) {
1986 DataBlockResponse r = resultBlocks[i]; 2159 DataBlockResponse r = resultBlocks[i];
1987 if (r != null) r.close(); 2160 if (r != null)
2161 r.close();
1988 } 2162 }
1989 2163
1990 closed = true; 2164 closed = true;
1991 } 2165 }
1992 2166
2010 * </pre> 2184 * </pre>
2011 * where each column is separated by ",\t" and each tuple surrounded 2185 * where each column is separated by ",\t" and each tuple surrounded
2012 * by brackets ("[" and "]"). A DataBlockResponse object holds the 2186 * by brackets ("[" and "]"). A DataBlockResponse object holds the
2013 * raw data as read from the server, in a parsed manner, ready for 2187 * raw data as read from the server, in a parsed manner, ready for
2014 * easy retrieval. 2188 * easy retrieval.
2015 * 2189 *
2016 * This object is not intended to be queried by multiple threads 2190 * This object is not intended to be queried by multiple threads
2017 * synchronously. It is designed to work for one thread retrieving 2191 * synchronously. It is designed to work for one thread retrieving
2018 * rows from it. When multiple threads will retrieve rows from this 2192 * rows from it. When multiple threads will retrieve rows from this
2019 * object, it is possible for threads to get the same data. 2193 * object, it is possible for threads to get the same data.
2020 */ 2194 */
2042 /** 2216 /**
2043 * addLine adds a String of data to this object's data array. 2217 * addLine adds a String of data to this object's data array.
2044 * Note that an IndexOutOfBoundsException can be thrown when an 2218 * Note that an IndexOutOfBoundsException can be thrown when an
2045 * attempt is made to add more than the original construction size 2219 * attempt is made to add more than the original construction size
2046 * specified. 2220 * specified.
2047 * 2221 *
2048 * @param line the header line as String 2222 * @param line the header line as String
2049 * @param linetype the line type according to the MAPI protocol 2223 * @param linetype the line type according to the MAPI protocol
2050 * @return a non-null String if the line is invalid, 2224 * @return a non-null String if the line is invalid,
2051 * or additional lines are not allowed. 2225 * or additional lines are not allowed.
2052 */ 2226 */
2081 * 2255 *
2082 * @throws SQLException if not all rows are filled 2256 * @throws SQLException if not all rows are filled
2083 */ 2257 */
2084 @Override 2258 @Override
2085 public void complete() throws SQLException { 2259 public void complete() throws SQLException {
2086 if ((pos + 1) != data.length) throw 2260 if ((pos + 1) != data.length)
2087 new SQLException("Inconsistent state detected! Current block capacity: " + data.length + ", block usage: " + (pos + 1) + ". Did MonetDB send what it promised to?", "M0M10"); 2261 throw new SQLException("Inconsistent state detected! Current block capacity: "
2262 + data.length + ", block usage: " + (pos + 1) + ". Did MonetDB send what it promised to?", "M0M10");
2088 } 2263 }
2089 2264
2090 /** 2265 /**
2091 * Instructs the Response implementation to close and do the 2266 * Instructs the Response implementation to close and do the
2092 * necessary clean up procedures. 2267 * necessary clean up procedures.
2478 res = new AutoCommitResponse(ac); 2653 res = new AutoCommitResponse(ac);
2479 break; 2654 break;
2480 case StartOfHeaderParser.Q_BLOCK: { 2655 case StartOfHeaderParser.Q_BLOCK: {
2481 // a new block of results for a 2656 // a new block of results for a
2482 // response... 2657 // response...
2483 int id = sohp.getNextAsInt(); 2658 int id = sohp.getNextAsInt();
2484 sohp.getNextAsInt(); // columncount 2659 sohp.getNextAsInt(); // columncount
2485 int rowcount = sohp.getNextAsInt(); 2660 int rowcount = sohp.getNextAsInt();
2486 int offset = sohp.getNextAsInt(); 2661 int offset = sohp.getNextAsInt();
2487 ResultSetResponse t = 2662 ResultSetResponse t =
2488 rsresponses.get(Integer.valueOf(id)); 2663 rsresponses.get(Integer.valueOf(id));
2646 private BufferedMCLWriter out; 2821 private BufferedMCLWriter out;
2647 private String error; 2822 private String error;
2648 private int state = WAIT; 2823 private int state = WAIT;
2649 2824
2650 final Lock sendLock = new ReentrantLock(); 2825 final Lock sendLock = new ReentrantLock();
2651 final Condition queryAvailable = sendLock.newCondition(); 2826 final Condition queryAvailable = sendLock.newCondition();
2652 final Condition waiting = sendLock.newCondition(); 2827 final Condition waiting = sendLock.newCondition();
2653 2828
2654 /** 2829 /**
2655 * Constructor which immediately starts this thread and sets it 2830 * Constructor which immediately starts this thread and sets it
2656 * into daemon mode. 2831 * into daemon mode.
2709 * @throws SQLException if this SendThread is already in use 2884 * @throws SQLException if this SendThread is already in use
2710 */ 2885 */
2711 public void runQuery(String[] templ, String query) throws SQLException { 2886 public void runQuery(String[] templ, String query) throws SQLException {
2712 sendLock.lock(); 2887 sendLock.lock();
2713 try { 2888 try {
2714 if (state != WAIT) 2889 if (state != WAIT)
2715 throw new SQLException("SendThread already in use or shutting down!", "M0M03"); 2890 throw new SQLException("SendThread already in use or shutting down!", "M0M03");
2716 2891
2717 this.templ = templ; 2892 this.templ = templ;
2718 this.query = query; 2893 this.query = query;
2719 2894
2748 } 2923 }
2749 return error; 2924 return error;
2750 } 2925 }
2751 2926
2752 /** 2927 /**
2753 * Requests this SendThread to stop. 2928 * Requests this SendThread to stop.
2754 */ 2929 */
2755 public void shutdown() { 2930 public void shutdown() {
2756 sendLock.lock(); 2931 sendLock.lock();
2757 state = SHUTDOWN; 2932 state = SHUTDOWN;
2758 sendLock.unlock(); 2933 sendLock.unlock();
2759 this.interrupt(); // break any wait conditions 2934 this.interrupt(); // break any wait conditions
2760 } 2935 }
2761 } 2936 }
2762 // }}} 2937 // }}}
2763 } 2938 }
2764