diff --git a/src/backend/distributed/planner/multi_planner.c b/src/backend/distributed/planner/multi_planner.c
index 7839c7cfc..d81776541 100644
--- a/src/backend/distributed/planner/multi_planner.c
+++ b/src/backend/distributed/planner/multi_planner.c
@@ -454,6 +454,9 @@ FinalizeNonRouterPlan(PlannedStmt *localPlan, MultiPlan *multiPlan,
finalPlan->queryId = localPlan->queryId;
finalPlan->utilityStmt = localPlan->utilityStmt;
+ /* add original range table list for access permission checks */
+ finalPlan->rtable = list_concat(finalPlan->rtable, localPlan->rtable);
+
return finalPlan;
}
@@ -473,7 +476,7 @@ FinalizeRouterPlan(PlannedStmt *localPlan, CustomScan *customScan)
List *targetList = NIL;
List *columnNameList = NIL;
- /* we will have only one range table entry */
+ /* we will have custom scan range table entry as the first one in the list */
int customScanRangeTableIndex = 1;
/* build a targetlist to read from the custom scan output */
@@ -514,6 +517,9 @@ FinalizeRouterPlan(PlannedStmt *localPlan, CustomScan *customScan)
remoteScanRangeTableEntry = RemoteScanRangeTableEntry(columnNameList);
routerPlan->rtable = list_make1(remoteScanRangeTableEntry);
+ /* add original range table list for access permission checks */
+ routerPlan->rtable = list_concat(routerPlan->rtable, localPlan->rtable);
+
routerPlan->canSetTag = true;
routerPlan->relationOids = NIL;
diff --git a/src/test/regress/expected/multi_explain.out b/src/test/regress/expected/multi_explain.out
index e2ef27342..b5871d084 100644
--- a/src/test/regress/expected/multi_explain.out
+++ b/src/test/regress/expected/multi_explain.out
@@ -40,9 +40,9 @@ EXPLAIN (COSTS FALSE, FORMAT TEXT)
SELECT l_quantity, count(*) count_quantity FROM lineitem
GROUP BY l_quantity ORDER BY count_quantity, l_quantity;
Sort
- Sort Key: COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint), l_quantity
+ Sort Key: COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint), remote_scan.l_quantity
-> HashAggregate
- Group Key: l_quantity
+ Group Key: remote_scan.l_quantity
-> Custom Scan (Citus Real-Time)
Task Count: 8
Tasks Shown: One of 8
@@ -60,7 +60,7 @@ EXPLAIN (COSTS FALSE, FORMAT JSON)
"Plan": {
"Node Type": "Sort",
"Parallel Aware": false,
- "Sort Key": ["COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)", "l_quantity"],
+ "Sort Key": ["COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)", "remote_scan.l_quantity"],
"Plans": [
{
"Node Type": "Aggregate",
@@ -68,7 +68,7 @@ EXPLAIN (COSTS FALSE, FORMAT JSON)
"Partial Mode": "Simple",
"Parent Relationship": "Outer",
"Parallel Aware": false,
- "Group Key": ["l_quantity"],
+ "Group Key": ["remote_scan.l_quantity"],
"Plans": [
{
"Node Type": "Custom Scan",
@@ -131,8 +131,8 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
Sort
false
- - COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)
- - l_quantity
+ - COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)
+ - remote_scan.l_quantity
@@ -142,7 +142,7 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
Outer
false
- - l_quantity
+ - remote_scan.l_quantity
@@ -205,8 +205,8 @@ EXPLAIN (COSTS FALSE, FORMAT YAML)
Node Type: "Sort"
Parallel Aware: false
Sort Key:
- - "COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)"
- - "l_quantity"
+ - "COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)"
+ - "remote_scan.l_quantity"
Plans:
- Node Type: "Aggregate"
Strategy: "Hashed"
@@ -214,7 +214,7 @@ EXPLAIN (COSTS FALSE, FORMAT YAML)
Parent Relationship: "Outer"
Parallel Aware: false
Group Key:
- - "l_quantity"
+ - "remote_scan.l_quantity"
Plans:
- Node Type: "Custom Scan"
Parent Relationship: "Outer"
@@ -246,9 +246,9 @@ EXPLAIN (COSTS FALSE, FORMAT TEXT)
SELECT l_quantity, count(*) count_quantity FROM lineitem
GROUP BY l_quantity ORDER BY count_quantity, l_quantity;
Sort
- Sort Key: COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint), l_quantity
+ Sort Key: COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint), remote_scan.l_quantity
-> HashAggregate
- Group Key: l_quantity
+ Group Key: remote_scan.l_quantity
-> Custom Scan (Citus Real-Time)
Task Count: 8
Tasks Shown: One of 8
@@ -261,9 +261,9 @@ Sort
EXPLAIN (COSTS FALSE, VERBOSE TRUE)
SELECT sum(l_quantity) / avg(l_quantity) FROM lineitem;
Aggregate
- Output: (sum("?column?") / (sum("?column?_1") / pg_catalog.sum("?column?_2")))
+ Output: (sum(remote_scan."?column?") / (sum(remote_scan."?column?_1") / pg_catalog.sum(remote_scan."?column?_2")))
-> Custom Scan (Citus Real-Time)
- Output: "?column?", "?column?_1", "?column?_2"
+ Output: remote_scan."?column?", remote_scan."?column?_1", remote_scan."?column?_2"
Task Count: 8
Tasks Shown: One of 8
-> Task
@@ -279,7 +279,7 @@ EXPLAIN (COSTS FALSE)
ORDER BY l_quantity LIMIT 10;
Limit
-> Sort
- Sort Key: l_quantity
+ Sort Key: remote_scan.l_quantity
-> Custom Scan (Citus Real-Time)
Task Count: 8
Tasks Shown: One of 8
@@ -368,10 +368,10 @@ EXPLAIN (COSTS FALSE, VERBOSE TRUE)
SELECT sum(l_quantity) / avg(l_quantity) FROM lineitem
HAVING sum(l_quantity) > 100;
Aggregate
- Output: (sum("?column?") / (sum("?column?_1") / pg_catalog.sum("?column?_2")))
+ Output: (sum(remote_scan."?column?") / (sum(remote_scan."?column?_1") / pg_catalog.sum(remote_scan."?column?_2")))
Filter: (sum(remote_scan.worker_column_4) > '100'::numeric)
-> Custom Scan (Citus Real-Time)
- Output: "?column?", "?column?_1", "?column?_2", worker_column_4
+ Output: remote_scan."?column?", remote_scan."?column?_1", remote_scan."?column?_2", remote_scan.worker_column_4
Task Count: 8
Tasks Shown: One of 8
-> Task
@@ -386,11 +386,11 @@ EXPLAIN (COSTS FALSE, VERBOSE TRUE)
GROUP BY l_quantity
HAVING l_quantity > (100 * random());
HashAggregate
- Output: l_quantity
+ Output: remote_scan.l_quantity
Group Key: remote_scan.l_quantity
Filter: ((remote_scan.worker_column_2)::double precision > ('100'::double precision * random()))
-> Custom Scan (Citus Real-Time)
- Output: l_quantity, worker_column_2
+ Output: remote_scan.l_quantity, remote_scan.worker_column_2
Task Count: 8
Tasks Shown: One of 8
-> Task
diff --git a/src/test/regress/expected/multi_explain_0.out b/src/test/regress/expected/multi_explain_0.out
index af839b514..c7f97c695 100644
--- a/src/test/regress/expected/multi_explain_0.out
+++ b/src/test/regress/expected/multi_explain_0.out
@@ -40,9 +40,9 @@ EXPLAIN (COSTS FALSE, FORMAT TEXT)
SELECT l_quantity, count(*) count_quantity FROM lineitem
GROUP BY l_quantity ORDER BY count_quantity, l_quantity;
Sort
- Sort Key: COALESCE((sum((COALESCE((sum(count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint), l_quantity
+ Sort Key: COALESCE((sum((COALESCE((sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint), remote_scan.l_quantity
-> HashAggregate
- Group Key: l_quantity
+ Group Key: remote_scan.l_quantity
-> Custom Scan (Citus Real-Time)
Task Count: 8
Tasks Shown: One of 8
@@ -59,13 +59,13 @@ EXPLAIN (COSTS FALSE, FORMAT JSON)
{
"Plan": {
"Node Type": "Sort",
- "Sort Key": ["COALESCE((sum((COALESCE((sum(count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)", "l_quantity"],
+ "Sort Key": ["COALESCE((sum((COALESCE((sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)", "remote_scan.l_quantity"],
"Plans": [
{
"Node Type": "Aggregate",
"Strategy": "Hashed",
"Parent Relationship": "Outer",
- "Group Key": ["l_quantity"],
+ "Group Key": ["remote_scan.l_quantity"],
"Plans": [
{
"Node Type": "Custom Scan",
@@ -123,8 +123,8 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
Sort
- - COALESCE((sum((COALESCE((sum(count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)
- - l_quantity
+ - COALESCE((sum((COALESCE((sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)
+ - remote_scan.l_quantity
@@ -132,7 +132,7 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
Hashed
Outer
- - l_quantity
+ - remote_scan.l_quantity
@@ -190,14 +190,14 @@ EXPLAIN (COSTS FALSE, FORMAT YAML)
- Plan:
Node Type: "Sort"
Sort Key:
- - "COALESCE((sum((COALESCE((sum(count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)"
- - "l_quantity"
+ - "COALESCE((sum((COALESCE((sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)"
+ - "remote_scan.l_quantity"
Plans:
- Node Type: "Aggregate"
Strategy: "Hashed"
Parent Relationship: "Outer"
Group Key:
- - "l_quantity"
+ - "remote_scan.l_quantity"
Plans:
- Node Type: "Custom Scan"
Parent Relationship: "Outer"
@@ -225,9 +225,9 @@ EXPLAIN (COSTS FALSE, FORMAT TEXT)
SELECT l_quantity, count(*) count_quantity FROM lineitem
GROUP BY l_quantity ORDER BY count_quantity, l_quantity;
Sort
- Sort Key: COALESCE((sum((COALESCE((sum(count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint), l_quantity
+ Sort Key: COALESCE((sum((COALESCE((sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint), remote_scan.l_quantity
-> HashAggregate
- Group Key: l_quantity
+ Group Key: remote_scan.l_quantity
-> Custom Scan (Citus Real-Time)
Task Count: 8
Tasks Shown: One of 8
@@ -240,9 +240,9 @@ Sort
EXPLAIN (COSTS FALSE, VERBOSE TRUE)
SELECT sum(l_quantity) / avg(l_quantity) FROM lineitem;
Aggregate
- Output: (sum("?column?") / (sum("?column?_1") / sum("?column?_2")))
+ Output: (sum(remote_scan."?column?") / (sum(remote_scan."?column?_1") / sum(remote_scan."?column?_2")))
-> Custom Scan (Citus Real-Time)
- Output: "?column?", "?column?_1", "?column?_2"
+ Output: remote_scan."?column?", remote_scan."?column?_1", remote_scan."?column?_2"
Task Count: 8
Tasks Shown: One of 8
-> Task
@@ -258,7 +258,7 @@ EXPLAIN (COSTS FALSE)
ORDER BY l_quantity LIMIT 10;
Limit
-> Sort
- Sort Key: l_quantity
+ Sort Key: remote_scan.l_quantity
-> Custom Scan (Citus Real-Time)
Task Count: 8
Tasks Shown: One of 8
@@ -347,10 +347,10 @@ EXPLAIN (COSTS FALSE, VERBOSE TRUE)
SELECT sum(l_quantity) / avg(l_quantity) FROM lineitem
HAVING sum(l_quantity) > 100;
Aggregate
- Output: (sum("?column?") / (sum("?column?_1") / sum("?column?_2")))
+ Output: (sum(remote_scan."?column?") / (sum(remote_scan."?column?_1") / sum(remote_scan."?column?_2")))
Filter: (sum(remote_scan.worker_column_4) > '100'::numeric)
-> Custom Scan (Citus Real-Time)
- Output: "?column?", "?column?_1", "?column?_2", worker_column_4
+ Output: remote_scan."?column?", remote_scan."?column?_1", remote_scan."?column?_2", remote_scan.worker_column_4
Task Count: 8
Tasks Shown: One of 8
-> Task
@@ -365,11 +365,11 @@ EXPLAIN (COSTS FALSE, VERBOSE TRUE)
GROUP BY l_quantity
HAVING l_quantity > (100 * random());
HashAggregate
- Output: l_quantity
+ Output: remote_scan.l_quantity
Group Key: remote_scan.l_quantity
Filter: ((remote_scan.worker_column_2)::double precision > ('100'::double precision * random()))
-> Custom Scan (Citus Real-Time)
- Output: l_quantity, worker_column_2
+ Output: remote_scan.l_quantity, remote_scan.worker_column_2
Task Count: 8
Tasks Shown: One of 8
-> Task
diff --git a/src/test/regress/expected/multi_join_order_tpch_large.out b/src/test/regress/expected/multi_join_order_tpch_large.out
index 9489b567e..8f4655b46 100644
--- a/src/test/regress/expected/multi_join_order_tpch_large.out
+++ b/src/test/regress/expected/multi_join_order_tpch_large.out
@@ -55,12 +55,12 @@ ORDER BY
revenue DESC,
o_orderdate;
LOG: join order: [ "orders" ][ local partition join "lineitem" ][ single partition join "customer" ]
- QUERY PLAN
---------------------------------------------------------------------------------
+ QUERY PLAN
+------------------------------------------------------------------------------------------------
Sort (cost=0.00..0.00 rows=0 width=0)
- Sort Key: sum((sum(revenue))) DESC, o_orderdate
+ Sort Key: sum((sum(remote_scan.revenue))) DESC, remote_scan.o_orderdate
-> HashAggregate (cost=0.00..0.00 rows=0 width=0)
- Group Key: l_orderkey, o_orderdate, o_shippriority
+ Group Key: remote_scan.l_orderkey, remote_scan.o_orderdate, remote_scan.o_shippriority
-> Custom Scan (Citus Task-Tracker) (cost=0.00..0.00 rows=0 width=0)
explain statements for distributed queries are not enabled
(6 rows)
@@ -98,12 +98,12 @@ GROUP BY
ORDER BY
revenue DESC;
LOG: join order: [ "orders" ][ local partition join "lineitem" ][ single partition join "customer" ][ broadcast join "nation" ]
- QUERY PLAN
-----------------------------------------------------------------------------------------
+ QUERY PLAN
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=0.00..0.00 rows=0 width=0)
- Sort Key: sum((sum(revenue))) DESC
+ Sort Key: sum((sum(remote_scan.revenue))) DESC
-> HashAggregate (cost=0.00..0.00 rows=0 width=0)
- Group Key: c_custkey, c_name, c_acctbal, c_phone, n_name, c_address, c_comment
+ Group Key: remote_scan.c_custkey, remote_scan.c_name, remote_scan.c_acctbal, remote_scan.c_phone, remote_scan.n_name, remote_scan.c_address, remote_scan.c_comment
-> Custom Scan (Citus Task-Tracker) (cost=0.00..0.00 rows=0 width=0)
explain statements for distributed queries are not enabled
(6 rows)
@@ -161,7 +161,7 @@ LOG: join order: [ "lineitem" ][ local partition join "orders" ][ single partit
QUERY PLAN
--------------------------------------------------------------------------
HashAggregate (cost=0.00..0.00 rows=0 width=0)
- Group Key: l_partkey
+ Group Key: remote_scan.l_partkey
-> Custom Scan (Citus Task-Tracker) (cost=0.00..0.00 rows=0 width=0)
explain statements for distributed queries are not enabled
(4 rows)
diff --git a/src/test/regress/expected/multi_join_order_tpch_small.out b/src/test/regress/expected/multi_join_order_tpch_small.out
index c0466b1e3..b6f8cbf78 100644
--- a/src/test/regress/expected/multi_join_order_tpch_small.out
+++ b/src/test/regress/expected/multi_join_order_tpch_small.out
@@ -49,12 +49,12 @@ ORDER BY
revenue DESC,
o_orderdate;
LOG: join order: [ "orders" ][ broadcast join "customer" ][ local partition join "lineitem" ]
- QUERY PLAN
------------------------------------------------------------------------------
+ QUERY PLAN
+------------------------------------------------------------------------------------------------
Sort (cost=0.00..0.00 rows=0 width=0)
- Sort Key: sum((sum(revenue))) DESC, o_orderdate
+ Sort Key: sum((sum(remote_scan.revenue))) DESC, remote_scan.o_orderdate
-> HashAggregate (cost=0.00..0.00 rows=0 width=0)
- Group Key: l_orderkey, o_orderdate, o_shippriority
+ Group Key: remote_scan.l_orderkey, remote_scan.o_orderdate, remote_scan.o_shippriority
-> Custom Scan (Citus Real-Time) (cost=0.00..0.00 rows=0 width=0)
explain statements for distributed queries are not enabled
(6 rows)
@@ -92,12 +92,12 @@ GROUP BY
ORDER BY
revenue DESC;
LOG: join order: [ "orders" ][ broadcast join "customer" ][ broadcast join "nation" ][ local partition join "lineitem" ]
- QUERY PLAN
-----------------------------------------------------------------------------------------
+ QUERY PLAN
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=0.00..0.00 rows=0 width=0)
- Sort Key: sum((sum(revenue))) DESC
+ Sort Key: sum((sum(remote_scan.revenue))) DESC
-> HashAggregate (cost=0.00..0.00 rows=0 width=0)
- Group Key: c_custkey, c_name, c_acctbal, c_phone, n_name, c_address, c_comment
+ Group Key: remote_scan.c_custkey, remote_scan.c_name, remote_scan.c_acctbal, remote_scan.c_phone, remote_scan.n_name, remote_scan.c_address, remote_scan.c_comment
-> Custom Scan (Citus Real-Time) (cost=0.00..0.00 rows=0 width=0)
explain statements for distributed queries are not enabled
(6 rows)
diff --git a/src/test/regress/expected/multi_multiuser.out b/src/test/regress/expected/multi_multiuser.out
new file mode 100644
index 000000000..3a4c9c0a5
--- /dev/null
+++ b/src/test/regress/expected/multi_multiuser.out
@@ -0,0 +1,138 @@
+--
+-- MULTI_MULTIUSERS
+--
+-- Test user permissions.
+--
+ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 1420000;
+ALTER SEQUENCE pg_catalog.pg_dist_jobid_seq RESTART 1420000;
+SET citus.shard_replication_factor TO 1;
+SET citus.shard_count TO 2;
+CREATE TABLE test (id integer);
+SELECT create_distributed_table('test', 'id');
+ create_distributed_table
+--------------------------
+
+(1 row)
+
+CREATE USER full_access;
+NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
+HINT: Connect to worker nodes directly to manually create all necessary users and roles.
+CREATE USER read_access;
+NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
+HINT: Connect to worker nodes directly to manually create all necessary users and roles.
+CREATE USER no_access;
+NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
+HINT: Connect to worker nodes directly to manually create all necessary users and roles.
+GRANT ALL ON TABLE test TO full_access;
+GRANT SELECT ON TABLE test TO read_access;
+\c - - - :worker_1_port
+CREATE USER full_access;
+NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
+HINT: Connect to worker nodes directly to manually create all necessary users and roles.
+CREATE USER read_access;
+NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
+HINT: Connect to worker nodes directly to manually create all necessary users and roles.
+CREATE USER no_access;
+NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
+HINT: Connect to worker nodes directly to manually create all necessary users and roles.
+GRANT ALL ON TABLE test_1420000 TO full_access;
+GRANT SELECT ON TABLE test_1420000 TO read_access;
+\c - - - :worker_2_port
+CREATE USER full_access;
+NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
+HINT: Connect to worker nodes directly to manually create all necessary users and roles.
+CREATE USER read_access;
+NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
+HINT: Connect to worker nodes directly to manually create all necessary users and roles.
+CREATE USER no_access;
+NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
+HINT: Connect to worker nodes directly to manually create all necessary users and roles.
+GRANT ALL ON TABLE test_1420001 TO full_access;
+GRANT SELECT ON TABLE test_1420001 TO read_access;
+\c - - - :master_port
+-- create prepare tests
+PREPARE prepare_insert AS INSERT INTO test VALUES ($1);
+PREPARE prepare_select AS SELECT count(*) FROM test;
+-- check full permission
+SET ROLE full_access;
+EXECUTE prepare_insert(1);
+EXECUTE prepare_select;
+ count
+-------
+ 1
+(1 row)
+
+INSERT INTO test VALUES (2);
+SELECT count(*) FROM test;
+ count
+-------
+ 2
+(1 row)
+
+SELECT count(*) FROM test WHERE id = 1;
+ count
+-------
+ 1
+(1 row)
+
+SET citus.task_executor_type TO 'task-tracker';
+SELECT count(*) FROM test;
+ count
+-------
+ 2
+(1 row)
+
+SET citus.task_executor_type TO 'real-time';
+-- check read permission
+SET ROLE read_access;
+EXECUTE prepare_insert(1);
+ERROR: permission denied for relation test
+EXECUTE prepare_select;
+ count
+-------
+ 2
+(1 row)
+
+INSERT INTO test VALUES (2);
+ERROR: permission denied for relation test
+SELECT count(*) FROM test;
+ count
+-------
+ 2
+(1 row)
+
+SELECT count(*) FROM test WHERE id = 1;
+ count
+-------
+ 1
+(1 row)
+
+SET citus.task_executor_type TO 'task-tracker';
+SELECT count(*) FROM test;
+ count
+-------
+ 2
+(1 row)
+
+SET citus.task_executor_type TO 'real-time';
+-- check no permission
+SET ROLE no_access;
+EXECUTE prepare_insert(1);
+ERROR: permission denied for relation test
+EXECUTE prepare_select;
+ERROR: permission denied for relation test
+INSERT INTO test VALUES (2);
+ERROR: permission denied for relation test
+SELECT count(*) FROM test;
+ERROR: permission denied for relation test
+SELECT count(*) FROM test WHERE id = 1;
+ERROR: permission denied for relation test
+SET citus.task_executor_type TO 'task-tracker';
+SELECT count(*) FROM test;
+ERROR: permission denied for relation test
+SET citus.task_executor_type TO 'real-time';
+RESET ROLE;
+DROP TABLE test;
+DROP USER full_access;
+DROP USER read_access;
+DROP USER no_access;
diff --git a/src/test/regress/expected/multi_mx_explain.out b/src/test/regress/expected/multi_mx_explain.out
index 02dfbee99..8faca4b77 100644
--- a/src/test/regress/expected/multi_mx_explain.out
+++ b/src/test/regress/expected/multi_mx_explain.out
@@ -62,9 +62,9 @@ EXPLAIN (COSTS FALSE, FORMAT TEXT)
SELECT l_quantity, count(*) count_quantity FROM lineitem_mx
GROUP BY l_quantity ORDER BY count_quantity, l_quantity;
Sort
- Sort Key: COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint), l_quantity
+ Sort Key: COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint), remote_scan.l_quantity
-> HashAggregate
- Group Key: l_quantity
+ Group Key: remote_scan.l_quantity
-> Custom Scan (Citus Real-Time)
Task Count: 16
Tasks Shown: One of 16
@@ -82,7 +82,7 @@ EXPLAIN (COSTS FALSE, FORMAT JSON)
"Plan": {
"Node Type": "Sort",
"Parallel Aware": false,
- "Sort Key": ["COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)", "l_quantity"],
+ "Sort Key": ["COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)", "remote_scan.l_quantity"],
"Plans": [
{
"Node Type": "Aggregate",
@@ -90,7 +90,7 @@ EXPLAIN (COSTS FALSE, FORMAT JSON)
"Partial Mode": "Simple",
"Parent Relationship": "Outer",
"Parallel Aware": false,
- "Group Key": ["l_quantity"],
+ "Group Key": ["remote_scan.l_quantity"],
"Plans": [
{
"Node Type": "Custom Scan",
@@ -154,8 +154,8 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
Sort
false
- - COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)
- - l_quantity
+ - COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)
+ - remote_scan.l_quantity
@@ -165,7 +165,7 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
Outer
false
- - l_quantity
+ - remote_scan.l_quantity
@@ -228,8 +228,8 @@ EXPLAIN (COSTS FALSE, FORMAT YAML)
Node Type: "Sort"
Parallel Aware: false
Sort Key:
- - "COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)"
- - "l_quantity"
+ - "COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)"
+ - "remote_scan.l_quantity"
Plans:
- Node Type: "Aggregate"
Strategy: "Hashed"
@@ -237,7 +237,7 @@ EXPLAIN (COSTS FALSE, FORMAT YAML)
Parent Relationship: "Outer"
Parallel Aware: false
Group Key:
- - "l_quantity"
+ - "remote_scan.l_quantity"
Plans:
- Node Type: "Custom Scan"
Parent Relationship: "Outer"
@@ -269,9 +269,9 @@ EXPLAIN (COSTS FALSE, FORMAT TEXT)
SELECT l_quantity, count(*) count_quantity FROM lineitem_mx
GROUP BY l_quantity ORDER BY count_quantity, l_quantity;
Sort
- Sort Key: COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint), l_quantity
+ Sort Key: COALESCE((pg_catalog.sum((COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint), remote_scan.l_quantity
-> HashAggregate
- Group Key: l_quantity
+ Group Key: remote_scan.l_quantity
-> Custom Scan (Citus Real-Time)
Task Count: 16
Tasks Shown: One of 16
@@ -285,9 +285,9 @@ Sort
EXPLAIN (COSTS FALSE, VERBOSE TRUE)
SELECT sum(l_quantity) / avg(l_quantity) FROM lineitem_mx;
Aggregate
- Output: (sum("?column?") / (sum("?column?_1") / pg_catalog.sum("?column?_2")))
+ Output: (sum(remote_scan."?column?") / (sum(remote_scan."?column?_1") / pg_catalog.sum(remote_scan."?column?_2")))
-> Custom Scan (Citus Real-Time)
- Output: "?column?", "?column?_1", "?column?_2"
+ Output: remote_scan."?column?", remote_scan."?column?_1", remote_scan."?column?_2"
Task Count: 16
Tasks Shown: One of 16
-> Task
@@ -303,7 +303,7 @@ EXPLAIN (COSTS FALSE)
ORDER BY l_quantity LIMIT 10;
Limit
-> Sort
- Sort Key: l_quantity
+ Sort Key: remote_scan.l_quantity
-> Custom Scan (Citus Real-Time)
Task Count: 16
Tasks Shown: One of 16
diff --git a/src/test/regress/expected/multi_mx_explain_0.out b/src/test/regress/expected/multi_mx_explain_0.out
index 0a74d3001..3c425c949 100644
--- a/src/test/regress/expected/multi_mx_explain_0.out
+++ b/src/test/regress/expected/multi_mx_explain_0.out
@@ -62,9 +62,9 @@ EXPLAIN (COSTS FALSE, FORMAT TEXT)
SELECT l_quantity, count(*) count_quantity FROM lineitem_mx
GROUP BY l_quantity ORDER BY count_quantity, l_quantity;
Sort
- Sort Key: COALESCE((sum((COALESCE((sum(count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint), l_quantity
+ Sort Key: COALESCE((sum((COALESCE((sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint), remote_scan.l_quantity
-> HashAggregate
- Group Key: l_quantity
+ Group Key: remote_scan.l_quantity
-> Custom Scan (Citus Real-Time)
Task Count: 16
Tasks Shown: One of 16
@@ -81,13 +81,13 @@ EXPLAIN (COSTS FALSE, FORMAT JSON)
{
"Plan": {
"Node Type": "Sort",
- "Sort Key": ["COALESCE((sum((COALESCE((sum(count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)", "l_quantity"],
+ "Sort Key": ["COALESCE((sum((COALESCE((sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)", "remote_scan.l_quantity"],
"Plans": [
{
"Node Type": "Aggregate",
"Strategy": "Hashed",
"Parent Relationship": "Outer",
- "Group Key": ["l_quantity"],
+ "Group Key": ["remote_scan.l_quantity"],
"Plans": [
{
"Node Type": "Custom Scan",
@@ -146,8 +146,8 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
Sort
- - COALESCE((sum((COALESCE((sum(count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)
- - l_quantity
+ - COALESCE((sum((COALESCE((sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)
+ - remote_scan.l_quantity
@@ -155,7 +155,7 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
Hashed
Outer
- - l_quantity
+ - remote_scan.l_quantity
@@ -213,14 +213,14 @@ EXPLAIN (COSTS FALSE, FORMAT YAML)
- Plan:
Node Type: "Sort"
Sort Key:
- - "COALESCE((sum((COALESCE((sum(count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)"
- - "l_quantity"
+ - "COALESCE((sum((COALESCE((sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint)"
+ - "remote_scan.l_quantity"
Plans:
- Node Type: "Aggregate"
Strategy: "Hashed"
Parent Relationship: "Outer"
Group Key:
- - "l_quantity"
+ - "remote_scan.l_quantity"
Plans:
- Node Type: "Custom Scan"
Parent Relationship: "Outer"
@@ -248,9 +248,9 @@ EXPLAIN (COSTS FALSE, FORMAT TEXT)
SELECT l_quantity, count(*) count_quantity FROM lineitem_mx
GROUP BY l_quantity ORDER BY count_quantity, l_quantity;
Sort
- Sort Key: COALESCE((sum((COALESCE((sum(count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint), l_quantity
+ Sort Key: COALESCE((sum((COALESCE((sum(remote_scan.count_quantity))::bigint, '0'::bigint))))::bigint, '0'::bigint), remote_scan.l_quantity
-> HashAggregate
- Group Key: l_quantity
+ Group Key: remote_scan.l_quantity
-> Custom Scan (Citus Real-Time)
Task Count: 16
Tasks Shown: One of 16
@@ -264,9 +264,9 @@ Sort
EXPLAIN (COSTS FALSE, VERBOSE TRUE)
SELECT sum(l_quantity) / avg(l_quantity) FROM lineitem_mx;
Aggregate
- Output: (sum("?column?") / (sum("?column?_1") / sum("?column?_2")))
+ Output: (sum(remote_scan."?column?") / (sum(remote_scan."?column?_1") / sum(remote_scan."?column?_2")))
-> Custom Scan (Citus Real-Time)
- Output: "?column?", "?column?_1", "?column?_2"
+ Output: remote_scan."?column?", remote_scan."?column?_1", remote_scan."?column?_2"
Task Count: 16
Tasks Shown: One of 16
-> Task
@@ -282,7 +282,7 @@ EXPLAIN (COSTS FALSE)
ORDER BY l_quantity LIMIT 10;
Limit
-> Sort
- Sort Key: l_quantity
+ Sort Key: remote_scan.l_quantity
-> Custom Scan (Citus Real-Time)
Task Count: 16
Tasks Shown: One of 16
diff --git a/src/test/regress/multi_schedule b/src/test/regress/multi_schedule
index 87cc32444..986ccce31 100644
--- a/src/test/regress/multi_schedule
+++ b/src/test/regress/multi_schedule
@@ -225,3 +225,8 @@ test: multi_remove_node_reference_table
# multi_transactional_drop_shards tests for dropping shards using connection API
# ----------
test: multi_transactional_drop_shards
+
+# ----------
+# multi_multiuser tests simple combinations of permission access and queries
+# ----------
+test: multi_multiuser
diff --git a/src/test/regress/output/multi_subquery.source b/src/test/regress/output/multi_subquery.source
index 4c5931f17..3f892b2fa 100644
--- a/src/test/regress/output/multi_subquery.source
+++ b/src/test/regress/output/multi_subquery.source
@@ -853,7 +853,7 @@ GROUP BY
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
HashAggregate (cost=0.00..0.00 rows=0 width=0)
- Group Key: hasdone
+ Group Key: remote_scan.hasdone
-> Custom Scan (Citus Real-Time) (cost=0.00..0.00 rows=0 width=0)
Task Count: 2
Tasks Shown: One of 2
@@ -1020,7 +1020,7 @@ LIMIT
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.00..0.00 rows=0 width=0)
-> Sort (cost=0.00..0.00 rows=0 width=0)
- Sort Key: user_lastseen DESC
+ Sort Key: remote_scan.user_lastseen DESC
-> Custom Scan (Citus Real-Time) (cost=0.00..0.00 rows=0 width=0)
Task Count: 2
Tasks Shown: One of 2
diff --git a/src/test/regress/output/multi_subquery_0.source b/src/test/regress/output/multi_subquery_0.source
index 096c204e4..5d5eb53e9 100644
--- a/src/test/regress/output/multi_subquery_0.source
+++ b/src/test/regress/output/multi_subquery_0.source
@@ -853,7 +853,7 @@ GROUP BY
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
HashAggregate (cost=0.00..0.00 rows=0 width=0)
- Group Key: hasdone
+ Group Key: remote_scan.hasdone
-> Custom Scan (Citus Real-Time) (cost=0.00..0.00 rows=0 width=0)
Task Count: 2
Tasks Shown: One of 2
@@ -1017,7 +1017,7 @@ LIMIT
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.00..0.00 rows=0 width=0)
-> Sort (cost=0.00..0.00 rows=0 width=0)
- Sort Key: user_lastseen DESC
+ Sort Key: remote_scan.user_lastseen DESC
-> Custom Scan (Citus Real-Time) (cost=0.00..0.00 rows=0 width=0)
Task Count: 2
Tasks Shown: One of 2
diff --git a/src/test/regress/sql/multi_multiuser.sql b/src/test/regress/sql/multi_multiuser.sql
new file mode 100644
index 000000000..486b827b3
--- /dev/null
+++ b/src/test/regress/sql/multi_multiuser.sql
@@ -0,0 +1,92 @@
+--
+-- MULTI_MULTIUSERS
+--
+-- Test user permissions.
+--
+
+ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 1420000;
+ALTER SEQUENCE pg_catalog.pg_dist_jobid_seq RESTART 1420000;
+
+SET citus.shard_replication_factor TO 1;
+SET citus.shard_count TO 2;
+
+CREATE TABLE test (id integer);
+SELECT create_distributed_table('test', 'id');
+
+CREATE USER full_access;
+CREATE USER read_access;
+CREATE USER no_access;
+
+GRANT ALL ON TABLE test TO full_access;
+GRANT SELECT ON TABLE test TO read_access;
+
+\c - - - :worker_1_port
+CREATE USER full_access;
+CREATE USER read_access;
+CREATE USER no_access;
+
+GRANT ALL ON TABLE test_1420000 TO full_access;
+GRANT SELECT ON TABLE test_1420000 TO read_access;
+
+\c - - - :worker_2_port
+CREATE USER full_access;
+CREATE USER read_access;
+CREATE USER no_access;
+
+GRANT ALL ON TABLE test_1420001 TO full_access;
+GRANT SELECT ON TABLE test_1420001 TO read_access;
+
+\c - - - :master_port
+
+-- create prepare tests
+PREPARE prepare_insert AS INSERT INTO test VALUES ($1);
+PREPARE prepare_select AS SELECT count(*) FROM test;
+
+-- check full permission
+SET ROLE full_access;
+
+EXECUTE prepare_insert(1);
+EXECUTE prepare_select;
+
+INSERT INTO test VALUES (2);
+SELECT count(*) FROM test;
+SELECT count(*) FROM test WHERE id = 1;
+
+SET citus.task_executor_type TO 'task-tracker';
+SELECT count(*) FROM test;
+SET citus.task_executor_type TO 'real-time';
+
+-- check read permission
+SET ROLE read_access;
+
+EXECUTE prepare_insert(1);
+EXECUTE prepare_select;
+
+INSERT INTO test VALUES (2);
+SELECT count(*) FROM test;
+SELECT count(*) FROM test WHERE id = 1;
+
+SET citus.task_executor_type TO 'task-tracker';
+SELECT count(*) FROM test;
+SET citus.task_executor_type TO 'real-time';
+
+-- check no permission
+SET ROLE no_access;
+
+EXECUTE prepare_insert(1);
+EXECUTE prepare_select;
+
+INSERT INTO test VALUES (2);
+SELECT count(*) FROM test;
+SELECT count(*) FROM test WHERE id = 1;
+
+SET citus.task_executor_type TO 'task-tracker';
+SELECT count(*) FROM test;
+SET citus.task_executor_type TO 'real-time';
+
+RESET ROLE;
+
+DROP TABLE test;
+DROP USER full_access;
+DROP USER read_access;
+DROP USER no_access;