KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > h2 > jdbc > JdbcConnection


1 /*
2  * Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
3  * Initial Developer: H2 Group
4  */

5 package org.h2.jdbc;
6
7 import java.io.InputStream JavaDoc;
8 import java.io.Reader JavaDoc;
9 import java.sql.Blob JavaDoc;
10 import java.sql.CallableStatement JavaDoc;
11 import java.sql.Clob JavaDoc;
12 import java.sql.Connection JavaDoc;
13 import java.sql.DatabaseMetaData JavaDoc;
14 import java.sql.PreparedStatement JavaDoc;
15 import java.sql.ResultSet JavaDoc;
16 import java.sql.SQLException JavaDoc;
17 import java.sql.SQLWarning JavaDoc;
18 //#ifdef JDK14
19
import java.sql.Savepoint JavaDoc;
20 //#endif
21
import java.sql.Statement JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.Map JavaDoc;
24 import java.util.Properties JavaDoc;
25
26 import org.h2.command.CommandInterface;
27 import org.h2.engine.ConnectionInfo;
28 import org.h2.engine.Constants;
29 import org.h2.engine.SessionInterface;
30 import org.h2.engine.SessionRemote;
31 import org.h2.expression.ParameterInterface;
32 import org.h2.jdbcx.JdbcConnectionListener;
33 import org.h2.message.Message;
34 import org.h2.message.Trace;
35 import org.h2.message.TraceObject;
36 import org.h2.result.ResultInterface;
37 import org.h2.util.TempFileDeleter;
38 import org.h2.value.Value;
39 import org.h2.value.ValueInt;
40 import org.h2.value.ValueLob;
41 import org.h2.value.ValueNull;
42
43 //#ifdef JDK16
44
/*
45 import java.sql.Array;
46 import java.sql.NClob;
47 import java.sql.Struct;
48 import java.sql.SQLXML;
49 import java.sql.SQLClientInfoException;
50 */

51 //#endif
52

53 /**
54  * Represents a connection (session) to a database.
55  */

56 public class JdbcConnection extends TraceObject implements Connection JavaDoc {
57     // TODO test: check if enough sychronization on jdbc objects
58
// TODO feature auto-reconnect on lost connection!
59

60     private String JavaDoc url;
61     private String JavaDoc user;
62     
63     private int holdability
64 //#ifdef JDK14
65
= ResultSet.HOLD_CURSORS_OVER_COMMIT
66 //#endif
67
;
68     
69     private SessionInterface session;
70     private CommandInterface commit, rollback;
71     private CommandInterface setAutoCommitTrue, setAutoCommitFalse, getAutoCommit;
72     private CommandInterface getReadOnly, getGeneratedKeys;
73     private CommandInterface setLockMode, getLockMode;
74     private Exception JavaDoc openStackTrace;
75 //#ifdef JDK14
76
private int savepointId;
77 //#endif
78
private Trace trace;
79     private JdbcConnectionListener listener;
80     private boolean isInternal;
81     private String JavaDoc catalog;
82     private Statement JavaDoc executingStatement;
83
84     /**
85      * Creates a new statement.
86      *
87      * @return the new statement
88      * @throws SQLException
89      * if the connection is closed
90      */

91     public Statement JavaDoc createStatement() throws SQLException JavaDoc {
92         try {
93             int id = getNextId(TraceObject.STATEMENT);
94             if(debug()) {
95                 debugCodeAssign("Statement", TraceObject.STATEMENT, id);
96                 debugCodeCall("createStatement");
97             }
98             checkClosed();
99             return new JdbcStatement(session, this, ResultSet.TYPE_FORWARD_ONLY, id, false);
100         } catch(Throwable JavaDoc e) {
101             throw logAndConvert(e);
102         }
103     }
104
105     /**
106      * Creates a statement with the specified result set type and concurrency.
107      *
108      * @return the statement
109      * @throws SQLException
110      * if the connection is closed or the result set type or
111      * concurrency are not supported
112      */

113     public Statement JavaDoc createStatement(int resultSetType, int resultSetConcurrency) throws SQLException JavaDoc {
114         try {
115             int id = getNextId(TraceObject.STATEMENT);
116             if(debug()) {
117                 debugCodeAssign("Statement", TraceObject.STATEMENT, id);
118                 debugCode("createStatement("+resultSetType+", "+resultSetConcurrency+");");
119             }
120             checkClosed();
121             checkTypeAndConcurrency(resultSetType, resultSetConcurrency);
122             return new JdbcStatement(session, this, resultSetType, id, false);
123         } catch(Throwable JavaDoc e) {
124             throw logAndConvert(e);
125         }
126     }
127
128     /**
129      * Creates a statement with the specified result set type, concurrency, and holdability.
130      *
131      * @return the statement
132      * @throws SQLException
133      * if the connection is closed or the result set type,
134      * concurrency, or holdability are not supported
135      */

136     public Statement JavaDoc createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException JavaDoc {
137         try {
138             int id = getNextId(TraceObject.STATEMENT);
139             if(debug()) {
140                 debugCodeAssign("Statement", TraceObject.STATEMENT, id);
141                 debugCode("createStatement("+resultSetType+", "+resultSetConcurrency+", "+resultSetHoldability+");");
142             }
143             checkClosed();
144             checkTypeAndConcurrency(resultSetType, resultSetConcurrency);
145             checkHoldability(resultSetHoldability);
146             return new JdbcStatement(session, this, resultSetType, id, false);
147         } catch(Throwable JavaDoc e) {
148             throw logAndConvert(e);
149         }
150     }
151
152     /**
153      * Creates a new prepared statement.
154      *
155      * @return the prepared statement
156      * @throws SQLException
157      * if the connection is closed
158      */

159     public PreparedStatement JavaDoc prepareStatement(String JavaDoc sql) throws SQLException JavaDoc {
160         try {
161             int id = getNextId(TraceObject.PREPARED_STATEMENT);
162             if(debug()) {
163                 debugCodeAssign("PreparedStatement", TraceObject.PREPARED_STATEMENT, id);
164                 debugCodeCall("prepareStatement", sql);
165             }
166             checkClosed();
167             sql = translateSQL(sql);
168             return new JdbcPreparedStatement(session, this, sql, ResultSet.TYPE_FORWARD_ONLY, id, false);
169         } catch(Throwable JavaDoc e) {
170             throw logAndConvert(e);
171         }
172     }
173
174     PreparedStatement JavaDoc prepareAutoCloseStatement(String JavaDoc sql) throws SQLException JavaDoc {
175         try {
176             int id = getNextId(TraceObject.PREPARED_STATEMENT);
177             if(debug()) {
178                 debugCodeAssign("PreparedStatement", TraceObject.PREPARED_STATEMENT, id);
179                 debugCodeCall("prepareStatement", sql);
180             }
181             checkClosed();
182             sql = translateSQL(sql);
183             return new JdbcPreparedStatement(session, this, sql, ResultSet.TYPE_FORWARD_ONLY, id, true);
184         } catch(Throwable JavaDoc e) {
185             throw logAndConvert(e);
186         }
187     }
188
189     /**
190      * Gets the database meta data for this database.
191      *
192      * @return the database meta data
193      * @throws SQLException
194      * if the connection is closed
195      */

196     public DatabaseMetaData JavaDoc getMetaData() throws SQLException JavaDoc {
197         try {
198             int id = getNextId(TraceObject.DATABASE_META_DATA);
199             if(debug()) {
200                 debugCodeAssign("DatabaseMetaData", TraceObject.DATABASE_META_DATA, id);
201                 debugCodeCall("getMetaData");
202             }
203             checkClosed();
204             return new JdbcDatabaseMetaData(this, trace, id);
205         } catch(Throwable JavaDoc e) {
206             throw logAndConvert(e);
207         }
208     }
209
210     /**
211      * INTERNAL
212      */

213     public void setJdbcConnectionListener(JdbcConnectionListener listener) {
214         this.listener = listener;
215     }
216
217     /**
218      * Closes this connection. All open statements, prepared statements and
219      * result sets that where created by this connection become invalid after
220      * calling this method. If there is an uncommitted transaction, it will be
221      * rolled back.
222      */

223     public void close() throws SQLException JavaDoc {
224         TempFileDeleter.deleteUnused();
225         synchronized(this) {
226             if(listener == null) {
227                 closeConnection();
228             } else {
229                 listener.closed(this);
230             }
231         }
232     }
233
234     /**
235      * INTERNAL
236      */

237     public void closeConnection() throws SQLException JavaDoc {
238         try {
239             debugCodeCall("close");
240             if(executingStatement != null) {
241                 executingStatement.cancel();
242             }
243             if (session != null && !session.isClosed()) {
244                 try {
245                     rollbackInternal();
246                     commit = closeAndSetNull(commit);
247                     rollback = closeAndSetNull(rollback);
248                     setAutoCommitTrue = closeAndSetNull(setAutoCommitTrue);
249                     setAutoCommitFalse = closeAndSetNull(setAutoCommitFalse);
250                     getAutoCommit = closeAndSetNull(getAutoCommit);
251                     getReadOnly = closeAndSetNull(getReadOnly);
252                     getGeneratedKeys = closeAndSetNull(getGeneratedKeys);
253                     getLockMode = closeAndSetNull(getLockMode);
254                     setLockMode = closeAndSetNull(setLockMode);
255                 } finally {
256                     try {
257                         session.close();
258                     } finally {
259                         session = null;
260                     }
261                 }
262             }
263         } catch(Throwable JavaDoc e) {
264             throw logAndConvert(e);
265         }
266     }
267
268     private CommandInterface closeAndSetNull(CommandInterface command) {
269         if(command != null) {
270             command.close();
271         }
272         return null;
273     }
274
275     /**
276      * Switches autocommit on or off. Calling this function does not commit the
277      * current transaction.
278      *
279      * @param autoCommit
280      * true for autocommit on, false for off
281      * @throws SQLException
282      * if the connection is closed
283      */

284     public synchronized void setAutoCommit(boolean autoCommit) throws SQLException JavaDoc {
285         try {
286             if(debug()) {
287                 debugCode("setAutoCommit("+autoCommit+");");
288             }
289             checkClosed();
290             if (autoCommit) {
291                 setAutoCommitTrue = prepareCommand("SET AUTOCOMMIT TRUE", setAutoCommitTrue);
292                 setAutoCommitTrue.executeUpdate();
293             } else {
294                 setAutoCommitFalse = prepareCommand("SET AUTOCOMMIT FALSE", setAutoCommitFalse);
295                 setAutoCommitFalse.executeUpdate();
296             }
297         } catch(Throwable JavaDoc e) {
298             throw logAndConvert(e);
299         }
300     }
301
302     /**
303      * Gets the current setting for autocommit.
304      *
305      * @return true for on, false for off
306      * @throws SQLException
307      * if the connection is closed
308      */

309     public synchronized boolean getAutoCommit() throws SQLException JavaDoc {
310         debugCodeCall("getAutoCommit");
311         return getInternalAutoCommit();
312     }
313     
314     private boolean getInternalAutoCommit() throws SQLException JavaDoc {
315         try {
316             checkClosed();
317             getAutoCommit = prepareCommand("CALL AUTOCOMMIT()", getAutoCommit);
318             ResultInterface result = getAutoCommit.executeQuery(0, false);
319             result.next();
320             boolean autocommit = result.currentRow()[0].getBoolean().booleanValue();
321             result.close();
322             return autocommit;
323         } catch(Throwable JavaDoc e) {
324             throw logAndConvert(e);
325         }
326     }
327
328     /**
329      * Commits the current transaction. This call has only an effect if
330      * autocommit is switched off.
331      *
332      * @throws SQLException
333      * if the connection is closed
334      */

335     public synchronized void commit() throws SQLException JavaDoc {
336         try {
337             debugCodeCall("commit");
338             checkClosed();
339             commit = prepareCommand("COMMIT", commit);
340             commit.executeUpdate();
341         } catch(Throwable JavaDoc e) {
342             throw logAndConvert(e);
343         }
344     }
345
346     /**
347      * Rolls back the current transaction. This call has only an effect if
348      * autocommit is switched off.
349      *
350      * @throws SQLException
351      * if the connection is closed
352      */

353     public synchronized void rollback() throws SQLException JavaDoc {
354         try {
355             debugCodeCall("rollback");
356             checkClosed();
357             rollbackInternal();
358         } catch(Throwable JavaDoc e) {
359             throw logAndConvert(e);
360         }
361     }
362
363     /**
364      * Returns true if this connection has been closed.
365      *
366      * @return true if close was called
367      */

368     public boolean isClosed() throws SQLException JavaDoc {
369         try {
370             debugCodeCall("isClosed");
371             return session == null || session.isClosed();
372         } catch(Throwable JavaDoc e) {
373             throw logAndConvert(e);
374         }
375     }
376
377
378     /**
379      * Translates a SQL statement into the database grammar.
380      *
381      * @return the translated statement
382      * @throws SQLException
383      * if the connection is closed
384      */

385     public String JavaDoc nativeSQL(String JavaDoc sql) throws SQLException JavaDoc {
386         try {
387             debugCodeCall("nativeSQL", sql);
388             checkClosed();
389             return translateSQL(sql);
390         } catch(Throwable JavaDoc e) {
391             throw logAndConvert(e);
392         }
393     }
394
395     /**
396      * According to the JDBC specs, this
397      * setting is only a hint to the database to enable optimizations - it does
398      * not cause writes to be prohibited.
399      *
400      * @throws SQLException
401      * if the connection is closed
402      */

403     public void setReadOnly(boolean readOnly) throws SQLException JavaDoc {
404         try {
405             if(debug()) {
406                 debugCode("setReadOnly("+readOnly+");");
407             }
408             checkClosed();
409         } catch(Throwable JavaDoc e) {
410             throw logAndConvert(e);
411         }
412     }
413
414     /**
415      * Returns true if the database is read-only.
416      *
417      * @return if the database is read-only
418      * @throws SQLException
419      * if the connection is closed
420      */

421     public boolean isReadOnly() throws SQLException JavaDoc {
422         try {
423             debugCodeCall("isReadOnly");
424             checkClosed();
425             getReadOnly = prepareCommand("CALL READONLY()", getReadOnly);
426             ResultInterface result = getReadOnly.executeQuery(0, false);
427             result.next();
428             boolean readOnly = result.currentRow()[0].getBoolean().booleanValue();
429             return readOnly;
430         } catch(Throwable JavaDoc e) {
431             throw logAndConvert(e);
432         }
433     }
434
435     /**
436      * Set the default catalog name.
437      * This call is ignored.
438      *
439      * @throws SQLException if the connection is closed
440      */

441     public void setCatalog(String JavaDoc catalog) throws SQLException JavaDoc {
442         try {
443             debugCodeCall("setCatalog", catalog);
444             checkClosed();
445         } catch(Throwable JavaDoc e) {
446             throw logAndConvert(e);
447         }
448     }
449
450     /**
451      * Gets the current catalog name.
452      *
453      * @throws SQLException
454      * if the connection is closed
455      */

456     public String JavaDoc getCatalog() throws SQLException JavaDoc {
457         try {
458             debugCodeCall("getCatalog");
459             checkClosed();
460             if(catalog == null) {
461                 CommandInterface cat = prepareCommand("CALL DATABASE()");
462                 ResultInterface result = cat.executeQuery(0, false);
463                 result.next();
464                 catalog = result.currentRow()[0].getString();
465                 cat.close();
466             }
467             return catalog;
468         } catch(Throwable JavaDoc e) {
469             throw logAndConvert(e);
470         }
471     }
472
473     /**
474      * Gets the first warning reported by calls on this object.
475      *
476      * @return null
477      */

478     public SQLWarning JavaDoc getWarnings() throws SQLException JavaDoc {
479         try {
480             debugCodeCall("getWarnings");
481             checkClosed();
482             return null;
483         } catch(Throwable JavaDoc e) {
484             throw logAndConvert(e);
485         }
486     }
487
488     /**
489      * Clears all warnings.
490      */

491     public void clearWarnings() throws SQLException JavaDoc {
492         try {
493             debugCodeCall("clearWarnings");
494             checkClosed();
495         } catch(Throwable JavaDoc e) {
496             throw logAndConvert(e);
497         }
498     }
499
500     /**
501      * Creates a prepared statement with the specified result set type and
502      * concurrency.
503      *
504      * @return the prepared statement
505      * @throws SQLException
506      * if the connection is closed or the result set type or
507      * concurrency are not supported
508      */

509     public PreparedStatement JavaDoc prepareStatement(String JavaDoc sql, int resultSetType, int resultSetConcurrency) throws SQLException JavaDoc {
510         try {
511             int id = getNextId(TraceObject.PREPARED_STATEMENT);
512             if(debug()) {
513                 debugCodeAssign("PreparedStatement", TraceObject.PREPARED_STATEMENT, id);
514                 debugCode("prepareStatement("+quote(sql)+", "+resultSetType+", "+resultSetConcurrency+");");
515             }
516             checkClosed();
517             checkTypeAndConcurrency(resultSetType, resultSetConcurrency);
518             sql = translateSQL(sql);
519             return new JdbcPreparedStatement(session, this, sql, resultSetType, id, false);
520         } catch(Throwable JavaDoc e) {
521             throw logAndConvert(e);
522         }
523     }
524
525     /**
526      * Changes the current transaction isolation level. Calling this method will
527      * commit any open transactions, even if the new level is the same as the
528      * old one, except if the level is not supported.
529      *
530      * @param level the new transaction isolation level,
531      * Connection.TRANSACTION_READ_UNCOMMITTED,
532      * Connection.TRANSACTION_READ_COMMITTED, or
533      * Connection.TRANSACTION_SERIALIZABLE
534      * @throws SQLException if the connection is closed or the isolation level is not supported
535      */

536     public void setTransactionIsolation(int level) throws SQLException JavaDoc {
537         try {
538             debugCodeCall("setTransactionIsolation", level);
539             checkClosed();
540             int lockMode;
541             switch(level) {
542             case Connection.TRANSACTION_READ_UNCOMMITTED:
543                 lockMode = Constants.LOCK_MODE_OFF;
544                 break;
545             case Connection.TRANSACTION_READ_COMMITTED:
546                 lockMode = Constants.LOCK_MODE_READ_COMMITTED;
547                 break;
548             case Connection.TRANSACTION_REPEATABLE_READ:
549             case Connection.TRANSACTION_SERIALIZABLE:
550                 lockMode = Constants.LOCK_MODE_TABLE;
551                 break;
552             default:
553                 throw Message.getInvalidValueException("" + level, "level");
554             }
555             commit();
556             setLockMode = prepareCommand("SET LOCK_MODE ?", setLockMode);
557             ((ParameterInterface)setLockMode.getParameters().get(0)).setValue(ValueInt.get(lockMode));
558             setLockMode.executeUpdate();
559         } catch(Throwable JavaDoc e) {
560             throw logAndConvert(e);
561         }
562     }
563
564     /**
565      * Returns the current transaction isolation level.
566      *
567      * @return the isolation level.
568      * @throws SQLException if the connection is closed
569      */

570     public int getTransactionIsolation() throws SQLException JavaDoc {
571         try {
572             debugCodeCall("getTransactionIsolation");
573             checkClosed();
574             getLockMode = prepareCommand("CALL LOCK_MODE()", getLockMode);
575             ResultInterface result = getLockMode.executeQuery(0, false);
576             result.next();
577             int lockMode = result.currentRow()[0].getInt();
578             result.close();
579             int transactionIsolationLevel;
580             switch(lockMode) {
581             case Constants.LOCK_MODE_OFF:
582                 transactionIsolationLevel = Connection.TRANSACTION_READ_UNCOMMITTED;
583                 break;
584             case Constants.LOCK_MODE_READ_COMMITTED:
585                 transactionIsolationLevel = Connection.TRANSACTION_READ_COMMITTED;
586                 break;
587             case Constants.LOCK_MODE_TABLE:
588             case Constants.LOCK_MODE_TABLE_GC:
589                 transactionIsolationLevel = Connection.TRANSACTION_SERIALIZABLE;
590                 break;
591             default:
592                 throw Message.getInternalError("lockMode:" + lockMode);
593             }
594             return transactionIsolationLevel;
595         } catch(Throwable JavaDoc e) {
596             throw logAndConvert(e);
597         }
598     }
599
600     /**
601      * Changes the current result set holdability.
602      *
603      * @param holdability
604      * ResultSet.HOLD_CURSORS_OVER_COMMIT or
605      * ResultSet.CLOSE_CURSORS_AT_COMMIT;
606      * @throws SQLException
607      * if the connection is closed or the holdability is not
608      * supported
609      */

610     public void setHoldability(int holdability) throws SQLException JavaDoc {
611         try {
612             debugCodeCall("setHoldability", holdability);
613             checkClosed();
614             checkHoldability(holdability);
615             this.holdability = holdability;
616         } catch(Throwable JavaDoc e) {
617             throw logAndConvert(e);
618         }
619     }
620
621     /**
622      * Returns the current result set holdability.
623      *
624      * @return the holdability
625      * @throws SQLException if the connection is closed
626      */

627     public int getHoldability() throws SQLException JavaDoc {
628         try {
629             debugCodeCall("getHoldability");
630             checkClosed();
631             return holdability;
632         } catch(Throwable JavaDoc e) {
633             throw logAndConvert(e);
634         }
635     }
636
637     /**
638      * Gets the type map.
639      *
640      * @return null
641      * @throws SQLException
642      * if the connection is closed
643      */

644     public Map JavaDoc getTypeMap() throws SQLException JavaDoc {
645         try {
646             debugCodeCall("getTypeMap");
647             checkClosed();
648             return null;
649         } catch(Throwable JavaDoc e) {
650             throw logAndConvert(e);
651         }
652     }
653
654     /**
655      * Sets the type map.
656      *
657      * @throws SQLException Unsupported Feature (SQL State 0A000) if the map is not empty
658      */

659     public void setTypeMap(Map JavaDoc map) throws SQLException JavaDoc {
660         try {
661             debugCode("setTypeMap("+quoteMap(map)+");");
662             if(map != null && map.size()>0) {
663                 throw Message.getUnsupportedException();
664             }
665         } catch(Throwable JavaDoc e) {
666             throw logAndConvert(e);
667         }
668     }
669
670     private String JavaDoc quoteMap(Map JavaDoc map) {
671         if(map == null) {
672             return "null";
673         }
674         if(map.size() == 0) {
675             return "new Map()";
676         }
677         StringBuffer JavaDoc buff = new StringBuffer JavaDoc("new Map() /* ");
678         try {
679             // Map<String, Class>
680
for(Iterator JavaDoc it = map.entrySet().iterator(); it.hasNext(); ) {
681                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
682                 String JavaDoc key = (String JavaDoc) entry.getKey();
683                 buff.append(key);
684                 buff.append(':');
685                 Class JavaDoc clazz = (Class JavaDoc) entry.getValue();
686                 buff.append(clazz.getName());
687             }
688         } catch(Exception JavaDoc e) {
689             buff.append(e.toString()+": "+map.toString());
690         }
691         buff.append("*/");
692         return buff.toString();
693     }
694
695     /**
696      * Creates a new callable statement.
697      *
698      * @return the callable statement
699      * @throws SQLException
700      * if the connection is closed or the statement is not valid
701      */

702     public CallableStatement JavaDoc prepareCall(String JavaDoc sql) throws SQLException JavaDoc {
703         try {
704             int id = getNextId(TraceObject.CALLABLE_STATEMENT);
705             if(debug()) {
706                 debugCodeAssign("CallableStatement", TraceObject.CALLABLE_STATEMENT, id);
707                 debugCodeCall("prepareCall", sql);
708             }
709             checkClosed();
710             sql = translateSQL(sql);
711             return new JdbcCallableStatement(session, this, sql, ResultSet.TYPE_FORWARD_ONLY, id);
712         } catch(Throwable JavaDoc e) {
713             throw logAndConvert(e);
714         }
715     }
716
717     /**
718      * Creates a callable statement with the specified result set type and
719      * concurrency.
720      *
721      * @return the callable statement
722      * @throws SQLException
723      * if the connection is closed or the result set type or
724      * concurrency are not supported
725      */

726     public CallableStatement JavaDoc prepareCall(String JavaDoc sql, int resultSetType, int resultSetConcurrency) throws SQLException JavaDoc {
727         try {
728             int id = getNextId(TraceObject.CALLABLE_STATEMENT);
729             if(debug()) {
730                 debugCodeAssign("CallableStatement", TraceObject.CALLABLE_STATEMENT, id);
731                 debugCode("prepareCall("+quote(sql)+", "+resultSetType+", "+resultSetConcurrency+");");
732             }
733             checkClosed();
734             checkTypeAndConcurrency(resultSetType, resultSetConcurrency);
735             sql = translateSQL(sql);
736             return new JdbcCallableStatement(session, this, sql, resultSetType, id);
737         } catch(Throwable JavaDoc e) {
738             throw logAndConvert(e);
739         }
740     }
741
742     /**
743      * Creates a callable statement with the specified result set type,
744      * concurrency, and holdability.
745      *
746      * @return the callable statement
747      * @throws SQLException
748      * if the connection is closed or the result set type,
749      * concurrency, or holdability are not supported
750      */

751     public CallableStatement JavaDoc prepareCall(String JavaDoc sql, int resultSetType,
752             int resultSetConcurrency, int resultSetHoldability) throws SQLException JavaDoc {
753         try {
754             int id = getNextId(TraceObject.CALLABLE_STATEMENT);
755             if(debug()) {
756                 debugCodeAssign("CallableStatement", TraceObject.CALLABLE_STATEMENT, id);
757                 debugCode("prepareCall("+quote(sql)+", "+resultSetType+", "+resultSetConcurrency+", "+resultSetHoldability+");");
758             }
759             checkClosed();
760             checkTypeAndConcurrency(resultSetType, resultSetConcurrency);
761             checkHoldability(resultSetHoldability);
762             sql = translateSQL(sql);
763             return new JdbcCallableStatement(session, this, sql, resultSetType, id);
764         } catch(Throwable JavaDoc e) {
765             throw logAndConvert(e);
766         }
767     }
768
769     /**
770      * Creates a new unnamed savepoint.
771      *
772      * @return the new savepoint
773      */

774     //#ifdef JDK14
775
public Savepoint JavaDoc setSavepoint() throws SQLException JavaDoc {
776         try {
777             int id = getNextId(TraceObject.SAVEPOINT);
778             if(debug()) {
779                 debugCodeAssign("Savepoint", TraceObject.SAVEPOINT, id);
780                 debugCodeCall("setSavepoint");
781             }
782             checkClosed();
783             CommandInterface set = prepareCommand("SAVEPOINT " + JdbcSavepoint.getName(null, savepointId));
784             set.executeUpdate();
785             JdbcSavepoint savepoint = new JdbcSavepoint(this, savepointId, null, trace, id);
786             savepointId++;
787             return savepoint;
788         } catch(Throwable JavaDoc e) {
789             throw logAndConvert(e);
790         }
791     }
792     //#endif
793

794     /**
795      * Creates a new named savepoint.
796      *
797      * @return the new savepoint
798      */

799     //#ifdef JDK14
800
public Savepoint JavaDoc setSavepoint(String JavaDoc name) throws SQLException JavaDoc {
801         try {
802             int id = getNextId(TraceObject.SAVEPOINT);
803             if(debug()) {
804                 debugCodeAssign("Savepoint", TraceObject.SAVEPOINT, id);
805                 debugCodeCall("setSavepoint", name);
806             }
807             checkClosed();
808             CommandInterface set = prepareCommand("SAVEPOINT " + JdbcSavepoint.getName(name, 0));
809             set.executeUpdate();
810             JdbcSavepoint savepoint = new JdbcSavepoint(this, 0, name, trace, id);
811             return savepoint;
812         } catch(Throwable JavaDoc e) {
813             throw logAndConvert(e);
814         }
815     }
816     //#endif
817

818     /**
819      * Rolls back to a savepoint.
820      */

821     //#ifdef JDK14
822
public void rollback(Savepoint JavaDoc savepoint) throws SQLException JavaDoc {
823         try {
824             JdbcSavepoint sp = convertSavepoint(savepoint);
825             debugCode("rollback("+sp.toString()+");");
826             checkClosed();
827             sp.rollback();
828         } catch(Throwable JavaDoc e) {
829             throw logAndConvert(e);
830         }
831     }
832     //#endif
833

834     /**
835      * Releases a savepoint.
836      */

837     //#ifdef JDK14
838
public void releaseSavepoint(Savepoint JavaDoc savepoint) throws SQLException JavaDoc {
839         try {
840             debugCode("releaseSavepoint(savepoint);");
841             checkClosed();
842             convertSavepoint(savepoint).release();
843         } catch(Throwable JavaDoc e) {
844             throw logAndConvert(e);
845         }
846     }
847
848     private JdbcSavepoint convertSavepoint(Savepoint JavaDoc savepoint) throws SQLException JavaDoc {
849         if (!(savepoint instanceof JdbcSavepoint)) {
850             throw Message.getSQLException(Message.SAVEPOINT_IS_INVALID_1, "" + savepoint);
851         }
852         return (JdbcSavepoint) savepoint;
853     }
854     //#endif
855

856     /**
857      * Creates a prepared statement with the specified result set type, concurrency, and holdability.
858      *
859      * @return the prepared statement
860      * @throws SQLException
861      * if the connection is closed or the result set type, concurrency, or holdability are not supported
862      */

863     public PreparedStatement JavaDoc prepareStatement(String JavaDoc sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException JavaDoc {
864         try {
865             int id = getNextId(TraceObject.PREPARED_STATEMENT);
866             if(debug()) {
867                 debugCodeAssign("PreparedStatement", TraceObject.PREPARED_STATEMENT, id);
868                 debugCode("prepareStatement("+quote(sql)+", "+resultSetType+", "+resultSetConcurrency+", " + resultSetHoldability +");");
869             }
870             checkClosed();
871             checkTypeAndConcurrency(resultSetType, resultSetConcurrency);
872             checkHoldability(resultSetHoldability);
873             sql = translateSQL(sql);
874             return new JdbcPreparedStatement(session, this, sql, resultSetType, id, false);
875         } catch(Throwable JavaDoc e) {
876             throw logAndConvert(e);
877         }
878     }
879
880     /**
881      * Creates a new prepared statement. This method just calls
882      * prepareStatement(String sql).
883      *
884      * @return the prepared statement
885      * @throws SQLException
886      * if the connection is closed
887      */

888     public PreparedStatement JavaDoc prepareStatement(String JavaDoc sql, int autoGeneratedKeys) throws SQLException JavaDoc {
889         try {
890             if(debug()) {
891                 debugCode("prepareStatement("+quote(sql)+", "+autoGeneratedKeys+");");
892             }
893             return prepareStatement(sql);
894         } catch(Throwable JavaDoc e) {
895             throw logAndConvert(e);
896         }
897     }
898
899     /**
900      * Creates a new prepared statement. This method just calls
901      * prepareStatement(String sql).
902      *
903      * @return the prepared statement
904      * @throws SQLException
905      * if the connection is closed
906      */

907     public PreparedStatement JavaDoc prepareStatement(String JavaDoc sql, int[] columnIndexes) throws SQLException JavaDoc {
908         try {
909             if(debug()) {
910                 debugCode("prepareStatement("
911                         +quote(sql)+", "
912                         +quoteIntArray(columnIndexes)+");");
913             }
914             return prepareStatement(sql);
915         } catch(Throwable JavaDoc e) {
916             throw logAndConvert(e);
917         }
918     }
919
920     /**
921      * Creates a new prepared statement. This method just calls
922      * prepareStatement(String sql).
923      *
924      * @return the prepared statement
925      * @throws SQLException
926      * if the connection is closed
927      */

928     public PreparedStatement JavaDoc prepareStatement(String JavaDoc sql, String JavaDoc[] columnNames) throws SQLException JavaDoc {
929         try {
930             if(debug()) {
931                 debugCode("prepareStatement("
932                         +quote(sql)+", "
933                         +quoteArray(columnNames)+");");
934             }
935             return prepareStatement(sql);
936         } catch(Throwable JavaDoc e) {
937             throw logAndConvert(e);
938         }
939     }
940
941     // =============================================================
942

943     /**
944      * INTERNAL
945      */

946     public JdbcConnection(String JavaDoc url, Properties JavaDoc info) throws SQLException JavaDoc {
947         try {
948             checkJavaVersion();
949             ConnectionInfo ci = new ConnectionInfo(url, info);
950             if (ci.isRemote()) {
951                 session = new SessionRemote().createSession(ci);
952             } else {
953                 SessionInterface si = (SessionInterface) Class.forName("org.h2.engine.Session").newInstance();
954                 session = si.createSession(ci);
955             }
956             trace = session.getTrace();
957             int id = getNextId(TraceObject.CONNECTION);
958             setTrace(trace, TraceObject.CONNECTION, id);
959             if(info()) {
960                 infoCodeAssign("Connection", TraceObject.CONNECTION, id);
961                 trace.infoCode("DriverManager.getConnection("+quote(url)+", \"<user>\", \"<password>\");");
962             }
963             this.url = ci.getURL();
964             this.user = ci.getUserName();
965             openStackTrace = new Exception JavaDoc("Stack Trace");
966         } catch(Throwable JavaDoc e) {
967             throw logAndConvert(e);
968         }
969     }
970
971     /**
972      * INTERNAL
973      */

974     public JdbcConnection(SessionInterface session, String JavaDoc user, String JavaDoc url) throws SQLException JavaDoc {
975         isInternal = true;
976         this.session = session;
977         trace = session.getTrace();
978         int id = getNextId(TraceObject.CONNECTION);
979         setTrace(trace, TraceObject.CONNECTION, id);
980         this.user = user;
981         this.url = url;
982     }
983
984     private void checkJavaVersion() throws SQLException JavaDoc {
985         try {
986 //#ifdef JDK14
987
// check for existence of this class (avoiding Class . forName)
988
Class JavaDoc clazz = java.sql.Savepoint JavaDoc.class;
989             clazz.getClass();
990 //#endif
991
} catch(Throwable JavaDoc e) {
992             throw Message.getSQLException(Message.UNSUPPORTED_JAVA_VERSION);
993         }
994     }
995
996     CommandInterface prepareCommand(String JavaDoc sql) throws SQLException JavaDoc {
997         return session.prepareCommand(sql);
998     }
999
1000    CommandInterface prepareCommand(String JavaDoc sql, CommandInterface old) throws SQLException JavaDoc {
1001        return old == null ? session.prepareCommand(sql) : old;
1002    }
1003    
1004    private int translateGetEnd(String JavaDoc sql, int i, char c) throws SQLException JavaDoc {
1005        int len = sql.length();
1006        switch(c) {
1007        case '\'': {
1008            int j = sql.indexOf('\'', i + 1);
1009            if (j < 0) {
1010                throw Message.getSyntaxError(sql, i);
1011            }
1012            return j;
1013        }
1014        case '"': {
1015            int j = sql.indexOf('"', i + 1);
1016            if (j < 0) {
1017                throw Message.getSyntaxError(sql, i);
1018            }
1019            return j;
1020        }
1021        case '/': {
1022            checkRunOver(i+1, len, sql);
1023            if (sql.charAt(i + 1) == '*') {
1024                // block comment
1025
int j = sql.indexOf("*/", i + 2);
1026                if (j < 0) {
1027                    throw Message.getSyntaxError(sql, i);
1028                }
1029                i = j + 1;
1030            } else if (sql.charAt(i + 1) == '/') {
1031                // single line comment
1032
i += 2;
1033                while (i < len && (c = sql.charAt(i)) != '\r' && c != '\n') {
1034                    i++;
1035                }
1036            }
1037            return i;
1038        }
1039        case '-': {
1040            checkRunOver(i+1, len, sql);
1041            if (sql.charAt(i + 1) == '-') {
1042                // single line comment
1043
i += 2;
1044                while (i < len && (c = sql.charAt(i)) != '\r' && c != '\n') {
1045                    i++;
1046                }
1047            }
1048            return i;
1049        }
1050        default:
1051            throw Message.getInternalError("c=" + c);
1052        }
1053    }
1054
1055    String JavaDoc translateSQL(String JavaDoc sql) throws SQLException JavaDoc {
1056        if (sql == null || sql.indexOf('{') < 0) {
1057            return sql;
1058        }
1059        int len = sql.length();
1060        char[] chars = null;
1061        int level = 0;
1062        for (int i = 0; i < len; i++) {
1063            char c = sql.charAt(i);
1064            switch (c) {
1065            case '\'':
1066            case '"':
1067            case '/':
1068            case '-':
1069                i = translateGetEnd(sql, i, c);
1070                break;
1071            case '{':
1072                level++;
1073                if (chars == null) {
1074                    chars = sql.toCharArray();
1075                }
1076                chars[i] = ' ';
1077                while (Character.isSpaceChar(chars[i])) {
1078                    i++;
1079                    checkRunOver(i, len, sql);
1080                }
1081                int start = i;
1082                if(chars[i] >= '0' && chars[i] <= '9') {
1083                    chars[i-1]='{';
1084                    while(true) {
1085                        checkRunOver(i, len, sql);
1086                        c = chars[i];
1087                        if(c=='}') {
1088                            break;
1089                        }
1090                        switch(c) {
1091                        case '\'':
1092                        case '"':
1093                        case '/':
1094                        case '-':
1095                            i = translateGetEnd(sql, i, c);
1096                            break;
1097                        }
1098                        i++;
1099                    }
1100                    level--;
1101                    break;
1102                } else if (chars[i] == '?') {
1103                    // TODO nativeSQL: '? = ...' : register out parameter
1104
chars[i++] = ' ';
1105                    checkRunOver(i, len, sql);
1106                    while (Character.isSpaceChar(chars[i])) {
1107                        i++;
1108                        checkRunOver(i, len, sql);
1109                    }
1110                    if (sql.charAt(i) != '=') {
1111                        throw Message.getSyntaxError(sql, i, "=");
1112                    }
1113                    chars[i++] = ' ';
1114                    checkRunOver(i, len, sql);
1115                    while (Character.isSpaceChar(chars[i])) {
1116                        i++;
1117                        checkRunOver(i, len, sql);
1118                    }
1119                }
1120                while (!Character.isSpaceChar(chars[i])) {
1121                    i++;
1122                    checkRunOver(i, len, sql);
1123                }
1124                int repl = 0;
1125                if (found(sql, start, "fn")) {
1126                    repl = 2;
1127                } else if (found(sql, start, "escape")) {
1128                    break;
1129                } else if (found(sql, start, "call")) {
1130                    break;
1131                } else if (found(sql, start, "oj")) {
1132                    repl = 2;
1133                } else if (found(sql, start, "ts")) {
1134                    repl = 2;
1135                } else if (found(sql, start, "t")) {
1136                    repl = 1;
1137                } else if (found(sql, start, "d")) {
1138                    repl = 1;
1139                } else if (found(sql, start, "params")) {
1140                    repl = 1;
1141                }
1142                for (i = start; repl > 0; i++, repl--) {
1143                    chars[i] = ' ';
1144                }
1145                break;
1146            case '}':
1147                if (--level < 0) {
1148                    throw Message.getSyntaxError(sql, i);
1149                }
1150                chars[i] = ' ';
1151                break;
1152            }
1153        }
1154        if (level != 0) {
1155            throw Message.getSyntaxError(sql, sql.length() - 1);
1156        }
1157        if (chars != null) {
1158            sql = new String JavaDoc(chars);
1159        }
1160        return sql;
1161    }
1162
1163    private void checkRunOver(int i, int len, String JavaDoc sql) throws SQLException JavaDoc {
1164        if(i >= len) {
1165            throw Message.getSyntaxError(sql, i);
1166        }
1167    }
1168
1169    private boolean found(String JavaDoc sql, int start, String JavaDoc other) {
1170        return sql.regionMatches(true, start, other, 0, other.length());
1171    }
1172
1173    private void checkTypeAndConcurrency(int resultSetType, int resultSetConcurrency) throws SQLException JavaDoc {
1174        // TODO compatibility / correctness: OpenOffice uses TYPE_SCROLL_SENSITIVE
1175
// if (resultSetType == ResultSet.TYPE_SCROLL_SENSITIVE) {
1176
// throw Message.getInvalidValueException("" + resultSetType, "resultSetType");
1177
// }
1178
// if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY) {
1179
// throw Message.getInvalidValueException("" + resultSetConcurrency, "resultSetConcurrency");
1180
// }
1181
}
1182
1183    private void checkHoldability(int resultSetHoldability) throws SQLException JavaDoc {
1184        // TODO compatibility / correctness: DBPool uses ResultSet.HOLD_CURSORS_OVER_COMMIT
1185
//#ifdef JDK14
1186
if(resultSetHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT &&
1187                resultSetHoldability != ResultSet.CLOSE_CURSORS_AT_COMMIT) {
1188            throw Message.getInvalidValueException("" + resultSetHoldability, "resultSetHoldability");
1189        }
1190//#endif
1191
}
1192
1193    void checkClosed() throws SQLException JavaDoc {
1194        if (session == null) {
1195            throw Message.getSQLException(Message.OBJECT_CLOSED);
1196        }
1197        if(session.isClosed()) {
1198            throw Message.getSQLException(Message.DATABASE_CALLED_AT_SHUTDOWN);
1199        }
1200    }
1201
1202    String JavaDoc getURL() throws SQLException JavaDoc {
1203        checkClosed();
1204        return url;
1205    }
1206
1207    String JavaDoc getUser() throws SQLException JavaDoc {
1208        checkClosed();
1209        return user;
1210    }
1211
1212    protected void finalize() {
1213        if(!Constants.RUN_FINALIZERS) {
1214            return;
1215        }
1216        if(isInternal) {
1217            return;
1218        }
1219        if (session != null) {
1220            trace.error("Connection not closed", openStackTrace);
1221            try {
1222                close();
1223            } catch (SQLException JavaDoc e) {
1224                trace.debug("finalize", e);
1225            }
1226        }
1227    }
1228
1229    private void rollbackInternal() throws SQLException JavaDoc {
1230        rollback = prepareCommand("ROLLBACK", rollback);
1231        rollback.executeUpdate();
1232    }
1233
1234    /**
1235     * INTERNAL
1236     */

1237    public int getPowerOffCount() {
1238        return (session == null || session.isClosed()) ? 0 : session.getPowerOffCount();
1239    }
1240
1241    /**
1242     * INTERNAL
1243     */

1244    public void setPowerOffCount(int count) throws SQLException JavaDoc {
1245        if(session != null) {
1246            session.setPowerOffCount(count);
1247        }
1248    }
1249
1250    /**
1251     * INTERNAL
1252     */

1253    public void setExecutingStatement(Statement JavaDoc stat) {
1254        executingStatement = stat;
1255    }
1256
1257    ResultSet JavaDoc getGeneratedKeys(JdbcStatement statement) throws SQLException JavaDoc {
1258        checkClosed();
1259        getGeneratedKeys = prepareCommand("CALL IDENTITY()", getGeneratedKeys);
1260        ResultInterface result = getGeneratedKeys.executeQuery(0, false);
1261        int id = getNextId(TraceObject.RESULT_SET);
1262        if(debug()) {
1263            debugCodeAssign("ResultSet", TraceObject.RESULT_SET, id);
1264            debugCodeCall("executeQuery", "CALL IDENTITY()");
1265        }
1266        ResultSet JavaDoc rs = new JdbcResultSet(session, this, statement, result, id, false);
1267        return rs;
1268     }
1269    
1270    /**
1271     * Create a new empty Clob object.
1272     *
1273     * @return the object
1274     */

1275    public Clob JavaDoc createClob() throws SQLException JavaDoc {
1276        try {
1277            int id = getNextId(TraceObject.CLOB);
1278            debugCodeAssign("Clob", TraceObject.CLOB, id);
1279            debugCodeCall("createClob");
1280            checkClosed();
1281            ValueLob v = ValueLob.createSmallLob(Value.CLOB, new byte[0]);
1282            return new JdbcClob(session, this, v, id);
1283        } catch(Throwable JavaDoc e) {
1284            throw logAndConvert(e);
1285        }
1286    }
1287
1288    /**
1289     * Create a new empty Blob object.
1290     *
1291     * @return the object
1292     */

1293    public Blob JavaDoc createBlob() throws SQLException JavaDoc {
1294        try {
1295            int id = getNextId(TraceObject.BLOB);
1296            debugCodeAssign("Blob", TraceObject.BLOB, id);
1297            debugCodeCall("createClob");
1298            checkClosed();
1299            ValueLob v = ValueLob.createSmallLob(Value.BLOB, new byte[0]);
1300            return new JdbcBlob(session, this, v, id);
1301        } catch(Throwable JavaDoc e) {
1302            throw logAndConvert(e);
1303        }
1304    }
1305
1306    /**
1307     * Create a new empty NClob object.
1308     *
1309     * @return the object
1310     */

1311    //#ifdef JDK16
1312
/*
1313    public NClob createNClob() throws SQLException {
1314        try {
1315            int id = getNextId(TraceObject.CLOB);
1316            debugCodeAssign("NClob", TraceObject.CLOB, id);
1317            debugCodeCall("createNClob");
1318            checkClosed();
1319            ValueLob v = ValueLob.createSmallLob(Value.CLOB, new byte[0]);
1320            return new JdbcClob(session, this, v, id);
1321        } catch(Throwable e) {
1322            throw logAndConvert(e);
1323        }
1324    }
1325*/

1326    //#endif
1327

1328    /**
1329     * Create a new empty SQLXML object.
1330     * @throws SQLException Unsupported Feature (SQL State 0A000)
1331     */

1332    //#ifdef JDK16
1333
/*
1334    public SQLXML createSQLXML() throws SQLException {
1335        throw Message.getUnsupportedException();
1336    }
1337*/

1338    //#endif
1339

1340    /**
1341     * Create a new empty Array object.
1342     * @throws SQLException Unsupported Feature (SQL State 0A000)
1343     */

1344    //#ifdef JDK16
1345
/*
1346    public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
1347        throw Message.getUnsupportedException();
1348    }
1349*/

1350    //#endif
1351

1352    /**
1353     * Create a new empty Struct object.
1354     * @throws SQLException Unsupported Feature (SQL State 0A000)
1355     */

1356    //#ifdef JDK16
1357
/*
1358    public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
1359        throw Message.getUnsupportedException();
1360    }
1361*/

1362    //#endif
1363

1364    /**
1365     * Returns true if this connection is still valid.
1366     *
1367     * @return true if the connection is valid.
1368     */

1369    public synchronized boolean isValid(int timeout) {
1370        try {
1371            debugCodeCall("isValid", timeout);
1372            checkClosed();
1373            getInternalAutoCommit();
1374            return true;
1375        } catch(Throwable JavaDoc e) {
1376            // this method doesn't throw an exception, but it logs it
1377
logAndConvert(e);
1378            return false;
1379        }
1380    }
1381
1382    /**
1383     * Set a client property.
1384     * @throws SQLException Unsupported Feature (SQL State 0A000)
1385     */

1386    //#ifdef JDK16
1387
/*
1388    public void setClientInfo(String name, String value) throws SQLClientInfoException {
1389        throw new SQLClientInfoException();
1390    }
1391*/

1392    //#endif
1393

1394    /**
1395     * Set the client properties.
1396     * @throws SQLException Unsupported Feature (SQL State 0A000)
1397     */

1398    //#ifdef JDK16
1399
/*
1400    public void setClientInfo(Properties properties) throws SQLClientInfoException {
1401        throw new SQLClientInfoException();
1402    }
1403*/

1404    //#endif
1405

1406    /**
1407     * Get the client properties.
1408     * @throws SQLException Unsupported Feature (SQL State 0A000)
1409     */

1410    //#ifdef JDK16
1411
/*
1412    public Properties getClientInfo() throws SQLClientInfoException {
1413        throw new SQLClientInfoException();
1414    }
1415*/

1416    //#endif
1417

1418    /**
1419     * Set a client property.
1420     * @throws SQLException Unsupported Feature (SQL State 0A000)
1421     */

1422    public String JavaDoc getClientInfo(String JavaDoc name) throws SQLException JavaDoc {
1423        throw Message.getUnsupportedException();
1424    }
1425
1426    /**
1427     * Return an object of this class if possible.
1428     * @throws SQLException Unsupported Feature (SQL State 0A000)
1429     */

1430    //#ifdef JDK16
1431
/*
1432    public <T> T unwrap(Class<T> iface) throws SQLException {
1433        throw Message.getUnsupportedException();
1434    }
1435*/

1436    //#endif
1437

1438    /**
1439     * Checks if unwrap can return an object of this class.
1440     * @throws SQLException Unsupported Feature (SQL State 0A000)
1441     */

1442    //#ifdef JDK16
1443
/*
1444    public boolean isWrapperFor(Class<?> iface) throws SQLException {
1445        throw Message.getUnsupportedException();
1446    }
1447*/

1448    //#endif
1449

1450    Value createClob(Reader JavaDoc x, long length) throws SQLException JavaDoc {
1451        if(x == null) {
1452            return ValueNull.INSTANCE;
1453        }
1454        if(length <= 0) {
1455            length = -1;
1456        }
1457        Value v = ValueLob.createClob(x, length, session.getDataHandler());
1458        return v;
1459    }
1460
1461    Value createBlob(InputStream JavaDoc x, long length) throws SQLException JavaDoc {
1462        if(x == null) {
1463            return ValueNull.INSTANCE;
1464        }
1465        if(length <= 0) {
1466            length = -1;
1467        }
1468        Value v = ValueLob.createBlob(x, length, session.getDataHandler());
1469        return v;
1470    }
1471    
1472}
1473
Popular Tags