You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by da...@apache.org on 2010/06/07 15:51:09 UTC

svn commit: r952227 [2/2] - in /db/derby/code/trunk/java: engine/org/apache/derby/catalog/types/ 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/cat...

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/RoutinesDefinersRightsTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/RoutinesDefinersRightsTest.java?rev=952227&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/RoutinesDefinersRightsTest.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/RoutinesDefinersRightsTest.java Mon Jun  7 13:51:07 2010
@@ -0,0 +1,504 @@
+/*
+
+  Derby - Class org.apache.derbyTesting.functionTests.tests.lang.RoutinesDefinersRightsTest
+
+  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.derbyTesting.functionTests.tests.lang;
+
+import java.sql.SQLException;
+import java.sql.Connection;
+import java.sql.Statement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.DriverManager;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.DatabasePropertyTestSetup;
+import org.apache.derbyTesting.junit.TestConfiguration;
+import org.apache.derbyTesting.junit.CleanDatabaseTestSetup;
+import org.apache.derbyTesting.junit.JDBC;
+
+/**
+ * Test that routines declared with EXTERNAL SECURITY DEFINER/INVOKER behaves
+ * correctly. In addition to tests found here, see also the test in
+ * org.apache.derbyTesting.functionTests.tests.upgradeTests.
+ * Changes10_7#testExternalSecuritySpecification, which checks that the feature
+ * will not work if SQL authorization is not enabled.
+ *
+ */
+public class RoutinesDefinersRightsTest extends BaseJDBCTestCase
+{
+    private final static String pwSuffix = "pwSuffix";
+
+    /* SQL states */
+    private final static String NOEXECUTEPERMISSION  = "42504";
+    private final static String NOCOLUMNPERMISSION = "42502";
+    private final static String MULTIPLE_ELEMENTS = "42613";
+
+    // job categories
+    private final static int BOSS = 0;
+    private final static int MIDDLEMANAGER = 1;
+    private final static int FOOTSOLDIER = 2;
+
+
+    private final static String[] users = {"test_dbo", "PHB", "Dilbert"};
+    private final static double[] wages = {1000.0, 500.0, 100.0};
+    private final static int[] categories = {BOSS, MIDDLEMANAGER, FOOTSOLDIER};
+    /**
+     * Create a new instance of RoutinesDefinersRightsTest.
+     *
+     * @param name Fixture name
+     */
+    public RoutinesDefinersRightsTest(String name)
+    {
+        super(name);
+    }
+
+
+    /**
+     * Construct top level suite in this JUnit test
+     *
+     * @return A suite containing embedded and client suites.
+     */
+    public static Test suite()
+    {
+        TestSuite suite = new TestSuite("RoutinesDefinersRightsTest");
+
+        if (!JDBC.vmSupportsJSR169()) {
+            // 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.
+            suite.addTest(makeSuite());
+
+            // suite.addTest(
+            //     TestConfiguration.clientServerDecorator(makeSuite()));
+        }
+
+
+        return suite;
+    }
+
+    /**
+     * Construct suite of tests
+     *
+     * @return A suite containing the test cases.
+     */
+    private static Test makeSuite()
+    {
+        /* Tests running with sql authorization set.  First decorate
+         * with clean database, then with authentication +
+         * sqlAuthorization.
+         */
+        Test clean = new CleanDatabaseTestSetup(
+            new TestSuite(RoutinesDefinersRightsTest.class)) {
+                protected void decorateSQL(Statement s)
+                        throws SQLException {
+
+                    s.execute("create role middleManager");
+                    s.execute("create table s1.wages(employeeId int," +
+                              "                   category int," +
+                              "                   salary double," +
+                              "                   name VARCHAR(20))");
+                    PreparedStatement ps = s.getConnection().prepareStatement(
+                        "insert into s1.wages values (?,?,?,?)");
+
+                    for (int i=BOSS; i <= FOOTSOLDIER; i++) {
+                        ps.setInt(1, 1000 + i);
+                        ps.setInt(2, i);
+                        ps.setDouble(3, wages[i]);
+                        ps.setString(4, users[i]);
+                        ps.execute();
+                    }
+
+                    ps.close();
+
+                    s.execute
+                        ("create function s1.lookupWageFootSoldier(int) " +
+                         "returns double " +
+                         "language java parameter style java external name " +
+                         "'org.apache.derbyTesting.functionTests.tests.lang." +
+                         "RoutinesDefinersRightsTest.lookupWageFootSoldier' " +
+                         "EXTERNAL SECURITY DEFINER " +
+                         "reads sql data called on null input");
+
+                    s.execute
+                        ("grant execute on function s1.lookupWageFootSoldier " +
+                         "   to phb");
+
+                    s.execute
+                        ("create function s1.lookupWageFootSoldierI(int) " +
+                         "returns double " +
+                         "language java parameter style java external name " +
+                         "'org.apache.derbyTesting.functionTests.tests.lang." +
+                         "RoutinesDefinersRightsTest.lookupWageFootSoldier' " +
+                         "EXTERNAL SECURITY INVOKER " +
+                         "reads sql data called on null input");
+
+                    s.execute
+                        ("grant execute on function " +
+                         "    s1.lookupWageFootSoldierI to phb");
+
+                    s.execute
+                        ("create procedure s1.spTestBuiltins() " +
+                         "language java parameter style java external name " +
+                         "'org.apache.derbyTesting.functionTests.tests.lang." +
+                         "RoutinesDefinersRightsTest.spTestBuiltins' " +
+                         "EXTERNAL SECURITY DEFINER " +
+                         "reads sql data");
+
+                    s.execute
+                        ("grant execute on procedure s1.spTestBuiltins " +
+                         "   to phb");
+
+                    // Table function
+                    s.execute
+                        ("create function s1.selectFootSoldiers() " +
+                         "returns table (" +
+                         "    employeeId int," +
+                         "    category int," +
+                         "    salary double," +
+                         "    name varchar(20))" +
+                         "language java parameter style " +
+                         "    derby_jdbc_result_set " +
+                         "external name " +
+                         "'org.apache.derbyTesting.functionTests.tests.lang." +
+                         "RoutinesDefinersRightsTest.selectFootSoldiers' " +
+                         "EXTERNAL SECURITY DEFINER " +
+                         "reads sql data");
+
+                    // PHB needs to set his role to be able to use
+                    // s1.selectFootSoldiers. Just to vary a bit..
+                    s.execute
+                        ("grant execute on function s1.selectFootSoldiers " +
+                         "    to middleManager");
+                    s.execute
+                        ("grant middleManager to phb");
+
+                    s.execute
+                        ("create function s1.selectFootSoldiersI() " +
+                         "returns table (" +
+                         "    employeeId int," +
+                         "    category int," +
+                         "    salary double," +
+                         "    name varchar(20))" +
+                         "language java parameter style " +
+                         "    derby_jdbc_result_set " +
+                         "external name " +
+                         "'org.apache.derbyTesting.functionTests.tests.lang." +
+                         "RoutinesDefinersRightsTest.selectFootSoldiers' " +
+                         "EXTERNAL SECURITY INVOKER " +
+                         "reads sql data");
+                    s.execute
+                        ("grant execute on function s1.selectFootSoldiersI " +
+                         "    to middleManager");
+
+                    s.execute
+                        ("create schema phb authorization phb");
+                    s.execute
+                        ("create function phb.lookupDilbertWage() " +
+                         "returns double " +
+                         "language java parameter style java external name " +
+                         "'org.apache.derbyTesting.functionTests.tests.lang." +
+                         "RoutinesDefinersRightsTest.lookupDilbertWage' " +
+                         "EXTERNAL SECURITY DEFINER " +
+                         "reads sql data called on null input");
+                    s.execute
+                        ("grant execute on function phb.lookupDilbertWage " +
+                         "    to dilbert");
+
+                    // Check confliciting clauses
+                    assertStatementError(
+                        new String[]{MULTIPLE_ELEMENTS},
+                        s,
+                        "create function phb.lookupDilbertWage() " +
+                        "returns double " +
+                        "language java parameter style java external name " +
+                        "'org.apache.derbyTesting.functionTests.tests.lang." +
+                        "RoutinesDefinersRightsTest.lookupDilbertWage' " +
+                        "EXTERNAL SECURITY DEFINER " +
+                        "EXTERNAL SECURITY INVOKER " +
+                        "reads sql data called on null input");
+                }
+            };
+
+        return
+            TestConfiguration.sqlAuthorizationDecorator(
+                    DatabasePropertyTestSetup.builtinAuthentication(
+                        clean, users, pwSuffix));
+    }
+
+
+    public void testDefinersRights() throws SQLException
+    {
+        Connection c = null;
+        ResultSet rs = null;
+        Statement stm = null;
+
+        // Shut down database, just so we are sure the routine info is
+        // persisted into the on-disk dictionary correctly before we try to use
+        // it.
+        TestConfiguration.getCurrent().shutdownDatabase();
+
+        // Try as vainly as dilbert to execute lookupWageFootSoldier
+        c = openUserConnection("Dilbert");
+        stm = c.createStatement();
+        assertStatementError(
+            new String[]{NOEXECUTEPERMISSION},
+            stm,
+            "values s1.lookupWageFootSoldier(1002)");
+        stm.close();
+        c.close();
+
+        // Try as PHB
+        c = openUserConnection("PHB");
+        stm = c.createStatement();
+        rs = stm.executeQuery("values s1.lookupWageFootSoldier(1002)");
+        JDBC.assertSingleValueResultSet(rs, "100.0");
+        stm.close();
+        c.close();
+
+        // dbo can execute lookupWageFootSoldier, since he has select
+        // privileges on the wages table.
+        Connection dboConn = getConnection();
+        Statement dbos = dboConn.createStatement();
+
+        rs = dbos.executeQuery("values s1.lookupWageFootSoldier(1002)");
+        JDBC.assertSingleValueResultSet(rs, "100.0");
+
+        // We see that the method will not return wages for anything but foot
+        // soldiers, even for the dbo:
+        rs = dbos.executeQuery("values s1.lookupWageFootSoldier(1001)");
+        JDBC.assertSingleValueResultSet(rs, "-1.0");
+
+        dbos.close();
+        dboConn.close();
+
+        // ----------------------------------------
+        // Now try with a table function
+
+        c = openUserConnection("PHB");
+
+        stm = c.createStatement();
+        stm.executeUpdate("set role middlemanager");
+        rs = stm.executeQuery(
+            "select * from table (s1.selectFootSoldiers()) as t");
+        JDBC.assertFullResultSet(
+            rs,
+            new String[][]{{"1002", "2", "100.0", "Dilbert"}});
+
+        // Check that user and role is unchanged after call
+        rs = stm.executeQuery(
+            "values (current_user, session_user, current_role)");
+        JDBC.assertFullResultSet(
+            rs,
+            new String[][]{{"PHB", "PHB", "\"MIDDLEMANAGER\""}});
+
+        stm.close();
+        c.close();
+
+        // ------------------------------------
+        // Try with two levels of routines with different definers
+        c = openUserConnection("Dilbert");
+        stm = c.createStatement();
+        rs = stm.executeQuery("values phb.lookupDilbertWage()");
+        JDBC.assertSingleValueResultSet(rs, "100.0");
+
+        // sanity when we return
+        rs = stm.executeQuery(
+            "values (current_user, session_user, current_role)");
+        JDBC.assertFullResultSet(
+            rs,
+            new String[][]{{"DILBERT", "DILBERT", null}});
+
+        stm.close();
+        c.close();
+
+    }
+
+    public void testBuiltins() throws SQLException{
+        Connection c = openUserConnection("PHB");
+        Statement stm = c.createStatement();
+        stm.executeUpdate("set role middlemanager");
+        stm.executeUpdate("call s1.spTestBuiltins()");
+        stm.close();
+        c.close();
+    }
+
+
+    public void testInvokersRights() throws SQLException{
+        Connection c = null;
+        ResultSet rs = null;
+        Statement stm = null;
+
+        // Try as vainly as dilbert to execute lookupWageFootSoldier
+        c = openUserConnection("Dilbert");
+        stm = c.createStatement();
+        assertStatementError(
+            new String[]{NOEXECUTEPERMISSION},
+            stm,
+            "values s1.lookupWageFootSoldierI(1002)");
+        stm.close();
+        c.close();
+
+        // Try as PHB, vainly too, since no definer's rights now.
+        c = openUserConnection("PHB");
+        stm = c.createStatement();
+        assertStatementError(
+            new String[]{NOCOLUMNPERMISSION},
+            stm,
+            "values s1.lookupWageFootSoldierI(1002)");
+        stm.close();
+        c.close();
+
+        // dbo can execute lookupWageFootSoldier, since she has select
+        // privileges on the wages table.
+        Connection dboConn = getConnection();
+        Statement dbos = dboConn.createStatement();
+
+        rs = dbos.executeQuery("values s1.lookupWageFootSoldierI(1002)");
+        JDBC.assertSingleValueResultSet(rs, "100.0");
+
+        dbos.close();
+        dboConn.close();
+
+        // ----------------------------------------
+        // Now try with a table function
+
+        c = openUserConnection("PHB");
+
+        stm = c.createStatement();
+        stm.executeUpdate("set role middlemanager");
+        assertStatementError(
+            new String[]{NOCOLUMNPERMISSION},
+            stm,
+            "select * from table (s1.selectFootSoldiersI()) as t");
+
+        // Check that user and role is unchanged after failed call
+        rs = stm.executeQuery(
+            "values (current_user, session_user, current_role)");
+        JDBC.assertFullResultSet(
+            rs,
+            new String[][]{{"PHB", "PHB", "\"MIDDLEMANAGER\""}});
+
+        stm.close();
+        c.close();
+
+    }
+
+    public static double lookupWageFootSoldier(int employee)
+            throws SQLException
+    {
+        Connection c = null;
+
+        c = DriverManager.getConnection("jdbc:default:connection");
+        Statement cStmt = c.createStatement();
+
+        // Can only look up wages of foot soldiers
+        ResultSet rs = cStmt.executeQuery(
+            "select salary from s1.wages where employeeId=" +
+            employee + " and category = " + FOOTSOLDIER);
+
+        if (rs.next()) {
+            double result = rs.getDouble(1);
+            cStmt.close();
+            rs.close();
+            c.close();
+            return result;
+        } else {
+            cStmt.close();
+            rs.close();
+            c.close();
+            return -1.0;
+        }
+    }
+
+    public static ResultSet selectFootSoldiers()
+            throws SQLException
+    {
+        Connection c = null;
+
+        c = DriverManager.getConnection("jdbc:default:connection");
+        Statement cStmt = c.createStatement();
+
+        // Can only look up wages of foot soldiers
+        ResultSet rs = cStmt.executeQuery(
+            "select * from s1.wages where category = " +
+            FOOTSOLDIER);
+
+        return rs;
+    }
+
+
+    public static double lookupDilbertWage()
+            throws SQLException
+    {
+        Connection c = null;
+
+        c = DriverManager.getConnection("jdbc:default:connection");
+        Statement stm = c.createStatement();
+
+        // We are executing as middle manager so we can look up Dilberts wage
+        // for him.
+        c.commit(); // Need to be no transaction active when we set role
+        stm.executeUpdate("set role middlemanager");
+
+        // Check that definer is PHB even though we created function as dbo.
+        ResultSet rs = stm.executeQuery(
+            "values (current_user, session_user, current_role)");
+
+        JDBC.assertFullResultSet(
+            rs,
+            new String[][]{{"PHB", "DILBERT", "\"MIDDLEMANAGER\""}});
+
+        rs = stm.executeQuery(
+            "select salary from table (s1.selectFootSoldiers()) as t " +
+            "    where name='Dilbert'");
+        rs.next();
+        double result = rs.getDouble(1);
+
+        rs.close();
+        stm.close();
+        c.close();
+
+        return result;
+    }
+
+
+    public static void spTestBuiltins()
+            throws SQLException
+    {
+        Connection c = null;
+
+        c = DriverManager.getConnection("jdbc:default:connection");
+        Statement cStmt = c.createStatement();
+
+        ResultSet rs = cStmt.executeQuery(
+            "values (user, current_user, current schema, " +
+            "        session_user, current_role)");
+        JDBC.assertFullResultSet(
+            rs,
+            new String[][]{{"TEST_DBO", "TEST_DBO", "TEST_DBO", "PHB", null}});
+
+        cStmt.close();
+        c.close();
+    }
+}
+

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SQLSessionContextTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SQLSessionContextTest.java?rev=952227&r1=952226&r2=952227&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SQLSessionContextTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SQLSessionContextTest.java Mon Jun  7 13:51:07 2010
@@ -53,6 +53,8 @@ import org.apache.derbyTesting.junit.JDB
  *    {client/server, embedded} x
  *    {data base owner}
  *
+ * See also RoutinesDefinersRightsTest, which tests the current user part of
+ * the SQLSessionContext.
  */
 public class SQLSessionContextTest extends BaseJDBCTestCase
 {

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java?rev=952227&r1=952226&r2=952227&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java Mon Jun  7 13:51:07 2010
@@ -87,6 +87,7 @@ public class _Suite extends BaseTestCase
         suite.addTest(SQLSessionContextTest.suite());
         suite.addTest(RoutineSecurityTest.suite());
         suite.addTest(RoutineTest.suite());
+        suite.addTest(RoutinesDefinersRightsTest.suite());
         suite.addTest(SQLAuthorizationPropTest.suite());
         suite.addTest(StatementPlanCacheTest.suite());
         suite.addTest(StreamsTest.suite());

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/tools/dblook_makeDB.sql
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/tools/dblook_makeDB.sql?rev=952227&r1=952226&r2=952227&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/tools/dblook_makeDB.sql (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/tools/dblook_makeDB.sql Mon Jun  7 13:51:07 2010
@@ -75,6 +75,8 @@ create procedure p_deterministic() deter
 
 create procedure p_not_deterministic() language java not deterministic parameter style java modifies sql data external name 'foo.bar.wibble';
 
+create procedure p_definers_rights() language java  parameter style java modifies sql data external name 'foo.bar.wibble' external security definer;
+
 -- ----------------------------------------------
 -- Functions.
 -- ----------------------------------------------
@@ -87,6 +89,9 @@ create function f_deterministic() return
 
 create function f_not_deterministic() returns int language java parameter style java no sql not deterministic external name 'foo.bar.wibble';
 
+create function f_definers_rights() returns int language java parameter style java no sql not deterministic external name 'foo.bar.wibble' external security definer;
+
+
 -- ----------------------------------------------
 -- Tables
 -- ----------------------------------------------

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/Changes10_7.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/Changes10_7.java?rev=952227&r1=952226&r2=952227&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/Changes10_7.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/Changes10_7.java Mon Jun  7 13:51:07 2010
@@ -63,6 +63,7 @@ public class Changes10_7 extends Upgrade
 
     private static final String SYNTAX_ERROR = "42X01";
     private static final String  UPGRADE_REQUIRED = "XCL47";
+    private static final String  GRANT_REVOKE_WITH_LEGACY_ACCESS = "42Z60";
 
     ///////////////////////////////////////////////////////////////////////////////////
     //
@@ -138,4 +139,43 @@ public class Changes10_7 extends Upgrade
         s.close();
     }
 
+    /**
+     * Make sure that that database is at level 10.7 in order to enjoy
+     * routines with specified EXTERNAL SECURITY INVOKER or DEFINER.
+     */
+    public void testExternalSecuritySpecification() throws SQLException
+    {
+        String functionWithDefinersRights =
+            "create function f_4551( a varchar( 100 ) ) returns int\n" +
+            "language java parameter style java reads sql data\n" +
+            "external security definer\n" +
+            "external name 'Z.getIntValue'\n";
+
+        Statement s = createStatement();
+
+        switch ( getPhase() )
+        {
+        case PH_CREATE: // create with old version
+        case PH_POST_SOFT_UPGRADE:
+            // soft-downgrade: boot with old version after soft-upgrade
+            assertStatementError(
+                SYNTAX_ERROR, s, functionWithDefinersRights );
+            break;
+
+        case PH_SOFT_UPGRADE: // boot with new version and soft-upgrade
+            assertStatementError(
+                UPGRADE_REQUIRED, s, functionWithDefinersRights );
+            break;
+
+        case PH_HARD_UPGRADE: // boot with new version and hard-upgrade.
+            // Syntax now accepted and dictionary level ok, but
+            // sqlAuthorization not enabled (a priori) - expected.
+            assertStatementError(GRANT_REVOKE_WITH_LEGACY_ACCESS,
+                                 s, functionWithDefinersRights );
+            break;
+        }
+
+        s.close();
+    }
+
 }

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/JDBC.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/JDBC.java?rev=952227&r1=952226&r2=952227&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/JDBC.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/JDBC.java Mon Jun  7 13:51:07 2010
@@ -1289,6 +1289,25 @@ public class JDBC {
         }
     }
 
+
+    /**
+     * Asserts that the current user is the same as the one specified.
+     *
+     * @param con connection to check schema in
+     * @param schema expected user name
+     * @throws SQLException if something goes wrong
+     */
+    public static void assertCurrentUser(Connection con, String user)
+            throws SQLException {
+        Statement stmt = con.createStatement();
+        try {
+            JDBC.assertSingleValueResultSet(
+                    stmt.executeQuery("VALUES CURRENT_USER"), user);
+        } finally {
+            stmt.close();
+        }
+    }
+
     /**
      * Convert byte array to String.
      * Each byte is converted to a hexadecimal string representation.