Repository: prestodb/presto
Pull request #24638: Utilized Columns fix for views
Author: login: kevintang2022
Created: 2025-02-26T18:58:02Z | Merged: 2025-03-28T03:03:07Z

## Description
<!---Describe your changes in detail-->
- Perform the exploration of a view's definition just like how we would perform exploration of a subquery
## Motivation and Context
<!---Why is this change required? What problem does it solve?-->
<!---If it fixes an open issue, please link to the issue here.-->
[T214103298](https://www.internalfb.com/intern/tasks/?t=214103298)
The user's dataswarm tasks is failing because the ACL is checking every column in the view table when it should only be checking ACL on the utilized columns

## Impact
<!---Describe any public API or user-facing feature change or any performance impact-->

## Test Plan
<!---Please fill in how you tested your change-->
Added automated tests for queries involving views

Deploy to verifier cluster
## Contributor checklist

- [ ] Please make sure your submission complies with our [contributing guide](https://github.com/prestodb/presto/blob/master/CONTRIBUTING.md), in particular [code style](https://github.com/prestodb/presto/blob/master/CONTRIBUTING.md#code-style) and [commit standards](https://github.com/prestodb/presto/blob/master/CONTRIBUTING.md#commit-standards).
- [ ] PR description addresses the issue accurately and concisely.  If the change is non-trivial, a GitHub Issue is referenced.
- [ ] Documented new properties (with its default value), SQL syntax, functions, or other functionality.
- [x] If release notes are required, they follow the [release notes guidelines](https://github.com/prestodb/presto/wiki/Release-Notes-Guidelines).
- [x] Adequate tests were added if applicable.
- [ ] CI passed.

## Release Notes
Please follow [release notes guidelines](https://github.com/prestodb/presto/wiki/Release-Notes-Guidelines) and fill in the release notes below.

```
== RELEASE NOTES ==

General Changes
* Improve analysis of utilized columns in a query by exploring view definitions and checking the utilized columns of the underlying tables

```





Diff:
diff --git a/presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/UtilizedColumnsAnalyzer.java b/presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/UtilizedColumnsAnalyzer.java
index 978dd5b20de61..fc8752c3cef98 100644
--- a/presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/UtilizedColumnsAnalyzer.java
+++ b/presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/UtilizedColumnsAnalyzer.java
@@ -314,6 +314,15 @@ protected Void visitTable(Table table, Context context)
         {
             handleRelation(table, context);
 
+            Analysis.NamedQuery namedQuery = analysis.getNamedQuery(table);
+            if (namedQuery != null && namedQuery.isFromView()) {
+                handleRelation(table, context, namedQuery.getQuery().getQueryBody());
+                process(namedQuery.getQuery(), context);
+            }
+            else {
+                handleRelation(table, context);
+            }
+
             return null;
         }
 
diff --git a/presto-main-base/src/test/java/com/facebook/presto/sql/analyzer/AbstractAnalyzerTest.java b/presto-main-base/src/test/java/com/facebook/presto/sql/analyzer/AbstractAnalyzerTest.java
index 9d2fde1d9d4f4..01e0ca48371ff 100644
--- a/presto-main-base/src/test/java/com/facebook/presto/sql/analyzer/AbstractAnalyzerTest.java
+++ b/presto-main-base/src/test/java/com/facebook/presto/sql/analyzer/AbstractAnalyzerTest.java
@@ -67,6 +67,8 @@
 import java.util.Optional;
 import java.util.function.Consumer;
 
+import static com.facebook.presto.SystemSessionProperties.CHECK_ACCESS_CONTROL_ON_UTILIZED_COLUMNS_ONLY;
+import static com.facebook.presto.SystemSessionProperties.CHECK_ACCESS_CONTROL_WITH_SUBFIELDS;
 import static com.facebook.presto.common.type.BigintType.BIGINT;
 import static com.facebook.presto.common.type.DoubleType.DOUBLE;
 import static com.facebook.presto.common.type.TypeSignature.parseTypeSignature;
@@ -106,6 +108,8 @@ public class AbstractAnalyzerTest
     protected static final Session CLIENT_SESSION = testSessionBuilder()
             .setCatalog(TPCH_CATALOG)
             .setSchema("s1")
+            .setSystemProperty(CHECK_ACCESS_CONTROL_ON_UTILIZED_COLUMNS_ONLY, "true")
+            .setSystemProperty(CHECK_ACCESS_CONTROL_WITH_SUBFIELDS, "true")
             .build();
 
     protected static final SqlInvokedFunction SQL_FUNCTION_SQUARE = new SqlInvokedFunction(
@@ -353,6 +357,103 @@ public void setup()
                 new SchemaTableName("s1", "v5"),
                 ImmutableList.of(ColumnMetadata.builder().setName("a").setType(BIGINT).build()));
         inSetupTransaction(session -> metadata.createView(session, TPCH_CATALOG, viewMetadata5, viewData5, false));
+
+        String viewDataInvoker1 = JsonCodec.jsonCodec(ViewDefinition.class).toJson(
+                new ViewDefinition(
+                        "select a,b,c from t1",
+                        Optional.of(TPCH_CATALOG),
+                        Optional.of("s1"),
+                        ImmutableList.of(
+                                new ViewDefinition.ViewColumn("a", BIGINT),
+                                new ViewDefinition.ViewColumn("b", BIGINT),
+                                new ViewDefinition.ViewColumn("c", BIGINT)),
+                        Optional.empty(),
+                        true));
+
+        ConnectorTableMetadata viewMetadataInvoker1 = new ConnectorTableMetadata(
+                new SchemaTableName("s1", "view_invoker1"),
+                ImmutableList.of(
+                        ColumnMetadata.builder().setName("a").setType(BIGINT).build(),
+                        ColumnMetadata.builder().setName("b").setType(BIGINT).build(),
+                        ColumnMetadata.builder().setName("c").setType(BIGINT).build()));
+        inSetupTransaction(session -> metadata.createView(session, TPCH_CATALOG, viewMetadataInvoker1, viewDataInvoker1, false));
+
+        String viewDataInvoker2 = JsonCodec.jsonCodec(ViewDefinition.class).toJson(
+                new ViewDefinition(
+                        "select x, y, z from t13",
+                        Optional.of(TPCH_CATALOG),
+                        Optional.of("s1"),
+                        ImmutableList.of(
+                                new ViewDefinition.ViewColumn("x", BIGINT),
+                                new ViewDefinition.ViewColumn("y", BIGINT),
+                                new ViewDefinition.ViewColumn("z", BIGINT)),
+                        Optional.empty(),
+                        true));
+        ConnectorTableMetadata viewMetadataInvoker2 = new ConnectorTableMetadata(
+                new SchemaTableName("s1", "view_invoker2"),
+                ImmutableList.of(
+                        ColumnMetadata.builder().setName("x").setType(BIGINT).build(),
+                        ColumnMetadata.builder().setName("y").setType(BIGINT).build(),
+                        ColumnMetadata.builder().setName("z").setType(BIGINT).build()));
+        inSetupTransaction(session -> metadata.createView(session, TPCH_CATALOG, viewMetadataInvoker2, viewDataInvoker2, false));
+
+        String viewDataDefiner1 = JsonCodec.jsonCodec(ViewDefinition.class).toJson(
+                new ViewDefinition(
+                        "select a,b,c from t1",
+                        Optional.of(TPCH_CATALOG),
+                        Optional.of("s1"),
+                        ImmutableList.of(
+                                new ViewDefinition.ViewColumn("a", BIGINT),
+                                new ViewDefinition.ViewColumn("b", BIGINT),
+                                new ViewDefinition.ViewColumn("c", BIGINT)),
+                        Optional.of("different_user"),
+                        false));
+
+        ConnectorTableMetadata viewMetadataDefiner1 = new ConnectorTableMetadata(
+                new SchemaTableName("s1", "view_definer1"),
+                ImmutableList.of(
+                        ColumnMetadata.builder().setName("a").setType(BIGINT).build(),
+                        ColumnMetadata.builder().setName("b").setType(BIGINT).build(),
+                        ColumnMetadata.builder().setName("c").setType(BIGINT).build()));
+        inSetupTransaction(session -> metadata.createView(session, TPCH_CATALOG, viewMetadataDefiner1, viewDataDefiner1, false));
+
+        String viewDataDefiner2 = JsonCodec.jsonCodec(ViewDefinition.class).toJson(
+                new ViewDefinition(
+                        "select x, y, z from t13",
+                        Optional.of(TPCH_CATALOG),
+                        Optional.of("s1"),
+                        ImmutableList.of(
+                                new ViewDefinition.ViewColumn("x", BIGINT),
+                                new ViewDefinition.ViewColumn("y", BIGINT),
+                                new ViewDefinition.ViewColumn("z", BIGINT)),
+                        Optional.of("different_user"),
+                        false));
+        ConnectorTableMetadata viewMetadataDefiner2 = new ConnectorTableMetadata(
+                new SchemaTableName("s1", "view_definer2"),
+                ImmutableList.of(
+                        ColumnMetadata.builder().setName("x").setType(BIGINT).build(),
+                        ColumnMetadata.builder().setName("y").setType(BIGINT).build(),
+                        ColumnMetadata.builder().setName("z").setType(BIGINT).build()));
+        inSetupTransaction(session -> metadata.createView(session, TPCH_CATALOG, viewMetadataDefiner2, viewDataDefiner2, false));
+
+        String viewDataInvokerWithCte1 = JsonCodec.jsonCodec(ViewDefinition.class).toJson(
+                new ViewDefinition(
+                        "WITH cte as (SELECT a + 1 as c1, b +1 as c2, c +1 as c3 FROM t1) SELECT c1, c2, c3 from cte where c1 > 5",
+                        Optional.of(TPCH_CATALOG),
+                        Optional.of("s1"),
+                        ImmutableList.of(
+                                new ViewDefinition.ViewColumn("c1", BIGINT),
+                                new ViewDefinition.ViewColumn("c2", BIGINT),
+                                new ViewDefinition.ViewColumn("c3", BIGINT)),
+                        Optional.empty(),
+                        true));
+        ConnectorTableMetadata viewMetadataInvokerWithCte1 = new ConnectorTableMetadata(
+                new SchemaTableName("s1", "view_invoker_with_cte1"),
+                ImmutableList.of(
+                        ColumnMetadata.builder().setName("c1").setType(BIGINT).build(),
+                        ColumnMetadata.builder().setName("c2").setType(BIGINT).build(),
+                        ColumnMetadata.builder().setName("c3").setType(BIGINT).build()));
+        inSetupTransaction(session -> metadata.createView(session, TPCH_CATALOG, viewMetadataInvokerWithCte1, viewDataInvokerWithCte1, false));
     }
 
     private void inSetupTransaction(Consumer<Session> consumer)
diff --git a/presto-main-base/src/test/java/com/facebook/presto/sql/analyzer/TestUtilizedColumnsAnalyzer.java b/presto-main-base/src/test/java/com/facebook/presto/sql/analyzer/TestUtilizedColumnsAnalyzer.java
index c835834421664..ad917049eb660 100644
--- a/presto-main-base/src/test/java/com/facebook/presto/sql/analyzer/TestUtilizedColumnsAnalyzer.java
+++ b/presto-main-base/src/test/java/com/facebook/presto/sql/analyzer/TestUtilizedColumnsAnalyzer.java
@@ -15,6 +15,7 @@
 
 import com.facebook.presto.common.QualifiedObjectName;
 import com.facebook.presto.spi.WarningCollector;
+import com.facebook.presto.spi.analyzer.AccessControlInfo;
 import com.facebook.presto.sql.tree.Statement;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
@@ -23,6 +24,7 @@
 
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import static com.facebook.presto.transaction.TransactionBuilder.transaction;
 import static org.testng.Assert.assertEquals;
@@ -36,13 +38,13 @@ public void testWildcardSelect()
     {
         // Test wildcard select
         assertUtilizedTableColumns("SELECT * FROM t1",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c", "d")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c", "d"))));
 
         // Test outer select * captures everything
         assertUtilizedTableColumns("SELECT * FROM (SELECT a + b FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"))));
         assertUtilizedTableColumns("SELECT * FROM (SELECT a + b FROM (SELECT * FROM t1))",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"))));
     }
 
     @Test
@@ -50,7 +52,7 @@ public void testCountStar()
     {
         // Test count(*) should not need column access for anything, but should still need table access
         assertUtilizedTableColumns("SELECT count(*) FROM t1",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of()));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of())));
     }
 
     @Test
@@ -58,9 +60,9 @@ public void testRecursiveProjectionPruning()
     {
         // Test recursive pruning of projections in subquery
         assertUtilizedTableColumns("SELECT a FROM (SELECT * FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"))));
         assertUtilizedTableColumns("SELECT a FROM (SELECT a, b FROM (SELECT a, b, c FROM t1))",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"))));
     }
 
     @Test
@@ -68,31 +70,31 @@ public void testAliasing()
     {
         // Test aliasing
         assertUtilizedTableColumns("SELECT x FROM (SELECT *, a as x FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"))));
 
         // Test alias expression with multiple columns referenced in alias
         assertUtilizedTableColumns("SELECT x FROM (SELECT *, a + b as x FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"))));
 
         // Test chained aliasing
         assertUtilizedTableColumns("SELECT x + 3 FROM (SELECT y + 2 as x FROM (SELECT z + 1 as y FROM (SELECT a as z FROM t1 WHERE b = 1)))",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"))));
 
         // Test aliased relation
         assertUtilizedTableColumns("SELECT mytable.a, mytable.b FROM (SELECT * FROM t1 WHERE t1.c = 1) mytable",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"))));
 
         // Test aliased relation for self-join
         assertUtilizedTableColumns("SELECT x.a, y.b FROM t1 x, t1 y",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"))));
 
         // Test filter on aliased relation
         assertUtilizedTableColumns("SELECT count(x) FROM (SELECT a as x, * FROM t1) t WHERE t.b = 3",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"))));
 
         // Test aliased relation with column aliases
         assertUtilizedTableColumns("SELECT y FROM (SELECT x, y FROM t1 AS mytable (w, x, y, z))",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("c"))));
     }
 
     @Test
@@ -100,29 +102,29 @@ public void testJoin()
     {
         // Cartesian join
         assertUtilizedTableColumns("SELECT * FROM (SELECT * FROM t1, t2)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c", "d"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c", "d"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a", "b"))));
 
         // Joins with column aliases
         assertUtilizedTableColumns("SELECT t2.a + y FROM t2 CROSS JOIN (SELECT *, c + d AS y FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("c", "d"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("c", "d"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a"))));
         assertUtilizedTableColumns("SELECT mytable.a + myothertable.b AS f1, myothertable.z FROM t2 AS mytable CROSS JOIN (SELECT *, a + b AS x, c - 1 AS z FROM t1) myothertable",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("b", "c"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("b", "c"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a"))));
 
         // Columns in ON join condition should be checked
         assertUtilizedTableColumns("SELECT t1.a FROM t1 JOIN t2 ON t1.c = t2.b",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("b"))));
 
         // When joining to subquery, prune unused columns from subquery
         assertUtilizedTableColumns("SELECT t2.a FROM t2 FULL OUTER JOIN (SELECT a, b FROM t1 WHERE c > 0) mytable ON t2.a = mytable.a",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a"))));
 
         // Prune unused columns from joined relation
         assertUtilizedTableColumns("SELECT w FROM (SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a AND t1.b = t2.b) AS t(u, v, w, x, y, z)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a", "b"))));
 
         // Join with USING clause
         assertUtilizedTableColumns("SELECT t1.c FROM t1 JOIN t2 USING (a, b)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a", "b"))));
     }
 
     @Test
@@ -130,50 +132,50 @@ public void testGroupBy()
     {
         // Capture column in GROUP BY
         assertUtilizedTableColumns("SELECT a, b FROM (SELECT count(a) AS a, avg(b) AS b FROM t1 GROUP BY c)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"))));
 
         // Capture columns in subquery in GROUP BY expression
         assertUtilizedTableColumns("SELECT a, b FROM (SELECT count(a) AS a, avg(b) AS b FROM t1 GROUP BY (c * (SELECT max(a) FROM t2)))",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a"))));
 
         // Capture column in HAVING
         assertUtilizedTableColumns("SELECT count(a) AS c FROM t1 WHERE b = 0 GROUP BY c HAVING max(d) > 10",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c", "d")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c", "d"))));
 
         // Capture columns in subquery in HAVING expression
         assertUtilizedTableColumns("SELECT count(a) FROM t1 GROUP BY b HAVING count(a) > (SELECT max(a) FROM t2)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a"))));
 
         // ROLLUP, CUBE, and GROUPING SETS do not allow for expressions so we only need to test for explicit columns
 
         // Capture column in ROLLUP
         assertUtilizedTableColumns("SELECT a, b FROM (SELECT count(a) AS a, avg(b) AS b FROM t1 GROUP BY ROLLUP(c))",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"))));
 
         // Capture column in CUBE
         assertUtilizedTableColumns("SELECT a, b FROM (SELECT count(a) AS a, avg(b) AS b FROM t1 GROUP BY CUBE(c, d))",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c", "d")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c", "d"))));
 
         // Capture columns in GROUPING SETS
         assertUtilizedTableColumns("SELECT x FROM (SELECT sum(c) AS x FROM t1 GROUP BY GROUPING SETS (a, b))",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"))));
         assertUtilizedTableColumns("SELECT x FROM (SELECT grouping(a, b) AS x FROM t1 GROUP BY GROUPING SETS (a, b))",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"))));
 
         // Test ordinal in GROUP BY
         assertUtilizedTableColumns("SELECT * FROM (SELECT count(a), count(b), c FROM t1 WHERE b = 0 GROUP BY 3)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"))));
     }
 
     public void testOrderBy()
     {
         // Column reference in ORDER BY
         assertUtilizedTableColumns("SELECT * FROM (SELECT b, c FROM t1 WHERE b = 0 ORDER BY b)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("b", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("b", "c"))));
 
         // Test ordinal in ORDER BY
         assertUtilizedTableColumns("SELECT * FROM (SELECT b, c FROM t1 WHERE b = 0 ORDER BY 2)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("b", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("b", "c"))));
     }
 
     @Test
@@ -181,33 +183,33 @@ public void testCTE()
     {
         // Test CTE columns are pruned
         assertUtilizedTableColumns("WITH mytable AS (SELECT * FROM t1) SELECT x FROM (SELECT a AS x FROM mytable)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"))));
 
         // CTE filter column is captured
         assertUtilizedTableColumns("WITH mytable AS (SELECT a as x, b as y FROM t1 WHERE c = 0) SELECT x FROM mytable",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c"))));
 
         // Unused CTE shouldn't require column level permissions, but should require table level permissions
         assertUtilizedTableColumns("WITH mytable AS (SELECT * FROM t1) SELECT a FROM t2",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of(), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of(), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a"))));
 
         // Test CTE aliased twice for self-join
         assertUtilizedTableColumns("WITH t AS (SELECT a, b FROM t1) SELECT 1 FROM t AS mytable JOIN t as myothertable ON mytable.a = myothertable.b",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"))));
     }
 
     @Test
     public void testInsert()
     {
         assertUtilizedTableColumns("INSERT INTO t2 SELECT a, b FROM t1",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"))));
     }
 
     @Test
     public void testCTAS()
     {
         assertUtilizedTableColumns("CREATE TABLE foo AS SELECT a, b FROM t1",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"))));
     }
 
     @Test
@@ -215,19 +217,19 @@ public void testSetOperations()
     {
         // Test EXCEPT
         assertUtilizedTableColumns("SELECT a, b FROM t1 WHERE c = 0 EXCEPT SELECT * from t2",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a", "b"))));
 
         // Test INTERSECT
         assertUtilizedTableColumns("SELECT a FROM (SELECT * FROM t1 WHERE t1.b = 0 INTERSECT SELECT * from t1 WHERE t1.c = 0)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"))));
 
         // Test UNION
         assertUtilizedTableColumns("SELECT * FROM ((SELECT a, b FROM t1 WHERE c = 0) UNION (SELECT * FROM t2 WHERE b = 0))",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a", "b"))));
         assertUtilizedTableColumns("SELECT a, b FROM (SELECT a, b, c, d FROM t1 UNION ALL SELECT a AS w, b AS x, a AS y, b AS z FROM t2) WHERE c = 0 and d = c",
-                ImmutableMap.of(
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(
                         QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c", "d"),
-                        QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a", "b")));
+                        QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a", "b"))));
     }
 
     @Test
@@ -235,26 +237,26 @@ public void testLateral()
     {
         // Select item in lateral should be checked
         assertUtilizedTableColumns("SELECT a, x FROM t1 CROSS JOIN LATERAL (SELECT b as x)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"))));
 
         // Test pruning of select items in lateral if they are unused
         assertUtilizedTableColumns("SELECT a FROM t1 CROSS JOIN LATERAL (SELECT b as x)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"))));
 
         // Test lateral from different table
         assertUtilizedTableColumns("SELECT * FROM t1 CROSS JOIN LATERAL (SELECT b FROM t2)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c", "d"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c", "d"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("b"))));
 
         // Test chained lateral
         assertUtilizedTableColumns("SELECT a, x, y FROM t1 CROSS JOIN LATERAL (SELECT a + 1 as x) CROSS JOIN LATERAL (SELECT x + 2 as y)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"))));
     }
 
     @Test
     public void testSampledRelation()
     {
         assertUtilizedTableColumns("SELECT a FROM (SELECT * FROM t1 TABLESAMPLE BERNOULLI (10))",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"))));
     }
 
     @Test
@@ -262,53 +264,53 @@ public void testUnnest()
     {
         // Unnest column gets pruned if unused
         assertUtilizedTableColumns("SELECT a FROM t7 CROSS JOIN UNNEST (c) AS t(x)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t7"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t7"), ImmutableSet.of("a"))));
 
         // Unnest column used through alias
         assertUtilizedTableColumns("SELECT a, x FROM t7 CROSS JOIN UNNEST (c) AS t(x)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t7"), ImmutableSet.of("a", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t7"), ImmutableSet.of("a", "c"))));
 
         // Multiple unnest columns
         assertUtilizedTableColumns("SELECT a, x, y FROM t7 CROSS JOIN UNNEST (c, d) AS t(x, y)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t7"), ImmutableSet.of("a", "c", "d")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t7"), ImmutableSet.of("a", "c", "d"))));
 
         // Unused unnest columns are pruned, but used ones are kept
         assertUtilizedTableColumns("SELECT a, y FROM t7 CROSS JOIN UNNEST (c, d) AS t(x, y)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t7"), ImmutableSet.of("a", "d")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t7"), ImmutableSet.of("a", "d"))));
 
         // Unnest from subquery
         assertUtilizedTableColumns("SELECT y FROM (SELECT (SELECT ARRAY_AGG(a) FROM t1) x) CROSS JOIN UNNEST(x) AS t(y)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"))));
     }
 
     @Test
     public void testUnnestMap()
     {
         assertUtilizedTableColumns("SELECT t.x, t.y FROM (select * from t1) as cte1 CROSS JOIN UNNEST (MAP(array_agg(cte1.a), array_agg(cte1.a))) AS t(x, y)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"))));
 
         // Fall back to checking all columns does not happen
         assertUtilizedTableColumns("SELECT cte1.a, t.y FROM (select * from t1) as cte1 CROSS JOIN UNNEST (MAP(array_agg(cte1.c), array_agg(cte1.c))) AS t(x, y)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c"))));
 
         // The map was constructed from t1.c and t1.d, so in the outer scope, if one of the key or value fields get used, both count as being utilized
         assertUtilizedTableColumns("SELECT t.c3, cte1.x FROM t1 CROSS JOIN UNNEST (array_agg(t1.b),MAP(array_agg(t1.c), array_agg(t1.d))) AS t(c1 , c2, c3) inner join (select * from t13) as cte1 on cte1.x = t1.d",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("c", "d"),
-                        QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x")));
-//
-//        // Tricky case: t.c3 is utilized. It has field index of 2, but it should correspond to the expression index 1 (array_agg(t1.c))
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("c", "d"),
+                        QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x"))));
+
+        // Tricky case: t.c3 is utilized. It has field index of 2, but it should correspond to the expression index 1 (array_agg(t1.c))
         assertUtilizedTableColumns("SELECT t.c3, cte1.x FROM t1 CROSS JOIN UNNEST (MAP(array_agg(t1.b), array_agg(t1.b)), array_agg(t1.c), array_agg(t1.d)) AS t(c1 , c2, c3, c4) inner join (select * from t13) as cte1 on cte1.x = t1.d",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("c", "d"),
-                        QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("c", "d"),
+                        QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x"))));
     }
 
     @Test
     public void testValues()
     {
-        assertUtilizedTableColumns("SELECT * FROM (VALUES 1, 2, 3)", ImmutableMap.of());
-        assertUtilizedTableColumns("SELECT * FROM (VALUES array[2, 2]) a(x) CROSS JOIN UNNEST(x)", ImmutableMap.of());
+        assertUtilizedTableColumns("SELECT * FROM (VALUES 1, 2, 3)", ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of()));
+        assertUtilizedTableColumns("SELECT * FROM (VALUES array[2, 2]) a(x) CROSS JOIN UNNEST(x)", ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of()));
         assertUtilizedTableColumns("SELECT a, b FROM t1 CROSS JOIN (VALUES 1, 2, 3)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"))));
     }
 
     @Test
@@ -316,25 +318,25 @@ public void testInSubquery()
     {
         // IN/NOT IN subqueries should keep all their select columns
         assertUtilizedTableColumns("SELECT a FROM (SELECT * FROM t1 WHERE t1.b IN (SELECT b FROM t2))",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("b"))));
         assertUtilizedTableColumns("SELECT a FROM (SELECT * FROM t1 WHERE t1.b IN (SELECT b FROM t2 WHERE t2.a = 0) AND t1.c = 0)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a", "b"))));
         assertUtilizedTableColumns("SELECT a, b FROM t1 WHERE t1.b IN (SELECT b FROM t2 WHERE t2.a NOT IN (SELECT x FROM t3) AND t1.c = 0)",
-                ImmutableMap.of(
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(
                         QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"),
                         QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a", "b"),
-                        QualifiedObjectName.valueOf("tpch.s1.t3"), ImmutableSet.of("x")));
+                        QualifiedObjectName.valueOf("tpch.s1.t3"), ImmutableSet.of("x"))));
 
         // Test aliased IN subquery (self join)
         assertUtilizedTableColumns("SELECT r1.a, r1.b FROM t1 as r1 WHERE r1.b IN (SELECT r2.c FROM t1 as r2 WHERE r2.d = 0)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c", "d")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c", "d"))));
 
         // Test correlated IN subquery
         assertUtilizedTableColumns("SELECT r1.a, r1.b, r2.a FROM t1 as r1 JOIN t2 as r2 ON r1.a = r2.a WHERE 0 IN (SELECT x FROM t3 r3 WHERE r2.a = r3.a)",
-                ImmutableMap.of(
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(
                         QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"),
                         QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a"),
-                        QualifiedObjectName.valueOf("tpch.s1.t3"), ImmutableSet.of("a", "x")));
+                        QualifiedObjectName.valueOf("tpch.s1.t3"), ImmutableSet.of("a", "x"))));
     }
 
     @Test
@@ -342,19 +344,19 @@ public void testExistsSubquery()
     {
         // In exists/not exists subqueries, the select list should be ignored
         assertUtilizedTableColumns("SELECT a FROM t1 WHERE NOT EXISTS (SELECT * FROM t2)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of()));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of())));
         assertUtilizedTableColumns("SELECT a FROM (SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t2.b = t1.b))",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("b"))));
 
         // Chain of correlated exists subquery (self join)
         assertUtilizedTableColumns("SELECT r1.a, r1.b FROM t2 r1, t1 WHERE EXISTS (SELECT r2.a, r2.b FROM t2 r2 WHERE r2.a = r1.b AND EXISTS (SELECT r3.a, r3.b FROM t2 r3 WHERE r3.a = r2.b AND r3.b = t1.c))",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("c"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("c"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a", "b"))));
 
         // Exists subquery in SELECT
         assertUtilizedTableColumns("SELECT EXISTS(SELECT * FROM t1) = EXISTS(SELECT * FROM t2)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of(), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of()));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of(), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of())));
         assertUtilizedTableColumns("SELECT EXISTS(SELECT * FROM t1 WHERE t1.a = 0) = EXISTS(SELECT * FROM t2)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of()));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of())));
     }
 
     @Test
@@ -362,54 +364,54 @@ public void testScalarSubquery()
     {
         // Scalar subquery in SELECT expression
         assertUtilizedTableColumns("SELECT a, (SELECT avg(a) FROM t2) FROM t1",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a"))));
         assertUtilizedTableColumns("SELECT mycolumn FROM (SELECT a, ((SELECT avg(a) FROM t2) * 5) as mycolumn FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of(), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of(), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a"))));
 
         // Scalar subquery in SELECT should be pruned if unreferenced
         assertUtilizedTableColumns("SELECT a FROM (SELECT a, (SELECT avg(a) FROM t2) as mycolumn FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of()));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of())));
 
         // Scalar subquery in GROUP BY
         assertUtilizedTableColumns("SELECT count(a) FROM t1 GROUP BY (b * (SELECT avg(a) FROM t2))",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a"))));
         assertUtilizedTableColumns("SELECT count(a) FROM t1 GROUP BY (b * (SELECT avg(c)))",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"))));
 
         // Scalar subquery in HAVING
         assertUtilizedTableColumns("SELECT count(a) FROM t1 GROUP BY b HAVING count(a) > (SELECT avg(a) FROM t2)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a"))));
         assertUtilizedTableColumns("SELECT count(r1.a) FROM t1 as r1 GROUP BY b HAVING count(r1.a) > (SELECT avg(r1.b))",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"))));
 
         // Scalar subquery in where with ANY/ALL
         assertUtilizedTableColumns("SELECT t1.c FROM t1 WHERE t1.b >= ANY(SELECT max(t1.a) FROM t1 GROUP BY t1.b)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"))));
         assertUtilizedTableColumns("SELECT a FROM t1 WHERE t1.b >= ALL(SELECT b FROM t2)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("b"))));
     }
 
     @Test
     public void testDerivedColumns()
     {
         assertUtilizedTableColumns("SELECT b_is_zero FROM (SELECT *, b = 0 AS b_is_zero FROM t1 WHERE a = 0)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"))));
         assertUtilizedTableColumns("WITH mycte AS (SELECT *, b = 0 as b_is_zero FROM t1 WHERE a = 0) SELECT a FROM mycte",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"))));
     }
 
     @Test
     public void testOrderByInAggregation()
     {
         assertUtilizedTableColumns("SELECT myarray FROM (SELECT array_agg(a ORDER BY b, c DESC) AS myarray FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"))));
     }
 
     @Test
     public void testWindowFunction()
     {
         assertUtilizedTableColumns("SELECT mycolumn FROM (SELECT sum(a) OVER (PARTITION BY b ORDER BY c) AS mycolumn FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"))));
     }
 
     @Test
@@ -417,19 +419,19 @@ public void testAggregationFilter()
     {
         // Filter expression should be captured
         assertUtilizedTableColumns("SELECT mycolumn FROM (SELECT sum(a) FILTER (WHERE b > 0) AS mycolumn FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"))));
 
         // Filter expression should be captured for count star
         assertUtilizedTableColumns("SELECT count(*) FILTER (WHERE a > 5) FROM t1",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"))));
 
         // If the filter expression is an IN subquery, all select items of the subquery should be captured
         assertUtilizedTableColumns("SELECT mycolumn FROM (SELECT sum(a) FILTER (WHERE b IN (SELECT c FROM t1)) AS mycolumn FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"))));
 
         // Filter expression referencing different table should be captured
         assertUtilizedTableColumns("SELECT mycolumn FROM (SELECT sum(a) FILTER (WHERE b IN (SELECT b FROM t2)) AS mycolumn FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("b"))));
     }
 
     @Test
@@ -437,27 +439,27 @@ public void testLambdaExpressions()
     {
         // Column reference inside lambda should be captured
         assertUtilizedTableColumns("SELECT mycolumn FROM (SELECT apply(0, x -> x + a) as mycolumn FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"))));
 
         // Aggregated column as lambda argument
         assertUtilizedTableColumns("SELECT mycolumn FROM (SELECT apply(sum(a), x -> x * x) as mycolumn FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"))));
 
         // Prune columns that are not used in lambda expression
         assertUtilizedTableColumns("SELECT apply(0, x -> x + a) FROM (SELECT * FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"))));
 
         // Column references in transform
         assertUtilizedTableColumns("SELECT mycolumn FROM (SELECT transform(c, x -> x * b) as mycolumn FROM t7)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t7"), ImmutableSet.of("b", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t7"), ImmutableSet.of("b", "c"))));
 
         // Column references in map_filter
         assertUtilizedTableColumns("SELECT map_filter(x, (k, v) -> k = a) FROM (SELECT a, b, MAP(c, d) as x FROM t7)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t7"), ImmutableSet.of("a", "c", "d")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t7"), ImmutableSet.of("a", "c", "d"))));
 
         // Column references in reduce
         assertUtilizedTableColumns("SELECT reduce(c, a, (s, x) -> s + x, s -> b * s) FROM (SELECT * FROM t7)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t7"), ImmutableSet.of("a", "b", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t7"), ImmutableSet.of("a", "b", "c"))));
     }
 
     @Test
@@ -465,27 +467,27 @@ public void testConditionals()
     {
         // If expression with subquery
         assertUtilizedTableColumns("SELECT mycolumn FROM (SELECT if(false, a, (SELECT max(a) FROM t2)) as mycolumn FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a"))));
 
         // Simple case expression with subquery
         assertUtilizedTableColumns("SELECT mycolumn FROM (SELECT CASE a WHEN 1 THEN 1 WHEN 2 THEN (SELECT max(a) FROM t2) ELSE 0 END as mycolumn FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a"))));
 
         // Searched case expression with subquery
         assertUtilizedTableColumns("SELECT mycolumn FROM (SELECT CASE WHEN a = 1 THEN 1 WHEN b = 2 THEN (SELECT max(a) FROM t2) ELSE 0 END as mycolumn FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a"))));
 
         // Coalesce expression with subquery
         assertUtilizedTableColumns("SELECT mycolumn FROM (SELECT COALESCE(a, b, (SELECT max(a) FROM t2), (SELECT max(b) FROM t2)) as mycolumn FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a", "b"))));
 
         // Nullif expression with subquery
         assertUtilizedTableColumns("SELECT mycolumn FROM (SELECT NULLIF(a, (SELECT max(a) FROM t2)) as mycolumn FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a"))));
 
         // Try expression with subquery
         assertUtilizedTableColumns("SELECT mycolumn FROM (SELECT TRY(a / (SELECT max(a) FROM t2)) as mycolumn FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"), QualifiedObjectName.valueOf("tpch.s1.t2"), ImmutableSet.of("a"))));
     }
 
     @Test
@@ -493,19 +495,19 @@ public void testConstructors()
     {
         // Array constructor
         assertUtilizedTableColumns("SELECT * FROM (SELECT ARRAY[a, b] FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"))));
         assertUtilizedTableColumns("SELECT a FROM t7 WHERE ARRAY[t7.b] = c",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t7"), ImmutableSet.of("a", "b", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t7"), ImmutableSet.of("a", "b", "c"))));
         assertUtilizedTableColumns("SELECT c FROM (SELECT ARRAY[a, b], c FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("c"))));
 
         // Map constructor
         assertUtilizedTableColumns("SELECT * FROM (SELECT MAP(array_agg(a), array_agg(b)) FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"))));
 
         // Row constructor
         assertUtilizedTableColumns("SELECT * FROM (SELECT ROW(a, b) FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"))));
     }
 
     @Test
@@ -513,7 +515,7 @@ public void testDereference()
     {
         assertUtilizedTableColumns(
                 "SELECT b.x.y FROM t10",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t10"), ImmutableSet.of("b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t10"), ImmutableSet.of("b"))));
     }
 
     @Test
@@ -521,11 +523,11 @@ public void testNoPruningWhenShortCircuited()
     {
         // Should not prune even if conditional is constant
         assertUtilizedTableColumns("SELECT mycolumn FROM (SELECT if(false, a, b) as mycolumn FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"))));
 
         // Should not prune even if WHERE condition can be short-circuited
         assertUtilizedTableColumns("SELECT mycolumn FROM (SELECT a as mycolumn FROM t1 WHERE b > 0 AND false AND c < 10)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"))));
     }
 
     @Test
@@ -533,11 +535,11 @@ public void testUDF()
     {
         // Column reference in UDF in filter
         assertUtilizedTableColumns("SELECT mycolumn FROM (SELECT a as mycolumn FROM t1 WHERE unittest.memory.square(b) > 0)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b"))));
 
         // Prune column reference in UDF in select
         assertUtilizedTableColumns("SELECT mycolumn FROM (SELECT a as mycolumn, unittest.memory.square(b) FROM t1)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"))));
     }
 
     @Test
@@ -545,7 +547,7 @@ public void testCteWithExpressionInSelect()
     {
         assertUtilizedTableColumns(
                 "with cte as (select x as c1, y as c2, z + 1 as c3 from t13) select c1, c3 from (select * from cte)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x", "z")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x", "z"))));
     }
 
     @Test
@@ -553,10 +555,10 @@ public void testMultipleCtes()
     {
         assertUtilizedTableColumns(
                 "with cte1 as (select x as c1, y as c2, z + 1 as c3 from t13), cte2 as (select c1 + 1 as a, c3 as b from cte1) select a, b from (select * from cte2)",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x", "z")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x", "z"))));
         assertUtilizedTableColumns(
                 "with cte1 as (select x as c1, z + 1 as c2, y from t13), cte2 as (select c1 + 1 c3, c2 +1 as c4 from cte1) select c3 from cte2",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x"))));
     }
 
     @Test
@@ -564,7 +566,7 @@ public void testMultipleCtesUsingSameTable()
     {
         assertUtilizedTableColumns(
                 "with cte1 as (select x + 1 as c1, y as c2, z + 1 as c3 from t13), cte2 as (with cte1 AS (select y +1 as c1 from t13) select * from cte1) SELECT cte1.c1, cte2.c1 from cte1 join cte2 on cte1.c1=cte2.c1",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x", "y")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x", "y"))));
     }
 
     @Test
@@ -574,7 +576,7 @@ public void testMultipleCtesSameNameSameTable()
         // Currently, it just looks the relations using the name (string) of the CTE
         assertUtilizedTableColumns(
                 "with cte1 as (select x + 1 as c1 from t13), cte2 as (with cte1 as (select x + 1 as c2, y + 1 as c3, z as c4 from t13) select * from cte1) select cte1.c1, cte2.c3 from cte1 join cte2 on true",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x", "y", "z")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x", "y", "z"))));
     }
 
     @Test
@@ -583,8 +585,8 @@ public void testMultipleCtesSameNameDifferentTable()
         // This happens because the two CTE1s having the same name, and the CTE1 of t13 has its first column utilized, so the CTE1 of t1 will also have its first column added.
         assertUtilizedTableColumns(
                 "with cte1 as (select x + 1 as c1 from t13), cte2 as (with cte1 as (select a + 1 as c2, b + 1 as c3, c as c4 from t1) select * from cte1) select cte1.c1 from cte1 join cte2 on true",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x"),
-                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x"),
+                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a"))));
     }
 
     @Test
@@ -592,7 +594,7 @@ public void testMultipleCtesDifferentNameSameTable()
     {
         assertUtilizedTableColumns(
                 "with cte1 as (select x + 1 as c1 from t13), cte2 as (with cte3 as (select x + 1 as c2, y + 1 as c3, z as c4 from t13) select * from cte3) select cte1.c1, cte2.c3 from cte1 join cte2 on true",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x", "y")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x", "y"))));
     }
 
     @Test
@@ -601,8 +603,8 @@ public void testMultipleCtesDifferentNameDifferentTable()
         // This is the same behavior for join queries like "select t1.a from t1 join t13 on true" regardless of wrapping in CTE
         assertUtilizedTableColumns(
                 "with cte1 as (select x + 1 as c1 from t13), cte2 as (with cte3 as (select a + 1 as c2, b + 1 as c3, c as c4 from t1) select * from cte3) select cte1.c1 from cte1 join cte2 on true",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x"),
-                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of()));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x"),
+                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of())));
     }
 
     @Test
@@ -612,11 +614,42 @@ public void testMultipleCtesSameNameDifferentTableMultipleColumnsUtilized()
         // It's trying to add the third column of CTE1 of t1 but it does not exist.
         assertUtilizedTableColumns(
                 "with cte1 as (select x + 1 as c1 from t13), cte2 as (with cte1 as (select a + 1 as c2, b + 1 as c3, c as c4 from t1) select * from cte1) select cte1.c1, cte2.c4 from cte1 join cte2 on true",
-                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x"),
-                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c")));
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x"),
+                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"))));
+    }
+
+    public void testInvokerView()
+    {
+        assertUtilizedTableColumns("SELECT view_invoker1.a, view_invoker1.c, view_invoker2.y FROM view_invoker1 left join view_invoker2 on view_invoker2.y = view_invoker1.c",
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(
+                        QualifiedObjectName.valueOf("tpch.s1.view_invoker1"), ImmutableSet.of("a", "c"),
+                        QualifiedObjectName.valueOf("tpch.s1.view_invoker2"), ImmutableSet.of("y"),
+                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c"),
+                        QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("y"))));
+
+        assertUtilizedTableColumns("SELECT view_invoker_with_cte1.c1, view_invoker_with_cte1.c3 FROM view_invoker_with_cte1",
+                ImmutableMap.of("AllowAllAccessControl:user", ImmutableMap.of(
+                        QualifiedObjectName.valueOf("tpch.s1.view_invoker_with_cte1"), ImmutableSet.of("c1", "c3"),
+                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c"))));
+    }
+
+    public void testDefinerView()
+    {
+        @Language("SQL") String query = "SELECT view_definer1.a, view_definer1.c, view_invoker2.y FROM view_definer1 left join view_invoker2 on view_invoker2.y = view_definer1.c";
+
+        assertUtilizedTableColumns(query,
+                ImmutableMap.of("ViewAccessControl:different_user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c")),
+                        "AllowAllAccessControl:user", ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.view_invoker2"), ImmutableSet.of("y"),
+                                QualifiedObjectName.valueOf("tpch.s1.view_definer1"), ImmutableSet.of("a", "c"),
+                                QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("y"))));
+    }
+
+    private String extractAccessControlInfo(AccessControlInfo accessControlInfo)
+    {
+        return accessControlInfo.getAccessControl().getClass().getSimpleName() + ":" + accessControlInfo.getIdentity().getUser();
     }
 
-    private void assertUtilizedTableColumns(@Language("SQL") String query, Map<QualifiedObjectName, Set<String>> expected)
+    private void assertUtilizedTableColumns(@Language("SQL") String query, Map<String, Map<QualifiedObjectName, Set<String>>> expected)
     {
         transaction(transactionManager, accessControl)
                 .singleStatement()
@@ -626,7 +659,7 @@ private void assertUtilizedTableColumns(@Language("SQL") String query, Map<Quali
                     Analyzer analyzer = createAnalyzer(session, metadata, WarningCollector.NOOP);
                     Statement statement = SQL_PARSER.createStatement(query);
                     Analysis analysis = analyzer.analyze(statement);
-                    assertEquals(analysis.getUtilizedTableColumnReferences().values().stream().findFirst().get(), expected);
+                    assertEquals(analysis.getUtilizedTableColumnReferences().entrySet().stream().collect(Collectors.toMap(entry -> extractAccessControlInfo(entry.getKey()), Map.Entry::getValue)), expected);
                 });
     }
 }
diff --git a/presto-spi/src/main/java/com/facebook/presto/spi/security/AccessControlContext.java b/presto-spi/src/main/java/com/facebook/presto/spi/security/AccessControlContext.java
index 11b2720fb3473..dd5bd29dd7515 100644
--- a/presto-spi/src/main/java/com/facebook/presto/spi/security/AccessControlContext.java
+++ b/presto-spi/src/main/java/com/facebook/presto/spi/security/AccessControlContext.java
@@ -18,6 +18,7 @@
 import com.facebook.presto.spi.QueryId;
 import com.facebook.presto.spi.WarningCollector;
 
+import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 
@@ -101,4 +102,29 @@ public Optional<String> getSchema()
     {
         return schema;
     }
+
+    @Override
+    public int hashCode()
+    {
+        return Objects.hash(queryId, clientInfo, clientTags, source, queryType, catalog, schema);
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        AccessControlContext other = (AccessControlContext) obj;
+        return Objects.equals(this.queryId, other.queryId) &&
+                Objects.equals(this.clientInfo, other.clientInfo) &&
+                Objects.equals(this.clientTags, other.clientTags) &&
+                Objects.equals(this.source, other.source) &&
+                Objects.equals(this.queryType, other.queryType) &&
+                Objects.equals(this.catalog, other.catalog) &&
+                Objects.equals(this.schema, other.schema);
+    }
 }


Reviews:
user: login: rschlussel
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-20T15:07:25Z
user: login: rschlussel
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T14:23:11Z
user: login: kevintang2022
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T17:48:07Z
user: login: kevintang2022
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T17:48:30Z
user: login: kevintang2022
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T17:48:48Z
user: login: kevintang2022
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T17:58:32Z
user: login: kevintang2022
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T19:33:13Z
user: login: rschlussel
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T21:04:37Z
user: login: rschlussel
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-03-27T20:40:02Z
user: login: rschlussel
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-27T23:29:43Z

Review comments:
diff_hunk: @@ -353,6 +357,103 @@ public void setup()
                 new SchemaTableName("s1", "v5"),
                 ImmutableList.of(new ColumnMetadata("a", BIGINT)));
         inSetupTransaction(session -> metadata.createView(session, TPCH_CATALOG, viewMetadata5, viewData5, false));
+
+        String viewData6 = JsonCodec.jsonCodec(ViewDefinition.class).toJson(
path: presto-main/src/test/java/com/facebook/presto/sql/analyzer/AbstractAnalyzerTest.java
user: login: rschlussel
body: i know everything else just uses t, v, etc. but can you give these views more descriptive names so it's easier to understand the tests that use them?
created_at: 2025-03-19T20:39:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -605,7 +632,7 @@ private void assertUtilizedTableColumns(@Language("SQL") String query, Map<Quali
                     Analyzer analyzer = createAnalyzer(session, metadata, WarningCollector.NOOP);
                     Statement statement = SQL_PARSER.createStatement(query);
                     Analysis analysis = analyzer.analyze(statement);
-                    assertEquals(analysis.getUtilizedTableColumnReferences().values().stream().findFirst().get(), expected);
+                    assertEquals(analysis.getUtilizedTableColumnReferences().values(), expected);
path: presto-main/src/test/java/com/facebook/presto/sql/analyzer/TestUtilizedColumnsAnalyzer.java
user: login: rschlussel
body: can you assert on the whole map (incl. access control info) and not just the values? that way we can be sure it's all correct for definer vs. invoker.
created_at: 2025-03-19T20:42:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -596,42 +596,38 @@ public void testMultipleCtesSameNameDifferentTableMultipleColumnsUtilized()
         // It's trying to add the third column of CTE1 of t1 but it does not exist.
         assertUtilizedTableColumns(
                 "with cte1 as (select x + 1 as c1 from t13), cte2 as (with cte1 as (select a + 1 as c2, b + 1 as c3, c as c4 from t1) select * from cte1) select cte1.c1, cte2.c4 from cte1 join cte2 on true",
-                ImmutableSet.of(ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x"),
-                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"))));
+                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x"),
+                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c")));
     }
 
     public void testInvokerView()
     {
-        assertUtilizedTableColumns("SELECT view_invoker1.a, view_invoker1.c, view_invoker2.y FROM view_invoker1 left join view_invoker2 on view_invoker2.y = view_invoker1.c", ImmutableSet.of(
+        assertUtilizedTableColumns("SELECT view_invoker1.a, view_invoker1.c, view_invoker2.y FROM view_invoker1 left join view_invoker2 on view_invoker2.y = view_invoker1.c",
                 ImmutableMap.of(
                         QualifiedObjectName.valueOf("tpch.s1.view_invoker1"), ImmutableSet.of("a", "c"),
                         QualifiedObjectName.valueOf("tpch.s1.view_invoker2"), ImmutableSet.of("y"),
                         QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c"),
-                        QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("y"))
-
-        ));
+                        QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("y")));
 
-        assertUtilizedTableColumns("SELECT view_invoker_with_cte1.c1, view_invoker_with_cte1.c3 FROM view_invoker_with_cte1", ImmutableSet.of(
+        assertUtilizedTableColumns("SELECT view_invoker_with_cte1.c1, view_invoker_with_cte1.c3 FROM view_invoker_with_cte1",
                 ImmutableMap.of(
                         QualifiedObjectName.valueOf("tpch.s1.view_invoker_with_cte1"), ImmutableSet.of("c1", "c3"),
-                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c"))
-        ));
+                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c")));
     }
 
     public void testDefinerView()
     {
         @Language("SQL") String query = "SELECT view_definer1.a, view_definer1.c, view_definer2.y FROM view_definer1 left join view_definer2 on view_definer2.y = view_definer1.c";
 
-        assertUtilizedTableColumns(query, ImmutableSet.of(
+        assertUtilizedTableColumns(query,
                 ImmutableMap.of(
path: presto-main/src/test/java/com/facebook/presto/sql/analyzer/TestUtilizedColumnsAnalyzer.java
user: login: rschlussel
body: shouldn't definer mode expect 2 different accessControlInfos?
created_at: 2025-03-26T14:23:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -596,42 +596,38 @@ public void testMultipleCtesSameNameDifferentTableMultipleColumnsUtilized()
         // It's trying to add the third column of CTE1 of t1 but it does not exist.
         assertUtilizedTableColumns(
                 "with cte1 as (select x + 1 as c1 from t13), cte2 as (with cte1 as (select a + 1 as c2, b + 1 as c3, c as c4 from t1) select * from cte1) select cte1.c1, cte2.c4 from cte1 join cte2 on true",
-                ImmutableSet.of(ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x"),
-                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"))));
+                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x"),
+                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c")));
     }
 
     public void testInvokerView()
     {
-        assertUtilizedTableColumns("SELECT view_invoker1.a, view_invoker1.c, view_invoker2.y FROM view_invoker1 left join view_invoker2 on view_invoker2.y = view_invoker1.c", ImmutableSet.of(
+        assertUtilizedTableColumns("SELECT view_invoker1.a, view_invoker1.c, view_invoker2.y FROM view_invoker1 left join view_invoker2 on view_invoker2.y = view_invoker1.c",
                 ImmutableMap.of(
                         QualifiedObjectName.valueOf("tpch.s1.view_invoker1"), ImmutableSet.of("a", "c"),
                         QualifiedObjectName.valueOf("tpch.s1.view_invoker2"), ImmutableSet.of("y"),
                         QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c"),
-                        QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("y"))
-
-        ));
+                        QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("y")));
 
-        assertUtilizedTableColumns("SELECT view_invoker_with_cte1.c1, view_invoker_with_cte1.c3 FROM view_invoker_with_cte1", ImmutableSet.of(
+        assertUtilizedTableColumns("SELECT view_invoker_with_cte1.c1, view_invoker_with_cte1.c3 FROM view_invoker_with_cte1",
                 ImmutableMap.of(
                         QualifiedObjectName.valueOf("tpch.s1.view_invoker_with_cte1"), ImmutableSet.of("c1", "c3"),
-                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c"))
-        ));
+                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c")));
     }
 
     public void testDefinerView()
     {
         @Language("SQL") String query = "SELECT view_definer1.a, view_definer1.c, view_definer2.y FROM view_definer1 left join view_definer2 on view_definer2.y = view_definer1.c";
 
-        assertUtilizedTableColumns(query, ImmutableSet.of(
+        assertUtilizedTableColumns(query,
                 ImmutableMap.of(
path: presto-main/src/test/java/com/facebook/presto/sql/analyzer/TestUtilizedColumnsAnalyzer.java
user: login: kevintang2022
body: When I ran this, there were 3 access control infos.
AccessControl1: [view_definer1, view_definer2]
AccessControl2: [t1]
AccessControl3: [t13]
created_at: 2025-03-26T17:48:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -596,42 +596,38 @@ public void testMultipleCtesSameNameDifferentTableMultipleColumnsUtilized()
         // It's trying to add the third column of CTE1 of t1 but it does not exist.
         assertUtilizedTableColumns(
                 "with cte1 as (select x + 1 as c1 from t13), cte2 as (with cte1 as (select a + 1 as c2, b + 1 as c3, c as c4 from t1) select * from cte1) select cte1.c1, cte2.c4 from cte1 join cte2 on true",
-                ImmutableSet.of(ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x"),
-                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"))));
+                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x"),
+                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c")));
     }
 
     public void testInvokerView()
     {
-        assertUtilizedTableColumns("SELECT view_invoker1.a, view_invoker1.c, view_invoker2.y FROM view_invoker1 left join view_invoker2 on view_invoker2.y = view_invoker1.c", ImmutableSet.of(
+        assertUtilizedTableColumns("SELECT view_invoker1.a, view_invoker1.c, view_invoker2.y FROM view_invoker1 left join view_invoker2 on view_invoker2.y = view_invoker1.c",
                 ImmutableMap.of(
                         QualifiedObjectName.valueOf("tpch.s1.view_invoker1"), ImmutableSet.of("a", "c"),
                         QualifiedObjectName.valueOf("tpch.s1.view_invoker2"), ImmutableSet.of("y"),
                         QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c"),
-                        QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("y"))
-
-        ));
+                        QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("y")));
 
-        assertUtilizedTableColumns("SELECT view_invoker_with_cte1.c1, view_invoker_with_cte1.c3 FROM view_invoker_with_cte1", ImmutableSet.of(
+        assertUtilizedTableColumns("SELECT view_invoker_with_cte1.c1, view_invoker_with_cte1.c3 FROM view_invoker_with_cte1",
                 ImmutableMap.of(
                         QualifiedObjectName.valueOf("tpch.s1.view_invoker_with_cte1"), ImmutableSet.of("c1", "c3"),
-                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c"))
-        ));
+                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c")));
     }
 
     public void testDefinerView()
     {
         @Language("SQL") String query = "SELECT view_definer1.a, view_definer1.c, view_definer2.y FROM view_definer1 left join view_definer2 on view_definer2.y = view_definer1.c";
 
-        assertUtilizedTableColumns(query, ImmutableSet.of(
+        assertUtilizedTableColumns(query,
                 ImmutableMap.of(
path: presto-main/src/test/java/com/facebook/presto/sql/analyzer/TestUtilizedColumnsAnalyzer.java
user: login: kevintang2022
body: I recently changed the test case because I added an equals method to AccessControlContext
created_at: 2025-03-26T17:48:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -596,42 +596,38 @@ public void testMultipleCtesSameNameDifferentTableMultipleColumnsUtilized()
         // It's trying to add the third column of CTE1 of t1 but it does not exist.
         assertUtilizedTableColumns(
                 "with cte1 as (select x + 1 as c1 from t13), cte2 as (with cte1 as (select a + 1 as c2, b + 1 as c3, c as c4 from t1) select * from cte1) select cte1.c1, cte2.c4 from cte1 join cte2 on true",
-                ImmutableSet.of(ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x"),
-                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"))));
+                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x"),
+                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c")));
     }
 
     public void testInvokerView()
     {
-        assertUtilizedTableColumns("SELECT view_invoker1.a, view_invoker1.c, view_invoker2.y FROM view_invoker1 left join view_invoker2 on view_invoker2.y = view_invoker1.c", ImmutableSet.of(
+        assertUtilizedTableColumns("SELECT view_invoker1.a, view_invoker1.c, view_invoker2.y FROM view_invoker1 left join view_invoker2 on view_invoker2.y = view_invoker1.c",
                 ImmutableMap.of(
                         QualifiedObjectName.valueOf("tpch.s1.view_invoker1"), ImmutableSet.of("a", "c"),
                         QualifiedObjectName.valueOf("tpch.s1.view_invoker2"), ImmutableSet.of("y"),
                         QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c"),
-                        QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("y"))
-
-        ));
+                        QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("y")));
 
-        assertUtilizedTableColumns("SELECT view_invoker_with_cte1.c1, view_invoker_with_cte1.c3 FROM view_invoker_with_cte1", ImmutableSet.of(
+        assertUtilizedTableColumns("SELECT view_invoker_with_cte1.c1, view_invoker_with_cte1.c3 FROM view_invoker_with_cte1",
                 ImmutableMap.of(
                         QualifiedObjectName.valueOf("tpch.s1.view_invoker_with_cte1"), ImmutableSet.of("c1", "c3"),
-                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c"))
-        ));
+                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c")));
     }
 
     public void testDefinerView()
     {
         @Language("SQL") String query = "SELECT view_definer1.a, view_definer1.c, view_definer2.y FROM view_definer1 left join view_definer2 on view_definer2.y = view_definer1.c";
 
-        assertUtilizedTableColumns(query, ImmutableSet.of(
+        assertUtilizedTableColumns(query,
                 ImmutableMap.of(
path: presto-main/src/test/java/com/facebook/presto/sql/analyzer/TestUtilizedColumnsAnalyzer.java
user: login: kevintang2022
body: For this query, can you give me what the expected result should actually be?
created_at: 2025-03-26T17:48:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -596,42 +596,38 @@ public void testMultipleCtesSameNameDifferentTableMultipleColumnsUtilized()
         // It's trying to add the third column of CTE1 of t1 but it does not exist.
         assertUtilizedTableColumns(
                 "with cte1 as (select x + 1 as c1 from t13), cte2 as (with cte1 as (select a + 1 as c2, b + 1 as c3, c as c4 from t1) select * from cte1) select cte1.c1, cte2.c4 from cte1 join cte2 on true",
-                ImmutableSet.of(ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x"),
-                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c"))));
+                ImmutableMap.of(QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("x"),
+                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "b", "c")));
     }
 
     public void testInvokerView()
     {
-        assertUtilizedTableColumns("SELECT view_invoker1.a, view_invoker1.c, view_invoker2.y FROM view_invoker1 left join view_invoker2 on view_invoker2.y = view_invoker1.c", ImmutableSet.of(
+        assertUtilizedTableColumns("SELECT view_invoker1.a, view_invoker1.c, view_invoker2.y FROM view_invoker1 left join view_invoker2 on view_invoker2.y = view_invoker1.c",
                 ImmutableMap.of(
                         QualifiedObjectName.valueOf("tpch.s1.view_invoker1"), ImmutableSet.of("a", "c"),
                         QualifiedObjectName.valueOf("tpch.s1.view_invoker2"), ImmutableSet.of("y"),
                         QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c"),
-                        QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("y"))
-
-        ));
+                        QualifiedObjectName.valueOf("tpch.s1.t13"), ImmutableSet.of("y")));
 
-        assertUtilizedTableColumns("SELECT view_invoker_with_cte1.c1, view_invoker_with_cte1.c3 FROM view_invoker_with_cte1", ImmutableSet.of(
+        assertUtilizedTableColumns("SELECT view_invoker_with_cte1.c1, view_invoker_with_cte1.c3 FROM view_invoker_with_cte1",
                 ImmutableMap.of(
                         QualifiedObjectName.valueOf("tpch.s1.view_invoker_with_cte1"), ImmutableSet.of("c1", "c3"),
-                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c"))
-        ));
+                        QualifiedObjectName.valueOf("tpch.s1.t1"), ImmutableSet.of("a", "c")));
     }
 
     public void testDefinerView()
     {
         @Language("SQL") String query = "SELECT view_definer1.a, view_definer1.c, view_definer2.y FROM view_definer1 left join view_definer2 on view_definer2.y = view_definer1.c";
 
-        assertUtilizedTableColumns(query, ImmutableSet.of(
+        assertUtilizedTableColumns(query,
                 ImmutableMap.of(
path: presto-main/src/test/java/com/facebook/presto/sql/analyzer/TestUtilizedColumnsAnalyzer.java
user: login: kevintang2022
body: It seems we create a new accessControl when it's definer mode, but not invoker mode

```
                if (owner.isPresent() && !owner.get().equals(session.getIdentity().getUser())) {
                    // definer mode
                    identity = new Identity(owner.get(), Optional.empty(), session.getIdentity().getExtraCredentials());
                    viewAccessControl = new ViewAccessControl(accessControl);
                }
                else {
                    identity = session.getIdentity();
                    viewAccessControl = accessControl;
                }
```
created_at: 2025-03-26T17:58:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -101,4 +102,27 @@ public Optional<String> getSchema()
     {
         return schema;
     }
+
+    @Override
+    public int hashCode()
+    {
+        return Objects.hash(queryId, clientInfo, clientTags, source, queryType);
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        AccessControlContext other = (AccessControlContext) obj;
+        return Objects.equals(this.queryId, other.queryId) &&
+                Objects.equals(this.clientInfo, other.clientInfo) &&
+                Objects.equals(this.clientTags, other.clientTags) &&
+                Objects.equals(this.source, other.source) &&
+                Objects.equals(this.queryType, other.queryType);
path: presto-spi/src/main/java/com/facebook/presto/spi/security/AccessControlContext.java
user: login: kevintang2022
body: Also need to include schema
created_at: 2025-03-26T19:33:13Z
author_association: CONTRIBUTOR

PR comments:
user: login: steveburnett
created_at: 2025-03-20T15:16:06Z
body: Thanks for the release note! Suggest rephrasing to follow the [Order of Changes](https://github.com/prestodb/presto/wiki/Release-Notes-Guidelines#order-of-changes) in the Release Notes Guidelines. I adapted phrasing from your Description in the PR, but if you have a better way to phrase it, please do. 

```
== RELEASE NOTES ==

General Changes
* Improve exploration of a view's definition by checking ACL only on the utilized columns. 
``` 
author_association: CONTRIBUTOR
user: login: kevintang2022
created_at: 2025-03-27T20:52:21Z
body: Needed to fix merge conflict on the test file
author_association: CONTRIBUTOR