0001: /*
0002: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
0003: * (http://h2database.com/html/license.html).
0004: * Initial Developer: H2 Group
0005: */
0006: package org.h2.jdbc;
0007:
0008: import java.io.InputStream;
0009: import java.io.Reader;
0010: import java.sql.Blob;
0011: import java.sql.CallableStatement;
0012: import java.sql.Clob;
0013: import java.sql.Connection;
0014: import java.sql.DatabaseMetaData;
0015: import java.sql.PreparedStatement;
0016: import java.sql.ResultSet;
0017: import java.sql.SQLException;
0018: import java.sql.SQLWarning;
0019: import java.sql.Savepoint;
0020: import java.sql.Statement;
0021: import java.util.Map;
0022: import java.util.Properties;
0023:
0024: import org.h2.command.CommandInterface;
0025: import org.h2.constant.ErrorCode;
0026: import org.h2.constant.SysProperties;
0027: import org.h2.engine.ConnectionInfo;
0028: import org.h2.engine.Constants;
0029: import org.h2.engine.SessionInterface;
0030: import org.h2.engine.SessionRemote;
0031: import org.h2.expression.ParameterInterface;
0032: import org.h2.message.Message;
0033: import org.h2.message.Trace;
0034: import org.h2.message.TraceObject;
0035: import org.h2.result.ResultInterface;
0036: import org.h2.util.ClassUtils;
0037: import org.h2.util.JdbcConnectionListener;
0038: import org.h2.value.Value;
0039: import org.h2.value.ValueInt;
0040: import org.h2.value.ValueLob;
0041: import org.h2.value.ValueNull;
0042: import org.h2.value.ValueString;
0043:
0044: //#ifdef JDK16
0045: /*
0046: import java.sql.Array;
0047: import java.sql.NClob;
0048: import java.sql.Struct;
0049: import java.sql.SQLXML;
0050: import java.sql.SQLClientInfoException;
0051: */
0052: //#endif
0053: /**
0054: * Represents a connection (session) to a database.
0055: */
0056: public class JdbcConnection extends TraceObject implements Connection {
0057: // TODO test: check if enough synchronization on jdbc objects
0058: // TODO feature: auto-reconnect on lost connection
0059:
0060: private String url;
0061: private String user;
0062:
0063: private int holdability = 1; // ResultSet.HOLD_CURSORS_OVER_COMMIT
0064:
0065: private SessionInterface session;
0066: private CommandInterface commit, rollback;
0067: private CommandInterface setAutoCommitTrue, setAutoCommitFalse,
0068: getAutoCommit;
0069: private CommandInterface getReadOnly, getGeneratedKeys;
0070: private CommandInterface setLockMode, getLockMode;
0071: private CommandInterface setQueryTimeout, getQueryTimeout;
0072: private Exception openStackTrace;
0073: //#ifdef JDK14
0074: private int savepointId;
0075: //#endif
0076: private Trace trace;
0077: private JdbcConnectionListener listener;
0078: private boolean isInternal;
0079: private String catalog;
0080: private Statement executingStatement;
0081:
0082: /**
0083: * Creates a new statement.
0084: *
0085: * @return the new statement
0086: * @throws SQLException if the connection is closed
0087: */
0088: public Statement createStatement() throws SQLException {
0089: try {
0090: int id = getNextId(TraceObject.STATEMENT);
0091: if (debug()) {
0092: debugCodeAssign("Statement", TraceObject.STATEMENT, id,
0093: "createStatement()");
0094: }
0095: checkClosed();
0096: return new JdbcStatement(session, this ,
0097: ResultSet.TYPE_FORWARD_ONLY, id, false);
0098: } catch (Throwable e) {
0099: throw logAndConvert(e);
0100: }
0101: }
0102:
0103: /**
0104: * Creates a statement with the specified result set type and concurrency.
0105: *
0106: * @return the statement
0107: * @throws SQLException
0108: * if the connection is closed or the result set type or
0109: * concurrency are not supported
0110: */
0111: public Statement createStatement(int resultSetType,
0112: int resultSetConcurrency) throws SQLException {
0113: try {
0114: int id = getNextId(TraceObject.STATEMENT);
0115: if (debug()) {
0116: debugCodeAssign("Statement", TraceObject.STATEMENT, id,
0117: "createStatement(" + resultSetType + ", "
0118: + resultSetConcurrency + ")");
0119: }
0120: checkClosed();
0121: checkTypeAndConcurrency(resultSetType, resultSetConcurrency);
0122: return new JdbcStatement(session, this , resultSetType, id,
0123: false);
0124: } catch (Throwable e) {
0125: throw logAndConvert(e);
0126: }
0127: }
0128:
0129: /**
0130: * Creates a statement with the specified result set type, concurrency, and
0131: * holdability.
0132: *
0133: * @return the statement
0134: * @throws SQLException if the connection is closed or the result set type,
0135: * concurrency, or holdability are not supported
0136: */
0137: public Statement createStatement(int resultSetType,
0138: int resultSetConcurrency, int resultSetHoldability)
0139: throws SQLException {
0140: try {
0141: int id = getNextId(TraceObject.STATEMENT);
0142: if (debug()) {
0143: debugCodeAssign("Statement", TraceObject.STATEMENT, id,
0144: "createStatement(" + resultSetType + ", "
0145: + resultSetConcurrency + ", "
0146: + resultSetHoldability + ")");
0147: }
0148: checkClosed();
0149: checkTypeAndConcurrency(resultSetType, resultSetConcurrency);
0150: checkHoldability(resultSetHoldability);
0151: return new JdbcStatement(session, this , resultSetType, id,
0152: false);
0153: } catch (Throwable e) {
0154: throw logAndConvert(e);
0155: }
0156: }
0157:
0158: /**
0159: * Creates a new prepared statement.
0160: *
0161: * @return the prepared statement
0162: * @throws SQLException
0163: * if the connection is closed
0164: */
0165: public PreparedStatement prepareStatement(String sql)
0166: throws SQLException {
0167: try {
0168: int id = getNextId(TraceObject.PREPARED_STATEMENT);
0169: if (debug()) {
0170: debugCodeAssign("PreparedStatement",
0171: TraceObject.PREPARED_STATEMENT, id,
0172: "prepareStatement(" + quote(sql) + ")");
0173: }
0174: checkClosed();
0175: sql = translateSQL(sql);
0176: return new JdbcPreparedStatement(session, this , sql,
0177: ResultSet.TYPE_FORWARD_ONLY, id, false);
0178: } catch (Throwable e) {
0179: throw logAndConvert(e);
0180: }
0181: }
0182:
0183: PreparedStatement prepareAutoCloseStatement(String sql)
0184: throws SQLException {
0185: try {
0186: int id = getNextId(TraceObject.PREPARED_STATEMENT);
0187: if (debug()) {
0188: debugCodeAssign("PreparedStatement",
0189: TraceObject.PREPARED_STATEMENT, id,
0190: "prepareStatement(" + quote(sql) + ")");
0191: }
0192: checkClosed();
0193: sql = translateSQL(sql);
0194: return new JdbcPreparedStatement(session, this , sql,
0195: ResultSet.TYPE_FORWARD_ONLY, id, true);
0196: } catch (Throwable e) {
0197: throw logAndConvert(e);
0198: }
0199: }
0200:
0201: /**
0202: * Gets the database meta data for this database.
0203: *
0204: * @return the database meta data
0205: * @throws SQLException
0206: * if the connection is closed
0207: */
0208: public DatabaseMetaData getMetaData() throws SQLException {
0209: try {
0210: int id = getNextId(TraceObject.DATABASE_META_DATA);
0211: if (debug()) {
0212: debugCodeAssign("DatabaseMetaData",
0213: TraceObject.DATABASE_META_DATA, id,
0214: "getMetaData()");
0215: }
0216: checkClosed();
0217: return new JdbcDatabaseMetaData(this , trace, id);
0218: } catch (Throwable e) {
0219: throw logAndConvert(e);
0220: }
0221: }
0222:
0223: /**
0224: * INTERNAL
0225: */
0226: public void setJdbcConnectionListener(
0227: JdbcConnectionListener listener) {
0228: this .listener = listener;
0229: }
0230:
0231: /**
0232: * INTERNAL
0233: */
0234: public SessionInterface getSession() {
0235: return session;
0236: }
0237:
0238: /**
0239: * Closes this connection. All open statements, prepared statements and
0240: * result sets that where created by this connection become invalid after
0241: * calling this method. If there is an uncommitted transaction, it will be
0242: * rolled back.
0243: */
0244: public void close() throws SQLException {
0245: synchronized (this ) {
0246: if (listener == null) {
0247: closeConnection();
0248: } else {
0249: listener.closed(this );
0250: }
0251: }
0252: }
0253:
0254: /**
0255: * INTERNAL
0256: */
0257: public void closeConnection() throws SQLException {
0258: try {
0259: debugCodeCall("close");
0260: if (executingStatement != null) {
0261: executingStatement.cancel();
0262: }
0263: if (session == null) {
0264: return;
0265: }
0266: session.cancel();
0267: synchronized (session) {
0268: try {
0269: if (!session.isClosed()) {
0270: try {
0271: rollbackInternal();
0272: commit = closeAndSetNull(commit);
0273: rollback = closeAndSetNull(rollback);
0274: setAutoCommitTrue = closeAndSetNull(setAutoCommitTrue);
0275: setAutoCommitFalse = closeAndSetNull(setAutoCommitFalse);
0276: getAutoCommit = closeAndSetNull(getAutoCommit);
0277: getReadOnly = closeAndSetNull(getReadOnly);
0278: getGeneratedKeys = closeAndSetNull(getGeneratedKeys);
0279: getLockMode = closeAndSetNull(getLockMode);
0280: setLockMode = closeAndSetNull(setLockMode);
0281: getQueryTimeout = closeAndSetNull(getQueryTimeout);
0282: setQueryTimeout = closeAndSetNull(setQueryTimeout);
0283: } finally {
0284: session.close();
0285: }
0286: }
0287: } finally {
0288: session = null;
0289: }
0290: }
0291: } catch (Throwable e) {
0292: throw logAndConvert(e);
0293: }
0294: }
0295:
0296: private CommandInterface closeAndSetNull(CommandInterface command) {
0297: if (command != null) {
0298: command.close();
0299: }
0300: return null;
0301: }
0302:
0303: /**
0304: * Switches auto commit on or off. Calling this function does not commit the
0305: * current transaction.
0306: *
0307: * @param autoCommit
0308: * true for auto commit on, false for off
0309: * @throws SQLException
0310: * if the connection is closed
0311: */
0312: public synchronized void setAutoCommit(boolean autoCommit)
0313: throws SQLException {
0314: try {
0315: if (debug()) {
0316: debugCode("setAutoCommit(" + autoCommit + ");");
0317: }
0318: checkClosed();
0319: if (autoCommit) {
0320: setAutoCommitTrue = prepareCommand(
0321: "SET AUTOCOMMIT TRUE", setAutoCommitTrue);
0322: setAutoCommitTrue.executeUpdate();
0323: } else {
0324: setAutoCommitFalse = prepareCommand(
0325: "SET AUTOCOMMIT FALSE", setAutoCommitFalse);
0326: setAutoCommitFalse.executeUpdate();
0327: }
0328: } catch (Throwable e) {
0329: throw logAndConvert(e);
0330: }
0331: }
0332:
0333: /**
0334: * Gets the current setting for auto commit.
0335: *
0336: * @return true for on, false for off
0337: * @throws SQLException
0338: * if the connection is closed
0339: */
0340: public synchronized boolean getAutoCommit() throws SQLException {
0341: try {
0342: checkClosed();
0343: debugCodeCall("getAutoCommit");
0344: return getInternalAutoCommit();
0345: } catch (Throwable e) {
0346: throw logAndConvert(e);
0347: }
0348: }
0349:
0350: private boolean getInternalAutoCommit() throws SQLException {
0351: getAutoCommit = prepareCommand("CALL AUTOCOMMIT()",
0352: getAutoCommit);
0353: ResultInterface result = getAutoCommit.executeQuery(0, false);
0354: result.next();
0355: boolean autoCommit = result.currentRow()[0].getBoolean()
0356: .booleanValue();
0357: result.close();
0358: return autoCommit;
0359: }
0360:
0361: /**
0362: * Commits the current transaction. This call has only an effect if
0363: * auto commit is switched off.
0364: *
0365: * @throws SQLException
0366: * if the connection is closed
0367: */
0368: public synchronized void commit() throws SQLException {
0369: try {
0370: debugCodeCall("commit");
0371: checkClosed();
0372: commit = prepareCommand("COMMIT", commit);
0373: commit.executeUpdate();
0374: } catch (Throwable e) {
0375: throw logAndConvert(e);
0376: }
0377: }
0378:
0379: /**
0380: * Rolls back the current transaction. This call has only an effect if
0381: * auto commit is switched off.
0382: *
0383: * @throws SQLException
0384: * if the connection is closed
0385: */
0386: public synchronized void rollback() throws SQLException {
0387: try {
0388: debugCodeCall("rollback");
0389: checkClosed();
0390: rollbackInternal();
0391: } catch (Throwable e) {
0392: throw logAndConvert(e);
0393: }
0394: }
0395:
0396: /**
0397: * Returns true if this connection has been closed.
0398: *
0399: * @return true if close was called
0400: */
0401: public boolean isClosed() throws SQLException {
0402: try {
0403: debugCodeCall("isClosed");
0404: return session == null || session.isClosed();
0405: } catch (Throwable e) {
0406: throw logAndConvert(e);
0407: }
0408: }
0409:
0410: /**
0411: * Translates a SQL statement into the database grammar.
0412: *
0413: * @return the translated statement
0414: * @throws SQLException
0415: * if the connection is closed
0416: */
0417: public String nativeSQL(String sql) throws SQLException {
0418: try {
0419: debugCodeCall("nativeSQL", sql);
0420: checkClosed();
0421: return translateSQL(sql);
0422: } catch (Throwable e) {
0423: throw logAndConvert(e);
0424: }
0425: }
0426:
0427: /**
0428: * According to the JDBC specs, this
0429: * setting is only a hint to the database to enable optimizations - it does
0430: * not cause writes to be prohibited.
0431: *
0432: * @throws SQLException
0433: * if the connection is closed
0434: */
0435: public void setReadOnly(boolean readOnly) throws SQLException {
0436: try {
0437: if (debug()) {
0438: debugCode("setReadOnly(" + readOnly + ");");
0439: }
0440: checkClosed();
0441: } catch (Throwable e) {
0442: throw logAndConvert(e);
0443: }
0444: }
0445:
0446: /**
0447: * Returns true if the database is read-only.
0448: *
0449: * @return if the database is read-only
0450: * @throws SQLException
0451: * if the connection is closed
0452: */
0453: public boolean isReadOnly() throws SQLException {
0454: try {
0455: debugCodeCall("isReadOnly");
0456: checkClosed();
0457: getReadOnly = prepareCommand("CALL READONLY()", getReadOnly);
0458: ResultInterface result = getReadOnly.executeQuery(0, false);
0459: result.next();
0460: boolean readOnly = result.currentRow()[0].getBoolean()
0461: .booleanValue();
0462: return readOnly;
0463: } catch (Throwable e) {
0464: throw logAndConvert(e);
0465: }
0466: }
0467:
0468: /**
0469: * Set the default catalog name.
0470: * This call is ignored.
0471: *
0472: * @throws SQLException if the connection is closed
0473: */
0474: public void setCatalog(String catalog) throws SQLException {
0475: try {
0476: debugCodeCall("setCatalog", catalog);
0477: checkClosed();
0478: } catch (Throwable e) {
0479: throw logAndConvert(e);
0480: }
0481: }
0482:
0483: /**
0484: * Gets the current catalog name.
0485: *
0486: * @throws SQLException
0487: * if the connection is closed
0488: */
0489: public String getCatalog() throws SQLException {
0490: try {
0491: debugCodeCall("getCatalog");
0492: checkClosed();
0493: if (catalog == null) {
0494: CommandInterface cat = prepareCommand(
0495: "CALL DATABASE()", Integer.MAX_VALUE);
0496: ResultInterface result = cat.executeQuery(0, false);
0497: result.next();
0498: catalog = result.currentRow()[0].getString();
0499: cat.close();
0500: }
0501: return catalog;
0502: } catch (Throwable e) {
0503: throw logAndConvert(e);
0504: }
0505: }
0506:
0507: /**
0508: * Gets the first warning reported by calls on this object.
0509: *
0510: * @return null
0511: */
0512: public SQLWarning getWarnings() throws SQLException {
0513: try {
0514: debugCodeCall("getWarnings");
0515: checkClosed();
0516: return null;
0517: } catch (Throwable e) {
0518: throw logAndConvert(e);
0519: }
0520: }
0521:
0522: /**
0523: * Clears all warnings.
0524: */
0525: public void clearWarnings() throws SQLException {
0526: try {
0527: debugCodeCall("clearWarnings");
0528: checkClosed();
0529: } catch (Throwable e) {
0530: throw logAndConvert(e);
0531: }
0532: }
0533:
0534: /**
0535: * Creates a prepared statement with the specified result set type and
0536: * concurrency.
0537: *
0538: * @return the prepared statement
0539: * @throws SQLException
0540: * if the connection is closed or the result set type or
0541: * concurrency are not supported
0542: */
0543: public PreparedStatement prepareStatement(String sql,
0544: int resultSetType, int resultSetConcurrency)
0545: throws SQLException {
0546: try {
0547: int id = getNextId(TraceObject.PREPARED_STATEMENT);
0548: if (debug()) {
0549: debugCodeAssign("PreparedStatement",
0550: TraceObject.PREPARED_STATEMENT, id,
0551: "prepareStatement(" + quote(sql) + ", "
0552: + resultSetType + ", "
0553: + resultSetConcurrency + ")");
0554: }
0555: checkClosed();
0556: checkTypeAndConcurrency(resultSetType, resultSetConcurrency);
0557: sql = translateSQL(sql);
0558: return new JdbcPreparedStatement(session, this , sql,
0559: resultSetType, id, false);
0560: } catch (Throwable e) {
0561: throw logAndConvert(e);
0562: }
0563: }
0564:
0565: /**
0566: * Changes the current transaction isolation level. Calling this method will
0567: * commit an open transaction, even if the new level is the same as the old
0568: * one, except if the level is not supported.
0569: *
0570: * @param level the new transaction isolation level,
0571: * Connection.TRANSACTION_READ_UNCOMMITTED,
0572: * Connection.TRANSACTION_READ_COMMITTED, or
0573: * Connection.TRANSACTION_SERIALIZABLE
0574: * @throws SQLException if the connection is closed or the isolation level
0575: * is not supported
0576: */
0577: public void setTransactionIsolation(int level) throws SQLException {
0578: try {
0579: debugCodeCall("setTransactionIsolation", level);
0580: checkClosed();
0581: int lockMode;
0582: switch (level) {
0583: case Connection.TRANSACTION_READ_UNCOMMITTED:
0584: lockMode = Constants.LOCK_MODE_OFF;
0585: break;
0586: case Connection.TRANSACTION_READ_COMMITTED:
0587: lockMode = Constants.LOCK_MODE_READ_COMMITTED;
0588: break;
0589: case Connection.TRANSACTION_REPEATABLE_READ:
0590: case Connection.TRANSACTION_SERIALIZABLE:
0591: lockMode = Constants.LOCK_MODE_TABLE;
0592: break;
0593: default:
0594: throw Message.getInvalidValueException("" + level,
0595: "level");
0596: }
0597: commit();
0598: setLockMode = prepareCommand("SET LOCK_MODE ?", setLockMode);
0599: ((ParameterInterface) setLockMode.getParameters().get(0))
0600: .setValue(ValueInt.get(lockMode));
0601: setLockMode.executeUpdate();
0602: } catch (Throwable e) {
0603: throw logAndConvert(e);
0604: }
0605: }
0606:
0607: /**
0608: * INTERNAL
0609: */
0610: public void setQueryTimeout(int seconds) throws SQLException {
0611: try {
0612: commit();
0613: setQueryTimeout = prepareCommand("SET QUERY_TIMEOUT ?",
0614: setQueryTimeout);
0615: ((ParameterInterface) setQueryTimeout.getParameters()
0616: .get(0)).setValue(ValueInt.get(seconds * 1000));
0617: setQueryTimeout.executeUpdate();
0618: } catch (Throwable e) {
0619: throw logAndConvert(e);
0620: }
0621: }
0622:
0623: /**
0624: * INTERNAL
0625: */
0626: public int getQueryTimeout() throws SQLException {
0627: try {
0628: getQueryTimeout = prepareCommand(
0629: "SELECT VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE NAME=?",
0630: getQueryTimeout);
0631: ((ParameterInterface) getQueryTimeout.getParameters()
0632: .get(0)).setValue(ValueString.get("QUERY_TIMEOUT"));
0633: ResultInterface result = getQueryTimeout.executeQuery(0,
0634: false);
0635: result.next();
0636: int queryTimeout = result.currentRow()[0].getInt();
0637: result.close();
0638: if (queryTimeout == 0) {
0639: return 0;
0640: } else {
0641: // round to the next second, otherwise 999 millis would return 0 seconds
0642: return (queryTimeout + 999) / 1000;
0643: }
0644: } catch (Throwable e) {
0645: throw logAndConvert(e);
0646: }
0647:
0648: }
0649:
0650: /**
0651: * Returns the current transaction isolation level.
0652: *
0653: * @return the isolation level.
0654: * @throws SQLException if the connection is closed
0655: */
0656: public int getTransactionIsolation() throws SQLException {
0657: try {
0658: debugCodeCall("getTransactionIsolation");
0659: checkClosed();
0660: getLockMode = prepareCommand("CALL LOCK_MODE()",
0661: getLockMode);
0662: ResultInterface result = getLockMode.executeQuery(0, false);
0663: result.next();
0664: int lockMode = result.currentRow()[0].getInt();
0665: result.close();
0666: int transactionIsolationLevel;
0667: switch (lockMode) {
0668: case Constants.LOCK_MODE_OFF:
0669: transactionIsolationLevel = Connection.TRANSACTION_READ_UNCOMMITTED;
0670: break;
0671: case Constants.LOCK_MODE_READ_COMMITTED:
0672: transactionIsolationLevel = Connection.TRANSACTION_READ_COMMITTED;
0673: break;
0674: case Constants.LOCK_MODE_TABLE:
0675: case Constants.LOCK_MODE_TABLE_GC:
0676: transactionIsolationLevel = Connection.TRANSACTION_SERIALIZABLE;
0677: break;
0678: default:
0679: throw Message.getInternalError("lockMode:" + lockMode);
0680: }
0681: return transactionIsolationLevel;
0682: } catch (Throwable e) {
0683: throw logAndConvert(e);
0684: }
0685: }
0686:
0687: /**
0688: * Changes the current result set holdability.
0689: *
0690: * @param holdability
0691: * ResultSet.HOLD_CURSORS_OVER_COMMIT or
0692: * ResultSet.CLOSE_CURSORS_AT_COMMIT;
0693: * @throws SQLException
0694: * if the connection is closed or the holdability is not
0695: * supported
0696: */
0697: public void setHoldability(int holdability) throws SQLException {
0698: try {
0699: debugCodeCall("setHoldability", holdability);
0700: checkClosed();
0701: checkHoldability(holdability);
0702: this .holdability = holdability;
0703: } catch (Throwable e) {
0704: throw logAndConvert(e);
0705: }
0706: }
0707:
0708: /**
0709: * Returns the current result set holdability.
0710: *
0711: * @return the holdability
0712: * @throws SQLException if the connection is closed
0713: */
0714: public int getHoldability() throws SQLException {
0715: try {
0716: debugCodeCall("getHoldability");
0717: checkClosed();
0718: return holdability;
0719: } catch (Throwable e) {
0720: throw logAndConvert(e);
0721: }
0722: }
0723:
0724: /**
0725: * Gets the type map.
0726: *
0727: * @return null
0728: * @throws SQLException
0729: * if the connection is closed
0730: */
0731: public Map getTypeMap() throws SQLException {
0732: try {
0733: debugCodeCall("getTypeMap");
0734: checkClosed();
0735: return null;
0736: } catch (Throwable e) {
0737: throw logAndConvert(e);
0738: }
0739: }
0740:
0741: /**
0742: * [Partially supported] Sets the type map. This is only supported if the
0743: * map is empty or null.
0744: */
0745: public void setTypeMap(Map map) throws SQLException {
0746: try {
0747: debugCode("setTypeMap(" + quoteMap(map) + ");");
0748: checkMap(map);
0749: } catch (Throwable e) {
0750: throw logAndConvert(e);
0751: }
0752: }
0753:
0754: /**
0755: * Creates a new callable statement.
0756: *
0757: * @return the callable statement
0758: * @throws SQLException
0759: * if the connection is closed or the statement is not valid
0760: */
0761: public CallableStatement prepareCall(String sql)
0762: throws SQLException {
0763: try {
0764: int id = getNextId(TraceObject.CALLABLE_STATEMENT);
0765: if (debug()) {
0766: debugCodeAssign("CallableStatement",
0767: TraceObject.CALLABLE_STATEMENT, id,
0768: "prepareCall(" + quote(sql) + ")");
0769: }
0770: checkClosed();
0771: sql = translateSQL(sql);
0772: return new JdbcCallableStatement(session, this , sql,
0773: ResultSet.TYPE_FORWARD_ONLY, id);
0774: } catch (Throwable e) {
0775: throw logAndConvert(e);
0776: }
0777: }
0778:
0779: /**
0780: * Creates a callable statement with the specified result set type and
0781: * concurrency.
0782: *
0783: * @return the callable statement
0784: * @throws SQLException
0785: * if the connection is closed or the result set type or
0786: * concurrency are not supported
0787: */
0788: public CallableStatement prepareCall(String sql, int resultSetType,
0789: int resultSetConcurrency) throws SQLException {
0790: try {
0791: int id = getNextId(TraceObject.CALLABLE_STATEMENT);
0792: if (debug()) {
0793: debugCodeAssign("CallableStatement",
0794: TraceObject.CALLABLE_STATEMENT, id,
0795: "prepareCall(" + quote(sql) + ", "
0796: + resultSetType + ", "
0797: + resultSetConcurrency + ")");
0798: }
0799: checkClosed();
0800: checkTypeAndConcurrency(resultSetType, resultSetConcurrency);
0801: sql = translateSQL(sql);
0802: return new JdbcCallableStatement(session, this , sql,
0803: resultSetType, id);
0804: } catch (Throwable e) {
0805: throw logAndConvert(e);
0806: }
0807: }
0808:
0809: /**
0810: * Creates a callable statement with the specified result set type,
0811: * concurrency, and holdability.
0812: *
0813: * @return the callable statement
0814: * @throws SQLException
0815: * if the connection is closed or the result set type,
0816: * concurrency, or holdability are not supported
0817: */
0818: public CallableStatement prepareCall(String sql, int resultSetType,
0819: int resultSetConcurrency, int resultSetHoldability)
0820: throws SQLException {
0821: try {
0822: int id = getNextId(TraceObject.CALLABLE_STATEMENT);
0823: if (debug()) {
0824: debugCodeAssign("CallableStatement",
0825: TraceObject.CALLABLE_STATEMENT, id,
0826: "prepareCall(" + quote(sql) + ", "
0827: + resultSetType + ", "
0828: + resultSetConcurrency + ", "
0829: + resultSetHoldability + ")");
0830: }
0831: checkClosed();
0832: checkTypeAndConcurrency(resultSetType, resultSetConcurrency);
0833: checkHoldability(resultSetHoldability);
0834: sql = translateSQL(sql);
0835: return new JdbcCallableStatement(session, this , sql,
0836: resultSetType, id);
0837: } catch (Throwable e) {
0838: throw logAndConvert(e);
0839: }
0840: }
0841:
0842: /**
0843: * Creates a new unnamed savepoint.
0844: *
0845: * @return the new savepoint
0846: */
0847: //#ifdef JDK14
0848: public Savepoint setSavepoint() throws SQLException {
0849: try {
0850: int id = getNextId(TraceObject.SAVEPOINT);
0851: if (debug()) {
0852: debugCodeAssign("Savepoint", TraceObject.SAVEPOINT, id,
0853: "setSavepoint()");
0854: }
0855: checkClosed();
0856: CommandInterface set = prepareCommand("SAVEPOINT "
0857: + JdbcSavepoint.getName(null, savepointId),
0858: Integer.MAX_VALUE);
0859: set.executeUpdate();
0860: JdbcSavepoint savepoint = new JdbcSavepoint(this ,
0861: savepointId, null, trace, id);
0862: savepointId++;
0863: return savepoint;
0864: } catch (Throwable e) {
0865: throw logAndConvert(e);
0866: }
0867: }
0868:
0869: //#endif
0870:
0871: /**
0872: * Creates a new named savepoint.
0873: *
0874: * @return the new savepoint
0875: */
0876: //#ifdef JDK14
0877: public Savepoint setSavepoint(String name) throws SQLException {
0878: try {
0879: int id = getNextId(TraceObject.SAVEPOINT);
0880: if (debug()) {
0881: debugCodeAssign("Savepoint", TraceObject.SAVEPOINT, id,
0882: "setSavepoint(" + quote(name) + ")");
0883: }
0884: checkClosed();
0885: CommandInterface set = prepareCommand("SAVEPOINT "
0886: + JdbcSavepoint.getName(name, 0), Integer.MAX_VALUE);
0887: set.executeUpdate();
0888: JdbcSavepoint savepoint = new JdbcSavepoint(this , 0, name,
0889: trace, id);
0890: return savepoint;
0891: } catch (Throwable e) {
0892: throw logAndConvert(e);
0893: }
0894: }
0895:
0896: //#endif
0897:
0898: /**
0899: * Rolls back to a savepoint.
0900: */
0901: //#ifdef JDK14
0902: public void rollback(Savepoint savepoint) throws SQLException {
0903: try {
0904: JdbcSavepoint sp = convertSavepoint(savepoint);
0905: debugCode("rollback(" + sp.getTraceObjectName() + ");");
0906: checkClosed();
0907: sp.rollback();
0908: } catch (Throwable e) {
0909: throw logAndConvert(e);
0910: }
0911: }
0912:
0913: //#endif
0914:
0915: /**
0916: * Releases a savepoint.
0917: */
0918: //#ifdef JDK14
0919: public void releaseSavepoint(Savepoint savepoint)
0920: throws SQLException {
0921: try {
0922: debugCode("releaseSavepoint(savepoint);");
0923: checkClosed();
0924: convertSavepoint(savepoint).release();
0925: } catch (Throwable e) {
0926: throw logAndConvert(e);
0927: }
0928: }
0929:
0930: private JdbcSavepoint convertSavepoint(Savepoint savepoint)
0931: throws SQLException {
0932: if (!(savepoint instanceof JdbcSavepoint)) {
0933: throw Message.getSQLException(
0934: ErrorCode.SAVEPOINT_IS_INVALID_1, "" + savepoint);
0935: }
0936: return (JdbcSavepoint) savepoint;
0937: }
0938:
0939: //#endif
0940:
0941: /**
0942: * Creates a prepared statement with the specified result set type,
0943: * concurrency, and holdability.
0944: *
0945: * @return the prepared statement
0946: * @throws SQLException if the connection is closed or the result set type,
0947: * concurrency, or holdability are not supported
0948: */
0949: public PreparedStatement prepareStatement(String sql,
0950: int resultSetType, int resultSetConcurrency,
0951: int resultSetHoldability) throws SQLException {
0952: try {
0953: int id = getNextId(TraceObject.PREPARED_STATEMENT);
0954: if (debug()) {
0955: debugCodeAssign("PreparedStatement",
0956: TraceObject.PREPARED_STATEMENT, id,
0957: "prepareStatement(" + quote(sql) + ", "
0958: + resultSetType + ", "
0959: + resultSetConcurrency + ", "
0960: + resultSetHoldability + ")");
0961: }
0962: checkClosed();
0963: checkTypeAndConcurrency(resultSetType, resultSetConcurrency);
0964: checkHoldability(resultSetHoldability);
0965: sql = translateSQL(sql);
0966: return new JdbcPreparedStatement(session, this , sql,
0967: resultSetType, id, false);
0968: } catch (Throwable e) {
0969: throw logAndConvert(e);
0970: }
0971: }
0972:
0973: /**
0974: * Creates a new prepared statement. This method just calls
0975: * prepareStatement(String sql).
0976: *
0977: * @return the prepared statement
0978: * @throws SQLException
0979: * if the connection is closed
0980: */
0981: public PreparedStatement prepareStatement(String sql,
0982: int autoGeneratedKeys) throws SQLException {
0983: try {
0984: if (debug()) {
0985: debugCode("prepareStatement(" + quote(sql) + ", "
0986: + autoGeneratedKeys + ");");
0987: }
0988: return prepareStatement(sql);
0989: } catch (Throwable e) {
0990: throw logAndConvert(e);
0991: }
0992: }
0993:
0994: /**
0995: * Creates a new prepared statement. This method just calls
0996: * prepareStatement(String sql).
0997: *
0998: * @return the prepared statement
0999: * @throws SQLException
1000: * if the connection is closed
1001: */
1002: public PreparedStatement prepareStatement(String sql,
1003: int[] columnIndexes) throws SQLException {
1004: try {
1005: if (debug()) {
1006: debugCode("prepareStatement(" + quote(sql) + ", "
1007: + quoteIntArray(columnIndexes) + ");");
1008: }
1009: return prepareStatement(sql);
1010: } catch (Throwable e) {
1011: throw logAndConvert(e);
1012: }
1013: }
1014:
1015: /**
1016: * Creates a new prepared statement. This method just calls
1017: * prepareStatement(String sql).
1018: *
1019: * @return the prepared statement
1020: * @throws SQLException
1021: * if the connection is closed
1022: */
1023: public PreparedStatement prepareStatement(String sql,
1024: String[] columnNames) throws SQLException {
1025: try {
1026: if (debug()) {
1027: debugCode("prepareStatement(" + quote(sql) + ", "
1028: + quoteArray(columnNames) + ");");
1029: }
1030: return prepareStatement(sql);
1031: } catch (Throwable e) {
1032: throw logAndConvert(e);
1033: }
1034: }
1035:
1036: // =============================================================
1037:
1038: /**
1039: * INTERNAL
1040: */
1041: public JdbcConnection(String url, Properties info)
1042: throws SQLException {
1043: this (new ConnectionInfo(url, info), true);
1044: }
1045:
1046: /**
1047: * INTERNAL
1048: */
1049: public JdbcConnection(ConnectionInfo ci, boolean useBaseDir)
1050: throws SQLException {
1051: try {
1052: checkJavaVersion();
1053: if (ci.isRemote()) {
1054: session = new SessionRemote().createSession(ci);
1055: } else {
1056: SessionInterface si = (SessionInterface) ClassUtils
1057: .loadSystemClass("org.h2.engine.Session")
1058: .newInstance();
1059: if (useBaseDir) {
1060: String baseDir = SysProperties.getBaseDir();
1061: if (baseDir != null) {
1062: ci.setBaseDir(baseDir);
1063: }
1064: }
1065: session = si.createSession(ci);
1066: }
1067: trace = session.getTrace();
1068: int id = getNextId(TraceObject.CONNECTION);
1069: setTrace(trace, TraceObject.CONNECTION, id);
1070: this .user = ci.getUserName();
1071: if (info()) {
1072: trace.infoCode("Connection " + getTraceObjectName()
1073: + " = DriverManager.getConnection("
1074: + quote(ci.getOriginalURL()) + ", "
1075: + quote(user) + ", \"\")");
1076: }
1077: this .url = ci.getURL();
1078: openStackTrace = new Exception("Stack Trace");
1079: } catch (Throwable e) {
1080: throw logAndConvert(e);
1081: }
1082: }
1083:
1084: /**
1085: * INTERNAL
1086: */
1087: public JdbcConnection(SessionInterface session, String user,
1088: String url) throws SQLException {
1089: isInternal = true;
1090: this .session = session;
1091: trace = session.getTrace();
1092: int id = getNextId(TraceObject.CONNECTION);
1093: setTrace(trace, TraceObject.CONNECTION, id);
1094: this .user = user;
1095: this .url = url;
1096: }
1097:
1098: private void checkJavaVersion() throws SQLException {
1099: try {
1100: //#ifdef JDK14
1101: // check for existence of this class (avoiding Class . forName)
1102: Class clazz = java.sql.Savepoint.class;
1103: clazz.getClass();
1104: //#endif
1105: } catch (Throwable e) {
1106: throw Message
1107: .getSQLException(ErrorCode.UNSUPPORTED_JAVA_VERSION);
1108: }
1109: }
1110:
1111: CommandInterface prepareCommand(String sql, int fetchSize)
1112: throws SQLException {
1113: return session.prepareCommand(sql, fetchSize);
1114: }
1115:
1116: CommandInterface prepareCommand(String sql, CommandInterface old)
1117: throws SQLException {
1118: return old == null ? session.prepareCommand(sql,
1119: Integer.MAX_VALUE) : old;
1120: }
1121:
1122: private int translateGetEnd(String sql, int i, char c)
1123: throws SQLException {
1124: int len = sql.length();
1125: switch (c) {
1126: case '\'': {
1127: int j = sql.indexOf('\'', i + 1);
1128: if (j < 0) {
1129: throw Message.getSyntaxError(sql, i);
1130: }
1131: return j;
1132: }
1133: case '"': {
1134: int j = sql.indexOf('"', i + 1);
1135: if (j < 0) {
1136: throw Message.getSyntaxError(sql, i);
1137: }
1138: return j;
1139: }
1140: case '/': {
1141: checkRunOver(i + 1, len, sql);
1142: if (sql.charAt(i + 1) == '*') {
1143: // block comment
1144: int j = sql.indexOf("*/", i + 2);
1145: if (j < 0) {
1146: throw Message.getSyntaxError(sql, i);
1147: }
1148: i = j + 1;
1149: } else if (sql.charAt(i + 1) == '/') {
1150: // single line comment
1151: i += 2;
1152: while (i < len && (c = sql.charAt(i)) != '\r'
1153: && c != '\n') {
1154: i++;
1155: }
1156: }
1157: return i;
1158: }
1159: case '-': {
1160: checkRunOver(i + 1, len, sql);
1161: if (sql.charAt(i + 1) == '-') {
1162: // single line comment
1163: i += 2;
1164: while (i < len && (c = sql.charAt(i)) != '\r'
1165: && c != '\n') {
1166: i++;
1167: }
1168: }
1169: return i;
1170: }
1171: default:
1172: throw Message.getInternalError("c=" + c);
1173: }
1174: }
1175:
1176: String translateSQL(String sql) throws SQLException {
1177: if (sql == null || sql.indexOf('{') < 0) {
1178: return sql;
1179: }
1180: int len = sql.length();
1181: char[] chars = null;
1182: int level = 0;
1183: for (int i = 0; i < len; i++) {
1184: char c = sql.charAt(i);
1185: switch (c) {
1186: case '\'':
1187: case '"':
1188: case '/':
1189: case '-':
1190: i = translateGetEnd(sql, i, c);
1191: break;
1192: case '{':
1193: level++;
1194: if (chars == null) {
1195: chars = sql.toCharArray();
1196: }
1197: chars[i] = ' ';
1198: while (Character.isSpaceChar(chars[i])) {
1199: i++;
1200: checkRunOver(i, len, sql);
1201: }
1202: int start = i;
1203: if (chars[i] >= '0' && chars[i] <= '9') {
1204: chars[i - 1] = '{';
1205: while (true) {
1206: checkRunOver(i, len, sql);
1207: c = chars[i];
1208: if (c == '}') {
1209: break;
1210: }
1211: switch (c) {
1212: case '\'':
1213: case '"':
1214: case '/':
1215: case '-':
1216: i = translateGetEnd(sql, i, c);
1217: break;
1218: default:
1219: }
1220: i++;
1221: }
1222: level--;
1223: break;
1224: } else if (chars[i] == '?') {
1225: // TODO nativeSQL: '? = ...' : register out parameter
1226: chars[i++] = ' ';
1227: checkRunOver(i, len, sql);
1228: while (Character.isSpaceChar(chars[i])) {
1229: i++;
1230: checkRunOver(i, len, sql);
1231: }
1232: if (sql.charAt(i) != '=') {
1233: throw Message.getSyntaxError(sql, i, "=");
1234: }
1235: chars[i++] = ' ';
1236: checkRunOver(i, len, sql);
1237: while (Character.isSpaceChar(chars[i])) {
1238: i++;
1239: checkRunOver(i, len, sql);
1240: }
1241: }
1242: while (!Character.isSpaceChar(chars[i])) {
1243: i++;
1244: checkRunOver(i, len, sql);
1245: }
1246: int remove = 0;
1247: if (found(sql, start, "fn")) {
1248: remove = 2;
1249: } else if (found(sql, start, "escape")) {
1250: break;
1251: } else if (found(sql, start, "call")) {
1252: break;
1253: } else if (found(sql, start, "oj")) {
1254: remove = 2;
1255: } else if (found(sql, start, "ts")) {
1256: remove = 2;
1257: } else if (found(sql, start, "t")) {
1258: remove = 1;
1259: } else if (found(sql, start, "d")) {
1260: remove = 1;
1261: } else if (found(sql, start, "params")) {
1262: remove = "params".length();
1263: }
1264: for (i = start; remove > 0; i++, remove--) {
1265: chars[i] = ' ';
1266: }
1267: break;
1268: case '}':
1269: if (--level < 0) {
1270: throw Message.getSyntaxError(sql, i);
1271: }
1272: chars[i] = ' ';
1273: break;
1274: default:
1275: }
1276: }
1277: if (level != 0) {
1278: throw Message.getSyntaxError(sql, sql.length() - 1);
1279: }
1280: if (chars != null) {
1281: sql = new String(chars);
1282: }
1283: return sql;
1284: }
1285:
1286: private void checkRunOver(int i, int len, String sql)
1287: throws SQLException {
1288: if (i >= len) {
1289: throw Message.getSyntaxError(sql, i);
1290: }
1291: }
1292:
1293: private boolean found(String sql, int start, String other) {
1294: return sql.regionMatches(true, start, other, 0, other.length());
1295: }
1296:
1297: private void checkTypeAndConcurrency(int resultSetType,
1298: int resultSetConcurrency) throws SQLException {
1299: // TODO compatibility / correctness: OpenOffice uses TYPE_SCROLL_SENSITIVE
1300: // if (resultSetType == ResultSet.TYPE_SCROLL_SENSITIVE) {
1301: // throw Message.getInvalidValueException(
1302: // "" + resultSetType, "resultSetType");
1303: // }
1304: // if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY) {
1305: // throw Message.getInvalidValueException(
1306: // "" + resultSetConcurrency, "resultSetConcurrency");
1307: // }
1308: }
1309:
1310: private void checkHoldability(int resultSetHoldability)
1311: throws SQLException {
1312: // TODO compatibility / correctness: DBPool uses
1313: // ResultSet.HOLD_CURSORS_OVER_COMMIT
1314: //#ifdef JDK14
1315: if (resultSetHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT
1316: && resultSetHoldability != ResultSet.CLOSE_CURSORS_AT_COMMIT) {
1317: throw Message.getInvalidValueException(""
1318: + resultSetHoldability, "resultSetHoldability");
1319: }
1320: //#endif
1321: }
1322:
1323: void checkClosed() throws SQLException {
1324: if (session == null) {
1325: throw Message.getSQLException(ErrorCode.OBJECT_CLOSED);
1326: }
1327: if (session.isClosed()) {
1328: throw Message
1329: .getSQLException(ErrorCode.DATABASE_CALLED_AT_SHUTDOWN);
1330: }
1331: }
1332:
1333: String getURL() throws SQLException {
1334: checkClosed();
1335: return url;
1336: }
1337:
1338: String getUser() throws SQLException {
1339: checkClosed();
1340: return user;
1341: }
1342:
1343: protected void finalize() {
1344: if (!SysProperties.runFinalize) {
1345: return;
1346: }
1347: if (isInternal) {
1348: return;
1349: }
1350: if (session != null) {
1351: trace.error("Connection not closed", openStackTrace);
1352: try {
1353: close();
1354: } catch (SQLException e) {
1355: trace.debug("finalize", e);
1356: }
1357: }
1358: }
1359:
1360: private void rollbackInternal() throws SQLException {
1361: rollback = prepareCommand("ROLLBACK", rollback);
1362: rollback.executeUpdate();
1363: }
1364:
1365: /**
1366: * INTERNAL
1367: */
1368: public int getPowerOffCount() {
1369: return (session == null || session.isClosed()) ? 0 : session
1370: .getPowerOffCount();
1371: }
1372:
1373: /**
1374: * INTERNAL
1375: */
1376: public void setPowerOffCount(int count) throws SQLException {
1377: if (session != null) {
1378: session.setPowerOffCount(count);
1379: }
1380: }
1381:
1382: /**
1383: * INTERNAL
1384: */
1385: public void setExecutingStatement(Statement stat) {
1386: executingStatement = stat;
1387: }
1388:
1389: ResultInterface getGeneratedKeys(JdbcStatement statement, int id)
1390: throws SQLException {
1391: getGeneratedKeys = prepareCommand("CALL IDENTITY()",
1392: getGeneratedKeys);
1393: return getGeneratedKeys.executeQuery(0, false);
1394: }
1395:
1396: /**
1397: * Create a new empty Clob object.
1398: *
1399: * @return the object
1400: */
1401: public Clob createClob() throws SQLException {
1402: try {
1403: int id = getNextId(TraceObject.CLOB);
1404: debugCodeAssign("Clob", TraceObject.CLOB, id,
1405: "createClob()");
1406: checkClosed();
1407: ValueLob v = ValueLob.createSmallLob(Value.CLOB,
1408: new byte[0]);
1409: return new JdbcClob(session, this , v, id);
1410: } catch (Throwable e) {
1411: throw logAndConvert(e);
1412: }
1413: }
1414:
1415: /**
1416: * Create a new empty Blob object.
1417: *
1418: * @return the object
1419: */
1420: public Blob createBlob() throws SQLException {
1421: try {
1422: int id = getNextId(TraceObject.BLOB);
1423: debugCodeAssign("Blob", TraceObject.BLOB, id,
1424: "createClob()");
1425: checkClosed();
1426: ValueLob v = ValueLob.createSmallLob(Value.BLOB,
1427: new byte[0]);
1428: return new JdbcBlob(session, this , v, id);
1429: } catch (Throwable e) {
1430: throw logAndConvert(e);
1431: }
1432: }
1433:
1434: /**
1435: * Create a new empty NClob object.
1436: *
1437: * @return the object
1438: */
1439: //#ifdef JDK16
1440: /*
1441: public NClob createNClob() throws SQLException {
1442: try {
1443: int id = getNextId(TraceObject.CLOB);
1444: debugCodeAssign("NClob", TraceObject.CLOB, id, "createNClob()");
1445: checkClosed();
1446: ValueLob v = ValueLob.createSmallLob(Value.CLOB, new byte[0]);
1447: return new JdbcClob(session, this, v, id);
1448: } catch (Throwable e) {
1449: throw logAndConvert(e);
1450: }
1451: }
1452: */
1453: //#endif
1454: /**
1455: * [Not supported] Create a new empty SQLXML object.
1456: */
1457: //#ifdef JDK16
1458: /*
1459: public SQLXML createSQLXML() throws SQLException {
1460: throw Message.getUnsupportedException();
1461: }
1462: */
1463: //#endif
1464: /**
1465: * [Not supported] Create a new empty Array object.
1466: */
1467: //#ifdef JDK16
1468: /*
1469: public Array createArrayOf(String typeName, Object[] elements)
1470: throws SQLException {
1471: throw Message.getUnsupportedException();
1472: }
1473: */
1474: //#endif
1475: /**
1476: * [Not supported] Create a new empty Struct object.
1477: */
1478: //#ifdef JDK16
1479: /*
1480: public Struct createStruct(String typeName, Object[] attributes)
1481: throws SQLException {
1482: throw Message.getUnsupportedException();
1483: }
1484: */
1485: //#endif
1486: /**
1487: * Returns true if this connection is still valid.
1488: *
1489: * @return true if the connection is valid.
1490: */
1491: public synchronized boolean isValid(int timeout) {
1492: try {
1493: debugCodeCall("isValid", timeout);
1494: checkClosed();
1495: getInternalAutoCommit();
1496: return true;
1497: } catch (Throwable e) {
1498: // this method doesn't throw an exception, but it logs it
1499: logAndConvert(e);
1500: return false;
1501: }
1502: }
1503:
1504: /**
1505: * [Not supported] Set a client property.
1506: */
1507: //#ifdef JDK16
1508: /*
1509: public void setClientInfo(String name, String value)
1510: throws SQLClientInfoException {
1511: throw new SQLClientInfoException();
1512: }
1513: */
1514: //#endif
1515: /**
1516: * [Not supported] Set the client properties.
1517: */
1518: //#ifdef JDK16
1519: /*
1520: public void setClientInfo(Properties properties) throws SQLClientInfoException {
1521: throw new SQLClientInfoException();
1522: }
1523: */
1524: //#endif
1525: /**
1526: * [Not supported] Get the client properties.
1527: */
1528: //#ifdef JDK16
1529: /*
1530: public Properties getClientInfo() throws SQLClientInfoException {
1531: throw new SQLClientInfoException();
1532: }
1533: */
1534: //#endif
1535: /**
1536: * [Not supported] Set a client property.
1537: */
1538: public String getClientInfo(String name) throws SQLException {
1539: throw Message.getUnsupportedException();
1540: }
1541:
1542: /**
1543: * [Not supported] Return an object of this class if possible.
1544: *
1545: * @param iface the class
1546: */
1547: //#ifdef JDK16
1548: /*
1549: public <T> T unwrap(Class<T> iface) throws SQLException {
1550: throw Message.getUnsupportedException();
1551: }
1552: */
1553: //#endif
1554: /**
1555: * [Not supported] Checks if unwrap can return an object of this class.
1556: *
1557: * @param iface the class
1558: */
1559: //#ifdef JDK16
1560: /*
1561: public boolean isWrapperFor(Class< ? > iface) throws SQLException {
1562: throw Message.getUnsupportedException();
1563: }
1564: */
1565: //#endif
1566: Value createClob(Reader x, long length) throws SQLException {
1567: if (x == null) {
1568: return ValueNull.INSTANCE;
1569: }
1570: if (length <= 0) {
1571: length = -1;
1572: }
1573: Value v = ValueLob.createClob(x, length, session
1574: .getDataHandler());
1575: return v;
1576: }
1577:
1578: Value createBlob(InputStream x, long length) throws SQLException {
1579: if (x == null) {
1580: return ValueNull.INSTANCE;
1581: }
1582: if (length <= 0) {
1583: length = -1;
1584: }
1585: Value v = ValueLob.createBlob(x, length, session
1586: .getDataHandler());
1587: return v;
1588: }
1589:
1590: private void checkMap(Map map) throws SQLException {
1591: if (map != null && map.size() > 0) {
1592: throw Message.getUnsupportedException();
1593: }
1594: }
1595:
1596: /**
1597: * INTERNAL
1598: */
1599: public String toString() {
1600: return getTraceObjectName() + ": url=" + url + " user=" + user;
1601: }
1602:
1603: }
|