Mercurial > hg > monetdb-java
comparison src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java @ 0:a5a898f6886c
Copy of MonetDB java directory changeset e6e32756ad31.
author | Sjoerd Mullender <sjoerd@acm.org> |
---|---|
date | Wed, 21 Sep 2016 09:34:48 +0200 (2016-09-21) |
parents | |
children | a0e8adf10d41 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a5a898f6886c |
---|---|
1 /* | |
2 * This Source Code Form is subject to the terms of the Mozilla Public | |
3 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. | |
5 * | |
6 * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V. | |
7 */ | |
8 | |
9 package nl.cwi.monetdb.jdbc; | |
10 | |
11 import java.sql.*; | |
12 import java.util.*; | |
13 import java.net.URL; | |
14 import java.io.*; | |
15 import java.nio.*; | |
16 import java.math.*; // BigDecimal, etc. | |
17 import java.text.SimpleDateFormat; | |
18 | |
19 /** | |
20 * A {@link PreparedStatement} suitable for the MonetDB database. | |
21 * | |
22 * This implementation of the PreparedStatement interface uses the | |
23 * capabilities of the MonetDB/SQL backend to prepare and execute | |
24 * queries. The backend takes care of finding the '?'s in the input and | |
25 * returns the types it expects for them. | |
26 * | |
27 * An example of a server response on a prepare query is: | |
28 * <pre> | |
29 * % prepare select name from tables where id > ? and id < ?; | |
30 * &5 0 2 3 2 | |
31 * # prepare, prepare, prepare # table_name | |
32 * # type, digits, scale # name | |
33 * # varchar, int, int # type | |
34 * # 0, 0, 0 # length | |
35 * [ "int", 9, 0 ] | |
36 * [ "int", 9, 0 ] | |
37 * </pre> | |
38 * | |
39 * @author Fabian Groffen | |
40 * @version 0.3 | |
41 */ | |
42 public class MonetPreparedStatement | |
43 extends MonetStatement | |
44 implements PreparedStatement | |
45 { | |
46 private final String[] monetdbType; | |
47 private final int[] javaType; | |
48 private final int[] digits; | |
49 private final int[] scale; | |
50 private final String[] schema; | |
51 private final String[] table; | |
52 private final String[] column; | |
53 private final int id; | |
54 private final int size; | |
55 private final int rscolcnt; | |
56 | |
57 private final String[] values; | |
58 | |
59 private final MonetConnection connection; | |
60 | |
61 /* only parse the date patterns once, use multiple times */ | |
62 /** Format of a timestamp with RFC822 time zone */ | |
63 final SimpleDateFormat mTimestampZ = | |
64 new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ"); | |
65 /** Format of a timestamp */ | |
66 final SimpleDateFormat mTimestamp = | |
67 new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); | |
68 /** Format of a time with RFC822 time zone */ | |
69 final SimpleDateFormat mTimeZ = | |
70 new SimpleDateFormat("HH:mm:ss.SSSZ"); | |
71 /** Format of a time */ | |
72 final SimpleDateFormat mTime = | |
73 new SimpleDateFormat("HH:mm:ss.SSS"); | |
74 /** Format of a date used by mserver */ | |
75 final SimpleDateFormat mDate = | |
76 new SimpleDateFormat("yyyy-MM-dd"); | |
77 | |
78 /** | |
79 * MonetPreparedStatement constructor which checks the arguments for | |
80 * validity. A MonetPreparedStatement is backed by a | |
81 * {@link MonetStatement}, which deals with most of the required stuff of | |
82 * this class. | |
83 * | |
84 * @param connection the connection that created this Statement | |
85 * @param resultSetType type of {@link ResultSet} to produce | |
86 * @param resultSetConcurrency concurrency of ResultSet to produce | |
87 * @param prepareQuery the query string to prepare | |
88 * @throws SQLException if an error occurs during login | |
89 * @throws IllegalArgumentException is one of the arguments is null or empty | |
90 */ | |
91 MonetPreparedStatement( | |
92 MonetConnection connection, | |
93 int resultSetType, | |
94 int resultSetConcurrency, | |
95 int resultSetHoldability, | |
96 String prepareQuery) | |
97 throws SQLException, IllegalArgumentException | |
98 { | |
99 super( | |
100 connection, | |
101 resultSetType, | |
102 resultSetConcurrency, | |
103 resultSetHoldability | |
104 ); | |
105 | |
106 if (!super.execute("PREPARE " + prepareQuery)) | |
107 throw new SQLException("Unexpected server response", "M0M10"); | |
108 | |
109 // cheat a bit to get the ID and the number of columns | |
110 id = ((MonetConnection.ResultSetResponse)header).id; | |
111 size = ((MonetConnection.ResultSetResponse)header).tuplecount; | |
112 rscolcnt = ((MonetConnection.ResultSetResponse)header).columncount; | |
113 | |
114 // initialise blank finals | |
115 monetdbType = new String[size]; | |
116 javaType = new int[size]; | |
117 digits = new int[size]; | |
118 scale = new int[size]; | |
119 schema = new String[size]; | |
120 table = new String[size]; | |
121 column = new String[size]; | |
122 values = new String[size]; | |
123 | |
124 this.connection = connection; | |
125 | |
126 // fill the arrays | |
127 ResultSet rs = super.getResultSet(); | |
128 for (int i = 0; rs.next(); i++) { | |
129 monetdbType[i] = rs.getString("type"); | |
130 javaType[i] = MonetDriver.getJavaType(monetdbType[i]); | |
131 digits[i] = rs.getInt("digits"); | |
132 scale[i] = rs.getInt("scale"); | |
133 if (rscolcnt == 3) | |
134 continue; | |
135 schema[i] = rs.getString("schema"); | |
136 table[i] = rs.getString("table"); | |
137 column[i] = rs.getString("column"); | |
138 } | |
139 rs.close(); | |
140 | |
141 // PreparedStatements are by default poolable | |
142 poolable = true; | |
143 } | |
144 | |
145 /** | |
146 * Constructs an empty MonetPreparedStatement. This constructor is | |
147 * in particular useful for extensions of this class. | |
148 * | |
149 * @param connection the connection that created this Statement | |
150 * @param resultSetType type of ResultSet to produce | |
151 * @param resultSetConcurrency concurrency of ResultSet to produce | |
152 * @throws SQLException if an error occurs during login | |
153 */ | |
154 /* Disabled this constructor code as it is not part of the JDBC interface | |
155 It may be enabled again when a subclass is constructed which needs it. | |
156 MonetPreparedStatement( | |
157 MonetConnection connection, | |
158 int resultSetType, | |
159 int resultSetConcurrency, | |
160 int resultSetHoldability) | |
161 throws SQLException | |
162 { | |
163 super( | |
164 connection, | |
165 resultSetType, | |
166 resultSetConcurrency, | |
167 resultSetHoldability | |
168 ); | |
169 // initialise blank finals | |
170 monetdbType = null; | |
171 javaType = null; | |
172 digits = null; | |
173 scale = null; | |
174 schema = null; | |
175 table = null; | |
176 column = null; | |
177 values = null; | |
178 id = -1; | |
179 size = -1; | |
180 rscolcnt = -1; | |
181 | |
182 this.connection = connection; | |
183 } | |
184 */ | |
185 | |
186 //== methods interface PreparedStatement | |
187 | |
188 /** | |
189 * Adds a set of parameters to this PreparedStatement object's batch | |
190 * of commands. | |
191 * | |
192 * @throws SQLException if a database access error occurs | |
193 */ | |
194 @Override | |
195 public void addBatch() throws SQLException { | |
196 super.addBatch(transform()); | |
197 } | |
198 | |
199 /** override the addBatch from the Statement to throw an SQLException */ | |
200 @Override | |
201 public void addBatch(String q) throws SQLException { | |
202 throw new SQLException("This method is not available in a PreparedStatement!", "M1M05"); | |
203 } | |
204 | |
205 /** | |
206 * Clears the current parameter values immediately. | |
207 * | |
208 * In general, parameter values remain in force for repeated use of a | |
209 * statement. Setting a parameter value automatically clears its previous | |
210 * value. However, in some cases it is useful to immediately release the | |
211 * resources used by the current parameter values; this can be done by | |
212 * calling the method clearParameters. | |
213 */ | |
214 @Override | |
215 public void clearParameters() { | |
216 for (int i = 0; i < values.length; i++) { | |
217 values[i] = null; | |
218 } | |
219 } | |
220 | |
221 /** | |
222 * Executes the SQL statement in this PreparedStatement object, | |
223 * which may be any kind of SQL statement. Some prepared statements | |
224 * return multiple results; the execute method handles these complex | |
225 * statements as well as the simpler form of statements handled by | |
226 * the methods executeQuery and executeUpdate. | |
227 * | |
228 * The execute method returns a boolean to indicate the form of the | |
229 * first result. You must call either the method getResultSet or | |
230 * getUpdateCount to retrieve the result; you must call | |
231 * getMoreResults to move to any subsequent result(s). | |
232 * | |
233 * @return true if the first result is a ResultSet object; false if the | |
234 * first result is an update count or there is no result | |
235 * @throws SQLException if a database access error occurs or an argument | |
236 * is supplied to this method | |
237 */ | |
238 @Override | |
239 public boolean execute() throws SQLException { | |
240 return super.execute(transform()); | |
241 } | |
242 | |
243 /** override the execute from the Statement to throw an SQLException */ | |
244 @Override | |
245 public boolean execute(String q) throws SQLException { | |
246 throw new SQLException("This method is not available in a PreparedStatement!", "M1M05"); | |
247 } | |
248 | |
249 /** | |
250 * Executes the SQL query in this PreparedStatement object and returns the | |
251 * ResultSet object generated by the query. | |
252 * | |
253 * @return a ResultSet object that contains the data produced by the query; | |
254 * never null | |
255 * @throws SQLException if a database access error occurs or the SQL | |
256 * statement does not return a ResultSet object | |
257 */ | |
258 @Override | |
259 public ResultSet executeQuery() throws SQLException{ | |
260 if (execute() != true) | |
261 throw new SQLException("Query did not produce a result set", "M1M19"); | |
262 | |
263 return getResultSet(); | |
264 } | |
265 | |
266 /** override the executeQuery from the Statement to throw an SQLException*/ | |
267 @Override | |
268 public ResultSet executeQuery(String q) throws SQLException { | |
269 throw new SQLException("This method is not available in a PreparedStatement!", "M1M05"); | |
270 } | |
271 | |
272 /** | |
273 * Executes the SQL statement in this PreparedStatement object, which must | |
274 * be an SQL INSERT, UPDATE or DELETE statement; or an SQL statement that | |
275 * returns nothing, such as a DDL statement. | |
276 * | |
277 * @return either (1) the row count for INSERT, UPDATE, or DELETE | |
278 * statements or (2) 0 for SQL statements that return nothing | |
279 * @throws SQLException if a database access error occurs or the SQL | |
280 * statement returns a ResultSet object | |
281 */ | |
282 @Override | |
283 public int executeUpdate() throws SQLException { | |
284 if (execute() != false) | |
285 throw new SQLException("Query produced a result set", "M1M17"); | |
286 | |
287 return getUpdateCount(); | |
288 } | |
289 | |
290 /** override the executeUpdate from the Statement to throw an SQLException*/ | |
291 @Override | |
292 public int executeUpdate(String q) throws SQLException { | |
293 throw new SQLException("This method is not available in a PreparedStatement!", "M1M05"); | |
294 } | |
295 | |
296 /** | |
297 * Returns the index (0..size-1) in the backing arrays for the given | |
298 * resultset column number or an SQLException when not found | |
299 */ | |
300 private int getColumnIdx(int colnr) throws SQLException { | |
301 int curcol = 0; | |
302 for (int i = 0; i < size; i++) { | |
303 if (column[i] == null) | |
304 continue; | |
305 curcol++; | |
306 if (curcol == colnr) | |
307 return i; | |
308 } | |
309 throw new SQLException("No such column with index: " + colnr, "M1M05"); | |
310 } | |
311 /** | |
312 * Returns the index (0..size-1) in the backing arrays for the given | |
313 * parameter number or an SQLException when not found | |
314 */ | |
315 private int getParamIdx(int paramnr) throws SQLException { | |
316 int curparam = 0; | |
317 for (int i = 0; i < size; i++) { | |
318 if (column[i] != null) | |
319 continue; | |
320 curparam++; | |
321 if (curparam == paramnr) | |
322 return i; | |
323 } | |
324 throw new SQLException("No such parameter with index: " + paramnr, "M1M05"); | |
325 } | |
326 | |
327 | |
328 /* helper for the anonymous class inside getMetaData */ | |
329 private abstract class rsmdw extends MonetWrapper implements ResultSetMetaData {} | |
330 /** | |
331 * Retrieves a ResultSetMetaData object that contains information | |
332 * about the columns of the ResultSet object that will be returned | |
333 * when this PreparedStatement object is executed. | |
334 * | |
335 * Because a PreparedStatement object is precompiled, it is possible | |
336 * to know about the ResultSet object that it will return without | |
337 * having to execute it. Consequently, it is possible to invoke the | |
338 * method getMetaData on a PreparedStatement object rather than | |
339 * waiting to execute it and then invoking the ResultSet.getMetaData | |
340 * method on the ResultSet object that is returned. | |
341 * | |
342 * @return the description of a ResultSet object's columns or null if the | |
343 * driver cannot return a ResultSetMetaData object | |
344 * @throws SQLException if a database access error occurs | |
345 */ | |
346 @Override | |
347 public ResultSetMetaData getMetaData() { | |
348 if (rscolcnt == 3) | |
349 return null; // not sufficient data with pre-Dec2011 PREPARE | |
350 | |
351 // return inner class which implements the ResultSetMetaData interface | |
352 return new rsmdw() { | |
353 /** | |
354 * Returns the number of columns in this ResultSet object. | |
355 * | |
356 * @returns the number of columns | |
357 */ | |
358 @Override | |
359 public int getColumnCount() { | |
360 int cnt = 0; | |
361 | |
362 for (int i = 0; i < size; i++) { | |
363 if (column[i] != null) | |
364 cnt++; | |
365 } | |
366 return cnt; | |
367 } | |
368 | |
369 /** | |
370 * Indicates whether the designated column is automatically numbered. | |
371 * | |
372 * @param column the first column is 1, the second is 2, ... | |
373 * @return true if so; false otherwise | |
374 * @throws SQLException if a database access error occurs | |
375 */ | |
376 @Override | |
377 public boolean isAutoIncrement(int column) throws SQLException { | |
378 /* TODO: in MonetDB only numeric (int, decimal) columns could be autoincrement/serial | |
379 * This however requires an expensive dbmd.getColumns(null, schema, table, column) | |
380 * query call to pull the IS_AUTOINCREMENT value for this column. | |
381 * See also ResultSetMetaData.isAutoIncrement() | |
382 */ | |
383 // For now we simply allways return false. | |
384 return false; | |
385 } | |
386 | |
387 /** | |
388 * Indicates whether a column's case matters. | |
389 * | |
390 * @param column the first column is 1, the second is 2, ... | |
391 * @returns false | |
392 */ | |
393 @Override | |
394 public boolean isCaseSensitive(int column) throws SQLException { | |
395 switch (javaType[getColumnIdx(column)]) { | |
396 case Types.CHAR: | |
397 case Types.VARCHAR: | |
398 case Types.LONGVARCHAR: // MonetDB doesn't use type LONGVARCHAR, it's here for completeness | |
399 case Types.CLOB: | |
400 return true; | |
401 } | |
402 | |
403 return false; | |
404 } | |
405 | |
406 /** | |
407 * Indicates whether the designated column can be used in a | |
408 * where clause. | |
409 * | |
410 * Returning true for all here, even for CLOB, BLOB. | |
411 * | |
412 * @param column the first column is 1, the second is 2, ... | |
413 * @returns true | |
414 */ | |
415 @Override | |
416 public boolean isSearchable(int column) { | |
417 return true; | |
418 } | |
419 | |
420 /** | |
421 * Indicates whether the designated column is a cash value. | |
422 * From the MonetDB database perspective it is by definition | |
423 * unknown whether the value is a currency, because there are | |
424 * no currency datatypes such as MONEY. With this knowledge | |
425 * we can always return false here. | |
426 * | |
427 * @param column the first column is 1, the second is 2, ... | |
428 * @returns false | |
429 */ | |
430 @Override | |
431 public boolean isCurrency(int column) { | |
432 return false; | |
433 } | |
434 | |
435 /** | |
436 * Indicates whether values in the designated column are signed | |
437 * numbers. | |
438 * Within MonetDB all numeric types (except oid and ptr) are signed. | |
439 * | |
440 * @param column the first column is 1, the second is 2, ... | |
441 * @return true if so; false otherwise | |
442 */ | |
443 @Override | |
444 public boolean isSigned(int column) throws SQLException { | |
445 String monettype = getColumnTypeName(column); | |
446 if (monettype != null) { | |
447 if ("oid".equals(monettype) | |
448 || "ptr".equals(monettype)) | |
449 return false; | |
450 } | |
451 // we can hardcode this, based on the colum type | |
452 switch (javaType[getColumnIdx(column)]) { | |
453 case Types.NUMERIC: | |
454 case Types.DECIMAL: | |
455 case Types.TINYINT: | |
456 case Types.SMALLINT: | |
457 case Types.INTEGER: | |
458 case Types.BIGINT: | |
459 case Types.REAL: | |
460 case Types.FLOAT: | |
461 case Types.DOUBLE: | |
462 return true; | |
463 case Types.BIT: // we don't use type BIT, it's here for completeness | |
464 case Types.BOOLEAN: | |
465 case Types.DATE: | |
466 case Types.TIME: | |
467 case Types.TIMESTAMP: | |
468 default: | |
469 return false; | |
470 } | |
471 } | |
472 | |
473 /** | |
474 * Indicates the designated column's normal maximum width in | |
475 * characters. | |
476 * | |
477 * @param column the first column is 1, the second is 2, ... | |
478 * @return the normal maximum number of characters allowed as the | |
479 * width of the designated column | |
480 * @throws SQLException if there is no such column | |
481 */ | |
482 @Override | |
483 public int getColumnDisplaySize(int column) throws SQLException { | |
484 return digits[getColumnIdx(column)]; | |
485 } | |
486 | |
487 /** | |
488 * Get the designated column's table's schema. | |
489 * | |
490 * @param column the first column is 1, the second is 2, ... | |
491 * @return schema name or "" if not applicable | |
492 * @throws SQLException if a database access error occurs | |
493 */ | |
494 @Override | |
495 public String getSchemaName(int column) throws SQLException { | |
496 return schema[getColumnIdx(column)]; | |
497 } | |
498 | |
499 /** | |
500 * Gets the designated column's table name. | |
501 * | |
502 * @param column the first column is 1, the second is 2, ... | |
503 * @return table name or "" if not applicable | |
504 */ | |
505 @Override | |
506 public String getTableName(int col) throws SQLException { | |
507 return table[getColumnIdx(col)]; | |
508 } | |
509 | |
510 /** | |
511 * Get the designated column's number of decimal digits. | |
512 * This method is currently very expensive as it needs to | |
513 * retrieve the information from the database using an SQL | |
514 * query. | |
515 * | |
516 * @param column the first column is 1, the second is 2, ... | |
517 * @return precision | |
518 * @throws SQLException if a database access error occurs | |
519 */ | |
520 @Override | |
521 public int getPrecision(int column) throws SQLException { | |
522 return digits[getColumnIdx(column)]; | |
523 } | |
524 | |
525 /** | |
526 * Gets the designated column's number of digits to right of | |
527 * the decimal point. This method is currently very | |
528 * expensive as it needs to retrieve the information from | |
529 * the database using an SQL query. | |
530 * | |
531 * @param column the first column is 1, the second is 2, ... | |
532 * @return scale | |
533 * @throws SQLException if a database access error occurs | |
534 */ | |
535 @Override | |
536 public int getScale(int column) throws SQLException { | |
537 return scale[getColumnIdx(column)]; | |
538 } | |
539 | |
540 /** | |
541 * Indicates the nullability of values in the designated | |
542 * column. This method is currently very expensive as it | |
543 * needs to retrieve the information from the database using | |
544 * an SQL query. | |
545 * | |
546 * @param column the first column is 1, the second is 2, ... | |
547 * @return nullability | |
548 * @throws SQLException if a database access error occurs | |
549 */ | |
550 @Override | |
551 public int isNullable(int column) throws SQLException { | |
552 return columnNullableUnknown; | |
553 } | |
554 | |
555 /** | |
556 * Gets the designated column's table's catalog name. | |
557 * MonetDB does not support the catalog naming concept as in: catalog.schema.table naming scheme | |
558 * | |
559 * @param column the first column is 1, the second is 2, ... | |
560 * @return the name of the catalog for the table in which the given | |
561 * column appears or "" if not applicable | |
562 */ | |
563 @Override | |
564 public String getCatalogName(int column) throws SQLException { | |
565 return null; // MonetDB does NOT support catalogs | |
566 } | |
567 | |
568 /** | |
569 * Indicates whether the designated column is definitely not | |
570 * writable. MonetDB does not support cursor updates, so | |
571 * nothing is writable. | |
572 * | |
573 * @param column the first column is 1, the second is 2, ... | |
574 * @return true if so; false otherwise | |
575 */ | |
576 @Override | |
577 public boolean isReadOnly(int column) { | |
578 return true; | |
579 } | |
580 | |
581 /** | |
582 * Indicates whether it is possible for a write on the | |
583 * designated column to succeed. | |
584 * | |
585 * @param column the first column is 1, the second is 2, ... | |
586 * @return true if so; false otherwise | |
587 */ | |
588 @Override | |
589 public boolean isWritable(int column) { | |
590 return false; | |
591 } | |
592 | |
593 /** | |
594 * Indicates whether a write on the designated column will | |
595 * definitely succeed. | |
596 * | |
597 * @param column the first column is 1, the second is 2, ... | |
598 * @return true if so; false otherwise | |
599 */ | |
600 @Override | |
601 public boolean isDefinitelyWritable(int column) { | |
602 return false; | |
603 } | |
604 | |
605 /** | |
606 * Returns the fully-qualified name of the Java class whose | |
607 * instances are manufactured if the method | |
608 * ResultSet.getObject is called to retrieve a value from | |
609 * the column. ResultSet.getObject may return a subclass of | |
610 * the class returned by this method. | |
611 * | |
612 * @param column the first column is 1, the second is 2, ... | |
613 * @return the fully-qualified name of the class in the Java | |
614 * programming language that would be used by the method | |
615 * ResultSet.getObject to retrieve the value in the | |
616 * specified column. This is the class name used for custom | |
617 * mapping. | |
618 * @throws SQLException if there is no such column | |
619 */ | |
620 @Override | |
621 public String getColumnClassName(int column) throws SQLException { | |
622 return MonetResultSet.getClassForType(javaType[getColumnIdx(column)]).getName(); | |
623 } | |
624 | |
625 /** | |
626 * Gets the designated column's suggested title for use in | |
627 * printouts and displays. This is currently equal to | |
628 * getColumnName(). | |
629 * | |
630 * @param column the first column is 1, the second is 2, ... | |
631 * @return the suggested column title | |
632 * @throws SQLException if there is no such column | |
633 */ | |
634 @Override | |
635 public String getColumnLabel(int column) throws SQLException { | |
636 return getColumnName(column); | |
637 } | |
638 | |
639 /** | |
640 * Gets the designated column's name | |
641 * | |
642 * @param column the first column is 1, the second is 2, ... | |
643 * @return the column name | |
644 * @throws SQLException if there is no such column | |
645 */ | |
646 @Override | |
647 public String getColumnName(int col) throws SQLException { | |
648 return column[getColumnIdx(col)]; | |
649 } | |
650 | |
651 /** | |
652 * Retrieves the designated column's SQL type. | |
653 * | |
654 * @param column the first column is 1, the second is 2, ... | |
655 * @return SQL type from java.sql.Types | |
656 * @throws SQLException if there is no such column | |
657 */ | |
658 @Override | |
659 public int getColumnType(int column) throws SQLException { | |
660 return javaType[getColumnIdx(column)]; | |
661 } | |
662 | |
663 /** | |
664 * Retrieves the designated column's database-specific type name. | |
665 * | |
666 * @param column the first column is 1, the second is 2, ... | |
667 * @return type name used by the database. If the column type is a | |
668 * user-defined type, then a fully-qualified type name is | |
669 * returned. | |
670 * @throws SQLException if there is no such column | |
671 */ | |
672 @Override | |
673 public String getColumnTypeName(int column) throws SQLException { | |
674 return monetdbType[getColumnIdx(column)]; | |
675 } | |
676 }; | |
677 } | |
678 | |
679 /* helper class for the anonymous class in getParameterMetaData */ | |
680 private abstract class pmdw extends MonetWrapper implements ParameterMetaData {} | |
681 /** | |
682 * Retrieves the number, types and properties of this | |
683 * PreparedStatement object's parameters. | |
684 * | |
685 * @return a ParameterMetaData object that contains information | |
686 * about the number, types and properties of this | |
687 * PreparedStatement object's parameters | |
688 * @throws SQLException if a database access error occurs | |
689 */ | |
690 @Override | |
691 public ParameterMetaData getParameterMetaData() throws SQLException { | |
692 return new pmdw() { | |
693 /** | |
694 * Retrieves the number of parameters in the | |
695 * PreparedStatement object for which this ParameterMetaData | |
696 * object contains information. | |
697 * | |
698 * @return the number of parameters | |
699 * @throws SQLException if a database access error occurs | |
700 */ | |
701 @Override | |
702 public int getParameterCount() throws SQLException { | |
703 int cnt = 0; | |
704 | |
705 for (int i = 0; i < size; i++) { | |
706 if (column[i] == null) | |
707 cnt++; | |
708 } | |
709 | |
710 return cnt; | |
711 } | |
712 | |
713 /** | |
714 * Retrieves whether null values are allowed in the | |
715 * designated parameter. | |
716 * | |
717 * This is currently always unknown for MonetDB/SQL. | |
718 * | |
719 * @param param the first parameter is 1, the second is 2, ... | |
720 * @return the nullability status of the given parameter; | |
721 * one of ParameterMetaData.parameterNoNulls, | |
722 * ParameterMetaData.parameterNullable, or | |
723 * ParameterMetaData.parameterNullableUnknown | |
724 * @throws SQLException if a database access error occurs | |
725 */ | |
726 @Override | |
727 public int isNullable(int param) throws SQLException { | |
728 return ParameterMetaData.parameterNullableUnknown; | |
729 } | |
730 | |
731 /** | |
732 * Retrieves whether values for the designated parameter can | |
733 * be signed numbers. | |
734 * | |
735 * @param param the first parameter is 1, the second is 2, ... | |
736 * @return true if so; false otherwise | |
737 * @throws SQLException if a database access error occurs | |
738 */ | |
739 @Override | |
740 public boolean isSigned(int param) throws SQLException { | |
741 // we can hardcode this, based on the colum type | |
742 // (from ResultSetMetaData.isSigned) | |
743 switch (javaType[getParamIdx(param)]) { | |
744 case Types.NUMERIC: | |
745 case Types.DECIMAL: | |
746 case Types.TINYINT: | |
747 case Types.SMALLINT: | |
748 case Types.INTEGER: | |
749 case Types.BIGINT: | |
750 case Types.REAL: | |
751 case Types.FLOAT: | |
752 case Types.DOUBLE: | |
753 return true; | |
754 case Types.BIT: // we don't use type BIT, it's here for completeness | |
755 case Types.BOOLEAN: | |
756 case Types.DATE: | |
757 case Types.TIME: | |
758 case Types.TIMESTAMP: | |
759 default: | |
760 return false; | |
761 } | |
762 } | |
763 | |
764 /** | |
765 * Retrieves the designated parameter's number of decimal | |
766 * digits. | |
767 * | |
768 * @param param the first parameter is 1, the second is 2, ... | |
769 * @return precision | |
770 * @throws SQLException if a database access error occurs | |
771 */ | |
772 @Override | |
773 public int getPrecision(int param) throws SQLException { | |
774 return digits[getParamIdx(param)]; | |
775 } | |
776 | |
777 /** | |
778 * Retrieves the designated parameter's number of digits to | |
779 * right of the decimal point. | |
780 * | |
781 * @param param the first parameter is 1, the second is 2, ... | |
782 * @return scale | |
783 * @throws SQLException if a database access error occurs | |
784 */ | |
785 @Override | |
786 public int getScale(int param) throws SQLException { | |
787 return scale[getParamIdx(param)]; | |
788 } | |
789 | |
790 /** | |
791 * Retrieves the designated parameter's SQL type. | |
792 * | |
793 * @param param the first parameter is 1, the second is 2, ... | |
794 * @return SQL type from java.sql.Types | |
795 * @throws SQLException if a database access error occurs | |
796 */ | |
797 @Override | |
798 public int getParameterType(int param) throws SQLException { | |
799 return javaType[getParamIdx(param)]; | |
800 } | |
801 | |
802 /** | |
803 * Retrieves the designated parameter's database-specific | |
804 * type name. | |
805 * | |
806 * @param param the first parameter is 1, the second is 2, ... | |
807 * @return type the name used by the database. If the | |
808 * parameter type is a user-defined type, then a | |
809 * fully-qualified type name is returned. | |
810 * @throws SQLException if a database access error occurs | |
811 */ | |
812 @Override | |
813 public String getParameterTypeName(int param) throws SQLException { | |
814 return monetdbType[getParamIdx(param)]; | |
815 } | |
816 | |
817 /** | |
818 * Retrieves the fully-qualified name of the Java class | |
819 * whose instances should be passed to the method | |
820 * PreparedStatement.setObject. | |
821 * | |
822 * @param param the first parameter is 1, the second is 2, ... | |
823 * @return the fully-qualified name of the class in the Java | |
824 * programming language that would be used by the | |
825 * method PreparedStatement.setObject to set the | |
826 * value in the specified parameter. This is the | |
827 * class name used for custom mapping. | |
828 * @throws SQLException if a database access error occurs | |
829 */ | |
830 @Override | |
831 public String getParameterClassName(int param) throws SQLException { | |
832 Map<String,Class<?>> map = getConnection().getTypeMap(); | |
833 Class<?> c; | |
834 if (map.containsKey(monetdbType[getParamIdx(param)])) { | |
835 c = (Class)map.get(monetdbType[getParamIdx(param)]); | |
836 } else { | |
837 c = MonetResultSet.getClassForType( | |
838 javaType[getParamIdx(param)] | |
839 ); | |
840 } | |
841 return c.getName(); | |
842 } | |
843 | |
844 /** | |
845 * Retrieves the designated parameter's mode. | |
846 * For MonetDB/SQL this is currently always unknown. | |
847 * | |
848 * @param param - the first parameter is 1, the second is 2, ... | |
849 * @return mode of the parameter; one of | |
850 * ParameterMetaData.parameterModeIn, | |
851 * ParameterMetaData.parameterModeOut, or | |
852 * ParameterMetaData.parameterModeInOut | |
853 * ParameterMetaData.parameterModeUnknown. | |
854 * @throws SQLException if a database access error occurs | |
855 */ | |
856 @Override | |
857 public int getParameterMode(int param) throws SQLException { | |
858 return ParameterMetaData.parameterModeUnknown; | |
859 } | |
860 }; | |
861 } | |
862 | |
863 /** | |
864 * Sets the designated parameter to the given Array object. The | |
865 * driver converts this to an SQL ARRAY value when it sends it to | |
866 * the database. | |
867 * | |
868 * @param i the first parameter is 1, the second is 2, ... | |
869 * @param x an Array object that maps an SQL ARRAY value | |
870 * @throws SQLException if a database access error occurs | |
871 */ | |
872 @Override | |
873 public void setArray(int i, Array x) throws SQLException { | |
874 throw new SQLException("Operation setArray(int i, Array x) currently not supported!", "0A000"); | |
875 } | |
876 | |
877 /** | |
878 * Sets the designated parameter to the given input stream, which will have | |
879 * the specified number of bytes. When a very large ASCII value is input to | |
880 * a LONGVARCHAR parameter, it may be more practical to send it via a | |
881 * java.io.InputStream. Data will be read from the stream as needed until | |
882 * end-of-file is reached. The JDBC driver will do any necessary conversion | |
883 * from ASCII to the database char format. | |
884 * | |
885 * Note: This stream object can either be a standard Java stream object or | |
886 * your own subclass that implements the standard interface. | |
887 * | |
888 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
889 * @param x the Java input stream that contains the ASCII parameter value | |
890 * @throws SQLException if a database access error occurs | |
891 * @throws SQLFeatureNotSupportedException the JDBC driver does | |
892 * not support this method | |
893 */ | |
894 @Override | |
895 public void setAsciiStream(int parameterIndex, InputStream x) | |
896 throws SQLException | |
897 { | |
898 throw newSQLFeatureNotSupportedException("setAsciiStream"); | |
899 } | |
900 | |
901 /** | |
902 * Sets the designated parameter to the given input stream, which will have | |
903 * the specified number of bytes. When a very large ASCII value is input to | |
904 * a LONGVARCHAR parameter, it may be more practical to send it via a | |
905 * java.io.InputStream. Data will be read from the stream as needed until | |
906 * end-of-file is reached. The JDBC driver will do any necessary conversion | |
907 * from ASCII to the database char format. | |
908 * | |
909 * Note: This stream object can either be a standard Java stream object or | |
910 * your own subclass that implements the standard interface. | |
911 * | |
912 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
913 * @param x the Java input stream that contains the ASCII parameter value | |
914 * @param length the number of bytes in the stream | |
915 * @throws SQLException if a database access error occurs | |
916 */ | |
917 @Override | |
918 public void setAsciiStream(int parameterIndex, InputStream x, int length) | |
919 throws SQLException | |
920 { | |
921 throw newSQLFeatureNotSupportedException("setAsciiStream"); | |
922 } | |
923 | |
924 /** | |
925 * Sets the designated parameter to the given input stream, which | |
926 * will have the specified number of bytes. When a very large ASCII | |
927 * value is input to a LONGVARCHAR parameter, it may be more | |
928 * practical to send it via a java.io.InputStream. Data will be read | |
929 * from the stream as needed until end-of-file is reached. The JDBC | |
930 * driver will do any necessary conversion from ASCII to the | |
931 * database char format. | |
932 * | |
933 * Note: This stream object can either be a standard Java stream object or | |
934 * your own subclass that implements the standard interface. | |
935 * | |
936 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
937 * @param x the Java input stream that contains the ASCII parameter value | |
938 * @param length the number of bytes in the stream | |
939 * @throws SQLException if a database access error occurs | |
940 * @throws SQLFeatureNotSupportedException the JDBC driver does | |
941 * not support this method | |
942 */ | |
943 @Override | |
944 public void setAsciiStream(int parameterIndex, InputStream x, long length) | |
945 throws SQLException | |
946 { | |
947 throw newSQLFeatureNotSupportedException("setAsciiStream"); | |
948 } | |
949 | |
950 /** | |
951 * Sets the designated parameter to the given java.math.BigDecimal value. | |
952 * The driver converts this to an SQL NUMERIC value when it sends it to the | |
953 * database. | |
954 * | |
955 * @param idx the first parameter is 1, the second is 2, ... | |
956 * @param x the parameter value | |
957 * @throws SQLException if a database access error occurs | |
958 */ | |
959 @Override | |
960 public void setBigDecimal(int idx, BigDecimal x) | |
961 throws SQLException | |
962 { | |
963 // get array position | |
964 int i = getParamIdx(idx); | |
965 | |
966 // round to the scale of the DB: | |
967 x = x.setScale(scale[i], RoundingMode.HALF_UP); | |
968 | |
969 // if precision is now greater than that of the db, throw an error: | |
970 if (x.precision() > digits[i]) { | |
971 throw new SQLDataException("DECIMAL value exceeds allowed digits/scale: " + x.toPlainString() + " (" + digits[i] + "/" + scale[i] + ")", "22003"); | |
972 } | |
973 | |
974 // MonetDB doesn't like leading 0's, since it counts them as part of | |
975 // the precision, so let's strip them off. (But be careful not to do | |
976 // this to the exact number "0".) Also strip off trailing | |
977 // numbers that are inherent to the double representation. | |
978 String xStr = x.toPlainString(); | |
979 int dot = xStr.indexOf("."); | |
980 if (dot >= 0) | |
981 xStr = xStr.substring(0, Math.min(xStr.length(), dot + 1 + scale[i])); | |
982 while (xStr.startsWith("0") && xStr.length() > 1) | |
983 xStr = xStr.substring(1); | |
984 setValue(idx, xStr); | |
985 } | |
986 | |
987 /** | |
988 * Sets the designated parameter to the given input stream, which will have | |
989 * the specified number of bytes. When a very large binary value is input | |
990 * to a LONGVARBINARY parameter, it may be more practical to send it via a | |
991 * java.io.InputStream object. The data will be read from the stream as | |
992 * needed until end-of-file is reached. | |
993 * | |
994 * Note: This stream object can either be a standard Java stream object or | |
995 * your own subclass that implements the standard interface. | |
996 * | |
997 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
998 * @param x the java input stream which contains the binary parameter value | |
999 * @throws SQLException if a database access error occurs | |
1000 * @throws SQLFeatureNotSupportedException the JDBC driver does | |
1001 * not support this method | |
1002 */ | |
1003 @Override | |
1004 public void setBinaryStream(int parameterIndex, InputStream x) | |
1005 throws SQLException | |
1006 { | |
1007 throw newSQLFeatureNotSupportedException("setBinaryStream"); | |
1008 } | |
1009 | |
1010 /** | |
1011 * Sets the designated parameter to the given input stream, which will have | |
1012 * the specified number of bytes. When a very large binary value is input | |
1013 * to a LONGVARBINARY parameter, it may be more practical to send it via a | |
1014 * java.io.InputStream object. The data will be read from the stream as | |
1015 * needed until end-of-file is reached. | |
1016 * | |
1017 * Note: This stream object can either be a standard Java stream object or | |
1018 * your own subclass that implements the standard interface. | |
1019 * | |
1020 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
1021 * @param x the java input stream which contains the binary parameter value | |
1022 * @param length the number of bytes in the stream | |
1023 * @throws SQLException if a database access error occurs | |
1024 * @throws SQLFeatureNotSupportedException the JDBC driver does | |
1025 * not support this method | |
1026 */ | |
1027 @Override | |
1028 public void setBinaryStream(int parameterIndex, InputStream x, int length) | |
1029 throws SQLException | |
1030 { | |
1031 throw newSQLFeatureNotSupportedException("setBinaryStream"); | |
1032 } | |
1033 | |
1034 /** | |
1035 * Sets the designated parameter to the given input stream, which will have | |
1036 * the specified number of bytes. When a very large binary value is input | |
1037 * to a LONGVARBINARY parameter, it may be more practical to send it via a | |
1038 * java.io.InputStream object. The data will be read from the stream as | |
1039 * needed until end-of-file is reached. | |
1040 * | |
1041 * Note: This stream object can either be a standard Java stream object or | |
1042 * your own subclass that implements the standard interface. | |
1043 * | |
1044 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
1045 * @param x the java input stream which contains the binary parameter value | |
1046 * @param length the number of bytes in the stream | |
1047 * @throws SQLException if a database access error occurs | |
1048 * @throws SQLFeatureNotSupportedException the JDBC driver does | |
1049 * not support this method | |
1050 */ | |
1051 @Override | |
1052 public void setBinaryStream(int parameterIndex, InputStream x, long length) | |
1053 throws SQLException | |
1054 { | |
1055 throw newSQLFeatureNotSupportedException("setBinaryStream"); | |
1056 } | |
1057 | |
1058 /** | |
1059 * Sets the designated parameter to the given Blob object. The driver | |
1060 * converts this to an SQL BLOB value when it sends it to the database. | |
1061 * | |
1062 * @param i the first parameter is 1, the second is 2, ... | |
1063 * @param x a Blob object that maps an SQL BLOB value | |
1064 * @throws SQLException if a database access error occurs | |
1065 * @throws SQLFeatureNotSupportedException the JDBC driver does | |
1066 * not support this method | |
1067 */ | |
1068 @Override | |
1069 public void setBlob(int i, InputStream x) throws SQLException { | |
1070 throw newSQLFeatureNotSupportedException("setBlob"); | |
1071 } | |
1072 | |
1073 /** | |
1074 * Sets the designated parameter to the given Blob object. The driver | |
1075 * converts this to an SQL BLOB value when it sends it to the database. | |
1076 * | |
1077 * @param i the first parameter is 1, the second is 2, ... | |
1078 * @param x a Blob object that maps an SQL BLOB value | |
1079 * @throws SQLException if a database access error occurs | |
1080 * @throws SQLFeatureNotSupportedException the JDBC driver does | |
1081 * not support this method | |
1082 */ | |
1083 @Override | |
1084 public void setBlob(int i, Blob x) throws SQLException { | |
1085 throw newSQLFeatureNotSupportedException("setBlob"); | |
1086 } | |
1087 | |
1088 /** | |
1089 * Sets the designated parameter to a InputStream object. The | |
1090 * inputstream must contain the number of characters specified by | |
1091 * length otherwise a SQLException will be generated when the | |
1092 * PreparedStatement is executed. This method differs from the | |
1093 * setBinaryStream (int, InputStream, int) method because it informs | |
1094 * the driver that the parameter value should be sent to the server | |
1095 * as a BLOB. When the setBinaryStream method is used, the driver | |
1096 * may have to do extra work to determine whether the parameter data | |
1097 * should be sent to the server as a LONGVARBINARY or a BLOB. | |
1098 * | |
1099 * @param i the first parameter is 1, the second is 2, ... | |
1100 * @param is an object that contains the data to set the parameter | |
1101 * value to | |
1102 * @param length the number of bytes in the parameter data | |
1103 * @throws SQLException if a database access error occurs | |
1104 * @throws SQLFeatureNotSupportedException the JDBC driver does | |
1105 * not support this method | |
1106 */ | |
1107 @Override | |
1108 public void setBlob(int i, InputStream is, long length) throws SQLException { | |
1109 throw newSQLFeatureNotSupportedException("setBlob"); | |
1110 } | |
1111 | |
1112 /** | |
1113 * Sets the designated parameter to the given Java boolean value. The | |
1114 * driver converts this to an SQL BIT value when it sends it to the | |
1115 * database. | |
1116 * | |
1117 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
1118 * @param x the parameter value | |
1119 * @throws SQLException if a database access error occurs | |
1120 */ | |
1121 @Override | |
1122 public void setBoolean(int parameterIndex, boolean x) throws SQLException { | |
1123 setValue(parameterIndex, "" + x); | |
1124 } | |
1125 | |
1126 /** | |
1127 * Sets the designated parameter to the given Java byte value. The driver | |
1128 * converts this to an SQL TINYINT value when it sends it to the database. | |
1129 * | |
1130 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
1131 * @param x the parameter value | |
1132 * @throws SQLException if a database access error occurs | |
1133 */ | |
1134 @Override | |
1135 public void setByte(int parameterIndex, byte x) throws SQLException { | |
1136 setValue(parameterIndex, "" + x); | |
1137 } | |
1138 | |
1139 static final String HEXES = "0123456789ABCDEF"; | |
1140 /** | |
1141 * Sets the designated parameter to the given Java array of bytes. The | |
1142 * driver converts this to an SQL VARBINARY or LONGVARBINARY (depending | |
1143 * on the argument's size relative to the driver's limits on VARBINARY | |
1144 * values) when it sends it to the database. | |
1145 * | |
1146 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
1147 * @param x the parameter value | |
1148 * @throws SQLException if a database access error occurs | |
1149 */ | |
1150 @Override | |
1151 public void setBytes(int parameterIndex, byte[] x) throws SQLException { | |
1152 if (x == null) { | |
1153 setNull(parameterIndex, -1); | |
1154 return; | |
1155 } | |
1156 | |
1157 StringBuilder hex = new StringBuilder(x.length * 2); | |
1158 byte b; | |
1159 for (int i = 0; i < x.length; i++) { | |
1160 b = x[i]; | |
1161 hex.append(HEXES.charAt((b & 0xF0) >> 4)) | |
1162 .append(HEXES.charAt((b & 0x0F))); | |
1163 } | |
1164 setValue(parameterIndex, "blob '" + hex.toString() + "'"); | |
1165 } | |
1166 | |
1167 /** | |
1168 * Sets the designated parameter to the given Reader object, which is the | |
1169 * given number of characters long. When a very large UNICODE value is | |
1170 * input to a LONGVARCHAR parameter, it may be more practical to send it | |
1171 * via a java.io.Reader object. The data will be read from the stream as | |
1172 * needed until end-of-file is reached. The JDBC driver will do any | |
1173 * necessary conversion from UNICODE to the database char format. | |
1174 * | |
1175 * Note: This stream object can either be a standard Java stream object or | |
1176 * your own subclass that implements the standard interface. | |
1177 * | |
1178 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
1179 * @param reader the java.io.Reader object that contains the Unicode data | |
1180 * @param length the number of characters in the stream | |
1181 * @throws SQLException if a database access error occurs | |
1182 */ | |
1183 @Override | |
1184 public void setCharacterStream( | |
1185 int parameterIndex, | |
1186 Reader reader, | |
1187 int length) | |
1188 throws SQLException | |
1189 { | |
1190 if (reader == null) { | |
1191 setNull(parameterIndex, -1); | |
1192 return; | |
1193 } | |
1194 | |
1195 CharBuffer tmp = CharBuffer.allocate(length); | |
1196 try { | |
1197 reader.read(tmp); | |
1198 } catch (IOException e) { | |
1199 throw new SQLException(e.getMessage(), "M1M25"); | |
1200 } | |
1201 setString(parameterIndex, tmp.toString()); | |
1202 } | |
1203 | |
1204 /** | |
1205 * Sets the designated parameter to the given Reader object, which is the | |
1206 * given number of characters long. When a very large UNICODE value is | |
1207 * input to a LONGVARCHAR parameter, it may be more practical to send it | |
1208 * via a java.io.Reader object. The data will be read from the stream as | |
1209 * needed until end-of-file is reached. The JDBC driver will do any | |
1210 * necessary conversion from UNICODE to the database char format. | |
1211 * | |
1212 * Note: This stream object can either be a standard Java stream object or | |
1213 * your own subclass that implements the standard interface. | |
1214 * | |
1215 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
1216 * @param reader the java.io.Reader object that contains the Unicode data | |
1217 * @throws SQLException if a database access error occurs | |
1218 * @throws SQLFeatureNotSupportedException the JDBC driver does | |
1219 * not support this method | |
1220 */ | |
1221 @Override | |
1222 public void setCharacterStream(int parameterIndex, Reader reader) | |
1223 throws SQLException | |
1224 { | |
1225 setCharacterStream(parameterIndex, reader, 0); | |
1226 } | |
1227 | |
1228 /** | |
1229 * Sets the designated parameter to the given Reader object, which is the | |
1230 * given number of characters long. When a very large UNICODE value is | |
1231 * input to a LONGVARCHAR parameter, it may be more practical to send it | |
1232 * via a java.io.Reader object. The data will be read from the stream as | |
1233 * needed until end-of-file is reached. The JDBC driver will do any | |
1234 * necessary conversion from UNICODE to the database char format. | |
1235 * | |
1236 * Note: This stream object can either be a standard Java stream object or | |
1237 * your own subclass that implements the standard interface. | |
1238 * | |
1239 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
1240 * @param reader the java.io.Reader object that contains the Unicode data | |
1241 * @param length the number of characters in the stream | |
1242 * @throws SQLException if a database access error occurs | |
1243 */ | |
1244 @Override | |
1245 public void setCharacterStream( | |
1246 int parameterIndex, | |
1247 Reader reader, | |
1248 long length) | |
1249 throws SQLException | |
1250 { | |
1251 // given the implementation of the int-version, downcast is ok | |
1252 setCharacterStream(parameterIndex, reader, (int)length); | |
1253 } | |
1254 | |
1255 /** | |
1256 * Sets the designated parameter to the given Clob object. The driver | |
1257 * converts this to an SQL CLOB value when it sends it to the database. | |
1258 * | |
1259 * @param i the first parameter is 1, the second is 2, ... | |
1260 * @param x a Clob object that maps an SQL CLOB value | |
1261 * @throws SQLException if a database access error occurs | |
1262 */ | |
1263 @Override | |
1264 public void setClob(int i, Clob x) throws SQLException { | |
1265 if (x == null) { | |
1266 setNull(i, -1); | |
1267 return; | |
1268 } | |
1269 | |
1270 // simply serialise the CLOB into a variable for now... far from | |
1271 // efficient, but might work for a few cases... | |
1272 // be on your marks: we have to cast the length down! | |
1273 setString(i, x.getSubString(1L, (int)(x.length()))); | |
1274 } | |
1275 | |
1276 /** | |
1277 * Sets the designated parameter to the given Clob object. The driver | |
1278 * converts this to an SQL CLOB value when it sends it to the database. | |
1279 * | |
1280 * @param i the first parameter is 1, the second is 2, ... | |
1281 * @param reader an object that contains the data to set the parameter | |
1282 * value to | |
1283 * @throws SQLException if a database access error occurs | |
1284 * @throws SQLFeatureNotSupportedException the JDBC driver does | |
1285 * not support this method | |
1286 */ | |
1287 @Override | |
1288 public void setClob(int i, Reader reader) throws SQLException { | |
1289 if (reader == null) { | |
1290 setNull(i, -1); | |
1291 return; | |
1292 } | |
1293 // Some buffer. Size of 8192 is default for BufferedReader, so... | |
1294 char[] arr = new char[8192]; | |
1295 StringBuilder buf = new StringBuilder(8192 * 8); | |
1296 int numChars; | |
1297 try { | |
1298 while ((numChars = reader.read(arr, 0, arr.length)) > 0) { | |
1299 buf.append(arr, 0, numChars); | |
1300 } | |
1301 setString(i, buf.toString()); | |
1302 } catch (IOException e) { | |
1303 throw new SQLException(e); | |
1304 } | |
1305 } | |
1306 | |
1307 /** | |
1308 * Sets the designated parameter to a Reader object. The reader must | |
1309 * contain the number of characters specified by length otherwise a | |
1310 * SQLException will be generated when the PreparedStatement is | |
1311 * executed. This method differs from the setCharacterStream (int, | |
1312 * Reader, int) method because it informs the driver that the | |
1313 * parameter value should be sent to the server as a CLOB. When the | |
1314 * setCharacterStream method is used, the driver may have to do | |
1315 * extra work to determine whether the parameter data should be sent | |
1316 * to the server as a LONGVARCHAR or a CLOB. | |
1317 * | |
1318 * @param i the first parameter is 1, the second is 2, ... | |
1319 * @param reader An object that contains the data to set the | |
1320 * parameter value to. | |
1321 * @param length the number of characters in the parameter data. | |
1322 * @throws SQLException if a database access error occurs | |
1323 */ | |
1324 @Override | |
1325 public void setClob(int i, Reader reader, long length) throws SQLException { | |
1326 if (reader == null || length < 0) { | |
1327 setNull(i, -1); | |
1328 return; | |
1329 } | |
1330 // simply serialise the CLOB into a variable for now... far from | |
1331 // efficient, but might work for a few cases... | |
1332 CharBuffer buf = CharBuffer.allocate((int)length); // have to down cast :( | |
1333 try { | |
1334 reader.read(buf); | |
1335 } catch (IOException e) { | |
1336 throw new SQLException("failed to read from stream: " + | |
1337 e.getMessage(), "M1M25"); | |
1338 } | |
1339 // We have to rewind the buffer, because otherwise toString() returns "". | |
1340 buf.rewind(); | |
1341 setString(i, buf.toString()); | |
1342 } | |
1343 | |
1344 /** | |
1345 * Sets the designated parameter to the given java.sql.Date value. The | |
1346 * driver converts this to an SQL DATE value when it sends it to the | |
1347 * database. | |
1348 * | |
1349 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
1350 * @param x the parameter value | |
1351 * @throws SQLException if a database access error occurs | |
1352 */ | |
1353 @Override | |
1354 public void setDate(int parameterIndex, java.sql.Date x) | |
1355 throws SQLException | |
1356 { | |
1357 setDate(parameterIndex, x, null); | |
1358 } | |
1359 | |
1360 /** | |
1361 * Sets the designated parameter to the given java.sql.Date value, using | |
1362 * the given Calendar object. The driver uses the Calendar object to | |
1363 * construct an SQL DATE value, which the driver then sends to the | |
1364 * database. With a Calendar object, the driver can calculate the date | |
1365 * taking into account a custom timezone. If no Calendar object is | |
1366 * specified, the driver uses the default timezone, which is that of the | |
1367 * virtual machine running the application. | |
1368 * | |
1369 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
1370 * @param x the parameter value | |
1371 * @param cal the Calendar object the driver will use to construct the date | |
1372 * @throws SQLException if a database access error occurs | |
1373 */ | |
1374 @Override | |
1375 public void setDate(int parameterIndex, java.sql.Date x, Calendar cal) | |
1376 throws SQLException | |
1377 { | |
1378 if (x == null) { | |
1379 setNull(parameterIndex, -1); | |
1380 return; | |
1381 } | |
1382 | |
1383 if (cal == null) { | |
1384 setValue(parameterIndex, "date '" + x.toString() + "'"); | |
1385 } else { | |
1386 mDate.setTimeZone(cal.getTimeZone()); | |
1387 setValue(parameterIndex, "date '" + mDate.format(x) + "'"); | |
1388 } | |
1389 } | |
1390 | |
1391 /** | |
1392 * Sets the designated parameter to the given Java double value. The driver | |
1393 * converts this to an SQL DOUBLE value when it sends it to the database. | |
1394 * | |
1395 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
1396 * @param x the parameter value | |
1397 * @throws SQLException if a database access error occurs | |
1398 */ | |
1399 @Override | |
1400 public void setDouble(int parameterIndex, double x) throws SQLException { | |
1401 setValue(parameterIndex, "" + x); | |
1402 } | |
1403 | |
1404 /** | |
1405 * Sets the designated parameter to the given Java float value. The driver | |
1406 * converts this to an SQL FLOAT value when it sends it to the database. | |
1407 * | |
1408 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
1409 * @param x the parameter value | |
1410 * @throws SQLException if a database access error occurs | |
1411 */ | |
1412 @Override | |
1413 public void setFloat(int parameterIndex, float x) throws SQLException { | |
1414 setValue(parameterIndex, "" + x); | |
1415 } | |
1416 | |
1417 /** | |
1418 * Sets the designated parameter to the given Java int value. The driver | |
1419 * converts this to an SQL INTEGER value when it sends it to the database. | |
1420 * | |
1421 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
1422 * @param x the parameter value | |
1423 * @throws SQLException if a database access error occurs | |
1424 */ | |
1425 @Override | |
1426 public void setInt(int parameterIndex, int x) throws SQLException { | |
1427 setValue(parameterIndex, "" + x); | |
1428 } | |
1429 | |
1430 /** | |
1431 * Sets the designated parameter to the given Java long value. The driver | |
1432 * converts this to an SQL BIGINT value when it sends it to the database. | |
1433 * | |
1434 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
1435 * @param x the parameter value | |
1436 * @throws SQLException if a database access error occurs | |
1437 */ | |
1438 @Override | |
1439 public void setLong(int parameterIndex, long x) throws SQLException { | |
1440 setValue(parameterIndex, "" + x); | |
1441 } | |
1442 | |
1443 /** | |
1444 * Sets the designated parameter to a Reader object. The Reader | |
1445 * reads the data till end-of-file is reached. The driver does the | |
1446 * necessary conversion from Java character format to the national | |
1447 * character set in the database. | |
1448 * | |
1449 * @param i the first parameter is 1, the second is 2, ... | |
1450 * @param value the parameter value | |
1451 * @throws SQLException if a database access error occurs | |
1452 * @throws SQLFeatureNotSupportedException the JDBC driver does | |
1453 * not support this method | |
1454 */ | |
1455 @Override | |
1456 public void setNCharacterStream(int i, Reader value) throws SQLException { | |
1457 throw newSQLFeatureNotSupportedException("setNCharacterStream"); | |
1458 } | |
1459 | |
1460 /** | |
1461 * Sets the designated parameter to a Reader object. The Reader | |
1462 * reads the data till end-of-file is reached. The driver does the | |
1463 * necessary conversion from Java character format to the national | |
1464 * character set in the database. | |
1465 * | |
1466 * @param i the first parameter is 1, the second is 2, ... | |
1467 * @param value the parameter value | |
1468 * @param length the number of characters in the parameter data. | |
1469 * @throws SQLException if a database access error occurs | |
1470 * @throws SQLFeatureNotSupportedException the JDBC driver does | |
1471 * not support this method | |
1472 */ | |
1473 @Override | |
1474 public void setNCharacterStream(int i, Reader value, long length) | |
1475 throws SQLException | |
1476 { | |
1477 throw newSQLFeatureNotSupportedException("setNCharacterStream"); | |
1478 } | |
1479 | |
1480 /** | |
1481 * Sets the designated parameter to a java.sql.NClob object. The | |
1482 * driver converts this to a SQL NCLOB value when it sends it to the | |
1483 * database. | |
1484 * | |
1485 * @param i the first parameter is 1, the second is 2, ... | |
1486 * @param value the parameter value | |
1487 * @throws SQLException if a database access error occurs | |
1488 * @throws SQLFeatureNotSupportedException the JDBC driver does | |
1489 * not support this method | |
1490 */ | |
1491 @Override | |
1492 public void setNClob(int i, Reader value) throws SQLException { | |
1493 throw newSQLFeatureNotSupportedException("setNClob"); | |
1494 } | |
1495 | |
1496 /** | |
1497 * Sets the designated parameter to a java.sql.NClob object. The | |
1498 * driver converts this to a SQL NCLOB value when it sends it to the | |
1499 * database. | |
1500 * | |
1501 * @param i the first parameter is 1, the second is 2, ... | |
1502 * @param value the parameter value | |
1503 * @throws SQLException if a database access error occurs | |
1504 * @throws SQLFeatureNotSupportedException the JDBC driver does | |
1505 * not support this method | |
1506 */ | |
1507 @Override | |
1508 public void setNClob(int i, NClob value) throws SQLException { | |
1509 throw newSQLFeatureNotSupportedException("setNClob"); | |
1510 } | |
1511 | |
1512 /** | |
1513 * Sets the designated parameter to a Reader object. The reader must | |
1514 * contain the number of characters specified by length otherwise a | |
1515 * SQLException will be generated when the PreparedStatement is | |
1516 * executed. This method differs from the setCharacterStream (int, | |
1517 * Reader, int) method because it informs the driver that the | |
1518 * parameter value should be sent to the server as a NCLOB. When the | |
1519 * setCharacterStream method is used, the driver may have to do | |
1520 * extra work to determine whether the parameter data should be sent | |
1521 * to the server as a LONGNVARCHAR or a NCLOB. | |
1522 * | |
1523 * @param i the first parameter is 1, the second is 2, ... | |
1524 * @param r An object that contains the data to set the parameter | |
1525 * value to | |
1526 * @param length the number of characters in the parameter data | |
1527 * @throws SQLException if a database access error occurs | |
1528 * @throws SQLFeatureNotSupportedException the JDBC driver does | |
1529 * not support this method | |
1530 */ | |
1531 @Override | |
1532 public void setNClob(int i, Reader r, long length) throws SQLException { | |
1533 throw newSQLFeatureNotSupportedException("setNClob"); | |
1534 } | |
1535 | |
1536 /** | |
1537 * Sets the designated paramter to the given String object. The | |
1538 * driver converts this to a SQL NCHAR or NVARCHAR or LONGNVARCHAR | |
1539 * value (depending on the argument's size relative to the driver's | |
1540 * limits on NVARCHAR values) when it sends it to the database. | |
1541 * | |
1542 * @param i the first parameter is 1, the second is 2, ... | |
1543 * @param value the parameter value | |
1544 * @throws SQLException if a database access error occurs | |
1545 * @throws SQLFeatureNotSupportedException the JDBC driver does | |
1546 * not support this method | |
1547 */ | |
1548 @Override | |
1549 public void setNString(int i, String value) throws SQLException { | |
1550 throw newSQLFeatureNotSupportedException("setNString"); | |
1551 } | |
1552 | |
1553 /** | |
1554 * Sets the designated parameter to SQL NULL. | |
1555 * | |
1556 * Note: You must specify the parameter's SQL type. | |
1557 * | |
1558 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
1559 * @param sqlType the SQL type code defined in java.sql.Types | |
1560 * @throws SQLException if a database access error occurs | |
1561 */ | |
1562 @Override | |
1563 public void setNull(int parameterIndex, int sqlType) throws SQLException { | |
1564 // we discard the given type here, the backend converts the | |
1565 // value NULL to whatever it needs for the column | |
1566 setValue(parameterIndex, "NULL"); | |
1567 } | |
1568 | |
1569 /** | |
1570 * Sets the designated parameter to SQL NULL. This version of the method | |
1571 * setNull should be used for user-defined types and REF type parameters. | |
1572 * Examples of user-defined types include: STRUCT, DISTINCT, JAVA_OBJECT, | |
1573 * and named array types. | |
1574 * | |
1575 * Note: To be portable, applications must give the SQL type code and the | |
1576 * fully-qualified SQL type name when specifying a NULL user-defined or REF | |
1577 * parameter. In the case of a user-defined type the name is the type name | |
1578 * of the parameter itself. For a REF parameter, the name is the type name | |
1579 * of the referenced type. If a JDBC driver does not need the type code or | |
1580 * type name information, it may ignore it. Although it is intended for | |
1581 * user-defined and Ref parameters, this method may be used to set a null | |
1582 * parameter of any JDBC type. If the parameter does not have a | |
1583 * user-defined or REF type, the given typeName is ignored. | |
1584 * | |
1585 * @param paramIndex the first parameter is 1, the second is 2, ... | |
1586 * @param sqlType a value from java.sql.Types | |
1587 * @param typeName the fully-qualified name of an SQL user-defined type; | |
1588 * ignored if the parameter is not a user-defined type or | |
1589 * REF | |
1590 * @throws SQLException if a database access error occurs | |
1591 */ | |
1592 @Override | |
1593 public void setNull(int paramIndex, int sqlType, String typeName) | |
1594 throws SQLException | |
1595 { | |
1596 // MonetDB/SQL's NULL needs no type | |
1597 setNull(paramIndex, sqlType); | |
1598 } | |
1599 | |
1600 /** | |
1601 * Sets the value of the designated parameter using the given | |
1602 * object. The second parameter must be of type Object; therefore, | |
1603 * the java.lang equivalent objects should be used for built-in | |
1604 * types. | |
1605 * | |
1606 * The JDBC specification specifies a standard mapping from Java | |
1607 * Object types to SQL types. The given argument will be converted | |
1608 * to the corresponding SQL type before being sent to the database. | |
1609 * | |
1610 * Note that this method may be used to pass datatabase-specific | |
1611 * abstract data types, by using a driver-specific Java type. If the | |
1612 * object is of a class implementing the interface SQLData, the JDBC | |
1613 * driver should call the method SQLData.writeSQL to write it to the | |
1614 * SQL data stream. If, on the other hand, the object is of a class | |
1615 * implementing Ref, Blob, Clob, Struct, or Array, the driver should | |
1616 * pass it to the database as a value of the corresponding SQL type. | |
1617 * | |
1618 * This method throws an exception if there is an ambiguity, for | |
1619 * example, if the object is of a class implementing more than one | |
1620 * of the interfaces named above. | |
1621 * | |
1622 * @param index the first parameter is 1, the second is 2, ... | |
1623 * @param x the object containing the input parameter value | |
1624 * @throws SQLException if a database access error occurs or the type of | |
1625 * the given object is ambiguous | |
1626 */ | |
1627 @Override | |
1628 public void setObject(int index, Object x) throws SQLException { | |
1629 setObject(index, x, javaType[getParamIdx(index)]); | |
1630 } | |
1631 | |
1632 /** | |
1633 * Sets the value of the designated parameter with the given object. This | |
1634 * method is like the method setObject below, except that it assumes a scale | |
1635 * of zero. | |
1636 * | |
1637 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
1638 * @param x the object containing the input parameter value | |
1639 * @param targetSqlType the SQL type (as defined in java.sql.Types) to be | |
1640 * sent to the database | |
1641 * @throws SQLException if a database access error occurs | |
1642 */ | |
1643 @Override | |
1644 public void setObject(int parameterIndex, Object x, int targetSqlType) | |
1645 throws SQLException | |
1646 { | |
1647 setObject(parameterIndex, x, targetSqlType, 0); | |
1648 } | |
1649 | |
1650 /** | |
1651 * Sets the value of the designated parameter with the given object. The | |
1652 * second argument must be an object type; for integral values, the | |
1653 * java.lang equivalent objects should be used. | |
1654 * | |
1655 * The given Java object will be converted to the given targetSqlType | |
1656 * before being sent to the database. If the object has a custom mapping | |
1657 * (is of a class implementing the interface SQLData), the JDBC driver | |
1658 * should call the method SQLData.writeSQL to write it to the SQL data | |
1659 * stream. If, on the other hand, the object is of a class implementing | |
1660 * Ref, Blob, Clob, Struct, or Array, the driver should pass it to the | |
1661 * database as a value of the corresponding SQL type. | |
1662 * | |
1663 * Note that this method may be used to pass database-specific abstract | |
1664 * data types. | |
1665 * | |
1666 * To meet the requirements of this interface, the Java object is | |
1667 * converted in the driver, instead of using a SQL CAST construct. | |
1668 * | |
1669 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
1670 * @param x the object containing the input parameter value | |
1671 * @param targetSqlType the SQL type (as defined in java.sql.Types) to | |
1672 * be sent to the database. The scale argument may | |
1673 * further qualify this type. | |
1674 * @param scale for java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types, | |
1675 * this is the number of digits after the decimal | |
1676 * point. For Java Object types InputStream and Reader, | |
1677 * this is the length of the data in the stream or | |
1678 * reader. For all other types, this value will be | |
1679 * ignored. | |
1680 * @throws SQLException if a database access error occurs | |
1681 * @see Types | |
1682 */ | |
1683 @Override | |
1684 public void setObject( | |
1685 int parameterIndex, | |
1686 Object x, | |
1687 int targetSqlType, | |
1688 int scale) | |
1689 throws SQLException | |
1690 { | |
1691 // this is according to table B-5 | |
1692 if (x instanceof String) { | |
1693 switch (targetSqlType) { | |
1694 case Types.TINYINT: | |
1695 case Types.SMALLINT: | |
1696 case Types.INTEGER: | |
1697 { | |
1698 int val; | |
1699 try { | |
1700 val = Integer.parseInt((String)x); | |
1701 } catch (NumberFormatException e) { | |
1702 val = 0; | |
1703 } | |
1704 setInt(parameterIndex, val); | |
1705 } break; | |
1706 case Types.BIGINT: | |
1707 { | |
1708 long val; | |
1709 try { | |
1710 val = Long.parseLong((String)x); | |
1711 } catch (NumberFormatException e) { | |
1712 val = 0; | |
1713 } | |
1714 setLong(parameterIndex, val); | |
1715 } break; | |
1716 case Types.REAL: | |
1717 { | |
1718 float val; | |
1719 try { | |
1720 val = Float.parseFloat((String)x); | |
1721 } catch (NumberFormatException e) { | |
1722 val = 0; | |
1723 } | |
1724 setFloat(parameterIndex, val); | |
1725 } break; | |
1726 case Types.FLOAT: | |
1727 case Types.DOUBLE: | |
1728 { | |
1729 double val; | |
1730 try { | |
1731 val = Double.parseDouble((String)x); | |
1732 } catch (NumberFormatException e) { | |
1733 val = 0; | |
1734 } | |
1735 setDouble(parameterIndex, val); | |
1736 } break; | |
1737 case Types.DECIMAL: | |
1738 case Types.NUMERIC: | |
1739 { | |
1740 BigDecimal val; | |
1741 try { | |
1742 val = new BigDecimal((String)x); | |
1743 } catch (NumberFormatException e) { | |
1744 try { | |
1745 val = new BigDecimal(0.0); | |
1746 } catch (NumberFormatException ex) { | |
1747 throw new SQLException("Internal error: unable to create template BigDecimal: " + ex.getMessage(), "M0M03"); | |
1748 } | |
1749 } | |
1750 val = val.setScale(scale, BigDecimal.ROUND_HALF_UP); | |
1751 setBigDecimal(parameterIndex, val); | |
1752 } break; | |
1753 case Types.BIT: | |
1754 case Types.BOOLEAN: | |
1755 setBoolean(parameterIndex, (Boolean.valueOf((String)x)).booleanValue()); | |
1756 break; | |
1757 case Types.CHAR: | |
1758 case Types.VARCHAR: | |
1759 case Types.LONGVARCHAR: | |
1760 setString(parameterIndex, (String)x); | |
1761 break; | |
1762 case Types.BINARY: | |
1763 case Types.VARBINARY: | |
1764 case Types.LONGVARBINARY: | |
1765 setBytes(parameterIndex, ((String)x).getBytes()); | |
1766 break; | |
1767 case Types.DATE: | |
1768 { | |
1769 java.sql.Date val; | |
1770 try { | |
1771 val = java.sql.Date.valueOf((String)x); | |
1772 } catch (IllegalArgumentException e) { | |
1773 val = new java.sql.Date(0L); | |
1774 } | |
1775 setDate(parameterIndex, val); | |
1776 } break; | |
1777 case Types.TIME: | |
1778 { | |
1779 Time val; | |
1780 try { | |
1781 val = Time.valueOf((String)x); | |
1782 } catch (IllegalArgumentException e) { | |
1783 val = new Time(0L); | |
1784 } | |
1785 setTime(parameterIndex, val); | |
1786 } break; | |
1787 case Types.TIMESTAMP: | |
1788 { | |
1789 Timestamp val; | |
1790 try { | |
1791 val = Timestamp.valueOf((String)x); | |
1792 } catch (IllegalArgumentException e) { | |
1793 val = new Timestamp(0L); | |
1794 } | |
1795 setTimestamp(parameterIndex, val); | |
1796 } break; | |
1797 case Types.NCHAR: | |
1798 case Types.NVARCHAR: | |
1799 case Types.LONGNVARCHAR: | |
1800 throw newSQLFeatureNotSupportedException("setObject() with targetType N[VAR]CHAR"); | |
1801 default: | |
1802 throw new SQLException("Conversion not allowed", "M1M05"); | |
1803 } | |
1804 } else if (x instanceof BigDecimal || | |
1805 x instanceof Byte || | |
1806 x instanceof Short || | |
1807 x instanceof Integer || | |
1808 x instanceof Long || | |
1809 x instanceof Float || | |
1810 x instanceof Double) | |
1811 { | |
1812 Number num = (Number)x; | |
1813 switch (targetSqlType) { | |
1814 case Types.TINYINT: | |
1815 setByte(parameterIndex, num.byteValue()); | |
1816 break; | |
1817 case Types.SMALLINT: | |
1818 setShort(parameterIndex, num.shortValue()); | |
1819 break; | |
1820 case Types.INTEGER: | |
1821 setInt(parameterIndex, num.intValue()); | |
1822 break; | |
1823 case Types.BIGINT: | |
1824 if (x instanceof BigDecimal) { | |
1825 BigDecimal bd = (BigDecimal)x; | |
1826 setLong(parameterIndex, bd.setScale(scale, BigDecimal.ROUND_HALF_UP).longValue()); | |
1827 } else { | |
1828 setLong(parameterIndex, num.longValue()); | |
1829 } | |
1830 break; | |
1831 case Types.REAL: | |
1832 setFloat(parameterIndex, num.floatValue()); | |
1833 break; | |
1834 case Types.FLOAT: | |
1835 case Types.DOUBLE: | |
1836 setDouble(parameterIndex, num.doubleValue()); | |
1837 break; | |
1838 case Types.DECIMAL: | |
1839 case Types.NUMERIC: | |
1840 if (x instanceof BigDecimal) { | |
1841 setBigDecimal(parameterIndex, (BigDecimal)x); | |
1842 } else { | |
1843 setBigDecimal(parameterIndex, | |
1844 new BigDecimal(num.doubleValue())); | |
1845 } | |
1846 break; | |
1847 case Types.BIT: | |
1848 case Types.BOOLEAN: | |
1849 if (num.doubleValue() != 0.0) { | |
1850 setBoolean(parameterIndex, true); | |
1851 } else { | |
1852 setBoolean(parameterIndex, false); | |
1853 } | |
1854 break; | |
1855 case Types.CHAR: | |
1856 case Types.VARCHAR: | |
1857 case Types.LONGVARCHAR: | |
1858 setString(parameterIndex, x.toString()); | |
1859 break; | |
1860 default: | |
1861 throw new SQLException("Conversion not allowed", "M1M05"); | |
1862 } | |
1863 } else if (x instanceof Boolean) { | |
1864 boolean val = ((Boolean)x).booleanValue(); | |
1865 switch (targetSqlType) { | |
1866 case Types.TINYINT: | |
1867 setByte(parameterIndex, (byte)(val ? 1 : 0)); | |
1868 break; | |
1869 case Types.SMALLINT: | |
1870 setShort(parameterIndex, (short)(val ? 1 : 0)); | |
1871 break; | |
1872 case Types.INTEGER: | |
1873 setInt(parameterIndex, (val ? 1 : 0)); // do not cast to (int) as it generates a compiler warning | |
1874 break; | |
1875 case Types.BIGINT: | |
1876 setLong(parameterIndex, (long)(val ? 1 : 0)); | |
1877 break; | |
1878 case Types.REAL: | |
1879 setFloat(parameterIndex, (float)(val ? 1.0 : 0.0)); | |
1880 break; | |
1881 case Types.FLOAT: | |
1882 case Types.DOUBLE: | |
1883 setDouble(parameterIndex, (val ? 1.0 : 0.0)); // do no cast to (double) as it generates a compiler warning | |
1884 break; | |
1885 case Types.DECIMAL: | |
1886 case Types.NUMERIC: | |
1887 { | |
1888 BigDecimal dec; | |
1889 try { | |
1890 dec = new BigDecimal(val ? 1.0 : 0.0); | |
1891 } catch (NumberFormatException e) { | |
1892 throw new SQLException("Internal error: unable to create template BigDecimal: " + e.getMessage(), "M0M03"); | |
1893 } | |
1894 setBigDecimal(parameterIndex, dec); | |
1895 } break; | |
1896 case Types.BIT: | |
1897 case Types.BOOLEAN: | |
1898 setBoolean(parameterIndex, val); | |
1899 break; | |
1900 case Types.CHAR: | |
1901 case Types.VARCHAR: | |
1902 case Types.LONGVARCHAR: | |
1903 setString(parameterIndex, "" + val); | |
1904 break; | |
1905 default: | |
1906 throw new SQLException("Conversion not allowed", "M1M05"); | |
1907 } | |
1908 } else if (x instanceof BigInteger) { | |
1909 BigInteger num = (BigInteger)x; | |
1910 switch (targetSqlType) { | |
1911 case Types.BIGINT: | |
1912 setLong(parameterIndex, num.longValue()); | |
1913 break; | |
1914 case Types.CHAR: | |
1915 case Types.VARCHAR: | |
1916 case Types.LONGVARCHAR: | |
1917 setString(parameterIndex, x.toString()); | |
1918 break; | |
1919 default: | |
1920 throw new SQLException("Conversion not allowed", "M1M05"); | |
1921 } | |
1922 } else if (x instanceof byte[]) { | |
1923 switch (targetSqlType) { | |
1924 case Types.BINARY: | |
1925 case Types.VARBINARY: | |
1926 case Types.LONGVARBINARY: | |
1927 setBytes(parameterIndex, (byte[])x); | |
1928 break; | |
1929 default: | |
1930 throw new SQLException("Conversion not allowed", "M1M05"); | |
1931 } | |
1932 } else if (x instanceof java.sql.Date || | |
1933 x instanceof Timestamp || | |
1934 x instanceof Time || | |
1935 x instanceof Calendar || | |
1936 x instanceof java.util.Date) | |
1937 { | |
1938 switch (targetSqlType) { | |
1939 case Types.CHAR: | |
1940 case Types.VARCHAR: | |
1941 case Types.LONGVARCHAR: | |
1942 setString(parameterIndex, x.toString()); | |
1943 break; | |
1944 case Types.DATE: | |
1945 if (x instanceof Time) { | |
1946 throw new SQLException("Conversion not allowed", "M1M05"); | |
1947 } else if (x instanceof java.sql.Date) { | |
1948 setDate(parameterIndex, (java.sql.Date)x); | |
1949 } else if (x instanceof Timestamp) { | |
1950 setDate(parameterIndex, new java.sql.Date(((Timestamp)x).getTime())); | |
1951 } else if (x instanceof java.util.Date) { | |
1952 setDate(parameterIndex, new java.sql.Date( | |
1953 ((java.util.Date)x).getTime())); | |
1954 } else if (x instanceof Calendar) { | |
1955 setDate(parameterIndex, new java.sql.Date( | |
1956 ((Calendar)x).getTimeInMillis())); | |
1957 } | |
1958 break; | |
1959 case Types.TIME: | |
1960 if (x instanceof Time) { | |
1961 setTime(parameterIndex, (Time)x); | |
1962 } else if (x instanceof java.sql.Date) { | |
1963 throw new SQLException("Conversion not allowed", "M1M05"); | |
1964 } else if (x instanceof Timestamp) { | |
1965 setTime(parameterIndex, new Time(((Timestamp)x).getTime())); | |
1966 } else if (x instanceof java.util.Date) { | |
1967 setTime(parameterIndex, new java.sql.Time( | |
1968 ((java.util.Date)x).getTime())); | |
1969 } else if (x instanceof Calendar) { | |
1970 setTime(parameterIndex, new java.sql.Time( | |
1971 ((Calendar)x).getTimeInMillis())); | |
1972 } | |
1973 break; | |
1974 case Types.TIMESTAMP: | |
1975 if (x instanceof Time) { | |
1976 throw new SQLException("Conversion not allowed", "M1M05"); | |
1977 } else if (x instanceof java.sql.Date) { | |
1978 setTimestamp(parameterIndex, new Timestamp(((java.sql.Date)x).getTime())); | |
1979 } else if (x instanceof Timestamp) { | |
1980 setTimestamp(parameterIndex, (Timestamp)x); | |
1981 } else if (x instanceof java.util.Date) { | |
1982 setTimestamp(parameterIndex, new java.sql.Timestamp( | |
1983 ((java.util.Date)x).getTime())); | |
1984 } else if (x instanceof Calendar) { | |
1985 setTimestamp(parameterIndex, new java.sql.Timestamp( | |
1986 ((Calendar)x).getTimeInMillis())); | |
1987 } | |
1988 break; | |
1989 default: | |
1990 throw new SQLException("Conversion not allowed", "M1M05"); | |
1991 } | |
1992 } else if (x instanceof Array) { | |
1993 setArray(parameterIndex, (Array)x); | |
1994 } else if (x instanceof Blob) { | |
1995 setBlob(parameterIndex, (Blob)x); | |
1996 } else if (x instanceof Clob) { | |
1997 setClob(parameterIndex, (Clob)x); | |
1998 } else if (x instanceof Struct) { | |
1999 // I have no idea how to do this... | |
2000 throw newSQLFeatureNotSupportedException("setObject() with object of type Struct"); | |
2001 } else if (x instanceof Ref) { | |
2002 setRef(parameterIndex, (Ref)x); | |
2003 } else if (x instanceof java.net.URL) { | |
2004 setURL(parameterIndex, (java.net.URL)x); | |
2005 } else if (x instanceof RowId) { | |
2006 setRowId(parameterIndex, (RowId)x); | |
2007 } else if (x instanceof NClob) { | |
2008 throw newSQLFeatureNotSupportedException("setObject() with object of type NClob"); | |
2009 } else if (x instanceof SQLXML) { | |
2010 throw newSQLFeatureNotSupportedException("setObject() with object of type SQLXML"); | |
2011 } else if (x instanceof SQLData) { // not in JDBC4.1??? | |
2012 SQLData sx = (SQLData)x; | |
2013 final int paramnr = parameterIndex; | |
2014 final String sqltype = sx.getSQLTypeName(); | |
2015 SQLOutput out = new SQLOutput() { | |
2016 @Override | |
2017 public void writeString(String x) throws SQLException { | |
2018 // special situation, this is when a string | |
2019 // representation is given, but we need to prefix it | |
2020 // with the actual sqltype the server expects, or we | |
2021 // will get an error back | |
2022 setValue( | |
2023 paramnr, | |
2024 sqltype + " '" + x.replaceAll("\\\\", "\\\\\\\\").replaceAll("'", "\\\\'") + "'" | |
2025 ); | |
2026 } | |
2027 | |
2028 @Override | |
2029 public void writeBoolean(boolean x) throws SQLException { | |
2030 setBoolean(paramnr, x); | |
2031 } | |
2032 | |
2033 @Override | |
2034 public void writeByte(byte x) throws SQLException { | |
2035 setByte(paramnr, x); | |
2036 } | |
2037 | |
2038 @Override | |
2039 public void writeShort(short x) throws SQLException { | |
2040 setShort(paramnr, x); | |
2041 } | |
2042 | |
2043 @Override | |
2044 public void writeInt(int x) throws SQLException { | |
2045 setInt(paramnr, x); | |
2046 } | |
2047 | |
2048 @Override | |
2049 public void writeLong(long x) throws SQLException { | |
2050 setLong(paramnr, x); | |
2051 } | |
2052 | |
2053 @Override | |
2054 public void writeFloat(float x) throws SQLException { | |
2055 setFloat(paramnr, x); | |
2056 } | |
2057 | |
2058 @Override | |
2059 public void writeDouble(double x) throws SQLException { | |
2060 setDouble(paramnr, x); | |
2061 } | |
2062 | |
2063 @Override | |
2064 public void writeBigDecimal(BigDecimal x) throws SQLException { | |
2065 setBigDecimal(paramnr, x); | |
2066 } | |
2067 | |
2068 @Override | |
2069 public void writeBytes(byte[] x) throws SQLException { | |
2070 setBytes(paramnr, x); | |
2071 } | |
2072 | |
2073 @Override | |
2074 public void writeDate(java.sql.Date x) throws SQLException { | |
2075 setDate(paramnr, x); | |
2076 } | |
2077 | |
2078 @Override | |
2079 public void writeTime(java.sql.Time x) throws SQLException { | |
2080 setTime(paramnr, x); | |
2081 } | |
2082 | |
2083 @Override | |
2084 public void writeTimestamp(Timestamp x) throws SQLException { | |
2085 setTimestamp(paramnr, x); | |
2086 } | |
2087 | |
2088 @Override | |
2089 public void writeCharacterStream(Reader x) throws SQLException { | |
2090 setCharacterStream(paramnr, x); | |
2091 } | |
2092 | |
2093 @Override | |
2094 public void writeAsciiStream(InputStream x) throws SQLException { | |
2095 setAsciiStream(paramnr, x); | |
2096 } | |
2097 | |
2098 @Override | |
2099 public void writeBinaryStream(InputStream x) throws SQLException { | |
2100 setBinaryStream(paramnr, x); | |
2101 } | |
2102 | |
2103 @Override | |
2104 public void writeObject(SQLData x) throws SQLException { | |
2105 setObject(paramnr, x); | |
2106 } | |
2107 | |
2108 @Override | |
2109 public void writeRef(Ref x) throws SQLException { | |
2110 setRef(paramnr, x); | |
2111 } | |
2112 | |
2113 @Override | |
2114 public void writeBlob(Blob x) throws SQLException { | |
2115 setBlob(paramnr, x); | |
2116 } | |
2117 | |
2118 @Override | |
2119 public void writeClob(Clob x) throws SQLException { | |
2120 setClob(paramnr, x); | |
2121 } | |
2122 | |
2123 @Override | |
2124 public void writeStruct(Struct x) throws SQLException { | |
2125 setObject(paramnr, x); | |
2126 } | |
2127 | |
2128 @Override | |
2129 public void writeArray(Array x) throws SQLException { | |
2130 setArray(paramnr, x); | |
2131 } | |
2132 | |
2133 @Override | |
2134 public void writeURL(URL x) throws SQLException { | |
2135 setURL(paramnr, x); | |
2136 } | |
2137 | |
2138 @Override | |
2139 public void writeNString(String x) throws SQLException { | |
2140 setNString(paramnr, x); | |
2141 } | |
2142 | |
2143 @Override | |
2144 public void writeNClob(NClob x) throws SQLException { | |
2145 setNClob(paramnr, x); | |
2146 } | |
2147 | |
2148 @Override | |
2149 public void writeRowId(RowId x) throws SQLException { | |
2150 setRowId(paramnr, x); | |
2151 } | |
2152 | |
2153 @Override | |
2154 public void writeSQLXML(SQLXML x) throws SQLException { | |
2155 setSQLXML(paramnr, x); | |
2156 } | |
2157 }; | |
2158 sx.writeSQL(out); | |
2159 } else { // java Class | |
2160 throw newSQLFeatureNotSupportedException("setObject() with object of type Class"); | |
2161 } | |
2162 } | |
2163 | |
2164 /** | |
2165 * Sets the designated parameter to the given REF(<structured-type>) value. | |
2166 * The driver converts this to an SQL REF value when it sends it to the | |
2167 * database. | |
2168 * | |
2169 * @param i the first parameter is 1, the second is 2, ... | |
2170 * @param x an SQL REF value | |
2171 * @throws SQLException if a database access error occurs | |
2172 * @throws SQLFeatureNotSupportedException the JDBC driver does | |
2173 * not support this method | |
2174 */ | |
2175 @Override | |
2176 public void setRef(int i, Ref x) throws SQLException { | |
2177 throw newSQLFeatureNotSupportedException("setRef"); | |
2178 } | |
2179 | |
2180 /** | |
2181 * Sets the designated parameter to the given java.sql.RowId object. | |
2182 * The driver converts this to a SQL ROWID value when it sends it to | |
2183 * the database. | |
2184 * | |
2185 * @param i the first parameter is 1, the second is 2, ... | |
2186 * @param x the parameter value | |
2187 * @throws SQLException if a database access error occurs | |
2188 * @throws SQLFeatureNotSupportedException the JDBC driver does | |
2189 * not support this method | |
2190 */ | |
2191 @Override | |
2192 public void setRowId(int i, RowId x) throws SQLException { | |
2193 throw newSQLFeatureNotSupportedException("setRowId"); | |
2194 } | |
2195 | |
2196 /** | |
2197 * Sets the designated parameter to the given Java short value. The driver | |
2198 * converts this to an SQL SMALLINT value when it sends it to the database. | |
2199 * | |
2200 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
2201 * @param x the parameter value | |
2202 * @throws SQLException if a database access error occurs | |
2203 */ | |
2204 @Override | |
2205 public void setShort(int parameterIndex, short x) throws SQLException { | |
2206 setValue(parameterIndex, "" + x); | |
2207 } | |
2208 | |
2209 /** | |
2210 * Sets the designated parameter to the given Java String value. The driver | |
2211 * converts this to an SQL VARCHAR or LONGVARCHAR value (depending on the | |
2212 * argument's size relative to the driver's limits on VARCHAR values) when | |
2213 * it sends it to the database. | |
2214 * | |
2215 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
2216 * @param x the parameter value | |
2217 * @throws SQLException if a database access error occurs | |
2218 */ | |
2219 @Override | |
2220 public void setString(int parameterIndex, String x) throws SQLException { | |
2221 if (x == null) { | |
2222 setNull(parameterIndex, -1); | |
2223 return; | |
2224 } | |
2225 | |
2226 setValue( | |
2227 parameterIndex, | |
2228 "'" + x.replaceAll("\\\\", "\\\\\\\\").replaceAll("'", "\\\\'") + "'" | |
2229 ); | |
2230 } | |
2231 | |
2232 /** | |
2233 * Sets the designated parameter to the given java.sql.SQLXML | |
2234 * object. The driver converts this to an SQL XML value when it | |
2235 * sends it to the database. | |
2236 * | |
2237 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
2238 * @param x a SQLXML object that maps an SQL XML value | |
2239 * @throws SQLException if a database access error occurs | |
2240 * @throws SQLFeatureNotSupportedException the JDBC driver does | |
2241 * not support this method | |
2242 */ | |
2243 @Override | |
2244 public void setSQLXML(int parameterIndex, SQLXML x) throws SQLException { | |
2245 throw newSQLFeatureNotSupportedException("setSQLXML"); | |
2246 } | |
2247 | |
2248 /** | |
2249 * Sets the designated parameter to the given java.sql.Time value. | |
2250 * The driver converts this to an SQL TIME value when it sends it to | |
2251 * the database. | |
2252 * | |
2253 * @param index the first parameter is 1, the second is 2, ... | |
2254 * @param x the parameter value | |
2255 * @throws SQLException if a database access error occurs | |
2256 */ | |
2257 @Override | |
2258 public void setTime(int index, Time x) throws SQLException { | |
2259 setTime(index, x, null); | |
2260 } | |
2261 | |
2262 /** | |
2263 * Sets the designated parameter to the given java.sql.Time value, | |
2264 * using the given Calendar object. The driver uses the Calendar | |
2265 * object to construct an SQL TIME value, which the driver then | |
2266 * sends to the database. With a Calendar object, the driver can | |
2267 * calculate the time taking into account a custom timezone. If no | |
2268 * Calendar object is specified, the driver uses the default | |
2269 * timezone, which is that of the virtual machine running the | |
2270 * application. | |
2271 * | |
2272 * @param index the first parameter is 1, the second is 2, ... | |
2273 * @param x the parameter value | |
2274 * @param cal the Calendar object the driver will use to construct the time | |
2275 * @throws SQLException if a database access error occurs | |
2276 */ | |
2277 @Override | |
2278 public void setTime(int index, Time x, Calendar cal) | |
2279 throws SQLException | |
2280 { | |
2281 if (x == null) { | |
2282 setNull(index, -1); | |
2283 return; | |
2284 } | |
2285 | |
2286 boolean hasTimeZone = monetdbType[getParamIdx(index)].endsWith("tz"); | |
2287 if (hasTimeZone) { | |
2288 // timezone shouldn't matter, since the server is timezone | |
2289 // aware in this case | |
2290 String RFC822 = mTimeZ.format(x); | |
2291 setValue(index, "timetz '" + | |
2292 RFC822.substring(0, 15) + ":" + RFC822.substring(15) + "'"); | |
2293 } else { | |
2294 // server is not timezone aware for this field, and no | |
2295 // calendar given, since we told the server our timezone at | |
2296 // connection creation, we can just write a plain timestamp | |
2297 // here | |
2298 if (cal == null) { | |
2299 setValue(index, "time '" + x.toString() + "'"); | |
2300 } else { | |
2301 mTime.setTimeZone(cal.getTimeZone()); | |
2302 setValue(index, "time '" + mTime.format(x) + "'"); | |
2303 } | |
2304 } | |
2305 } | |
2306 | |
2307 /** | |
2308 * Sets the designated parameter to the given java.sql.Timestamp | |
2309 * value. The driver converts this to an SQL TIMESTAMP value when | |
2310 * it sends it to the database. | |
2311 * | |
2312 * @param index the first parameter is 1, the second is 2, ... | |
2313 * @param x the parameter value | |
2314 * @throws SQLException if a database access error occurs | |
2315 */ | |
2316 @Override | |
2317 public void setTimestamp(int index, Timestamp x) | |
2318 throws SQLException | |
2319 { | |
2320 setTimestamp(index, x, null); | |
2321 } | |
2322 | |
2323 /** | |
2324 * Sets the designated parameter to the given java.sql.Timestamp | |
2325 * value, using the given Calendar object. The driver uses the | |
2326 * Calendar object to construct an SQL TIMESTAMP value, which the | |
2327 * driver then sends to the database. With a Calendar object, the | |
2328 * driver can calculate the timestamp taking into account a custom | |
2329 * timezone. If no Calendar object is specified, the driver uses the | |
2330 * default timezone, which is that of the virtual machine running | |
2331 * the application. | |
2332 * | |
2333 * @param index the first parameter is 1, the second is 2, ... | |
2334 * @param x the parameter value | |
2335 * @param cal the Calendar object the driver will use to construct the | |
2336 * timestamp | |
2337 * @throws SQLException if a database access error occurs | |
2338 */ | |
2339 @Override | |
2340 public void setTimestamp(int index, Timestamp x, Calendar cal) | |
2341 throws SQLException | |
2342 { | |
2343 if (x == null) { | |
2344 setNull(index, -1); | |
2345 return; | |
2346 } | |
2347 | |
2348 boolean hasTimeZone = monetdbType[getParamIdx(index)].endsWith("tz"); | |
2349 if (hasTimeZone) { | |
2350 // timezone shouldn't matter, since the server is timezone | |
2351 // aware in this case | |
2352 String RFC822 = mTimestampZ.format(x); | |
2353 setValue(index, "timestamptz '" + | |
2354 RFC822.substring(0, 26) + ":" + RFC822.substring(26) + "'"); | |
2355 } else { | |
2356 // server is not timezone aware for this field, and no | |
2357 // calendar given, since we told the server our timezone at | |
2358 // connection creation, we can just write a plain timestamp | |
2359 // here | |
2360 if (cal == null) { | |
2361 setValue(index, "timestamp '" + x.toString() + "'"); | |
2362 } else { | |
2363 mTimestamp.setTimeZone(cal.getTimeZone()); | |
2364 setValue(index, "timestamp '" + mTimestamp.format(x) + "'"); | |
2365 } | |
2366 } | |
2367 } | |
2368 | |
2369 /** | |
2370 * Sets the designated parameter to the given input stream, which will have | |
2371 * the specified number of bytes. A Unicode character has two bytes, with | |
2372 * the first byte being the high byte, and the second being the low byte. | |
2373 * When a very large Unicode value is input to a LONGVARCHAR parameter, it | |
2374 * may be more practical to send it via a java.io.InputStream object. The | |
2375 * data will be read from the stream as needed until end-of-file is | |
2376 * reached. The JDBC driver will do any necessary conversion from Unicode | |
2377 * to the database char format. | |
2378 * | |
2379 * Note: This stream object can either be a standard Java stream object or | |
2380 * your own subclass that implements the standard interface. | |
2381 * | |
2382 * @deprecated | |
2383 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
2384 * @param x a java.io.InputStream object that contains the Unicode | |
2385 * parameter value as two-byte Unicode characters | |
2386 * @param length the number of bytes in the stream | |
2387 * @throws SQLException if a database access error occurs | |
2388 */ | |
2389 @Override | |
2390 @Deprecated | |
2391 public void setUnicodeStream(int parameterIndex, InputStream x, int length) | |
2392 throws SQLException | |
2393 { | |
2394 throw newSQLFeatureNotSupportedException("setUnicodeStream"); | |
2395 } | |
2396 | |
2397 /** | |
2398 * Sets the designated parameter to the given java.net.URL value. The | |
2399 * driver converts this to an SQL DATALINK value when it sends it to the | |
2400 * database. | |
2401 * | |
2402 * @param parameterIndex the first parameter is 1, the second is 2, ... | |
2403 * @param x the java.net.URL object to be set | |
2404 * @throws SQLException if a database access error occurs | |
2405 */ | |
2406 @Override | |
2407 public void setURL(int parameterIndex, URL x) throws SQLException { | |
2408 throw newSQLFeatureNotSupportedException("setURL"); | |
2409 } | |
2410 | |
2411 /** | |
2412 * Releases this PreparedStatement object's database and JDBC | |
2413 * resources immediately instead of waiting for this to happen when | |
2414 * it is automatically closed. It is generally good practice to | |
2415 * release resources as soon as you are finished with them to avoid | |
2416 * tying up database resources. | |
2417 * | |
2418 * Calling the method close on a PreparedStatement object that is | |
2419 * already closed has no effect. | |
2420 * | |
2421 * <b>Note:</b> A PreparedStatement object is automatically closed | |
2422 * when it is garbage collected. When a Statement object is closed, | |
2423 * its current ResultSet object, if one exists, is also closed. | |
2424 */ | |
2425 @Override | |
2426 public void close() { | |
2427 try { | |
2428 if (!closed && id != -1) | |
2429 connection.sendControlCommand("release " + id); | |
2430 } catch (SQLException e) { | |
2431 // probably server closed connection | |
2432 } | |
2433 super.close(); | |
2434 } | |
2435 | |
2436 /** | |
2437 * Call close to release the server-sided handle for this | |
2438 * PreparedStatement. | |
2439 */ | |
2440 @Override | |
2441 protected void finalize() { | |
2442 close(); | |
2443 } | |
2444 | |
2445 //== end methods interface PreparedStatement | |
2446 | |
2447 /** | |
2448 * Sets the given index with the supplied value. If the given index is | |
2449 * out of bounds, and SQLException is thrown. The given value should | |
2450 * never be null. | |
2451 * | |
2452 * @param index the parameter index | |
2453 * @param val the exact String representation to set | |
2454 * @throws SQLException if the given index is out of bounds | |
2455 */ | |
2456 void setValue(int index, String val) throws SQLException { | |
2457 values[getParamIdx(index)] = val; | |
2458 } | |
2459 | |
2460 /** | |
2461 * Transforms the prepare query into a simple SQL query by replacing | |
2462 * the ?'s with the given column contents. | |
2463 * Mind that the JDBC specs allow `reuse' of a value for a column over | |
2464 * multiple executes. | |
2465 * | |
2466 * @return the simple SQL string for the prepare query | |
2467 * @throws SQLException if not all columns are set | |
2468 */ | |
2469 private String transform() throws SQLException { | |
2470 StringBuilder buf = new StringBuilder(8 + 12 * size); | |
2471 buf.append("exec "); | |
2472 buf.append(id); | |
2473 buf.append('('); | |
2474 // check if all columns are set and do a replace | |
2475 int col = 0; | |
2476 for (int i = 0; i < size; i++) { | |
2477 if (column[i] != null) | |
2478 continue; | |
2479 col++; | |
2480 if (col > 1) | |
2481 buf.append(','); | |
2482 if (values[i] == null) throw | |
2483 new SQLException("Cannot execute, parameter " + col + " is missing.", "M1M05"); | |
2484 | |
2485 buf.append(values[i]); | |
2486 } | |
2487 buf.append(')'); | |
2488 | |
2489 return buf.toString(); | |
2490 } | |
2491 | |
2492 /** | |
2493 * Small helper method that formats the "Method ... not implemented" message | |
2494 * and creates a new SQLFeatureNotSupportedException object | |
2495 * whose SQLState is set to "0A000". | |
2496 * | |
2497 * @param name the method name | |
2498 * @return a new created SQLFeatureNotSupportedException object with SQLState 0A000 | |
2499 */ | |
2500 private final static SQLFeatureNotSupportedException newSQLFeatureNotSupportedException(String name) { | |
2501 return new SQLFeatureNotSupportedException("Method " + name + " not implemented", "0A000"); | |
2502 } | |
2503 } |