1 | /* |
2 | |
3 | Derby - Class org.apache.derby.impl.sql.GenericStorablePreparedStatement |
4 | |
5 | Copyright 1998, 2004 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.sql; |
22 | |
23 | import org.apache.derby.iapi.services.monitor.ModuleFactory; |
24 | import org.apache.derby.iapi.services.monitor.Monitor; |
25 | |
26 | import org.apache.derby.iapi.services.sanity.SanityManager; |
27 | |
28 | import org.apache.derby.catalog.UUID; |
29 | import org.apache.derby.iapi.services.uuid.UUIDFactory; |
30 | import org.apache.derby.iapi.util.ByteArray; |
31 | |
32 | import org.apache.derby.iapi.sql.dictionary.DataDictionary; |
33 | |
34 | import org.apache.derby.iapi.sql.Activation; |
35 | import org.apache.derby.iapi.sql.ResultColumnDescriptor; |
36 | import org.apache.derby.iapi.sql.ResultDescription; |
37 | import org.apache.derby.iapi.sql.ResultSet; |
38 | import org.apache.derby.iapi.sql.PreparedStatement; |
39 | import org.apache.derby.iapi.sql.Statement; |
40 | import org.apache.derby.iapi.sql.StorablePreparedStatement; |
41 | |
42 | import org.apache.derby.iapi.sql.execute.ConstantAction; |
43 | import org.apache.derby.iapi.sql.conn.LanguageConnectionContext; |
44 | |
45 | import org.apache.derby.iapi.error.StandardException; |
46 | |
47 | import org.apache.derby.iapi.reference.SQLState; |
48 | |
49 | import org.apache.derby.iapi.services.loader.GeneratedClass; |
50 | import org.apache.derby.iapi.services.loader.ClassFactory; |
51 | import org.apache.derby.iapi.services.context.ContextService; |
52 | |
53 | import org.apache.derby.iapi.services.io.StoredFormatIds; |
54 | import org.apache.derby.iapi.services.io.FormatIdUtil; |
55 | import org.apache.derby.iapi.services.io.ArrayUtil; |
56 | import org.apache.derby.iapi.services.io.Formatable; |
57 | |
58 | import org.apache.derby.iapi.services.monitor.Monitor; |
59 | |
60 | import java.sql.Timestamp; |
61 | import java.io.ObjectOutput; |
62 | import java.io.ObjectInput; |
63 | import java.io.IOException; |
64 | |
65 | import org.apache.derby.iapi.services.loader.ClassFactory; |
66 | import org.apache.derby.iapi.services.loader.GeneratedClass; |
67 | import org.apache.derby.iapi.services.loader.GeneratedMethod; |
68 | /** |
69 | * Prepared statement that can be made persistent. |
70 | * @author jamie |
71 | */ |
72 | public class GenericStorablePreparedStatement |
73 | extends GenericPreparedStatement implements Formatable, StorablePreparedStatement |
74 | { |
75 | |
76 | // formatable |
77 | private ByteArray byteCode; |
78 | private String className; |
79 | |
80 | /** |
81 | * Niladic constructor, for formatable |
82 | * only. |
83 | */ |
84 | public GenericStorablePreparedStatement() |
85 | { |
86 | super(); |
87 | } |
88 | |
89 | GenericStorablePreparedStatement(Statement stmt) |
90 | { |
91 | super(stmt); |
92 | } |
93 | |
94 | /** |
95 | * Get our byte code array. Used |
96 | * by others to save off our byte |
97 | * code for us. |
98 | * |
99 | * @return the byte code saver |
100 | */ |
101 | ByteArray getByteCodeSaver() |
102 | { |
103 | if (byteCode == null) { |
104 | byteCode = new ByteArray(); |
105 | } |
106 | return byteCode; |
107 | } |
108 | |
109 | /** |
110 | * Get and load the activation class. Will always |
111 | * return a loaded/valid class or null if the class |
112 | * cannot be loaded. |
113 | * |
114 | * @return the generated class, or null if the |
115 | * class cannot be loaded |
116 | * |
117 | * @exception StandardException on error |
118 | */ |
119 | public GeneratedClass getActivationClass() |
120 | throws StandardException |
121 | { |
122 | if (activationClass == null) |
123 | loadGeneratedClass(); |
124 | |
125 | return activationClass; |
126 | } |
127 | |
128 | void setActivationClass(GeneratedClass ac) { |
129 | |
130 | super.setActivationClass(ac); |
131 | if (ac != null) { |
132 | className = ac.getName(); |
133 | |
134 | // see if this is an pre-compiled class |
135 | if (byteCode != null && byteCode.getArray() == null) |
136 | byteCode = null; |
137 | } |
138 | } |
139 | |
140 | ///////////////////////////////////////////////////////////// |
141 | // |
142 | // STORABLEPREPAREDSTATEMENT INTERFACE |
143 | // |
144 | ///////////////////////////////////////////////////////////// |
145 | |
146 | /** |
147 | * Load up the class from the saved bytes. |
148 | * |
149 | * @exception StandardException on error |
150 | */ |
151 | public void loadGeneratedClass() |
152 | throws StandardException |
153 | { |
154 | LanguageConnectionContext lcc = |
155 | (LanguageConnectionContext) ContextService.getContext |
156 | (LanguageConnectionContext.CONTEXT_ID); |
157 | ClassFactory classFactory = lcc.getLanguageConnectionFactory().getClassFactory(); |
158 | |
159 | GeneratedClass gc = classFactory.loadGeneratedClass(className, byteCode); |
160 | |
161 | /* |
162 | ** No special try catch logic to write out bad classes |
163 | ** here. We don't expect any problems, and in any |
164 | ** event, we don't have the class builder available |
165 | ** here. |
166 | */ |
167 | setActivationClass(gc); |
168 | } |
169 | |
170 | |
171 | ///////////////////////////////////////////////////////////// |
172 | // |
173 | // EXTERNALIZABLE INTERFACE |
174 | // |
175 | ///////////////////////////////////////////////////////////// |
176 | /** |
177 | * |
178 | * @exception IOException on error |
179 | */ |
180 | public void writeExternal(ObjectOutput out) throws IOException |
181 | { |
182 | out.writeObject(getCursorInfo()); |
183 | out.writeBoolean(needsSavepoint()); |
184 | out.writeBoolean(isAtomic); |
185 | out.writeObject(executionConstants); |
186 | out.writeObject(resultDesc); |
187 | |
188 | // savedObjects may be null |
189 | if (savedObjects == null) |
190 | { |
191 | out.writeBoolean(false); |
192 | } |
193 | else |
194 | { |
195 | out.writeBoolean(true); |
196 | ArrayUtil.writeArrayLength(out, savedObjects); |
197 | ArrayUtil.writeArrayItems(out, savedObjects); |
198 | } |
199 | |
200 | /* |
201 | ** Write out the class name and byte code |
202 | ** if we have them. They might be null if |
203 | ** we don't want to write out the plan, and |
204 | ** would prefer it just write out null (e.g. |
205 | ** we know the plan is invalid). |
206 | */ |
207 | out.writeObject(className); |
208 | out.writeBoolean(byteCode != null); |
209 | if (byteCode != null) |
210 | byteCode.writeExternal(out); |
211 | } |
212 | |
213 | |
214 | /** |
215 | * @see java.io.Externalizable#readExternal |
216 | * |
217 | * @exception IOException on error |
218 | * @exception ClassNotFoundException on error |
219 | */ |
220 | public void readExternal(ObjectInput in) |
221 | throws IOException, ClassNotFoundException |
222 | { |
223 | setCursorInfo((CursorInfo)in.readObject()); |
224 | setNeedsSavepoint(in.readBoolean()); |
225 | isAtomic = (in.readBoolean()); |
226 | executionConstants = (ConstantAction) in.readObject(); |
227 | resultDesc = (ResultDescription) in.readObject(); |
228 | |
229 | if (in.readBoolean()) |
230 | { |
231 | savedObjects = new Object[ArrayUtil.readArrayLength(in)]; |
232 | ArrayUtil.readArrayItems(in, savedObjects); |
233 | } |
234 | |
235 | className = (String)in.readObject(); |
236 | if (in.readBoolean()) { |
237 | byteCode = new ByteArray(); |
238 | byteCode.readExternal(in); |
239 | } |
240 | else |
241 | byteCode = null; |
242 | } |
243 | |
244 | ///////////////////////////////////////////////////////////// |
245 | // |
246 | // FORMATABLE INTERFACE |
247 | // |
248 | ///////////////////////////////////////////////////////////// |
249 | /** |
250 | * Get the formatID which corresponds to this class. |
251 | * |
252 | * @return the formatID of this class |
253 | */ |
254 | public int getTypeFormatId() { return StoredFormatIds.STORABLE_PREPARED_STATEMENT_V01_ID; } |
255 | |
256 | ///////////////////////////////////////////////////////////// |
257 | // |
258 | // MISC |
259 | // |
260 | ///////////////////////////////////////////////////////////// |
261 | public boolean isStorable() { |
262 | return true; |
263 | } |
264 | public String toString() |
265 | { |
266 | if (SanityManager.DEBUG) |
267 | { |
268 | String acn; |
269 | if (activationClass ==null) |
270 | acn = "null"; |
271 | else |
272 | acn = activationClass.getName(); |
273 | |
274 | return "GSPS " + System.identityHashCode(this) + " activationClassName="+acn+" className="+className; |
275 | } |
276 | else |
277 | { |
278 | return ""; |
279 | } |
280 | } |
281 | } |