1 | /* |
2 | |
3 | Derby - Class org.apache.derby.impl.jdbc.EmbedConnection30 |
4 | |
5 | Copyright 2001, 2005 The Apache Software Foundation or its licensors, as applicable. |
6 | |
7 | Licensed under the Apache License, Version 2.0 (the "License"); |
8 | you may not use this file except in compliance with the License. |
9 | You may obtain a copy of the License at |
10 | |
11 | http://www.apache.org/licenses/LICENSE-2.0 |
12 | |
13 | Unless required by applicable law or agreed to in writing, software |
14 | distributed under the License is distributed on an "AS IS" BASIS, |
15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | See the License for the specific language governing permissions and |
17 | limitations under the License. |
18 | |
19 | */ |
20 | |
21 | package org.apache.derby.impl.jdbc; |
22 | |
23 | import org.apache.derby.iapi.error.StandardException; |
24 | import org.apache.derby.iapi.sql.conn.StatementContext; |
25 | |
26 | import org.apache.derby.impl.jdbc.EmbedConnection; |
27 | import org.apache.derby.impl.jdbc.Util; |
28 | import org.apache.derby.jdbc.InternalDriver; |
29 | |
30 | import org.apache.derby.iapi.reference.SQLState; |
31 | import org.apache.derby.iapi.reference.Limits; |
32 | |
33 | import org.apache.derby.iapi.error.ExceptionSeverity; |
34 | |
35 | import java.sql.Savepoint; |
36 | import java.sql.SQLException; |
37 | |
38 | import java.util.Properties; |
39 | import java.util.Vector; |
40 | |
41 | |
42 | /** |
43 | * This class extends the EmbedConnection20 class in order to support new |
44 | * methods and classes that come with JDBC 3.0. |
45 | |
46 | <P><B>Supports</B> |
47 | <UL> |
48 | <LI> JSR169 - Subsetting only removes getTypeMap and setTypeMap, which references |
49 | java.util.Map which exists in Foundation and ee.miniumum. Thus the methods can |
50 | safely be left in the implementation for JSR169. |
51 | |
52 | <LI> JDBC 3.0 - Separate from JDBC 2.0 implementation as JDBC 3.0 introduces |
53 | a new class java.sql.Savepoint, which is referenced by java.sql.Connection. |
54 | </UL> |
55 | * |
56 | * @see org.apache.derby.impl.jdbc.EmbedConnection |
57 | * |
58 | */ |
59 | public class EmbedConnection30 extends EmbedConnection |
60 | { |
61 | |
62 | ////////////////////////////////////////////////////////// |
63 | // CONSTRUCTORS |
64 | ////////////////////////////////////////////////////////// |
65 | |
66 | public EmbedConnection30( |
67 | InternalDriver driver, |
68 | String url, |
69 | Properties info) |
70 | throws SQLException |
71 | { |
72 | super(driver, url, info); |
73 | } |
74 | |
75 | public EmbedConnection30( |
76 | EmbedConnection inputConnection) |
77 | { |
78 | super(inputConnection); |
79 | } |
80 | |
81 | ///////////////////////////////////////////////////////////////////////// |
82 | // |
83 | // JDBC 3.0 - New public methods |
84 | // |
85 | ///////////////////////////////////////////////////////////////////////// |
86 | |
87 | /** |
88 | * Creates an unnamed savepoint in the current transaction and |
89 | * returns the new Savepoint object that represents it. |
90 | * |
91 | * |
92 | * @return The new Savepoint object |
93 | * |
94 | * @exception SQLException if a database access error occurs or |
95 | * this Connection object is currently in auto-commit mode |
96 | */ |
97 | public Savepoint setSavepoint() |
98 | throws SQLException |
99 | { |
100 | return commonSetSavepointCode(null, false); |
101 | } |
102 | |
103 | /** |
104 | * Creates a savepoint with the given name in the current transaction and |
105 | * returns the new Savepoint object that represents it. |
106 | * |
107 | * |
108 | * @param name A String containing the name of the savepoint |
109 | * |
110 | * @return The new Savepoint object |
111 | * |
112 | * @exception SQLException if a database access error occurs or |
113 | * this Connection object is currently in auto-commit mode |
114 | */ |
115 | public Savepoint setSavepoint( |
116 | String name) |
117 | throws SQLException |
118 | { |
119 | return commonSetSavepointCode(name, true); |
120 | } |
121 | |
122 | /** |
123 | * Creates a savepoint with the given name(if it is a named savepoint else we will generate a name |
124 | * becuase Cloudscape only supports named savepoints internally) in the current transaction and |
125 | * returns the new Savepoint object that represents it. |
126 | * |
127 | * @param name A String containing the name of the savepoint. Will be null if this is an unnamed savepoint |
128 | * @param userSuppliedSavepointName If true means it's a named user defined savepoint. |
129 | * |
130 | * @return The new Savepoint object |
131 | */ |
132 | private Savepoint commonSetSavepointCode(String name, boolean userSuppliedSavepointName) throws SQLException |
133 | { |
134 | synchronized (getConnectionSynchronization()) { |
135 | setupContextStack(); |
136 | try { |
137 | verifySavepointCommandIsAllowed(); |
138 | if (userSuppliedSavepointName && (name == null))//make sure that if it is a named savepoint then supplied name is not null |
139 | throw newSQLException(SQLState.NULL_NAME_FOR_SAVEPOINT); |
140 | //make sure that if it is a named savepoint then supplied name length is not > 128 |
141 | if (userSuppliedSavepointName && (name.length() > Limits.MAX_IDENTIFIER_LENGTH)) |
142 | throw newSQLException(SQLState.LANG_IDENTIFIER_TOO_LONG, name, String.valueOf(Limits.MAX_IDENTIFIER_LENGTH)); |
143 | if (userSuppliedSavepointName && name.startsWith("SYS")) //to enforce DB2 restriction which is savepoint name can't start with SYS |
144 | throw newSQLException(SQLState.INVALID_SCHEMA_SYS, "SYS"); |
145 | Savepoint savePt = new EmbedSavepoint30(this, name); |
146 | return savePt; |
147 | } catch (StandardException e) { |
148 | throw handleException(e); |
149 | } finally { |
150 | restoreContextStack(); |
151 | } |
152 | } |
153 | } |
154 | |
155 | /** |
156 | * Undoes all changes made after the given Savepoint object was set. |
157 | * This method should be used only when auto-commit has been disabled. |
158 | * |
159 | * |
160 | * @param savepoint The Savepoint object to rollback to |
161 | * |
162 | * @exception SQLException if a database access error occurs, |
163 | * the Savepoint object is no longer valid, or this Connection |
164 | * object is currently in auto-commit mode |
165 | */ |
166 | public void rollback( |
167 | Savepoint savepoint) |
168 | throws SQLException |
169 | { |
170 | synchronized (getConnectionSynchronization()) { |
171 | setupContextStack(); |
172 | try { |
173 | verifySavepointCommandIsAllowed(); |
174 | verifySavepointArg(savepoint); |
175 | //Need to cast and get the name because JDBC3 spec doesn't support names for |
176 | //unnamed savepoints but Cloudscape keeps names for named & unnamed savepoints. |
177 | getLanguageConnection().internalRollbackToSavepoint(((EmbedSavepoint30)savepoint).getInternalName(),true, savepoint); |
178 | } catch (StandardException e) { |
179 | throw handleException(e); |
180 | } finally { |
181 | restoreContextStack(); |
182 | } |
183 | } |
184 | } |
185 | |
186 | /** |
187 | * Removes the given Savepoint object from the current transaction. |
188 | * Any reference to the savepoint after it has been removed will cause |
189 | * an SQLException to be thrown |
190 | * |
191 | * |
192 | * @param savepoint The Savepoint object to be removed |
193 | * |
194 | * @exception SQLException if a database access error occurs or the |
195 | * given Savepoint object is not a valid savepoint in the current transaction |
196 | */ |
197 | public void releaseSavepoint( |
198 | Savepoint savepoint) |
199 | throws SQLException |
200 | { |
201 | synchronized (getConnectionSynchronization()) { |
202 | setupContextStack(); |
203 | try { |
204 | verifySavepointCommandIsAllowed(); |
205 | verifySavepointArg(savepoint); |
206 | //Need to cast and get the name because JDBC3 spec doesn't support names for |
207 | //unnamed savepoints but Cloudscape keeps name for named & unnamed savepoints. |
208 | getLanguageConnection().releaseSavePoint(((EmbedSavepoint30)savepoint).getInternalName(), savepoint); |
209 | } catch (StandardException e) { |
210 | throw handleException(e); |
211 | } finally { |
212 | restoreContextStack(); |
213 | } |
214 | } |
215 | } |
216 | |
217 | // used by setSavepoint to check autocommit is false and not inside the trigger code |
218 | private void verifySavepointCommandIsAllowed() throws SQLException |
219 | { |
220 | if (autoCommit) |
221 | throw newSQLException(SQLState.NO_SAVEPOINT_WHEN_AUTO); |
222 | |
223 | //Bug 4507 - savepoint not allowed inside trigger |
224 | StatementContext stmtCtxt = getLanguageConnection().getStatementContext(); |
225 | if (stmtCtxt!= null && stmtCtxt.inTrigger()) |
226 | throw newSQLException(SQLState.NO_SAVEPOINT_IN_TRIGGER); |
227 | } |
228 | |
229 | // used by release/rollback to check savepoint argument |
230 | private void verifySavepointArg(Savepoint savepoint) throws SQLException |
231 | { |
232 | //bug 4451 - Check for null savepoint |
233 | EmbedSavepoint30 lsv = (EmbedSavepoint30) savepoint; |
234 | // bug 4451 need to throw error for null Savepoint |
235 | if (lsv == null) |
236 | throw |
237 | Util.generateCsSQLException(SQLState.XACT_SAVEPOINT_NOT_FOUND, "null"); |
238 | |
239 | //bug 4468 - verify that savepoint rollback is for a savepoint from the current |
240 | // connection |
241 | if (!lsv.sameConnection(this)) |
242 | throw newSQLException(SQLState.XACT_SAVEPOINT_RELEASE_ROLLBACK_FAIL); |
243 | |
244 | return; |
245 | } |
246 | } |