Source Code Cross Referenced for GenericLanguageConnectionContext.java in  » Database-DBMS » db-derby-10.2 » org » apache » derby » impl » sql » conn » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database DBMS » db derby 10.2 » org.apache.derby.impl.sql.conn 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:
0003:           Derby - Class org.apache.derby.impl.sql.conn.GenericLanguageConnectionContext
0004:
0005:           Licensed to the Apache Software Foundation (ASF) under one or more
0006:           contributor license agreements.  See the NOTICE file distributed with
0007:           this work for additional information regarding copyright ownership.
0008:           The ASF licenses this file to you under the Apache License, Version 2.0
0009:           (the "License"); you may not use this file except in compliance with
0010:           the License.  You may obtain a copy of the License at
0011:
0012:              http://www.apache.org/licenses/LICENSE-2.0
0013:
0014:           Unless required by applicable law or agreed to in writing, software
0015:           distributed under the License is distributed on an "AS IS" BASIS,
0016:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017:           See the License for the specific language governing permissions and
0018:           limitations under the License.
0019:
0020:         */
0021:
0022:        package org.apache.derby.impl.sql.conn;
0023:
0024:        import org.apache.derby.iapi.services.context.ContextImpl;
0025:        import org.apache.derby.iapi.services.cache.CacheManager;
0026:
0027:        import org.apache.derby.impl.sql.compile.CompilerContextImpl;
0028:        import org.apache.derby.impl.sql.execute.InternalTriggerExecutionContext;
0029:        import org.apache.derby.impl.sql.execute.AutoincrementCounter;
0030:        import org.apache.derby.impl.sql.GenericPreparedStatement;
0031:        import org.apache.derby.impl.sql.GenericStatement;
0032:        import org.apache.derby.iapi.sql.Statement;
0033:        import org.apache.derby.impl.sql.conn.CachedStatement;
0034:
0035:        import org.apache.derby.iapi.services.property.PropertyUtil;
0036:        import org.apache.derby.iapi.services.context.Context;
0037:        import org.apache.derby.iapi.services.context.ContextManager;
0038:        import org.apache.derby.iapi.services.monitor.Monitor;
0039:        import org.apache.derby.iapi.services.sanity.SanityManager;
0040:        import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
0041:        import org.apache.derby.iapi.services.loader.GeneratedClass;
0042:        import org.apache.derby.iapi.services.cache.Cacheable;
0043:        import org.apache.derby.iapi.db.Database;
0044:        import org.apache.derby.iapi.error.StandardException;
0045:        import org.apache.derby.iapi.sql.compile.CompilerContext;
0046:        import org.apache.derby.iapi.sql.compile.OptimizerFactory;
0047:        import org.apache.derby.iapi.sql.conn.Authorizer;
0048:        import org.apache.derby.iapi.error.ExceptionSeverity;
0049:        import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
0050:        import org.apache.derby.iapi.sql.conn.LanguageConnectionFactory;
0051:        import org.apache.derby.iapi.sql.conn.StatementContext;
0052:        import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
0053:        import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptorList;
0054:        import org.apache.derby.iapi.sql.dictionary.DataDictionary;
0055:        import org.apache.derby.iapi.sql.dictionary.DataDictionaryContext;
0056:        import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
0057:        import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
0058:        import org.apache.derby.iapi.types.DataValueFactory;
0059:        import org.apache.derby.iapi.sql.compile.TypeCompilerFactory;
0060:        import org.apache.derby.iapi.sql.depend.DependencyManager;
0061:        import org.apache.derby.iapi.sql.depend.Provider;
0062:        import org.apache.derby.iapi.reference.SQLState;
0063:        import org.apache.derby.iapi.reference.Limits;
0064:        import org.apache.derby.iapi.sql.execute.ConstantAction;
0065:        import org.apache.derby.iapi.sql.execute.CursorActivation;
0066:        import org.apache.derby.iapi.sql.execute.ExecPreparedStatement;
0067:        import org.apache.derby.iapi.sql.execute.ExecutionContext;
0068:        import org.apache.derby.iapi.sql.execute.ExecutionStmtValidator;
0069:        import org.apache.derby.iapi.sql.Activation;
0070:        import org.apache.derby.iapi.sql.LanguageFactory;
0071:        import org.apache.derby.iapi.sql.PreparedStatement;
0072:        import org.apache.derby.iapi.sql.ResultSet;
0073:        import org.apache.derby.iapi.sql.ParameterValueSet;
0074:
0075:        import org.apache.derby.iapi.store.access.TransactionController;
0076:        import org.apache.derby.iapi.store.access.AccessFactory;
0077:        import org.apache.derby.iapi.store.access.XATransactionController;
0078:        import org.apache.derby.iapi.util.IdUtil;
0079:        import org.apache.derby.iapi.util.StringUtil;
0080:
0081:        import org.apache.derby.catalog.UUID;
0082:        import org.apache.derby.iapi.sql.execute.RunTimeStatistics;
0083:        import org.apache.derby.iapi.db.TriggerExecutionContext;
0084:        import org.apache.derby.iapi.reference.Property;
0085:
0086:        import java.util.List;
0087:        import java.util.ArrayList;
0088:        import java.util.Enumeration;
0089:        import java.util.Hashtable;
0090:        import java.util.Properties;
0091:        import java.util.Vector;
0092:        import java.util.Stack;
0093:        import java.io.Serializable;
0094:
0095:        /**
0096:         * LanguageConnectionContext keeps the pool of prepared statements,
0097:         * activations, and cursors in use by the current connection.
0098:         * <p>
0099:         * The generic impl does not provide statement caching.
0100:         *
0101:         * @author ames
0102:         *
0103:         */
0104:        public class GenericLanguageConnectionContext extends ContextImpl
0105:                implements  LanguageConnectionContext {
0106:
0107:            // make sure these are not zeros
0108:            private final static int NON_XA = 0;
0109:            private final static int XA_ONE_PHASE = 1;
0110:            private final static int XA_TWO_PHASE = 2;
0111:
0112:            /*
0113:            	fields
0114:             */
0115:
0116:            private final Vector acts;
0117:            private volatile boolean unusedActs = false;
0118:            protected int bindCount;
0119:            private boolean ddWriteMode;
0120:            private boolean runTimeStatisticsSetting;
0121:            private boolean statisticsTiming;
0122:
0123:            //all the temporary tables declared for this connection
0124:            private ArrayList allDeclaredGlobalTempTables;
0125:            //The currentSavepointLevel is used to provide the rollback behavior of temporary tables.
0126:            //At any point, this variable has the total number of savepoints defined for the transaction.
0127:            private int currentSavepointLevel = 0;
0128:
0129:            protected long nextCursorId;
0130:
0131:            protected int nextSavepointId;
0132:
0133:            private RunTimeStatistics runTimeStatisticsObject;
0134:            private StringBuffer sb;
0135:
0136:            private Database db;
0137:
0138:            private final int instanceNumber;
0139:            private String drdaID;
0140:            private String dbname;
0141:
0142:            private int identifierCasing = UNKNOWN_CASING;
0143:
0144:            /**
0145:            The transaction to use within this language connection context.  It may
0146:            be more appropriate to have it in a separate context (LanguageTransactionContext?).
0147:            REVISIT (nat): I shoehorned the transaction context that
0148:            the language uses into this class.  The main purpose is so
0149:            that the various language code can find out what its
0150:            transaction is.
0151:             **/
0152:            protected TransactionController tran;
0153:
0154:            /**
0155:             * If non-null indicates that a nested user transaction is in progress.
0156:             */
0157:            protected TransactionController childTransaction;
0158:
0159:            /**
0160:             * queryNestingDepth is a counter used to keep track of how many calls 
0161:             * have been made to begin nested transactions. Only the first call 
0162:             * actually starts a Nested User Transaction with the store. Subsequent
0163:             * calls simply increment this counter. commitNestedTransaction only
0164:             * decrements the counter and when it drops to 0 actually commits the 
0165:             * nested user transaction.
0166:             */
0167:            protected int queryNestingDepth;
0168:
0169:            protected DataValueFactory dataFactory;
0170:            protected LanguageFactory langFactory;
0171:            protected TypeCompilerFactory tcf;
0172:            protected OptimizerFactory of;
0173:            protected LanguageConnectionFactory connFactory;
0174:
0175:            /* 
0176:             * A statement context is "pushed" and "popped" at the beginning and
0177:             * end of every statement so that only that statement is cleaned up
0178:             * on a Statement Exception.  As a performance optimization, we only push
0179:             * the outermost statement context once, and never pop it.  Also, we
0180:             * save off a 2nd StatementContext for speeding server side method
0181:             * invocation, though we still push and pop it as needed.  All other
0182:             * statement contexts will allocated and pushed and popped on demand.
0183:             */
0184:            private final StatementContext[] statementContexts = new StatementContext[2];
0185:            private int statementDepth;
0186:            protected int outermostTrigger = -1;
0187:
0188:            protected Authorizer authorizer;
0189:            protected String userName = null; //The name the user connects with.
0190:            //May still be quoted.
0191:
0192:            protected SchemaDescriptor sd;
0193:
0194:            // RESOLVE - How do we want to set the default.
0195:            private int defaultIsolationLevel = ExecutionContext.READ_COMMITTED_ISOLATION_LEVEL;
0196:            protected int isolationLevel = defaultIsolationLevel;
0197:
0198:            private boolean isolationLevelExplicitlySet = false;
0199:            // Isolation level can be changed using JDBC api Connection.setTransactionIsolation
0200:            // or it can be changed using SQL "set current isolation = NEWLEVEL".
0201:            // 
0202:            // In XA transactions, BrokeredConnection keeps isolation state information.
0203:            // When isolation is changed in XA transaction using JDBC, that state gets
0204:            // correctly set in BrokeredConnection.setTransactionIsolation method. But
0205:            // when SQL is used to set the isolation level, the code path is different
0206:            // and it does not go through BrokeredConnection's setTransactionIsolation
0207:            // method and hence the state is not maintained correctly when coming through
0208:            // SQL. To get around this, I am adding following flag which will get set
0209:            // everytime the isolation level is set using JDBC or SQL. This flag will be
0210:            // checked at global transaction start and end time. If the flag is set to true
0211:            // then BrokeredConnection's isolation level state will be brought upto date
0212:            // with Real Connection's isolation level and this flag will be set to false
0213:            // after that.
0214:            private boolean isolationLevelSetUsingSQLorJDBC = false;
0215:
0216:            // isolation level to when preparing statements.
0217:            // if unspecified, the statement won't be prepared with a specific 
0218:            // scan isolationlevel
0219:            protected int prepareIsolationLevel = ExecutionContext.UNSPECIFIED_ISOLATION_LEVEL;
0220:
0221:            // Whether or not to write executing statement info to db2j.log
0222:            private boolean logStatementText;
0223:            private boolean logQueryPlan;
0224:            private HeaderPrintWriter istream;
0225:
0226:            // this used to be computed in OptimizerFactoryContextImpl; i.e everytime a
0227:            // connection was made. To keep the semantics same I'm putting it out here
0228:            // instead of in the OptimizerFactory which is only initialized when the
0229:            // database is booted.
0230:            private int lockEscalationThreshold;
0231:
0232:            private Vector stmtValidators;
0233:            private Vector triggerExecutionContexts;
0234:            private Vector triggerTables;
0235:
0236:            protected AccessFactory af;
0237:
0238:            // OptimizerTrace
0239:            private boolean optimizerTrace;
0240:            private boolean optimizerTraceHtml;
0241:            private String lastOptimizerTraceOutput;
0242:            private String optimizerTraceOutput;
0243:
0244:            //// Support for AUTOINCREMENT
0245:
0246:            /**
0247:             * To support lastAutoincrementValue: This is a hashtable which maps
0248:             * schemaName,tableName,columnName to a Long value.
0249:             */
0250:            private Hashtable autoincrementHT;
0251:            /**
0252:             * whether to allow updates or not. 
0253:             */
0254:            private boolean autoincrementUpdate;
0255:            private long identityVal; //support IDENTITY_VAL_LOCAL function
0256:            private boolean identityNotNull; //frugal programmer
0257:
0258:            // cache of ai being handled in memory (bulk insert + alter table).
0259:            private Hashtable autoincrementCacheHashtable;
0260:
0261:            // temp public
0262:            public CacheManager statementCache;
0263:
0264:            /*
0265:               constructor
0266:             */
0267:            public GenericLanguageConnectionContext(ContextManager cm,
0268:                    TransactionController tranCtrl,
0269:
0270:                    LanguageFactory lf, LanguageConnectionFactory lcf,
0271:                    Database db, String userName, int instanceNumber,
0272:                    String drdaID, String dbname) throws StandardException {
0273:                super (
0274:                        cm,
0275:                        org.apache.derby.iapi.reference.ContextId.LANG_CONNECTION);
0276:                acts = new Vector();
0277:                tran = tranCtrl;
0278:
0279:                dataFactory = lcf.getDataValueFactory();
0280:                tcf = lcf.getTypeCompilerFactory();
0281:                of = lcf.getOptimizerFactory();
0282:                langFactory = lf;
0283:                connFactory = lcf;
0284:                this .db = db;
0285:                this .userName = userName;
0286:                this .instanceNumber = instanceNumber;
0287:                this .drdaID = drdaID;
0288:                this .dbname = dbname;
0289:
0290:                /* Find out whether or not to log info on executing statements to error log
0291:                 */
0292:                String logStatementProperty = PropertyUtil.getServiceProperty(
0293:                        getTransactionCompile(),
0294:                        "derby.language.logStatementText");
0295:                logStatementText = Boolean.valueOf(logStatementProperty)
0296:                        .booleanValue();
0297:
0298:                String logQueryPlanProperty = PropertyUtil.getServiceProperty(
0299:                        getTransactionCompile(), "derby.language.logQueryPlan");
0300:                logQueryPlan = Boolean.valueOf(logQueryPlanProperty)
0301:                        .booleanValue();
0302:
0303:                setRunTimeStatisticsMode(logQueryPlan);
0304:
0305:                lockEscalationThreshold = PropertyUtil.getServiceInt(tranCtrl,
0306:                        Property.LOCKS_ESCALATION_THRESHOLD,
0307:                        Property.MIN_LOCKS_ESCALATION_THRESHOLD,
0308:                        Integer.MAX_VALUE,
0309:                        Property.DEFAULT_LOCKS_ESCALATION_THRESHOLD);
0310:                stmtValidators = new Vector();
0311:                triggerExecutionContexts = new Vector();
0312:                triggerTables = new Vector();
0313:
0314:                af = lcf.getAccessFactory();
0315:                statementCache = lcf.getStatementCache();
0316:            }
0317:
0318:            public void initialize(boolean sqlConnection)
0319:                    throws StandardException {
0320:                //
0321:                //Creating the authorizer authorizes the connection.
0322:                authorizer = new GenericAuthorizer(IdUtil
0323:                        .getUserAuthorizationId(userName), this , sqlConnection);
0324:
0325:                //we can ignore the following if this is a database connection
0326:                //associated with internal thread such as logSniffer and StageTrunc
0327:                if (!sqlConnection)
0328:                    return;
0329:
0330:                /*
0331:                 ** Set the authorization id.  User shouldn't
0332:                 ** be null or else we are going to blow up trying
0333:                 ** to create a schema for this user.
0334:                 */
0335:                if (SanityManager.DEBUG) {
0336:                    if (getAuthorizationId() == null) {
0337:                        SanityManager
0338:                                .THROWASSERT("User name is null,"
0339:                                        + " check the connection manager to make sure it is set"
0340:                                        + " reasonably");
0341:                    }
0342:                }
0343:
0344:                setDefaultSchema(initDefaultSchemaDescriptor());
0345:            }
0346:
0347:            protected SchemaDescriptor initDefaultSchemaDescriptor()
0348:                    throws StandardException {
0349:                /*
0350:                 ** - If the database supports schemas and a schema with the
0351:                 ** same name as the user's name exists (has been created using
0352:                 ** create schema already) the database will set the users
0353:                 ** default schema to the the schema with the same name as the
0354:                 ** user.
0355:                 ** - Else Set the default schema to APP.
0356:                 */
0357:                // SchemaDescriptor sd;
0358:                DataDictionary dd = getDataDictionary();
0359:                String authorizationId = getAuthorizationId();
0360:
0361:                if ((sd = dd.getSchemaDescriptor(authorizationId,
0362:                        getTransactionCompile(), false)) == null) {
0363:                    sd = new SchemaDescriptor(dd, authorizationId,
0364:                            authorizationId, (UUID) null, false);
0365:                }
0366:                return sd;
0367:            }
0368:
0369:            //
0370:            // LanguageConnectionContext interface
0371:            //
0372:            /**
0373:             * @see LanguageConnectionContext#getLogStatementText
0374:             */
0375:            public boolean getLogStatementText() {
0376:                return logStatementText;
0377:            }
0378:
0379:            /**
0380:             * @see LanguageConnectionContext#setLogStatementText
0381:             */
0382:            public void setLogStatementText(boolean logStatementText) {
0383:                this .logStatementText = logStatementText;
0384:            }
0385:
0386:            /**
0387:             * @see LanguageConnectionContext#getLogQueryPlan
0388:             */
0389:            public boolean getLogQueryPlan() {
0390:                return logQueryPlan;
0391:            }
0392:
0393:            /**
0394:             * @see LanguageConnectionContext#usesSqlAuthorization
0395:             */
0396:            public boolean usesSqlAuthorization() {
0397:                return getDataDictionary().usesSqlAuthorization();
0398:            }
0399:
0400:            /**
0401:             * get the lock escalation threshold.
0402:             */
0403:            public int getLockEscalationThreshold() {
0404:                return lockEscalationThreshold;
0405:            }
0406:
0407:            /*
0408:            	The methods that follow are for consistency checking purposes
0409:             */
0410:
0411:            public int getCacheSize() {
0412:                if (statementCache != null)
0413:                    return statementCache.getNumberInUse();
0414:                else
0415:                    return 0;
0416:            }
0417:
0418:            /**
0419:             * Add the activation to those known about by this connection.
0420:             */
0421:            public void addActivation(Activation a) throws StandardException {
0422:                acts.addElement(a);
0423:
0424:                // DERBY-418. Activations which are marked unused,
0425:                // are closed here. Activations Vector is iterated 
0426:                // to identify and close unused activations, only if 
0427:                // unusedActs flag is set to true and if the total 
0428:                // size exceeds 20.
0429:                if ((unusedActs) && (acts.size() > 20)) {
0430:                    unusedActs = false;
0431:                    for (int i = acts.size() - 1; i >= 0; i--) {
0432:
0433:                        // it maybe the case that a Activation's reset() ends up
0434:                        // closing one or more activation leaving our index beyond
0435:                        // the end of the array
0436:                        if (i >= acts.size())
0437:                            continue;
0438:
0439:                        Activation a1 = (Activation) acts.elementAt(i);
0440:                        if (!a1.isInUse()) {
0441:                            a1.close();
0442:                        }
0443:                    }
0444:                }
0445:
0446:                if (SanityManager.DEBUG) {
0447:
0448:                    if (SanityManager.DEBUG_ON("memoryLeakTrace")) {
0449:
0450:                        if (acts.size() > 20)
0451:                            System.out
0452:                                    .println("memoryLeakTrace:GenericLanguageContext:activations "
0453:                                            + acts.size());
0454:                    }
0455:                }
0456:            }
0457:
0458:            /**
0459:             * Make a note that some activations are marked unused
0460:             */
0461:            public void notifyUnusedActivation() {
0462:                unusedActs = true;
0463:            }
0464:
0465:            /**
0466:             * @see LanguageConnectionContext#checkIfAnyDeclaredGlobalTempTablesForThisConnection
0467:             */
0468:            public boolean checkIfAnyDeclaredGlobalTempTablesForThisConnection() {
0469:                return (allDeclaredGlobalTempTables == null ? false : true);
0470:            }
0471:
0472:            /**
0473:             * @see LanguageConnectionContext#addDeclaredGlobalTempTable
0474:             */
0475:            public void addDeclaredGlobalTempTable(TableDescriptor td)
0476:                    throws StandardException {
0477:
0478:                if (findDeclaredGlobalTempTable(td.getName()) != null) //if table already declared, throw an exception
0479:                {
0480:                    throw StandardException
0481:                            .newException(
0482:                                    SQLState.LANG_OBJECT_ALREADY_EXISTS_IN_OBJECT,
0483:                                    "Declared global temporary table",
0484:                                    td.getName(),
0485:                                    "Schema",
0486:                                    SchemaDescriptor.STD_DECLARED_GLOBAL_TEMPORARY_TABLES_SCHEMA_NAME);
0487:                }
0488:
0489:                //save all the information about temp table in this special class
0490:                TempTableInfo tempTableInfo = new TempTableInfo(td,
0491:                        currentSavepointLevel);
0492:
0493:                if (allDeclaredGlobalTempTables == null)
0494:                    allDeclaredGlobalTempTables = new ArrayList();
0495:
0496:                allDeclaredGlobalTempTables.add(tempTableInfo);
0497:            }
0498:
0499:            /**
0500:             * @see LanguageConnectionContext#dropDeclaredGlobalTempTable
0501:             */
0502:            public boolean dropDeclaredGlobalTempTable(String tableName) {
0503:                TempTableInfo tempTableInfo = findDeclaredGlobalTempTable(tableName);
0504:                if (tempTableInfo != null) {
0505:                    if (SanityManager.DEBUG)
0506:                        if (tempTableInfo.getDeclaredInSavepointLevel() > currentSavepointLevel)
0507:                            SanityManager
0508:                                    .THROWASSERT("declared in savepoint level can not be higher than the current savepoint level");
0509:
0510:                    //following checks if the table was declared in the current unit of work.
0511:                    if (tempTableInfo.getDeclaredInSavepointLevel() == currentSavepointLevel) {
0512:                        //since the table was declared in this unit of work,
0513:                        //the drop table method should remove it from the valid list of temp table for this unit of work
0514:                        allDeclaredGlobalTempTables
0515:                                .remove(allDeclaredGlobalTempTables
0516:                                        .indexOf(tempTableInfo));
0517:                        if (allDeclaredGlobalTempTables.size() == 0)
0518:                            allDeclaredGlobalTempTables = null;
0519:                    } else {
0520:                        //since the table was not declared in this unit of work, the drop table method will just mark the table as dropped
0521:                        //in the current unit of work. This information will be used at rollback time.
0522:                        tempTableInfo
0523:                                .setDroppedInSavepointLevel(currentSavepointLevel);
0524:                    }
0525:                    return true;
0526:                } else
0527:                    return false;
0528:            }
0529:
0530:            /**
0531:             * After a release of a savepoint, we need to go through our temp tables list. If there are tables with their declare or drop
0532:             * or modified in savepoint levels set to savepoint levels higher than the current savepoint level, then we should change them
0533:             * to the current savepoint level
0534:             */
0535:            private void tempTablesReleaseSavepointLevels() {
0536:                //unlike rollback, here we check for dropped in / declared in / modified in savepoint levels > current savepoint level only.
0537:                //This is because the temp tables with their savepoint levels same as currentSavepointLevel have correct value assigned to them and
0538:                //do not need to be changed and hence no need to check for >=
0539:                for (int i = 0; i < allDeclaredGlobalTempTables.size(); i++) {
0540:                    TempTableInfo tempTableInfo = (TempTableInfo) allDeclaredGlobalTempTables
0541:                            .get(i);
0542:                    if (tempTableInfo.getDroppedInSavepointLevel() > currentSavepointLevel)
0543:                        tempTableInfo
0544:                                .setDroppedInSavepointLevel(currentSavepointLevel);
0545:
0546:                    if (tempTableInfo.getDeclaredInSavepointLevel() > currentSavepointLevel)
0547:                        tempTableInfo
0548:                                .setDeclaredInSavepointLevel(currentSavepointLevel);
0549:
0550:                    if (tempTableInfo.getModifiedInSavepointLevel() > currentSavepointLevel)
0551:                        tempTableInfo
0552:                                .setModifiedInSavepointLevel(currentSavepointLevel);
0553:                }
0554:            }
0555:
0556:            /**
0557:             * do the necessary work at commit time for temporary tables
0558:             * 1)If a temporary table was marked as dropped in this transaction, then remove it from the list of temp tables for this connection
0559:             * 2)If a temporary table was not dropped in this transaction, then mark it's declared savepoint level and modified savepoint level as -1
0560:             */
0561:            private void tempTablesAndCommit() {
0562:                for (int i = allDeclaredGlobalTempTables.size() - 1; i >= 0; i--) {
0563:                    TempTableInfo tempTableInfo = (TempTableInfo) allDeclaredGlobalTempTables
0564:                            .get(i);
0565:                    if (tempTableInfo.getDroppedInSavepointLevel() != -1) {
0566:                        //this means table was dropped in this unit of work and hence should be removed from valid list of temp tables
0567:                        allDeclaredGlobalTempTables.remove(i);
0568:                    } else //this table was not dropped in this unit of work, hence set its declaredInSavepointLevel as -1 and also mark it as not modified 
0569:                    {
0570:                        tempTableInfo.setDeclaredInSavepointLevel(-1);
0571:                        tempTableInfo.setModifiedInSavepointLevel(-1);
0572:                    }
0573:                }
0574:            }
0575:
0576:            /**
0577:            	Reset the connection before it is returned (indirectly) by
0578:            	a PooledConnection object. See EmbeddedConnection.
0579:             */
0580:            public void resetFromPool() throws StandardException {
0581:                // Reset IDENTITY_VAL_LOCAL
0582:                identityNotNull = false;
0583:
0584:                // drop all temp tables.
0585:                dropAllDeclaredGlobalTempTables();
0586:            }
0587:
0588:            /**
0589:             * Drop all the declared global temporary tables associated with this connection. This gets called
0590:             * when a getConnection() is done on a PooledConnection. This will ensure all the temporary tables
0591:             * declared on earlier connection handle associated with this physical database connection are dropped
0592:             * before a new connection handle is issued on that same physical database connection.
0593:             */
0594:            private void dropAllDeclaredGlobalTempTables()
0595:                    throws StandardException {
0596:                if (allDeclaredGlobalTempTables == null)
0597:                    return;
0598:
0599:                DependencyManager dm = getDataDictionary()
0600:                        .getDependencyManager();
0601:                StandardException topLevelStandardException = null;
0602:
0603:                //collect all the exceptions we might receive while dropping the temporary tables and throw them as one chained exception at the end.
0604:                for (int i = 0; i < allDeclaredGlobalTempTables.size(); i++) {
0605:                    try {
0606:                        TempTableInfo tempTableInfo = (TempTableInfo) allDeclaredGlobalTempTables
0607:                                .get(i);
0608:                        TableDescriptor td = tempTableInfo.getTableDescriptor();
0609:                        //the following 2 lines of code has been copied from DropTableConstantAction. If there are any changes made there in future,
0610:                        //we should check if they need to be made here too.
0611:                        dm
0612:                                .invalidateFor(td,
0613:                                        DependencyManager.DROP_TABLE, this );
0614:                        tran.dropConglomerate(td.getHeapConglomerateId());
0615:                    } catch (StandardException e) {
0616:                        e.setNestedException(topLevelStandardException);
0617:                        topLevelStandardException = e;
0618:                    }
0619:                }
0620:
0621:                allDeclaredGlobalTempTables = null;
0622:                try {
0623:                    internalCommit(true);
0624:                } catch (StandardException e) {
0625:                    e.setNestedException(topLevelStandardException);
0626:                    topLevelStandardException = e;
0627:                }
0628:                if (topLevelStandardException != null)
0629:                    throw topLevelStandardException;
0630:            }
0631:
0632:            //do the necessary work at rollback time for temporary tables
0633:            /**
0634:             * do the necessary work at rollback time for temporary tables
0635:             * 1)If a temp table was declared in the UOW, then drop it and remove it from list of temporary tables.
0636:             * 2)If a temp table was declared and dropped in the UOW, then remove it from list of temporary tables.
0637:             * 3)If an existing temp table was dropped in the UOW, then recreate it with no data.
0638:             * 4)If an existing temp table was modified in the UOW, then get rid of all the rows from the table.
0639:             */
0640:            private void tempTablesAndRollback() throws StandardException {
0641:                for (int i = allDeclaredGlobalTempTables.size() - 1; i >= 0; i--) {
0642:                    TempTableInfo tempTableInfo = (TempTableInfo) allDeclaredGlobalTempTables
0643:                            .get(i);
0644:                    if (tempTableInfo.getDeclaredInSavepointLevel() >= currentSavepointLevel) {
0645:                        if (tempTableInfo.getDroppedInSavepointLevel() == -1) {
0646:                            //the table was declared but not dropped in the unit of work getting rolled back and hence we will remove
0647:                            //it from valid list of temporary tables and drop the conglomerate associated with it
0648:                            TableDescriptor td = tempTableInfo
0649:                                    .getTableDescriptor();
0650:                            tran.dropConglomerate(td.getHeapConglomerateId()); //remove the conglomerate created for this temp table
0651:                            allDeclaredGlobalTempTables.remove(i); //remove it from the list of temp tables
0652:                        } else if (tempTableInfo.getDroppedInSavepointLevel() >= currentSavepointLevel) {
0653:                            //the table was declared and dropped in the unit of work getting rolled back
0654:                            allDeclaredGlobalTempTables.remove(i);
0655:                        }
0656:                    } else if (tempTableInfo.getDroppedInSavepointLevel() >= currentSavepointLevel) //this means the table was declared in an earlier savepoint unit / transaction and then dropped in current UOW 
0657:                    {
0658:                        //restore the old definition of temp table because drop is being rolledback
0659:                        TableDescriptor td = tempTableInfo.getTableDescriptor();
0660:                        td = cleanupTempTableOnCommitOrRollback(td, false);
0661:                        //In order to store the old conglomerate information for the temp table, we need to replace the
0662:                        //existing table descriptor with the old table descriptor which has the old conglomerate information
0663:                        tempTableInfo.setTableDescriptor(td);
0664:                        tempTableInfo.setDroppedInSavepointLevel(-1);
0665:                        //following will mark the table as not modified. This is because the table data has been deleted as part of the current rollback
0666:                        tempTableInfo.setModifiedInSavepointLevel(-1);
0667:                        allDeclaredGlobalTempTables.set(i, tempTableInfo);
0668:                    } else if (tempTableInfo.getModifiedInSavepointLevel() >= currentSavepointLevel) //this means the table was declared in an earlier savepoint unit / transaction and modified in current UOW
0669:                    {
0670:                        //following will mark the table as not modified. This is because the table data will be deleted as part of the current rollback
0671:                        tempTableInfo.setModifiedInSavepointLevel(-1);
0672:                        TableDescriptor td = tempTableInfo.getTableDescriptor();
0673:                        getDataDictionary().getDependencyManager()
0674:                                .invalidateFor(td,
0675:                                        DependencyManager.DROP_TABLE, this );
0676:                        cleanupTempTableOnCommitOrRollback(td, true);
0677:                    } // there is no else here because there is no special processing required for temp tables declares in earlier work of unit/transaction and not modified
0678:                }
0679:
0680:                if (allDeclaredGlobalTempTables.size() == 0)
0681:                    allDeclaredGlobalTempTables = null;
0682:            }
0683:
0684:            /**
0685:             * This is called at the commit time for temporary tables with ON COMMIT DELETE ROWS
0686:             * If a temp table with ON COMMIT DELETE ROWS doesn't have any held cursor open on them, we delete the data from
0687:             * them by dropping the conglomerate and recreating the conglomerate. In order to store the new conglomerate
0688:             * information for the temp table, we need to replace the existing table descriptor with the new table descriptor
0689:             * which has the new conglomerate information
0690:             * @param tableName Temporary table name whose table descriptor is getting changed
0691:             * @param td New table descriptor for the temporary table
0692:             */
0693:            private void replaceDeclaredGlobalTempTable(String tableName,
0694:                    TableDescriptor td) {
0695:                TempTableInfo tempTableInfo = findDeclaredGlobalTempTable(tableName);
0696:                tempTableInfo.setDroppedInSavepointLevel(-1);
0697:                tempTableInfo.setDeclaredInSavepointLevel(-1);
0698:                tempTableInfo.setTableDescriptor(td);
0699:                allDeclaredGlobalTempTables.set(allDeclaredGlobalTempTables
0700:                        .indexOf(tempTableInfo), tempTableInfo);
0701:            }
0702:
0703:            /**
0704:             * @see LanguageConnectionContext#getTableDescriptorForDeclaredGlobalTempTable
0705:             */
0706:            public TableDescriptor getTableDescriptorForDeclaredGlobalTempTable(
0707:                    String tableName) {
0708:                TempTableInfo tempTableInfo = findDeclaredGlobalTempTable(tableName);
0709:                if (tempTableInfo == null)
0710:                    return null;
0711:                else
0712:                    return tempTableInfo.getTableDescriptor();
0713:            }
0714:
0715:            /**
0716:             * Find the declared global temporary table in the list of temporary tables known by this connection.
0717:             * @param tableName look for this table name in the saved list
0718:             * @return data structure defining the temporary table if found. Else, return null 
0719:             *
0720:             */
0721:            private TempTableInfo findDeclaredGlobalTempTable(String tableName) {
0722:                if (allDeclaredGlobalTempTables == null)
0723:                    return null;
0724:
0725:                for (int i = 0; i < allDeclaredGlobalTempTables.size(); i++) {
0726:                    if (((TempTableInfo) allDeclaredGlobalTempTables.get(i))
0727:                            .matches(tableName))
0728:                        return (TempTableInfo) allDeclaredGlobalTempTables
0729:                                .get(i);
0730:                }
0731:                return null;
0732:            }
0733:
0734:            /**
0735:             * @see LanguageConnectionContext#markTempTableAsModifiedInUnitOfWork
0736:             */
0737:            public void markTempTableAsModifiedInUnitOfWork(String tableName) {
0738:                TempTableInfo tempTableInfo = findDeclaredGlobalTempTable(tableName);
0739:                tempTableInfo
0740:                        .setModifiedInSavepointLevel(currentSavepointLevel);
0741:            }
0742:
0743:            /**
0744:             * @see LanguageConnectionContext#prepareInternalStatement
0745:             */
0746:            public PreparedStatement prepareInternalStatement(
0747:                    SchemaDescriptor compilationSchema, String sqlText,
0748:                    boolean isForReadOnly, boolean forMetaData)
0749:                    throws StandardException {
0750:                return connFactory.getStatement(compilationSchema, sqlText,
0751:                        isForReadOnly).prepare(this , forMetaData);
0752:            }
0753:
0754:            /**
0755:             * @see LanguageConnectionContext#prepareInternalStatement
0756:             */
0757:            public PreparedStatement prepareInternalStatement(String sqlText)
0758:                    throws StandardException {
0759:                return connFactory.getStatement(sd, sqlText, true)
0760:                        .prepare(this );
0761:            }
0762:
0763:            /**
0764:             * Remove the activation to those known about by this connection.
0765:             *
0766:             */
0767:            public void removeActivation(Activation a) {
0768:                if (SanityManager.DEBUG) {
0769:                    SanityManager.ASSERT(a.isClosed(),
0770:                            "Activation is not closed");
0771:                }
0772:
0773:                acts.removeElement(a);
0774:
0775:                int capacity = acts.capacity();
0776:
0777:                if (capacity > 20 && (capacity > 2 * acts.size())) {
0778:                    acts.trimToSize();
0779:                }
0780:            }
0781:
0782:            /**
0783:             * Return the number of activations known for this connection.
0784:             * Note that some of these activations may not be in use
0785:             * (when a prepared statement is finalized, its activations
0786:             * are marked as unused and later closed and removed on
0787:             * the next commit/rollback).
0788:             */
0789:            public int getActivationCount() {
0790:                return acts.size();
0791:            }
0792:
0793:            /**
0794:             * See if a given cursor is available for use.
0795:             * if so return its activation. Returns null if not found.
0796:             * For use in execution.
0797:             *
0798:             * @return the activation for the given cursor, null
0799:             *	if none was found.
0800:             */
0801:            public CursorActivation lookupCursorActivation(String cursorName) {
0802:
0803:                int size = acts.size();
0804:                if (size > 0) {
0805:                    for (int i = 0; i < size; i++) {
0806:                        Activation a = (Activation) acts.elementAt(i);
0807:
0808:                        if (!a.isInUse()) {
0809:                            continue;
0810:                        }
0811:
0812:                        String executingCursorName = a.getCursorName();
0813:
0814:                        if (cursorName.equals(executingCursorName)) {
0815:
0816:                            ResultSet rs = a.getResultSet();
0817:                            if (rs == null)
0818:                                continue;
0819:
0820:                            // if the result set is closed, the the cursor doesn't exist
0821:                            if (rs.isClosed()) {
0822:                                continue;
0823:                            }
0824:
0825:                            return (CursorActivation) a;
0826:                        }
0827:                    }
0828:                }
0829:                return null;
0830:            }
0831:
0832:            /**
0833:             *  This method will remove a statement from the  statement cache.
0834:             *  It will be called,  for example, if there is an exception preparing
0835:             *  the statement.
0836:             *
0837:             *  @param statement Statement to remove
0838:             *  @exception StandardException thrown if lookup goes wrong.
0839:             */
0840:            public void removeStatement(Statement statement)
0841:                    throws StandardException {
0842:
0843:                if (statementCache == null)
0844:                    return;
0845:
0846:                Cacheable cachedItem = statementCache.findCached(statement);
0847:                if (cachedItem != null)
0848:                    statementCache.remove(cachedItem);
0849:            }
0850:
0851:            /**
0852:             * See if a given statement has already been compiled for this user, and
0853:             * if so use its prepared statement. Returns null if not found.
0854:             *
0855:             * @exception StandardException thrown if lookup goes wrong.
0856:             * @return the prepared statement for the given string, null
0857:             *	if none was found.
0858:             */
0859:            public PreparedStatement lookupStatement(GenericStatement statement)
0860:                    throws StandardException {
0861:
0862:                if (statementCache == null)
0863:                    return null;
0864:
0865:                // statement caching disable when in DDL mode
0866:                if (dataDictionaryInWriteMode()) {
0867:                    return null;
0868:                }
0869:
0870:                Cacheable cachedItem = statementCache.find(statement);
0871:
0872:                CachedStatement cs = (CachedStatement) cachedItem;
0873:
0874:                GenericPreparedStatement ps = cs.getPreparedStatement();
0875:
0876:                synchronized (ps) {
0877:                    if (ps.upToDate()) {
0878:                        GeneratedClass ac = ps.getActivationClass();
0879:
0880:                        // Check to see if the statement was prepared before some change
0881:                        // in the class loading set. If this is the case then force it to be invalid
0882:                        int currentClasses = getLanguageConnectionFactory()
0883:                                .getClassFactory().getClassLoaderVersion();
0884:
0885:                        if (ac.getClassLoaderVersion() != currentClasses) {
0886:                            ps
0887:                                    .makeInvalid(
0888:                                            DependencyManager.INTERNAL_RECOMPILE_REQUEST,
0889:                                            this );
0890:                        }
0891:
0892:                        // note that the PreparedStatement is not kept in the cache. This is because
0893:                        // having items kept in the cache that ultimately are held onto by
0894:                        // user code is impossible to manage. E.g. an open ResultSet would hold onto
0895:                        // a PreparedStatement (through its activation) and the user can allow
0896:                        // this object to be garbage collected. Pushing a context stack is impossible
0897:                        // in garbage collection as it may deadlock with the open connection and
0898:                        // the context manager assumes a singel current thread per context stack
0899:                    }
0900:                }
0901:
0902:                statementCache.release(cachedItem);
0903:                return ps;
0904:            }
0905:
0906:            /**
0907:            	Get a connection unique system generated name for a cursor.
0908:             */
0909:            public String getUniqueCursorName() {
0910:                return getNameString("SQLCUR", nextCursorId++);
0911:            }
0912:
0913:            /**
0914:            	Get a connection unique system generated name for an unnamed savepoint.
0915:             */
0916:            public String getUniqueSavepointName() {
0917:                return getNameString("SAVEPT", nextSavepointId++);
0918:            }
0919:
0920:            /**
0921:            	Get a connection unique system generated id for an unnamed savepoint.
0922:             */
0923:            public int getUniqueSavepointID() {
0924:                return nextSavepointId - 1;
0925:            }
0926:
0927:            /**
0928:             * Build a String for a statement name.
0929:             *
0930:             * @param prefix	The prefix for the statement name.
0931:             * @param number	The number to append for uniqueness
0932:             *
0933:             * @return	A unique String for a statement name.
0934:             */
0935:            private String getNameString(String prefix, long number) {
0936:                if (sb != null) {
0937:                    sb.setLength(0);
0938:                } else {
0939:                    sb = new StringBuffer();
0940:                }
0941:                sb.append(prefix).append(number);
0942:
0943:                return sb.toString();
0944:            }
0945:
0946:            /**
0947:             * Do a commit as appropriate for an internally generated
0948:             * commit (e.g. as needed by sync, or autocommit).
0949:             *
0950:             * @param	commitStore	true if we should commit the Store transaction
0951:             *
0952:             * @exception StandardException thrown on failure
0953:             */
0954:            public void internalCommit(boolean commitStore)
0955:                    throws StandardException {
0956:                doCommit(commitStore, true, NON_XA, false);
0957:            }
0958:
0959:            /**
0960:             * Do a commmit as is appropriate for a user requested
0961:             * commit (e.g. a java.sql.Connection.commit() or a language
0962:             * 'COMMIT' statement.  Does some extra checking to make
0963:             * sure that users aren't doing anything bad.
0964:             *
0965:             * @exception StandardException thrown on failure
0966:             */
0967:            public void userCommit() throws StandardException {
0968:                doCommit(true, true, NON_XA, true);
0969:            }
0970:
0971:            /**
0972:            	Commit the language transaction by doing a commitNoSync()
0973:            	on the store's TransactionController.
0974:
0975:            	<p>
0976:            	Do *NOT* tell the data dictionary that the transaction is
0977:            	finished. The reason is that this would allow other transactions
0978:            	to see comitted DDL that could be undone in the event of a
0979:            	system crash.
0980:
0981:            	@param	commitflag	the flags to pass to commitNoSync in the store's
0982:            						TransactionController
0983:
0984:            	@exception StandardException thrown on failure
0985:             */
0986:            public final void internalCommitNoSync(int commitflag)
0987:                    throws StandardException {
0988:                doCommit(true, false, commitflag, false);
0989:            }
0990:
0991:            /**
0992:            	Same as userCommit except commit a distributed transaction.   
0993:            	This commit always commit store and sync the commit.
0994:
0995:            	@param onePhase if true, allow it to commit without first going thru a
0996:            	prepared state.
0997:
0998:            	@exception StandardException	thrown if something goes wrong
0999:             */
1000:            public final void xaCommit(boolean onePhase)
1001:                    throws StandardException {
1002:                // further overload internalCommit to make it understand 2 phase commit
1003:                doCommit(true /* commit store */, true /* sync */,
1004:                        onePhase ? XA_ONE_PHASE : XA_TWO_PHASE, true);
1005:            }
1006:
1007:            /**
1008:             * This is where the work on internalCommit(), userCOmmit() and 
1009:             * internalCommitNoSync() actually takes place.
1010:             * <p>
1011:             * When a commit happens, the language connection context
1012:             * will close all open activations/cursors and commit the
1013:             * Store transaction.
1014:             * <p>
1015:             * REVISIT: we talked about having a LanguageTransactionContext,
1016:             * but since store transaction management is currently in flux
1017:             * and our context might want to delegate to that context,
1018:             * for now all commit/rollback actions are handled directly by
1019:             * the language connection context.
1020:             * REVISIT: this may need additional alterations when
1021:             * RELEASE SAVEPOINT/ROLLBACK TO SAVEPOINT show up.
1022:             * <P>
1023:             * Since the access manager's own context takes care of its own
1024:             * resources on commit, and the transaction stays open, there is
1025:             * nothing that this context has to do with the transaction controller.
1026:             * <p>
1027:             * Also, tell the data dictionary that the transaction is finished,
1028:             * if necessary (that is, if the data dictionary was put into
1029:             * DDL mode in this transaction.
1030:             *
1031:             *
1032:             * @param	commitStore	true if we should commit the Store transaction
1033:             * @param	sync		true means do a synchronized commit,
1034:             *						false means do an unsynchronized commit
1035:             * @param	commitflag	if this is an unsynchronized commit, the flags to
1036:             *						pass to commitNoSync in the store's
1037:             *						TransactionController.  If this is a synchronized
1038:             *						commit, this flag is overloaded for xacommit.
1039:             * @param   requestedByUser    False iff the commit is for internal use and
1040:             *                      we should ignore the check to prevent commits
1041:             *                      in an atomic statement.
1042:             *
1043:             * @exception StandardException		Thrown on error
1044:             */
1045:
1046:            protected void doCommit(boolean commitStore, boolean sync,
1047:                    int commitflag, boolean requestedByUser)
1048:                    throws StandardException {
1049:                StatementContext statementContext = getStatementContext();
1050:                if (requestedByUser && (statementContext != null)
1051:                        && statementContext.inUse()
1052:                        && statementContext.isAtomic()) {
1053:                    throw StandardException
1054:                            .newException(SQLState.LANG_NO_COMMIT_IN_NESTED_CONNECTION);
1055:                }
1056:
1057:                // Log commit to error log, if appropriate
1058:                if (logStatementText) {
1059:                    if (istream == null) {
1060:                        istream = Monitor.getStream();
1061:                    }
1062:                    String xactId = tran.getTransactionIdString();
1063:                    istream.printlnWithHeader(LanguageConnectionContext.xidStr
1064:                            + xactId + "), " + LanguageConnectionContext.lccStr
1065:                            + instanceNumber + "), "
1066:                            + LanguageConnectionContext.dbnameStr + dbname
1067:                            + "), " + LanguageConnectionContext.drdaStr
1068:                            + drdaID + "), Committing");
1069:                }
1070:
1071:                resetActivations(false);
1072:
1073:                //do the clean up work required for temporary tables at the commit time. This cleanup work
1074:                //can possibly remove entries from allDeclaredGlobalTempTables and that's why we need to check
1075:                //again later to see if we there are still any entries in allDeclaredGlobalTempTables
1076:                if (allDeclaredGlobalTempTables != null) {
1077:                    tempTablesAndCommit();
1078:                    //at commit time, for all the temp tables declared with ON COMMIT DELETE ROWS, make sure there are no held cursor open on them.
1079:                    //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
1080:                    if (allDeclaredGlobalTempTables != null) {
1081:                        for (int i = 0; i < allDeclaredGlobalTempTables.size(); i++) {
1082:                            TableDescriptor td = ((TempTableInfo) (allDeclaredGlobalTempTables
1083:                                    .get(i))).getTableDescriptor();
1084:                            if (td.isOnCommitDeleteRows() == false) //do nothing for temp table with ON COMMIT PRESERVE ROWS
1085:                            {
1086:                                continue;
1087:                            }
1088:                            if (checkIfAnyActivationHasHoldCursor(td.getName()) == false)//temp tables with ON COMMIT DELETE ROWS and no open held cursors
1089:                            {
1090:                                getDataDictionary().getDependencyManager()
1091:                                        .invalidateFor(td,
1092:                                                DependencyManager.DROP_TABLE,
1093:                                                this );
1094:                                cleanupTempTableOnCommitOrRollback(td, true);
1095:                            }
1096:                        }
1097:                    }
1098:                }
1099:
1100:                currentSavepointLevel = 0; //reset the current savepoint level for the connection to 0 at the end of commit work for temp tables
1101:
1102:                // Do *NOT* tell the DataDictionary to start using its cache again
1103:                // if this is an unsynchronized commit. The reason is that it
1104:                // would allow other transactions to see this transaction's DDL,
1105:                // which could be rolled back in case of a system crash.
1106:                if (sync) {
1107:                    finishDDTransaction();
1108:                }
1109:
1110:                // now commit the Store transaction
1111:                TransactionController tc = getTransactionExecute();
1112:                if (tc != null && commitStore) {
1113:                    if (sync) {
1114:                        if (commitflag == NON_XA) {
1115:                            // regular commit
1116:                            tc.commit();
1117:                        } else {
1118:                            // This may be a xa_commit, check overloaded commitflag.
1119:
1120:                            if (SanityManager.DEBUG)
1121:                                SanityManager.ASSERT(commitflag == XA_ONE_PHASE
1122:                                        || commitflag == XA_TWO_PHASE,
1123:                                        "invalid commit flag");
1124:
1125:                            ((XATransactionController) tc)
1126:                                    .xa_commit(commitflag == XA_ONE_PHASE);
1127:
1128:                        }
1129:                    } else {
1130:                        tc.commitNoSync(commitflag);
1131:                    }
1132:
1133:                    // reset the savepoints to the new
1134:                    // location, since any outer nesting
1135:                    // levels expect there to be a savepoint
1136:                    resetSavepoints();
1137:                }
1138:            }
1139:
1140:            /**
1141:             * If dropAndRedeclare is true, that means we have come here for temp tables with on commit delete rows
1142:             * and no held curosr open on them. We will drop the existing conglomerate and redeclare a new conglomerate
1143:             * similar to old conglomerate. This is a more efficient way of deleting all rows from the table.
1144:             *
1145:             * If dropAndRedeclare is false, that means we have come here for the rollback cleanup work. We are trying
1146:             * to restore old definition of the temp table (because the drop on it is being rolled back).
1147:             */
1148:            private TableDescriptor cleanupTempTableOnCommitOrRollback(
1149:                    TableDescriptor td, boolean dropAndRedeclare)
1150:                    throws StandardException {
1151:                //create new conglomerate with same properties as the old conglomerate and same row template as the old conglomerate
1152:                long conglomId = tran
1153:                        .createConglomerate(
1154:                                "heap", // we're requesting a heap conglomerate
1155:                                td.getEmptyExecRow(getContextManager())
1156:                                        .getRowArray(), // row template
1157:                                null, //column sort order - not required for heap
1158:                                null, // properties
1159:                                (TransactionController.IS_TEMPORARY | TransactionController.IS_KEPT));
1160:
1161:                long cid = td.getHeapConglomerateId();
1162:
1163:                //remove the old conglomerate descriptor from the table descriptor
1164:                ConglomerateDescriptor cgd = td.getConglomerateDescriptor(cid);
1165:                td.getConglomerateDescriptorList()
1166:                        .dropConglomerateDescriptorByUUID(cgd.getUUID());
1167:                //add the new conglomerate descriptor to the table descriptor
1168:                cgd = getDataDictionary().getDataDescriptorGenerator()
1169:                        .newConglomerateDescriptor(conglomId, null, false,
1170:                                null, false, null, td.getUUID(),
1171:                                td.getSchemaDescriptor().getUUID());
1172:                ConglomerateDescriptorList conglomList = td
1173:                        .getConglomerateDescriptorList();
1174:                conglomList.add(cgd);
1175:
1176:                //reset the heap conglomerate number in table descriptor to -1 so it will be refetched next time with the new value
1177:                td.resetHeapConglomNumber();
1178:
1179:                if (dropAndRedeclare) {
1180:                    tran.dropConglomerate(cid); //remove the old conglomerate from the system
1181:                    replaceDeclaredGlobalTempTable(td.getName(), td);
1182:                }
1183:
1184:                return (td);
1185:            }
1186:
1187:            /**
1188:              Do a rollback as appropriate for an internally generated
1189:              rollback (e.g. as needed by sync, or autocommit).
1190:             
1191:              When a rollback happens, we 
1192:              close all open activations and invalidate their
1193:              prepared statements.  We then tell the cache to
1194:              age out everything else, which effectively invalidates
1195:              them.  Thus, all prepared statements will be
1196:              compiled anew on their 1st execution after
1197:              a rollback.
1198:              <p>
1199:              The invalidated statements can revalidate themselves without
1200:              a full recompile if they verify their dependencies' providers still
1201:              exist unchanged. REVISIT when invalidation types are created.
1202:              <p>
1203:              REVISIT: this may need additional alterations when
1204:              RELEASE SAVEPOINT/ROLLBACK TO SAVEPOINT show up.
1205:              <p>
1206:              Also, tell the data dictionary that the transaction is finished,
1207:              if necessary (that is, if the data dictionary was put into
1208:              DDL mode in this transaction.
1209:
1210:              @exception StandardException thrown on failure
1211:             */
1212:
1213:            public void internalRollback() throws StandardException {
1214:                doRollback(false /* non-xa */, false);
1215:            }
1216:
1217:            /**
1218:             * Do a rollback as is appropriate for a user requested
1219:             * rollback (e.g. a java.sql.Connection.rollback() or a language
1220:             * 'ROLLBACk' statement.  Does some extra checking to make
1221:             * sure that users aren't doing anything bad.
1222:             *
1223:             * @exception StandardException thrown on failure
1224:             */
1225:            public void userRollback() throws StandardException {
1226:                doRollback(false /* non-xa */, true);
1227:            }
1228:
1229:            /**
1230:                Same as userRollback() except rolls back a distrubuted transaction.
1231:
1232:            	@exception StandardException	thrown if something goes wrong
1233:             */
1234:            public void xaRollback() throws StandardException {
1235:                doRollback(true /* xa */, true);
1236:            }
1237:
1238:            /**
1239:             * When a rollback happens, the language connection context
1240:             * will close all open activations and invalidate
1241:             * their prepared statements. Then the language will abort the
1242:             * Store transaction.
1243:             * <p>
1244:             * The invalidated statements can revalidate themselves without
1245:             * a full recompile if they verify their dependencies' providers still
1246:             * exist unchanged. REVISIT when invalidation types are created.
1247:             * <p>
1248:             * REVISIT: this may need additional alterations when
1249:             * RELEASE SAVEPOINT/ROLLBACK TO SAVEPOINT show up.
1250:             * <p>
1251:             * Also, tell the data dictionary that the transaction is finished,
1252:             * if necessary (that is, if the data dictionary was put into
1253:             * DDL mode in this transaction.
1254:             *
1255:             * @param xa	true if this is an xa rollback
1256:             * @param requestedByUser	true if requested by user
1257:             *
1258:             * @exception StandardException thrown on failure
1259:             */
1260:            private void doRollback(boolean xa, boolean requestedByUser)
1261:                    throws StandardException {
1262:                StatementContext statementContext = getStatementContext();
1263:                if (requestedByUser && (statementContext != null)
1264:                        && statementContext.inUse()
1265:                        && statementContext.isAtomic()) {
1266:                    throw StandardException
1267:                            .newException(SQLState.LANG_NO_ROLLBACK_IN_NESTED_CONNECTION);
1268:                }
1269:
1270:                // Log rollback to error log, if appropriate
1271:                if (logStatementText) {
1272:                    if (istream == null) {
1273:                        istream = Monitor.getStream();
1274:                    }
1275:                    String xactId = tran.getTransactionIdString();
1276:                    istream.printlnWithHeader(LanguageConnectionContext.xidStr
1277:                            + xactId + "), " + LanguageConnectionContext.lccStr
1278:                            + instanceNumber + "), "
1279:                            + LanguageConnectionContext.dbnameStr + dbname
1280:                            + "), " + LanguageConnectionContext.dbnameStr
1281:                            + dbname + "), "
1282:                            + LanguageConnectionContext.drdaStr + drdaID
1283:                            + "), Rolling back");
1284:                }
1285:
1286:                resetActivations(true);
1287:
1288:                currentSavepointLevel = 0; //reset the current savepoint level for the connection to 0 at the beginning of rollback work for temp tables
1289:                if (allDeclaredGlobalTempTables != null)
1290:                    tempTablesAndRollback();
1291:
1292:                finishDDTransaction();
1293:
1294:                // now rollback the Store transaction
1295:                TransactionController tc = getTransactionExecute();
1296:                if (tc != null) {
1297:                    if (xa)
1298:                        ((XATransactionController) tc).xa_rollback();
1299:                    else
1300:                        tc.abort();
1301:                    // reset the savepoints to the new
1302:                    // location, since any outer nesting
1303:                    // levels expet there to be a savepoint
1304:                    resetSavepoints();
1305:                }
1306:            }
1307:
1308:            /**
1309:             * Reset all statement savepoints. Traverses the StatementContext
1310:             * stack from bottom to top, calling resetSavePoint()
1311:             * on each element.
1312:             *
1313:             * @exception StandardException thrown if something goes wrong
1314:             */
1315:            private void resetSavepoints() throws StandardException {
1316:                final ContextManager cm = getContextManager();
1317:                final List stmts = cm
1318:                        .getContextStack(org.apache.derby.iapi.reference.ContextId.LANG_STATEMENT);
1319:                final int end = stmts.size();
1320:                for (int i = 0; i < end; ++i) {
1321:                    ((StatementContext) stmts.get(i)).resetSavePoint();
1322:                }
1323:            }
1324:
1325:            /**
1326:             * Let the context deal with a rollback to savepoint
1327:             *
1328:             * @param	savepointName	Name of the savepoint that needs to be rolled back
1329:             * @param	refreshStyle	boolean indicating whether or not the controller should close
1330:             * open conglomerates and scans. Also used to determine if language should close
1331:             * open activations.
1332:             * @param	kindOfSavepoint	 A NULL value means it is an internal savepoint (ie not a user defined savepoint)
1333:             * Non NULL value means it is a user defined savepoint which can be a SQL savepoint or a JDBC savepoint
1334:             *   A String value for kindOfSavepoint would mean it is SQL savepoint
1335:             *   A JDBC Savepoint object value for kindOfSavepoint would mean it is JDBC savepoint
1336:             *
1337:             * @exception StandardException thrown if something goes wrong
1338:             */
1339:            public void internalRollbackToSavepoint(String savepointName,
1340:                    boolean refreshStyle, Object kindOfSavepoint)
1341:                    throws StandardException {
1342:                // now rollback the Store transaction to the savepoint
1343:                TransactionController tc = getTransactionExecute();
1344:                if (tc != null) {
1345:                    boolean closeConglomerates;
1346:
1347:                    if (refreshStyle) {
1348:                        closeConglomerates = true;
1349:                        // bug 5145 - don't forget to close the activations while rolling
1350:                        // back to a savepoint
1351:                        resetActivations(true);
1352:                    } else {
1353:                        closeConglomerates = false;
1354:                    }
1355:
1356:                    currentSavepointLevel = tc.rollbackToSavePoint(
1357:                            savepointName, closeConglomerates, kindOfSavepoint);
1358:                }
1359:
1360:                if (tc != null && refreshStyle
1361:                        && allDeclaredGlobalTempTables != null)
1362:                    tempTablesAndRollback();
1363:            }
1364:
1365:            /**
1366:              Let the context deal with a release of a savepoint
1367:
1368:              @param	savepointName	Name of the savepoint that needs to be released
1369:              @param	kindOfSavepoint	 A NULL value means it is an internal savepoint (ie not a user defined savepoint)
1370:              Non NULL value means it is a user defined savepoint which can be a SQL savepoint or a JDBC savepoint
1371:              A String value for kindOfSavepoint would mean it is SQL savepoint
1372:              A JDBC Savepoint object value for kindOfSavepoint would mean it is JDBC savepoint
1373:
1374:              @exception StandardException thrown if something goes wrong
1375:             */
1376:            public void releaseSavePoint(String savepointName,
1377:                    Object kindOfSavepoint) throws StandardException {
1378:                TransactionController tc = getTransactionExecute();
1379:                if (tc != null) {
1380:                    currentSavepointLevel = tc.releaseSavePoint(savepointName,
1381:                            kindOfSavepoint);
1382:                    //after a release of a savepoint, we need to go through our temp tables list.
1383:                    if (allDeclaredGlobalTempTables != null)
1384:                        tempTablesReleaseSavepointLevels();
1385:                }
1386:            }
1387:
1388:            /**
1389:              Sets a savepoint. Causes the Store to set a savepoint.
1390:
1391:              @param	savepointName	name of savepoint
1392:              @param	kindOfSavepoint	 A NULL value means it is an internal savepoint (ie not a user defined savepoint)
1393:              Non NULL value means it is a user defined savepoint which can be a SQL savepoint or a JDBC savepoint
1394:              A String value for kindOfSavepoint would mean it is SQL savepoint
1395:              A JDBC Savepoint object value for kindOfSavepoint would mean it is JDBC savepoint
1396:
1397:            	@exception StandardException thrown if something goes wrong
1398:             */
1399:            public void languageSetSavePoint(String savepointName,
1400:                    Object kindOfSavepoint) throws StandardException {
1401:                TransactionController tc = getTransactionExecute();
1402:                if (tc != null) {
1403:                    currentSavepointLevel = tc.setSavePoint(savepointName,
1404:                            kindOfSavepoint);
1405:                }
1406:            }
1407:
1408:            /**
1409:             * Return true if any transaction is blocked, even if not by this one
1410:             *
1411:             */
1412:            public boolean anyoneBlocked() {
1413:                return getTransactionExecute().anyoneBlocked();
1414:            }
1415:
1416:            /**
1417:            	Sets the transaction controller to use with this language connection
1418:            	context.
1419:
1420:            	@param	tran	the transaction to use with this language connection context
1421:             */
1422:            public void setTransaction(TransactionController tran) {
1423:                this .tran = tran;
1424:            }
1425:
1426:            /**
1427:             * Start a Nested User Transaction (NUT) with the store. If a NUT is 
1428:             * already active simply increment a counter, queryNestingDepth, to keep
1429:             * track of how many times we have tried to start a NUT.
1430:             */
1431:            public void beginNestedTransaction(boolean readOnly)
1432:                    throws StandardException {
1433:                if (childTransaction == null)
1434:                    childTransaction = tran
1435:                            .startNestedUserTransaction(readOnly);
1436:                queryNestingDepth++;
1437:                return;
1438:            }
1439:
1440:            public void commitNestedTransaction() throws StandardException {
1441:                if (--queryNestingDepth == 0) {
1442:                    childTransaction.commit();
1443:                    childTransaction.destroy();
1444:                    childTransaction = null;
1445:                    return;
1446:                }
1447:            }
1448:
1449:            /**
1450:             * Get the transaction controller to use at compile time with this language
1451:             * connection context. If a NUT is active then return NUT else return parent
1452:             * transaction.
1453:             */
1454:            public TransactionController getTransactionCompile() {
1455:                return (childTransaction != null) ? childTransaction : tran;
1456:            }
1457:
1458:            public TransactionController getTransactionExecute() {
1459:                return tran;
1460:            }
1461:
1462:            /** Get the data value factory to use with this language connection
1463:            	context.
1464:             */
1465:            public DataValueFactory getDataValueFactory() {
1466:                return dataFactory;
1467:            }
1468:
1469:            /**
1470:            	Get the language factory to use with this language connection
1471:            	context.
1472:             */
1473:            public LanguageFactory getLanguageFactory() {
1474:                return langFactory;
1475:            }
1476:
1477:            public OptimizerFactory getOptimizerFactory() {
1478:                return of;
1479:            }
1480:
1481:            /**
1482:            	Get the language connection factory to use with this language connection
1483:            	context.
1484:             */
1485:            public LanguageConnectionFactory getLanguageConnectionFactory() {
1486:                return connFactory;
1487:            }
1488:
1489:            /**
1490:             * check if there are any activations that reference this temporary table
1491:             * @param tableName look for any activations referencing this table name
1492:             * @return boolean  false if found no activations
1493:             */
1494:            private boolean checkIfAnyActivationHasHoldCursor(String tableName)
1495:                    throws StandardException {
1496:                for (int i = acts.size() - 1; i >= 0; i--) {
1497:                    Activation a = (Activation) acts.elementAt(i);
1498:                    if (a.checkIfThisActivationHasHoldCursor(tableName))
1499:                        return true;
1500:                }
1501:                return false;
1502:            }
1503:
1504:            /**
1505:             * Verify that there are no activations with open held result sets.
1506:             *
1507:             * @return boolean  Found no open (held) resultsets.
1508:             *
1509:             * @exception StandardException thrown on failure
1510:             */
1511:            /* This gets used in case of hold cursors. If there are any hold cursors open
1512:             * then user can't change the isolation level without closing them. At the
1513:             * execution time, set transaction isolation level calls this method before
1514:             * changing the isolation level.
1515:             */
1516:            public boolean verifyAllHeldResultSetsAreClosed()
1517:                    throws StandardException {
1518:                boolean seenOpenResultSets = false;
1519:
1520:                /* For every activation */
1521:                for (int i = acts.size() - 1; i >= 0; i--) {
1522:
1523:                    Activation a = (Activation) acts.elementAt(i);
1524:
1525:                    if (SanityManager.DEBUG) {
1526:                        SanityManager.ASSERT(a instanceof  CursorActivation,
1527:                                "a is not a CursorActivation");
1528:                    }
1529:
1530:                    if (!a.isInUse()) {
1531:                        continue;
1532:                    }
1533:
1534:                    if (!a.getResultSetHoldability()) {
1535:                        continue;
1536:                    }
1537:
1538:                    ResultSet rs = ((CursorActivation) a).getResultSet();
1539:
1540:                    /* is there an open result set? */
1541:                    if ((rs != null) && !rs.isClosed() && rs.returnsRows()) {
1542:                        seenOpenResultSets = true;
1543:                        break;
1544:                    }
1545:                }
1546:
1547:                if (!seenOpenResultSets)
1548:                    return (true);
1549:
1550:                // There may be open ResultSet's that are yet to be garbage collected
1551:                // let's try and force these out rather than throw an error
1552:                System.gc();
1553:                System.runFinalization();
1554:
1555:                /* For every activation */
1556:                for (int i = acts.size() - 1; i >= 0; i--) {
1557:
1558:                    Activation a = (Activation) acts.elementAt(i);
1559:
1560:                    if (SanityManager.DEBUG) {
1561:                        SanityManager.ASSERT(a instanceof  CursorActivation,
1562:                                "a is not a CursorActivation");
1563:                    }
1564:
1565:                    if (!a.isInUse()) {
1566:                        continue;
1567:                    }
1568:
1569:                    if (!a.getResultSetHoldability()) {
1570:                        continue;
1571:                    }
1572:
1573:                    ResultSet rs = ((CursorActivation) a).getResultSet();
1574:
1575:                    /* is there an open held result set? */
1576:                    if ((rs != null) && !rs.isClosed() && rs.returnsRows()) {
1577:                        return (false);
1578:                    }
1579:                }
1580:                return (true);
1581:            }
1582:
1583:            /**
1584:             * Verify that there are no activations with open result sets
1585:             * on the specified prepared statement.
1586:             *
1587:             * @param pStmt		The prepared Statement
1588:             * @param provider	The object precipitating a possible invalidation
1589:             * @param action	The action causing the possible invalidation
1590:             *
1591:             * @return Nothing.
1592:             *
1593:             * @exception StandardException thrown on failure
1594:             */
1595:            public boolean verifyNoOpenResultSets(PreparedStatement pStmt,
1596:                    Provider provider, int action) throws StandardException {
1597:                /*
1598:                 ** It is not a problem to create an index when there is an open
1599:                 ** result set, since it doesn't invalidate the access path that was
1600:                 ** chosen for the result set.
1601:                 */
1602:                boolean seenOpenResultSets = false;
1603:
1604:                /* For every activation */
1605:
1606:                // synchronize on acts as other threads may be closing activations
1607:                // in this list, thus invalidating the Enumeration
1608:                for (int i = acts.size() - 1; i >= 0; i--) {
1609:
1610:                    Activation a = (Activation) acts.elementAt(i);
1611:
1612:                    if (!a.isInUse()) {
1613:                        continue;
1614:                    }
1615:
1616:                    /* for this prepared statement */
1617:                    if (pStmt == a.getPreparedStatement()) {
1618:                        ResultSet rs = a.getResultSet();
1619:
1620:                        /* is there an open result set? */
1621:                        if (rs != null && !rs.isClosed()) {
1622:                            if (!rs.returnsRows())
1623:                                continue;
1624:                            seenOpenResultSets = true;
1625:                            break;
1626:                        }
1627:
1628:                    }
1629:                }
1630:
1631:                if (!seenOpenResultSets)
1632:                    return false;
1633:
1634:                // There may be open ResultSet's that are yet to be garbage collected
1635:                // let's try and force these out rather than throw an error
1636:                System.gc();
1637:                System.runFinalization();
1638:
1639:                /* For every activation */
1640:                // synchronize on acts as other threads may be closing activations
1641:                // in this list, thus invalidating the Enumeration
1642:                for (int i = acts.size() - 1; i >= 0; i--) {
1643:
1644:                    Activation a = (Activation) acts.elementAt(i);
1645:
1646:                    if (!a.isInUse()) {
1647:                        continue;
1648:                    }
1649:
1650:                    /* for this prepared statement */
1651:                    if (pStmt == a.getPreparedStatement()) {
1652:                        ResultSet rs = a.getResultSet();
1653:
1654:                        /* is there an open result set? */
1655:                        if (rs != null && !rs.isClosed()) {
1656:                            if ((provider != null) && rs.returnsRows()) {
1657:                                DependencyManager dmgr = getDataDictionary()
1658:                                        .getDependencyManager();
1659:
1660:                                throw StandardException
1661:                                        .newException(
1662:                                                SQLState.LANG_CANT_INVALIDATE_OPEN_RESULT_SET,
1663:                                                dmgr.getActionString(action),
1664:                                                provider.getObjectName());
1665:
1666:                            }
1667:                            return true;
1668:                        }
1669:                    }
1670:                }
1671:                return false;
1672:            }
1673:
1674:            /**
1675:             *	Get the Authorization Id
1676:             *
1677:             * @return String	the authorization id
1678:             */
1679:            public String getAuthorizationId() {
1680:                return authorizer.getAuthorizationId();
1681:            }
1682:
1683:            /**
1684:             *	Get the default schema
1685:             *
1686:             * @return SchemaDescriptor	the default schema
1687:             */
1688:            public SchemaDescriptor getDefaultSchema() {
1689:                return sd;
1690:            }
1691:
1692:            /**
1693:             * Get the current schema name
1694:             *
1695:             * @return current schema name
1696:             */
1697:            public String getCurrentSchemaName() {
1698:                if (null == sd)
1699:                    return null;
1700:                return sd.getSchemaName();
1701:            }
1702:
1703:            /**
1704:             * Set the default schema -- used by SET SCHEMA.
1705:             * 
1706:             * @param sd the new default schema.
1707:             * If null, then the default schema descriptor is used.
1708:             *
1709:             * @exception StandardException thrown on failure
1710:             */
1711:            public void setDefaultSchema(SchemaDescriptor sd)
1712:                    throws StandardException {
1713:                if (sd == null) {
1714:                    sd = initDefaultSchemaDescriptor();
1715:                }
1716:                this .sd = sd;
1717:
1718:            }
1719:
1720:            /**
1721:             * Get the identity column value most recently generated.
1722:             *
1723:             * @return the generated identity column value
1724:             */
1725:            public Long getIdentityValue() {
1726:                return identityNotNull ? new Long(identityVal) : null;
1727:            }
1728:
1729:            /**
1730:             * Set the field of most recently generated identity column value.
1731:             *
1732:             * @param val the generated identity column value
1733:             */
1734:            public void setIdentityValue(long val) {
1735:                identityVal = val;
1736:                identityNotNull = true;
1737:            }
1738:
1739:            /**
1740:            	Empty as much of the cache as possible. It is not guaranteed
1741:            	that the cache is empty after this call, as statements may be kept
1742:            	by currently executing queries, activations that are about to be garbage
1743:            	collected.
1744:             */
1745:            public void emptyCache() {
1746:                /* We know prepared statements don't become dirty
1747:                 ** statementCache.cleanAll(); 
1748:                 */
1749:                if (statementCache != null)
1750:                    statementCache.ageOut();
1751:            }
1752:
1753:            /**
1754:             * Push a CompilerContext on the context stack with
1755:             * the current default schema as the default schema
1756:             * which we compile against.
1757:             *
1758:             * @return the compiler context
1759:             *
1760:             * @exception StandardException thrown on failure
1761:             */
1762:            public final CompilerContext pushCompilerContext() {
1763:                return pushCompilerContext((SchemaDescriptor) null);
1764:            }
1765:
1766:            /**
1767:             * Push a CompilerContext on the context stack with
1768:             * the passed in default schema as the default schema
1769:             * we compile against.
1770:             *
1771:             * @param sd the default schema 
1772:             *
1773:             * @return the compiler context
1774:             *
1775:             */
1776:            public CompilerContext pushCompilerContext(SchemaDescriptor sd) {
1777:                CompilerContext cc;
1778:                boolean firstCompilerContext = false;
1779:
1780:                //	DEBUG	END
1781:
1782:                cc = (CompilerContext) (getContextManager()
1783:                        .getContext(CompilerContext.CONTEXT_ID));
1784:
1785:                /*
1786:                 ** If there is no compiler context, this is the first one on the
1787:                 ** stack, so don't pop it when we're done (saves time).
1788:                 */
1789:                if (cc == null) {
1790:                    firstCompilerContext = true;
1791:                }
1792:
1793:                if (cc == null || cc.getInUse()) {
1794:                    cc = new CompilerContextImpl(getContextManager(), this , tcf);
1795:                    if (firstCompilerContext) {
1796:                        cc.firstOnStack();
1797:                    }
1798:                } else {
1799:                    /* Reset the next column,table, subquery and ResultSet numbers at 
1800:                     * the beginning of each statement 
1801:                     */
1802:                    cc.resetContext();
1803:                }
1804:
1805:                cc.setInUse(true);
1806:
1807:                // Save off the current isolation level on entry so that it gets restored
1808:                cc.setEntryIsolationLevel(getCurrentIsolationLevel());
1809:
1810:                StatementContext sc = getStatementContext();
1811:                if (sc.getSystemCode())
1812:                    cc.setReliability(CompilerContext.INTERNAL_SQL_LEGAL);
1813:
1814:                return cc;
1815:            }
1816:
1817:            /**
1818:             * Pop a CompilerContext off the context stack.
1819:             *
1820:             * @param cc  The compiler context.
1821:             */
1822:            public void popCompilerContext(CompilerContext cc) {
1823:                cc.setCurrentDependent(null);
1824:
1825:                cc.setInUse(false);
1826:
1827:                // Restore the isolation level at the time of entry to CompilerContext
1828:                isolationLevel = cc.getEntryIsolationLevel();
1829:
1830:                /*
1831:                 ** Only pop the compiler context if it's not the first one
1832:                 ** on the stack.
1833:                 */
1834:                if (!cc.isFirstOnStack()) {
1835:                    cc.popMe();
1836:                } else {
1837:                    cc.setCompilationSchema((SchemaDescriptor) null);
1838:                }
1839:            }
1840:
1841:            /**
1842:             * Push a StatementContext on the context stack.
1843:             *
1844:             * @param isAtomic whether this statement is atomic or not
1845:             * @param isForReadOnly whether this statement is for a read only resultset
1846:             * @param stmtText the text of the statement.  Needed for any language
1847:             * 	statement (currently, for any statement that can cause a trigger
1848:             * 	to fire).  Please set this unless you are some funky jdbc setXXX
1849:             *	method or something.
1850:             * @param pvs parameter value set, if it has one
1851:             * @param rollbackParentContext True if 1) the statement context is
1852:             * 	NOT a top-level context, AND 2) in the event of a statement-level
1853:             *	exception, the parent context needs to be rolled back, too.
1854:             * @param timeoutMillis timeout value for this statement, in milliseconds.
1855:             *  The value 0 means that no timeout is set.
1856:             *
1857:             * @return StatementContext  The statement context.
1858:             *
1859:             */
1860:            public StatementContext pushStatementContext(boolean isAtomic,
1861:                    boolean isForReadOnly, String stmtText,
1862:                    ParameterValueSet pvs, boolean rollbackParentContext,
1863:                    long timeoutMillis) {
1864:                int parentStatementDepth = statementDepth;
1865:                boolean inTrigger = false;
1866:                boolean parentIsAtomic = false;
1867:
1868:                // by default, assume we are going to use the outermost statement context
1869:                StatementContext statementContext = statementContexts[0];
1870:
1871:                /*
1872:                 ** If we haven't allocated any statement contexts yet, allocate
1873:                 ** the outermost stmt context now and push it.
1874:                 */
1875:                if (statementContext == null) {
1876:                    statementContext = statementContexts[0] = new GenericStatementContext(
1877:                            this , tran);
1878:                } else if (statementDepth > 0) {
1879:                    StatementContext parentStatementContext;
1880:                    /*
1881:                     ** We also cache a 2nd statement context, though we still
1882:                     ** push and pop it. Note, new contexts are automatically pushed.
1883:                     */
1884:                    if (statementDepth == 1) {
1885:                        statementContext = statementContexts[1];
1886:
1887:                        if (statementContext == null)
1888:                            statementContext = statementContexts[1] = new GenericStatementContext(
1889:                                    this , tran);
1890:                        else
1891:                            statementContext.pushMe();
1892:
1893:                        parentStatementContext = statementContexts[0];
1894:                    } else {
1895:                        parentStatementContext = getStatementContext();
1896:                        statementContext = new GenericStatementContext(this ,
1897:                                tran);
1898:                    }
1899:
1900:                    inTrigger = parentStatementContext.inTrigger()
1901:                            || (outermostTrigger == parentStatementDepth);
1902:                    parentIsAtomic = parentStatementContext.isAtomic();
1903:                    statementContext.setSQLAllowed(parentStatementContext
1904:                            .getSQLAllowed(), false);
1905:                    if (parentStatementContext.getSystemCode())
1906:                        statementContext.setSystemCode();
1907:                }
1908:
1909:                incrementStatementDepth();
1910:
1911:                statementContext.setInUse(inTrigger,
1912:                        isAtomic || parentIsAtomic, isForReadOnly, stmtText,
1913:                        pvs, timeoutMillis);
1914:                if (rollbackParentContext)
1915:                    statementContext.setParentRollback();
1916:                return statementContext;
1917:            }
1918:
1919:            /**
1920:             * Pop a StatementContext of the context stack.
1921:             *
1922:             * @param statementContext  The statement context.
1923:             * @param error				The error, if any  (Only relevant for DEBUG)
1924:             */
1925:            public void popStatementContext(StatementContext statementContext,
1926:                    Throwable error) {
1927:                if (statementContext != null) {
1928:                    /*
1929:                     ** If someone beat us to the punch, then it is ok,
1930:                     ** just silently ignore it.  We probably got here
1931:                     ** because we had a try catch block around a push/pop
1932:                     ** statement context, and we already got the context
1933:                     ** on a cleanupOnError.
1934:                     */
1935:                    if (!statementContext.inUse()) {
1936:                        return;
1937:                    }
1938:                    statementContext.clearInUse();
1939:                }
1940:
1941:                decrementStatementDepth();
1942:                if (statementDepth == -1) {
1943:                    /*
1944:                     * Only ignore the pop request for an already
1945:                     * empty stack when dealing with a session exception.
1946:                     */
1947:                    if (SanityManager.DEBUG) {
1948:                        int severity = (error instanceof  StandardException) ? ((StandardException) error)
1949:                                .getSeverity()
1950:                                : 0;
1951:                        SanityManager
1952:                                .ASSERT(error != null,
1953:                                        "Must have error to try popStatementContext with 0 depth");
1954:                        SanityManager
1955:                                .ASSERT(
1956:                                        (severity == ExceptionSeverity.SESSION_SEVERITY),
1957:                                        "Must have session severity error to try popStatementContext with 0 depth");
1958:                        SanityManager
1959:                                .ASSERT(
1960:                                        statementContext == statementContexts[0],
1961:                                        "statementContext is expected to equal statementContexts[0]");
1962:                    }
1963:                    resetStatementDepth(); // pretend we did nothing.
1964:                } else if (statementDepth == 0) {
1965:                    if (SanityManager.DEBUG) {
1966:                        /* Okay to pop last context on a session exception.
1967:                         * (We call clean up on error when exiting connection.)
1968:                         */
1969:                        int severity = (error instanceof  StandardException) ? ((StandardException) error)
1970:                                .getSeverity()
1971:                                : 0;
1972:                        if ((error == null)
1973:                                || (severity != ExceptionSeverity.SESSION_SEVERITY)) {
1974:                            SanityManager
1975:                                    .ASSERT(
1976:                                            statementContext == statementContexts[0],
1977:                                            "statementContext is expected to equal statementContexts[0]");
1978:                        }
1979:                    }
1980:                } else {
1981:                    if (SanityManager.DEBUG) {
1982:                        SanityManager
1983:                                .ASSERT(
1984:                                        statementContext != statementContexts[0],
1985:                                        "statementContext is not expected to equal statementContexts[0]");
1986:                        if (statementDepth <= 0)
1987:                            SanityManager
1988:                                    .THROWASSERT("statement depth expected to be >0, was "
1989:                                            + statementDepth);
1990:
1991:                        if (getContextManager().getContext(
1992:                                statementContext.getIdName()) != statementContext) {
1993:                            SanityManager
1994:                                    .THROWASSERT("trying to pop statement context from middle of stack");
1995:                        }
1996:                    }
1997:
1998:                    statementContext.popMe();
1999:                }
2000:
2001:            }
2002:
2003:            /**
2004:             * Push a new execution statement validator.  An execution statement 
2005:             * validator is an object that validates the current statement to
2006:             * ensure that it is permitted given the current execution context.
2007:             * An example of a validator a trigger ExecutionStmtValidator that
2008:             * doesn't allow ddl on the trigger target table.
2009:             * <p>
2010:             * Multiple ExecutionStmtValidators may be active at any given time.
2011:             * This mirrors the way there can be multiple connection nestings
2012:             * at a single time.  The validation is performed by calling each
2013:             * validator's validateStatement() method.  This yields the union
2014:             * of all validations.
2015:             *
2016:             * @param validator the validator to add
2017:             */
2018:            public void pushExecutionStmtValidator(
2019:                    ExecutionStmtValidator validator) {
2020:                stmtValidators.addElement(validator);
2021:            }
2022:
2023:            /**
2024:             * Remove the validator.  Does an object identity (validator == validator)
2025:             * comparison.  Asserts that the validator is found.
2026:             *
2027:             * @param validator the validator to remove
2028:             *
2029:             * @exception StandardException on error
2030:             */
2031:            public void popExecutionStmtValidator(
2032:                    ExecutionStmtValidator validator) throws StandardException {
2033:                boolean foundElement = stmtValidators.removeElement(validator);
2034:                if (SanityManager.DEBUG) {
2035:                    if (!foundElement) {
2036:                        SanityManager.THROWASSERT("statement validator "
2037:                                + validator + " not found");
2038:                    }
2039:                }
2040:            }
2041:
2042:            /**
2043:             * Push a new trigger execution context.
2044:             * <p>
2045:             * Multiple TriggerExecutionContexts may be active at any given time.
2046:             *
2047:             * @param tec the trigger execution context
2048:             *
2049:             * @exception StandardException on trigger recursion error
2050:             */
2051:            public void pushTriggerExecutionContext(TriggerExecutionContext tec)
2052:                    throws StandardException {
2053:                if (outermostTrigger == -1) {
2054:                    outermostTrigger = statementDepth;
2055:                }
2056:
2057:                /* Maximum 16 nesting levels allowed */
2058:                if (triggerExecutionContexts.size() >= Limits.DB2_MAX_TRIGGER_RECURSION) {
2059:                    throw StandardException
2060:                            .newException(SQLState.LANG_TRIGGER_RECURSION_EXCEEDED);
2061:                }
2062:
2063:                triggerExecutionContexts.addElement(tec);
2064:            }
2065:
2066:            /**
2067:             * Remove the tec.  Does an object identity (tec == tec)
2068:             * comparison.  Asserts that the tec is found.
2069:             *
2070:             * @param tec the tec to remove
2071:             *
2072:             * @exception StandardException on error
2073:             */
2074:            public void popTriggerExecutionContext(TriggerExecutionContext tec)
2075:                    throws StandardException {
2076:                if (outermostTrigger == statementDepth) {
2077:                    outermostTrigger = -1;
2078:                }
2079:
2080:                boolean foundElement = triggerExecutionContexts
2081:                        .removeElement(tec);
2082:                if (SanityManager.DEBUG) {
2083:                    if (!foundElement) {
2084:                        SanityManager.THROWASSERT("trigger execution context "
2085:                                + tec + " not found");
2086:                    }
2087:                }
2088:            }
2089:
2090:            /**
2091:             * Get the topmost tec.  
2092:             *
2093:             * @return the tec
2094:             */
2095:            public TriggerExecutionContext getTriggerExecutionContext() {
2096:                return triggerExecutionContexts.size() == 0 ? (TriggerExecutionContext) null
2097:                        : (TriggerExecutionContext) triggerExecutionContexts
2098:                                .lastElement();
2099:            }
2100:
2101:            /**
2102:             * Validate a statement.  Does so by stepping through all the validators
2103:             * and executing them.  If a validator throws and exception, then the
2104:             * checking is stopped and the exception is passed up.
2105:             *
2106:             * @param constantAction the constantAction that is about to be executed (and
2107:             *	should be validated
2108:             *
2109:             * @exception StandardException on validation failure
2110:             */
2111:            public void validateStmtExecution(ConstantAction constantAction)
2112:                    throws StandardException {
2113:                if (SanityManager.DEBUG) {
2114:                    SanityManager.ASSERT(constantAction != null,
2115:                            "constantAction is null");
2116:                }
2117:
2118:                if (stmtValidators.size() > 0) {
2119:                    for (Enumeration e = stmtValidators.elements(); e
2120:                            .hasMoreElements();) {
2121:                        ((ExecutionStmtValidator) e.nextElement())
2122:                                .validateStatement(constantAction);
2123:                    }
2124:                }
2125:            }
2126:
2127:            /**
2128:             * Set the trigger table descriptor.  Used to compile
2129:             * statements that may special trigger pseudo tables.
2130:             *
2131:             * @param td the table that the trigger is 
2132:             * defined upon
2133:             *
2134:             */
2135:            public void pushTriggerTable(TableDescriptor td) {
2136:                triggerTables.addElement(td);
2137:            }
2138:
2139:            /**
2140:             * Remove the trigger table descriptor.
2141:             *
2142:             * @param td the table to remove from the stack.
2143:             */
2144:            public void popTriggerTable(TableDescriptor td) {
2145:                boolean foundElement = triggerTables.removeElement(td);
2146:                if (SanityManager.DEBUG) {
2147:                    if (!foundElement) {
2148:                        SanityManager.THROWASSERT("trigger table not found: "
2149:                                + td);
2150:                    }
2151:                }
2152:            }
2153:
2154:            /**
2155:             * Get the topmost trigger table descriptor
2156:             *
2157:             * @return the table descriptor, or null if we
2158:             * aren't in the middle of compiling a create
2159:             * trigger.
2160:             */
2161:            public TableDescriptor getTriggerTable() {
2162:                return triggerTables.size() == 0 ? (TableDescriptor) null
2163:                        : (TableDescriptor) triggerTables.lastElement();
2164:            }
2165:
2166:            /**
2167:             * @see LanguageConnectionContext#getDatabase
2168:             */
2169:            public Database getDatabase() {
2170:                return db;
2171:            }
2172:
2173:            /** @see LanguageConnectionContext#incrementBindCount */
2174:            public int incrementBindCount() {
2175:                bindCount++;
2176:                return bindCount;
2177:            }
2178:
2179:            /** @see LanguageConnectionContext#decrementBindCount */
2180:            public int decrementBindCount() {
2181:                bindCount--;
2182:
2183:                if (SanityManager.DEBUG) {
2184:                    if (bindCount < 0)
2185:                        SanityManager.THROWASSERT("Level of nested binding == "
2186:                                + bindCount);
2187:                }
2188:
2189:                return bindCount;
2190:            }
2191:
2192:            /** @see LanguageConnectionContext#getBindCount */
2193:            public int getBindCount() {
2194:                return bindCount;
2195:            }
2196:
2197:            /** @see LanguageConnectionContext#setDataDictionaryWriteMode */
2198:            public final void setDataDictionaryWriteMode() {
2199:                ddWriteMode = true;
2200:            }
2201:
2202:            /** @see LanguageConnectionContext#dataDictionaryInWriteMode */
2203:            public final boolean dataDictionaryInWriteMode() {
2204:                return ddWriteMode;
2205:            }
2206:
2207:            /** @see LanguageConnectionContext#setRunTimeStatisticsMode */
2208:            public void setRunTimeStatisticsMode(boolean onOrOff) {
2209:                runTimeStatisticsSetting = onOrOff;
2210:            }
2211:
2212:            /** @see LanguageConnectionContext#getRunTimeStatisticsMode */
2213:            public boolean getRunTimeStatisticsMode() {
2214:                return runTimeStatisticsSetting;
2215:            }
2216:
2217:            /** @see LanguageConnectionContext#setStatisticsTiming */
2218:            public void setStatisticsTiming(boolean onOrOff) {
2219:                statisticsTiming = onOrOff;
2220:            }
2221:
2222:            /** @see LanguageConnectionContext#getStatisticsTiming */
2223:            public boolean getStatisticsTiming() {
2224:                return statisticsTiming;
2225:            }
2226:
2227:            /** @see LanguageConnectionContext#setRunTimeStatisticsObject */
2228:            public void setRunTimeStatisticsObject(
2229:                    RunTimeStatistics runTimeStatisticsObject) {
2230:                this .runTimeStatisticsObject = runTimeStatisticsObject;
2231:            }
2232:
2233:            /** @see LanguageConnectionContext#getRunTimeStatisticsObject */
2234:            public RunTimeStatistics getRunTimeStatisticsObject() {
2235:                return runTimeStatisticsObject;
2236:            }
2237:
2238:            /**
2239:             *	Reports how many statement levels deep we are.
2240:             *
2241:             *	@return	a statement level >= OUTERMOST_STATEMENT
2242:             */
2243:            public int getStatementDepth() {
2244:                return statementDepth;
2245:            }
2246:
2247:            /**
2248:             * @see LanguageConnectionContext#isIsolationLevelSetUsingSQLorJDBC
2249:             */
2250:            public boolean isIsolationLevelSetUsingSQLorJDBC() {
2251:                return isolationLevelSetUsingSQLorJDBC;
2252:            }
2253:
2254:            /**
2255:             * @see LanguageConnectionContext#resetIsolationLevelFlagUsedForSQLandJDBC
2256:             */
2257:            public void resetIsolationLevelFlagUsedForSQLandJDBC() {
2258:                isolationLevelSetUsingSQLorJDBC = false;
2259:            }
2260:
2261:            /**
2262:             * @see LanguageConnectionContext#setIsolationLevel
2263:             */
2264:            public void setIsolationLevel(int isolationLevel)
2265:                    throws StandardException {
2266:                StatementContext stmtCtxt = getStatementContext();
2267:                if (stmtCtxt != null && stmtCtxt.inTrigger())
2268:                    throw StandardException.newException(
2269:                            SQLState.LANG_NO_XACT_IN_TRIGGER,
2270:                            getTriggerExecutionContext().toString());
2271:
2272:                // find if there are any held cursors from previous isolation level.
2273:                // if yes, then throw an exception that isolation change not allowed until
2274:                // the held cursors are closed.
2275:                // I had to move this check outside of transaction idle check because if a
2276:                // transactions creates held cursors and commits the transaction, then
2277:                // there still would be held cursors but the transaction state would be idle.
2278:                // In order to check the above mentioned case, the held cursor check
2279:                // shouldn't rely on transaction state.
2280:                if (this .isolationLevel != isolationLevel) {
2281:                    if (!verifyAllHeldResultSetsAreClosed()) {
2282:                        throw StandardException
2283:                                .newException(SQLState.LANG_CANT_CHANGE_ISOLATION_HOLD_CURSOR);
2284:                    }
2285:                }
2286:
2287:                /* Commit and set to new isolation level.
2288:                 * NOTE: We commit first in case there's some kind
2289:                 * of error, like can't commit within a server side jdbc call.
2290:                 */
2291:                TransactionController tc = getTransactionExecute();
2292:                if (!tc.isIdle()) {
2293:                    // If this transaction is in progress, commit it.
2294:                    // However, do not allow commit to happen if this is a global
2295:                    // transaction.
2296:                    if (tc.isGlobal())
2297:                        throw StandardException
2298:                                .newException(SQLState.LANG_NO_SET_TRAN_ISO_IN_GLOBAL_CONNECTION);
2299:
2300:                    userCommit();
2301:                }
2302:                this .isolationLevel = isolationLevel;
2303:                this .isolationLevelExplicitlySet = true;
2304:                this .isolationLevelSetUsingSQLorJDBC = true;
2305:            }
2306:
2307:            /**
2308:             * @see LanguageConnectionContext#getCurrentIsolationLevel
2309:             */
2310:            public int getCurrentIsolationLevel() {
2311:                return (isolationLevel == ExecutionContext.UNSPECIFIED_ISOLATION_LEVEL) ? defaultIsolationLevel
2312:                        : isolationLevel;
2313:            }
2314:
2315:            /**
2316:             * @see LanguageConnectionContext#getCurrentIsolationLevel
2317:             */
2318:            public String getCurrentIsolationLevelStr() {
2319:                if (isolationLevel >= 0
2320:                        && isolationLevel < ExecutionContext.CS_TO_SQL_ISOLATION_MAP.length)
2321:                    return ExecutionContext.CS_TO_SQL_ISOLATION_MAP[isolationLevel][0];
2322:                return ExecutionContext.CS_TO_SQL_ISOLATION_MAP[ExecutionContext.UNSPECIFIED_ISOLATION_LEVEL][0];
2323:            }
2324:
2325:            /**
2326:             * @see LanguageConnectionContext#setPrepareIsolationLevel
2327:             */
2328:            public void setPrepareIsolationLevel(int level) {
2329:                prepareIsolationLevel = level;
2330:            }
2331:
2332:            /**
2333:             * @see LanguageConnectionContext#getPrepareIsolationLevel
2334:             */
2335:            public int getPrepareIsolationLevel() {
2336:                if (!isolationLevelExplicitlySet)
2337:                    return prepareIsolationLevel;
2338:                else
2339:                    return ExecutionContext.UNSPECIFIED_ISOLATION_LEVEL;
2340:            }
2341:
2342:            /**
2343:             * @see LanguageConnectionContext#getExecutionContext
2344:             */
2345:            public ExecutionContext getExecutionContext() {
2346:                return (ExecutionContext) getContextManager().getContext(
2347:                        ExecutionContext.CONTEXT_ID);
2348:            }
2349:
2350:            /**
2351:             * @see LanguageConnectionContext#getStatementContext
2352:             */
2353:            public StatementContext getStatementContext() {
2354:                return (StatementContext) getContextManager()
2355:                        .getContext(
2356:                                org.apache.derby.iapi.reference.ContextId.LANG_STATEMENT);
2357:            }
2358:
2359:            /**
2360:             * @see LanguageConnectionContext#setOptimizerTrace
2361:             */
2362:            public boolean setOptimizerTrace(boolean onOrOff) {
2363:                if (of == null) {
2364:                    return false;
2365:                }
2366:                if (!of.supportsOptimizerTrace()) {
2367:                    return false;
2368:                }
2369:                optimizerTrace = onOrOff;
2370:                return true;
2371:            }
2372:
2373:            /**
2374:             * @see LanguageConnectionContext#getOptimizerTrace
2375:             */
2376:            public boolean getOptimizerTrace() {
2377:                return optimizerTrace;
2378:            }
2379:
2380:            /**
2381:             * @see LanguageConnectionContext#setOptimizerTraceHtml
2382:             */
2383:            public boolean setOptimizerTraceHtml(boolean onOrOff) {
2384:                if (of == null) {
2385:                    return false;
2386:                }
2387:                if (!of.supportsOptimizerTrace()) {
2388:                    return false;
2389:                }
2390:                optimizerTraceHtml = onOrOff;
2391:                return true;
2392:            }
2393:
2394:            /**
2395:             * @see LanguageConnectionContext#getOptimizerTraceHtml
2396:             */
2397:            public boolean getOptimizerTraceHtml() {
2398:                return optimizerTraceHtml;
2399:            }
2400:
2401:            /**
2402:             * @see LanguageConnectionContext#setOptimizerTraceOutput
2403:             */
2404:            public void setOptimizerTraceOutput(String startingText) {
2405:                if (optimizerTrace) {
2406:                    lastOptimizerTraceOutput = optimizerTraceOutput;
2407:                    optimizerTraceOutput = startingText;
2408:                }
2409:            }
2410:
2411:            /**
2412:             * @see LanguageConnectionContext#appendOptimizerTraceOutput
2413:             */
2414:            public void appendOptimizerTraceOutput(String output) {
2415:                optimizerTraceOutput = (optimizerTraceOutput == null) ? output
2416:                        : optimizerTraceOutput + output;
2417:            }
2418:
2419:            /**
2420:             * @see LanguageConnectionContext#getOptimizerTraceOutput
2421:             */
2422:            public String getOptimizerTraceOutput() {
2423:                return lastOptimizerTraceOutput;
2424:            }
2425:
2426:            /**
2427:             *	Reports whether there is any outstanding work in the transaction.
2428:             *
2429:             *	@return	true if there is outstanding work in the transaction
2430:             *				false otherwise
2431:             */
2432:            public boolean isTransactionPristine() {
2433:                return getTransactionExecute().isPristine();
2434:            }
2435:
2436:            /**
2437:             *	Get the lock handle for the current transaction.
2438:             *
2439:             *	@param	lockScope	SINGLE_TRANSACTION_LOCK or MULTI_TRANSACTION_LOCK
2440:             *
2441:             *	@return	the current lock handle
2442:             *
2443:             * @exception StandardException thrown if something goes wrong
2444:             */
2445:            public Object getLockObject(int lockScope) throws StandardException {
2446:                switch (lockScope) {
2447:                case SINGLE_TRANSACTION_LOCK:
2448:                    return getTransactionExecute().getLockObject();
2449:
2450:                case MULTI_TRANSACTION_LOCK:
2451:                    return new Object();
2452:
2453:                default:
2454:                    throw StandardException
2455:                            .newException(SQLState.NOT_IMPLEMENTED);
2456:                }
2457:            }
2458:
2459:            /**
2460:             * Convert an identifier to the proper case for this connection. This method
2461:             * is here to support the Plugin.
2462:             *
2463:             * @param id an identifier string
2464:             * @return  the string converted to upper or lower case, as appropriate
2465:             *
2466:             * @exception StandardException thrown if something goes wrong
2467:             */
2468:            public String convertIdentifierCase(String id)
2469:                    throws StandardException {
2470:                if (ANTI_ANSI_CASING == getIdentifierCasing())
2471:                    return StringUtil.SQLToLowerCase(id);
2472:                else
2473:                    return StringUtil.SQLToUpperCase(id);
2474:            }
2475:
2476:            /**
2477:             *	Get casing for delimited identifiers. This feature is here to
2478:             *	support the Plugin.
2479:             *
2480:             *	@return	ANSI_CASING or ANTI_ANSI_CASING.
2481:             *
2482:             * @exception StandardException thrown if something goes wrong
2483:             */
2484:            public int getIdentifierCasing() throws StandardException {
2485:                if (UNKNOWN_CASING == identifierCasing) {
2486:                    identifierCasing = ANSI_CASING;
2487:                }
2488:                return identifierCasing;
2489:            }
2490:
2491:            //
2492:            // Context interface
2493:            //
2494:            /**
2495:            	If worse than a transaction error, everything goes; we
2496:            	rely on other contexts to kill the context manager
2497:            	for this session.
2498:            	<p>
2499:            	If a transaction error, act like we saw a rollback.
2500:            	<p>
2501:            	If more severe or a java error, the outer cleanup
2502:            	will shutdown the connection, so we don't have to clean up.
2503:            	<p>
2504:            	REMIND: connection should throw out all contexts and start
2505:            	over when the connection is closed... perhaps by throwing
2506:            	out the context manager?
2507:            	<p>
2508:            	REVISIT: If statement error, should we do anything?
2509:            	<P>
2510:            	Since the access manager's own context takes care of its own
2511:            	resources on errors, there is nothing that this context has
2512:            	to do with the transaction controller.
2513:
2514:            	@exception StandardException thrown on error. REVISIT: don't want
2515:            	cleanupOnError's to throw exceptions.
2516:             */
2517:            public void cleanupOnError(Throwable error)
2518:                    throws StandardException {
2519:
2520:                /*
2521:                 ** If it isn't a StandardException, then assume
2522:                 ** session severity. It is probably an unexpected
2523:                 ** java error somewhere in the language.
2524:                 ** Store layer treats JVM error as session severity, 
2525:                 ** hence to be consistent and to avoid getting rawstore
2526:                 ** protocol violation errors, we treat java errors here
2527:                 ** to be of session severity.
2528:                 */
2529:
2530:                int severity = (error instanceof  StandardException) ? ((StandardException) error)
2531:                        .getSeverity()
2532:                        : ExceptionSeverity.SESSION_SEVERITY;
2533:
2534:                if (statementContexts[0] != null) {
2535:                    statementContexts[0].clearInUse();
2536:
2537:                    // Force the StatementContext that's normally
2538:                    // left on the stack for optimization to be popped
2539:                    // when the session is closed. Ensures full cleanup
2540:                    // and no hanging refrences in the ContextManager.
2541:                    if (severity >= ExceptionSeverity.SESSION_SEVERITY)
2542:                        statementContexts[0].popMe();
2543:                }
2544:                if (statementContexts[1] != null) {
2545:                    statementContexts[1].clearInUse();
2546:                }
2547:
2548:                // closing the activations closes all the open cursors.
2549:                // the activations are, for all intents and purposes, the
2550:                // cursors.
2551:                if (severity >= ExceptionSeverity.SESSION_SEVERITY) {
2552:                    for (int i = acts.size() - 1; i >= 0; i--) {
2553:                        // it maybe the case that a reset()/close() ends up closing
2554:                        // one or more activation leaving our index beyond
2555:                        // the end of the array
2556:                        if (i >= acts.size())
2557:                            continue;
2558:                        Activation a = (Activation) acts.elementAt(i);
2559:                        a.reset();
2560:                        a.close();
2561:                    }
2562:
2563:                    popMe();
2564:                }
2565:
2566:                /*
2567:                 ** We have some global state that we need
2568:                 ** to clean up no matter what.  Be sure
2569:                 ** to do so.
2570:                 */
2571:                else if (severity >= ExceptionSeverity.TRANSACTION_SEVERITY) {
2572:                    internalRollback();
2573:                }
2574:            }
2575:
2576:            /**
2577:             * @see Context#isLastHandler
2578:             */
2579:            public boolean isLastHandler(int severity) {
2580:                return false;
2581:            }
2582:
2583:            //
2584:            // class implementation
2585:            //
2586:
2587:            /**
2588:            	resets all open activations, to close their result sets.
2589:            	Also cleans up (close()) activations that have been
2590:            	marked as unused during statement finalization.
2591:
2592:            	@exception StandardException thrown on failure
2593:             */
2594:            private void resetActivations(boolean andClose)
2595:                    throws StandardException {
2596:
2597:                // don't use an enumeration as the activation may remove
2598:                // itself from the list, thus invalidating the Enumeration
2599:                for (int i = acts.size() - 1; i >= 0; i--) {
2600:
2601:                    // it maybe the case that a reset() ends up closing
2602:                    // one or more activation leaving our index beyond
2603:                    // the end of the array
2604:                    if (i >= acts.size())
2605:                        continue;
2606:
2607:                    Activation a = (Activation) acts.elementAt(i);
2608:                    /*
2609:                     ** andClose true means we are here for rollback.
2610:                     ** In case of rollback, we don't care for holding
2611:                     ** cursors and that's why I am resetting holdability
2612:                     ** to false for all activations just before rollback
2613:                     */
2614:                    if (andClose)
2615:                        a.setResultSetHoldability(false);
2616:
2617:                    /*
2618:                     ** Look for stale activations.  Activations are
2619:                     ** marked as unused during statement finalization.
2620:                     ** Here, we sweep and remove this inactive ones.
2621:                     */
2622:                    if (!a.isInUse()) {
2623:                        a.close();
2624:                        continue;
2625:                    }
2626:
2627:                    a.reset();
2628:
2629:                    // Only invalidate statements if we performed DDL.
2630:                    if (andClose && dataDictionaryInWriteMode()) {
2631:                        ExecPreparedStatement ps = a.getPreparedStatement();
2632:                        if (ps != null) {
2633:                            ps.makeInvalid(DependencyManager.ROLLBACK, this );
2634:                        }
2635:                    }
2636:                }
2637:            }
2638:
2639:            /**
2640:            	Finish the data dictionary transaction, if any.
2641:
2642:            	@exception StandardException	Thrown on error
2643:             */
2644:            private void finishDDTransaction() throws StandardException {
2645:
2646:                /* Was the data dictionary put into write mode? */
2647:                if (ddWriteMode) {
2648:                    DataDictionary dd = getDataDictionary();
2649:
2650:                    /* Tell the data dictionary that the transaction is finished */
2651:                    dd.transactionFinished();
2652:
2653:                    /* The data dictionary isn't in write mode any more */
2654:                    ddWriteMode = false;
2655:                }
2656:            }
2657:
2658:            ////////////////////////////////////////////////////////////////////
2659:            //
2660:            //	MINIONS
2661:            //
2662:            ////////////////////////////////////////////////////////////////////
2663:
2664:            /**
2665:             *	Increments the statement depth.
2666:             */
2667:            private void incrementStatementDepth() {
2668:                statementDepth++;
2669:            }
2670:
2671:            /**
2672:             * Decrements the statement depth
2673:             */
2674:            private void decrementStatementDepth() {
2675:                statementDepth--;
2676:            }
2677:
2678:            /**
2679:             *	Resets the statementDepth.
2680:             */
2681:            protected void resetStatementDepth() {
2682:                statementDepth = 0;
2683:            }
2684:
2685:            /**
2686:             * Get the name of the system schema.
2687:             *
2688:             * @return	A String containing the name of the system schema.
2689:             * @throws StandardException
2690:             */
2691:            public String getSystemSchemaName() throws StandardException {
2692:                return convertIdentifierCase(SchemaDescriptor.STD_SYSTEM_SCHEMA_NAME);
2693:            }
2694:
2695:            /**
2696:             * Get the name of the SYSIBM schema.
2697:             *
2698:             * @return	A String containing the name of the SYSIBM schema.
2699:             * @throws StandardException
2700:             */
2701:            public String getSysIBMSchemaName() throws StandardException {
2702:                return convertIdentifierCase(SchemaDescriptor.IBM_SYSTEM_SCHEMA_NAME);
2703:            }
2704:
2705:            /**
2706:             * Get the name of the SYSCS_DIAG schema.
2707:             *
2708:             * @return	A String containing the name of the SYSIBM schema.
2709:             * @throws StandardException
2710:             */
2711:            public String getSystemDiagSchemaName() throws StandardException {
2712:                return (convertIdentifierCase(SchemaDescriptor.STD_SYSTEM_DIAG_SCHEMA_NAME));
2713:            }
2714:
2715:            /**
2716:             * Get the name of the SYSCS_UTIL schema.
2717:             *
2718:             * @return	A String containing the name of the SYSIBM schema.
2719:             * @throws StandardException
2720:             */
2721:            public String getSystemUtilSchemaName() throws StandardException {
2722:                return (convertIdentifierCase(SchemaDescriptor.STD_SYSTEM_UTIL_SCHEMA_NAME));
2723:            }
2724:
2725:            /**
2726:             * Get the declared global temporary tables schema name.
2727:             *
2728:             * @return	a String containing the declared global temporary tables schema name.
2729:             * @throws StandardException
2730:             */
2731:            public String getDeclaredGlobalTemporaryTablesSchemaName()
2732:                    throws StandardException {
2733:                return convertIdentifierCase(SchemaDescriptor.STD_DECLARED_GLOBAL_TEMPORARY_TABLES_SCHEMA_NAME);
2734:            }
2735:
2736:            public DataDictionary getDataDictionary() {
2737:                DataDictionaryContext ddc = (DataDictionaryContext) getContextManager()
2738:                        .getContext(DataDictionaryContext.CONTEXT_ID);
2739:
2740:                if (ddc != null) {
2741:                    return ddc.getDataDictionary();
2742:                } else {
2743:                    return null;
2744:                }
2745:            }
2746:
2747:            /**
2748:              @see LanguageConnectionContext#setReadOnly
2749:              @exception StandardException The operation is disallowed.
2750:             */
2751:            public void setReadOnly(boolean on) throws StandardException {
2752:                if (!tran.isPristine())
2753:                    throw StandardException
2754:                            .newException(SQLState.AUTH_SET_CONNECTION_READ_ONLY_IN_ACTIVE_XACT);
2755:                authorizer.setReadOnlyConnection(on, true);
2756:            }
2757:
2758:            /**
2759:              @see LanguageConnectionContext#isReadOnly
2760:             */
2761:            public boolean isReadOnly() {
2762:                return authorizer.isReadOnlyConnection();
2763:            }
2764:
2765:            /**
2766:              @see LanguageConnectionContext#getAuthorizer
2767:             */
2768:            public Authorizer getAuthorizer() {
2769:                return authorizer;
2770:            }
2771:
2772:            /** @see LanguageConnectionContext#getAccessFactory */
2773:            public AccessFactory getAccessFactory() {
2774:                return af;
2775:            }
2776:
2777:            /**
2778:             * Implements ConnectionInfo.lastAutoincrementValue.
2779:             * lastAutoincrementValue searches for the last autoincrement value inserted
2780:             * into a column specified by the user. The search for the "last" value
2781:             * supports nesting levels caused by triggers (Only triggers cause nesting,
2782:             * not server side JDBC). 
2783:             * If lastAutoincrementValue is called from within a trigger, the search
2784:             * space for ai-values are those values that are inserted by this trigger as
2785:             * well as previous triggers; 
2786:             * i.e if a SQL statement fires trigger T1, which in turn does something
2787:             * that fires trigger t2, and if lastAutoincrementValue is called from
2788:             * within t2, then autoincrement values genereated by t1 are visible to
2789:             * it. By the same logic, if it is called from within t1, then it does not
2790:             * see values inserted by t2.
2791:             *
2792:             * @see LanguageConnectionContext#lastAutoincrementValue
2793:             * @see org.apache.derby.iapi.db.ConnectionInfo#lastAutoincrementValue
2794:             */
2795:            public Long lastAutoincrementValue(String schemaName,
2796:                    String tableName, String columnName) {
2797:                String aiKey = AutoincrementCounter.makeIdentity(schemaName,
2798:                        tableName, columnName);
2799:
2800:                int size = triggerExecutionContexts.size();
2801:                //		System.out.println(" searching for " + aiKey);
2802:                for (int i = size - 1; i >= 0; i--) {
2803:                    // first loop through triggers.
2804:                    InternalTriggerExecutionContext itec = (InternalTriggerExecutionContext) triggerExecutionContexts
2805:                            .elementAt(i);
2806:                    Long value = itec.getAutoincrementValue(aiKey);
2807:                    if (value == null)
2808:                        continue;
2809:
2810:                    return value;
2811:                }
2812:                if (autoincrementHT == null)
2813:                    return null;
2814:                return (Long) autoincrementHT.get(aiKey);
2815:            }
2816:
2817:            /**
2818:             * @see LanguageConnectionContext#setAutoincrementUpdate
2819:             */
2820:            public void setAutoincrementUpdate(boolean flag) {
2821:                autoincrementUpdate = flag;
2822:            }
2823:
2824:            /**
2825:             * @see LanguageConnectionContext#getAutoincrementUpdate
2826:             */
2827:            public boolean getAutoincrementUpdate() {
2828:                return autoincrementUpdate;
2829:            }
2830:
2831:            /**
2832:             * @see LanguageConnectionContext#autoincrementCreateCounter
2833:             */
2834:            public void autoincrementCreateCounter(String s, String t,
2835:                    String c, Long initialValue, long increment, int position) {
2836:                String key = AutoincrementCounter.makeIdentity(s, t, c);
2837:
2838:                if (autoincrementCacheHashtable == null) {
2839:                    autoincrementCacheHashtable = new Hashtable();
2840:                }
2841:
2842:                AutoincrementCounter aic = (AutoincrementCounter) autoincrementCacheHashtable
2843:                        .get(key);
2844:                if (aic != null) {
2845:                    if (SanityManager.DEBUG) {
2846:                        SanityManager
2847:                                .THROWASSERT("Autoincrement Counter already exists:"
2848:                                        + key);
2849:                    }
2850:                    return;
2851:                }
2852:
2853:                aic = new AutoincrementCounter(initialValue, increment, 0, s,
2854:                        t, c, position);
2855:                autoincrementCacheHashtable.put(key, aic);
2856:            }
2857:
2858:            /**
2859:             * returns the <b>next</b> value to be inserted into an autoincrement col.
2860:             * This is used internally by the system to generate autoincrement values
2861:             * which are going to be inserted into a autoincrement column. This is
2862:             * used when as autoincrement column is added to a table by an alter 
2863:             * table statemenet and during bulk insert.
2864:             *
2865:             * @param schemaName
2866:             * @param tableName
2867:             * @param columnName identify the column uniquely in the system.
2868:             */
2869:            public long nextAutoincrementValue(String schemaName,
2870:                    String tableName, String columnName)
2871:                    throws StandardException {
2872:                String key = AutoincrementCounter.makeIdentity(schemaName,
2873:                        tableName, columnName);
2874:
2875:                AutoincrementCounter aic = (AutoincrementCounter) autoincrementCacheHashtable
2876:                        .get(key);
2877:
2878:                if (aic == null) {
2879:                    if (SanityManager.DEBUG) {
2880:                        SanityManager.THROWASSERT("counter doesn't exist:"
2881:                                + key);
2882:                    }
2883:                    return 0;
2884:                } else {
2885:                    return aic.update();
2886:                }
2887:            }
2888:
2889:            /**
2890:             * Flush the cache of autoincrement values being kept by the lcc.
2891:             * This will result in the autoincrement values being written to the
2892:             * SYSCOLUMNS table as well as the mapping used by lastAutoincrementValue
2893:             * 
2894:             * @exception StandardException thrown on error.
2895:             * @see LanguageConnectionContext#lastAutoincrementValue
2896:             * @see GenericLanguageConnectionContext#lastAutoincrementValue
2897:             * @see org.apache.derby.iapi.db.ConnectionInfo#lastAutoincrementValue
2898:             */
2899:            public void autoincrementFlushCache(UUID tableUUID)
2900:                    throws StandardException {
2901:                if (autoincrementCacheHashtable == null)
2902:                    return;
2903:
2904:                if (autoincrementHT == null)
2905:                    autoincrementHT = new Hashtable();
2906:
2907:                DataDictionary dd = getDataDictionary();
2908:                for (Enumeration e = autoincrementCacheHashtable.keys(); e
2909:                        .hasMoreElements();) {
2910:                    Object key = e.nextElement();
2911:                    AutoincrementCounter aic = (AutoincrementCounter) autoincrementCacheHashtable
2912:                            .get(key);
2913:                    Long value = aic.getCurrentValue();
2914:                    aic.flushToDisk(getTransactionExecute(), dd, tableUUID);
2915:                    if (value != null) {
2916:                        autoincrementHT.put(key, value);
2917:                    }
2918:                }
2919:                autoincrementCacheHashtable.clear();
2920:            }
2921:
2922:            /**
2923:             * Copies an existing hashtable of autoincrement mappings 
2924:             * into autoincrementHT, the cache of autoincrement values 
2925:             * kept in the languageconnectioncontext.
2926:             */
2927:            public void copyHashtableToAIHT(Hashtable from) {
2928:                if (from.isEmpty())
2929:                    return;
2930:                if (autoincrementHT == null)
2931:                    autoincrementHT = new Hashtable();
2932:
2933:                for (Enumeration e = from.keys(); e.hasMoreElements();) {
2934:                    Object key = e.nextElement();
2935:                    Object value = from.get(key);
2936:                    autoincrementHT.put(key, value);
2937:                }
2938:            }
2939:
2940:            /**
2941:             * @see LanguageConnectionContext#getInstanceNumber
2942:             */
2943:            public int getInstanceNumber() {
2944:                return instanceNumber;
2945:            }
2946:
2947:            /**
2948:             * @see LanguageConnectionContext#getDrdaID
2949:             */
2950:            public String getDrdaID() {
2951:                return drdaID;
2952:            }
2953:
2954:            /**
2955:             * @see LanguageConnectionContext#setDrdaID
2956:             */
2957:            public void setDrdaID(String drdaID) {
2958:                this .drdaID = drdaID;
2959:            }
2960:
2961:            /**
2962:             * @see LanguageConnectionContext#getDbname
2963:             */
2964:            public String getDbname() {
2965:                return dbname;
2966:            }
2967:
2968:            /**
2969:             * @see LanguageConnectionContext#getLastActivation
2970:             */
2971:            public Activation getLastActivation() {
2972:                return (Activation) acts.lastElement();
2973:            }
2974:
2975:            public StringBuffer appendErrorInfo() {
2976:
2977:                TransactionController tc = getTransactionExecute();
2978:                if (tc == null)
2979:                    return null;
2980:
2981:                StringBuffer sb = new StringBuffer(200);
2982:
2983:                sb.append(LanguageConnectionContext.xidStr);
2984:                sb.append(tc.getTransactionIdString());
2985:                sb.append("), ");
2986:
2987:                sb.append(LanguageConnectionContext.lccStr);
2988:                sb.append(Integer.toString(getInstanceNumber()));
2989:                sb.append("), ");
2990:
2991:                sb.append(LanguageConnectionContext.dbnameStr);
2992:                sb.append(getDbname());
2993:                sb.append("), ");
2994:
2995:                sb.append(LanguageConnectionContext.drdaStr);
2996:                sb.append(getDrdaID());
2997:                sb.append("), ");
2998:
2999:                return sb;
3000:            }
3001:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.