KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > jdbc > EmbedPreparedStatement


1 /*
2
3    Derby - Class org.apache.derby.impl.jdbc.EmbedPreparedStatement
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.jdbc;
23
24 import org.apache.derby.iapi.services.sanity.SanityManager;
25
26 import org.apache.derby.iapi.types.VariableSizeDataValue;
27
28 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
29 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
30 import org.apache.derby.iapi.sql.PreparedStatement;
31 import org.apache.derby.iapi.sql.execute.ExecPreparedStatement;
32 import org.apache.derby.iapi.sql.ResultSet;
33 import org.apache.derby.iapi.sql.Activation;
34 import org.apache.derby.iapi.sql.ParameterValueSet;
35 import org.apache.derby.iapi.sql.ResultDescription;
36 import org.apache.derby.iapi.types.DataTypeDescriptor;
37 import org.apache.derby.iapi.types.DataValueDescriptor;
38 import org.apache.derby.iapi.types.RawToBinaryFormatStream;
39 import org.apache.derby.iapi.types.ReaderToUTF8Stream;
40
41 import org.apache.derby.iapi.error.StandardException;
42
43 import org.apache.derby.iapi.services.io.LimitReader;
44
45 import org.apache.derby.iapi.reference.SQLState;
46 import org.apache.derby.iapi.reference.JDBC40Translation;
47 import org.apache.derby.iapi.reference.JDBC30Translation;
48 import org.apache.derby.iapi.reference.JDBC20Translation;
49
50 import java.util.Calendar JavaDoc;
51 import java.util.Vector JavaDoc;
52
53 /*
54  We would import these, but have name-overlap
55 import java.sql.PreparedStatement;
56 import java.sql.ResultSet;
57 */

58 import java.sql.ResultSetMetaData JavaDoc;
59 import java.sql.SQLException JavaDoc;
60 import java.sql.Date JavaDoc;
61 import java.sql.Time JavaDoc;
62 import java.sql.Timestamp JavaDoc;
63 import java.sql.Clob JavaDoc;
64 import java.sql.Blob JavaDoc;
65
66 import java.io.InputStream JavaDoc;
67 import java.io.DataInputStream JavaDoc;
68 import java.io.IOException JavaDoc;
69 import java.io.EOFException JavaDoc;
70 import java.io.Reader JavaDoc;
71 import java.sql.Types JavaDoc;
72
73 import org.apache.derby.iapi.jdbc.BrokeredConnectionControl;
74 import org.apache.derby.iapi.jdbc.EngineParameterMetaData;
75 import org.apache.derby.iapi.jdbc.EnginePreparedStatement;
76
77 /**
78  *
79  * EmbedPreparedStatement is a local JDBC statement.
80   <P><B>Supports</B>
81    <UL>
82    <LI> JSR169
83    </UL>
84  */

85 public abstract class EmbedPreparedStatement
86     extends EmbedStatement
87     implements EnginePreparedStatement
88 {
89
90     //Moving jdbc2.0 batch related code in this class because callableStatement in jdbc 20 needs
91
//this code too and it doesn't derive from prepared statement in jdbc 20 in our implementation.
92

93     protected ResultSetMetaData JavaDoc rMetaData;
94     //bug 4579-If the prepared statement was revalidated after doing getMetaData(), we
95
//should get the metadata info again on next getMetaData(). We store the generated
96
//class name in following variable during getMetaData() call. If it differs from the
97
//current generated class name, then that indicates a refetch of metadata is required.
98
private String JavaDoc gcDuringGetMetaData;
99
100     protected PreparedStatement preparedStatement;
101     private Activation activation;
102         
103         private BrokeredConnectionControl bcc=null;
104
105     /*
106         Constructor assumes caller will setup context stack
107         and restore it.
108      */

109     public EmbedPreparedStatement (EmbedConnection conn, String JavaDoc sql, boolean forMetaData,
110                                       int resultSetType, int resultSetConcurrency,
111                                       int resultSetHoldability,
112                                       int autoGeneratedKeys,
113                                       int[] columnIndexes,
114                                       String JavaDoc[] columnNames)
115         throws SQLException JavaDoc {
116
117         super(conn, forMetaData, resultSetType, resultSetConcurrency, resultSetHoldability);
118         // PreparedStatement is poolable by default
119
isPoolable = true;
120
121         // if the sql string is null, raise an error
122
if (sql == null)
123             throw newSQLException(SQLState.NULL_SQL_TEXT);
124
125             // set up the SQLText in EmbedStatement
126
SQLText = sql;
127
128             try {
129                 preparedStatement = lcc.prepareInternalStatement
130                 (lcc.getDefaultSchema(), sql, resultSetConcurrency==JDBC20Translation.CONCUR_READ_ONLY, forMetaData);
131                 
132                 addWarning(preparedStatement.getCompileTimeWarnings());
133
134                 activation = preparedStatement.getActivation(lcc, resultSetType == JDBC20Translation.TYPE_SCROLL_INSENSITIVE);
135
136                 checkRequiresCallableStatement(activation);
137
138             //bug 4838 - save the auto-generated key information in activation. keeping this
139
//information in lcc will not work work as it can be tampered by a nested trasaction
140
if (autoGeneratedKeys == JDBC30Translation.RETURN_GENERATED_KEYS)
141                     activation.setAutoGeneratedKeysResultsetInfo(columnIndexes, columnNames);
142
143             } catch (Throwable JavaDoc t) {
144             throw handleException(t);
145             }
146     }
147
148     /**
149         JDBC states that a Statement is closed when garbage collected.
150
151         @exception Throwable Allows any exception to be thrown during finalize
152     */

153     protected void finalize() throws Throwable JavaDoc {
154         super.finalize();
155
156         /*
157         ** We mark the activation as not being used and
158         ** that is it. We rely on the connection to sweep
159         ** through the activations to find the ones that
160         ** aren't in use, and to close them. We cannot
161         ** do a activation.close() here because there are
162         ** synchronized methods under close that cannot
163         ** be called during finalization.
164         */

165         if (activation != null)
166         {
167             activation.markUnused();
168         }
169     }
170
171     /*
172      * Statement interface
173         we override all Statement methods that take a SQL
174         string as they must thrown an exception in a PreparedStatement.
175         See the JDBC 3.0 spec.
176      */

177     public final boolean execute(String JavaDoc sql) throws SQLException JavaDoc {
178         throw newSQLException(SQLState.NOT_FOR_PREPARED_STATEMENT, "execute(String)");
179     }
180     public final boolean execute(String JavaDoc sql, int autoGenKeys) throws SQLException JavaDoc {
181         throw newSQLException(SQLState.NOT_FOR_PREPARED_STATEMENT, "execute(String, int)");
182     }
183     public final boolean execute(String JavaDoc sql, int[] columnIndexes) throws SQLException JavaDoc {
184         throw newSQLException(SQLState.NOT_FOR_PREPARED_STATEMENT, "execute(String, int[])");
185     }
186     public final boolean execute(String JavaDoc sql, String JavaDoc[] columnNames) throws SQLException JavaDoc {
187         throw newSQLException(SQLState.NOT_FOR_PREPARED_STATEMENT, "execute(String, String[])");
188     }
189     public final java.sql.ResultSet JavaDoc executeQuery(String JavaDoc sql) throws SQLException JavaDoc {
190         throw newSQLException(SQLState.NOT_FOR_PREPARED_STATEMENT, "executeQuery(String)");
191     }
192     public final int executeUpdate(String JavaDoc sql) throws SQLException JavaDoc {
193         throw newSQLException(SQLState.NOT_FOR_PREPARED_STATEMENT, "executeUpdate(String)");
194     }
195     public final int executeUpdate(String JavaDoc sql, int autoGenKeys) throws SQLException JavaDoc {
196         throw newSQLException(SQLState.NOT_FOR_PREPARED_STATEMENT, "executeUpdate(String, int)");
197     }
198     public final int executeUpdate(String JavaDoc sql, int[] columnIndexes) throws SQLException JavaDoc {
199         throw newSQLException(SQLState.NOT_FOR_PREPARED_STATEMENT, "executeUpdate(String, int[])");
200     }
201     public final int executeUpdate(String JavaDoc sql, String JavaDoc[] columnNames) throws SQLException JavaDoc {
202         throw newSQLException(SQLState.NOT_FOR_PREPARED_STATEMENT, "executeUpdate(String, String[])");
203     }
204     public final void addBatch(String JavaDoc sql) throws SQLException JavaDoc {
205         throw newSQLException(SQLState.NOT_FOR_PREPARED_STATEMENT, "addBatch(String)");
206     }
207
208
209     /**
210      * Additional close to close our activation.
211      * In the case that a XAConnection is involved in the creation of this
212      * PreparedStatement for e.g in the following case
213      *
214      * <code>
215      * XAConnection xaconn = xadatasource.getXAConnection();//where xadatasource is an object of XADataSource
216      * Connection conn = xaconnection.getConnection();
217      * PreparedStatement ps = conn.preparedStatement("values 1");
218      * </code>
219      *
220      * In the above case the PreparedStatement will actually be a
221      * BrokeredPreparedStatement40 object. Hence when we call
222      * bcc.onStatementClose and pass the PreparedStatement that caused it
223      * applicationStatement will be the appropriate choice since it will
224      * contain the appropriate instance of PreparedStatement in each case
225      *
226      * @throws SQLException upon failure
227      *
228      */

229     void closeActions() throws SQLException JavaDoc {
230
231         if (bcc!=null) {
232             java.sql.PreparedStatement JavaDoc ps_app =
233                 (java.sql.PreparedStatement JavaDoc)applicationStatement;
234             bcc.onStatementClose(ps_app);
235         }
236         //we release the resource for preparedStatement
237
preparedStatement = null;
238
239         try{
240             setupContextStack();
241         } catch (SQLException JavaDoc se) {
242             //we may have already committed the transaction in which case
243
//setupContextStack will fail, the close should just return
244
return;
245         }
246         try
247         {
248             activation.close();
249             activation = null;
250         } catch (Throwable JavaDoc t)
251         {
252             throw handleException(t);
253         } finally {
254             restoreContextStack();
255         }
256     }
257     
258     /*
259      * PreparedStatement interface; we have inherited from
260      * EmbedStatement to get the Statement interface for
261      * EmbedPreparedStatement (needed by PreparedStatement)
262      * These are the JDBC interface comments, so we know
263      * what to do.
264      */

265
266     /**
267      * A prepared SQL query is executed and its ResultSet is returned.
268      *
269      * @return a ResultSet that contains the data produced by the
270      * query; never null
271      * @exception SQLException thrown on failure.
272      */

273     public final java.sql.ResultSet JavaDoc executeQuery() throws SQLException JavaDoc {
274             try {
275                 executeStatement(activation, true, false);
276             } catch(SQLException JavaDoc sqle) {
277                 checkStatementValidity(sqle);
278             }
279             
280             if (SanityManager.DEBUG) {
281                 if (results == null)
282                     SanityManager.THROWASSERT("no results returned on executeQuery()");
283             }
284             
285             return results;
286         }
287
288     /**
289      * Execute a SQL INSERT, UPDATE or DELETE statement. In addition,
290      * SQL statements that return nothing such as SQL DDL statements
291      * can be executed.
292      *
293      * @return either the row count for INSERT, UPDATE or DELETE; or 0
294      * for SQL statements that return nothing
295      * @exception SQLException thrown on failure.
296      */

297         public final int executeUpdate() throws SQLException JavaDoc {
298             try {
299                 executeStatement(activation, false, true);
300             } catch(SQLException JavaDoc sqle) {
301                 checkStatementValidity(sqle);
302             }
303             return updateCount;
304         }
305
306     /**
307      * Set a parameter to SQL NULL.
308      *
309      * <P><B>Note:</B> You must specify the parameter's SQL type.
310      *
311      * @param parameterIndex the first parameter is 1, the second is 2, ...
312      * @param sqlType SQL type code defined by java.sql.Types
313      * @exception SQLException thrown on failure.
314      */

315     public void setNull(int parameterIndex, int sqlType) throws SQLException JavaDoc {
316
317         checkForSupportedDataType(sqlType);
318         checkStatus();
319
320         int jdbcTypeId = getParameterJDBCType(parameterIndex);
321         
322         if (!DataTypeDescriptor.isJDBCTypeEquivalent(jdbcTypeId, sqlType)) {
323
324             throw dataTypeConversion(parameterIndex, Util.typeName(sqlType));
325         }
326         
327         try {
328             /* JDBC is one-based, DBMS is zero-based */
329             getParms().getParameterForSet(parameterIndex - 1).setToNull();
330         } catch (StandardException t) {
331             throw EmbedResultSet.noStateChangeException(t);
332         }
333
334     }
335
336     /**
337      * Set a parameter to a Java boolean value. According to the JDBC API spec,
338      * the driver converts this to a SQL BIT value when it sends it to the
339      * database. But we don't have to do this, since the database engine
340      * supports a boolean type.
341      *
342      * @param parameterIndex the first parameter is 1, the second is 2, ...
343      * @param x the parameter value
344      * @exception SQLException thrown on failure.
345      */

346     public void setBoolean(int parameterIndex, boolean x) throws SQLException JavaDoc {
347         
348         checkStatus();
349         try {
350             /* JDBC is one-based, DBMS is zero-based */
351             getParms().getParameterForSet(parameterIndex - 1).setValue(x);
352
353         } catch (StandardException t) {
354             throw EmbedResultSet.noStateChangeException(t);
355         }
356     }
357
358     /**
359      * Set a parameter to a Java byte value. The driver converts this
360      * to a SQL TINYINT value when it sends it to the database.
361      *
362      * @param parameterIndex the first parameter is 1, the second is 2, ...
363      * @param x the parameter value
364      * @exception SQLException thrown on failure.
365      */

366     public void setByte(int parameterIndex, byte x) throws SQLException JavaDoc {
367
368         checkStatus();
369         try {
370
371             getParms().getParameterForSet(parameterIndex - 1).setValue(x);
372
373         } catch (Throwable JavaDoc t) {
374             throw EmbedResultSet.noStateChangeException(t);
375         }
376     }
377
378     /**
379      * Set a parameter to a Java short value. The driver converts this
380      * to a SQL SMALLINT value when it sends it to the database.
381      *
382      * @param parameterIndex the first parameter is 1, the second is 2, ...
383      * @param x the parameter value
384      * @exception SQLException thrown on failure.
385      */

386     public void setShort(int parameterIndex, short x) throws SQLException JavaDoc {
387
388         checkStatus();
389         try {
390             /* JDBC is one-based, DBMS is zero-based */
391             getParms().getParameterForSet(parameterIndex - 1).setValue(x);
392
393         } catch (Throwable JavaDoc t) {
394             throw EmbedResultSet.noStateChangeException(t);
395         }
396     }
397
398     /**
399      * Set a parameter to a Java int value. The driver converts this
400      * to a SQL INTEGER value when it sends it to the database.
401      *
402      * @param parameterIndex the first parameter is 1, the second is 2, ...
403      * @param x the parameter value
404      * @exception SQLException thrown on failure.
405      */

406     public void setInt(int parameterIndex, int x) throws SQLException JavaDoc {
407         checkStatus();
408
409         try {
410             /* JDBC is one-based, DBMS is zero-based */
411             getParms().getParameterForSet(parameterIndex - 1).setValue(x);
412         } catch (Throwable JavaDoc t) {
413             throw EmbedResultSet.noStateChangeException(t);
414         }
415     }
416
417     /**
418      * Set a parameter to a Java long value. The driver converts this
419      * to a SQL BIGINT value when it sends it to the database.
420      *
421      * @param parameterIndex the first parameter is 1, the second is 2, ...
422      * @param x the parameter value
423      * @exception SQLException thrown on failure.
424      */

425     public void setLong(int parameterIndex, long x) throws SQLException JavaDoc {
426         checkStatus();
427         try {
428             /* JDBC is one-based, DBMS is zero-based */
429             getParms().getParameterForSet(parameterIndex - 1).setValue(x);
430
431         } catch (Throwable JavaDoc t) {
432             throw EmbedResultSet.noStateChangeException(t);
433         }
434
435     }
436
437     /**
438      * Set a parameter to a Java float value. The driver converts this
439      * to a SQL FLOAT value when it sends it to the database.
440      *
441      * @param parameterIndex the first parameter is 1, the second is 2, ...
442      * @param x the parameter value
443      * @exception SQLException thrown on failure.
444      */

445     public void setFloat(int parameterIndex, float x) throws SQLException JavaDoc {
446         checkStatus();
447         try {
448             /* JDBC is one-based, DBMS is zero-based */
449             getParms().getParameterForSet(parameterIndex - 1).setValue(x);
450
451         } catch (Throwable JavaDoc t) {
452             throw EmbedResultSet.noStateChangeException(t);
453         }
454
455     }
456
457     /**
458      * Set a parameter to a Java double value. The driver converts this
459      * to a SQL DOUBLE value when it sends it to the database.
460      *
461      * @param parameterIndex the first parameter is 1, the second is 2, ...
462      * @param x the parameter value
463      * @exception SQLException thrown on failure.
464      */

465     public void setDouble(int parameterIndex, double x) throws SQLException JavaDoc {
466         checkStatus();
467
468         try {
469             /* JDBC is one-based, DBMS is zero-based */
470             getParms().getParameterForSet(parameterIndex - 1).setValue(x);
471
472         } catch (Throwable JavaDoc t) {
473             throw EmbedResultSet.noStateChangeException(t);
474         }
475
476     }
477
478     /**
479      * Set a parameter to a Java String value. The driver converts this
480      * to a SQL VARCHAR or LONGVARCHAR value (depending on the arguments
481      * size relative to the driver's limits on VARCHARs) when it sends
482      * it to the database.
483      *
484      * @param parameterIndex the first parameter is 1, the second is 2, ...
485      * @param x the parameter value
486      * @exception SQLException thrown on failure.
487      */

488     public void setString(int parameterIndex, String JavaDoc x) throws SQLException JavaDoc {
489         checkStatus();
490         try {
491             /* JDBC is one-based, DBMS is zero-based */
492             getParms().getParameterForSet(parameterIndex - 1).setValue(x);
493
494         } catch (Throwable JavaDoc t) {
495             throw EmbedResultSet.noStateChangeException(t);
496         }
497     }
498
499     /**
500      * Set a parameter to a Java array of bytes. The driver converts
501      * this to a SQL VARBINARY or LONGVARBINARY (depending on the
502      * argument's size relative to the driver's limits on VARBINARYs)
503      * when it sends it to the database.
504      *
505      * @param parameterIndex the first parameter is 1, the second is 2, ...
506      * @param x the parameter value
507      * @exception SQLException thrown on failure.
508      */

509     public void setBytes(int parameterIndex, byte x[]) throws SQLException JavaDoc {
510         checkStatus();
511
512         try {
513             /* JDBC is one-based, DBMS is zero-based */
514             getParms().getParameterForSet(parameterIndex - 1).setValue(x);
515
516         } catch (Throwable JavaDoc t) {
517             throw EmbedResultSet.noStateChangeException(t);
518         }
519
520     }
521
522     /**
523      * Set a parameter to a java.sql.Date value. The driver converts this
524      * to a SQL DATE value when it sends it to the database.
525      *
526      * @param parameterIndex the first parameter is 1, the second is 2, ...
527      * @param x the parameter value
528      * @exception SQLException thrown on failure.
529      */

530     public void setDate(int parameterIndex, Date JavaDoc x) throws SQLException JavaDoc {
531         setDate( parameterIndex, x, (Calendar JavaDoc) null);
532     }
533
534     /**
535      * Set a parameter to a java.sql.Time value. The driver converts this
536      * to a SQL TIME value when it sends it to the database.
537      *
538      * @param parameterIndex the first parameter is 1, the second is 2, ...
539      * @param x the parameter value
540      * @exception SQLException thrown on failure.
541      */

542     public void setTime(int parameterIndex, Time JavaDoc x) throws SQLException JavaDoc {
543         setTime( parameterIndex, x, (Calendar JavaDoc) null);
544     }
545
546     /**
547      * Set a parameter to a java.sql.Timestamp value. The driver
548      * converts this to a SQL TIMESTAMP value when it sends it to the
549      * database.
550      *
551      * @param parameterIndex the first parameter is 1, the second is 2, ...
552      * @param x the parameter value
553      * @exception SQLException thrown on failure.
554      */

555     public void setTimestamp(int parameterIndex, Timestamp JavaDoc x)
556         throws SQLException JavaDoc {
557         setTimestamp( parameterIndex, x, (Calendar JavaDoc) null);
558     }
559
560     /**
561      * We do this inefficiently and read it all in here. The target type
562      * is assumed to be a String.
563      *
564      * @param parameterIndex the first parameter is 1, the second is 2, ...
565      * @param x the java input stream which contains the ASCII parameter value
566      * @param length the number of bytes in the stream
567      * @exception SQLException thrown on failure.
568      */

569     public final void setAsciiStream(int parameterIndex, InputStream JavaDoc x, long length)
570         throws SQLException JavaDoc {
571         checkAsciiStreamConditions(parameterIndex);
572         java.io.Reader JavaDoc r = null;
573
574         if (x != null)
575         {
576             // Use ISO-8859-1 and not US-ASCII as JDBC seems to define
577
// ASCII as 8 bits. US-ASCII is 7.
578
try {
579                 r = new java.io.InputStreamReader JavaDoc(x, "ISO-8859-1");
580             } catch (java.io.UnsupportedEncodingException JavaDoc uee) {
581                 throw new SQLException JavaDoc(uee.getMessage());
582             }
583         }
584
585         setCharacterStreamInternal(parameterIndex, r, false, length);
586     }
587
588     /**
589      * We do this inefficiently and read it all in here. The target type
590      * is assumed to be a String.
591      *
592      * @param parameterIndex the first parameter is 1, the second is 2, ...
593      * @param x the java input stream which contains the ASCII parameter value
594      * @param length the number of bytes in the stream
595      * @exception SQLException thrown on failure.
596      */

597
598     public final void setAsciiStream(int parameterIndex, InputStream JavaDoc x, int length)
599     throws SQLException JavaDoc {
600         setAsciiStream(parameterIndex,x,(long)length);
601     }
602
603
604     /**
605         Deprecated in JDBC 3.0
606      *
607      * @param parameterIndex the first parameter is 1, the second is 2, ...
608      * @param x the java input stream which contains the
609      * UNICODE parameter value
610      * @param length the number of bytes in the stream
611      * @exception SQLException thrown on failure.
612      */

613     public void setUnicodeStream(int parameterIndex, InputStream JavaDoc x, int length)
614         throws SQLException JavaDoc
615     {
616         throw Util.notImplemented("setUnicodeStream");
617     }
618
619     /**
620      * When a very large UNICODE value is input to a LONGVARCHAR
621      * parameter, it may be more practical to send it via a
622      * java.io.Reader. JDBC will read the data from the stream
623      * as needed, until it reaches end-of-file. The JDBC driver will
624      * do any necessary conversion from UNICODE to the database char format.
625      *
626      * <P><B>Note:</B> This stream object can either be a standard
627      * Java stream object or your own subclass that implements the
628      * standard interface.
629      *
630      * @param parameterIndex the first parameter is 1, the second is 2, ...
631      * @param reader the java reader which contains the UNICODE data
632      * @param length the number of characters in the stream
633      * @exception SQLException if a database-access error occurs.
634      */

635     public final void setCharacterStream(int parameterIndex,
636                   java.io.Reader JavaDoc reader,
637               long length) throws SQLException JavaDoc {
638         checkCharacterStreamConditions(parameterIndex);
639         setCharacterStreamInternal(parameterIndex, reader, false, length);
640     }
641
642     /**
643      * When a very large UNICODE value is input to a LONGVARCHAR
644      * parameter, it may be more practical to send it via a
645      * java.io.Reader. JDBC will read the data from the stream
646      * as needed, until it reaches end-of-file. The JDBC driver will
647      * do any necessary conversion from UNICODE to the database char format.
648      *
649      * <P><B>Note:</B> This stream object can either be a standard
650      * Java stream object or your own subclass that implements the
651      * standard interface.
652      *
653      * @param parameterIndex the first parameter is 1, the second is 2, ...
654      * @param reader the java reader which contains the UNICODE data
655      * @param length the number of characters in the stream
656      * @exception SQLException if a database-access error occurs.
657      */

658     public final void setCharacterStream(int parameterIndex,
659         java.io.Reader JavaDoc reader,
660         int length) throws SQLException JavaDoc {
661         setCharacterStream(parameterIndex,reader,(long)length);
662     }
663
664     /**
665      * Check general preconditions for setCharacterStream methods.
666      *
667      * @param parameterIndex 1-based index of the parameter.
668      */

669     private final void checkCharacterStreamConditions(int parameterIndex)
670             throws SQLException JavaDoc {
671         checkStatus();
672         int jdbcTypeId = getParameterJDBCType(parameterIndex);
673         if (!DataTypeDescriptor.isCharacterStreamAssignable(jdbcTypeId)) {
674             throw dataTypeConversion(parameterIndex, "java.io.Reader");
675         }
676     }
677
678     /**
679      * Check general preconditions for setAsciiStream methods.
680      *
681      * @param parameterIndex 1-based index of the parameter.
682      */

683     private final void checkAsciiStreamConditions(int parameterIndex)
684             throws SQLException JavaDoc {
685         checkStatus();
686         int jdbcTypeId = getParameterJDBCType(parameterIndex);
687         if (!DataTypeDescriptor.isAsciiStreamAssignable(jdbcTypeId)) {
688             throw dataTypeConversion(parameterIndex,
689                                      "java.io.InputStream(ASCII)");
690         }
691     }
692
693     /**
694      * Set the given character stream for the specified parameter.
695      *
696      * If <code>lengthLess</code> is <code>true</code>, the following
697      * conditions are either not checked or verified at the execution time
698      * of the prepared statement:
699      * <ol><li>If the stream length is negative.
700      * <li>If the stream's actual length equals the specified length.</ol>
701      * The <code>lengthLess</code> variable was added to differentiate between
702      * streams with invalid lengths and streams without known lengths.
703      *
704      * @param parameterIndex the 1-based index of the parameter to set.
705      * @param reader the data.
706      * @param lengthLess tells whether we know the length of the data or not.
707      * @param length the length of the data. Ignored if <code>lengthLess</code>
708      * is <code>true</code>.
709      */

710     private void setCharacterStreamInternal(int parameterIndex,
711                                             Reader reader,
712                                             final boolean lengthLess,
713                                             long length)
714         throws SQLException JavaDoc
715     {
716         // Check for negative length if length is specified.
717
if (!lengthLess && length < 0)
718             throw newSQLException(SQLState.NEGATIVE_STREAM_LENGTH);
719
720         int jdbcTypeId = getParameterJDBCType(parameterIndex);
721
722
723         if (reader == null) {
724              setNull(parameterIndex, jdbcTypeId);
725              return;
726         }
727
728         /*
729            The value stored should not exceed the maximum value that can be
730            stored in an integer
731            This checking needs to be done because currently derby does not
732            support Clob sizes greater than 2G-1
733         */

734         if (!lengthLess && length > Integer.MAX_VALUE)
735                throw newSQLException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE,
736                                      getParameterSQLType(parameterIndex));
737
738         try {
739             ReaderToUTF8Stream utfIn;
740             ParameterValueSet pvs = getParms();
741             // Need column width to figure out if truncation is needed
742
DataTypeDescriptor dtd[] = preparedStatement
743                     .getParameterTypes();
744             int colWidth = dtd[parameterIndex - 1].getMaximumWidth();
745             // Default to max column width. This will be used to limit the
746
// amount of data read when operating on "lengthless" streams.
747
int usableLength = colWidth;
748
749             if (!lengthLess) {
750                 // We cast the length from long to int. This wouldn't be
751
// appropriate if the limit of 2G-1 is decided to be increased
752
// at a later stage.
753
int intLength = (int)length;
754                 int truncationLength = 0;
755
756                 usableLength = intLength;
757
758                 // Currently long varchar does not allow for truncation of
759
// trailing blanks.
760
// For char and varchar types, current mechanism of
761
// materializing when using streams seems fine given their max
762
// limits.
763
// This change is fix for DERBY-352: Insert of clobs using
764
// streams should not materialize the entire stream into memory
765
// In case of clobs, the truncation of trailing blanks is
766
// factored in when reading from the stream without
767
// materializing the entire stream, and so the special casing
768
// for clob below.
769
if (jdbcTypeId == Types.CLOB)
770                 {
771
772                     // It is possible that the length of the stream passed in
773
// is greater than the column width, in which case the data
774
// from the stream needs to be truncated.
775
// usableLength is the length of the data from stream that
776
// can be inserted which is min(colWidth,length) provided
777
// length - colWidth has trailing blanks only
778
// we have used intLength into which the length variable had
779
// been cast to an int and stored
780
if (intLength > colWidth) {
781                         usableLength = colWidth;
782                         truncationLength = intLength - usableLength;
783                     }
784                 }
785                 // Create a stream with truncation.
786
utfIn = new ReaderToUTF8Stream(reader, usableLength,
787                         truncationLength, getParameterSQLType(parameterIndex));
788             } else {
789                 // Create a stream without exactness checks,
790
// but with a maximum limit.
791
utfIn = new ReaderToUTF8Stream(reader, colWidth,
792                                 getParameterSQLType(parameterIndex));
793             }
794
795             // JDBC is one-based, DBMS is zero-based.
796
// Note that for lengthless stream, usableLength will be
797
// the maximum length for the column.
798
// This is okay, based on the observation that
799
// setValue does not use the value for anything at all.
800
pvs.getParameterForSet(
801                 parameterIndex - 1).setValue(utfIn, usableLength);
802
803         } catch (StandardException t) {
804             throw EmbedResultSet.noStateChangeException(t);
805         }
806     }
807
808     /**
809      * Sets the designated parameter to the given input stream.
810      * When a very large binary value is input to a <code>LONGVARBINARY</code>
811      * parameter, it may be more practical to send it via a
812      * <code>java.io.InputStream</code> object. The data will be read from the
813      * stream as needed until end-of-file is reached.
814      *
815      * <em>Note:</em> This stream object can either be a standard Java stream
816      * object or your own subclass that implements the standard interface.
817      *
818      * @param parameterIndex the first parameter is 1, the second is 2, ...
819      * @param x the java input stream which contains the binary parameter value
820      * @throws SQLException if a database access error occurs or this method is
821      * called on a closed <code>PreparedStatement</code>
822      */

823     public void setBinaryStream(int parameterIndex, InputStream JavaDoc x)
824             throws SQLException JavaDoc {
825         checkBinaryStreamConditions(parameterIndex);
826         setBinaryStreamInternal(parameterIndex, x, true, -1);
827     }
828
829     /**
830      * sets the parameter to the Binary stream
831      *
832      * @param parameterIndex the first parameter is 1, the second is 2, ...
833      * @param x the java input stream which contains the binary parameter value
834      * @param length the number of bytes in the stream
835      * @exception SQLException thrown on failure.
836      */

837     public final void setBinaryStream(int parameterIndex, InputStream JavaDoc x, long length)
838         throws SQLException JavaDoc {
839         checkBinaryStreamConditions(parameterIndex);
840         setBinaryStreamInternal(parameterIndex, x, false, length);
841     }
842
843     /**
844      * sets the parameter to the binary stream
845      *
846      * @param parameterIndex the first parameter is 1, the second is 2, ...
847      * @param x the java input stream which contains the binary parameter value
848      * @param length the number of bytes in the stream
849      * @exception SQLException thrown on failure.
850      */

851     public final void setBinaryStream(int parameterIndex, InputStream JavaDoc x, int length)
852     throws SQLException JavaDoc {
853         setBinaryStream(parameterIndex,x,(long)length);
854     }
855
856     /**
857      * Set the given stream for the specified parameter.
858      *
859      * If <code>lengthLess</code> is <code>true</code>, the following
860      * conditions are either not checked or verified at the execution time
861      * of the prepared statement:
862      * <ol><li>If the stream length is negative.
863      * <li>If the stream's actual length equals the specified length.</ol>
864      * The <code>lengthLess</code> variable was added to differentiate between
865      * streams with invalid lengths and streams without known lengths.
866      *
867      * @param parameterIndex the 1-based index of the parameter to set.
868      * @param x the data.
869      * @param lengthLess tells whether we know the length of the data or not.
870      * @param length the length of the data. Ignored if <code>lengthLess</code>
871      * is <code>true</code>.
872      */

873     private void setBinaryStreamInternal(int parameterIndex, InputStream JavaDoc x,
874                                          final boolean lengthLess, long length)
875         throws SQLException JavaDoc
876     {
877
878         if ( !lengthLess && length < 0 )
879             throw newSQLException(SQLState.NEGATIVE_STREAM_LENGTH);
880         
881         int jdbcTypeId = getParameterJDBCType(parameterIndex);
882         if (x == null) {
883             setNull(parameterIndex, jdbcTypeId);
884             return;
885         }
886         
887         // max number of bytes that can be set to be inserted
888
// in Derby is 2Gb-1 (ie Integer.MAX_VALUE).
889
// (e.g into a blob column).
890
// For now, we cast the length from long to int as a result.
891
// If we ever decide to increase these limits for lets say blobs,
892
// in that case the cast to int would not be appropriate.
893
if ( !lengthLess && length > Integer.MAX_VALUE ) {
894             throw newSQLException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE,
895                getEmbedParameterSetMetaData().getParameterTypeName(
896                    parameterIndex));
897         }
898
899         try {
900             RawToBinaryFormatStream rawStream;
901             if (lengthLess) {
902                 // Force length to -1 for good measure.
903
length = -1;
904                 DataTypeDescriptor dtd[] =
905                     preparedStatement.getParameterTypes();
906                 rawStream = new RawToBinaryFormatStream(x,
907                         dtd[parameterIndex -1].getMaximumWidth(),
908                         dtd[parameterIndex -1].getTypeName());
909             } else {
910                 rawStream = new RawToBinaryFormatStream(x, (int)length);
911             }
912             getParms().getParameterForSet(parameterIndex - 1).setValue(
913                     rawStream, (int)length);
914
915         } catch (StandardException t) {
916             throw EmbedResultSet.noStateChangeException(t);
917         }
918     }
919
920     /**
921      * Check general preconditions for setBinaryStream methods.
922      *
923      * @param parameterIndex 1-based index of the parameter.
924      */

925     private final void checkBinaryStreamConditions(int parameterIndex)
926             throws SQLException JavaDoc {
927         checkStatus();
928         int jdbcTypeId = getParameterJDBCType(parameterIndex);
929         if (!DataTypeDescriptor.isBinaryStreamAssignable(jdbcTypeId)) {
930             throw dataTypeConversion(parameterIndex, "java.io.InputStream");
931         }
932     }
933
934     /////////////////////////////////////////////////////////////////////////
935
//
936
// JDBC 2.0 - New public methods
937
//
938
/////////////////////////////////////////////////////////////////////////
939

940     /**
941      *
942      * JDBC 2.0
943      *
944      * Sets the designated parameter to SQL <code>NULL</code>.
945      * This version of the method <code>setNull</code> should
946      * be used for user-defined types and REF type parameters. Examples
947      * of user-defined types include: STRUCT, DISTINCT, JAVA_OBJECT, and
948      * named array types.
949      *
950      * @param paramIndex the first parameter is 1, the second is 2, ...
951      * @param sqlType a value from <code>java.sql.Types</code>
952      * @param typeName the fully-qualified name of an SQL user-defined type;
953      * ignored if the parameter is not a user-defined type or REF
954      * @exception SQLException if a database access error occurs or
955      * this method is called on a closed <code>PreparedStatement</code>
956      * @exception SQLFeatureNotSupportedException if <code>sqlType</code> is
957      * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
958      * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
959      * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
960      * <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
961      * or <code>STRUCT</code> data type and the JDBC driver does not support
962      * this data type or if the JDBC driver does not support this method
963      *
964      */

965     public void setNull(int paramIndex,
966         int sqlType,
967         String JavaDoc typeName)
968         throws SQLException JavaDoc {
969         setNull(paramIndex,sqlType);
970     }
971
972     /**
973      * JDBC 2.0
974      *
975      * Add a set of parameters to the batch.
976      *
977      * @exception SQLException if a database-access error occurs.
978      */

979     public void addBatch() throws SQLException JavaDoc {
980       checkStatus();
981
982       // need to synchronized to ensure that two threads
983
// don't both create a Vector at the same time. This
984
// would lead to one of the set of parameters being thrown
985
// away
986
synchronized (getConnectionSynchronization()) {
987             if (batchStatements == null)
988                 batchStatements = new Vector JavaDoc();
989
990           //get a clone of the parameterValueSet and save it in the vector
991
//which will be used later on at the time of batch execution.
992
//This way we will get a copy of the current statement's parameter
993
//values rather than a pointer to the statement's parameter value
994
//set which will change with every new statement in the batch.
995
batchStatements.addElement(getParms().getClone());
996           clearParameters();
997       }
998     }
999
1000    boolean executeBatchElement(Object JavaDoc batchElement) throws SQLException JavaDoc, StandardException {
1001        
1002        ParameterValueSet temp = (ParameterValueSet) batchElement;
1003
1004        int numberOfParameters = temp.getParameterCount();
1005
1006        for (int j=0; j<numberOfParameters; j++) {
1007            temp.getParameter(j).setInto(this, j + 1);
1008        }
1009
1010        return super.executeStatement(activation, false, true);
1011    }
1012
1013 
1014
1015    /**
1016     * <P>In general, parameter values remain in force for repeated use of a
1017     * Statement. Setting a parameter value automatically clears its
1018     * previous value. However, in some cases it is useful to immediately
1019     * release the resources used by the current parameter values; this can
1020     * be done by calling clearParameters.
1021     * @exception SQLException thrown on failure.
1022     */

1023    public void clearParameters() throws SQLException JavaDoc {
1024        checkStatus();
1025
1026        ParameterValueSet pvs = getParms();
1027        if (pvs != null)
1028            pvs.clearParameters();
1029    }
1030
1031    /**
1032     * JDBC 2.0
1033     *
1034     * The number, types and properties of a ResultSet's columns
1035     * are provided by the getMetaData method.
1036     *
1037     * @return the description of a ResultSet's columns
1038     * @exception SQLException Feature not implemented for now.
1039     */

1040    public java.sql.ResultSetMetaData JavaDoc getMetaData() throws SQLException JavaDoc
1041    {
1042        checkExecStatus();
1043        synchronized (getConnectionSynchronization())
1044        {
1045            //reason for casting is getActivationClass is not available on PreparedStatement
1046
ExecPreparedStatement execp = (ExecPreparedStatement)preparedStatement;
1047
1048            setupContextStack(); // make sure there's context
1049

1050            try {
1051                //bug 4579 - if the statement is invalid, regenerate the metadata info
1052
if (preparedStatement.isValid() == false)
1053                {
1054                    //need to revalidate the statement here, otherwise getResultDescription would
1055
//still have info from previous valid statement
1056
preparedStatement.rePrepare(lcc);
1057                    rMetaData = null;
1058                }
1059                //bug 4579 - gcDuringGetMetaData will be null if this is the first time
1060
//getMetaData call is made.
1061
//Second check - if the statement was revalidated since last getMetaData call,
1062
//then gcDuringGetMetaData wouldn't match with current generated class name
1063
if (gcDuringGetMetaData == null || gcDuringGetMetaData.equals(execp.getActivationClass().getName()) == false)
1064                {
1065                    rMetaData = null;
1066                    gcDuringGetMetaData = execp.getActivationClass().getName();
1067                }
1068                if (rMetaData == null)
1069                {
1070                    ResultDescription resd = preparedStatement.getResultDescription();
1071                    if (resd != null)
1072                    {
1073                        // Internally, the result description has information
1074
// which is used for insert, update and delete statements
1075
// Externally, we decided that statements which don't
1076
// produce result sets such as insert, update and delete
1077
// should not return ResultSetMetaData. This is enforced
1078
// here
1079
String JavaDoc statementType = resd.getStatementType();
1080                        if (statementType.equals("INSERT") ||
1081                                statementType.equals("UPDATE") ||
1082                                statementType.equals("DELETE"))
1083                            rMetaData = null;
1084                        else
1085                            rMetaData = newEmbedResultSetMetaData(resd);
1086                    }
1087                }
1088            } catch (Throwable JavaDoc t) {
1089                throw handleException(t);
1090            } finally {
1091                restoreContextStack();
1092            }
1093        }
1094        return rMetaData;
1095    }
1096
1097    //----------------------------------------------------------------------
1098
// Advanced features:
1099

1100    /**
1101     * The interface says that the type of the Object parameter must
1102     * be compatible with the type of the targetSqlType. We check that,
1103     * and if it flies, we expect the underlying engine to do the
1104     * required conversion once we pass in the value using its type.
1105     * So, an Integer converting to a CHAR is done via setInteger()
1106     * support on the underlying CHAR type.
1107     *
1108     * <p>If x is null, it won't tell us its type, so we pass it on to setNull
1109     *
1110     * @param parameterIndex The first parameter is 1, the second is 2, ...
1111     * @param x The object containing the input parameter value
1112     * @param targetSqlType The SQL type (as defined in java.sql.Types) to be
1113     * sent to the database. The scale argument may further qualify this type.
1114     * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
1115     * this is the number of digits after the decimal. For all other
1116     * types this value will be ignored,
1117     * @exception SQLException thrown on failure.
1118     */

1119    public final void setObject(int parameterIndex, Object JavaDoc x, int targetSqlType, int scale)
1120            throws SQLException JavaDoc {
1121
1122        if (x == null) {
1123            setNull(parameterIndex, targetSqlType);
1124            return;
1125        }
1126
1127        checkForSupportedDataType(targetSqlType);
1128
1129        int paramJDBCType = getParameterJDBCType(parameterIndex);
1130
1131        if (paramJDBCType != java.sql.Types.JAVA_OBJECT) {
1132            if (!DataTypeDescriptor.isJDBCTypeEquivalent(paramJDBCType, targetSqlType)) {
1133                throw dataTypeConversion(parameterIndex, Util.typeName(targetSqlType));
1134            }
1135        }
1136
1137        setObject(parameterIndex, x);
1138                
1139        /*
1140        * If the parameter type is DECIMAL or NUMERIC, then
1141        * we need to set the correct scale or set it
1142        * to the default which is zero for setObject.
1143        */

1144        if ((paramJDBCType == Types.DECIMAL) ||
1145             (paramJDBCType == Types.NUMERIC))
1146        {
1147            setScale(parameterIndex, scale);
1148        }
1149    }
1150
1151    /**
1152      * This method is like setObject above, but assumes a scale of zero.
1153     * @exception SQLException thrown on failure.
1154      */

1155    public final void setObject(int parameterIndex, Object JavaDoc x, int targetSqlType)
1156        throws SQLException JavaDoc {
1157        setObject(parameterIndex, x, targetSqlType, 0);
1158    }
1159
1160    /**
1161     * <p>Set the value of a parameter using an object; use the
1162     * java.lang equivalent objects for integral values.
1163     *
1164     * <p>The JDBC specification specifies a standard mapping from
1165     * Java Object types to SQL types. The given argument java object
1166     * will be converted to the corresponding SQL type before being
1167     * sent to the database.
1168     *
1169     * <p>Note that this method may be used to pass datatabase
1170     * specific abstract data types, by using a Driver specific Java
1171     * type.
1172     *
1173     * @param parameterIndex The first parameter is 1, the second is 2, ...
1174     * @param x The object containing the input parameter value
1175     * @exception SQLException thrown on failure.
1176     */

1177    public final void setObject(int parameterIndex, Object JavaDoc x) throws SQLException JavaDoc {
1178        checkStatus();
1179
1180
1181        int colType = getParameterJDBCType(parameterIndex);
1182
1183        // JDBC Tutorial and Reference books states in the PreparedStatement
1184
// overview, that passing a untyped null into setObject() is not allowed.
1185
// JCC disallows this, basically SQL can not handle a untyped NULL.
1186
// Section 25.1.6 (Third edition), 24.1.5 (Second Edition)
1187

1188        if (x == null) {
1189            //setNull(parameterIndex, colType);
1190
//return;
1191
throw dataTypeConversion(parameterIndex, "null");
1192        }
1193        
1194        if (colType == org.apache.derby.iapi.reference.JDBC20Translation.SQL_TYPES_JAVA_OBJECT) {
1195            try {
1196                /* JDBC is one-based, DBMS is zero-based */
1197                getParms().setParameterAsObject(parameterIndex - 1, x);
1198                return;
1199
1200            } catch (Throwable JavaDoc t) {
1201                throw EmbedResultSet.noStateChangeException(t);
1202            }
1203        }
1204
1205
1206        // Need to do instanceof checks here so that the behaviour
1207
// for these calls is consistent with the matching setXXX() value.
1208

1209        // These are the supported setObject conversions from JDBC 3.0 table B5
1210
// Byte and Short were added to the table in JDBC 4.0.
1211

1212        if (x instanceof String JavaDoc) {
1213            setString(parameterIndex, (String JavaDoc) x);
1214            return;
1215        }
1216
1217        if (x instanceof Boolean JavaDoc) {
1218            setBoolean(parameterIndex, ((Boolean JavaDoc) x).booleanValue());
1219            return;
1220        }
1221        if (x instanceof Byte JavaDoc) {
1222            setByte(parameterIndex, ((Byte JavaDoc) x).byteValue());
1223            return;
1224        }
1225        if (x instanceof Short JavaDoc) {
1226            setShort(parameterIndex, ((Short JavaDoc) x).shortValue());
1227            return;
1228        }
1229        if (x instanceof Integer JavaDoc) {
1230            setInt(parameterIndex, ((Integer JavaDoc) x).intValue());
1231            return;
1232        }
1233        if (x instanceof Long JavaDoc) {
1234            setLong(parameterIndex, ((Long JavaDoc) x).longValue());
1235            return;
1236        }
1237
1238        if (x instanceof Float JavaDoc) {
1239            setFloat(parameterIndex, ((Float JavaDoc) x).floatValue());
1240            return;
1241        }
1242        if (x instanceof Double JavaDoc) {
1243            setDouble(parameterIndex, ((Double JavaDoc) x).doubleValue());
1244            return;
1245        }
1246
1247        if (x instanceof byte[]) {
1248            setBytes(parameterIndex, (byte[]) x);
1249            return;
1250        }
1251
1252        if (x instanceof Date JavaDoc) {
1253            setDate(parameterIndex, (Date JavaDoc) x);
1254            return;
1255        }
1256        if (x instanceof Time JavaDoc) {
1257            setTime(parameterIndex, (Time JavaDoc) x);
1258            return;
1259        }
1260        if (x instanceof Timestamp JavaDoc) {
1261            setTimestamp(parameterIndex, (Timestamp JavaDoc) x);
1262            return;
1263        }
1264
1265        if (x instanceof Blob JavaDoc) {
1266            setBlob(parameterIndex, (Blob JavaDoc) x);
1267            return;
1268        }
1269        if (x instanceof Clob JavaDoc) {
1270            setClob(parameterIndex, (Clob JavaDoc) x);
1271            return;
1272        }
1273
1274        if (setObjectConvert(parameterIndex, x))
1275            return;
1276
1277        
1278        throw dataTypeConversion(parameterIndex, x.getClass().getName());
1279
1280    }
1281
1282    /**
1283        Allow explict setObject conversions by sub-classes for classes
1284        not supported by this variant. E.g. BigDecimal
1285        This top-level implementation always returns false.
1286
1287        @return true if the object was set successfully, false if no valid
1288        conversion exists.
1289
1290        @exception SQLException value could not be set.
1291    */

1292    boolean setObjectConvert(int parameterIndex, Object JavaDoc x) throws SQLException JavaDoc
1293    {
1294        return false;
1295    }
1296
1297    /**
1298     * @see java.sql.Statement#execute
1299     * @exception SQLException thrown on failure.
1300     */

1301        public final boolean execute() throws SQLException JavaDoc {
1302            boolean ret=false;
1303            try{
1304                ret = executeStatement(activation, false, false);
1305            } catch(SQLException JavaDoc sqle) {
1306                checkStatementValidity(sqle);
1307            }
1308            return ret;
1309        }
1310    /**
1311     * Set a parameter to a java.sql.Date value. The driver converts this
1312     * to a SQL DATE value when it sends it to the database.
1313     *
1314     * @param parameterIndex the first parameter is 1, the second is 2, ...
1315     * @param x the parameter value
1316     * @exception SQLException Feature not implemented for now.
1317     */

1318    public final void setDate(int parameterIndex, java.sql.Date JavaDoc x, Calendar JavaDoc cal)
1319        throws SQLException JavaDoc
1320    {
1321        checkStatus();
1322        try {
1323            /* JDBC is one-based, DBMS is zero-based */
1324            getParms().getParameterForSet(parameterIndex - 1).setValue(x, cal);
1325
1326        } catch (Throwable JavaDoc t) {
1327            throw EmbedResultSet.noStateChangeException(t);
1328        }
1329    }
1330
1331    /**
1332     * Set a parameter to a java.sql.Time value. The driver converts this
1333     * to a SQL TIME value when it sends it to the database.
1334     *
1335     * @param parameterIndex the first parameter is 1, the second is 2, ...
1336     * @param x the parameter value
1337     * @exception SQLException Feature not implemented for now.
1338     */

1339    public final void setTime(int parameterIndex, java.sql.Time JavaDoc x, Calendar JavaDoc cal)
1340        throws SQLException JavaDoc
1341    {
1342        checkStatus();
1343        try {
1344            /* JDBC is one-based, DBMS is zero-based */
1345            getParms().getParameterForSet(parameterIndex - 1).setValue(x, cal);
1346
1347        } catch (Throwable JavaDoc t) {
1348            throw EmbedResultSet.noStateChangeException(t);
1349        }
1350    }
1351
1352    /**
1353     * Set a parameter to a java.sql.Timestamp value. The driver
1354     * converts this to a SQL TIMESTAMP value when it sends it to the
1355     * database.
1356     *
1357     * @param parameterIndex the first parameter is 1, the second is 2, ...
1358     * @param x the parameter value
1359     * @exception SQLException Feature not implemented for now.
1360     */

1361    public final void setTimestamp(int parameterIndex, java.sql.Timestamp JavaDoc x, Calendar JavaDoc cal)
1362        throws SQLException JavaDoc
1363    {
1364        checkStatus();
1365        try {
1366            /* JDBC is one-based, DBMS is zero-based */
1367            getParms().getParameterForSet(parameterIndex - 1).setValue(x, cal);
1368
1369        } catch (StandardException t) {
1370            throw EmbedResultSet.noStateChangeException(t);
1371        }
1372    }
1373
1374
1375    /**
1376     * JDBC 2.0
1377     *
1378     * Set a BLOB parameter.
1379     *
1380     * @param i the first parameter is 1, the second is 2, ...
1381     * @param x an object representing a BLOB
1382     */

1383    public void setBlob (int i, Blob JavaDoc x)
1384        throws SQLException JavaDoc
1385    {
1386        checkBlobConditions(i);
1387        if (x == null)
1388            setNull(i, Types.BLOB);
1389        else
1390        {
1391            // Note, x.length() needs to be called before retrieving the
1392
// stream using x.getBinaryStream() because EmbedBlob.length()
1393
// will read from the stream and drain some part of the stream
1394
// Hence the need to declare this local variable - streamLength
1395
long streamLength = x.length();
1396            setBinaryStreamInternal(i, x.getBinaryStream(), false,
1397                    streamLength);
1398        }
1399    }
1400
1401    /**
1402     * Check general (pre)conditions for setClob methods.
1403     *
1404     * @param parameterIndex 1-based index of the parameter.
1405     */

1406    private final void checkClobConditions(int parameterIndex)
1407            throws SQLException JavaDoc {
1408        checkStatus();
1409        if (getParameterJDBCType(parameterIndex) != Types.CLOB) {
1410            throw dataTypeConversion(parameterIndex, "java.sql.Clob");
1411        }
1412    }
1413
1414    /**
1415     * JDBC 2.0
1416     *
1417     * Set a CLOB parameter.
1418     *
1419     * @param i the first parameter is 1, the second is 2, ...
1420     * @param x an object representing a CLOB
1421     */

1422    public void setClob (int i, Clob JavaDoc x)
1423        throws SQLException JavaDoc
1424    {
1425        checkClobConditions(i);
1426        if (x == null)
1427            setNull(i, Types.CLOB);
1428        else
1429        {
1430            // 1. max number of characters that can be inserted into a clob column
1431
// is 2Gb-1 which is Integer.MAX_INT.
1432
// This means that we do not allow any inserts of clobs where
1433
// clob.length() > Integer.MAX_INT. For now, we cast the x.length()
1434
// to int as a result. This will work ok for valid clob values that
1435
// derby supports. If we ever decide to increase these limits for clobs, in that
1436
// case the cast of x.Length() to int would not be appropriate.
1437
// 2. Note, x.length() needs to be called before retrieving the
1438
// stream using x.getCharacterStream() because EmbedClob.length()
1439
// will read from the stream and drain the stream.
1440
// Hence the need to declare this local variable - streamLength
1441
long streamLength = x.length();
1442
1443            setCharacterStreamInternal(i, x.getCharacterStream(),
1444                                       false, streamLength);
1445        }
1446        
1447    }
1448
1449    /**
1450     * Get the ParameterValueSet from the activation
1451     *
1452     *
1453     * @return The ParameterValueSet for the activation
1454     *
1455     */

1456    public final ParameterValueSet getParms() {
1457
1458        return activation.getParameterValueSet();
1459    }
1460
1461
1462    /**
1463        Check the parameterINdex is in range and return the
1464        array of type descriptors.
1465
1466        @exception SQLException parameter is out of range
1467    */

1468    protected final DataTypeDescriptor[] getTypes(int parameterIndex)
1469        throws SQLException JavaDoc {
1470
1471        DataTypeDescriptor[] types = preparedStatement.getParameterTypes();
1472
1473        if (types == null) {
1474            throw newSQLException(SQLState.NO_INPUT_PARAMETERS);
1475        }
1476
1477        /* Check that the parameterIndex is in range. */
1478        if (parameterIndex < 1 ||
1479                parameterIndex > types.length) {
1480
1481            /* This message matches the one used by the DBMS */
1482            throw newSQLException(SQLState.LANG_INVALID_PARAM_POSITION,
1483            new Integer JavaDoc(parameterIndex), new Integer JavaDoc(types.length));
1484        }
1485        return types;
1486    }
1487
1488    /**
1489        Get the target JDBC type for a parameter. Will throw exceptions
1490        if the parameter index is out of range
1491
1492        @exception SQLException parameter is out of range
1493    */

1494    protected int getParameterJDBCType(int parameterIndex)
1495        throws SQLException JavaDoc {
1496
1497        DataTypeDescriptor[] types = getTypes(parameterIndex);
1498
1499        int type = types[parameterIndex -1] == null ?
1500            Types.OTHER :
1501            types[parameterIndex - 1].getTypeId().getJDBCTypeId();
1502
1503        if (SanityManager.DEBUG) {
1504            //int pmType = getEmbedParameterSetMetaData().getParameterType(parameterIndex);
1505
//if (type != pmType) {
1506
//SanityManager.THROWASSERT("MISMATCH PARAMETER META DATA param " + parameterIndex + " types " + type + " != " + pmType + "\n" + SQLText);
1507
//}
1508
}
1509
1510        return type;
1511    }
1512
1513    /**
1514     * Return the SQL type name for the parameter.
1515     *
1516     * @param parameterIndex the 1-based index of the parameter
1517     * @return SQL name of the parameter
1518     * @throws SQLException if parameter is out of range
1519     */

1520    protected final String JavaDoc getParameterSQLType(int parameterIndex)
1521            throws SQLException JavaDoc {
1522        DataTypeDescriptor[] pTypes = getTypes(parameterIndex);
1523        return pTypes[parameterIndex-1].getTypeName();
1524    }
1525
1526    /**
1527     * Set the scale of a parameter.
1528     *
1529     * @param parameterIndex The first parameter is 1, the second is 2, ...
1530     * @param scale The scale
1531     * @exception SQLException thrown on failure.
1532     */

1533    private void setScale(int parameterIndex, int scale)
1534        throws SQLException JavaDoc
1535    {
1536        checkStatus();
1537
1538        if (scale < 0)
1539            throw newSQLException(SQLState.BAD_SCALE_VALUE, new Integer JavaDoc(scale));
1540        
1541        try {
1542
1543            ParameterValueSet pvs = getParms();
1544
1545            /* JDBC is one-based, DBMS is zero-based */
1546            DataValueDescriptor value = pvs.getParameter(parameterIndex - 1);
1547
1548
1549            int origvaluelen = value.getLength();
1550            ((VariableSizeDataValue)
1551                        value).setWidth(VariableSizeDataValue.IGNORE_PRECISION,
1552                            scale,
1553                            false);
1554
1555            if (value.getLength() < origvaluelen)
1556            {
1557                activation.addWarning(StandardException.newWarning(SQLState.LANG_VALUE_TRUNCATED, value.getString()));
1558            }
1559
1560        } catch (StandardException t) {
1561            throw EmbedResultSet.noStateChangeException(t);
1562        }
1563    }
1564
1565
1566    /**
1567    * Immitate the function in JDBC 3.0
1568    *
1569    * Retrieves the number, types and properties of this PreparedStatement
1570    * object's parameters.
1571    *
1572    * @return a EngineParameterMetaData object that contains information about the
1573    * number, types and properties of this PreparedStatement object's parameters.
1574    * @exception SQLException if a database access error occurs
1575    */

1576    public EngineParameterMetaData getEmbedParameterSetMetaData()
1577        throws SQLException JavaDoc
1578    {
1579      checkExecStatus();
1580      return new EmbedParameterSetMetaData(
1581                getParms(), preparedStatement.getParameterTypes());
1582
1583    }
1584    /**
1585    * JDBC 3.0
1586    *
1587    * Sets the designated parameter to the given java.net.URL value. The driver
1588    * converts this to an SQL DATALINK value when it sends it to the database.
1589    *
1590    * @param parameterIndex - the first parameter is 1, the second is 2, ...
1591    * @param x - the java.net.URL object to be set
1592    * @exception SQLException Feature not implemented for now.
1593    */

1594    public final void setURL(int parameterIndex, java.net.URL JavaDoc x)
1595    throws SQLException JavaDoc
1596    {
1597        throw Util.notImplemented();
1598    }
1599
1600    //
1601
// methods to be overridden in subimplementations
1602
// that want to stay within their subimplementation.
1603
//
1604
protected EmbedResultSetMetaData newEmbedResultSetMetaData(ResultDescription resultDesc) {
1605
1606        return factory.newEmbedResultSetMetaData(resultDesc.getColumnInfo());
1607    }
1608
1609    public String JavaDoc toString() {
1610
1611        if (activation != null)
1612            return activation.getPreparedStatement().getObjectName();
1613        return super.toString();
1614    }
1615
1616    /*
1617    **
1618    */

1619    public void transferParameters(EmbedPreparedStatement newStatement) throws SQLException JavaDoc {
1620
1621        try {
1622            newStatement.activation.setParameters(getParms(), preparedStatement.getParameterTypes());
1623        } catch (StandardException se) {
1624            throw EmbedResultSet.noStateChangeException(se);
1625        }
1626    }
1627
1628    boolean executeStatement(Activation a,
1629                     boolean executeQuery, boolean executeUpdate)
1630                     throws SQLException JavaDoc {
1631
1632        checkExecStatus();
1633        checkIfInMiddleOfBatch();
1634        clearResultSets();
1635        return super.executeStatement(a, executeQuery, executeUpdate);
1636    }
1637
1638    final SQLException JavaDoc dataTypeConversion(int column, String JavaDoc sourceType)
1639        throws SQLException JavaDoc {
1640        SQLException JavaDoc se = newSQLException(SQLState.LANG_DATA_TYPE_GET_MISMATCH, getEmbedParameterSetMetaData().getParameterTypeName(column),
1641            sourceType);
1642        return se;
1643    }
1644        /*
1645         * This method is used to initialize the BrokeredConnectionControl
1646         * variable with its implementation. This method will be called in the
1647         * BrokeredConnectionControl class
1648         *
1649         * @param control used to call the onStatementClose and
1650         * onStatementErrorOccurred methods that have logic to
1651         * raise StatementEvents for the close and error events
1652         * on the PreparedStatement
1653         *
1654         */

1655        public void setBrokeredConnectionControl(BrokeredConnectionControl control) {
1656            bcc = control;
1657        }
1658        
1659        /*
1660         * Method calls onStatementError occurred on the
1661         * BrokeredConnectionControl class after checking the
1662         * SQLState of the SQLException thrown.
1663         *
1664         * In the case that a XAConnection is involved in the creation of this
1665         * PreparedStatement for e.g in the following case
1666         *
1667         * <code>
1668         * XAConnection xaconn = xadatasource.getXAConnection();//where xadatasource is an object of XADataSource
1669         * Connection conn = xaconnection.getConnection();
1670         * PreparedStatement ps = conn.preparedStatement("values 1");
1671         * </code>
1672         *
1673         * In the above case the PreparedStatement will actually be a
1674         * BrokeredPreparedStatement40 object. Hence when we call
1675         * bcc.onStatementClose and pass the PreparedStatement that caused it
1676         * applicationStatement will be the appropriate choice since it will
1677         * contain the appropriate instance of PreparedStatement in each case
1678         *
1679         */

1680        
1681        private void checkStatementValidity(SQLException JavaDoc sqle) throws SQLException JavaDoc {
1682            /*
1683             * Check if the exception has occurred because the connection
1684             * associated with the PreparedStatement has been closed
1685             */

1686            if(bcc != null && isClosed()) {
1687                //call the BrokeredConnectionControl interface method
1688
//onStatementErrorOccurred
1689
bcc.onStatementErrorOccurred((java.sql.PreparedStatement JavaDoc)
1690                                                applicationStatement,sqle);
1691            }
1692            throw sqle;
1693        }
1694
1695    /**
1696     * Checks whether a data type is supported for
1697     * <code>setObject(int, Object, int)</code> and
1698     * <code>setObject(int, Object, int, int)</code>.
1699     *
1700     * @param dataType the data type to check
1701     * @exception SQLException if the type is not supported
1702     */

1703    private void checkForSupportedDataType(int dataType) throws SQLException JavaDoc {
1704
1705        // JDBC 4.0 javadoc for setObject() says:
1706
//
1707
// Throws: (...) SQLFeatureNotSupportedException - if
1708
// targetSqlType is a ARRAY, BLOB, CLOB, DATALINK,
1709
// JAVA_OBJECT, NCHAR, NCLOB, NVARCHAR, LONGNVARCHAR, REF,
1710
// ROWID, SQLXML or STRUCT data type and the JDBC driver does
1711
// not support this data type
1712
//
1713
// Of these types, we only support BLOB, CLOB and
1714
// (sort of) JAVA_OBJECT.
1715

1716        switch (dataType) {
1717        case Types.ARRAY:
1718        case JDBC30Translation.DATALINK:
1719        case JDBC40Translation.NCHAR:
1720        case JDBC40Translation.NCLOB:
1721        case JDBC40Translation.NVARCHAR:
1722        case JDBC40Translation.LONGNVARCHAR:
1723        case Types.REF:
1724        case JDBC40Translation.ROWID:
1725        case JDBC40Translation.SQLXML:
1726        case Types.STRUCT:
1727            throw newSQLException(SQLState.DATA_TYPE_NOT_SUPPORTED,
1728                                  Util.typeName(dataType));
1729        }
1730    }
1731
1732   //jdbc 4.0 methods
1733

1734    /**
1735     * Sets the designated parameter to the given input stream.
1736     * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
1737     * parameter, it may be more practical to send it via a
1738     * <code>java.io.InputStream</code>. Data will be read from the stream as
1739     * needed until end-of-file is reached. The JDBC driver will do any
1740     * necessary conversion from ASCII to the database char format.
1741     *
1742     * <em>Note:</em> This stream object can either be a standard Java stream
1743     * object or your own subclass that implements the standard interface.
1744     *
1745     * @param parameterIndex the first parameter is 1, the second is 2, ...
1746     * @param x the Java input stream that contains the ASCII parameter value
1747     * @throws SQLException if a database access error occurs or this method is
1748     * called on a closed <code>PreparedStatement</code>
1749     */

1750    public void setAsciiStream(int parameterIndex, InputStream JavaDoc x)
1751            throws SQLException JavaDoc {
1752        checkAsciiStreamConditions(parameterIndex);
1753        java.io.Reader JavaDoc asciiStream = null;
1754
1755        if (x != null) {
1756            // Use ISO-8859-1 and not US-ASCII as JDBC seems to define
1757
// ASCII as 8 bits. US-ASCII is 7.
1758
try {
1759                asciiStream = new java.io.InputStreamReader JavaDoc(x, "ISO-8859-1");
1760            } catch (java.io.UnsupportedEncodingException JavaDoc uee) {
1761                throw new SQLException JavaDoc(uee.getMessage());
1762            }
1763        }
1764
1765        setCharacterStreamInternal(parameterIndex, asciiStream, true, -1);
1766    }
1767
1768    /**
1769     * Sets the designated parameter to the given <code>Reader</code> object.
1770     * When a very large UNICODE value is input to a LONGVARCHAR parameter, it
1771     * may be more practical to send it via a <code>java.io.Reader</code>
1772     * object. The data will be read from the stream as needed until
1773     * end-of-file is reached. The JDBC driver will do any necessary conversion
1774     * from UNICODE to the database char format.
1775     *
1776     * <em>Note:</em> This stream object can either be a standard Java stream
1777     * object or your own subclass that implements the standard interface.
1778     *
1779     * Using this lengthless overload is not less effective than using one
1780     * where the stream length is specified, but since there is no length
1781     * specified, the exact length check will not be performed.
1782     *
1783     * @param parameterIndex the first parameter is 1, the second is 2, ...
1784     * @param reader the <code>java.io.Reader</code> object that contains the
1785     * Unicode data
1786     * @throws SQLException if a database access error occurs or this method is
1787     * called on a closed <code>PreparedStatement</code>
1788     */

1789    public void setCharacterStream(int parameterIndex, Reader reader)
1790            throws SQLException JavaDoc {
1791        checkCharacterStreamConditions(parameterIndex);
1792        setCharacterStreamInternal(parameterIndex, reader,
1793                                   true, -1);
1794    }
1795
1796    /**
1797     * Sets the designated parameter to a <code>Reader</code> object.
1798     * This method differs from the <code>setCharacterStream(int,Reader)</code>
1799     * method because it informs the driver that the parameter value should be
1800     * sent to the server as a <code>CLOB</code>. When the
1801     * <code>setCharacterStream</code> method is used, the driver may have to
1802     * do extra work to determine whether the parameter data should be sent to
1803     * the server as a <code>LONGVARCHAR</code> or a <code>CLOB</code>.
1804     *
1805     * @param parameterIndex index of the first parameter is 1, the second is
1806     * 2, ...
1807     * @param reader an object that contains the data to set the parameter
1808     * value to.
1809     * @throws SQLException if a database access error occurs, this method is
1810     * called on a closed PreparedStatementor if parameterIndex does not
1811     * correspond to a parameter marker in the SQL statement
1812     */

1813    public void setClob(int parameterIndex, Reader reader)
1814            throws SQLException JavaDoc {
1815        checkClobConditions(parameterIndex);
1816        setCharacterStreamInternal(parameterIndex, reader, true, -1);
1817    }
1818
1819    /**
1820     * Sets the designated parameter to a Reader object.
1821     *
1822     * @param parameterIndex index of the first parameter is 1, the second is 2, ...
1823     * @param reader An object that contains the data to set the parameter value to.
1824     * @param length the number of characters in the parameter data.
1825     * @throws SQLException if parameterIndex does not correspond to a parameter
1826     * marker in the SQL statement, or if the length specified is less than zero.
1827     *
1828     */

1829
1830    
1831    public void setClob(int parameterIndex, Reader reader, long length)
1832    throws SQLException JavaDoc{
1833        checkClobConditions(parameterIndex);
1834        setCharacterStreamInternal(parameterIndex, reader, false, length);
1835    }
1836
1837    /**
1838     * Sets the designated parameter to a <code>InputStream</code> object.
1839     * This method differs from the <code>setBinaryStream(int, InputStream)
1840     * </code> method because it informs the driver that the parameter value
1841     * should be sent to the server as a <code>BLOB</code>. When the
1842     * <code>setBinaryStream</code> method is used, the driver may have to do
1843     * extra work to determine whether the parameter data should be sent to the
1844     * server as a <code>LONGVARBINARY</code> or a <code>BLOB</code>
1845     *
1846     * @param parameterIndex index of the first parameter is 1, the second is
1847     * 2, ...
1848     * @param inputStream an object that contains the data to set the parameter
1849     * value to.
1850     * @throws SQLException if a database access error occurs, this method is
1851     * called on a closed <code>PreparedStatement</code> or if
1852     * <code>parameterIndex</code> does not correspond to a parameter
1853     * marker in the SQL statement
1854     */

1855    public void setBlob(int parameterIndex, InputStream JavaDoc inputStream)
1856            throws SQLException JavaDoc {
1857        checkBlobConditions(parameterIndex);
1858        setBinaryStreamInternal(parameterIndex, inputStream, true, -1);
1859    }
1860
1861    /**
1862     * Sets the designated parameter to a InputStream object.
1863     *
1864     * @param parameterIndex index of the first parameter is 1,
1865     * the second is 2, ...
1866     * @param inputStream An object that contains the data to set the parameter
1867     * value to.
1868     * @param length the number of bytes in the parameter data.
1869     * @throws SQLException if parameterIndex does not correspond
1870     * to a parameter marker in the SQL statement, if the length specified
1871     * is less than zero or if the number of bytes in the inputstream does not match
1872     * the specfied length.
1873     */

1874
1875    
1876    public void setBlob(int parameterIndex, InputStream JavaDoc inputStream, long length)
1877    throws SQLException JavaDoc{
1878        checkBlobConditions(parameterIndex);
1879        setBinaryStreamInternal(parameterIndex, inputStream, false, length);
1880    }
1881
1882    /**
1883     * Check general (pre)conditions for setBlob methods.
1884     *
1885     * @param parameterIndex 1-based index of the parameter.
1886     */

1887    private final void checkBlobConditions(int parameterIndex)
1888            throws SQLException JavaDoc {
1889        checkStatus();
1890        if (getParameterJDBCType(parameterIndex) != Types.BLOB) {
1891            throw dataTypeConversion(parameterIndex, "java.sql.Blob");
1892        }
1893    }
1894}
1895
Popular Tags