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 ka...@apache.org on 2013/11/13 11:49:58 UTC
svn commit: r1541461 - in /db/derby/code/trunk/java:
engine/org/apache/derby/impl/sql/compile/
testing/org/apache/derbyTesting/functionTests/tests/lang/
Author: kahatlen
Date: Wed Nov 13 10:49:57 2013
New Revision: 1541461
URL: http://svn.apache.org/r1541461
Log:
DERBY-6411: Minimal select privilege should be checked in subqueries
Modified:
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CompilerContextImpl.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CursorNode.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromList.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/QueryTreeNode.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/GrantRevokeDDLTest.java
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CompilerContextImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CompilerContextImpl.java?rev=1541461&r1=1541460&r2=1541461&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CompilerContextImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CompilerContextImpl.java Wed Nov 13 10:49:57 2013
@@ -745,18 +745,18 @@ public class CompilerContextImpl extends
//DERBY-4191
if( currPrivType == Authorizer.MIN_SELECT_PRIV){
- //If we are here for MIN_SELECT_PRIV requirement, then first
- //check if there is already a SELECT privilege requirement on any
- //of the columns in the table. If yes, then we do not need to add
- //MIN_SELECT_PRIV requirement for the table because that
- //requirement is already getting satisfied with the already
- //existing SELECT privilege requirement
+ // If we are here for MIN_SELECT_PRIV requirement, then first
+ // check if there is already a SELECT privilege requirement on any
+ // of the columns in the table, or on the table itself. If yes,
+ // then we do not need to add MIN_SELECT_PRIV requirement for the
+ // table because that requirement is already getting satisfied with
+ // the already existing SELECT privilege requirement.
StatementTablePermission key = new StatementTablePermission(
tableUUID, Authorizer.SELECT_PRIV);
- StatementColumnPermission tableColumnPrivileges
- = requiredColumnPrivileges.get( key);
- if( tableColumnPrivileges != null)
+ if (requiredColumnPrivileges.containsKey(key) ||
+ requiredTablePrivileges.containsKey(key)) {
return;
+ }
}
if( currPrivType == Authorizer.SELECT_PRIV){
//If we are here for SELECT_PRIV requirement, then first check
@@ -766,10 +766,7 @@ public class CompilerContextImpl extends
//that, remove the MIN_SELECT_PRIV privilege requirement
StatementTablePermission key = new StatementTablePermission(
tableUUID, Authorizer.MIN_SELECT_PRIV);
- StatementColumnPermission tableColumnPrivileges
- = requiredColumnPrivileges.get( key);
- if( tableColumnPrivileges != null)
- requiredColumnPrivileges.remove(key);
+ requiredColumnPrivileges.remove(key);
}
StatementTablePermission key = new StatementTablePermission( tableUUID, currPrivType);
@@ -808,10 +805,7 @@ public class CompilerContextImpl extends
//that, remove the MIN_SELECT_PRIV privilege requirement
StatementTablePermission key = new StatementTablePermission(
table.getUUID(), Authorizer.MIN_SELECT_PRIV);
- StatementColumnPermission tableColumnPrivileges
- = requiredColumnPrivileges.get( key);
- if( tableColumnPrivileges != null)
- requiredColumnPrivileges.remove(key);
+ requiredColumnPrivileges.remove(key);
}
StatementTablePermission key = new StatementTablePermission( table.getUUID(), currPrivType);
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CursorNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CursorNode.java?rev=1541461&r1=1541460&r2=1541461&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CursorNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CursorNode.java Wed Nov 13 10:49:57 2013
@@ -290,24 +290,15 @@ public class CursorNode extends DMLState
+ fromList.size()
+ " on return from RS.bindExpressions()");
}
-
- //DERBY-4191 Make sure that we have minimum select privilege on
- //each of the tables in the query.
- getCompilerContext().pushCurrentPrivType(Authorizer.MIN_SELECT_PRIV);
- FromList resultSetFromList = resultSet.getFromList();
- for (int index = 0; index < resultSetFromList.size(); index++) {
- Object fromTable = resultSetFromList.elementAt(index);
- if (fromTable instanceof FromBaseTable) {
- collectTablePrivsAndStats((FromBaseTable)fromTable);
- }
- }
- getCompilerContext().popCurrentPrivType();
}
finally
{
getCompilerContext().popCurrentPrivType();
}
+ // Collect tables whose indexes we'll want to check for staleness.
+ collectTablesWithPossiblyStaleStats();
+
// bind the order by
if (orderByList != null)
{
@@ -397,39 +388,30 @@ public class CursorNode extends DMLState
}
/**
- * Collects required privileges for all types of tables, and table
- * descriptors for base tables whose index statistics we want to check for
- * staleness (or to create).
- *
- * @param fromTable the table
+ * Collects table descriptors for base tables whose index statistics we
+ * want to check for staleness (or to create).
*/
- private void collectTablePrivsAndStats(FromBaseTable fromTable) {
- TableDescriptor td = fromTable.getTableDescriptor();
- if (fromTable.isPrivilegeCollectionRequired()) {
- // We ask for MIN_SELECT_PRIV requirement of the first column in
- // the table. The first column is just a place holder. What we
- // really do at execution time when we see we are looking for
- // MIN_SELECT_PRIV privilege is as follows:
- //
- // 1) We will look for SELECT privilege at table level.
- // 2) If not found, we will look for SELECT privilege on
- // ANY column, not necessarily the first column. But since
- // the constructor for column privilege requires us to pass
- // a column descriptor, we just choose the first column for
- // MIN_SELECT_PRIV requirement.
- getCompilerContext().addRequiredColumnPriv(
- td.getColumnDescriptor(1));
+ private void collectTablesWithPossiblyStaleStats() throws StandardException {
+ if (!checkIndexStats) {
+ return;
}
+
// Save a list of base tables to check the index statistics for at a
// later time. We want to compute statistics for base user tables only,
// not for instance system tables or VTIs (see TableDescriptor for a
// list of all available "table types").
- if (checkIndexStats &&
- td.getTableType() == TableDescriptor.BASE_TABLE_TYPE) {
- if (statsToUpdate == null) {
- statsToUpdate = new ArrayList<TableDescriptor>();
+ FromList fromList = resultSet.getFromList();
+ for (int i = 0; i < fromList.size(); i++) {
+ FromTable fromTable = (FromTable) fromList.elementAt(i);
+ if (fromTable.isBaseTable()) {
+ TableDescriptor td = fromTable.getTableDescriptor();
+ if (td.getTableType() == TableDescriptor.BASE_TABLE_TYPE) {
+ if (statsToUpdate == null) {
+ statsToUpdate = new ArrayList<TableDescriptor>();
+ }
+ statsToUpdate.add(td);
+ }
}
- statsToUpdate.add(td);
}
}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromList.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromList.java?rev=1541461&r1=1541460&r2=1541461&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromList.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromList.java Wed Nov 13 10:49:57 2013
@@ -27,10 +27,12 @@ import java.util.Properties;
import org.apache.derby.iapi.error.StandardException;
import org.apache.derby.iapi.reference.SQLState;
import org.apache.derby.iapi.services.context.ContextManager;
+import org.apache.derby.iapi.sql.compile.CompilerContext;
import org.apache.derby.shared.common.sanity.SanityManager;
import org.apache.derby.iapi.sql.compile.Optimizable;
import org.apache.derby.iapi.sql.compile.OptimizableList;
import org.apache.derby.iapi.sql.compile.Optimizer;
+import org.apache.derby.iapi.sql.conn.Authorizer;
import org.apache.derby.iapi.sql.dictionary.DataDictionary;
import org.apache.derby.iapi.util.JBitSet;
import org.apache.derby.iapi.util.ReuseFactory;
@@ -355,6 +357,34 @@ class FromList extends QueryTreeNodeV
referencesSessionSchema = true;
setElementAt(newNode, index);
}
+
+ // DERBY-4191: We must have some SELECT privilege on every table
+ // that we read from, even if we don't actually read any column
+ // values from it (for example if we do SELECT COUNT(*) FROM T).
+ // We ask for MIN_SELECT_PRIV requirement of the first column in
+ // the table. The first column is just a place holder. What we
+ // really do at execution time when we see we are looking for
+ // MIN_SELECT_PRIV privilege is as follows:
+ //
+ // 1) We will look for SELECT privilege at table level.
+ // 2) If not found, we will look for SELECT privilege on
+ // ANY column, not necessarily the first column. But since
+ // the constructor for column privilege requires us to pass
+ // a column descriptor, we just choose the first column for
+ // MIN_SELECT_PRIV requirement.
+ final CompilerContext cc = getCompilerContext();
+ cc.pushCurrentPrivType(Authorizer.MIN_SELECT_PRIV);
+ for (int index = 0; index < size; index++) {
+ fromTable = (FromTable) elementAt(index);
+ if (fromTable.isPrivilegeCollectionRequired() &&
+ fromTable.isBaseTable() && !fromTable.forUpdate()) {
+ // This is a base table in the FROM list of a SELECT statement.
+ // Make sure we check for minimum SELECT privilege on it.
+ cc.addRequiredColumnPriv(
+ fromTable.getTableDescriptor().getColumnDescriptor(1));
+ }
+ }
+ cc.popCurrentPrivType();
}
/**
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/QueryTreeNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/QueryTreeNode.java?rev=1541461&r1=1541460&r2=1541461&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/QueryTreeNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/QueryTreeNode.java Wed Nov 13 10:49:57 2013
@@ -107,7 +107,7 @@ public abstract class QueryTreeNode impl
* and then it is turned off while we process the query underlying the view
* v1.
*/
- boolean isPrivilegeCollectionRequired = true;
+ private boolean isPrivilegeCollectionRequired = true;
QueryTreeNode(ContextManager cm) {
this.cm = cm;
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/GrantRevokeDDLTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/GrantRevokeDDLTest.java?rev=1541461&r1=1541460&r2=1541461&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/GrantRevokeDDLTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/GrantRevokeDDLTest.java Wed Nov 13 10:49:57 2013
@@ -10172,12 +10172,36 @@ public final class GrantRevokeDDLTest ex
user2St.execute("update user1.t4191_table3 "+
"set c31 = ( select 1 from user1.view_t4191_table3 )");
- //none of following selects will work because there is no select
- //privilege available to user2 yet.
- assertStatementError("42500", user2St, "select count(*) from user1.t4191");
- assertStatementError("42500", user2St, "select count(1) from user1.t4191");
+ // None of following selects will work because there is no select
+ // privilege available to user2 yet. Each row in the array contains
+ // a statement and the expected results or update count if the
+ // minimum select privilege had been granted.
+ Object[][] requireMinimumSelectPrivilege = {
+ { "select count(*) from user1.t4191", new String[][] {{"0"}} },
+ { "select count(1) from user1.t4191", new String[][] {{"0"}} },
+ { "select 1 from user1.t4191", new String[0][] },
+ { "select 1 from user1.t4191 for update", new String[0][] },
+ { "select 1 from user1.t4191 union values 2", new String[][] {{"2"}} },
+ { "values 1 union select 1 from user1.t4191", new String[][] {{"1"}} },
+ { "values (select count(*) from user1.t4191)", new String[][] {{"0"}} },
+ { "values (select count(1) from user1.t4191)", new String[][] {{"0"}} },
+ { "values ((select 1 from user1.t4191))", new String[][] {{null}} },
+ // DERBY-6408: Next two queries should have returned FALSE.
+ { "values exists(select 1 from user1.t4191)", new String[][] {{null}} },
+ { "values exists(select * from user1.t4191)", new String[][] {{null}} },
+ { "select count(*) from (select 1 from user1.t4191) s", new String[][] {{"0"}} },
+ { "insert into user1.t4191_table3 select 1, 2 from user1.t4191", new Integer(0) },
+ { "update user1.t4191_table3 set c31 = 1 where exists (select * from user1.t4191)", new Integer(0) },
+ { "delete from user1.t4191_table3 where exists (select * from user1.t4191)", new Integer(0) },
+ };
+
+ for (int i = 0; i < requireMinimumSelectPrivilege.length; i++) {
+ String sql = (String) requireMinimumSelectPrivilege[i][0];
+ assertStatementError("42500", user2St, sql);
+ }
+
+ // Should fail because there is no select privilege on column Y.
assertStatementError("42502", user2St, "select count(y) from user1.t4191");
- assertStatementError("42500", user2St, "select 1 from user1.t4191");
//update below should fail because user2 does not have update
//privileges on user1.t4191
assertStatementError("42502", user2St, "update user1.t4191 set x=0");
@@ -10187,19 +10211,22 @@ public final class GrantRevokeDDLTest ex
assertStatementError("42502", user2St, "update user1.t4191 set x=" +
" ( select z from user1.t4191_table2 )");
- //grant select on user1.t4191(x) to user2 and now the above select
- //statements will work
+ // Grant select on user1.t4191(x) to user2 and now the above
+ // statements, which previously failed because they didn't have
+ // the minimum select privilege on the table, will work.
user1St.execute("grant select(x) on t4191 to user2");
- String[][] expRS = new String [][]
- {
- {"0"}
- };
- rs = user2St.executeQuery("select count(*) from user1.t4191");
- JDBC.assertFullResultSet(rs, expRS, true);
- rs = user2St.executeQuery("select count(1) from user1.t4191");
- JDBC.assertFullResultSet(rs, expRS, true);
- rs = user2St.executeQuery("select 1 from user1.t4191");
- JDBC.assertEmpty(rs);
+
+ for (int i = 0; i < requireMinimumSelectPrivilege.length; i++) {
+ String sql = (String) requireMinimumSelectPrivilege[i][0];
+ Object expectedResult = requireMinimumSelectPrivilege[i][1];
+ if (expectedResult instanceof Integer) {
+ assertUpdateCount(
+ user2St, ((Integer) expectedResult).intValue(), sql);
+ } else {
+ JDBC.assertFullResultSet(user2St.executeQuery(sql),
+ (String[][]) expectedResult);
+ }
+ }
//user2 does not have select privilege on 2nd column from user1.t4191
assertStatementError("42502", user2St, "select count(y) from user1.t4191");
@@ -10272,13 +10299,13 @@ public final class GrantRevokeDDLTest ex
//following queries will still work because there is still a
//select privilege on user1.t4191 available to user2
rs = user2St.executeQuery("select count(*) from user1.t4191");
- JDBC.assertFullResultSet(rs, expRS, true);
+ JDBC.assertSingleValueResultSet(rs, "0");
rs = user2St.executeQuery("select count(1) from user1.t4191");
- JDBC.assertFullResultSet(rs, expRS, true);
+ JDBC.assertSingleValueResultSet(rs, "0");
rs = user2St.executeQuery("select 1 from user1.t4191");
JDBC.assertEmpty(rs);
rs = user2St.executeQuery("select count(y) from user1.t4191");
- JDBC.assertFullResultSet(rs, expRS, true);
+ JDBC.assertSingleValueResultSet(rs, "0");
//grant select privilege on user1.t4191(x) back to user2 so following
//update can succeed
user1St.execute("grant select(x) on t4191 to user2");