1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
|
package postgresql;
import java.io.*;
import java.math.*;
import java.sql.*;
import java.text.*;
import java.util.*;
/**
* @version 1.0 15-APR-1997
* @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
*
* A SQL Statement is pre-compiled and stored in a PreparedStatement object.
* This object can then be used to efficiently execute this statement multiple
* times.
*
* <B>Note:</B> The setXXX methods for setting IN parameter values must
* specify types that are compatible with the defined SQL type of the input
* parameter. For instance, if the IN parameter has SQL type Integer, then
* setInt should be used.
*
* If arbitrary parameter type conversions are required, then the setObject
* method should be used with a target SQL type.
*
* @see ResultSet
* @see java.sql.PreparedStatement
*/
public class PreparedStatement extends Statement implements java.sql.PreparedStatement
{
String sql;
String[] templateStrings;
String[] inStrings;
Connection connection;
/**
* Constructor for the PreparedStatement class. Split the SQL statement
* into segments - separated by the arguments. When we rebuild the
* thing with the arguments, we can substitute the args and join the
* whole thing together.
*
* @param conn the instanatiating connection
* @param sql the SQL statement with ? for IN markers
* @exception SQLException if something bad occurs
*/
public PreparedStatement(Connection connection, String sql) throws SQLException
{
super(connection);
Vector v = new Vector();
boolean inQuotes = false;
int lastParmEnd = 0, i;
this.sql = sql;
this.connection = connection;
for (i = 0; i < sql.length(); ++i)
{
int c = sql.charAt(i);
if (c == '\'')
inQuotes = !inQuotes;
if (c == '?' && !inQuotes)
{
v.addElement(sql.substring (lastParmEnd, i));
lastParmEnd = i + 1;
}
}
v.addElement(sql.substring (lastParmEnd, sql.length()));
templateStrings = new String[v.size()];
inStrings = new String[v.size() - 1];
clearParameters();
for (i = 0 ; i < templateStrings.length; ++i)
templateStrings[i] = (String)v.elementAt(i);
}
/**
* A Prepared SQL query is executed and its ResultSet is returned
*
* @return a ResultSet that contains the data produced by the
* query - never null
* @exception SQLException if a database access error occurs
*/
public java.sql.ResultSet executeQuery() throws SQLException
{
StringBuffer s = new StringBuffer();
int i;
for (i = 0 ; i < inStrings.length ; ++i)
{
if (inStrings[i] == null)
throw new SQLException("No value specified for parameter " + (i + 1));
s.append (templateStrings[i]);
s.append (inStrings[i]);
}
s.append(templateStrings[inStrings.length]);
return super.executeQuery(s.toString()); // in Statement class
}
/**
* Execute a SQL INSERT, UPDATE or DELETE statement. In addition,
* SQL statements that return nothing such as SQL DDL statements can
* be executed.
*
* @return either the row count for INSERT, UPDATE or DELETE; or
* 0 for SQL statements that return nothing.
* @exception SQLException if a database access error occurs
*/
public int executeUpdate() throws SQLException
{
StringBuffer s = new StringBuffer();
int i;
for (i = 0 ; i < inStrings.length ; ++i)
{
if (inStrings[i] == null)
throw new SQLException("No value specified for parameter " + (i + 1));
s.append (templateStrings[i]);
s.append (inStrings[i]);
}
s.append(templateStrings[inStrings.length]);
return super.executeUpdate(s.toString()); // in Statement class
}
/**
* Set a parameter to SQL NULL
*
* <B>Note:</B> You must specify the parameters SQL type (although
* PostgreSQL ignores it)
*
* @param parameterIndex the first parameter is 1, etc...
* @param sqlType the SQL type code defined in java.sql.Types
* @exception SQLException if a database access error occurs
*/
public void setNull(int parameterIndex, int sqlType) throws SQLException
{
set(parameterIndex, "null");
}
/**
* Set a parameter to a Java boolean value. The driver converts this
* to a SQL BIT value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public void setBoolean(int parameterIndex, boolean x) throws SQLException
{
set(parameterIndex, x ? "'t'" : "'f'");
}
/**
* Set a parameter to a Java byte value. The driver converts this to
* a SQL TINYINT value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public void setByte(int parameterIndex, byte x) throws SQLException
{
set(parameterIndex, (new Integer(x)).toString());
}
/**
* Set a parameter to a Java short value. The driver converts this
* to a SQL SMALLINT value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public void setShort(int parameterIndex, short x) throws SQLException
{
set(parameterIndex, (new Integer(x)).toString());
}
/**
* Set a parameter to a Java int value. The driver converts this to
* a SQL INTEGER value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public void setInt(int parameterIndex, int x) throws SQLException
{
set(parameterIndex, (new Integer(x)).toString());
}
/**
* Set a parameter to a Java long value. The driver converts this to
* a SQL BIGINT value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public void setLong(int parameterIndex, long x) throws SQLException
{
set(parameterIndex, (new Long(x)).toString());
}
/**
* Set a parameter to a Java float value. The driver converts this
* to a SQL FLOAT value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public void setFloat(int parameterIndex, float x) throws SQLException
{
set(parameterIndex, (new Float(x)).toString());
}
/**
* Set a parameter to a Java double value. The driver converts this
* to a SQL DOUBLE value when it sends it to the database
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public void setDouble(int parameterIndex, double x) throws SQLException
{
set(parameterIndex, (new Double(x)).toString());
}
/**
* Set a parameter to a java.lang.BigDecimal value. The driver
* converts this to a SQL NUMERIC value when it sends it to the
* database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException
{
set(parameterIndex, x.toString());
}
/**
* Set a parameter to a Java String value. The driver converts this
* to a SQL VARCHAR or LONGVARCHAR value (depending on the arguments
* size relative to the driver's limits on VARCHARs) when it sends it
* to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public void setString(int parameterIndex, String x) throws SQLException
{
StringBuffer b = new StringBuffer();
int i;
b.append('\'');
for (i = 0 ; i < x.length() ; ++i)
{
char c = x.charAt(i);
if (c == '\\' || c == '\'')
b.append((char)'\\');
b.append(c);
}
b.append('\'');
set(parameterIndex, b.toString());
}
/**
* Set a parameter to a Java array of bytes. The driver converts this
* to a SQL VARBINARY or LONGVARBINARY (depending on the argument's
* size relative to the driver's limits on VARBINARYs) when it sends
* it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public void setBytes(int parameterIndex, byte x[]) throws SQLException
{
throw new SQLException("Binary Data not supported");
}
/**
* Set a parameter to a java.sql.Date value. The driver converts this
* to a SQL DATE value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
{
DateFormat df = DateFormat.getDateInstance();
set(parameterIndex, "'" + df.format(x) + "'");
}
/**
* Set a parameter to a java.sql.Time value. The driver converts
* this to a SQL TIME value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public void setTime(int parameterIndex, Time x) throws SQLException
{
set(parameterIndex, "'" + x.toString() + "'");
}
/**
* Set a parameter to a java.sql.Timestamp value. The driver converts
* this to a SQL TIMESTAMP value when it sends it to the database.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
{
set(parameterIndex, "'" + x.toString() + "'");
}
/**
* When a very large ASCII value is input to a LONGVARCHAR parameter,
* it may be more practical to send it via a java.io.InputStream.
* JDBC will read the data from the stream as needed, until it reaches
* end-of-file. The JDBC driver will do any necessary conversion from
* ASCII to the database char format.
*
* <B>Note:</B> This stream object can either be a standard Java
* stream object or your own subclass that implements the standard
* interface.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @param length the number of bytes in the stream
* @exception SQLException if a database access error occurs
*/
public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException
{
setBinaryStream(parameterIndex, x, length);
}
/**
* When a very large Unicode value is input to a LONGVARCHAR parameter,
* it may be more practical to send it via a java.io.InputStream.
* JDBC will read the data from the stream as needed, until it reaches
* end-of-file. The JDBC driver will do any necessary conversion from
* UNICODE to the database char format.
*
* <B>Note:</B> This stream object can either be a standard Java
* stream object or your own subclass that implements the standard
* interface.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException
{
setBinaryStream(parameterIndex, x, length);
}
/**
* When a very large binary value is input to a LONGVARBINARY parameter,
* it may be more practical to send it via a java.io.InputStream.
* JDBC will read the data from the stream as needed, until it reaches
* end-of-file.
*
* <B>Note:</B> This stream object can either be a standard Java
* stream object or your own subclass that implements the standard
* interface.
*
* @param parameterIndex the first parameter is 1...
* @param x the parameter value
* @exception SQLException if a database access error occurs
*/
public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException
{
throw new SQLException("InputStream as parameter not supported");
}
/**
* In general, parameter values remain in force for repeated used of a
* Statement. Setting a parameter value automatically clears its
* previous value. However, in coms cases, it is useful to immediately
* release the resources used by the current parameter values; this
* can be done by calling clearParameters
*
* @exception SQLException if a database access error occurs
*/
public void clearParameters() throws SQLException
{
int i;
for (i = 0 ; i < inStrings.length ; i++)
inStrings[i] = null;
}
/**
* Set the value of a parameter using an object; use the java.lang
* equivalent objects for integral values.
*
* The given Java object will be converted to the targetSqlType before
* being sent to the database.
*
* note that this method may be used to pass database-specific
* abstract data types. This is done by using a Driver-specific
* Java type and using a targetSqlType of java.sql.Types.OTHER
*
* @param parameterIndex the first parameter is 1...
* @param x the object containing the input parameter value
* @param targetSqlType The SQL type to be send to the database
* @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC
* types this is the number of digits after the decimal. For
* all other types this value will be ignored.
* @exception SQLException if a database access error occurs
*/
public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException
{
switch (targetSqlType)
{
case Types.TINYINT:
case Types.SMALLINT:
case Types.INTEGER:
case Types.BIGINT:
case Types.REAL:
case Types.FLOAT:
case Types.DOUBLE:
case Types.DECIMAL:
case Types.NUMERIC:
if (x instanceof Boolean)
set(parameterIndex, ((Boolean)x).booleanValue() ? "1" : "0");
else
set(parameterIndex, x.toString());
break;
case Types.CHAR:
case Types.VARCHAR:
case Types.LONGVARCHAR:
setString(parameterIndex, x.toString());
case Types.DATE:
setDate(parameterIndex, (java.sql.Date)x);
case Types.TIME:
setTime(parameterIndex, (Time)x);
case Types.TIMESTAMP:
setTimestamp(parameterIndex, (Timestamp)x);
case Types.OTHER:
setString(parameterIndex, ((PG_Object)x).value);
default:
throw new SQLException("Unknown Types value");
}
}
public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException
{
setObject(parameterIndex, x, targetSqlType, 0);
}
public void setObject(int parameterIndex, Object x) throws SQLException
{
if (x instanceof String)
setString(parameterIndex, (String)x);
else if (x instanceof BigDecimal)
setBigDecimal(parameterIndex, (BigDecimal)x);
else if (x instanceof Integer)
setInt(parameterIndex, ((Integer)x).intValue());
else if (x instanceof Long)
setLong(parameterIndex, ((Long)x).longValue());
else if (x instanceof Float)
setFloat(parameterIndex, ((Float)x).floatValue());
else if (x instanceof Double)
setDouble(parameterIndex, ((Double)x).doubleValue());
else if (x instanceof byte[])
setBytes(parameterIndex, (byte[])x);
else if (x instanceof java.sql.Date)
setDate(parameterIndex, (java.sql.Date)x);
else if (x instanceof Time)
setTime(parameterIndex, (Time)x);
else if (x instanceof Timestamp)
setTimestamp(parameterIndex, (Timestamp)x);
else if (x instanceof Boolean)
setBoolean(parameterIndex, ((Boolean)x).booleanValue());
else if (x instanceof PG_Object)
setString(parameterIndex, ((PG_Object)x).value);
else
throw new SQLException("Unknown object type");
}
/**
* Some prepared statements return multiple results; the execute method
* handles these complex statements as well as the simpler form of
* statements handled by executeQuery and executeUpdate
*
* @return true if the next result is a ResultSet; false if it is an
* update count or there are no more results
* @exception SQLException if a database access error occurs
*/
public boolean execute() throws SQLException
{
StringBuffer s = new StringBuffer();
int i;
for (i = 0 ; i < inStrings.length ; ++i)
{
if (inStrings[i] == null)
throw new SQLException("No value specified for parameter " + (i + 1));
s.append (templateStrings[i]);
s.append (inStrings[i]);
}
s.append(templateStrings[inStrings.length]);
return super.execute(s.toString()); // in Statement class
}
// **************************************************************
// END OF PUBLIC INTERFACE
// **************************************************************
/**
* There are a lot of setXXX classes which all basically do
* the same thing. We need a method which actually does the
* set for us.
*
* @param paramIndex the index into the inString
* @param s a string to be stored
* @exception SQLException if something goes wrong
*/
private void set(int paramIndex, String s) throws SQLException
{
if (paramIndex < 1 || paramIndex > inStrings.length)
throw new SQLException("Parameter index out of range");
inStrings[paramIndex - 1] = s;
}
}
|