001: /*
002:
003: Derby - Class org.apache.derby.impl.jdbc.EmbedConnection30
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.jdbc;
023:
024: import org.apache.derby.iapi.error.StandardException;
025: import org.apache.derby.iapi.sql.conn.StatementContext;
026:
027: import org.apache.derby.impl.jdbc.EmbedConnection;
028: import org.apache.derby.impl.jdbc.Util;
029: import org.apache.derby.jdbc.InternalDriver;
030:
031: import org.apache.derby.iapi.reference.SQLState;
032: import org.apache.derby.iapi.reference.Limits;
033:
034: import org.apache.derby.iapi.error.ExceptionSeverity;
035:
036: import java.sql.Savepoint;
037: import java.sql.SQLException;
038:
039: import java.util.Properties;
040: import java.util.Vector;
041:
042: /**
043: * This class extends the EmbedConnection20 class in order to support new
044: * methods and classes that come with JDBC 3.0.
045:
046: <P><B>Supports</B>
047: <UL>
048: <LI> JSR169 - Subsetting only removes getTypeMap and setTypeMap, which references
049: java.util.Map which exists in Foundation and ee.miniumum. Thus the methods can
050: safely be left in the implementation for JSR169.
051:
052: <LI> JDBC 3.0 - Separate from JDBC 2.0 implementation as JDBC 3.0 introduces
053: a new class java.sql.Savepoint, which is referenced by java.sql.Connection.
054: </UL>
055: *
056: * @see org.apache.derby.impl.jdbc.EmbedConnection
057: *
058: */
059: public class EmbedConnection30 extends EmbedConnection {
060:
061: //////////////////////////////////////////////////////////
062: // CONSTRUCTORS
063: //////////////////////////////////////////////////////////
064:
065: public EmbedConnection30(InternalDriver driver, String url,
066: Properties info) throws SQLException {
067: super (driver, url, info);
068: }
069:
070: public EmbedConnection30(EmbedConnection inputConnection) {
071: super (inputConnection);
072: }
073:
074: /////////////////////////////////////////////////////////////////////////
075: //
076: // JDBC 3.0 - New public methods
077: //
078: /////////////////////////////////////////////////////////////////////////
079:
080: /**
081: * Creates an unnamed savepoint in the current transaction and
082: * returns the new Savepoint object that represents it.
083: *
084: *
085: * @return The new Savepoint object
086: *
087: * @exception SQLException if a database access error occurs or
088: * this Connection object is currently in auto-commit mode
089: */
090: public Savepoint setSavepoint() throws SQLException {
091: return commonSetSavepointCode(null, false);
092: }
093:
094: /**
095: * Creates a savepoint with the given name in the current transaction and
096: * returns the new Savepoint object that represents it.
097: *
098: *
099: * @param name A String containing the name of the savepoint
100: *
101: * @return The new Savepoint object
102: *
103: * @exception SQLException if a database access error occurs or
104: * this Connection object is currently in auto-commit mode
105: */
106: public Savepoint setSavepoint(String name) throws SQLException {
107: return commonSetSavepointCode(name, true);
108: }
109:
110: /**
111: * Creates a savepoint with the given name(if it is a named savepoint else we will generate a name
112: * becuase Cloudscape only supports named savepoints internally) in the current transaction and
113: * returns the new Savepoint object that represents it.
114: *
115: * @param name A String containing the name of the savepoint. Will be null if this is an unnamed savepoint
116: * @param userSuppliedSavepointName If true means it's a named user defined savepoint.
117: *
118: * @return The new Savepoint object
119: */
120: private Savepoint commonSetSavepointCode(String name,
121: boolean userSuppliedSavepointName) throws SQLException {
122: synchronized (getConnectionSynchronization()) {
123: setupContextStack();
124: try {
125: verifySavepointCommandIsAllowed();
126: if (userSuppliedSavepointName && (name == null))//make sure that if it is a named savepoint then supplied name is not null
127: throw newSQLException(SQLState.NULL_NAME_FOR_SAVEPOINT);
128: //make sure that if it is a named savepoint then supplied name length is not > 128
129: if (userSuppliedSavepointName
130: && (name.length() > Limits.MAX_IDENTIFIER_LENGTH))
131: throw newSQLException(
132: SQLState.LANG_IDENTIFIER_TOO_LONG,
133: name,
134: String
135: .valueOf(Limits.MAX_IDENTIFIER_LENGTH));
136: if (userSuppliedSavepointName && name.startsWith("SYS")) //to enforce DB2 restriction which is savepoint name can't start with SYS
137: throw newSQLException(SQLState.INVALID_SCHEMA_SYS,
138: "SYS");
139: Savepoint savePt = new EmbedSavepoint30(this , name);
140: return savePt;
141: } catch (StandardException e) {
142: throw handleException(e);
143: } finally {
144: restoreContextStack();
145: }
146: }
147: }
148:
149: /**
150: * Undoes all changes made after the given Savepoint object was set.
151: * This method should be used only when auto-commit has been disabled.
152: *
153: *
154: * @param savepoint The Savepoint object to rollback to
155: *
156: * @exception SQLException if a database access error occurs,
157: * the Savepoint object is no longer valid, or this Connection
158: * object is currently in auto-commit mode
159: */
160: public void rollback(Savepoint savepoint) throws SQLException {
161: synchronized (getConnectionSynchronization()) {
162: setupContextStack();
163: try {
164: verifySavepointCommandIsAllowed();
165: verifySavepointArg(savepoint);
166: //Need to cast and get the name because JDBC3 spec doesn't support names for
167: //unnamed savepoints but Cloudscape keeps names for named & unnamed savepoints.
168: getLanguageConnection().internalRollbackToSavepoint(
169: ((EmbedSavepoint30) savepoint)
170: .getInternalName(), true, savepoint);
171: } catch (StandardException e) {
172: throw handleException(e);
173: } finally {
174: restoreContextStack();
175: }
176: }
177: }
178:
179: /**
180: * Removes the given Savepoint object from the current transaction.
181: * Any reference to the savepoint after it has been removed will cause
182: * an SQLException to be thrown
183: *
184: *
185: * @param savepoint The Savepoint object to be removed
186: *
187: * @exception SQLException if a database access error occurs or the
188: * given Savepoint object is not a valid savepoint in the current transaction
189: */
190: public void releaseSavepoint(Savepoint savepoint)
191: throws SQLException {
192: synchronized (getConnectionSynchronization()) {
193: setupContextStack();
194: try {
195: verifySavepointCommandIsAllowed();
196: verifySavepointArg(savepoint);
197: //Need to cast and get the name because JDBC3 spec doesn't support names for
198: //unnamed savepoints but Cloudscape keeps name for named & unnamed savepoints.
199: getLanguageConnection().releaseSavePoint(
200: ((EmbedSavepoint30) savepoint)
201: .getInternalName(), savepoint);
202: } catch (StandardException e) {
203: throw handleException(e);
204: } finally {
205: restoreContextStack();
206: }
207: }
208: }
209:
210: // used by setSavepoint to check autocommit is false and not inside the trigger code
211: private void verifySavepointCommandIsAllowed() throws SQLException {
212: if (autoCommit)
213: throw newSQLException(SQLState.NO_SAVEPOINT_WHEN_AUTO);
214:
215: //Bug 4507 - savepoint not allowed inside trigger
216: StatementContext stmtCtxt = getLanguageConnection()
217: .getStatementContext();
218: if (stmtCtxt != null && stmtCtxt.inTrigger())
219: throw newSQLException(SQLState.NO_SAVEPOINT_IN_TRIGGER);
220: }
221:
222: // used by release/rollback to check savepoint argument
223: private void verifySavepointArg(Savepoint savepoint)
224: throws SQLException {
225: //bug 4451 - Check for null savepoint
226: EmbedSavepoint30 lsv = (EmbedSavepoint30) savepoint;
227: // bug 4451 need to throw error for null Savepoint
228: if (lsv == null)
229: throw Util.generateCsSQLException(
230: SQLState.XACT_SAVEPOINT_NOT_FOUND, "null");
231:
232: //bug 4468 - verify that savepoint rollback is for a savepoint from the current
233: // connection
234: if (!lsv.sameConnection(this))
235: throw newSQLException(SQLState.XACT_SAVEPOINT_RELEASE_ROLLBACK_FAIL);
236:
237: return;
238: }
239: }
|