📄 genericlanguageconnectioncontext.java
字号:
* @exception StandardException thrown if lookup goes wrong. * @return the prepared statement for the given string, null * if none was found. */ public PreparedStatement lookupStatement(GenericStatement statement) throws StandardException { if (statementCache == null) return null; // statement caching disable when in DDL mode if (dataDictionaryInWriteMode()) { return null; } Cacheable cachedItem = statementCache.find(statement); CachedStatement cs = (CachedStatement) cachedItem; GenericPreparedStatement ps = cs.getPreparedStatement(); synchronized (ps) { if (ps.upToDate()) { GeneratedClass ac = ps.getActivationClass(); // Check to see if the statement was prepared before some change // in the class loading set. If this is the case then force it to be invalid int currentClasses = getLanguageConnectionFactory().getClassFactory().getClassLoaderVersion(); if (ac.getClassLoaderVersion() != currentClasses) { ps.makeInvalid(DependencyManager.INTERNAL_RECOMPILE_REQUEST, this); } // note that the PreparedStatement is not kept in the cache. This is because // having items kept in the cache that ultimately are held onto by // user code is impossible to manage. E.g. an open ResultSet would hold onto // a PreparedStatement (through its activation) and the user can allow // this object to be garbage collected. Pushing a context stack is impossible // in garbage collection as it may deadlock with the open connection and // the context manager assumes a singel current thread per context stack } } statementCache.release(cachedItem); return ps; } /** Get a connection unique system generated name for a cursor. */ public String getUniqueCursorName() { return getNameString("SQLCUR", nextCursorId++); } /** Get a connection unique system generated name for an unnamed savepoint. */ public String getUniqueSavepointName() { return getNameString("SAVEPT", nextSavepointId++); } /** Get a connection unique system generated id for an unnamed savepoint. */ public int getUniqueSavepointID() { return nextSavepointId-1; } /** * Build a String for a statement name. * * @param prefix The prefix for the statement name. * @param number The number to append for uniqueness * * @return A unique String for a statement name. */ private String getNameString(String prefix, long number) { if (sb != null) { sb.setLength(0); } else { sb = new StringBuffer(); } sb.append(prefix).append(number); return sb.toString(); } /** * Do a commit as appropriate for an internally generated * commit (e.g. as needed by sync, or autocommit). * * @param commitStore true if we should commit the Store transaction * * @exception StandardException thrown on failure */ public void internalCommit(boolean commitStore) throws StandardException { doCommit(commitStore, true, NON_XA, false); } /** * Do a commmit as is appropriate for a user requested * commit (e.g. a java.sql.Connection.commit() or a language * 'COMMIT' statement. Does some extra checking to make * sure that users aren't doing anything bad. * * @exception StandardException thrown on failure */ public void userCommit() throws StandardException { doCommit(true, true, NON_XA, true); } /** Commit the language transaction by doing a commitNoSync() on the store's TransactionController. <p> Do *NOT* tell the data dictionary that the transaction is finished. The reason is that this would allow other transactions to see comitted DDL that could be undone in the event of a system crash. @param commitflag the flags to pass to commitNoSync in the store's TransactionController @exception StandardException thrown on failure */ public final void internalCommitNoSync(int commitflag) throws StandardException { doCommit(true, false, commitflag, false); } /** Same as userCommit except commit a distributed transaction. This commit always commit store and sync the commit. @param onePhase if true, allow it to commit without first going thru a prepared state. @return the commit instant @exception StandardException thrown if something goes wrong */ public final void xaCommit(boolean onePhase) throws StandardException { // further overload internalCommit to make it understand 2 phase commit doCommit(true /* commit store */, true /* sync */, onePhase ? XA_ONE_PHASE : XA_TWO_PHASE, true); } /** * This is where the work on internalCommit(), userCOmmit() and * internalCommitNoSync() actually takes place. * <p> * When a commit happens, the language connection context * will close all open activations/cursors and commit the * Store transaction. * <p> * REVISIT: we talked about having a LanguageTransactionContext, * but since store transaction management is currently in flux * and our context might want to delegate to that context, * for now all commit/rollback actions are handled directly by * the language connection context. * REVISIT: this may need additional alterations when * RELEASE SAVEPOINT/ROLLBACK TO SAVEPOINT show up. * <P> * Since the access manager's own context takes care of its own * resources on commit, and the transaction stays open, there is * nothing that this context has to do with the transaction controller. * <p> * Also, tell the data dictionary that the transaction is finished, * if necessary (that is, if the data dictionary was put into * DDL mode in this transaction. * * * @param commitStore true if we should commit the Store transaction * @param sync true means do a synchronized commit, * false means do an unsynchronized commit * @param commitflag if this is an unsynchronized commit, the flags to * pass to commitNoSync in the store's * TransactionController. If this is a synchronized * commit, this flag is overloaded for xacommit. * @param requestedByUser False iff the commit is for internal use and * we should ignore the check to prevent commits * in an atomic statement. * * @exception StandardException Thrown on error */ protected void doCommit(boolean commitStore, boolean sync, int commitflag, boolean requestedByUser) throws StandardException { StatementContext statementContext = getStatementContext(); if (requestedByUser && (statementContext != null) && statementContext.inUse() && statementContext.isAtomic()) { throw StandardException.newException(SQLState.LANG_NO_COMMIT_IN_NESTED_CONNECTION); } // Log commit to error log, if appropriate if (logStatementText) { if (istream == null) { istream = Monitor.getStream(); } String xactId = tran.getTransactionIdString(); istream.printlnWithHeader(LanguageConnectionContext.xidStr + xactId + "), " + LanguageConnectionContext.lccStr + instanceNumber + "), " + LanguageConnectionContext.dbnameStr + dbname + "), " + LanguageConnectionContext.drdaStr + drdaID + "), Committing"); } resetActivations(false); //do the clean up work required for temporary tables at the commit time. This cleanup work //can possibly remove entries from allDeclaredGlobalTempTables and that's why we need to check //again later to see if we there are still any entries in allDeclaredGlobalTempTables if (allDeclaredGlobalTempTables != null) { tempTablesAndCommit(); //at commit time, for all the temp tables declared with ON COMMIT DELETE ROWS, make sure there are no held cursor open on them. //If there are no held cursors open on ON COMMIT DELETE ROWS, drop those temp tables and redeclare them to get rid of all the data in them if (allDeclaredGlobalTempTables != null) { for (int i=0; i<allDeclaredGlobalTempTables.size(); i++) { TableDescriptor td = ((TempTableInfo)(allDeclaredGlobalTempTables.get(i))).getTableDescriptor(); if (td.isOnCommitDeleteRows() == false) //do nothing for temp table with ON COMMIT PRESERVE ROWS { continue; } if (checkIfAnyActivationHasHoldCursor(td.getName()) == false)//temp tables with ON COMMIT DELETE ROWS and no open held cursors { getDataDictionary().getDependencyManager().invalidateFor(td, DependencyManager.DROP_TABLE, this); cleanupTempTableOnCommitOrRollback(td, true); } } } } currentSavepointLevel = 0; //reset the current savepoint level for the connection to 0 at the end of commit work for temp tables // Do *NOT* tell the DataDictionary to start using its cache again // if this is an unsynchronized commit. The reason is that it // would allow other transactions to see this transaction's DDL, // which could be rolled back in case of a system crash. if (sync) { finishDDTransaction(); } // now commit the Store transaction TransactionController tc = getTransactionExecute(); if ( tc != null && commitStore ) { if (sync) { if (commitflag == NON_XA) { // regular commit tc.commit(); } else { // This may be a xa_commit, check overloaded commitflag. if (SanityManager.DEBUG) SanityManager.ASSERT(commitflag == XA_ONE_PHASE || commitflag == XA_TWO_PHASE, "invalid commit flag"); ((XATransactionController)tc).xa_commit(commitflag == XA_ONE_PHASE); } } else { tc.commitNoSync(commitflag); } // reset the savepoints to the new // location, since any outer nesting // levels expect there to be a savepoint resetSavepoints(statementContext); } } /** * If dropAndRedeclare is true, that means we have come here for temp tables with on commit delete rows * and no held curosr open on them. We will drop the existing conglomerate and redeclare a new conglomerate * similar to old conglomerate. This is a more efficient way of deleting all rows from the table. * * If dropAndRedeclare is false, that means we have come here for the rollback cleanup work. We are trying * to restore old definition of the temp table (because the drop on it is being rolled back). */ private TableDescriptor cleanupTempTableOnCommitOrRollback(TableDescriptor td, boolean dropAndRedeclare) throws StandardException { //create new conglomerate with same properties as the old conglomerate and same row template as the old conglomerate long conglomId = tran.createConglomerate( "heap", // we're requesting a heap conglomerate td.getEmptyExecRow(getContextManager()).getRowArray(), // row template null, //column sort order - not required for heap null, // properties (TransactionController.IS_TEMPORARY | TransactionController.IS_KEPT)); long cid = td.getHeapConglomerateId(); //remove the old conglomerate descriptor from the table descriptor ConglomerateDescriptor cgd = td.getConglomerateDescriptor(cid); td.getConglomerateDescriptorList().dropConglomerateDescriptorByUUID(cgd.getUUID()); //add the new conglomerate descriptor to the table descriptor cgd = getDataDictionary().getDataDescriptorGenerator().newConglomerateDescriptor(conglomId, null, false, null, false, null, td.getUUID(), td.getSchemaDescriptor().getUUID()); ConglomerateDescriptorList conglomList = td.getConglomerateDescriptorList(); conglomList.add(cgd); //reset the heap conglomerate number in table descriptor to -1 so it will be refetched next time with the new value td.resetHeapConglomNumber(); if(dropAndRedeclare) { tran.dropConglomerate(cid); //remove the old conglomerate from the system replaceDeclaredGlobalTempTable(td.getName(), td); } return(td); } /** Do a rollback as appropriate for an internally generated rollback (e.g. as needed by sync, or autocommit). When a rollback happens, we close all open activations and invalidate their prepared statements. We then tell the cache to age out everything else, which effectively invalidates them. Thus, all prepared statements will be compiled anew on their 1st execution after a rollback. <p> The invalidated statements can revalidate themselves without a full recompile if they verify their dependencies' providers still exist unchanged. REVISIT when invalidation types are created. <p> REVISIT: this may need additional alterations when RELEASE SAVEPOINT/ROLLBACK TO SAVEPOINT show up. <p> Also, tell the data dictionary that the transaction is finished, if necessary (that is, if the data dictionary was put into DDL mode in this transaction. @exception StandardException thrown on failure */ public void internalRollback() throws StandardException { doRollback(false /* non-xa */, false); } /** * Do a rollback as is appropriate for a user requested * rollback (e.g. a java.sql.Connection.rollback() or a language * 'ROLLBACk' statement. Does some extra checking to make * sure that users aren't doing anything bad. * * @exception StandardException thrown on failure */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -