~ubuntu-branches/ubuntu/oneiric/libpgjava/oneiric

« back to all changes in this revision

Viewing changes to src/interfaces/jdbc/org/postgresql/jdbc1/PreparedStatement.java

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Vandyck
  • Date: 2005-04-21 14:25:11 UTC
  • mfrom: (1.2.1 upstream) (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20050421142511-wibh5vc31fkrorx7
Tags: 7.4.7-3
Built with sources...

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
package org.postgresql.jdbc1;
2
 
 
3
 
// IMPORTANT NOTE: This file implements the JDBC 1 version of the driver.
4
 
// If you make any modifications to this file, you must make sure that the
5
 
// changes are also made (if relevent) to the related JDBC 2 class in the
6
 
// org.postgresql.jdbc2 package.
7
 
 
8
 
import java.io.*;
9
 
import java.math.*;
10
 
import java.sql.*;
11
 
import java.text.*;
12
 
import java.util.*;
13
 
import org.postgresql.largeobject.*;
14
 
import org.postgresql.util.*;
15
 
 
16
 
/*
17
 
 * A SQL Statement is pre-compiled and stored in a PreparedStatement object.
18
 
 * This object can then be used to efficiently execute this statement multiple
19
 
 * times.
20
 
 *
21
 
 * <p><B>Note:</B> The setXXX methods for setting IN parameter values must
22
 
 * specify types that are compatible with the defined SQL type of the input
23
 
 * parameter.  For instance, if the IN parameter has SQL type Integer, then
24
 
 * setInt should be used.
25
 
 *
26
 
 * <p>If arbitrary parameter type conversions are required, then the setObject
27
 
 * method should be used with a target SQL type.
28
 
 *
29
 
 * @see ResultSet
30
 
 * @see java.sql.PreparedStatement
31
 
 */
32
 
public class PreparedStatement extends Statement implements java.sql.PreparedStatement
33
 
{
34
 
        String sql;
35
 
        String[] templateStrings;
36
 
        String[] inStrings;
37
 
        Connection connection;
38
 
 
39
 
        /*
40
 
         * Constructor for the PreparedStatement class.
41
 
         * Split the SQL statement into segments - separated by the arguments.
42
 
         * When we rebuild the thing with the arguments, we can substitute the
43
 
         * args and join the whole thing together.
44
 
         *
45
 
         * @param conn the instanatiating connection
46
 
         * @param sql the SQL statement with ? for IN markers
47
 
         * @exception SQLException if something bad occurs
48
 
         */
49
 
        public PreparedStatement(Connection connection, String sql) throws SQLException
50
 
        {
51
 
                super(connection);
52
 
 
53
 
                Vector v = new Vector();
54
 
                boolean inQuotes = false;
55
 
                int lastParmEnd = 0, i;
56
 
 
57
 
                this.sql = sql;
58
 
                this.connection = connection;
59
 
                for (i = 0; i < sql.length(); ++i)
60
 
                {
61
 
                        int c = sql.charAt(i);
62
 
 
63
 
                        if (c == '\'')
64
 
                                inQuotes = !inQuotes;
65
 
                        if (c == '?' && !inQuotes)
66
 
                        {
67
 
                                v.addElement(sql.substring (lastParmEnd, i));
68
 
                                lastParmEnd = i + 1;
69
 
                        }
70
 
                }
71
 
                v.addElement(sql.substring (lastParmEnd, sql.length()));
72
 
 
73
 
                templateStrings = new String[v.size()];
74
 
                inStrings = new String[v.size() - 1];
75
 
                clearParameters();
76
 
 
77
 
                for (i = 0 ; i < templateStrings.length; ++i)
78
 
                        templateStrings[i] = (String)v.elementAt(i);
79
 
        }
80
 
 
81
 
        /*
82
 
         * A Prepared SQL query is executed and its ResultSet is returned
83
 
         *
84
 
         * @return a ResultSet that contains the data produced by the
85
 
         *               *      query - never null
86
 
         * @exception SQLException if a database access error occurs
87
 
         */
88
 
        public java.sql.ResultSet executeQuery() throws SQLException
89
 
        {
90
 
                StringBuffer s = new StringBuffer();
91
 
                int i;
92
 
 
93
 
                for (i = 0 ; i < inStrings.length ; ++i)
94
 
                {
95
 
                        if (inStrings[i] == null)
96
 
                                throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
97
 
                        s.append (templateStrings[i]);
98
 
                        s.append (inStrings[i]);
99
 
                }
100
 
                s.append(templateStrings[inStrings.length]);
101
 
                return super.executeQuery(s.toString());        // in Statement class
102
 
        }
103
 
 
104
 
        /*
105
 
         * Execute a SQL INSERT, UPDATE or DELETE statement.  In addition,
106
 
         * SQL statements that return nothing such as SQL DDL statements can
107
 
         * be executed.
108
 
         *
109
 
         * @return either the row count for INSERT, UPDATE or DELETE; or
110
 
         *               *      0 for SQL statements that return nothing.
111
 
         * @exception SQLException if a database access error occurs
112
 
         */
113
 
        public int executeUpdate() throws SQLException
114
 
        {
115
 
                StringBuffer s = new StringBuffer();
116
 
                int i;
117
 
 
118
 
                for (i = 0 ; i < inStrings.length ; ++i)
119
 
                {
120
 
                        if (inStrings[i] == null)
121
 
                                throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
122
 
                        s.append (templateStrings[i]);
123
 
                        s.append (inStrings[i]);
124
 
                }
125
 
                s.append(templateStrings[inStrings.length]);
126
 
                return super.executeUpdate(s.toString());       // in Statement class
127
 
        }
128
 
 
129
 
        /*
130
 
         * Set a parameter to SQL NULL
131
 
         *
132
 
         * <p><B>Note:</B> You must specify the parameters SQL type (although
133
 
         * PostgreSQL ignores it)
134
 
         *
135
 
         * @param parameterIndex the first parameter is 1, etc...
136
 
         * @param sqlType the SQL type code defined in java.sql.Types
137
 
         * @exception SQLException if a database access error occurs
138
 
         */
139
 
        public void setNull(int parameterIndex, int sqlType) throws SQLException
140
 
        {
141
 
                set(parameterIndex, "null");
142
 
        }
143
 
 
144
 
        /*
145
 
         * Set a parameter to a Java boolean value.  The driver converts this
146
 
         * to a SQL BIT value when it sends it to the database.
147
 
         *
148
 
         * @param parameterIndex the first parameter is 1...
149
 
         * @param x the parameter value
150
 
         * @exception SQLException if a database access error occurs
151
 
         */
152
 
        public void setBoolean(int parameterIndex, boolean x) throws SQLException
153
 
        {
154
 
                set(parameterIndex, x ? "'t'" : "'f'");
155
 
        }
156
 
 
157
 
        /*
158
 
         * Set a parameter to a Java byte value.  The driver converts this to
159
 
         * a SQL TINYINT value when it sends it to the database.
160
 
         *
161
 
         * @param parameterIndex the first parameter is 1...
162
 
         * @param x the parameter value
163
 
         * @exception SQLException if a database access error occurs
164
 
         */
165
 
        public void setByte(int parameterIndex, byte x) throws SQLException
166
 
        {
167
 
                set(parameterIndex, Integer.toString(x));
168
 
        }
169
 
 
170
 
        /*
171
 
         * Set a parameter to a Java short value.  The driver converts this
172
 
         * to a SQL SMALLINT value when it sends it to the database.
173
 
         *
174
 
         * @param parameterIndex the first parameter is 1...
175
 
         * @param x the parameter value
176
 
         * @exception SQLException if a database access error occurs
177
 
         */
178
 
        public void setShort(int parameterIndex, short x) throws SQLException
179
 
        {
180
 
                set(parameterIndex, Integer.toString(x));
181
 
        }
182
 
 
183
 
        /*
184
 
         * Set a parameter to a Java int value.  The driver converts this to
185
 
         * a SQL INTEGER value when it sends it to the database.
186
 
         *
187
 
         * @param parameterIndex the first parameter is 1...
188
 
         * @param x the parameter value
189
 
         * @exception SQLException if a database access error occurs
190
 
         */
191
 
        public void setInt(int parameterIndex, int x) throws SQLException
192
 
        {
193
 
                set(parameterIndex, Integer.toString(x));
194
 
        }
195
 
 
196
 
        /*
197
 
         * Set a parameter to a Java long value.  The driver converts this to
198
 
         * a SQL BIGINT value when it sends it to the database.
199
 
         *
200
 
         * @param parameterIndex the first parameter is 1...
201
 
         * @param x the parameter value
202
 
         * @exception SQLException if a database access error occurs
203
 
         */
204
 
        public void setLong(int parameterIndex, long x) throws SQLException
205
 
        {
206
 
                set(parameterIndex, Long.toString(x));
207
 
        }
208
 
 
209
 
        /*
210
 
         * Set a parameter to a Java float value.  The driver converts this
211
 
         * to a SQL FLOAT value when it sends it to the database.
212
 
         *
213
 
         * @param parameterIndex the first parameter is 1...
214
 
         * @param x the parameter value
215
 
         * @exception SQLException if a database access error occurs
216
 
         */
217
 
        public void setFloat(int parameterIndex, float x) throws SQLException
218
 
        {
219
 
                set(parameterIndex, Float.toString(x));
220
 
        }
221
 
 
222
 
        /*
223
 
         * Set a parameter to a Java double value.      The driver converts this
224
 
         * to a SQL DOUBLE value when it sends it to the database
225
 
         *
226
 
         * @param parameterIndex the first parameter is 1...
227
 
         * @param x the parameter value
228
 
         * @exception SQLException if a database access error occurs
229
 
         */
230
 
        public void setDouble(int parameterIndex, double x) throws SQLException
231
 
        {
232
 
                set(parameterIndex, Double.toString(x));
233
 
        }
234
 
 
235
 
        /*
236
 
         * Set a parameter to a java.lang.BigDecimal value.  The driver
237
 
         * converts this to a SQL NUMERIC value when it sends it to the
238
 
         * database.
239
 
         *
240
 
         * @param parameterIndex the first parameter is 1...
241
 
         * @param x the parameter value
242
 
         * @exception SQLException if a database access error occurs
243
 
         */
244
 
        public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException
245
 
        {
246
 
                set(parameterIndex, x.toString());
247
 
        }
248
 
 
249
 
        /*
250
 
         * Set a parameter to a Java String value.      The driver converts this
251
 
         * to a SQL VARCHAR or LONGVARCHAR value (depending on the arguments
252
 
         * size relative to the driver's limits on VARCHARs) when it sends it
253
 
         * to the database.
254
 
         *
255
 
         * @param parameterIndex the first parameter is 1...
256
 
         * @param x the parameter value
257
 
         * @exception SQLException if a database access error occurs
258
 
         */
259
 
        public void setString(int parameterIndex, String x) throws SQLException
260
 
        {
261
 
                // if the passed string is null, then set this column to null
262
 
                if (x == null)
263
 
                        setNull(parameterIndex, Types.OTHER);
264
 
                else
265
 
                {
266
 
                        StringBuffer b = new StringBuffer();
267
 
                        int i;
268
 
 
269
 
                        b.append('\'');
270
 
                        for (i = 0 ; i < x.length() ; ++i)
271
 
                        {
272
 
                                char c = x.charAt(i);
273
 
                                if (c == '\\' || c == '\'')
274
 
                                        b.append((char)'\\');
275
 
                                b.append(c);
276
 
                        }
277
 
                        b.append('\'');
278
 
                        set(parameterIndex, b.toString());
279
 
                }
280
 
        }
281
 
 
282
 
        /*
283
 
         * Set a parameter to a Java array of bytes.  The driver converts this
284
 
         * to a SQL VARBINARY or LONGVARBINARY (depending on the argument's
285
 
         * size relative to the driver's limits on VARBINARYs) when it sends
286
 
         * it to the database.
287
 
         *
288
 
         * <p>Implementation note:
289
 
         * <br>With org.postgresql, this creates a large object, and stores the
290
 
         * objects oid in this column.
291
 
         *
292
 
         * @param parameterIndex the first parameter is 1...
293
 
         * @param x the parameter value
294
 
         * @exception SQLException if a database access error occurs
295
 
         */
296
 
        public void setBytes(int parameterIndex, byte x[]) throws SQLException
297
 
        {
298
 
                if (connection.haveMinimumCompatibleVersion("7.2"))
299
 
                {
300
 
                        //Version 7.2 supports the bytea datatype for byte arrays
301
 
                        if (null == x)
302
 
                        {
303
 
                                setNull(parameterIndex, Types.OTHER);
304
 
                        }
305
 
                        else
306
 
                        {
307
 
                                setString(parameterIndex, PGbytea.toPGString(x));
308
 
                        }
309
 
                }
310
 
                else
311
 
                {
312
 
                        //Version 7.1 and earlier support done as LargeObjects
313
 
                        LargeObjectManager lom = connection.getLargeObjectAPI();
314
 
                        int oid = lom.create();
315
 
                        LargeObject lob = lom.open(oid);
316
 
                        lob.write(x);
317
 
                        lob.close();
318
 
                        setInt(parameterIndex, oid);
319
 
                }
320
 
        }
321
 
 
322
 
        /*
323
 
         * Set a parameter to a java.sql.Date value.  The driver converts this
324
 
         * to a SQL DATE value when it sends it to the database.
325
 
         *
326
 
         * @param parameterIndex the first parameter is 1...
327
 
         * @param x the parameter value
328
 
         * @exception SQLException if a database access error occurs
329
 
         */
330
 
        public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
331
 
        {
332
 
                if (null == x)
333
 
                {
334
 
                        setNull(parameterIndex, Types.OTHER);
335
 
                }
336
 
                else
337
 
                {
338
 
                        SimpleDateFormat df = new SimpleDateFormat("''yyyy-MM-dd''");
339
 
                        set(parameterIndex, df.format(x));
340
 
                }
341
 
                // The above is how the date should be handled.
342
 
                //
343
 
                // However, in JDK's prior to 1.1.6 (confirmed with the
344
 
                // Linux jdk1.1.3 and the Win95 JRE1.1.5), SimpleDateFormat seems
345
 
                // to format a date to the previous day. So the fix is to add a day
346
 
                // before formatting.
347
 
                //
348
 
                // PS: 86400000 is one day
349
 
                //
350
 
                //set(parameterIndex, df.format(new java.util.Date(x.getTime()+86400000)));
351
 
        }
352
 
 
353
 
        /*
354
 
         * Set a parameter to a java.sql.Time value.  The driver converts
355
 
         * this to a SQL TIME value when it sends it to the database.
356
 
         *
357
 
         * @param parameterIndex the first parameter is 1...));
358
 
         * @param x the parameter value
359
 
         * @exception SQLException if a database access error occurs
360
 
         */
361
 
        public void setTime(int parameterIndex, Time x) throws SQLException
362
 
        {
363
 
                if (null == x)
364
 
                {
365
 
                        setNull(parameterIndex, Types.OTHER);
366
 
                }
367
 
                else
368
 
                {
369
 
                        set(parameterIndex, "'" + x.toString() + "'");
370
 
                }
371
 
        }
372
 
 
373
 
        /*
374
 
         * Set a parameter to a java.sql.Timestamp value.  The driver converts
375
 
         * this to a SQL TIMESTAMP value when it sends it to the database.
376
 
         *
377
 
         * @param parameterIndex the first parameter is 1...
378
 
         * @param x the parameter value
379
 
         * @exception SQLException if a database access error occurs
380
 
         */
381
 
        public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
382
 
        {
383
 
                if (null == x)
384
 
                {
385
 
                        setNull(parameterIndex, Types.OTHER);
386
 
                }
387
 
                else
388
 
                {
389
 
                        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
390
 
                        df.setTimeZone(TimeZone.getTimeZone("GMT"));
391
 
 
392
 
                        // Make decimal from nanos.
393
 
                        StringBuffer decimal = new StringBuffer("000000000");   // max nanos length
394
 
                        String nanos = String.valueOf(x.getNanos());
395
 
                        decimal.setLength(decimal.length() - nanos.length());
396
 
                        decimal.append(nanos);
397
 
                        if (! connection.haveMinimumServerVersion("7.2")) {
398
 
                                // Because 7.1 include bug that "hh:mm:59.999" becomes "hh:mm:60.00".
399
 
                                decimal.setLength(2);
400
 
                        }
401
 
 
402
 
                        StringBuffer strBuf = new StringBuffer("'");
403
 
                        strBuf.append(df.format(x)).append('.').append(decimal).append("+00'");
404
 
                        set(parameterIndex, strBuf.toString());
405
 
                }
406
 
        }
407
 
 
408
 
        /*
409
 
         * When a very large ASCII value is input to a LONGVARCHAR parameter,
410
 
         * it may be more practical to send it via a java.io.InputStream.
411
 
         * JDBC will read the data from the stream as needed, until it reaches
412
 
         * end-of-file.  The JDBC driver will do any necessary conversion from
413
 
         * ASCII to the database char format.
414
 
         *
415
 
         * <P><B>Note:</B> This stream object can either be a standard Java
416
 
         * stream object or your own subclass that implements the standard
417
 
         * interface.
418
 
         *
419
 
         * @param parameterIndex the first parameter is 1...
420
 
         * @param x the parameter value
421
 
         * @param length the number of bytes in the stream
422
 
         * @exception SQLException if a database access error occurs
423
 
         */
424
 
        public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException
425
 
        {
426
 
                if (connection.haveMinimumCompatibleVersion("7.2"))
427
 
                {
428
 
                        //Version 7.2 supports AsciiStream for all PG text types (char, varchar, text)
429
 
                        //As the spec/javadoc for this method indicate this is to be used for
430
 
                        //large String values (i.e. LONGVARCHAR)  PG doesn't have a separate
431
 
                        //long varchar datatype, but with toast all text datatypes are capable of
432
 
                        //handling very large values.  Thus the implementation ends up calling
433
 
                        //setString() since there is no current way to stream the value to the server
434
 
                        try
435
 
                        {
436
 
                                InputStreamReader l_inStream = new InputStreamReader(x, "ASCII");
437
 
                                char[] l_chars = new char[length];
438
 
                                int l_charsRead = l_inStream.read(l_chars, 0, length);
439
 
                                setString(parameterIndex, new String(l_chars, 0, l_charsRead));
440
 
                        }
441
 
                        catch (UnsupportedEncodingException l_uee)
442
 
                        {
443
 
                                throw new PSQLException("postgresql.unusual", l_uee);
444
 
                        }
445
 
                        catch (IOException l_ioe)
446
 
                        {
447
 
                                throw new PSQLException("postgresql.unusual", l_ioe);
448
 
                        }
449
 
                }
450
 
                else
451
 
                {
452
 
                        //Version 7.1 supported only LargeObjects by treating everything
453
 
                        //as binary data
454
 
                        setBinaryStream(parameterIndex, x, length);
455
 
                }
456
 
        }
457
 
 
458
 
        /*
459
 
         * When a very large Unicode value is input to a LONGVARCHAR parameter,
460
 
         * it may be more practical to send it via a java.io.InputStream.
461
 
         * JDBC will read the data from the stream as needed, until it reaches
462
 
         * end-of-file.  The JDBC driver will do any necessary conversion from
463
 
         * UNICODE to the database char format.
464
 
         *
465
 
         * <P><B>Note:</B> This stream object can either be a standard Java
466
 
         * stream object or your own subclass that implements the standard
467
 
         * interface.
468
 
         *
469
 
         * @param parameterIndex the first parameter is 1...
470
 
         * @param x the parameter value
471
 
         * @exception SQLException if a database access error occurs
472
 
         */
473
 
        public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException
474
 
        {
475
 
                if (connection.haveMinimumCompatibleVersion("7.2"))
476
 
                {
477
 
                        //Version 7.2 supports AsciiStream for all PG text types (char, varchar, text)
478
 
                        //As the spec/javadoc for this method indicate this is to be used for
479
 
                        //large String values (i.e. LONGVARCHAR)  PG doesn't have a separate
480
 
                        //long varchar datatype, but with toast all text datatypes are capable of
481
 
                        //handling very large values.  Thus the implementation ends up calling
482
 
                        //setString() since there is no current way to stream the value to the server
483
 
                        try
484
 
                        {
485
 
                                InputStreamReader l_inStream = new InputStreamReader(x, "UTF-8");
486
 
                                char[] l_chars = new char[length];
487
 
                                int l_charsRead = l_inStream.read(l_chars, 0, length);
488
 
                                setString(parameterIndex, new String(l_chars, 0, l_charsRead));
489
 
                        }
490
 
                        catch (UnsupportedEncodingException l_uee)
491
 
                        {
492
 
                                throw new PSQLException("postgresql.unusual", l_uee);
493
 
                        }
494
 
                        catch (IOException l_ioe)
495
 
                        {
496
 
                                throw new PSQLException("postgresql.unusual", l_ioe);
497
 
                        }
498
 
                }
499
 
                else
500
 
                {
501
 
                        //Version 7.1 supported only LargeObjects by treating everything
502
 
                        //as binary data
503
 
                        setBinaryStream(parameterIndex, x, length);
504
 
                }
505
 
        }
506
 
 
507
 
        /*
508
 
         * When a very large binary value is input to a LONGVARBINARY parameter,
509
 
         * it may be more practical to send it via a java.io.InputStream.
510
 
         * JDBC will read the data from the stream as needed, until it reaches
511
 
         * end-of-file.
512
 
         *
513
 
         * <P><B>Note:</B> This stream object can either be a standard Java
514
 
         * stream object or your own subclass that implements the standard
515
 
         * interface.
516
 
         *
517
 
         * @param parameterIndex the first parameter is 1...
518
 
         * @param x the parameter value
519
 
         * @exception SQLException if a database access error occurs
520
 
         */
521
 
        public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException
522
 
        {
523
 
                if (connection.haveMinimumCompatibleVersion("7.2"))
524
 
                {
525
 
                        //Version 7.2 supports BinaryStream for for the PG bytea type
526
 
                        //As the spec/javadoc for this method indicate this is to be used for
527
 
                        //large binary values (i.e. LONGVARBINARY)      PG doesn't have a separate
528
 
                        //long binary datatype, but with toast the bytea datatype is capable of
529
 
                        //handling very large values.  Thus the implementation ends up calling
530
 
                        //setBytes() since there is no current way to stream the value to the server
531
 
                        byte[] l_bytes = new byte[length];
532
 
                        int l_bytesRead;
533
 
                        try
534
 
                        {
535
 
                                l_bytesRead = x.read(l_bytes, 0, length);
536
 
                        }
537
 
                        catch (IOException l_ioe)
538
 
                        {
539
 
                                throw new PSQLException("postgresql.unusual", l_ioe);
540
 
                        }
541
 
                        if (l_bytesRead == length)
542
 
                        {
543
 
                                setBytes(parameterIndex, l_bytes);
544
 
                        }
545
 
                        else
546
 
                        {
547
 
                                //the stream contained less data than they said
548
 
                                byte[] l_bytes2 = new byte[l_bytesRead];
549
 
                                System.arraycopy(l_bytes, 0, l_bytes2, 0, l_bytesRead);
550
 
                                setBytes(parameterIndex, l_bytes2);
551
 
                        }
552
 
                }
553
 
                else
554
 
                {
555
 
                        //Version 7.1 only supported streams for LargeObjects
556
 
                        //but the jdbc spec indicates that streams should be
557
 
                        //available for LONGVARBINARY instead
558
 
                        LargeObjectManager lom = connection.getLargeObjectAPI();
559
 
                        int oid = lom.create();
560
 
                        LargeObject lob = lom.open(oid);
561
 
                        OutputStream los = lob.getOutputStream();
562
 
                        try
563
 
                        {
564
 
                                // could be buffered, but then the OutputStream returned by LargeObject
565
 
                                // is buffered internally anyhow, so there would be no performance
566
 
                                // boost gained, if anything it would be worse!
567
 
                                int c = x.read();
568
 
                                int p = 0;
569
 
                                while (c > -1 && p < length)
570
 
                                {
571
 
                                        los.write(c);
572
 
                                        c = x.read();
573
 
                                        p++;
574
 
                                }
575
 
                                los.close();
576
 
                        }
577
 
                        catch (IOException se)
578
 
                        {
579
 
                                throw new PSQLException("postgresql.unusual", se);
580
 
                        }
581
 
                        // lob is closed by the stream so don't call lob.close()
582
 
                        setInt(parameterIndex, oid);
583
 
                }
584
 
        }
585
 
 
586
 
        /*
587
 
         * In general, parameter values remain in force for repeated used of a
588
 
         * Statement.  Setting a parameter value automatically clears its
589
 
         * previous value.      However, in coms cases, it is useful to immediately
590
 
         * release the resources used by the current parameter values; this
591
 
         * can be done by calling clearParameters
592
 
         *
593
 
         * @exception SQLException if a database access error occurs
594
 
         */
595
 
        public void clearParameters() throws SQLException
596
 
        {
597
 
                int i;
598
 
 
599
 
                for (i = 0 ; i < inStrings.length ; i++)
600
 
                        inStrings[i] = null;
601
 
        }
602
 
 
603
 
        /*
604
 
         * Set the value of a parameter using an object; use the java.lang
605
 
         * equivalent objects for integral values.
606
 
         *
607
 
         * <P>The given Java object will be converted to the targetSqlType before
608
 
         * being sent to the database.
609
 
         *
610
 
         * <P>note that this method may be used to pass database-specific
611
 
         * abstract data types.  This is done by using a Driver-specific
612
 
         * Java type and using a targetSqlType of java.sql.Types.OTHER
613
 
         *
614
 
         * @param parameterIndex the first parameter is 1...
615
 
         * @param x the object containing the input parameter value
616
 
         * @param targetSqlType The SQL type to be send to the database
617
 
         * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC
618
 
         *               *      types this is the number of digits after the decimal.  For
619
 
         *               *      all other types this value will be ignored.
620
 
         * @exception SQLException if a database access error occurs
621
 
         */
622
 
        public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException
623
 
        {
624
 
                if (x == null)
625
 
                {
626
 
                        setNull(parameterIndex, Types.OTHER);
627
 
                        return;
628
 
                }
629
 
                switch (targetSqlType)
630
 
                {
631
 
                        case Types.TINYINT:
632
 
                        case Types.SMALLINT:
633
 
                        case Types.INTEGER:
634
 
                        case Types.BIGINT:
635
 
                        case Types.REAL:
636
 
                        case Types.FLOAT:
637
 
                        case Types.DOUBLE:
638
 
                        case Types.DECIMAL:
639
 
                        case Types.NUMERIC:
640
 
                                if (x instanceof Boolean)
641
 
                                        set(parameterIndex, ((Boolean)x).booleanValue() ? "1" : "0");
642
 
                                else
643
 
                                        set(parameterIndex, x.toString());
644
 
                                break;
645
 
                        case Types.CHAR:
646
 
                        case Types.VARCHAR:
647
 
                        case Types.LONGVARCHAR:
648
 
                                setString(parameterIndex, x.toString());
649
 
                                break;
650
 
                        case Types.DATE:
651
 
                                setDate(parameterIndex, (java.sql.Date)x);
652
 
                                break;
653
 
                        case Types.TIME:
654
 
                                setTime(parameterIndex, (Time)x);
655
 
                                break;
656
 
                        case Types.TIMESTAMP:
657
 
                                setTimestamp(parameterIndex, (Timestamp)x);
658
 
                                break;
659
 
                        case Types.BIT:
660
 
                                if (x instanceof Boolean)
661
 
                                {
662
 
                                        set(parameterIndex, ((Boolean)x).booleanValue() ? "TRUE" : "FALSE");
663
 
                                }
664
 
                                else
665
 
                                {
666
 
                                        throw new PSQLException("postgresql.prep.type");
667
 
                                }
668
 
                                break;
669
 
                        case Types.BINARY:
670
 
                        case Types.VARBINARY:
671
 
                                setObject(parameterIndex, x);
672
 
                                break;
673
 
                        case Types.OTHER:
674
 
                                setString(parameterIndex, ((PGobject)x).getValue());
675
 
                                break;
676
 
                        default:
677
 
                                throw new PSQLException("postgresql.prep.type");
678
 
                }
679
 
        }
680
 
 
681
 
        public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException
682
 
        {
683
 
                setObject(parameterIndex, x, targetSqlType, 0);
684
 
        }
685
 
 
686
 
        /*
687
 
         * This stores an Object into a parameter.
688
 
         * <p>New for 6.4, if the object is not recognised, but it is
689
 
         * Serializable, then the object is serialised using the
690
 
         * org.postgresql.util.Serialize class.
691
 
         */
692
 
        public void setObject(int parameterIndex, Object x) throws SQLException
693
 
        {
694
 
                if (x == null)
695
 
                {
696
 
                        setNull(parameterIndex, Types.OTHER);
697
 
                        return;
698
 
                }
699
 
                if (x instanceof String)
700
 
                        setString(parameterIndex, (String)x);
701
 
                else if (x instanceof BigDecimal)
702
 
                        setBigDecimal(parameterIndex, (BigDecimal)x);
703
 
                else if (x instanceof Short)
704
 
                        setShort(parameterIndex, ((Short)x).shortValue());
705
 
                else if (x instanceof Integer)
706
 
                        setInt(parameterIndex, ((Integer)x).intValue());
707
 
                else if (x instanceof Long)
708
 
                        setLong(parameterIndex, ((Long)x).longValue());
709
 
                else if (x instanceof Float)
710
 
                        setFloat(parameterIndex, ((Float)x).floatValue());
711
 
                else if (x instanceof Double)
712
 
                        setDouble(parameterIndex, ((Double)x).doubleValue());
713
 
                else if (x instanceof byte[])
714
 
                        setBytes(parameterIndex, (byte[])x);
715
 
                else if (x instanceof java.sql.Date)
716
 
                        setDate(parameterIndex, (java.sql.Date)x);
717
 
                else if (x instanceof Time)
718
 
                        setTime(parameterIndex, (Time)x);
719
 
                else if (x instanceof Timestamp)
720
 
                        setTimestamp(parameterIndex, (Timestamp)x);
721
 
                else if (x instanceof Boolean)
722
 
                        setBoolean(parameterIndex, ((Boolean)x).booleanValue());
723
 
                else if (x instanceof PGobject)
724
 
                        setString(parameterIndex, ((PGobject)x).getValue());
725
 
                else
726
 
                        setLong(parameterIndex, connection.storeObject(x));
727
 
        }
728
 
 
729
 
        /*
730
 
         * Some prepared statements return multiple results; the execute method
731
 
         * handles these complex statements as well as the simpler form of
732
 
         * statements handled by executeQuery and executeUpdate
733
 
         *
734
 
         * @return true if the next result is a ResultSet; false if it is an
735
 
         *               *      update count or there are no more results
736
 
         * @exception SQLException if a database access error occurs
737
 
         */
738
 
        public boolean execute() throws SQLException
739
 
        {
740
 
                StringBuffer s = new StringBuffer();
741
 
                int i;
742
 
 
743
 
                for (i = 0 ; i < inStrings.length ; ++i)
744
 
                {
745
 
                        if (inStrings[i] == null)
746
 
                                throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
747
 
                        s.append (templateStrings[i]);
748
 
                        s.append (inStrings[i]);
749
 
                }
750
 
                s.append(templateStrings[inStrings.length]);
751
 
                return super.execute(s.toString());             // in Statement class
752
 
        }
753
 
 
754
 
        /*
755
 
         * Returns the SQL statement with the current template values
756
 
         * substituted.
757
 
         */
758
 
        public String toString()
759
 
        {
760
 
                StringBuffer s = new StringBuffer();
761
 
                int i;
762
 
 
763
 
                for (i = 0 ; i < inStrings.length ; ++i)
764
 
                {
765
 
                        if (inStrings[i] == null)
766
 
                                s.append( '?' );
767
 
                        else
768
 
                                s.append (templateStrings[i]);
769
 
                        s.append (inStrings[i]);
770
 
                }
771
 
                s.append(templateStrings[inStrings.length]);
772
 
                return s.toString();
773
 
        }
774
 
 
775
 
        // **************************************************************
776
 
        //      END OF PUBLIC INTERFACE
777
 
        // **************************************************************
778
 
 
779
 
        /*
780
 
         * There are a lot of setXXX classes which all basically do
781
 
         * the same thing.      We need a method which actually does the
782
 
         * set for us.
783
 
         *
784
 
         * @param paramIndex the index into the inString
785
 
         * @param s a string to be stored
786
 
         * @exception SQLException if something goes wrong
787
 
         */
788
 
        private void set(int paramIndex, String s) throws SQLException
789
 
        {
790
 
                if (paramIndex < 1 || paramIndex > inStrings.length)
791
 
                        throw new PSQLException("postgresql.prep.range");
792
 
                inStrings[paramIndex - 1] = s;
793
 
        }
794
 
}