001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.GenericActivationHolder
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.sql;
023:
024: import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
025:
026: import org.apache.derby.iapi.types.DataValueFactory;
027:
028: import org.apache.derby.iapi.sql.execute.ExecPreparedStatement;
029: import org.apache.derby.iapi.sql.execute.ExecRow;
030: import org.apache.derby.iapi.sql.execute.ExecutionFactory;
031: import org.apache.derby.iapi.sql.execute.NoPutResultSet;
032: import org.apache.derby.iapi.sql.execute.ConstantAction;
033:
034: import org.apache.derby.impl.sql.execute.BaseActivation;
035:
036: import org.apache.derby.iapi.types.DataTypeDescriptor;
037: import org.apache.derby.iapi.sql.ParameterValueSet;
038: import org.apache.derby.iapi.sql.ResultSet;
039: import org.apache.derby.iapi.sql.ResultDescription;
040: import org.apache.derby.iapi.sql.Activation;
041: import org.apache.derby.iapi.sql.execute.CursorResultSet;
042: import org.apache.derby.iapi.sql.execute.TemporaryRowHolder;
043:
044: import org.apache.derby.iapi.sql.dictionary.IndexRowGenerator;
045: import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
046:
047: import org.apache.derby.iapi.reference.SQLState;
048:
049: import org.apache.derby.iapi.error.StandardException;
050:
051: import org.apache.derby.iapi.services.loader.GeneratedClass;
052: import org.apache.derby.iapi.services.context.Context;
053:
054: import org.apache.derby.iapi.store.access.ConglomerateController;
055: import org.apache.derby.iapi.store.access.ScanController;
056:
057: import org.apache.derby.iapi.types.RowLocation;
058:
059: import org.apache.derby.iapi.services.sanity.SanityManager;
060:
061: import org.apache.derby.iapi.store.access.TransactionController;
062:
063: import java.sql.SQLWarning;
064: import java.util.Enumeration;
065: import java.util.Vector;
066: import java.util.Hashtable;
067:
068: /**
069: * This class holds an Activation, and passes through most of the calls
070: * to the activation. The purpose of this class is to allow a PreparedStatement
071: * to be recompiled without the caller having to detect this and get a new
072: * activation.
073: *
074: * In addition to the Activation, this class holds a reference to the
075: * PreparedStatement that created it, along with a reference to the
076: * GeneratedClass that was associated with the PreparedStatement at the time
077: * this holder was created. These references are used to validate the
078: * Activation, to ensure that an activation is used only with the
079: * PreparedStatement that created it, and to detect when recompilation has
080: * happened.
081: *
082: * We detect recompilation by checking whether the GeneratedClass has changed.
083: * If it has, we try to let the caller continue to use this ActivationHolder.
084: * We create a new instance of the new GeneratedClass (that is, we create a
085: * new Activation), and we compare the number and type of parameters. If these
086: * are compatible, we copy the parameters from the old to the new Activation.
087: * If they are not compatible, we throw an exception telling the user that
088: * the Activation is out of date, and they need to get a new one.
089: *
090: * @author Jeff Lichtman
091: */
092:
093: final class GenericActivationHolder implements Activation {
094: BaseActivation ac;
095: ExecPreparedStatement ps;
096: GeneratedClass gc;
097: DataTypeDescriptor[] paramTypes;
098: private final LanguageConnectionContext lcc;
099:
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,
110: GeneratedClass gc, ExecPreparedStatement ps,
111: boolean scrollable) throws StandardException {
112: this .lcc = lcc;
113: if (SanityManager.DEBUG) {
114: SanityManager.ASSERT(gc != null,
115: "generated class is null , ps is a "
116: + ps.getClass());
117: }
118:
119: this .gc = gc;
120: this .ps = ps;
121:
122: ac = (BaseActivation) gc.newInstance(lcc);
123: ac.setupActivation(ps, scrollable);
124: paramTypes = ps.getParameterTypes();
125: }
126:
127: /* Activation interface */
128:
129: /**
130: * @see Activation#reset
131: *
132: * @exception StandardException thrown on failure
133: */
134: public void reset() throws StandardException {
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: return ac.checkIfThisActivationHasHoldCursor(tableName);
147: }
148:
149: /**
150: * @see Activation#setCursorName
151: *
152: */
153: public void setCursorName(String cursorName) {
154: ac.setCursorName(cursorName);
155: }
156:
157: /**
158: * @see Activation#getCursorName
159: */
160: public String getCursorName() {
161: return ac.getCursorName();
162: }
163:
164: /**
165: * @see Activation#setResultSetHoldability
166: *
167: */
168: public void setResultSetHoldability(boolean resultSetHoldability) {
169: ac.setResultSetHoldability(resultSetHoldability);
170: }
171:
172: /**
173: * @see Activation#getResultSetHoldability
174: */
175: public boolean getResultSetHoldability() {
176: return ac.getResultSetHoldability();
177: }
178:
179: /** @see Activation#setAutoGeneratedKeysResultsetInfo */
180: public void setAutoGeneratedKeysResultsetInfo(int[] columnIndexes,
181: String[] columnNames) {
182: ac
183: .setAutoGeneratedKeysResultsetInfo(columnIndexes,
184: columnNames);
185: }
186:
187: /** @see Activation#getAutoGeneratedKeysResultsetMode */
188: public boolean getAutoGeneratedKeysResultsetMode() {
189: return ac.getAutoGeneratedKeysResultsetMode();
190: }
191:
192: /** @see Activation#getAutoGeneratedKeysColumnIndexes */
193: public int[] getAutoGeneratedKeysColumnIndexes() {
194: return ac.getAutoGeneratedKeysColumnIndexes();
195: }
196:
197: /** @see Activation#getAutoGeneratedKeysColumnNames */
198: public String[] getAutoGeneratedKeysColumnNames() {
199: return ac.getAutoGeneratedKeysColumnNames();
200: }
201:
202: /** @see org.apache.derby.iapi.sql.Activation#getLanguageConnectionContext */
203: public LanguageConnectionContext getLanguageConnectionContext() {
204: return lcc;
205: }
206:
207: public TransactionController getTransactionController() {
208: return ac.getTransactionController();
209: }
210:
211: /** @see Activation#getExecutionFactory */
212: public ExecutionFactory getExecutionFactory() {
213: return ac.getExecutionFactory();
214: }
215:
216: /**
217: * @see Activation#getParameterValueSet
218: */
219: public ParameterValueSet getParameterValueSet() {
220: return ac.getParameterValueSet();
221: }
222:
223: /**
224: * @see Activation#setParameters
225: */
226: public void setParameters(ParameterValueSet parameterValues,
227: DataTypeDescriptor[] parameterTypes)
228: throws StandardException {
229: ac.setParameters(parameterValues, parameterTypes);
230: }
231:
232: /**
233: * @see Activation#execute
234: *
235: * @exception StandardException Thrown on failure
236: */
237: public ResultSet execute() throws StandardException {
238: /*
239: ** Synchronize to avoid problems if another thread is preparing
240: ** the statement at the same time we're trying to execute it.
241: */
242: // synchronized (ps)
243: {
244: /* Has the activation class changed? */
245: if (gc != ps.getActivationClass()) {
246:
247: // ensure the statement is valid by rePreparing it.
248: ps.rePrepare(getLanguageConnectionContext());
249:
250: /*
251: ** If we get here, it means the PreparedStatement has been
252: ** recompiled. Get a new Activation and check whether the
253: ** parameters are compatible. If so, transfer the parameters
254: ** from the old Activation to the new one, and make that the
255: ** current Activation. If not, throw an exception.
256: */
257: GeneratedClass newGC = ps.getActivationClass();
258:
259: BaseActivation newAC = (BaseActivation) newGC
260: .newInstance(lcc);
261:
262: DataTypeDescriptor[] newParamTypes = ps
263: .getParameterTypes();
264:
265: /*
266: ** Link the new activation to the prepared statement.
267: */
268: newAC.setupActivation(ps, ac.getScrollable());
269:
270: newAC.setParameters(ac.getParameterValueSet(),
271: paramTypes);
272:
273: /*
274: ** IMPORTANT
275: **
276: ** Copy any essential state from the old activation
277: ** to the new activation. This must match the state
278: ** setup in EmbedStatement.
279: ** singleExecution, cursorName, holdability, maxRows.
280: */
281:
282: if (ac.isSingleExecution())
283: newAC.setSingleExecution();
284:
285: newAC.setCursorName(ac.getCursorName());
286:
287: newAC.setResultSetHoldability(ac
288: .getResultSetHoldability());
289: if (ac.getAutoGeneratedKeysResultsetMode()) //Need to do copy only if auto generated mode is on
290: newAC.setAutoGeneratedKeysResultsetInfo(ac
291: .getAutoGeneratedKeysColumnIndexes(), ac
292: .getAutoGeneratedKeysColumnNames());
293: newAC.setMaxRows(ac.getMaxRows());
294:
295: // break the link with the prepared statement
296: ac.setupActivation(null, false);
297: ac.close();
298:
299: /* Remember the new class information */
300: ac = newAC;
301: gc = newGC;
302: paramTypes = newParamTypes;
303: }
304: }
305:
306: String cursorName = ac.getCursorName();
307: if (cursorName != null) {
308: // have to see if another activation is open
309: // with the same cursor name. If so we can't use this name
310:
311: Activation activeCursor = lcc
312: .lookupCursorActivation(cursorName);
313:
314: if ((activeCursor != null) && (activeCursor != ac)) {
315: throw StandardException
316: .newException(
317: SQLState.LANG_CURSOR_ALREADY_EXISTS,
318: cursorName);
319: }
320: }
321:
322: return ac.execute();
323: }
324:
325: /**
326: * @see Activation#getResultSet
327: *
328: * @return the current ResultSet of this activation.
329: */
330: public ResultSet getResultSet() {
331: return ac.getResultSet();
332: }
333:
334: /**
335: * @see Activation#clearResultSet
336: */
337: public void clearResultSet() {
338: ac.clearResultSet();
339: }
340:
341: /**
342: * @see Activation#setCurrentRow
343: *
344: */
345: public void setCurrentRow(ExecRow currentRow, int resultSetNumber) {
346: ac.setCurrentRow(currentRow, resultSetNumber);
347: }
348:
349: /**
350: * @see Activation#clearCurrentRow
351: */
352: public void clearCurrentRow(int resultSetNumber) {
353: ac.clearCurrentRow(resultSetNumber);
354: }
355:
356: /**
357: * @see Activation#getPreparedStatement
358: */
359: public ExecPreparedStatement getPreparedStatement() {
360: return ps;
361: }
362:
363: public void checkStatementValidity() throws StandardException {
364: ac.checkStatementValidity();
365: }
366:
367: /**
368: * @see Activation#getResultDescription
369: */
370: public ResultDescription getResultDescription() {
371: return ac.getResultDescription();
372: }
373:
374: /**
375: * @see Activation#getDataValueFactory
376: */
377: public DataValueFactory getDataValueFactory() {
378: return ac.getDataValueFactory();
379: }
380:
381: /**
382: * @see Activation#getRowLocationTemplate
383: */
384: public RowLocation getRowLocationTemplate(int itemNumber) {
385: return ac.getRowLocationTemplate(itemNumber);
386: }
387:
388: /**
389: * @see Activation#getHeapConglomerateController
390: */
391: public ConglomerateController getHeapConglomerateController() {
392: return ac.getHeapConglomerateController();
393: }
394:
395: /**
396: * @see Activation#setHeapConglomerateController
397: */
398: public void setHeapConglomerateController(
399: ConglomerateController updateHeapCC) {
400: ac.setHeapConglomerateController(updateHeapCC);
401: }
402:
403: /**
404: * @see Activation#clearHeapConglomerateController
405: */
406: public void clearHeapConglomerateController() {
407: ac.clearHeapConglomerateController();
408: }
409:
410: /**
411: * @see Activation#getIndexScanController
412: */
413: public ScanController getIndexScanController() {
414: return ac.getIndexScanController();
415: }
416:
417: /**
418: * @see Activation#setIndexScanController
419: */
420: public void setIndexScanController(ScanController indexSC) {
421: ac.setIndexScanController(indexSC);
422: }
423:
424: /**
425: * @see Activation#getIndexConglomerateNumber
426: */
427: public long getIndexConglomerateNumber() {
428: return ac.getIndexConglomerateNumber();
429: }
430:
431: /**
432: * @see Activation#setIndexConglomerateNumber
433: */
434: public void setIndexConglomerateNumber(long indexConglomerateNumber) {
435: ac.setIndexConglomerateNumber(indexConglomerateNumber);
436: }
437:
438: /**
439: * @see Activation#clearIndexScanInfo
440: */
441: public void clearIndexScanInfo() {
442: ac.clearIndexScanInfo();
443: }
444:
445: /**
446: * @see Activation#close
447: *
448: * @exception StandardException Thrown on error
449: */
450: public void close() throws StandardException {
451: ac.close();
452: }
453:
454: /**
455: * @see Activation#isClosed
456: */
457: public boolean isClosed() {
458: return ac.isClosed();
459: }
460:
461: /**
462: Set the activation for a single execution.
463:
464: @see Activation#setSingleExecution
465: */
466: public void setSingleExecution() {
467: ac.setSingleExecution();
468: }
469:
470: /**
471: Is the activation set up for a single execution.
472:
473: @see Activation#isSingleExecution
474: */
475: public boolean isSingleExecution() {
476: return ac.isSingleExecution();
477: }
478:
479: /**
480: Get the number of subqueries in the entire query.
481: @return int The number of subqueries in the entire query.
482: */
483: public int getNumSubqueries() {
484: return ac.getNumSubqueries();
485: }
486:
487: /**
488: * @see Activation#setForCreateTable()
489: */
490: public void setForCreateTable() {
491: ac.setForCreateTable();
492: }
493:
494: /**
495: * @see Activation#getForCreateTable()
496: */
497: public boolean getForCreateTable() {
498: return ac.getForCreateTable();
499: }
500:
501: /**
502: * @see Activation#setDDLTableDescriptor
503: */
504: public void setDDLTableDescriptor(TableDescriptor td) {
505: ac.setDDLTableDescriptor(td);
506: }
507:
508: /**
509: * @see Activation#getDDLTableDescriptor
510: */
511: public TableDescriptor getDDLTableDescriptor() {
512: return ac.getDDLTableDescriptor();
513: }
514:
515: /**
516: * @see Activation#setMaxRows
517: */
518: public void setMaxRows(int maxRows) {
519: ac.setMaxRows(maxRows);
520: }
521:
522: /**
523: * @see Activation#getMaxRows
524: */
525: public int getMaxRows() {
526: return ac.getMaxRows();
527: }
528:
529: public void setTargetVTI(java.sql.ResultSet targetVTI) {
530: ac.setTargetVTI(targetVTI);
531: }
532:
533: public java.sql.ResultSet getTargetVTI() {
534: return ac.getTargetVTI();
535: }
536:
537: /* Class implementation */
538:
539: /**
540: * Mark the activation as unused.
541: */
542: public void markUnused() {
543: ac.markUnused();
544: }
545:
546: /**
547: * Is the activation in use?
548: *
549: * @return true/false
550: */
551: public boolean isInUse() {
552: return ac.isInUse();
553: }
554:
555: /**
556: @see org.apache.derby.iapi.sql.Activation#addWarning
557: */
558: public void addWarning(SQLWarning w) {
559: ac.addWarning(w);
560: }
561:
562: /**
563: @see org.apache.derby.iapi.sql.Activation#getWarnings
564: */
565: public SQLWarning getWarnings() {
566: return ac.getWarnings();
567: }
568:
569: /**
570: @see org.apache.derby.iapi.sql.Activation#clearWarnings
571: */
572: public void clearWarnings() {
573: ac.clearWarnings();
574: }
575:
576: /**
577: @see Activation#informOfRowCount
578: @exception StandardException Thrown on error
579: */
580: public void informOfRowCount(NoPutResultSet resultSet, long rowCount)
581: throws StandardException {
582: ac.informOfRowCount(resultSet, rowCount);
583: }
584:
585: /**
586: * @see Activation#isCursorActivation
587: */
588: public boolean isCursorActivation() {
589: return ac.isCursorActivation();
590: }
591:
592: public ConstantAction getConstantAction() {
593: return ac.getConstantAction();
594: }
595:
596: public void setParentResultSet(TemporaryRowHolder rs,
597: String resultSetId) {
598: ac.setParentResultSet(rs, resultSetId);
599: }
600:
601: public Vector getParentResultSet(String resultSetId) {
602: return ac.getParentResultSet(resultSetId);
603: }
604:
605: public void clearParentResultSets() {
606: ac.clearParentResultSets();
607: }
608:
609: public Hashtable getParentResultSets() {
610: return ac.getParentResultSets();
611: }
612:
613: public void setForUpdateIndexScan(CursorResultSet forUpdateResultSet) {
614: ac.setForUpdateIndexScan(forUpdateResultSet);
615: }
616:
617: public CursorResultSet getForUpdateIndexScan() {
618: return ac.getForUpdateIndexScan();
619: }
620:
621: public java.sql.ResultSet[][] getDynamicResults() {
622: return ac.getDynamicResults();
623: }
624:
625: public int getMaxDynamicResults() {
626: return ac.getMaxDynamicResults();
627: }
628:
629: }
|