preparedStmt.setActivationClass(null);
}
try {
HeaderPrintWriter istream = lcc.getLogStatementText() ? Monitor.getStream() : null;
/*
** For stored prepared statements, we want all
** errors, etc in the context of the underlying
** EXECUTE STATEMENT statement, so don't push/pop
** another statement context unless we don't have
** one. We won't have one if it is an internal
** SPS (e.g. jdbcmetadata).
*/
if (!preparedStmt.isStorable() || lcc.getStatementDepth() == 0)
{
// since this is for compilation only, set atomic
// param to true and timeout param to 0
statementContext = lcc.pushStatementContext(true, isForReadOnly, getSource(),
null, false, 0L);
}
/*
** RESOLVE: we may ultimately wish to pass in
** whether we are a jdbc metadata query or not to
** get the CompilerContext to make the createDependency()
** call a noop.
*/
CompilerContext cc = lcc.pushCompilerContext(compilationSchema);
if (prepareIsolationLevel !=
ExecutionContext.UNSPECIFIED_ISOLATION_LEVEL)
{
cc.setScanIsolationLevel(prepareIsolationLevel);
}
// Look for stored statements that are in a system schema
// and with a match compilation schema. If so, allow them
// to compile using internal SQL constructs.
if (internalSQL ||
(spsSchema != null) && (spsSchema.isSystemSchema()) &&
(spsSchema.equals(compilationSchema))) {
cc.setReliability(CompilerContext.INTERNAL_SQL_LEGAL);
}
try
{
// Statement logging if lcc.getLogStatementText() is true
if (istream != null)
{
String xactId = lcc.getTransactionExecute().getActiveStateTxIdString();
istream.printlnWithHeader(LanguageConnectionContext.xidStr +
xactId +
"), " +
LanguageConnectionContext.lccStr +
lcc.getInstanceNumber() +
"), " +
LanguageConnectionContext.dbnameStr +
lcc.getDbname() +
"), " +
LanguageConnectionContext.drdaStr +
lcc.getDrdaID() +
"), Begin compiling prepared statement: " +
getSource() +
" :End prepared statement");
}
Parser p = cc.getParser();
cc.setCurrentDependent(preparedStmt);
//Only top level statements go through here, nested statement
//will invoke this method from other places
StatementNode qt = p.parseStatement(statementText, paramDefaults);
parseTime = getCurrentTimeMillis(lcc);
if (SanityManager.DEBUG)
{
if (SanityManager.DEBUG_ON("DumpParseTree"))
{
qt.treePrint();
}
if (SanityManager.DEBUG_ON("StopAfterParsing"))
{
throw StandardException.newException(SQLState.LANG_STOP_AFTER_PARSING);
}
}
/*
** Tell the data dictionary that we are about to do
** a bunch of "get" operations that must be consistent with
** each other.
*/
DataDictionary dataDictionary = lcc.getDataDictionary();
int ddMode = dataDictionary == null ? 0 : dataDictionary.startReading(lcc);
try
{
// start a nested transaction -- all locks acquired by bind
// and optimize will be released when we end the nested
// transaction.
lcc.beginNestedTransaction(true);
qt.bindStatement();
bindTime = getCurrentTimeMillis(lcc);
if (SanityManager.DEBUG)
{
if (SanityManager.DEBUG_ON("DumpBindTree"))
{
qt.treePrint();
}
if (SanityManager.DEBUG_ON("StopAfterBinding")) {
throw StandardException.newException(SQLState.LANG_STOP_AFTER_BINDING);
}
}
//Derby424 - In order to avoid caching select statements referencing
// any SESSION schema objects (including statements referencing views
// in SESSION schema), we need to do the SESSION schema object check
// here.
//a specific eg for statement referencing a view in SESSION schema
//CREATE TABLE t28A (c28 int)
//INSERT INTO t28A VALUES (280),(281)
//CREATE VIEW SESSION.t28v1 as select * from t28A
//SELECT * from SESSION.t28v1 should show contents of view and we
// should not cache this statement because a user can later define
// a global temporary table with the same name as the view name.
//Following demonstrates that
//DECLARE GLOBAL TEMPORARY TABLE SESSION.t28v1(c21 int, c22 int) not
// logged
//INSERT INTO SESSION.t28v1 VALUES (280,1),(281,2)
//SELECT * from SESSION.t28v1 should show contents of global temporary
//table and not the view. Since this select statement was not cached
// earlier, it will be compiled again and will go to global temporary
// table to fetch data. This plan will not be cached either because
// select statement is using SESSION schema object.
//
//Following if statement makes sure that if the statement is
// referencing SESSION schema objects, then we do not want to cache it.
// We will remove the entry that was made into the cache for
//this statement at the beginning of the compile phase.
//The reason we do this check here rather than later in the compile
// phase is because for a view, later on, we loose the information that
// it was referencing SESSION schema because the reference
//view gets replaced with the actual view definition. Right after
// binding, we still have the information on the view and that is why
// we do the check here.
if (preparedStmt.referencesSessionSchema(qt)) {
if (foundInCache)
((GenericLanguageConnectionContext)lcc).removeStatement(this);
}
qt.optimizeStatement();
optimizeTime = getCurrentTimeMillis(lcc);
// Statement logging if lcc.getLogStatementText() is true
if (istream != null)
{
String xactId = lcc.getTransactionExecute().getActiveStateTxIdString();
istream.printlnWithHeader(LanguageConnectionContext.xidStr +
xactId +
"), " +
LanguageConnectionContext.lccStr +
lcc.getInstanceNumber() +
"), " +
LanguageConnectionContext.dbnameStr +
lcc.getDbname() +
"), " +
LanguageConnectionContext.drdaStr +
lcc.getDrdaID() +
"), End compiling prepared statement: " +
getSource() +
" :End prepared statement");
}
}
catch (StandardException se)
{
lcc.commitNestedTransaction();
// Statement logging if lcc.getLogStatementText() is true
if (istream != null)
{
String xactId = lcc.getTransactionExecute().getActiveStateTxIdString();
istream.printlnWithHeader(LanguageConnectionContext.xidStr +
xactId +
"), " +
LanguageConnectionContext.lccStr +
lcc.getInstanceNumber() +
"), " +