Source code: org/apache/derby/impl/sql/GenericActivationHolder.java
1 /*
2
3 Derby - Class org.apache.derby.impl.sql.GenericActivationHolder
4
5 Copyright 1997, 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.sql.conn.LanguageConnectionContext;
24
25 import org.apache.derby.iapi.types.DataValueFactory;
26
27 import org.apache.derby.iapi.sql.execute.ExecPreparedStatement;
28 import org.apache.derby.iapi.sql.execute.ExecRow;
29 import org.apache.derby.iapi.sql.execute.ExecutionFactory;
30 import org.apache.derby.iapi.sql.execute.NoPutResultSet;
31 import org.apache.derby.iapi.sql.execute.ConstantAction;
32
33 import org.apache.derby.impl.sql.execute.BaseActivation;
34
35 import org.apache.derby.iapi.types.DataTypeDescriptor;
36 import org.apache.derby.iapi.sql.ParameterValueSet;
37 import org.apache.derby.iapi.sql.ResultSet;
38 import org.apache.derby.iapi.sql.ResultDescription;
39 import org.apache.derby.iapi.sql.Activation;
40 import org.apache.derby.iapi.sql.execute.CursorResultSet;
41 import org.apache.derby.iapi.sql.execute.TemporaryRowHolder;
42
43 import org.apache.derby.iapi.sql.dictionary.IndexRowGenerator;
44 import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
45
46 import org.apache.derby.iapi.reference.SQLState;
47
48 import org.apache.derby.iapi.error.StandardException;
49
50 import org.apache.derby.iapi.services.loader.GeneratedClass;
51 import org.apache.derby.iapi.services.context.Context;
52
53 import org.apache.derby.iapi.store.access.ConglomerateController;
54 import org.apache.derby.iapi.store.access.ScanController;
55
56 import org.apache.derby.iapi.types.RowLocation;
57
58 import org.apache.derby.iapi.services.sanity.SanityManager;
59
60 import org.apache.derby.iapi.store.access.TransactionController;
61
62 import java.sql.SQLWarning;
63 import java.util.Enumeration;
64 import java.util.Vector;
65 import java.util.Hashtable;
66
67 /**
68 * This class holds an Activation, and passes through most of the calls
69 * to the activation. The purpose of this class is to allow a PreparedStatement
70 * to be recompiled without the caller having to detect this and get a new
71 * activation.
72 *
73 * In addition to the Activation, this class holds a reference to the
74 * PreparedStatement that created it, along with a reference to the
75 * GeneratedClass that was associated with the PreparedStatement at the time
76 * this holder was created. These references are used to validate the
77 * Activation, to ensure that an activation is used only with the
78 * PreparedStatement that created it, and to detect when recompilation has
79 * happened.
80 *
81 * We detect recompilation by checking whether the GeneratedClass has changed.
82 * If it has, we try to let the caller continue to use this ActivationHolder.
83 * We create a new instance of the new GeneratedClass (that is, we create a
84 * new Activation), and we compare the number and type of parameters. If these
85 * are compatible, we copy the parameters from the old to the new Activation.
86 * If they are not compatible, we throw an exception telling the user that
87 * the Activation is out of date, and they need to get a new one.
88 *
89 * @author Jeff Lichtman
90 */
91
92 final class GenericActivationHolder implements Activation
93 {
94 BaseActivation ac;
95 ExecPreparedStatement ps;
96 GeneratedClass gc;
97 DataTypeDescriptor[] paramTypes;
98 private final LanguageConnectionContext lcc;
99
100 /**
101 * Constructor for an ActivationHolder
102 *
103 * @param gc The GeneratedClass of the Activation
104 * @param ps The PreparedStatement this ActivationHolder is associated
105 * with
106 *
107 * @exception StandardException Thrown on error
108 */
109 GenericActivationHolder(LanguageConnectionContext lcc, GeneratedClass gc, ExecPreparedStatement ps, boolean scrollable)
110 throws StandardException
111 {
112 this.lcc = lcc;
113 if (SanityManager.DEBUG)
114 {
115 SanityManager.ASSERT(gc != null, "generated class is null , ps is a " + ps.getClass());
116 }
117
118 this.gc = gc;
119 this.ps = ps;
120
121 ac = (BaseActivation) gc.newInstance(lcc);
122 ac.setupActivation(ps, scrollable);
123 paramTypes = ps.getParameterTypes();
124 }
125
126 /* Activation interface */
127
128 /**
129 * @see Activation#reset
130 *
131 * @exception StandardException thrown on failure
132 */
133 public void reset() throws StandardException
134 {
135 ac.reset();
136 }
137
138 /**
139 * Temporary tables can be declared with ON COMMIT DELETE ROWS. But if the table has a held curosr open at
140 * commit time, data should not be deleted from the table. This method, (gets called at commit time) checks if this
141 * activation held cursor and if so, does that cursor reference the passed temp table name.
142 *
143 * @return true if this activation has held cursor and if it references the passed temp table name
144 */
145 public boolean checkIfThisActivationHasHoldCursor(String tableName)
146 {
147 return ac.checkIfThisActivationHasHoldCursor(tableName);
148 }
149
150 /**
151 * @see Activation#setCursorName
152 *
153 */
154 public void setCursorName(String cursorName)
155 {
156 ac.setCursorName(cursorName);
157 }
158
159 /**
160 * @see Activation#getCursorName
161 */
162 public String getCursorName()
163 {
164 return ac.getCursorName();
165 }
166
167 /**
168 * @see Activation#setResultSetHoldability
169 *
170 */
171 public void setResultSetHoldability(boolean resultSetHoldability)
172 {
173 ac.setResultSetHoldability(resultSetHoldability);
174 }
175
176 /**
177 * @see Activation#getResultSetHoldability
178 */
179 public boolean getResultSetHoldability()
180 {
181 return ac.getResultSetHoldability();
182 }
183
184 /** @see Activation#setAutoGeneratedKeysResultsetInfo */
185 public void setAutoGeneratedKeysResultsetInfo(int[] columnIndexes, String[] columnNames)
186 {
187 ac.setAutoGeneratedKeysResultsetInfo(columnIndexes, columnNames);
188 }
189
190 /** @see Activation#getAutoGeneratedKeysResultsetMode */
191 public boolean getAutoGeneratedKeysResultsetMode()
192 {
193 return ac.getAutoGeneratedKeysResultsetMode();
194 }
195
196 /** @see Activation#getAutoGeneratedKeysColumnIndexes */
197 public int[] getAutoGeneratedKeysColumnIndexes()
198 {
199 return ac.getAutoGeneratedKeysColumnIndexes();
200 }
201
202 /** @see Activation#getAutoGeneratedKeysColumnNames */
203 public String[] getAutoGeneratedKeysColumnNames()
204 {
205 return ac.getAutoGeneratedKeysColumnNames();
206 }
207
208 /** @see org.apache.derby.iapi.sql.Activation#getLanguageConnectionContext */
209 public LanguageConnectionContext getLanguageConnectionContext()
210 {
211 return lcc;
212 }
213
214 public TransactionController getTransactionController()
215 {
216 return ac.getTransactionController();
217 }
218
219 /** @see Activation#getExecutionFactory */
220 public ExecutionFactory getExecutionFactory()
221 {
222 return ac.getExecutionFactory();
223 }
224
225 /**
226 * @see Activation#getParameterValueSet
227 */
228 public ParameterValueSet getParameterValueSet()
229 {
230 return ac.getParameterValueSet();
231 }
232
233 /**
234 * @see Activation#setParameters
235 */
236 public void setParameters(ParameterValueSet parameterValues, DataTypeDescriptor[] parameterTypes) throws StandardException
237 {
238 ac.setParameters(parameterValues, parameterTypes);
239 }
240
241 /**
242 * @see Activation#execute
243 *
244 * @exception StandardException Thrown on failure
245 */
246 public ResultSet execute() throws StandardException
247 {
248 /*
249 ** Synchronize to avoid problems if another thread is preparing
250 ** the statement at the same time we're trying to execute it.
251 */
252 // synchronized (ps)
253 {
254 /* Has the activation class changed? */
255 if (gc != ps.getActivationClass())
256 {
257
258 // ensure the statement is valid by rePreparing it.
259 ps.rePrepare(getLanguageConnectionContext());
260
261 /*
262 ** If we get here, it means the PreparedStatement has been
263 ** recompiled. Get a new Activation and check whether the
264 ** parameters are compatible. If so, transfer the parameters
265 ** from the old Activation to the new one, and make that the
266 ** current Activation. If not, throw an exception.
267 */
268 GeneratedClass newGC = ps.getActivationClass();
269
270 BaseActivation newAC = (BaseActivation) newGC.newInstance(lcc);
271
272 DataTypeDescriptor[] newParamTypes = ps.getParameterTypes();
273
274 /*
275 ** Link the new activation to the prepared statement.
276 */
277 newAC.setupActivation(ps, ac.getScrollable());
278
279 newAC.setParameters(ac.getParameterValueSet(), paramTypes);
280
281
282 /*
283 ** IMPORTANT
284 **
285 ** Copy any essential state from the old activation
286 ** to the new activation. This must match the state
287 ** setup in EmbedStatement.
288 ** singleExecution, cursorName, holdability, maxRows.
289 */
290
291 if (ac.isSingleExecution())
292 newAC.setSingleExecution();
293
294 newAC.setCursorName(ac.getCursorName());
295
296 newAC.setResultSetHoldability(ac.getResultSetHoldability());
297 if (ac.getAutoGeneratedKeysResultsetMode()) //Need to do copy only if auto generated mode is on
298 newAC.setAutoGeneratedKeysResultsetInfo(ac.getAutoGeneratedKeysColumnIndexes(),
299 ac.getAutoGeneratedKeysColumnNames());
300 newAC.setMaxRows(ac.getMaxRows());
301
302 // break the link with the prepared statement
303 ac.setupActivation(null, false);
304 ac.close();
305
306 /* Remember the new class information */
307 ac = newAC;
308 gc = newGC;
309 paramTypes = newParamTypes;
310 }
311 }
312
313 String cursorName = ac.getCursorName();
314 if (cursorName != null)
315 {
316 // have to see if another activation is open
317 // with the same cursor name. If so we can't use this name
318
319 Activation activeCursor = lcc.lookupCursorActivation(cursorName);
320
321 if ((activeCursor != null) && (activeCursor != ac)) {
322 throw StandardException.newException(SQLState.LANG_CURSOR_ALREADY_EXISTS, cursorName);
323 }
324 }
325
326 return ac.execute();
327 }
328
329 /**
330 * @see Activation#getResultSet
331 *
332 * @return the current ResultSet of this activation.
333 */
334 public ResultSet getResultSet()
335 {
336 return ac.getResultSet();
337 }
338
339 /**
340 * @see Activation#clearResultSet
341 */
342 public void clearResultSet()
343 {
344 ac.clearResultSet();
345 }
346
347 /**
348 * @see Activation#setCurrentRow
349 *
350 */
351 public void setCurrentRow(ExecRow currentRow, int resultSetNumber)
352 {
353 ac.setCurrentRow(currentRow, resultSetNumber);
354 }
355
356 /**
357 * @see Activation#clearCurrentRow
358 */
359 public void clearCurrentRow(int resultSetNumber)
360 {
361 ac.clearCurrentRow(resultSetNumber);
362 }
363
364 /**
365 * @see Activation#getPreparedStatement
366 */
367 public ExecPreparedStatement getPreparedStatement()
368 {
369 return ps;
370 }
371
372 public void checkStatementValidity() throws StandardException {
373 ac.checkStatementValidity();
374 }
375
376 /**
377 * @see Activation#getResultDescription
378 */
379 public ResultDescription getResultDescription()
380 {
381 return ac.getResultDescription();
382 }
383
384 /**
385 * @see Activation#getDataValueFactory
386 */
387 public DataValueFactory getDataValueFactory()
388 {
389 return ac.getDataValueFactory();
390 }
391
392 /**
393 * @see Activation#getRowLocationTemplate
394 */
395 public RowLocation getRowLocationTemplate(int itemNumber)
396 {
397 return ac.getRowLocationTemplate(itemNumber);
398 }
399
400 /**
401 * @see Activation#getHeapConglomerateController
402 */
403 public ConglomerateController getHeapConglomerateController()
404 {
405 return ac.getHeapConglomerateController();
406 }
407
408 /**
409 * @see Activation#setHeapConglomerateController
410 */
411 public void setHeapConglomerateController(ConglomerateController updateHeapCC)
412 {
413 ac.setHeapConglomerateController(updateHeapCC);
414 }
415
416 /**
417 * @see Activation#clearHeapConglomerateController
418 */
419 public void clearHeapConglomerateController()
420 {
421 ac.clearHeapConglomerateController();
422 }
423
424 /**
425 * @see Activation#getIndexScanController
426 */
427 public ScanController getIndexScanController()
428 {
429 return ac.getIndexScanController();
430 }
431
432 /**
433 * @see Activation#setIndexScanController
434 */
435 public void setIndexScanController(ScanController indexSC)
436 {
437 ac.setIndexScanController(indexSC);
438 }
439
440 /**
441 * @see Activation#getIndexConglomerateNumber
442 */
443 public long getIndexConglomerateNumber()
444 {
445 return ac.getIndexConglomerateNumber();
446 }
447
448 /**
449 * @see Activation#setIndexConglomerateNumber
450 */
451 public void setIndexConglomerateNumber(long indexConglomerateNumber)
452 {
453 ac.setIndexConglomerateNumber(indexConglomerateNumber);
454 }
455
456 /**
457 * @see Activation#clearIndexScanInfo
458 */
459 public void clearIndexScanInfo()
460 {
461 ac.clearIndexScanInfo();
462 }
463
464 /**
465 * @see Activation#close
466 *
467 * @exception StandardException Thrown on error
468 */
469 public void close() throws StandardException
470 {
471 ac.close();
472 }
473
474 /**
475 * @see Activation#isClosed
476 */
477 public boolean isClosed()
478 {
479 return ac.isClosed();
480 }
481
482 /**
483 Set the activation for a single execution.
484
485 @see Activation#setSingleExecution
486 */
487 public void setSingleExecution() {
488 ac.setSingleExecution();
489 }
490
491 /**
492 Is the activation set up for a single execution.
493
494 @see Activation#isSingleExecution
495 */
496 public boolean isSingleExecution() {
497 return ac.isSingleExecution();
498 }
499
500 /**
501 Get the number of subqueries in the entire query.
502 @return int The number of subqueries in the entire query.
503 */
504 public int getNumSubqueries() {
505 return ac.getNumSubqueries();
506 }
507
508 /**
509 * @see Activation#setForCreateTable()
510 */
511 public void setForCreateTable()
512 {
513 ac.setForCreateTable();
514 }
515
516 /**
517 * @see Activation#getForCreateTable()
518 */
519 public boolean getForCreateTable()
520 {
521 return ac.getForCreateTable();
522 }
523
524 /**
525 * @see Activation#setDDLTableDescriptor
526 */
527 public void setDDLTableDescriptor(TableDescriptor td)
528 {
529 ac.setDDLTableDescriptor(td);
530 }
531
532 /**
533 * @see Activation#getDDLTableDescriptor
534 */
535 public TableDescriptor getDDLTableDescriptor()
536 {
537 return ac.getDDLTableDescriptor();
538 }
539
540 /**
541 * @see Activation#setMaxRows
542 */
543 public void setMaxRows(int maxRows)
544 {
545 ac.setMaxRows(maxRows);
546 }
547
548 /**
549 * @see Activation#getMaxRows
550 */
551 public int getMaxRows()
552 {
553 return ac.getMaxRows();
554 }
555
556 public void setTargetVTI(java.sql.ResultSet targetVTI)
557 {
558 ac.setTargetVTI(targetVTI);
559 }
560
561 public java.sql.ResultSet getTargetVTI()
562 {
563 return ac.getTargetVTI();
564 }
565
566 /* Class implementation */
567
568
569 /**
570 * Mark the activation as unused.
571 */
572 public void markUnused()
573 {
574 ac.markUnused();
575 }
576
577 /**
578 * Is the activation in use?
579 *
580 * @return true/false
581 */
582 public boolean isInUse()
583 {
584 return ac.isInUse();
585 }
586 /**
587 @see org.apache.derby.iapi.sql.Activation#addWarning
588 */
589 public void addWarning(SQLWarning w)
590 {
591 ac.addWarning(w);
592 }
593
594 /**
595 @see org.apache.derby.iapi.sql.Activation#getWarnings
596 */
597 public SQLWarning getWarnings()
598 {
599 return ac.getWarnings();
600 }
601
602 /**
603 @see org.apache.derby.iapi.sql.Activation#clearWarnings
604 */
605 public void clearWarnings()
606 {
607 ac.clearWarnings();
608 }
609
610 /**
611 @see Activation#informOfRowCount
612 @exception StandardException Thrown on error
613 */
614 public void informOfRowCount(NoPutResultSet resultSet, long rowCount)
615 throws StandardException
616 {
617 ac.informOfRowCount(resultSet, rowCount);
618 }
619
620 /**
621 * @see Activation#isCursorActivation
622 */
623 public boolean isCursorActivation()
624 {
625 return ac.isCursorActivation();
626 }
627
628 public ConstantAction getConstantAction() {
629 return ac.getConstantAction();
630 }
631
632 public void setParentResultSet(TemporaryRowHolder rs, String resultSetId)
633 {
634 ac.setParentResultSet(rs, resultSetId);
635 }
636
637
638 public Vector getParentResultSet(String resultSetId)
639 {
640 return ac.getParentResultSet(resultSetId);
641 }
642
643 public void clearParentResultSets()
644 {
645 ac.clearParentResultSets();
646 }
647
648 public Hashtable getParentResultSets()
649 {
650 return ac.getParentResultSets();
651 }
652
653 public void setForUpdateIndexScan(CursorResultSet forUpdateResultSet)
654 {
655 ac.setForUpdateIndexScan(forUpdateResultSet);
656 }
657
658 public CursorResultSet getForUpdateIndexScan()
659 {
660 return ac.getForUpdateIndexScan();
661 }
662
663 public java.sql.ResultSet[][] getDynamicResults() {
664 return ac.getDynamicResults();
665 }
666 public int getMaxDynamicResults() {
667 return ac.getMaxDynamicResults();
668 }
669
670 }