From 21464adfecea1f8b1604356909420303f2041bed Mon Sep 17 00:00:00 2001 From: Karina <55838532+Green-Chan@users.noreply.github.com> Date: Wed, 17 Jan 2024 16:39:07 +0300 Subject: [PATCH 1/9] Make isolation_update_node test system independent (#7423) Test isolation_update_node fails on some systems with the following error: ``` -s2: WARNING: connection to the remote node non-existent:57637 failed with the following error: could not translate host name "non-existent" to address: Name or service not known +s2: WARNING: connection to the remote node non-existent:57637 failed with the following error: could not translate host name "non-existent" to address: Temporary failure in name resolution ``` This slightly modifies an already existing [normalization rule](https://github.com/citusdata/citus/blob/739c6d26df56d38cda7f5420cccca947874d71e6/src/test/regress/bin/normalize.sed#L217-L218) to fix it. Co-authored-by: Karina Litskevich --- src/test/regress/bin/normalize.sed | 2 +- src/test/regress/expected/isolation_update_node.out | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/regress/bin/normalize.sed b/src/test/regress/bin/normalize.sed index 1d293e964..fb51bdc33 100644 --- a/src/test/regress/bin/normalize.sed +++ b/src/test/regress/bin/normalize.sed @@ -215,7 +215,7 @@ s/^(ERROR: The index name \(test_index_creation1_p2020_09_26)_([0-9])+_(tenant_ s/^(DEBUG: the index name on the shards of the partition is too long, switching to sequential and local execution mode to prevent self deadlocks: test_index_creation1_p2020_09_26)_([0-9])+_(tenant_id_timeperiod_idx)/\1_xxxxxx_\3/g # normalize errors for not being able to connect to a non-existing host -s/could not translate host name "foobar" to address: .*$/could not translate host name "foobar" to address: /g +s/could not translate host name "([A-Za-z0-9\.\-]+)" to address: .*$/could not translate host name "\1" to address: /g # ignore PL/pgSQL line numbers that differ on Mac builds s/(CONTEXT: PL\/pgSQL function .* line )([0-9]+)/\1XX/g diff --git a/src/test/regress/expected/isolation_update_node.out b/src/test/regress/expected/isolation_update_node.out index 1a1c65ec8..4b0a5f680 100644 --- a/src/test/regress/expected/isolation_update_node.out +++ b/src/test/regress/expected/isolation_update_node.out @@ -250,7 +250,7 @@ count step s1-commit-prepared: COMMIT prepared 'label'; -s2: WARNING: connection to the remote node non-existent:57637 failed with the following error: could not translate host name "non-existent" to address: Name or service not known +s2: WARNING: connection to the remote node non-existent:57637 failed with the following error: could not translate host name "non-existent" to address: step s2-execute-prepared: EXECUTE foo; From 51e607878b375c2860e2dd75f36de8cce246da50 Mon Sep 17 00:00:00 2001 From: zhjwpku Date: Wed, 17 Jan 2024 22:30:23 +0800 Subject: [PATCH 2/9] remove a duplicate forward declaration and polish some comments (#7371) remove a duplicate forward declaration and polish some comments Signed-off-by: Zhao Junwang --- .../distributed/executor/adaptive_executor.c | 10 ++++------ .../distributed/executor/multi_executor.c | 2 +- .../planner/fast_path_router_planner.c | 2 +- .../planner/multi_logical_planner.c | 6 +++--- .../planner/multi_router_planner.c | 20 +++++++++---------- src/include/distributed/distributed_planner.h | 2 +- .../distributed/multi_physical_planner.h | 6 +++--- 7 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/backend/distributed/executor/adaptive_executor.c b/src/backend/distributed/executor/adaptive_executor.c index b5566985a..1b0277f2e 100644 --- a/src/backend/distributed/executor/adaptive_executor.c +++ b/src/backend/distributed/executor/adaptive_executor.c @@ -401,7 +401,7 @@ typedef struct WorkerPool /* * Placement executions destined for worker node, but not assigned to any - * connection and not ready to start. + * connection and ready to start. */ dlist_head readyTaskQueue; int readyTaskCount; @@ -492,8 +492,6 @@ typedef struct WorkerSession } WorkerSession; -struct TaskPlacementExecution; - /* GUC, determining whether Citus opens 1 connection per task */ bool ForceMaxQueryParallelization = false; int MaxAdaptiveExecutorPoolSize = 16; @@ -585,7 +583,7 @@ typedef enum TaskPlacementExecutionState } TaskPlacementExecutionState; /* - * TaskPlacementExecution represents the an execution of a command + * TaskPlacementExecution represents the execution of a command * on a shard placement. */ typedef struct TaskPlacementExecution @@ -1908,7 +1906,7 @@ RunDistributedExecution(DistributedExecution *execution) /* * Iterate until all the tasks are finished. Once all the tasks - * are finished, ensure that that all the connection initializations + * are finished, ensure that all the connection initializations * are also finished. Otherwise, those connections are terminated * abruptly before they are established (or failed). Instead, we let * the ConnectionStateMachine() to properly handle them. @@ -3118,7 +3116,7 @@ ConnectionStateMachine(WorkerSession *session) * * We can only retry connection when the remote transaction has * not started over the connection. Otherwise, we'd have to deal - * with restoring the transaction state, which iis beyond our + * with restoring the transaction state, which is beyond our * purpose at this time. */ RemoteTransaction *transaction = &connection->remoteTransaction; diff --git a/src/backend/distributed/executor/multi_executor.c b/src/backend/distributed/executor/multi_executor.c index 45a791af4..386a278b4 100644 --- a/src/backend/distributed/executor/multi_executor.c +++ b/src/backend/distributed/executor/multi_executor.c @@ -168,7 +168,7 @@ CitusExecutorRun(QueryDesc *queryDesc, executorBoundParams = queryDesc->params; /* - * We do some potentially time consuming operations our self now before we hand of + * We do some potentially time consuming operations ourself now before we hand off * control to postgres' executor. To make sure that time spent is accurately measured * we remove the totaltime instrumentation from the queryDesc. Instead we will start * and stop the instrumentation of the total time and put it back on the queryDesc diff --git a/src/backend/distributed/planner/fast_path_router_planner.c b/src/backend/distributed/planner/fast_path_router_planner.c index 531075f9e..59f80bb40 100644 --- a/src/backend/distributed/planner/fast_path_router_planner.c +++ b/src/backend/distributed/planner/fast_path_router_planner.c @@ -252,7 +252,7 @@ FastPathRouterQuery(Query *query, Node **distributionKeyValue) /* * Distribution column must be used in a simple equality match check and it must be - * place at top level conjustion operator. In simple words, we should have + * place at top level conjunction operator. In simple words, we should have * WHERE dist_key = VALUE [AND ....]; * * We're also not allowing any other appearances of the distribution key in the quals. diff --git a/src/backend/distributed/planner/multi_logical_planner.c b/src/backend/distributed/planner/multi_logical_planner.c index f62e309f2..5201195c7 100644 --- a/src/backend/distributed/planner/multi_logical_planner.c +++ b/src/backend/distributed/planner/multi_logical_planner.c @@ -715,8 +715,8 @@ MultiNodeTree(Query *queryTree) /* - * ContainsReadIntermediateResultFunction determines whether an expresion tree contains - * a call to the read_intermediate_result function. + * ContainsReadIntermediateResultFunction determines whether an expression tree + * contains a call to the read_intermediate_result function. */ bool ContainsReadIntermediateResultFunction(Node *node) @@ -726,7 +726,7 @@ ContainsReadIntermediateResultFunction(Node *node) /* - * ContainsReadIntermediateResultArrayFunction determines whether an expresion + * ContainsReadIntermediateResultArrayFunction determines whether an expression * tree contains a call to the read_intermediate_results(result_ids, format) * function. */ diff --git a/src/backend/distributed/planner/multi_router_planner.c b/src/backend/distributed/planner/multi_router_planner.c index 620d506a0..44f955a32 100644 --- a/src/backend/distributed/planner/multi_router_planner.c +++ b/src/backend/distributed/planner/multi_router_planner.c @@ -434,7 +434,7 @@ ExtractSelectRangeTableEntry(Query *query) * for the given modification query. * * The function errors out if the input query is not a - * modify query (e.g., INSERT, UPDATE or DELETE). So, this + * modify query (e.g., INSERT, UPDATE, DELETE or MERGE). So, this * function is not expected to be called on SELECT queries. */ Oid @@ -2271,13 +2271,13 @@ SelectsFromDistributedTable(List *rangeTableList, Query *query) /* - * RouterQuery runs router pruning logic for SELECT, UPDATE, DELETE, and MERGE queries. - * If there are shards present and query is routable, all RTEs have been updated - * to point to the relevant shards in the originalQuery. Also, placementList is - * filled with the list of worker nodes that has all the required shard placements - * for the query execution. anchorShardId is set to the first pruned shardId of - * the given query. Finally, relationShardList is filled with the list of - * relation-to-shard mappings for the query. + * PlanRouterQuery runs router pruning logic for SELECT, UPDATE, DELETE, and + * MERGE queries. If there are shards present and query is routable, all RTEs + * have been updated to point to the relevant shards in the originalQuery. Also, + * placementList is filled with the list of worker nodes that has all the + * required shard placements for the query execution. anchorShardId is set to + * the first pruned shardId of the given query. Finally, relationShardList is + * filled with the list of relation-to-shard mappings for the query. * * If the given query is not routable, it fills planningError with the related * DeferredErrorMessage. The caller can check this error message to see if query @@ -2510,7 +2510,7 @@ AllShardsColocated(List *relationShardList) if (currentTableType == RANGE_DISTRIBUTED || currentTableType == APPEND_DISTRIBUTED) { - /* we do not have further strict colocation chceks */ + /* we do not have further strict colocation checks */ continue; } } @@ -2932,7 +2932,7 @@ TargetShardIntervalsForRestrictInfo(RelationRestrictionContext *restrictionConte } /* - * Different resrictions might have different partition columns. + * Different restrictions might have different partition columns. * We report partition column value if there is only one. */ if (multiplePartitionValuesExist) diff --git a/src/include/distributed/distributed_planner.h b/src/include/distributed/distributed_planner.h index d7234e4bc..23540f6f6 100644 --- a/src/include/distributed/distributed_planner.h +++ b/src/include/distributed/distributed_planner.h @@ -104,7 +104,7 @@ typedef struct FastPathRestrictionContext * Set to true when distKey = Param; in the queryTree */ bool distributionKeyHasParam; -}FastPathRestrictionContext; +} FastPathRestrictionContext; typedef struct PlannerRestrictionContext { diff --git a/src/include/distributed/multi_physical_planner.h b/src/include/distributed/multi_physical_planner.h index 60c5c9783..475a41b37 100644 --- a/src/include/distributed/multi_physical_planner.h +++ b/src/include/distributed/multi_physical_planner.h @@ -238,8 +238,8 @@ typedef struct Task TaskQuery taskQuery; /* - * A task can have multiple queries, in which case queryCount will be > 1. If - * a task has more one query, then taskQuery->queryType == TASK_QUERY_TEXT_LIST. + * A task can have multiple queries, in which case queryCount will be > 1, and + * taskQuery->queryType == TASK_QUERY_TEXT_LIST. */ int queryCount; @@ -290,7 +290,7 @@ typedef struct Task /* * When we evaluate functions and parameters in the query string then - * we should no longer send the list of parameters long with the + * we should no longer send the list of parameters along with the * query. */ bool parametersInQueryStringResolved; From 6cf6cf37fd2e6552e15afc499d9097b76e5f2a58 Mon Sep 17 00:00:00 2001 From: Valery <70659420+ValeryStupenkov@users.noreply.github.com> Date: Wed, 17 Jan 2024 18:04:42 +0300 Subject: [PATCH 3/9] Adds information to explain output when using citus.explain_distributed_queries=false (#7412) Fixes https://github.com/citusdata/citus/issues/6490 --- .../distributed/planner/multi_explain.c | 4 +-- .../expected/multi_join_order_additional.out | 36 +++++++++---------- .../multi_join_order_tpch_repartition.out | 18 +++++----- .../expected/multi_join_order_tpch_small.out | 14 ++++---- .../regress/expected/multi_join_pruning.out | 14 ++++---- .../expected/multi_task_assignment_policy.out | 32 ++++++++--------- 6 files changed, 58 insertions(+), 60 deletions(-) diff --git a/src/backend/distributed/planner/multi_explain.c b/src/backend/distributed/planner/multi_explain.c index 1d6a88934..4584e7740 100644 --- a/src/backend/distributed/planner/multi_explain.c +++ b/src/backend/distributed/planner/multi_explain.c @@ -197,9 +197,7 @@ CitusExplainScan(CustomScanState *node, List *ancestors, struct ExplainState *es if (!ExplainDistributedQueries) { - appendStringInfoSpaces(es->str, es->indent * 2); - appendStringInfo(es->str, "explain statements for distributed queries "); - appendStringInfo(es->str, "are not enabled\n"); + ExplainPropertyBool("citus.explain_distributed_queries", false, es); return; } diff --git a/src/test/regress/expected/multi_join_order_additional.out b/src/test/regress/expected/multi_join_order_additional.out index 405962dbc..6fde7da13 100644 --- a/src/test/regress/expected/multi_join_order_additional.out +++ b/src/test/regress/expected/multi_join_order_additional.out @@ -77,10 +77,10 @@ DEBUG: Router planner cannot handle multi-shard select queries LOG: join order: [ "lineitem" ][ local partition join "lineitem" ] DEBUG: join prunable for intervals [-2147483648,-1] and [0,2147483647] DEBUG: join prunable for intervals [0,2147483647] and [-2147483648,-1] - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (2 rows) SET client_min_messages TO LOG; @@ -92,11 +92,11 @@ SELECT count(*) FROM lineitem, orders WHERE (l_orderkey = o_orderkey AND l_quantity > 5) OR (l_orderkey = o_orderkey AND l_quantity < 10); LOG: join order: [ "lineitem" ][ local partition join "orders" ] - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Aggregate -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (3 rows) EXPLAIN (COSTS OFF) @@ -107,11 +107,11 @@ EXPLAIN (COSTS OFF) SELECT count(*) FROM orders, lineitem_hash WHERE o_orderkey = l_orderkey; LOG: join order: [ "orders" ][ dual partition join "lineitem_hash" ] - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Aggregate -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (3 rows) -- Verify we handle local joins between two hash-partitioned tables. @@ -119,11 +119,11 @@ EXPLAIN (COSTS OFF) SELECT count(*) FROM orders_hash, lineitem_hash WHERE o_orderkey = l_orderkey; LOG: join order: [ "orders_hash" ][ local partition join "lineitem_hash" ] - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Aggregate -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (3 rows) -- Validate that we can handle broadcast joins with hash-partitioned tables. @@ -131,11 +131,11 @@ EXPLAIN (COSTS OFF) SELECT count(*) FROM customer_hash, nation WHERE c_nationkey = n_nationkey; LOG: join order: [ "customer_hash" ][ reference join "nation" ] - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Aggregate -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (3 rows) -- Validate that we don't use a single-partition join method for a hash @@ -144,11 +144,11 @@ EXPLAIN (COSTS OFF) SELECT count(*) FROM orders, lineitem, customer_append WHERE o_custkey = l_partkey AND o_custkey = c_nationkey; LOG: join order: [ "orders" ][ dual partition join "lineitem" ][ dual partition join "customer_append" ] - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Aggregate -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (3 rows) -- Validate that we don't chose a single-partition join method with a @@ -157,11 +157,11 @@ EXPLAIN (COSTS OFF) SELECT count(*) FROM orders, customer_hash WHERE c_custkey = o_custkey; LOG: join order: [ "orders" ][ dual partition join "customer_hash" ] - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Aggregate -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (3 rows) -- Validate that we can re-partition a hash partitioned table to join with a @@ -170,11 +170,11 @@ EXPLAIN (COSTS OFF) SELECT count(*) FROM orders_hash, customer_append WHERE c_custkey = o_custkey; LOG: join order: [ "orders_hash" ][ dual partition join "customer_append" ] - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Aggregate -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (3 rows) -- Validate a 4 way join that could be done locally is planned as such by the logical @@ -195,11 +195,11 @@ JOIN ( WHERE event_type = 5 ) AS some_users ON (some_users.user_id = bar.user_id); LOG: join order: [ "users_table" ][ local partition join "events_table" ][ local partition join "users_table" ][ local partition join "events_table" ] - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Aggregate -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (3 rows) -- Reset client logging level to its previous value diff --git a/src/test/regress/expected/multi_join_order_tpch_repartition.out b/src/test/regress/expected/multi_join_order_tpch_repartition.out index e26a4bfec..736bfa2b4 100644 --- a/src/test/regress/expected/multi_join_order_tpch_repartition.out +++ b/src/test/regress/expected/multi_join_order_tpch_repartition.out @@ -22,11 +22,11 @@ WHERE and l_discount between 0.06 - 0.01 and 0.06 + 0.01 and l_quantity < 24; LOG: join order: [ "lineitem" ] - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Aggregate -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (3 rows) -- Query #3 from the TPC-H decision support benchmark @@ -61,7 +61,7 @@ LOG: join order: [ "orders" ][ local partition join "lineitem" ][ dual partitio -> HashAggregate Group Key: remote_scan.l_orderkey, remote_scan.o_orderdate, remote_scan.o_shippriority -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (6 rows) -- Query #10 from the TPC-H decision support benchmark @@ -98,12 +98,12 @@ GROUP BY ORDER BY revenue DESC; LOG: join order: [ "orders" ][ local partition join "lineitem" ][ dual partition join "customer_append" ][ reference join "nation" ] - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Sort Sort Key: remote_scan.revenue DESC -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (4 rows) -- Query #19 from the TPC-H decision support benchmark (modified) @@ -138,11 +138,11 @@ WHERE AND l_shipinstruct = 'DELIVER IN PERSON' ); LOG: join order: [ "lineitem" ][ dual partition join "part_append" ] - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Aggregate -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (3 rows) -- Query to test multiple re-partition jobs in a single query @@ -158,12 +158,12 @@ WHERE GROUP BY l_partkey; LOG: join order: [ "lineitem" ][ local partition join "orders" ][ dual partition join "part_append" ][ dual partition join "customer_append" ] - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- HashAggregate Group Key: remote_scan.l_partkey -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (4 rows) -- Reset client logging level to its previous value 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 b0b32bb1d..a2e86ce23 100644 --- a/src/test/regress/expected/multi_join_order_tpch_small.out +++ b/src/test/regress/expected/multi_join_order_tpch_small.out @@ -17,11 +17,11 @@ WHERE and l_discount between 0.06 - 0.01 and 0.06 + 0.01 and l_quantity < 24; LOG: join order: [ "lineitem" ] - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Aggregate -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (3 rows) -- Query #3 from the TPC-H decision support benchmark @@ -49,12 +49,12 @@ ORDER BY revenue DESC, o_orderdate; LOG: join order: [ "orders" ][ reference join "customer" ][ local partition join "lineitem" ] - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Sort Sort Key: remote_scan.revenue DESC, remote_scan.o_orderdate -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (4 rows) -- Query #10 from the TPC-H decision support benchmark @@ -98,7 +98,7 @@ LOG: join order: [ "orders" ][ reference join "customer" ][ reference join "nat -> HashAggregate 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 Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (6 rows) -- Query #19 from the TPC-H decision support benchmark (modified) @@ -133,11 +133,11 @@ WHERE AND l_shipinstruct = 'DELIVER IN PERSON' ); LOG: join order: [ "lineitem" ][ reference join "part" ] - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Aggregate -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (3 rows) -- Reset client logging level to its previous value diff --git a/src/test/regress/expected/multi_join_pruning.out b/src/test/regress/expected/multi_join_pruning.out index 27fdc3980..59c12de0a 100644 --- a/src/test/regress/expected/multi_join_pruning.out +++ b/src/test/regress/expected/multi_join_pruning.out @@ -104,11 +104,11 @@ SELECT count(*) DEBUG: Router planner cannot handle multi-shard select queries DEBUG: join prunable for intervals [{},{AZZXSP27F21T6,AZZXSP27F21T6}] and [{BA1000U2AMO4ZGX,BZZXSP27F21T6},{CA1000U2AMO4ZGX,CZZXSP27F21T6}] DEBUG: join prunable for intervals [{BA1000U2AMO4ZGX,BZZXSP27F21T6},{CA1000U2AMO4ZGX,CZZXSP27F21T6}] and [{},{AZZXSP27F21T6,AZZXSP27F21T6}] - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Aggregate -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (3 rows) EXPLAIN (COSTS OFF) @@ -118,11 +118,11 @@ SELECT count(*) DEBUG: Router planner cannot handle multi-shard select queries DEBUG: join prunable for intervals [(a,3,b),(b,4,c)] and [(c,5,d),(d,6,e)] DEBUG: join prunable for intervals [(c,5,d),(d,6,e)] and [(a,3,b),(b,4,c)] - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Aggregate -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (3 rows) -- Test that large table joins on partition varchar columns work @@ -133,14 +133,14 @@ SELECT count(*) DEBUG: Router planner cannot handle multi-shard select queries DEBUG: join prunable for intervals [AA1000U2AMO4ZGX,AZZXSP27F21T6] and [BA1000U2AMO4ZGX,BZZXSP27F21T6] DEBUG: join prunable for intervals [BA1000U2AMO4ZGX,BZZXSP27F21T6] and [AA1000U2AMO4ZGX,AZZXSP27F21T6] - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Aggregate -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (3 rows) -SET client_min_messages TO WARNING; +SET client_min_messages TO WARNING; DROP TABLE varchar_partitioned_table; DROP TABLE array_partitioned_table; DROP TABLE composite_partitioned_table; diff --git a/src/test/regress/expected/multi_task_assignment_policy.out b/src/test/regress/expected/multi_task_assignment_policy.out index 7a58103fa..0ac51027c 100644 --- a/src/test/regress/expected/multi_task_assignment_policy.out +++ b/src/test/regress/expected/multi_task_assignment_policy.out @@ -75,11 +75,11 @@ DEBUG: shard count after pruning for task_assignment_test_table: 3 DEBUG: assigned task to node localhost:xxxxx DEBUG: assigned task to node localhost:xxxxx DEBUG: assigned task to node localhost:xxxxx - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Aggregate -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (3 rows) EXPLAIN (COSTS OFF) SELECT count(*) FROM task_assignment_test_table; @@ -89,11 +89,11 @@ DEBUG: shard count after pruning for task_assignment_test_table: 3 DEBUG: assigned task to node localhost:xxxxx DEBUG: assigned task to node localhost:xxxxx DEBUG: assigned task to node localhost:xxxxx - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Aggregate -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (3 rows) -- Next test the first-replica task assignment policy @@ -105,11 +105,11 @@ DEBUG: shard count after pruning for task_assignment_test_table: 3 DEBUG: assigned task to node localhost:xxxxx DEBUG: assigned task to node localhost:xxxxx DEBUG: assigned task to node localhost:xxxxx - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Aggregate -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (3 rows) EXPLAIN (COSTS OFF) SELECT count(*) FROM task_assignment_test_table; @@ -119,11 +119,11 @@ DEBUG: shard count after pruning for task_assignment_test_table: 3 DEBUG: assigned task to node localhost:xxxxx DEBUG: assigned task to node localhost:xxxxx DEBUG: assigned task to node localhost:xxxxx - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Aggregate -> Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (3 rows) COMMIT; @@ -142,38 +142,38 @@ SET LOCAL citus.task_assignment_policy TO 'greedy'; EXPLAIN (COSTS FALSE) SELECT * FROM task_assignment_reference_table; DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (2 rows) EXPLAIN (COSTS FALSE) SELECT * FROM task_assignment_reference_table; DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (2 rows) SET LOCAL citus.task_assignment_policy TO 'first-replica'; EXPLAIN (COSTS FALSE) SELECT * FROM task_assignment_reference_table; DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (2 rows) EXPLAIN (COSTS FALSE) SELECT * FROM task_assignment_reference_table; DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan - QUERY PLAN + QUERY PLAN --------------------------------------------------------------------- Custom Scan (Citus Adaptive) - explain statements for distributed queries are not enabled + citus.explain_distributed_queries: false (2 rows) ROLLBACK; From fcfedff8d1e1d44dcc529e0c9afafd448ad88cd5 Mon Sep 17 00:00:00 2001 From: Jelte Fennema-Nio Date: Wed, 17 Jan 2024 16:36:26 +0100 Subject: [PATCH 4/9] Support running isolation_update_node in flaky test detection (#7425) I noticed in #7423 that `isolation_update_node` could not be run using flaky test detection. This fixes that. --- src/test/regress/citus_tests/run_test.py | 3 +++ src/test/regress/expected/isolation_update_node.out | 12 ++++++------ src/test/regress/spec/isolation_update_node.spec | 2 ++ 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/test/regress/citus_tests/run_test.py b/src/test/regress/citus_tests/run_test.py index b30d3edfa..d84462221 100755 --- a/src/test/regress/citus_tests/run_test.py +++ b/src/test/regress/citus_tests/run_test.py @@ -153,6 +153,9 @@ DEPS = { "isolation_extension_commands": TestDeps( None, ["isolation_setup", "isolation_add_remove_node"] ), + "isolation_update_node": TestDeps( + None, ["isolation_setup", "isolation_add_remove_node"] + ), "schema_based_sharding": TestDeps("minimal_schedule"), "multi_sequence_default": TestDeps( None, ["multi_test_helpers", "multi_cluster_management", "multi_table_ddl"] diff --git a/src/test/regress/expected/isolation_update_node.out b/src/test/regress/expected/isolation_update_node.out index 4b0a5f680..53d792e61 100644 --- a/src/test/regress/expected/isolation_update_node.out +++ b/src/test/regress/expected/isolation_update_node.out @@ -93,8 +93,8 @@ nodeid|nodename|nodeport starting permutation: s1-begin s1-update-node-1 s2-begin s2-update-node-1 s1-commit s2-abort s1-show-nodes s3-update-node-1-back s3-manually-fix-metadata nodeid|nodename |nodeport --------------------------------------------------------------------- - 25|localhost| 57638 - 24|localhost| 57637 + 23|localhost| 57638 + 22|localhost| 57637 (2 rows) step s1-begin: @@ -139,8 +139,8 @@ step s1-show-nodes: nodeid|nodename |nodeport|isactive --------------------------------------------------------------------- - 25|localhost| 57638|t - 24|localhost| 58637|t + 23|localhost| 57638|t + 22|localhost| 58637|t (2 rows) step s3-update-node-1-back: @@ -178,8 +178,8 @@ nodeid|nodename|nodeport starting permutation: s2-create-table s1-begin s1-update-node-nonexistent s1-prepare-transaction s2-cache-prepared-statement s1-commit-prepared s2-execute-prepared s1-update-node-existent s3-manually-fix-metadata nodeid|nodename |nodeport --------------------------------------------------------------------- - 27|localhost| 57638 - 26|localhost| 57637 + 23|localhost| 57638 + 22|localhost| 57637 (2 rows) step s2-create-table: diff --git a/src/test/regress/spec/isolation_update_node.spec b/src/test/regress/spec/isolation_update_node.spec index d6be6bfdc..ccbbbec1b 100644 --- a/src/test/regress/spec/isolation_update_node.spec +++ b/src/test/regress/spec/isolation_update_node.spec @@ -3,6 +3,8 @@ setup -- revert back to pg_isolation_test_session_is_blocked until the tests are fixed SELECT citus_internal.restore_isolation_tester_func(); + ALTER SEQUENCE pg_dist_node_nodeid_seq RESTART 22; + SELECT 1 FROM master_add_node('localhost', 57637); SELECT 1 FROM master_add_node('localhost', 57638); From 5ec056a172dd2db61c5d76ae57fb4b4b965cbe3f Mon Sep 17 00:00:00 2001 From: Jelte Fennema-Nio Date: Thu, 18 Jan 2024 13:05:24 +0100 Subject: [PATCH 5/9] Add pytest test example about connecting to a worker (#7386) I noticed while reviewing #7203 that there as no example of executing sql on a worker for the pytest README. Since this is a pretty common thing that people want to do, this PR adds that. --- src/test/regress/citus_tests/test/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/regress/citus_tests/test/README.md b/src/test/regress/citus_tests/test/README.md index 6aac98e49..73435ecf6 100644 --- a/src/test/regress/citus_tests/test/README.md +++ b/src/test/regress/citus_tests/test/README.md @@ -82,6 +82,7 @@ the name of the fixture. For example: ```python def test_some_query(cluster): cluster.coordinator.sql("SELECT 1") + assert cluster.workers[0].sql_value('SELECT 2') == 2 ``` If you need a cluster of a specific size you can use the `cluster_factory` From 188614512f8f1bf7424bc50cc98a837e9c2124ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCrkan=20=C4=B0ndibay?= Date: Thu, 18 Jan 2024 20:58:44 +0300 Subject: [PATCH 6/9] Adds comment on database and role propagation (#7388) DESCRIPTION: Adds comment on database and role propagation. Example commands are as below comment on database is '' comment on database is NULL comment on role is '' comment on role is NULL --------- Co-authored-by: Jelte Fennema-Nio --- src/backend/distributed/commands/comment.c | 131 ++++++++++++++++++ src/backend/distributed/commands/database.c | 30 +++- .../distributed/commands/dependencies.c | 10 +- .../commands/distribute_object_ops.c | 46 +++++- src/backend/distributed/commands/role.c | 12 ++ .../distributed/commands/text_search.c | 39 ------ .../deparser/deparse_comment_stmts.c | 77 ++++++++++ .../deparser/deparse_text_search.c | 62 --------- src/include/distributed/commands.h | 6 +- src/include/distributed/comment.h | 26 ++++ src/include/distributed/deparser.h | 3 + .../regress/expected/comment_on_database.out | 101 ++++++++++++++ src/test/regress/expected/comment_on_role.out | 99 +++++++++++++ src/test/regress/multi_1_schedule | 2 + src/test/regress/sql/comment_on_database.sql | 73 ++++++++++ src/test/regress/sql/comment_on_role.sql | 72 ++++++++++ 16 files changed, 669 insertions(+), 120 deletions(-) create mode 100644 src/backend/distributed/commands/comment.c create mode 100644 src/backend/distributed/deparser/deparse_comment_stmts.c create mode 100644 src/include/distributed/comment.h create mode 100644 src/test/regress/expected/comment_on_database.out create mode 100644 src/test/regress/expected/comment_on_role.out create mode 100644 src/test/regress/sql/comment_on_database.sql create mode 100644 src/test/regress/sql/comment_on_role.sql diff --git a/src/backend/distributed/commands/comment.c b/src/backend/distributed/commands/comment.c new file mode 100644 index 000000000..e18a5c5cc --- /dev/null +++ b/src/backend/distributed/commands/comment.c @@ -0,0 +1,131 @@ +/*------------------------------------------------------------------------- + * + * comment.c + * Commands to interact with the comments for all database + * object types. + * + * Copyright (c) Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/genam.h" +#include "access/htup_details.h" +#include "access/table.h" +#include "catalog/pg_shdescription.h" +#include "nodes/parsenodes.h" +#include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/rel.h" + +#include "distributed/comment.h" + +static char * GetCommentForObject(Oid classOid, Oid objectOid); + + +List * +GetCommentPropagationCommands(Oid classOid, Oid objOoid, char *objectName, ObjectType + objectType) +{ + List *commands = NIL; + + StringInfo commentStmt = makeStringInfo(); + + /* Get the comment for the database */ + char *comment = GetCommentForObject(classOid, objOoid); + char const *commentObjectType = ObjectTypeNames[objectType]; + + /* Create the SQL command to propagate the comment to other nodes */ + if (comment != NULL) + { + appendStringInfo(commentStmt, "COMMENT ON %s %s IS %s;", commentObjectType, + quote_identifier(objectName), + quote_literal_cstr(comment)); + } + + + /* Add the command to the list */ + if (commentStmt->len > 0) + { + commands = list_make1(commentStmt->data); + } + + return commands; +} + + +static char * +GetCommentForObject(Oid classOid, Oid objectOid) +{ + HeapTuple tuple; + char *comment = NULL; + + /* Open pg_shdescription catalog */ + Relation shdescRelation = table_open(SharedDescriptionRelationId, AccessShareLock); + + /* Scan the table */ + ScanKeyData scanKey[2]; + + ScanKeyInit(&scanKey[0], + Anum_pg_shdescription_objoid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(objectOid)); + ScanKeyInit(&scanKey[1], + Anum_pg_shdescription_classoid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(classOid)); + bool indexOk = true; + int scanKeyCount = 2; + SysScanDesc scan = systable_beginscan(shdescRelation, SharedDescriptionObjIndexId, + indexOk, NULL, scanKeyCount, + scanKey); + if ((tuple = systable_getnext(scan)) != NULL) + { + bool isNull = false; + + TupleDesc tupdesc = RelationGetDescr(shdescRelation); + + Datum descDatum = heap_getattr(tuple, Anum_pg_shdescription_description, tupdesc, + &isNull); + + + /* Add the command to the list */ + if (!isNull) + { + comment = TextDatumGetCString(descDatum); + } + else + { + comment = NULL; + } + } + + /* End the scan and close the catalog */ + systable_endscan(scan); + table_close(shdescRelation, AccessShareLock); + + return comment; +} + + +/* + * CommentObjectAddress resolves the ObjectAddress for the object + * on which the comment is placed. Optionally errors if the object does not + * exist based on the missing_ok flag passed in by the caller. + */ +List * +CommentObjectAddress(Node *node, bool missing_ok, bool isPostprocess) +{ + CommentStmt *stmt = castNode(CommentStmt, node); + Relation relation; + + ObjectAddress objectAddress = get_object_address(stmt->objtype, stmt->object, + &relation, AccessExclusiveLock, + missing_ok); + + ObjectAddress *objectAddressCopy = palloc0(sizeof(ObjectAddress)); + *objectAddressCopy = objectAddress; + return list_make1(objectAddressCopy); +} diff --git a/src/backend/distributed/commands/database.c b/src/backend/distributed/commands/database.c index 049af3a64..0eb87ec19 100644 --- a/src/backend/distributed/commands/database.c +++ b/src/backend/distributed/commands/database.c @@ -13,8 +13,10 @@ #include "miscadmin.h" +#include "access/genam.h" #include "access/heapam.h" #include "access/htup_details.h" +#include "access/table.h" #include "access/xact.h" #include "catalog/objectaddress.h" #include "catalog/pg_collation.h" @@ -25,6 +27,7 @@ #include "commands/defrem.h" #include "nodes/parsenodes.h" #include "utils/builtins.h" +#include "utils/fmgroids.h" #include "utils/lsyscache.h" #include "utils/rel.h" #include "utils/relcache.h" @@ -33,6 +36,7 @@ #include "distributed/adaptive_executor.h" #include "distributed/commands.h" #include "distributed/commands/utility_hook.h" +#include "distributed/comment.h" #include "distributed/deparse_shard_query.h" #include "distributed/deparser.h" #include "distributed/listutils.h" @@ -45,7 +49,6 @@ #include "distributed/worker_protocol.h" #include "distributed/worker_transaction.h" - /* * DatabaseCollationInfo is used to store collation related information of a database. */ @@ -672,6 +675,31 @@ GetTablespaceName(Oid tablespaceOid) } +/* + * GetDatabaseMetadataSyncCommands returns a list of sql statements + * for the given database id. The list contains the database ddl command, + * grant commands and comment propagation commands. + */ +List * +GetDatabaseMetadataSyncCommands(Oid dbOid) +{ + char *databaseName = get_database_name(dbOid); + char *databaseDDLCommand = CreateDatabaseDDLCommand(dbOid); + + List *ddlCommands = list_make1(databaseDDLCommand); + + List *grantDDLCommands = GrantOnDatabaseDDLCommands(dbOid); + List *commentDDLCommands = GetCommentPropagationCommands(DatabaseRelationId, dbOid, + databaseName, + OBJECT_DATABASE); + + ddlCommands = list_concat(ddlCommands, grantDDLCommands); + ddlCommands = list_concat(ddlCommands, commentDDLCommands); + + return ddlCommands; +} + + /* * GetDatabaseCollation gets oid of a database and returns all the collation related information * We need this method since collation related info in Form_pg_database is not accessible. diff --git a/src/backend/distributed/commands/dependencies.c b/src/backend/distributed/commands/dependencies.c index 3b3b3cfd6..c7de5d874 100644 --- a/src/backend/distributed/commands/dependencies.c +++ b/src/backend/distributed/commands/dependencies.c @@ -584,15 +584,7 @@ GetDependencyCreateDDLCommands(const ObjectAddress *dependency) */ if (dependency->objectId != MyDatabaseId && EnableCreateDatabasePropagation) { - char *databaseDDLCommand = CreateDatabaseDDLCommand(dependency->objectId); - - List *ddlCommands = list_make1(databaseDDLCommand); - - List *grantDDLCommands = GrantOnDatabaseDDLCommands(dependency->objectId); - - ddlCommands = list_concat(ddlCommands, grantDDLCommands); - - return ddlCommands; + return GetDatabaseMetadataSyncCommands(dependency->objectId); } return NIL; diff --git a/src/backend/distributed/commands/distribute_object_ops.c b/src/backend/distributed/commands/distribute_object_ops.c index fe1f422b6..5a62dd2c8 100644 --- a/src/backend/distributed/commands/distribute_object_ops.c +++ b/src/backend/distributed/commands/distribute_object_ops.c @@ -16,6 +16,7 @@ #include "distributed/commands.h" #include "distributed/commands/utility_hook.h" +#include "distributed/comment.h" #include "distributed/deparser.h" #include "distributed/version_compat.h" @@ -304,6 +305,17 @@ static DistributeObjectOps Any_DropRole = { .address = NULL, .markDistributed = false, }; + +static DistributeObjectOps Role_Comment = { + .deparse = DeparseCommentStmt, + .qualify = NULL, + .preprocess = PreprocessAlterDistributedObjectStmt, + .postprocess = NULL, + .objectType = OBJECT_DATABASE, + .operationType = DIST_OPS_ALTER, + .address = CommentObjectAddress, + .markDistributed = false, +}; static DistributeObjectOps Any_CreateForeignServer = { .deparse = DeparseCreateForeignServerStmt, .qualify = NULL, @@ -533,6 +545,17 @@ static DistributeObjectOps Database_Set = { .markDistributed = false, }; +static DistributeObjectOps Database_Comment = { + .deparse = DeparseCommentStmt, + .qualify = NULL, + .preprocess = PreprocessAlterDistributedObjectStmt, + .postprocess = NULL, + .objectType = OBJECT_DATABASE, + .operationType = DIST_OPS_ALTER, + .address = CommentObjectAddress, + .markDistributed = false, +}; + static DistributeObjectOps Database_Rename = { .deparse = DeparseAlterDatabaseRenameStmt, .qualify = NULL, @@ -972,13 +995,18 @@ static DistributeObjectOps TextSearchConfig_AlterOwner = { .markDistributed = false, }; static DistributeObjectOps TextSearchConfig_Comment = { - .deparse = DeparseTextSearchConfigurationCommentStmt, + .deparse = DeparseCommentStmt, + + /* TODO: When adding new comment types we should create an abstracted + * qualify function, just like we have an abstract deparse + * and adress function + */ .qualify = QualifyTextSearchConfigurationCommentStmt, .preprocess = PreprocessAlterDistributedObjectStmt, .postprocess = NULL, .objectType = OBJECT_TSCONFIGURATION, .operationType = DIST_OPS_ALTER, - .address = TextSearchConfigurationCommentObjectAddress, + .address = CommentObjectAddress, .markDistributed = false, }; static DistributeObjectOps TextSearchConfig_Define = { @@ -1041,13 +1069,13 @@ static DistributeObjectOps TextSearchDict_AlterOwner = { .markDistributed = false, }; static DistributeObjectOps TextSearchDict_Comment = { - .deparse = DeparseTextSearchDictionaryCommentStmt, + .deparse = DeparseCommentStmt, .qualify = QualifyTextSearchDictionaryCommentStmt, .preprocess = PreprocessAlterDistributedObjectStmt, .postprocess = NULL, .objectType = OBJECT_TSDICTIONARY, .operationType = DIST_OPS_ALTER, - .address = TextSearchDictCommentObjectAddress, + .address = CommentObjectAddress, .markDistributed = false, }; static DistributeObjectOps TextSearchDict_Define = { @@ -1780,6 +1808,16 @@ GetDistributeObjectOps(Node *node) return &TextSearchDict_Comment; } + case OBJECT_DATABASE: + { + return &Database_Comment; + } + + case OBJECT_ROLE: + { + return &Role_Comment; + } + default: { return &NoDistributeOps; diff --git a/src/backend/distributed/commands/role.c b/src/backend/distributed/commands/role.c index e6cd1d112..d0b33ccb9 100644 --- a/src/backend/distributed/commands/role.c +++ b/src/backend/distributed/commands/role.c @@ -45,6 +45,7 @@ #include "distributed/citus_safe_lib.h" #include "distributed/commands.h" #include "distributed/commands/utility_hook.h" +#include "distributed/comment.h" #include "distributed/coordinator_protocol.h" #include "distributed/deparser.h" #include "distributed/listutils.h" @@ -582,6 +583,17 @@ GenerateCreateOrAlterRoleCommand(Oid roleOid) { completeRoleList = lappend(completeRoleList, DeparseTreeNode(stmt)); } + + /* + * append COMMENT ON ROLE commands for this specific user + * When we propagate user creation, we also want to make sure that we propagate + * all the comments it has been given. For this, we check pg_shdescription + * for the ROLE entry corresponding to roleOid, and generate the relevant + * Comment stmts to be run in the new node. + */ + List *commentStmts = GetCommentPropagationCommands(AuthIdRelationId, roleOid, + rolename, OBJECT_ROLE); + completeRoleList = list_concat(completeRoleList, commentStmts); } return completeRoleList; diff --git a/src/backend/distributed/commands/text_search.c b/src/backend/distributed/commands/text_search.c index 4a386e321..cce246a73 100644 --- a/src/backend/distributed/commands/text_search.c +++ b/src/backend/distributed/commands/text_search.c @@ -790,45 +790,6 @@ AlterTextSearchDictionarySchemaStmtObjectAddress(Node *node, bool missing_ok, bo } -/* - * TextSearchConfigurationCommentObjectAddress resolves the ObjectAddress for the TEXT - * SEARCH CONFIGURATION on which the comment is placed. Optionally errors if the - * configuration does not exist based on the missing_ok flag passed in by the caller. - */ -List * -TextSearchConfigurationCommentObjectAddress(Node *node, bool missing_ok, bool - isPostprocess) -{ - CommentStmt *stmt = castNode(CommentStmt, node); - Assert(stmt->objtype == OBJECT_TSCONFIGURATION); - - Oid objid = get_ts_config_oid(castNode(List, stmt->object), missing_ok); - - ObjectAddress *address = palloc0(sizeof(ObjectAddress)); - ObjectAddressSet(*address, TSConfigRelationId, objid); - return list_make1(address); -} - - -/* - * TextSearchDictCommentObjectAddress resolves the ObjectAddress for the TEXT SEARCH - * DICTIONARY on which the comment is placed. Optionally errors if the dictionary does not - * exist based on the missing_ok flag passed in by the caller. - */ -List * -TextSearchDictCommentObjectAddress(Node *node, bool missing_ok, bool isPostprocess) -{ - CommentStmt *stmt = castNode(CommentStmt, node); - Assert(stmt->objtype == OBJECT_TSDICTIONARY); - - Oid objid = get_ts_dict_oid(castNode(List, stmt->object), missing_ok); - - ObjectAddress *address = palloc0(sizeof(ObjectAddress)); - ObjectAddressSet(*address, TSDictionaryRelationId, objid); - return list_make1(address); -} - - /* * AlterTextSearchConfigurationOwnerObjectAddress resolves the ObjectAddress for the TEXT * SEARCH CONFIGURATION for which the owner is changed. Optionally errors if the diff --git a/src/backend/distributed/deparser/deparse_comment_stmts.c b/src/backend/distributed/deparser/deparse_comment_stmts.c new file mode 100644 index 000000000..36a63c97b --- /dev/null +++ b/src/backend/distributed/deparser/deparse_comment_stmts.c @@ -0,0 +1,77 @@ +/*------------------------------------------------------------------------- + * + * deparse_coment_stmts.c + * + * All routines to deparse comment statements. + * + * Copyright (c), Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "catalog/namespace.h" +#include "commands/defrem.h" +#include "lib/stringinfo.h" +#include "nodes/parsenodes.h" +#include "parser/parse_type.h" +#include "utils/builtins.h" +#include "utils/elog.h" + +#include "pg_version_compat.h" + +#include "distributed/citus_ruleutils.h" +#include "distributed/commands.h" +#include "distributed/comment.h" +#include "distributed/deparser.h" +#include "distributed/listutils.h" +#include "distributed/log_utils.h" + + +const char *ObjectTypeNames[] = +{ + [OBJECT_DATABASE] = "DATABASE", + [OBJECT_ROLE] = "ROLE", + [OBJECT_TSCONFIGURATION] = "TEXT SEARCH CONFIGURATION", + [OBJECT_TSDICTIONARY] = "TEXT SEARCH DICTIONARY", + + /* When support for propagating comments to new objects is introduced, an entry for each + * statement type should be added to this list. The first element in each entry is the 'object_type' keyword + * that will be included in the 'COMMENT ON ..' statement (i.e. DATABASE,). The second element is the type of + * stmt->object, which represents the name of the propagated object. + */ +}; + +char * +DeparseCommentStmt(Node *node) +{ + CommentStmt *stmt = castNode(CommentStmt, node); + StringInfoData str = { 0 }; + initStringInfo(&str); + + const char *objectName = NULL; + if (IsA(stmt->object, String)) + { + objectName = quote_identifier(strVal(stmt->object)); + } + else if (IsA(stmt->object, List)) + { + objectName = NameListToQuotedString(castNode(List, stmt->object)); + } + else + { + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("unknown object type"))); + } + + const char *objectType = ObjectTypeNames[stmt->objtype]; + + char *comment = stmt->comment != NULL ? quote_literal_cstr(stmt->comment) : "NULL"; + + + appendStringInfo(&str, "COMMENT ON %s %s IS %s;", objectType, objectName, comment); + + return str.data; +} diff --git a/src/backend/distributed/deparser/deparse_text_search.c b/src/backend/distributed/deparser/deparse_text_search.c index e0c750d0d..ab5498ad8 100644 --- a/src/backend/distributed/deparser/deparse_text_search.c +++ b/src/backend/distributed/deparser/deparse_text_search.c @@ -395,68 +395,6 @@ DeparseAlterTextSearchDictionarySchemaStmt(Node *node) } -/* - * DeparseTextSearchConfigurationCommentStmt returns the sql statement representing - * COMMENT ON TEXT SEARCH CONFIGURATION ... IS ... - */ -char * -DeparseTextSearchConfigurationCommentStmt(Node *node) -{ - CommentStmt *stmt = castNode(CommentStmt, node); - Assert(stmt->objtype == OBJECT_TSCONFIGURATION); - - StringInfoData buf = { 0 }; - initStringInfo(&buf); - - appendStringInfo(&buf, "COMMENT ON TEXT SEARCH CONFIGURATION %s IS ", - NameListToQuotedString(castNode(List, stmt->object))); - - if (stmt->comment == NULL) - { - appendStringInfoString(&buf, "NULL"); - } - else - { - appendStringInfoString(&buf, quote_literal_cstr(stmt->comment)); - } - - appendStringInfoString(&buf, ";"); - - return buf.data; -} - - -/* - * DeparseTextSearchDictionaryCommentStmt returns the sql statement representing - * COMMENT ON TEXT SEARCH DICTIONARY ... IS ... - */ -char * -DeparseTextSearchDictionaryCommentStmt(Node *node) -{ - CommentStmt *stmt = castNode(CommentStmt, node); - Assert(stmt->objtype == OBJECT_TSDICTIONARY); - - StringInfoData buf = { 0 }; - initStringInfo(&buf); - - appendStringInfo(&buf, "COMMENT ON TEXT SEARCH DICTIONARY %s IS ", - NameListToQuotedString(castNode(List, stmt->object))); - - if (stmt->comment == NULL) - { - appendStringInfoString(&buf, "NULL"); - } - else - { - appendStringInfoString(&buf, quote_literal_cstr(stmt->comment)); - } - - appendStringInfoString(&buf, ";"); - - return buf.data; -} - - /* * AppendStringInfoTokentypeList specializes in adding a comma separated list of * token_tyoe's to TEXT SEARCH CONFIGURATION commands diff --git a/src/include/distributed/commands.h b/src/include/distributed/commands.h index 4eb6df8bf..de15553e7 100644 --- a/src/include/distributed/commands.h +++ b/src/include/distributed/commands.h @@ -230,6 +230,7 @@ extern List * PreprocessAlterDatabaseStmt(Node *node, const char *queryString, extern List * PreprocessAlterDatabaseRefreshCollStmt(Node *node, const char *queryString, ProcessUtilityContext processUtilityContext); +extern List * GetDatabaseMetadataSyncCommands(Oid dbOid); extern List * PreprocessAlterDatabaseSetStmt(Node *node, const char *queryString, @@ -693,11 +694,6 @@ extern List * AlterTextSearchConfigurationSchemaStmtObjectAddress(Node *node, extern List * AlterTextSearchDictionarySchemaStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess); -extern List * TextSearchConfigurationCommentObjectAddress(Node *node, - bool missing_ok, bool - isPostprocess); -extern List * TextSearchDictCommentObjectAddress(Node *node, - bool missing_ok, bool isPostprocess); extern List * AlterTextSearchConfigurationOwnerObjectAddress(Node *node, bool missing_ok, bool isPostprocess); diff --git a/src/include/distributed/comment.h b/src/include/distributed/comment.h new file mode 100644 index 000000000..bef216ae4 --- /dev/null +++ b/src/include/distributed/comment.h @@ -0,0 +1,26 @@ +/*------------------------------------------------------------------------- + * + * comment.h + * Declarations for comment related operations. + * + * Copyright (c) Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#ifndef COMMENT_H +#define COMMENT_H + +#include "postgres.h" + +#include "nodes/parsenodes.h" + + +extern const char *ObjectTypeNames[]; + + +extern List * GetCommentPropagationCommands(Oid classOid, Oid oid, char *objectName, + ObjectType objectType); +extern List * CommentObjectAddress(Node *node, bool missing_ok, bool isPostprocess); + +# endif /* COMMENT_H */ diff --git a/src/include/distributed/deparser.h b/src/include/distributed/deparser.h index 22636b401..437a9fd8e 100644 --- a/src/include/distributed/deparser.h +++ b/src/include/distributed/deparser.h @@ -143,6 +143,9 @@ extern void DefElemOptionToStatement(StringInfo buf, DefElem *option, const DefElemOptionFormat *opt_formats, int opt_formats_len); +/* forward declarations for deparse_comment_stmts.c */ +extern char * DeparseCommentStmt(Node *node); + /* forward declarations for deparse_statistics_stmts.c */ extern char * DeparseCreateStatisticsStmt(Node *node); diff --git a/src/test/regress/expected/comment_on_database.out b/src/test/regress/expected/comment_on_database.out new file mode 100644 index 000000000..a56fe8e03 --- /dev/null +++ b/src/test/regress/expected/comment_on_database.out @@ -0,0 +1,101 @@ +set citus.log_remote_commands to on; +set citus.enable_create_database_propagation to on; +set citus.grep_remote_commands to 'COMMENT ON DATABASE'; +create database "test1-\!escape"; +comment on DATABASE "test1-\!escape" is 'test-comment'; +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT ds.description AS database_comment + FROM pg_database d + LEFT JOIN pg_shdescription ds ON d.oid = ds.objoid + WHERE d.datname = 'test1-\!escape'; + $$ +); + result +--------------------------------------------------------------------- + test-comment + test-comment + test-comment +(3 rows) + +comment on DATABASE "test1-\!escape" is 'comment-needs\!escape'; +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT ds.description AS database_comment + FROM pg_database d + LEFT JOIN pg_shdescription ds ON d.oid = ds.objoid + WHERE d.datname = 'test1-\!escape'; + $$ +); + result +--------------------------------------------------------------------- + comment-needs\!escape + comment-needs\!escape + comment-needs\!escape +(3 rows) + +comment on DATABASE "test1-\!escape" is null; +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT ds.description AS database_comment + FROM pg_database d + LEFT JOIN pg_shdescription ds ON d.oid = ds.objoid + WHERE d.datname = 'test1-\!escape'; + $$ +); + result +--------------------------------------------------------------------- + + + +(3 rows) + +drop DATABASE "test1-\!escape"; +--test metadata sync +select 1 from citus_remove_node('localhost', :worker_2_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +create database "test1-\!escape"; +comment on DATABASE "test1-\!escape" is 'test-comment'; +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT ds.description AS database_comment + FROM pg_database d + LEFT JOIN pg_shdescription ds ON d.oid = ds.objoid + WHERE d.datname = 'test1-\!escape'; + $$ +); + result +--------------------------------------------------------------------- + test-comment + test-comment +(2 rows) + +select 1 from citus_add_node('localhost', :worker_2_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT ds.description AS database_comment + FROM pg_database d + LEFT JOIN pg_shdescription ds ON d.oid = ds.objoid + WHERE d.datname = 'test1-\!escape'; + $$ +); + result +--------------------------------------------------------------------- + test-comment + test-comment + test-comment +(3 rows) + +drop DATABASE "test1-\!escape"; +reset citus.enable_create_database_propagation; +reset citus.grep_remote_commands; +reset citus.log_remote_commands; diff --git a/src/test/regress/expected/comment_on_role.out b/src/test/regress/expected/comment_on_role.out new file mode 100644 index 000000000..2981195f1 --- /dev/null +++ b/src/test/regress/expected/comment_on_role.out @@ -0,0 +1,99 @@ +set citus.log_remote_commands to on; +set citus.grep_remote_commands to 'COMMENT ON ROLE'; +create role "role1-\!escape"; +comment on ROLE "role1-\!escape" is 'test-comment'; +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT ds.description AS role_comment + FROM pg_roles r + LEFT JOIN pg_shdescription ds ON r.oid = ds.objoid + WHERE r.rolname = 'role1-\!escape'; + $$ +); + result +--------------------------------------------------------------------- + test-comment + test-comment + test-comment +(3 rows) + +comment on role "role1-\!escape" is 'comment-needs\!escape'; +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT ds.description AS role_comment + FROM pg_roles r + LEFT JOIN pg_shdescription ds ON r.oid = ds.objoid + WHERE r.rolname = 'role1-\!escape'; + $$ +); + result +--------------------------------------------------------------------- + comment-needs\!escape + comment-needs\!escape + comment-needs\!escape +(3 rows) + +comment on role "role1-\!escape" is NULL; +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT ds.description AS role_comment + FROM pg_roles r + LEFT JOIN pg_shdescription ds ON r.oid = ds.objoid + WHERE r.rolname = 'role1-\!escape'; + $$ +); + result +--------------------------------------------------------------------- + + + +(3 rows) + +drop role "role1-\!escape"; +--test metadata sync +select 1 from citus_remove_node('localhost', :worker_2_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +create role "role1-\!escape"; +comment on ROLE "role1-\!escape" is 'test-comment'; +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT ds.description AS role_comment + FROM pg_roles r + LEFT JOIN pg_shdescription ds ON r.oid = ds.objoid + WHERE r.rolname = 'role1-\!escape'; + $$ +); + result +--------------------------------------------------------------------- + test-comment + test-comment +(2 rows) + +select 1 from citus_add_node('localhost', :worker_2_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT ds.description AS role_comment + FROM pg_roles r + LEFT JOIN pg_shdescription ds ON r.oid = ds.objoid + WHERE r.rolname = 'role1-\!escape'; + $$ +); + result +--------------------------------------------------------------------- + test-comment + test-comment + test-comment +(3 rows) + +drop role "role1-\!escape"; +reset citus.grep_remote_commands; +reset citus.log_remote_commands; diff --git a/src/test/regress/multi_1_schedule b/src/test/regress/multi_1_schedule index 2b9fdeb2d..cfff00942 100644 --- a/src/test/regress/multi_1_schedule +++ b/src/test/regress/multi_1_schedule @@ -38,6 +38,8 @@ test: create_single_shard_table test: create_drop_database_propagation test: create_drop_database_propagation_pg15 test: create_drop_database_propagation_pg16 +test: comment_on_database +test: comment_on_role # don't parallelize single_shard_table_udfs to make sure colocation ids are sequential test: single_shard_table_udfs test: schema_based_sharding diff --git a/src/test/regress/sql/comment_on_database.sql b/src/test/regress/sql/comment_on_database.sql new file mode 100644 index 000000000..2c5ced81f --- /dev/null +++ b/src/test/regress/sql/comment_on_database.sql @@ -0,0 +1,73 @@ +set citus.log_remote_commands to on; + +set citus.enable_create_database_propagation to on; +set citus.grep_remote_commands to 'COMMENT ON DATABASE'; + +create database "test1-\!escape"; + +comment on DATABASE "test1-\!escape" is 'test-comment'; + +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT ds.description AS database_comment + FROM pg_database d + LEFT JOIN pg_shdescription ds ON d.oid = ds.objoid + WHERE d.datname = 'test1-\!escape'; + $$ +); + +comment on DATABASE "test1-\!escape" is 'comment-needs\!escape'; + +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT ds.description AS database_comment + FROM pg_database d + LEFT JOIN pg_shdescription ds ON d.oid = ds.objoid + WHERE d.datname = 'test1-\!escape'; + $$ +); + +comment on DATABASE "test1-\!escape" is null; + +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT ds.description AS database_comment + FROM pg_database d + LEFT JOIN pg_shdescription ds ON d.oid = ds.objoid + WHERE d.datname = 'test1-\!escape'; + $$ +); + +drop DATABASE "test1-\!escape"; + +--test metadata sync +select 1 from citus_remove_node('localhost', :worker_2_port); +create database "test1-\!escape"; +comment on DATABASE "test1-\!escape" is 'test-comment'; + +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT ds.description AS database_comment + FROM pg_database d + LEFT JOIN pg_shdescription ds ON d.oid = ds.objoid + WHERE d.datname = 'test1-\!escape'; + $$ +); + +select 1 from citus_add_node('localhost', :worker_2_port); + +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT ds.description AS database_comment + FROM pg_database d + LEFT JOIN pg_shdescription ds ON d.oid = ds.objoid + WHERE d.datname = 'test1-\!escape'; + $$ +); + +drop DATABASE "test1-\!escape"; + + +reset citus.enable_create_database_propagation; +reset citus.grep_remote_commands; +reset citus.log_remote_commands; diff --git a/src/test/regress/sql/comment_on_role.sql b/src/test/regress/sql/comment_on_role.sql new file mode 100644 index 000000000..d65d57cca --- /dev/null +++ b/src/test/regress/sql/comment_on_role.sql @@ -0,0 +1,72 @@ +set citus.log_remote_commands to on; + +set citus.grep_remote_commands to 'COMMENT ON ROLE'; + +create role "role1-\!escape"; + +comment on ROLE "role1-\!escape" is 'test-comment'; + +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT ds.description AS role_comment + FROM pg_roles r + LEFT JOIN pg_shdescription ds ON r.oid = ds.objoid + WHERE r.rolname = 'role1-\!escape'; + $$ +); + +comment on role "role1-\!escape" is 'comment-needs\!escape'; + +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT ds.description AS role_comment + FROM pg_roles r + LEFT JOIN pg_shdescription ds ON r.oid = ds.objoid + WHERE r.rolname = 'role1-\!escape'; + $$ +); + +comment on role "role1-\!escape" is NULL; + +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT ds.description AS role_comment + FROM pg_roles r + LEFT JOIN pg_shdescription ds ON r.oid = ds.objoid + WHERE r.rolname = 'role1-\!escape'; + $$ +); + +drop role "role1-\!escape"; + + +--test metadata sync + +select 1 from citus_remove_node('localhost', :worker_2_port); +create role "role1-\!escape"; +comment on ROLE "role1-\!escape" is 'test-comment'; + +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT ds.description AS role_comment + FROM pg_roles r + LEFT JOIN pg_shdescription ds ON r.oid = ds.objoid + WHERE r.rolname = 'role1-\!escape'; + $$ +); + +select 1 from citus_add_node('localhost', :worker_2_port); + +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT ds.description AS role_comment + FROM pg_roles r + LEFT JOIN pg_shdescription ds ON r.oid = ds.objoid + WHERE r.rolname = 'role1-\!escape'; + $$ +); + +drop role "role1-\!escape"; + +reset citus.grep_remote_commands; +reset citus.log_remote_commands; From 14ecebe47cdd21d40edff0fcde09eab37d22cbf3 Mon Sep 17 00:00:00 2001 From: Jelte Fennema-Nio Date: Fri, 19 Jan 2024 17:11:29 +0100 Subject: [PATCH 7/9] Fix problems with make check (#7433) This fixes two problems: 1. Allow `make check -j20` to work, by disabling parallelism. This was reported by a user in #7432 2. Actually run all the tests by forwarding to `make check` instead of `check-full`, because confusingly `check-full` does not run all the tests. --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e42d0ffd3..77d8cad3e 100644 --- a/Makefile +++ b/Makefile @@ -61,6 +61,7 @@ check-style: # depend on install-all so that downgrade scripts are installed as well check: all install-all - $(MAKE) -C src/test/regress check-full + # explicetely does not use $(MAKE) to avoid parallelism + make -C src/test/regress check .PHONY: all check clean install install-downgrades install-all From 4b295cc857bda0a90ce0c3bed6a26bd4a7e448c9 Mon Sep 17 00:00:00 2001 From: zhjwpku Date: Mon, 22 Jan 2024 21:55:14 +0800 Subject: [PATCH 8/9] Simplify CitusNewNode (#7434) postgres refactored newNode() in PG 17, the main point for doing this is the original tricks is no longer neccessary for modern compilers[1]. This does the same for Citus. This should have no backward compatibility issues since it just replaces palloc0fast with palloc0. This is good for forward compatibility since palloc0fast no longer exists in PG 17. [1] https://www.postgresql.org/message-id/b51f1fa7-7e6a-4ecc-936d-90a8a1659e7c@iki.fi --- src/include/distributed/citus_nodes.h | 39 ++++++++------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/src/include/distributed/citus_nodes.h b/src/include/distributed/citus_nodes.h index 888133a89..16df367aa 100644 --- a/src/include/distributed/citus_nodes.h +++ b/src/include/distributed/citus_nodes.h @@ -92,38 +92,21 @@ CitusNodeTagI(Node *node) return ((CitusNode*)(node))->citus_tag; } -/* - * Postgres's nodes/nodes.h has more information on why we do this. - */ -#ifdef __GNUC__ /* Citus variant of newNode(), don't use directly. */ -#define CitusNewNode(size, tag) \ -({ CitusNode *_result; \ - AssertMacro((size) >= sizeof(CitusNode)); /* need the tag, at least */ \ - _result = (CitusNode *) palloc0fast(size); \ - _result->extensible.type = T_ExtensibleNode; \ - _result->extensible.extnodename = CitusNodeTagNames[tag - CITUS_NODE_TAG_START]; \ - _result->citus_tag =(int) (tag); \ - _result; \ -}) +static inline CitusNode * +CitusNewNode(size_t size, CitusNodeTag tag) +{ + CitusNode *result; -#else - -extern CitusNode *newCitusNodeMacroHolder; - -#define CitusNewNode(size, tag) \ -( \ - AssertMacro((size) >= sizeof(CitusNode)), /* need the tag, at least */ \ - newCitusNodeMacroHolder = (CitusNode *) palloc0fast(size), \ - newCitusNodeMacroHolder->extensible.type = T_ExtensibleNode, \ - newCitusNodeMacroHolder->extensible.extnodename = CitusNodeTagNames[tag - CITUS_NODE_TAG_START], \ - newCitusNodeMacroHolder->citus_tag =(int) (tag), \ - newCitusNodeMacroHolder \ -) - -#endif + Assert(size >= sizeof(CitusNode)); /* need the ExtensibleNode and the tag, at least */ + result = (CitusNode *) palloc0(size); + result->extensible.type = T_ExtensibleNode; + result->extensible.extnodename = CitusNodeTagNames[tag - CITUS_NODE_TAG_START]; + result->citus_tag = (int) (tag); + return result; +} /* * IsA equivalent that compares node tags, including Citus-specific nodes. From ee11492a0ed080b4c669460ae523cb437ab2faeb Mon Sep 17 00:00:00 2001 From: eaydingol <60466783+eaydingol@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:32:49 +0300 Subject: [PATCH 9/9] Generate qualified relation name (#7427) This change refactors the code by using generate_qualified_relation_name from id instead of using a sequence of functions to generate the relation name. Fixes #6602 --- .../distributed/commands/alter_table.c | 75 +++++++------------ .../citus_add_local_table_to_metadata.c | 8 +- .../commands/create_distributed_table.c | 5 +- src/backend/distributed/commands/multi_copy.c | 8 +- src/backend/distributed/commands/view.c | 4 +- .../executor/insert_select_executor.c | 7 +- .../distributed/operations/shard_transfer.c | 6 +- .../distributed/worker/worker_drop_protocol.c | 6 +- 8 files changed, 36 insertions(+), 83 deletions(-) diff --git a/src/backend/distributed/commands/alter_table.c b/src/backend/distributed/commands/alter_table.c index a81f23ad6..030dbbe78 100644 --- a/src/backend/distributed/commands/alter_table.c +++ b/src/backend/distributed/commands/alter_table.c @@ -209,12 +209,9 @@ static void ReplaceTable(Oid sourceId, Oid targetId, List *justBeforeDropCommand static bool HasAnyGeneratedStoredColumns(Oid relationId); static List * GetNonGeneratedStoredColumnNameList(Oid relationId); static void CheckAlterDistributedTableConversionParameters(TableConversionState *con); -static char * CreateWorkerChangeSequenceDependencyCommand(char *sequenceSchemaName, - char *sequenceName, - char *sourceSchemaName, - char *sourceName, - char *targetSchemaName, - char *targetName); +static char * CreateWorkerChangeSequenceDependencyCommand(char *qualifiedSequeceName, + char *qualifiedSourceName, + char *qualifiedTargetName); static void ErrorIfMatViewSizeExceedsTheLimit(Oid matViewOid); static char * CreateMaterializedViewDDLCommand(Oid matViewOid); static char * GetAccessMethodForMatViewIfExists(Oid viewOid); @@ -791,13 +788,15 @@ ConvertTableInternal(TableConversionState *con) justBeforeDropCommands = lappend(justBeforeDropCommands, detachFromParentCommand); } + char *qualifiedRelationName = quote_qualified_identifier(con->schemaName, + con->relationName); + if (PartitionedTable(con->relationId)) { if (!con->suppressNoticeMessages) { ereport(NOTICE, (errmsg("converting the partitions of %s", - quote_qualified_identifier(con->schemaName, - con->relationName)))); + qualifiedRelationName))); } List *partitionList = PartitionList(con->relationId); @@ -870,9 +869,7 @@ ConvertTableInternal(TableConversionState *con) if (!con->suppressNoticeMessages) { - ereport(NOTICE, (errmsg("creating a new table for %s", - quote_qualified_identifier(con->schemaName, - con->relationName)))); + ereport(NOTICE, (errmsg("creating a new table for %s", qualifiedRelationName))); } TableDDLCommand *tableCreationCommand = NULL; @@ -999,8 +996,6 @@ ConvertTableInternal(TableConversionState *con) { continue; } - char *qualifiedRelationName = quote_qualified_identifier(con->schemaName, - con->relationName); TableConversionParameters cascadeParam = { .relationId = colocatedTableId, @@ -1750,9 +1745,7 @@ CreateMaterializedViewDDLCommand(Oid matViewOid) { StringInfo query = makeStringInfo(); - char *viewName = get_rel_name(matViewOid); - char *schemaName = get_namespace_name(get_rel_namespace(matViewOid)); - char *qualifiedViewName = quote_qualified_identifier(schemaName, viewName); + char *qualifiedViewName = generate_qualified_relation_name(matViewOid); /* here we need to get the access method of the view to recreate it */ char *accessMethodName = GetAccessMethodForMatViewIfExists(matViewOid); @@ -1801,9 +1794,8 @@ ReplaceTable(Oid sourceId, Oid targetId, List *justBeforeDropCommands, bool suppressNoticeMessages) { char *sourceName = get_rel_name(sourceId); - char *targetName = get_rel_name(targetId); - Oid schemaId = get_rel_namespace(sourceId); - char *schemaName = get_namespace_name(schemaId); + char *qualifiedSourceName = generate_qualified_relation_name(sourceId); + char *qualifiedTargetName = generate_qualified_relation_name(targetId); StringInfo query = makeStringInfo(); @@ -1811,8 +1803,7 @@ ReplaceTable(Oid sourceId, Oid targetId, List *justBeforeDropCommands, { if (!suppressNoticeMessages) { - ereport(NOTICE, (errmsg("moving the data of %s", - quote_qualified_identifier(schemaName, sourceName)))); + ereport(NOTICE, (errmsg("moving the data of %s", qualifiedSourceName))); } if (!HasAnyGeneratedStoredColumns(sourceId)) @@ -1822,8 +1813,7 @@ ReplaceTable(Oid sourceId, Oid targetId, List *justBeforeDropCommands, * "INSERT INTO .. SELECT *"". */ appendStringInfo(query, "INSERT INTO %s SELECT * FROM %s", - quote_qualified_identifier(schemaName, targetName), - quote_qualified_identifier(schemaName, sourceName)); + qualifiedTargetName, qualifiedSourceName); } else { @@ -1838,9 +1828,8 @@ ReplaceTable(Oid sourceId, Oid targetId, List *justBeforeDropCommands, char *insertColumnString = StringJoin(nonStoredColumnNameList, ','); appendStringInfo(query, "INSERT INTO %s (%s) OVERRIDING SYSTEM VALUE SELECT %s FROM %s", - quote_qualified_identifier(schemaName, targetName), - insertColumnString, insertColumnString, - quote_qualified_identifier(schemaName, sourceName)); + qualifiedTargetName, insertColumnString, + insertColumnString, qualifiedSourceName); } ExecuteQueryViaSPI(query->data, SPI_OK_INSERT); @@ -1864,14 +1853,11 @@ ReplaceTable(Oid sourceId, Oid targetId, List *justBeforeDropCommands, */ if (ShouldSyncTableMetadata(targetId)) { - Oid sequenceSchemaOid = get_rel_namespace(sequenceOid); - char *sequenceSchemaName = get_namespace_name(sequenceSchemaOid); - char *sequenceName = get_rel_name(sequenceOid); + char *qualifiedSequenceName = generate_qualified_relation_name(sequenceOid); char *workerChangeSequenceDependencyCommand = - CreateWorkerChangeSequenceDependencyCommand(sequenceSchemaName, - sequenceName, - schemaName, sourceName, - schemaName, targetName); + CreateWorkerChangeSequenceDependencyCommand(qualifiedSequenceName, + qualifiedSourceName, + qualifiedTargetName); SendCommandToWorkersWithMetadata(workerChangeSequenceDependencyCommand); } else if (ShouldSyncTableMetadata(sourceId)) @@ -1894,25 +1880,23 @@ ReplaceTable(Oid sourceId, Oid targetId, List *justBeforeDropCommands, if (!suppressNoticeMessages) { - ereport(NOTICE, (errmsg("dropping the old %s", - quote_qualified_identifier(schemaName, sourceName)))); + ereport(NOTICE, (errmsg("dropping the old %s", qualifiedSourceName))); } resetStringInfo(query); appendStringInfo(query, "DROP %sTABLE %s CASCADE", IsForeignTable(sourceId) ? "FOREIGN " : "", - quote_qualified_identifier(schemaName, sourceName)); + qualifiedSourceName); ExecuteQueryViaSPI(query->data, SPI_OK_UTILITY); if (!suppressNoticeMessages) { - ereport(NOTICE, (errmsg("renaming the new table to %s", - quote_qualified_identifier(schemaName, sourceName)))); + ereport(NOTICE, (errmsg("renaming the new table to %s", qualifiedSourceName))); } resetStringInfo(query); appendStringInfo(query, "ALTER TABLE %s RENAME TO %s", - quote_qualified_identifier(schemaName, targetName), + qualifiedTargetName, quote_identifier(sourceName)); ExecuteQueryViaSPI(query->data, SPI_OK_UTILITY); } @@ -2172,18 +2156,13 @@ CheckAlterDistributedTableConversionParameters(TableConversionState *con) * worker_change_sequence_dependency query with the parameters. */ static char * -CreateWorkerChangeSequenceDependencyCommand(char *sequenceSchemaName, char *sequenceName, - char *sourceSchemaName, char *sourceName, - char *targetSchemaName, char *targetName) +CreateWorkerChangeSequenceDependencyCommand(char *qualifiedSequeceName, + char *qualifiedSourceName, + char *qualifiedTargetName) { - char *qualifiedSchemaName = quote_qualified_identifier(sequenceSchemaName, - sequenceName); - char *qualifiedSourceName = quote_qualified_identifier(sourceSchemaName, sourceName); - char *qualifiedTargetName = quote_qualified_identifier(targetSchemaName, targetName); - StringInfo query = makeStringInfo(); appendStringInfo(query, "SELECT worker_change_sequence_dependency(%s, %s, %s)", - quote_literal_cstr(qualifiedSchemaName), + quote_literal_cstr(qualifiedSequeceName), quote_literal_cstr(qualifiedSourceName), quote_literal_cstr(qualifiedTargetName)); diff --git a/src/backend/distributed/commands/citus_add_local_table_to_metadata.c b/src/backend/distributed/commands/citus_add_local_table_to_metadata.c index d95cdd353..93f1e7d28 100644 --- a/src/backend/distributed/commands/citus_add_local_table_to_metadata.c +++ b/src/backend/distributed/commands/citus_add_local_table_to_metadata.c @@ -1160,9 +1160,7 @@ DropIdentitiesOnTable(Oid relationId) if (attributeForm->attidentity) { - char *tableName = get_rel_name(relationId); - char *schemaName = get_namespace_name(get_rel_namespace(relationId)); - char *qualifiedTableName = quote_qualified_identifier(schemaName, tableName); + char *qualifiedTableName = generate_qualified_relation_name(relationId); StringInfo dropCommand = makeStringInfo(); @@ -1222,9 +1220,7 @@ DropViewsOnTable(Oid relationId) Oid viewId = InvalidOid; foreach_oid(viewId, reverseOrderedViews) { - char *viewName = get_rel_name(viewId); - char *schemaName = get_namespace_name(get_rel_namespace(viewId)); - char *qualifiedViewName = quote_qualified_identifier(schemaName, viewName); + char *qualifiedViewName = generate_qualified_relation_name(viewId); StringInfo dropCommand = makeStringInfo(); appendStringInfo(dropCommand, "DROP %sVIEW IF EXISTS %s", diff --git a/src/backend/distributed/commands/create_distributed_table.c b/src/backend/distributed/commands/create_distributed_table.c index 9f3975a1e..5ec6d6dd7 100644 --- a/src/backend/distributed/commands/create_distributed_table.c +++ b/src/backend/distributed/commands/create_distributed_table.c @@ -1323,10 +1323,7 @@ CreateCitusTable(Oid relationId, CitusTableType tableType, { List *partitionList = PartitionList(relationId); Oid partitionRelationId = InvalidOid; - Oid namespaceId = get_rel_namespace(relationId); - char *schemaName = get_namespace_name(namespaceId); - char *relationName = get_rel_name(relationId); - char *parentRelationName = quote_qualified_identifier(schemaName, relationName); + char *parentRelationName = generate_qualified_relation_name(relationId); /* * when there are many partitions, each call to CreateDistributedTable diff --git a/src/backend/distributed/commands/multi_copy.c b/src/backend/distributed/commands/multi_copy.c index c69e33f94..0284ea64d 100644 --- a/src/backend/distributed/commands/multi_copy.c +++ b/src/backend/distributed/commands/multi_copy.c @@ -2547,12 +2547,8 @@ ShardIdForTuple(CitusCopyDestReceiver *copyDest, Datum *columnValues, bool *colu if (columnNulls[partitionColumnIndex]) { - Oid relationId = copyDest->distributedRelationId; - char *relationName = get_rel_name(relationId); - Oid schemaOid = get_rel_namespace(relationId); - char *schemaName = get_namespace_name(schemaOid); - char *qualifiedTableName = quote_qualified_identifier(schemaName, - relationName); + char *qualifiedTableName = generate_qualified_relation_name( + copyDest->distributedRelationId); ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("the partition column of table %s cannot be NULL", diff --git a/src/backend/distributed/commands/view.c b/src/backend/distributed/commands/view.c index 0c39be4ca..9689b9267 100644 --- a/src/backend/distributed/commands/view.c +++ b/src/backend/distributed/commands/view.c @@ -392,9 +392,7 @@ CreateViewDDLCommand(Oid viewOid) static void AppendQualifiedViewNameToCreateViewCommand(StringInfo buf, Oid viewOid) { - char *viewName = get_rel_name(viewOid); - char *schemaName = get_namespace_name(get_rel_namespace(viewOid)); - char *qualifiedViewName = quote_qualified_identifier(schemaName, viewName); + char *qualifiedViewName = generate_qualified_relation_name(viewOid); appendStringInfo(buf, "%s ", qualifiedViewName); } diff --git a/src/backend/distributed/executor/insert_select_executor.c b/src/backend/distributed/executor/insert_select_executor.c index f5fbb3f78..a8dc1fa5a 100644 --- a/src/backend/distributed/executor/insert_select_executor.c +++ b/src/backend/distributed/executor/insert_select_executor.c @@ -143,15 +143,10 @@ NonPushableInsertSelectExecScan(CustomScanState *node) targetRelation->partitionColumn); if (distributionColumnIndex == -1) { - char *relationName = get_rel_name(targetRelationId); - Oid schemaOid = get_rel_namespace(targetRelationId); - char *schemaName = get_namespace_name(schemaOid); - ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg( "the partition column of table %s should have a value", - quote_qualified_identifier(schemaName, - relationName)))); + generate_qualified_relation_name(targetRelationId)))); } TargetEntry *selectPartitionTE = list_nth(selectQuery->targetList, diff --git a/src/backend/distributed/operations/shard_transfer.c b/src/backend/distributed/operations/shard_transfer.c index 7d6747caf..805ef39d7 100644 --- a/src/backend/distributed/operations/shard_transfer.c +++ b/src/backend/distributed/operations/shard_transfer.c @@ -1945,11 +1945,7 @@ ConstructQualifiedShardName(ShardInterval *shardInterval) static List * RecreateTableDDLCommandList(Oid relationId) { - const char *relationName = get_rel_name(relationId); - Oid relationSchemaId = get_rel_namespace(relationId); - const char *relationSchemaName = get_namespace_name(relationSchemaId); - const char *qualifiedRelationName = quote_qualified_identifier(relationSchemaName, - relationName); + const char *qualifiedRelationName = generate_qualified_relation_name(relationId); StringInfo dropCommand = makeStringInfo(); diff --git a/src/backend/distributed/worker/worker_drop_protocol.c b/src/backend/distributed/worker/worker_drop_protocol.c index 6d7b5326a..280de4493 100644 --- a/src/backend/distributed/worker/worker_drop_protocol.c +++ b/src/backend/distributed/worker/worker_drop_protocol.c @@ -170,14 +170,10 @@ WorkerDropDistributedTable(Oid relationId) */ if (!IsAnyObjectAddressOwnedByExtension(list_make1(distributedTableObject), NULL)) { - char *relName = get_rel_name(relationId); - Oid schemaId = get_rel_namespace(relationId); - char *schemaName = get_namespace_name(schemaId); - StringInfo dropCommand = makeStringInfo(); appendStringInfo(dropCommand, "DROP%sTABLE %s CASCADE", IsForeignTable(relationId) ? " FOREIGN " : " ", - quote_qualified_identifier(schemaName, relName)); + generate_qualified_relation_name(relationId)); Node *dropCommandNode = ParseTreeNode(dropCommand->data);