~ubuntu-branches/ubuntu/hoary/libpgjava/hoary

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Gybas
  • Date: 2002-02-06 23:43:06 UTC
  • Revision ID: james.westby@ubuntu.com-20020206234306-hsg7suqr8q56qg40
Tags: upstream-7.2
ImportĀ upstreamĀ versionĀ 7.2

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
}