db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From d..@apache.org
Subject svn commit: r643920 [1/2] - in /db/derby/code/trunk/java: engine/org/apache/derby/iapi/sql/ engine/org/apache/derby/iapi/sql/conn/ engine/org/apache/derby/iapi/sql/dictionary/ engine/org/apache/derby/impl/jdbc/ engine/org/apache/derby/impl/sql/ engine/...
Date Wed, 02 Apr 2008 14:35:41 GMT
Author: dag
Date: Wed Apr  2 07:35:37 2008
New Revision: 643920

URL: http://svn.apache.org/viewvc?rev=643920&view=rev
Log:
DERBY-3327 SQL roles: Implement authorization stack (and SQL session context to hold it)

Patch DERBY-3327-4-full-e.

See javadoc for SQLSessionContext for more details. This patch also solves DERBY-1331.

Added:
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/SQLSessionContext.java   (with props)
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/SQLSessionContextImpl.java   (with props)
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SQLSessionContextTest.java   (with props)
Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/Activation.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/LanguageConnectionContext.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/StatementContext.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/SchemaDescriptor.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericActivationHolder.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericPreparedStatement.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SpecialFunctionNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticMethodCallNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericStatementContext.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/BaseActivation.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/BasicNoPutResultSetImpl.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CallStatementResultSet.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DropSchemaConstantAction.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SetSchemaConstantAction.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/RolesTest.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/Activation.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/Activation.java?rev=643920&r1=643919&r2=643920&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/Activation.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/Activation.java Wed Apr  2 07:35:37 2008
@@ -24,6 +24,7 @@
 import org.apache.derby.iapi.error.StandardException;
 
 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
+import org.apache.derby.iapi.sql.conn.SQLSessionContext;
 
 import org.apache.derby.iapi.sql.dictionary.IndexRowGenerator;
 import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
@@ -586,23 +587,13 @@
 	*/
 	public int getMaxDynamicResults();
 
-	/**
-	 * Set the current role name of the dynamic call context stemming
-	 * from this activation (which must be a stored
-	 * procedure/function) call.
-	 *
-	 * @param role The name of the current role
-	 */
-	public void setNestedCurrentRole(String role);
 
 	/**
-	 * Get the current role name of the dynamic call context stemming
-	 * from this activation (which must be a stored
-	 * procedure/function) call.
-	 *
-	 * @return The name of the current role
+	 * Return the current SQL session context for all immediately
+	 * nested connections stemming from the call or function
+	 * invocation of the statement corresponding to this activation.
 	 */
-    public String getNestedCurrentRole();
+	public SQLSessionContext getNestedSQLSessionContext();
 
 	/**
 	 * This activation is created in a dynamic call context, remember

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/LanguageConnectionContext.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/LanguageConnectionContext.java?rev=643920&r1=643919&r2=643920&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/LanguageConnectionContext.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/LanguageConnectionContext.java Wed Apr  2 07:35:37 2008
@@ -424,16 +424,32 @@
 	public String getAuthorizationId();
 
 	/**
-	 *	Get the current default schema for the connection.
+	 * Get the default schema (used at compile-time when no activation
+	 * is yet available, cf. the activation argument overload version.
 	 *
-	 * @return SchemaDescriptor	the current schema
+	 * @return SchemaDescriptor	the default schema
 	 */
 	public SchemaDescriptor getDefaultSchema(); 
 
 	/**
-	 *	Set the current default schema
+	 * Get the default schema (used at execution time).  At execution
+	 * time, the current statement context is not always a reliable
+	 * place to find the correct SQL session context, viz. when a
+	 * dynamic result set referencing CURRENT SCHEMA is accessed after
+	 * a called procedure has returned only the activation of the call
+	 * is live and still holds the correct session context.
+	 * @param a current activation
+	 *
+	 * @return SchemaDescriptor	the default schema
+	 */
+	public SchemaDescriptor getDefaultSchema(Activation a);
+
+	/**
+	 * Set the default schema (at compile-time, see explanations for
+	 * getDefaultSchema overloads).
 	 *
-	 * @param sd the new default schema
+	 * @param sd the new default schema.
+	 * If null, then the default schema descriptor is used.
 	 *
 	 * @exception StandardException thrown on failure
 	 */
@@ -441,13 +457,48 @@
 		throws StandardException;
 
 	/**
-	 *	Get the current schema name
+	 * Set the default schema (at execution time, see explanations for
+	 * getDefaultSchema overloads); This version is used by SET SCHEMA.
+	 *
+	 * @param a current activation
+	 * @param sd the new default schema.
+	 * If null, then the default schema descriptor is used.
+	 *
+	 * @exception StandardException thrown on failure
+	 */
+	public void setDefaultSchema(Activation a, SchemaDescriptor sd)
+		throws StandardException;
+
+	/**
+	 * Reset any occurence of schemaName as current default schema in
+	 * the SQLSessionContext stack to the initial default, presumably
+	 * because schemaName is no longer a valid schema.
+	 *
+	 * @param activation current activation
+	 * @param schemaName the schema name occurences of which is to be reset
+	 *
+	 * @throws StandardException
+	 */
+	public void resetSchemaUsages(Activation activation, String schemaName)
+		throws StandardException;
+
+	/**
+	 *	Get the current schema name (at compile-time, see explanations for
+	 * getDefaultSchema overloads).
 	 *
 	 * @return SchemaDescriptor	the current schema
 	 */
 	public String getCurrentSchemaName();
 
 	/**
+	 * Get the current schema name (at execution time, see explanations for
+	 * getDefaultSchema overloads); This version is used by CURRENT SCHEMA.
+	 *
+	 * @return SchemaDescriptor	the current schema
+	 */
+	public String getCurrentSchemaName(Activation a);
+
+	/**
 	 * Get the identity column value most recently generated.
 	 *
 	 * @return the generated identity column value
@@ -540,7 +591,7 @@
      * @param timeoutMillis Timeout value for this statement, in milliseconds.
      *  Zero means no timeout.
 	 *
-	 * @return StatementContext	The statement context.
+	 * @return StatementContext The statement context.
 	 *
 	 */
 	StatementContext pushStatementContext(boolean isAtomic, boolean isForReadOnly, String stmtText,
@@ -1034,22 +1085,6 @@
 	public void closeUnusedActivations() throws StandardException;
 
 	/**
-	 * Remember most recent (call stack top) caller's activation when
-	 * invoking a method, see CallStatementResultSet#open.
-	 */
-	public void pushCaller(Activation a);
-
-	/**
-	 * Companion of pushCaller. See usage in CallStatementResultSet#open.
-	 */
-	public void popCaller();
-
-	/**
-	 * Get most recent (call stack top) caller's activation
-	 */
-	public Activation getCaller();
-
-    /**
 	 * Set the current role
 	 *
 	 * @param a activation of set role statement
@@ -1066,4 +1101,27 @@
 	 */
 	public String getCurrentRoleId(Activation a);
 
+	/**
+	 * Create a new SQL session context for the current activation
+	 * on the basis of the existing SQL session context (logical
+	 * session context analogue to call stack push, i.e. this happens
+	 * when a stored procedure or function that can contain SQL is
+	 * invoked. Called from generated code, see
+	 * StaticMethodCallNode#generateSetupNestedSessionContext.
+	 *
+	 * The new SQL session context is also set in the current statement
+	 * context (of the invocation).
+	 *
+	 * @see org.apache.derby.impl.sql.compile.StaticMethodCallNode#generateSetupNestedSessionContext
+	 * @see StatementContext#getSQLSessionContext
+	 *
+	 * @param a activation of the statement which performs the call.
+	 */
+	public void setupNestedSessionContext(Activation a);
+
+	/**
+	 * Create a fresh SQLSessionContext
+	 * @return new SQLSessionContext
+	 */
+	public SQLSessionContext createSQLSessionContext();
 }

Added: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/SQLSessionContext.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/SQLSessionContext.java?rev=643920&view=auto
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/SQLSessionContext.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/SQLSessionContext.java Wed Apr  2 07:35:37 2008
@@ -0,0 +1,91 @@
+/*
+
+   Derby - Class org.apache.derby.iapi.sql.conn.SQLSessionContext
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to you under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+
+package org.apache.derby.iapi.sql.conn;
+
+import java.lang.String;
+import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
+
+/**
+ * An implementation of this interface encapsulates some of the SQL
+ * session context's state variables, cf. SQL 2003, section 4.37.3,
+ * notably those which we need to save and restore when entering a
+ * stored procedure or function (which can contain SQL and thus a
+ * nested connection), cf. 4.37.3, 4.27.3 and 4.34.1.1.  <p> Presently
+ * this set contains the following properties: <ul> <li>current
+ * role</li> <li>current schema</li> </ul>
+ *
+ * The standard specifies that the authorization stack be copied onto
+ * the new SQL session context before it is pushed (and possibly
+ * modifed) with a new cell for the authorization ids (user, role). In
+ * our implementation we merge these two stacks for now. Also, the
+ * authorization id of current user is not represented yet, since it
+ * can not be modified in a session; Derby can not run routines with
+ * definer's rights yet.
+ * <p>
+ * SQL session context is implemented as follows: Statements at root
+ * connection level use the instance held by the the lcc, nested
+ * connections maintain instances of SQLSessionContext, held by the
+ * activation of the calling statement. This forms a logical stack as
+ * required by the standard. The statement context also holds a
+ * reference to the current SQLSessionContext.
+ * <p>
+ * When a dynamic result set references e.g. current role, the value
+ * retrieved will always be that of the current role when the
+ * statement is logically executed (inside procedure/function), not
+ * the current value when the result set is accessed outside the
+ * stored procedure/function.  This works since the nested SQL session
+ * context is kept by the caller activation, so even though the
+ * statement context of the call has been popped, we can get at the
+ * final state of the nested SQL session context since the caller's
+ * activation is alive as long as dynamic result sets need it).
+ * <p>
+ * If more than one nested connection is used inside a shared
+ * procedure, they will share the same nested SQL session
+ * context. Since the same dynamic call context is involved, this
+ * seems correct.
+ *
+ * @see org.apache.derby.iapi.sql.conn.LanguageConnectionContext#setupNestedSessionContext
+ */
+
+public interface SQLSessionContext {
+
+    /**
+     * Set the SQL role of this SQL connection context
+     * The empty string is returned if role is NONE.
+     */
+    public void setRole(String role);
+
+    /**
+     * Get the SQL role of this SQL connection context
+     */
+    public String getRole();
+
+    /**
+     * Set the schema of this SQL connection context
+     */
+    public void setDefaultSchema(SchemaDescriptor sd);
+
+    /**
+     * Get the schema of this SQL connection context
+     */
+    public SchemaDescriptor getDefaultSchema();
+}

Propchange: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/SQLSessionContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/StatementContext.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/StatementContext.java?rev=643920&r1=643919&r2=643920&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/StatementContext.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/StatementContext.java Wed Apr  2 07:35:37 2008
@@ -36,6 +36,7 @@
 
 import org.apache.derby.iapi.types.DataValueFactory;
 import org.apache.derby.iapi.sql.LanguageFactory;
+import org.apache.derby.iapi.sql.conn.SQLSessionContext;
 
 /**
  * StatementContext keeps the context for a statement.
@@ -248,5 +249,32 @@
 		too.
 	*/
 	public void setParentRollback();
+
+	/**
+     * Mark this statement context as associated with this activation.
+	 *
+	 * @param a activation
+     */
+	public void setActivation(Activation a);
+
+	/**
+     * Get activation associated with this statement context, if any.
+	 * Used to link up stack of activations of calls in nested
+	 * connections, see GenericPreparedStatement#getActivation.
+     */
+	public Activation getActivation();
+
+
+	/**
+	 * Get the current SQL session context
+	 */
+	public SQLSessionContext getSQLSessionContext();
+
+	/**
+	 * Set the current SQL session context
+	 *
+	 * @param ctx the SQL session context
+	 */
+	public void setSQLSessionContext(SQLSessionContext ctx);
 
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/SchemaDescriptor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/SchemaDescriptor.java?rev=643920&r1=643919&r2=643920&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/SchemaDescriptor.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/SchemaDescriptor.java Wed Apr  2 07:35:37 2008
@@ -24,6 +24,7 @@
 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
 import org.apache.derby.iapi.sql.depend.DependencyManager;
 import org.apache.derby.iapi.sql.depend.Provider;
+import org.apache.derby.iapi.sql.Activation;
 import org.apache.derby.iapi.store.access.TransactionController;
 import org.apache.derby.catalog.DependableFinder;
 import org.apache.derby.iapi.services.io.StoredFormatIds;
@@ -394,7 +395,8 @@
      * reset through the language connection context.
      * @throws StandardException Schema could not be dropped.
      */
-	public void drop(LanguageConnectionContext lcc) throws StandardException
+	public void drop(LanguageConnectionContext lcc,
+					 Activation activation) throws StandardException
 	{
         DataDictionary dd = getDataDictionary();
         DependencyManager dm = dd.getDependencyManager();
@@ -434,11 +436,6 @@
 	     ** LCC is free to set the new default schema to 
 	     ** some system defined default.
 	     */
-	    SchemaDescriptor currentDefault = lcc.getDefaultSchema();
-	    if ((currentDefault != null) &&
-                getSchemaName().equals(currentDefault.getSchemaName()))
-	    {
-	        lcc.setDefaultSchema((SchemaDescriptor)null);
-	    }        
+		lcc.resetSchemaUsages(activation, getSchemaName());
 	}
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java?rev=643920&r1=643919&r2=643920&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java Wed Apr  2 07:35:37 2008
@@ -3612,6 +3612,8 @@
                         lcc.prepareInternalStatement(insertSQL.toString());
                 Activation act = ps.getActivation(lcc, false);
 
+                statementContext.setActivation(act);
+
                 // in this for loop we are assigning values for parameters 
                 //in sql constructed earlier VALUES (?, ..)
                 for (int i=1, paramPosition=0; i<=resultDescription.getColumnCount(); i++) { 
@@ -3691,6 +3693,8 @@
             org.apache.derby.iapi.sql.PreparedStatement ps = lcc.prepareInternalStatement(updateWhereCurrentOfSQL.toString());
             Activation act = ps.getActivation(lcc, false);
 
+            statementContext.setActivation(act);
+
             //in this for loop we are assigning values for parameters in sql constructed earlier with columnname=?,... 
             for (int i=1, paramPosition=0; i<=resultDescription.getColumnCount(); i++) { 
                 if (columnGotUpdated[i-1])  //if the column got updated, do following
@@ -3757,6 +3761,9 @@
                 org.apache.derby.iapi.sql.PreparedStatement ps = lcc.prepareInternalStatement(deleteWhereCurrentOfSQL.toString());
                 // Get activation, so that we can get the warning from it
                 Activation act = ps.getActivation(lcc, false);
+
+                statementContext.setActivation(act);
+
                 // Don't set any timeout when deleting rows (use 0)
                 //execute delete where current of sql
                 org.apache.derby.iapi.sql.ResultSet rs = 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericActivationHolder.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericActivationHolder.java?rev=643920&r1=643919&r2=643920&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericActivationHolder.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericActivationHolder.java Wed Apr  2 07:35:37 2008
@@ -22,6 +22,7 @@
 package org.apache.derby.impl.sql;
 
 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
+import org.apache.derby.iapi.sql.conn.SQLSessionContext;
 
 import org.apache.derby.iapi.types.DataValueFactory;
 
@@ -564,12 +565,8 @@
 		return ac.getTargetVTI();
 	}
 
-	public void setNestedCurrentRole(String role) {
-		ac.setNestedCurrentRole(role);
-    }
-
-    public String getNestedCurrentRole() {
-		return ac.getNestedCurrentRole();
+	public SQLSessionContext getNestedSQLSessionContext() {
+		return ac.getNestedSQLSessionContext();
     }
 
 	public void setCallActivation(Activation a) {

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericPreparedStatement.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericPreparedStatement.java?rev=643920&r1=643919&r2=643920&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericPreparedStatement.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericPreparedStatement.java Wed Apr  2 07:35:37 2008
@@ -240,7 +240,17 @@
 		// deadlock.
 		lcc.closeUnusedActivations();
 
-		ac.setCallActivation(lcc.getCaller());
+		Activation callingAct = null;
+		StatementContext stmctx = lcc.getStatementContext();
+
+		if (stmctx != null) {
+			// if not null, callingAct represents the activation of
+			// a calling statement and this activation corresponds to
+			// a statement inside a stored procedure or function
+			callingAct = stmctx.getActivation();
+		}
+
+		ac.setCallActivation(callingAct);
 
 		return ac;
 	}
@@ -349,6 +359,8 @@
 
 			StatementContext statementContext = lccToUse.pushStatementContext(
 				isAtomic, updateMode==CursorNode.READ_ONLY, getSource(), pvs, rollbackParentContext, timeoutMillis);
+
+			statementContext.setActivation(activation);
 
 			if (needsSavepoint())
 			{

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SpecialFunctionNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SpecialFunctionNode.java?rev=643920&r1=643919&r2=643920&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SpecialFunctionNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SpecialFunctionNode.java Wed Apr  2 07:35:37 2008
@@ -232,7 +232,9 @@
 											 ClassName.LanguageConnectionContext, 0);
 		int argCount = 0;
 
-		if (methodName.equals("getCurrentRoleId")) {
+		if (methodName.equals("getCurrentRoleId") ||
+			methodName.equals("getCurrentSchemaName")) {
+
 			acb.pushThisAsActivation(mb);
 			argCount++;
 		}

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticMethodCallNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticMethodCallNode.java?rev=643920&r1=643919&r2=643920&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticMethodCallNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticMethodCallNode.java Wed Apr  2 07:35:37 2008
@@ -609,6 +609,35 @@
 	}
 
 	/**
+	 * Add code to set up the SQL session context for a stored
+	 * procedure or function which needs a nested SQL session
+	 * context (only needed for those which can contain SQL).
+	 *
+	 * The generated code calls setupNestedSessionContext.
+	 * @see org.apache.derby.iapi.sql.conn.LanguageConnectionContext#setupNestedSessionContext
+	 *
+	 * @param acb activation class builder
+	 * @param mb  method builder
+	 */
+	private void generateSetupNestedSessionContext(ActivationClassBuilder acb,
+												   MethodBuilder mb) {
+
+		// Generates the following Java code:
+		// ((Activation)this).getLanguageConnectionContext().
+		//       setupNestedSessionContext((Activation)this);
+
+		acb.pushThisAsActivation(mb);
+		mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
+					  "getLanguageConnectionContext",
+					  ClassName.LanguageConnectionContext, 0);
+		acb.pushThisAsActivation(mb);
+		mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
+					  "setupNestedSessionContext",
+					  "void", 1);
+	}
+
+
+	/**
 		Push extra code to generate the casts within the
 		arrays for the parameters passed as arrays.
 	*/
@@ -868,6 +897,13 @@
 			if (isSystemCode) {
 				mb.callMethod(VMOpcode.INVOKEINTERFACE, null,
 									"setSystemCode", "void", 0);
+			}
+
+			// If no SQL, there is no need to setup a nested session
+			// context.
+			if (sqlAllowed != RoutineAliasInfo.NO_SQL) {
+				generateSetupNestedSessionContext((ActivationClassBuilder) acb,
+												  mb);
 			}
 
 			// for a function we need to fetch the current SQL control

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java?rev=643920&r1=643919&r2=643920&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java Wed Apr  2 07:35:37 2008
@@ -47,10 +47,10 @@
 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
 import org.apache.derby.iapi.sql.conn.LanguageConnectionFactory;
 import org.apache.derby.iapi.sql.conn.StatementContext;
+import org.apache.derby.iapi.sql.conn.SQLSessionContext;
 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptorList;
 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
-import org.apache.derby.iapi.sql.dictionary.RoleDescriptor;
 import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
 import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
 import org.apache.derby.iapi.types.DataValueFactory;
@@ -73,7 +73,6 @@
 import org.apache.derby.iapi.store.access.TransactionController;
 import org.apache.derby.iapi.store.access.XATransactionController;
 import org.apache.derby.iapi.util.IdUtil;
-import org.apache.derby.iapi.util.StringUtil;
 
 import org.apache.derby.catalog.UUID;
 import org.apache.derby.iapi.sql.execute.RunTimeStatistics;
@@ -163,18 +162,6 @@
 	 */
 	private int queryNestingDepth;
 
-	/**
-	 * 'callers' keeps track of which, if any, stored procedure
-	 * activations are active. This helps implement the "authorization
-	 * stack" of SQL 2003, vol 2, section 4.34.1.1 and 4.27.3.
-	 *
-	 * For the top level, the current role is kept here,
-	 * cf. 'currentRole'.  For dynamic call contexts, the current role
-	 * is kept in the activation of the calling statement,
-	 * cf. 'getCurrentRoleId'.
-	 */
-	private ArrayList callers = new ArrayList(); // used as a stack only
-
 	protected DataValueFactory dataFactory;
 	protected LanguageFactory langFactory;
 	protected TypeCompilerFactory tcf;
@@ -197,8 +184,22 @@
     protected Authorizer authorizer;
 	protected String userName = null; //The name the user connects with.
 	                                  //May still be quoted.
-	protected String currentRole;
-	protected SchemaDescriptor	sd;
+	/**
+	 * The top SQL session context stack frame (SQL 2003, section
+	 * 4.37.3), is kept in topLevelSSC. For nested session contexts,
+	 * the SQL session context is held by the activation of the
+	 * calling statement, cf. setupNestedSessionContext and it is
+	 * accessible through the current statement context
+	 * (compile-time), or via the current activation (execution-time).
+	 * @see GenericLanguageConnectionContext#getTopLevelSQLSessionContext
+	 */
+	private SQLSessionContext topLevelSSC;
+
+	/**
+	 * Used to hold the computed value of the initial default schema,
+	 * cf logic in initDefaultSchemaDescriptor.
+	 */
+	private SchemaDescriptor cachedInitialDefaultSchemaDescr = null;
 
 	// RESOLVE - How do we want to set the default.
     private int defaultIsolationLevel = ExecutionContext.READ_COMMITTED_ISOLATION_LEVEL;
@@ -345,6 +346,13 @@
 		setDefaultSchema(initDefaultSchemaDescriptor());
 	}
 
+	/**
+	 * Compute the initial default schema and set
+	 * cachedInitialDefaultSchemaDescr accordingly.
+	 *
+	 * @return computed initial default schema value for this session
+	 * @throws StandardException
+	 */
 	protected SchemaDescriptor initDefaultSchemaDescriptor()
 		throws StandardException {
 		/*
@@ -355,18 +363,37 @@
 		** user.
         ** - Else Set the default schema to APP.
         */
-		// SchemaDescriptor sd;
+		if (cachedInitialDefaultSchemaDescr == null) {
+			DataDictionary dd = getDataDictionary();
+			String authorizationId = getAuthorizationId();
+			SchemaDescriptor sd =
+				dd.getSchemaDescriptor(
+					authorizationId, getTransactionCompile(), false);
 
-		DataDictionary dd = getDataDictionary();
-        String authorizationId = getAuthorizationId();
-	
-		if ( (sd = dd.getSchemaDescriptor(authorizationId, getTransactionCompile(), false)) == null )
-		{
-			sd = new SchemaDescriptor(dd, authorizationId, authorizationId, (UUID) null, false);
+			if (sd == null) {
+				sd = new SchemaDescriptor(
+					dd, authorizationId, authorizationId, (UUID) null, false);
+			}
+
+			cachedInitialDefaultSchemaDescr = sd;
 		}
-		return sd;
+		return cachedInitialDefaultSchemaDescr;
 	}
 
+	/**
+	 * Get the computed value for the initial default schema.
+	 * @return the schema descriptor of the computed initial default schema
+	 */
+	private SchemaDescriptor getInitialDefaultSchemaDescriptor() {
+		if (SanityManager.DEBUG) {
+			SanityManager.ASSERT(cachedInitialDefaultSchemaDescr != null,
+								 "cachedInitialDefaultSchemaDescr is null!");
+		}
+
+		return cachedInitialDefaultSchemaDescr;
+	}
+	
+
 	//
 	// LanguageConnectionContext interface
 	//
@@ -774,7 +801,8 @@
         public PreparedStatement prepareInternalStatement(String sqlText) 
 	    throws StandardException 
         {
-    	    return connFactory.getStatement(sd, sqlText, true).prepare(this);
+			return connFactory.
+				getStatement(getDefaultSchema(), sqlText, true).prepare(this);
     	}      
 
 	/**
@@ -1780,45 +1808,118 @@
 		return authorizer.getAuthorizationId();
 	}
 
-
 	/**
-	 *	Get the default schema
-	 *
-	 * @return SchemaDescriptor	the default schema
+	 * @see LanguageConnectionContext#getDefaultSchema
 	 */
 	public SchemaDescriptor getDefaultSchema() 
 	{ 
-		return sd; 
+		return getCurrentSQLSessionContext().getDefaultSchema();
 	}
+
 	/**
-	 * Get the current schema name
-	 *
-	 * @return current schema name
+	 * @see LanguageConnectionContext#getDefaultSchema(Activation a)
+	 */
+	public SchemaDescriptor getDefaultSchema(Activation a) {
+		return getCurrentSQLSessionContext(a.getCallActivation()).
+			getDefaultSchema();
+	}
+
+	/**
+	 * @see LanguageConnectionContext#getCurrentSchemaName()
 	 */
 	public String getCurrentSchemaName()
 	{
-        if( null == sd)
-            return null;
-		return sd.getSchemaName();
+		// getCurrentSchemaName with no arg is used even
+		// at run-time but only in places(*) where the statement context
+		// can be relied on, AFAICT.
+		//
+		// (*) SpaceTable#getConglomInfo,
+		//     SystemProcedures#{INSTALL|REPLACE|REMOVE}_JAR
+
+		SchemaDescriptor s = getDefaultSchema();
+		if( null == s)
+			return null;
+		return s.getSchemaName();
 	}
 
+
 	/**
-	 * Set the default schema -- used by SET SCHEMA.
-	 * 
-	 * @param sd the new default schema.
-	 * If null, then the default schema descriptor is used.
-	 *
-	 * @exception StandardException thrown on failure
+	 * @see LanguageConnectionContext#getCurrentSchemaName(Activation a)
+	 */
+	public String getCurrentSchemaName(Activation a)
+	{
+		SchemaDescriptor s = getDefaultSchema(a);
+		if( null == s)
+			return null;
+		return s.getSchemaName();
+	}
+
+	/**
+	 * @see LanguageConnectionContext#setDefaultSchema(SchemaDescriptor sd)
 	 */
 	public void setDefaultSchema(SchemaDescriptor sd)
 		throws StandardException
 	{ 	
-		if (sd == null)
-		{	
-		    sd = initDefaultSchemaDescriptor();
+		if (sd == null) {	
+		    sd = getInitialDefaultSchemaDescriptor();
+		}
+
+		getCurrentSQLSessionContext().setDefaultSchema(sd);
+	}
+
+	/**
+	 * @see LanguageConnectionContext#setDefaultSchema(Activation a,
+	 * SchemaDescriptor sd)
+	 */
+	public void setDefaultSchema(Activation a, SchemaDescriptor sd)
+		throws StandardException
+	{
+		Activation caller = a.getCallActivation();
+
+		if (sd == null) {
+			sd = getInitialDefaultSchemaDescriptor();
+		}
+
+		getCurrentSQLSessionContext(caller).setDefaultSchema(sd);
+	}
+
+
+	/**
+	 * @see LanguageConnectionContext#resetSchemaUsages(Activation activation,
+	 *      String schemaName)
+	 */
+	public void resetSchemaUsages(Activation activation, String schemaName)
+			throws StandardException {
+
+		Activation caller = activation.getCallActivation();
+		SchemaDescriptor defaultSchema = getInitialDefaultSchemaDescriptor();
+
+		// walk SQL session context chain
+		while (caller != null) {
+			SQLSessionContext ssc = caller.getNestedSQLSessionContext();
+			SchemaDescriptor s = ssc.getDefaultSchema();
+
+			if (SanityManager.DEBUG) {
+				SanityManager.ASSERT(s != null, "s should not be empty here");
+			}
+
+			if (schemaName.equals(s.getSchemaName())) {
+				ssc.setDefaultSchema(defaultSchema);
+			}
+			caller = caller.getCallActivation();
+		}
+
+		// finally top level
+		SQLSessionContext top = getTopLevelSQLSessionContext();
+		SchemaDescriptor sd = top.getDefaultSchema();
+
+		if (SanityManager.DEBUG) {
+			SanityManager.ASSERT(sd != null, "sd should not be empty here");
+		}
+
+		if (schemaName.equals(sd.getSchemaName())) {
+			top.setDefaultSchema(defaultSchema);
 		}
-		this.sd = sd;
-		
 	}
 
 	/**
@@ -1968,6 +2069,10 @@
 	/**
 	 * Push a StatementContext on the context stack.
 	 *
+	 * Inherit SQL session state a priori (statementContext will get
+	 * its own SQL session state if this statement executes a call,
+	 * cf. setupNestedSessionContext.
+
 	 * @param isAtomic whether this statement is atomic or not
 	 * @param isForReadOnly whether this statement is for a read only resultset
 	 * @param stmtText the text of the statement.  Needed for any language
@@ -2000,9 +2105,12 @@
 		** If we haven't allocated any statement contexts yet, allocate
 		** the outermost stmt context now and push it.
 		*/
+
 		if (statementContext == null)
 		{
 			statementContext = statementContexts[0] = new GenericStatementContext(this);
+			statementContext.
+				setSQLSessionContext(getTopLevelSQLSessionContext());
 		}
 		else if (statementDepth > 0)
 		{
@@ -2028,11 +2136,17 @@
 				statementContext = new GenericStatementContext(this);
 			}
 
+			statementContext.setSQLSessionContext(
+				parentStatementContext.getSQLSessionContext());
+
 			inTrigger = parentStatementContext.inTrigger() || (outermostTrigger == parentStatementDepth);
 			parentIsAtomic = parentStatementContext.isAtomic();
 			statementContext.setSQLAllowed(parentStatementContext.getSQLAllowed(), false);
 			if (parentStatementContext.getSystemCode())
 				statementContext.setSystemCode();
+		} else {
+			statementContext.
+				setSQLSessionContext(getTopLevelSQLSessionContext());
 		}
 
 		incrementStatementDepth();
@@ -3112,74 +3226,130 @@
 		return sb;
 	}
 
+	
 	/**
-	 * Remember most recent (call stack top) caller's activation when
-	 * invoking a method, see CallStatementResultSet#open.
+	 * @see LanguageConnectionContext#setCurrentRole(Activation a, String role)
 	 */
-	public void pushCaller(Activation a) {
-		callers.add(a);
+	public void setCurrentRole(Activation a, String role) {
+		getCurrentSQLSessionContext(a.getCallActivation()).
+			setRole(role);
 	}
 
+
 	/**
-	 * Companion of pushCaller. See usage in CallStatementResultSet#open.
+	 * @see LanguageConnectionContext#getCurrentRoleId(Activation a)
 	 */
-	public void popCaller() {
-		callers.remove(callers.size() - 1);
+	public String getCurrentRoleId(Activation a) {
+		return getCurrentSQLSessionContext(a.getCallActivation()).
+			getRole();
 	}
 
 
 	/**
-	 * Get most recent (call stack top) caller's activation
-	 * or null, if not in a call context.
+	 * Return the current SQL session context based on caller
+	 *
+	 * @param caller the activation of the caller, if any, of the
+	 * current activation
 	 */
-	public Activation getCaller() {
-		if (callers.isEmpty()) {
-			return null;
+	private SQLSessionContext getCurrentSQLSessionContext(Activation caller) {
+		SQLSessionContext curr;
+
+		if (caller == null ) {
+			// top level
+			curr = getTopLevelSQLSessionContext();
 		} else {
-			return (Activation)callers.get(callers.size() - 1);
+			// inside a nested SQL session context (stored
+			// procedure/function), the SQL session context is
+			// maintained in the activation of the caller
+			curr = caller.getNestedSQLSessionContext();
 		}
+
+		return curr;
 	}
 
 
 	/**
-	 * Set the current role
-	 *
-	 * @param a activation of set role statement
-	 * @param role	the id of the role to be set to current
+	 * Return the current SQL session context based on statement context
 	 */
-	public void setCurrentRole(Activation a, String role) {
-		Activation caller = a.getCallActivation();
-
-		if (caller != null ) {
-			//inside a stored procedure context
-			caller.setNestedCurrentRole(role);
+	private SQLSessionContext getCurrentSQLSessionContext() {
+		StatementContext ctx = getStatementContext();
+		SQLSessionContext curr;
+		
+		if (ctx == null || !ctx.inUse()) {
+			curr = getTopLevelSQLSessionContext();
 		} else {
-			// top level
-			this.currentRole = role;
+			// We are inside a nested connection in a procedure of
+			// function.
+			curr = ctx.getSQLSessionContext();
+
+			if (SanityManager.DEBUG) {
+				SanityManager.ASSERT(
+					curr != null,
+					"SQL session context should never be empty here");
+			}
 		}
+
+		return curr;
 	}
 
 
 	/**
-	 * Get the current role authorization identifier of the dynamic
-	 * call context associated with this activation.
-	 *
-	 * @param a activation  of statement needing current role
-	 * @return String	the role id
+	 * @see LanguageConnectionContext#setupNestedSessionContext(Activation a)
 	 */
-	public String getCurrentRoleId(Activation a) {
-		Activation caller = a.getCallActivation();
+	public void setupNestedSessionContext(Activation a) {
+		SQLSessionContext sc = a.getNestedSQLSessionContext();
 
-		if (caller != null ) {
-			// Want current role of stored procedure context
-			// Note that it may have returned at this point, but the
-			// activation still keeps track on what the current role
-			// was when we returned.
-			return caller.getNestedCurrentRole();
-		} else {
-			// Top level current role, no stored procedure call
-			// context.
-			return currentRole;
+		// Semantics for roles dictate (SQL 4.34.1.1 and 4.27.3.) that the
+		// role is initially inherited from the current session
+		// context. (Since we always run with INVOKER security
+		// characteristic. Derby can't yet run with DEFINER's rights).
+		//
+		sc.setRole(getCurrentRoleId(a));
+
+		// Inherit current default schema. The initial value of the
+		// default schema is implementation defined. In Derby we
+		// inherit it when we invoke stored procedures and functions.
+		sc.setDefaultSchema(getDefaultSchema(a));
+
+		StatementContext stmctx = getStatementContext();
+
+		// Since the statement is an invocation, it will now be
+		// associated with the pushed SQLSessionContext (and no longer
+		// just share that of its caller (or top).  The statement
+		// contexts of nested connection statements will inherit sc so
+		// the SQL session context is available when nested statements
+		// are compiled (and executed, for the most part).  However,
+		// for dynamic result sets, the relevant statement context
+		// (originating result set) is no longer available for
+		// execution time references to the SQL session context, so we
+		// rely on the activation of the caller for accessing it,
+		// cf. e.g. overload variants of
+		// getDefaultSchema/setDefaultSchema.  If such nested
+		// connections themselves turn out to be invocations, they in
+		// turn get a new SQLSessionContext associated with them etc.
+		stmctx.setSQLSessionContext(sc);
+	}
+
+
+	/**
+	 * Get the value of topLevelSSC, possibly initializing it first.
+	 * @see GenericLanguageConnectionContext#topLevelSSC
+	 */
+	private SQLSessionContext getTopLevelSQLSessionContext() {
+		if (topLevelSSC == null) {
+			topLevelSSC = new SQLSessionContextImpl(
+				getInitialDefaultSchemaDescriptor());
 		}
+		return topLevelSSC;
 	}
+
+
+	/**
+	 * @see LanguageConnectionContext#createSQLSessionContext
+	 */
+	public SQLSessionContext createSQLSessionContext() {
+		return new SQLSessionContextImpl(
+			getInitialDefaultSchemaDescriptor());
+	}
+
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericStatementContext.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericStatementContext.java?rev=643920&r1=643919&r2=643920&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericStatementContext.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/GenericStatementContext.java Wed Apr  2 07:35:37 2008
@@ -33,12 +33,14 @@
 
 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
 import org.apache.derby.iapi.sql.conn.StatementContext;
+import org.apache.derby.iapi.sql.conn.SQLSessionContext;
 
 import org.apache.derby.iapi.sql.depend.Dependency;
 import org.apache.derby.iapi.sql.depend.DependencyManager;
 
 import org.apache.derby.iapi.sql.execute.NoPutResultSet;
 
+import org.apache.derby.iapi.sql.Activation;
 import org.apache.derby.iapi.sql.ResultSet;
 import org.apache.derby.iapi.sql.ParameterValueSet;
 
@@ -96,6 +98,16 @@
 	*/
 	private short			sqlAllowed = -1;
 
+	/**
+	 * The activation associated with this context, or null
+	 */
+	private Activation activation;
+
+	/**
+	 * The SQLSessionContext associated with a statement context.
+	 */
+	private SQLSessionContext sqlSessionContext;
+
 	/*
 	   constructor
 		@param tc transaction
@@ -228,7 +240,9 @@
             cancelTask = null;
         }
         cancellationFlag = false;
-	}
+        activation = null;
+		sqlSessionContext = null;
+    }
 
 	/**
 	 * @see StatementContext#setSavePoint
@@ -743,5 +757,33 @@
 		}
 		return sb;
 
+	}
+
+	/**
+	 * @see StatementContext#setActivation(Activation a)
+	 */
+	public void setActivation(Activation a) {
+		activation = a;
+	}
+
+	/**
+	 * @see StatementContext#getActivation
+	 */
+	public Activation getActivation() {
+		return activation;
+	}
+
+	/**
+	 * @see StatementContext#getSQLSessionContext
+	 */
+	public SQLSessionContext getSQLSessionContext() {
+		return sqlSessionContext;
+	}
+
+	/**
+	 * @see StatementContext#setSQLSessionContext(SQLSessionContext ctx)
+	 */
+	public void setSQLSessionContext(SQLSessionContext ctx) {
+		sqlSessionContext = ctx;
 	}
 }

Added: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/SQLSessionContextImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/SQLSessionContextImpl.java?rev=643920&view=auto
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/SQLSessionContextImpl.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/SQLSessionContextImpl.java Wed Apr  2 07:35:37 2008
@@ -0,0 +1,53 @@
+/*
+
+   Derby - Class org.apache.derby.impl.sql.conn.SQLSessionContextImpl
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to you under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+
+package org.apache.derby.impl.sql.conn;
+
+import java.lang.String;
+import org.apache.derby.iapi.sql.conn.SQLSessionContext;
+import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
+
+public class SQLSessionContextImpl implements SQLSessionContext {
+
+    private String currentRole;
+    private SchemaDescriptor currentDefaultSchema;
+
+    public SQLSessionContextImpl (SchemaDescriptor sd) {
+        currentRole = null;
+        currentDefaultSchema = sd;
+    }
+
+    public void setRole(String role) {
+        currentRole = role;
+    }
+
+    public String getRole() {
+        return currentRole;
+    }
+
+    public void setDefaultSchema(SchemaDescriptor sd) {
+        currentDefaultSchema = sd;
+    }
+
+    public SchemaDescriptor getDefaultSchema() {
+        return currentDefaultSchema;
+    }
+}

Propchange: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/conn/SQLSessionContextImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/BaseActivation.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/BaseActivation.java?rev=643920&r1=643919&r2=643920&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/BaseActivation.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/BaseActivation.java Wed Apr  2 07:35:37 2008
@@ -47,6 +47,7 @@
 import org.apache.derby.iapi.sql.ResultSet;
 import org.apache.derby.iapi.sql.compile.Optimizer;
 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
+import org.apache.derby.iapi.sql.conn.SQLSessionContext;
 import org.apache.derby.iapi.sql.depend.DependencyManager;
 import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
 import org.apache.derby.iapi.sql.execute.ConstantAction;
@@ -140,33 +141,38 @@
 	private int[] autoGeneratedKeysColumnIndexes ;
 	private String[] autoGeneratedKeysColumnNames ;
 
-	// Authorization stack frame, cf. SQL 2003 4.31.1.1 and 4.27.3 is
-	// implemented as follows: Statements at root connection level
-	// (not executed within a stored procedure), maintain the current
-	// role in the lcc.  In this case, 'callActivation' is null.  If
-	// we are executing SQL inside a stored procedure (nested
-	// connection), then 'callActivation' will be non-null, and we
-	// maintain the current role in the activation of the calling
-	// statement, see 'setNestedCurrentRole'. The current role of a call
-	// context is kept in the field 'nestedCurrentRole'.
-	//
-	// 'callActivation' is set when activation is created (see
-	// GenericPreparedStatement#getActivation based on the top of the
-	// dynamic call stack of activation, see
-	// GenericLanguageConnectionContext#getCaller.
-	//
-	// Corner case: When a dynamic result set references current role,
-	// the value retrieved will always be that of the current role
-	// when the statement is executed (inside), not the current value
-	// when the result set is accessed outside the stored procedure.
-	//
-	// Consequence of this implementation: If more than one nested
-	// connection is used inside a shared procedure, they will share
-	// the current role setting. Since the same dynamic call context
-	// is involved, this seems correct.
-	//
+	/**
+	 * The 'callActivation' of an activation of a statement executing in
+	 * the root connection is null.
+	 *
+	 * A non-null 'callActivation' represents the activation of the
+	 * calling statement.
+	 *
+	 * That is, if we are executing an SQL statement ('this'
+	 * activation) inside a stored procedure or function in a nested
+	 * connection, then 'callActivation' will be non-null.
+	 *
+	 * 'callActivation' is set when this activation is created (@see
+	 * GenericPreparedStatement#getActivation) based on the top of the
+	 * dynamic call stack of execution, which is tracked by
+	 * StatementContext. The nested SQL session context is initialized
+	 * by code generated for the call, after parsameters are evaluated
+	 * @see org.apache.derby.impl.sql.compile.StaticMethodCallNode#generateSetupNestedSessionContext
+	 *
+	 */
 	private Activation callActivation;
-	private String nestedCurrentRole;
+
+	/**
+	 * The SQL session context of a call is kept here. Also, @see
+	 * BaseActivation#callActivation.
+
+	 * A nested execution maintains its session context,
+	 * nestedSQLSessionContext, in the activation of the calling
+	 * statement's activation ('this'). While not inside a stored
+	 * procedure or function, SQL session state state is held by the
+	 * LanguageConnectionContext.
+	 */
+	private SQLSessionContext nestedSQLSessionContext;
 
 	//Following is the position of the session table names list in savedObjects in compiler context
 	//This is updated to be the correct value at cursor generate time if the cursor references any session table names.
@@ -1333,25 +1339,17 @@
 	}
 
 	/**
-	 * Set the current role name of the dynamic call context stemming
-	 * from this activation (which must be a stored
-	 * procedure/function call).
-	 *
-	 * @param role The name of the current role
+	 * Return the current SQL session context for all immediately
+	 * nested connections stemming from the call or function
+	 * invocation of the statement corresponding to this activation.
 	 */
-	public void setNestedCurrentRole(String role) {
-		nestedCurrentRole = role;
-	}
+	public SQLSessionContext getNestedSQLSessionContext() {
 
-	/**
-	 * Get the current role name of the dynamic call context stemming
-	 * from this activation (which must be a stored
-	 * procedure/function call).
-	 *
-	 * @return The name of the current role
-	 */
-	public String getNestedCurrentRole() {
-		return nestedCurrentRole;
+		if (nestedSQLSessionContext == null) {
+			nestedSQLSessionContext = lcc.createSQLSessionContext();
+		}
+
+		return nestedSQLSessionContext;
 	}
 
 	/**

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/BasicNoPutResultSetImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/BasicNoPutResultSetImpl.java?rev=643920&r1=643919&r2=643920&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/BasicNoPutResultSetImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/BasicNoPutResultSetImpl.java Wed Apr  2 07:35:37 2008
@@ -781,6 +781,7 @@
 			{
 				subqueryTrackingArray = statementContext.getSubqueryTrackingArray();
 			}
+            statementContext.setActivation(activation);
 		}
 
 	}

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CallStatementResultSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CallStatementResultSet.java?rev=643920&r1=643919&r2=643920&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CallStatementResultSet.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CallStatementResultSet.java Wed Apr  2 07:35:37 2008
@@ -73,25 +73,7 @@
 	{
 		setup();
 
-        LanguageConnectionContext lcc =
-            activation.getLanguageConnectionContext();
-
-        // Push the "authorization stack" of SQL 2003, vol 2, section
-        // 4.34.1.1 and 4.27.3.
-        lcc.pushCaller(activation);
-
-        // Copy the current role into top cell of stack. Activations
-        // inside nested connections look to this activation for
-        // keeping its current role rather than rely on what's in lcc
-        // (top level only).
-        activation.setNestedCurrentRole(lcc.getCurrentRoleId(activation));
-
-        try {
-            methodCall.invoke(activation);
-        }
-        finally {
-            activation.getLanguageConnectionContext().popCaller();
-        }
+        methodCall.invoke(activation);
     }
 
     /**

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DropSchemaConstantAction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DropSchemaConstantAction.java?rev=643920&r1=643919&r2=643920&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DropSchemaConstantAction.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DropSchemaConstantAction.java Wed Apr  2 07:35:37 2008
@@ -96,7 +96,7 @@
 
         SchemaDescriptor sd = dd.getSchemaDescriptor(schemaName, null, true);
 
-        sd.drop(lcc);
+        sd.drop(lcc, activation);
 
 	}
 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SetSchemaConstantAction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SetSchemaConstantAction.java?rev=643920&r1=643919&r2=643920&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SetSchemaConstantAction.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/SetSchemaConstantAction.java Wed Apr  2 07:35:37 2008
@@ -121,6 +121,6 @@
 
                 SchemaDescriptor sd = dd.getSchemaDescriptor(thisSchemaName,
                         lcc.getTransactionExecute(), true);
-		lcc.setDefaultSchema(sd);
+		lcc.setDefaultSchema(activation, sd);
 	}
 }

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/RolesTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/RolesTest.java?rev=643920&r1=643919&r2=643920&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/RolesTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/RolesTest.java Wed Apr  2 07:35:37 2008
@@ -31,6 +31,7 @@
 import junit.framework.Test;
 import junit.framework.TestSuite;
 import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.JDBC;
 import org.apache.derbyTesting.junit.DatabasePropertyTestSetup;
 import org.apache.derbyTesting.junit.JDBC;
 import org.apache.derbyTesting.junit.TestConfiguration;
@@ -70,6 +71,7 @@
     private final static String revokeWarn               = "01007";
     private final static String notIdle                  = "25001";
     private final static String invalidRoleName          = "4293A";
+    private final static String userException = "38000";
 
     private int MAX_IDENTIFIER_LENGTH = 128;
     /**
@@ -431,12 +433,6 @@
         doStmt("set role 'FOO'",
                sqlAuthorizationRequired, null, null);
         
-        // JSR169 cannot run with tests with stored procedures that do
-        // database access - for they require a DriverManager connection to
-        // jdbc:default:connection; DriverManager is not supported with JSR169
-        if (!JDBC.vmSupportsJSR169())
-            doSetRoleInsideStoredProcedures("FOO");
-
         doStmt("set role none",
                sqlAuthorizationRequired, null , null);
 
@@ -464,6 +460,10 @@
                                sqlAuthorizationRequired, null , null);
         assertRoleInRs(rs, "ROLE", "BAR");
 
+        if (rs != null) {
+            rs.close();
+        }
+
         /*
          * REVOKE role
          */
@@ -774,7 +774,7 @@
         try {
             pstmt.setString(1, "BAR");
             int rowcnt = pstmt.executeUpdate();
-            assertEquals(rowcnt, 0, "rowcount from set role ? not 0");
+            assertEquals("rowcount from set role ? not 0", rowcnt, 0);
         } catch (SQLException e) {
             fail("execute of set role ? failed: [foo]" + e);
         }
@@ -783,7 +783,7 @@
         try {
             pstmt.setString(1, null);
             int rowcnt = pstmt.executeUpdate();
-            assertEquals(rowcnt, 0, "rowcount from set role ? not 0");
+            assertEquals("rowcount from set role ? not 0", rowcnt, 0);
         } catch (SQLException e) {
             fail("execute of set role ? failed: [NONE] " + e);
         }
@@ -795,7 +795,7 @@
             try {
                 pstmt.setString(1, "NONE");
                 int rowcnt = pstmt.executeUpdate();
-                assertEquals(rowcnt, 0, "rowcount from set role ? not 0");
+                assertEquals("rowcount from set role ? not 0", rowcnt, 0);
                 ResultSet rs = doQuery("values current_role", n_a, null , n_a );
                 assertRoleInRs(rs, "NONE", n_a);
                 rs.close();
@@ -815,57 +815,12 @@
 
     /* Test that current role is handled correctly when inside a
      * stored procedure.  The SQL standard requires we have an
-     * "authorization stack", see section 4.34.1.1. This implies that
-     * current role is popped at end of stored procedure.
-     * We test two levels deep.
+     * "authorization stack", see section 4.34.1.1 and
+     * 4.27.3. Initially tested here, but now moved to
+     * lang/SQLSessionContextTest.
      */
-    private void doSetRoleInsideStoredProcedures(String currRole)
-            throws SQLException
-    {
-        if (_authLevel != NO_SQLAUTHORIZATION) {
-            String n_a = null; // auth level not used for this test
 
-            doStmt("create procedure p2(role varchar(255))" +
-                   "  dynamic result sets 1 language java parameter style java"+
-                   "  external name 'org.apache.derbyTesting." +
-                   "functionTests.tests.lang.RolesTest.p2'" +
-                   "  modifies sql data",
-                   n_a, null, null);
-            doStmt("create function f2(role varchar(255))" +
-                   "  returns int language java parameter style java" +
-                   "  external name 'org.apache.derbyTesting." +
-                   "functionTests.tests.lang.RolesTest.f2'" +
-                   "  reads sql data",
-                   n_a, null, null);
-            doStmt("call p2('" + currRole + "')",
-                   n_a , null , null );
-
-            // Dynamic result set: At what time should CURRENT_ROLE be
-            // evaluated?  Logically at the inside, so it should be
-            // "BAR" also when accessed on outside. I think. Anyway,
-            // that's what's implemented: the activation of the call
-            // is still live and holds the current role as it was
-            // inside the nested scope even when the procedure call
-            // has returned.
-            ResultSet prs = _stm.getResultSet();
-            assertRoleInRs(prs, "BAR", "BAR");
-            prs.close();
-
-            // check that role didn't get impacted by change inside p2
-            // too 'BAR':
-            ResultSet rs = doQuery("values current_role",
-                                   n_a , null , null );
-            assertRoleInRs(rs, currRole, currRole);
-            rs.close();
 
-            rs = doQuery("values f2('" + currRole + "')",
-                         n_a , null , null );
-            rs.close();
-
-            doStmt("drop procedure p2", n_a, null, null);
-            doStmt("drop function  f2", n_a, null, null);
-        }
-    }
 
     private void assertSystableRowCount(String table,
                                         int rcNoAuth,
@@ -953,9 +908,10 @@
         println("SYS.SYSROLES:");
 
         while (rs.next()) {
-            println("r=" + rs.getString(1) + " -ee:" + rs.getString(2) +
-                    " -or:" + rs.getString(3) + " a:" + rs.getString(4) +
-                    " d:" + rs.getString(5));
+            println("uuid=" + rs.getString(1) +
+                    " r=" + rs.getString(2) + " -ee:" + rs.getString(3) +
+                    " -or:" + rs.getString(4) + " a:" + rs.getString(5) +
+                    " d:" + rs.getString(6));
         }
 
         rs.close();
@@ -1036,45 +992,14 @@
         if (_authLevel == NO_SQLAUTHORIZATION) {
             assertNull(rs);
         } else {
-            assertTrue("result set empty", rs.next());
-            String actualRole = rs.getString(1);
-
             if (isDbo()) {
-                assertTrue("role is " + actualRole + ", expected " + dboRole,
-                           dboRole.equals(actualRole));
+                JDBC.assertSingleValueResultSet(rs, dboRole);
             } else {
-                assertTrue("role is " + actualRole + ", expected " + notDboRole,
-                           notDboRole.equals(actualRole));
+                JDBC.assertSingleValueResultSet(rs, notDboRole);
             }
-
-            // cardinality should be 1
-            assertFalse("result set not empty", rs.next());
-        }
-    }
-
-    private void assertEquals(int a, int b, String txt)
-    {
-        if (a!=b) {
-            fail(txt);
         }
     }
 
-    private static void assertRsSingleStringValue(ResultSet rs,
-                                                  String expectedValue)
-            throws SQLException
-    {
-
-        assertTrue("result set empty", rs.next());
-        String actualValue = rs.getString(1);
-
-        assertTrue("string is " + actualValue + ", expected " + expectedValue,
-                   actualValue.equals(expectedValue));
-
-        // cardinality should be 1
-        assertFalse("result set not empty", rs.next());
-    }
-
-
     /**
      * Utility function used to test auto-drop of grant routine
      * permission to a role
@@ -1082,160 +1007,6 @@
      */
     public static int f1()
     {
-        return 1;
-    }
-
-
-    /**
-     * Utility procedure used to test that current role
-     * is stacked correctly according to dynamic scope.
-     */
-    public static void p2(String roleOutside, ResultSet[] rs1)
-            throws SQLException
-    {
-        Connection conn1 = null;
-        Connection conn2 = null;
-
-        try {
-            conn1 = DriverManager.getConnection("jdbc:default:connection");
-            PreparedStatement ps =
-                conn1.prepareStatement("values current_role");
-
-            // check that we inherit role correctly
-            ResultSet rs = ps.executeQuery();
-            assertRsSingleStringValue(rs, roleOutside);
-            rs.close();
-
-            // set the role to something else
-            Statement stm = conn1.createStatement();
-            stm.execute("set role bar");
-            rs = ps.executeQuery();
-
-            // check that role got set
-            assertRsSingleStringValue(rs, "BAR");
-
-            // another nesting level to test authorization stack even more
-            stm.execute(
-                "create procedure calledNestedFromP2(role varchar(255))" +
-                "  language java parameter style java" +
-                "  external name 'org.apache.derbyTesting." +
-                "functionTests.tests.lang.RolesTest.calledNestedFromP2'" +
-                "  modifies sql data");
-            conn1.commit(); // need to be idle
-            stm.execute("call calledNestedFromP2('BAR')");
-
-            rs = ps.executeQuery();
-
-            // check that role didn't get impacted by change inside
-            // calledNestedFromP2 too 'FOO':
-            assertRsSingleStringValue(rs, "BAR");
-            stm.execute("drop procedure calledNestedFromP2");
-
-            // Test that the role is shared by another nested
-            // connection also.
-            conn2 = DriverManager.getConnection("jdbc:default:connection");
-            PreparedStatement ps2 =
-                conn2.prepareStatement("values current_role");
-            ResultSet rs2 = ps2.executeQuery();
-            assertRsSingleStringValue(rs2, "BAR");
-
-            // Pass out CURRENT_ROLE in a dynamic result set.
-            rs = ps.executeQuery();
-            rs1[0] = rs;
-
-        } finally {
-
-            if (conn1 != null) {
-                try {
-                    conn1.close();
-                } catch (Exception e) {
-                }
-            }
-
-            if (conn2 != null) {
-                try {
-                    conn2.close();
-                } catch (Exception e) {
-                }
-            }
-        }
-
-    }
-
-    /**
-     * Called from p2 so we get to test with a call stack 3 levels
-     * deep.
-     */
-    public static void calledNestedFromP2(String roleOutside)
-            throws SQLException
-    {
-        Connection conn1 = null;
-
-        try {
-            conn1 = DriverManager.getConnection("jdbc:default:connection");
-            PreparedStatement ps =
-                conn1.prepareStatement("values current_role");
-
-            // check that we inherit role correctly
-            ResultSet rs = ps.executeQuery();
-            assertRsSingleStringValue(rs, roleOutside);
-            rs.close();
-
-            // set the role to something else
-            Statement stm = conn1.createStatement();
-            stm.execute("set role foo");
-            rs = ps.executeQuery();
-
-            // check that role got set
-            assertRsSingleStringValue(rs, "FOO");
-
-        } finally {
-            if (conn1 != null) {
-                try {
-                    conn1.close();
-                } catch (Exception e) {
-                }
-            }
-        }
-    }
-
-
-    /**
-     * Utility function used to test that current role
-     * is stacked correctly according to scope.
-     */
-    public static int f2(String roleOutside) throws SQLException
-    {
-        Connection conn1 = null;
-
-        try {
-            conn1 = DriverManager.getConnection("jdbc:default:connection");
-            PreparedStatement ps =
-                conn1.prepareStatement("values current_role");
-
-            // check that we inherit role correctly
-            ResultSet rs = ps.executeQuery();
-            assertRsSingleStringValue(rs, roleOutside);
-            rs.close();
-
-            // set the role to something else
-            Statement stm = conn1.createStatement();
-            stm.execute("set role bar");
-            rs = ps.executeQuery();
-
-            // check that role got set
-            assertRsSingleStringValue(rs, "BAR");
-
-        } finally {
-
-            if (conn1 != null) {
-                try {
-                    conn1.close();
-                } catch (Exception e) {
-                }
-            }
-
-        }
         return 1;
     }
 }



Mime
View raw message