diff --git a/src/backend/distributed/metadata/node_metadata.c b/src/backend/distributed/metadata/node_metadata.c index d29fdaae2..d031f4d2c 100644 --- a/src/backend/distributed/metadata/node_metadata.c +++ b/src/backend/distributed/metadata/node_metadata.c @@ -167,6 +167,7 @@ PG_FUNCTION_INFO_V1(citus_nodeport_for_nodeid); PG_FUNCTION_INFO_V1(citus_coordinator_nodeid); PG_FUNCTION_INFO_V1(citus_is_coordinator); PG_FUNCTION_INFO_V1(citus_internal_mark_node_not_synced); +PG_FUNCTION_INFO_V1(citus_is_primary_node); /* * DefaultNodeMetadata creates a NodeMetadata struct with the fields set to @@ -1665,6 +1666,36 @@ citus_is_coordinator(PG_FUNCTION_ARGS) } +/* + * citus_is_primary_node returns whether the current node is a primary for + * a given group_id. We consider the node a primary if it has + * pg_dist_node entries marked as primary + */ +Datum +citus_is_primary_node(PG_FUNCTION_ARGS) +{ + CheckCitusVersion(ERROR); + + int32 groupId = GetLocalGroupId(); + WorkerNode *workerNode = PrimaryNodeForGroup(groupId, NULL); + if (workerNode == NULL) + { + ereport(WARNING, (errmsg("could not find the current node in pg_dist_node"), + errdetail("If this is the coordinator node, consider adding it " + "into the metadata by using citus_set_coordinator_host() " + "UDF. Otherwise, if you're going to use this node as a " + "worker node for a new cluster, make sure to add this " + "node into the metadata from the coordinator by using " + "citus_add_node() UDF."))); + PG_RETURN_NULL(); + } + + bool isPrimary = workerNode->nodeId == GetLocalNodeId(); + + PG_RETURN_BOOL(isPrimary); +} + + /* * EnsureParentSessionHasExclusiveLockOnPgDistNode ensures given session id * holds Exclusive lock on pg_dist_node. diff --git a/src/backend/distributed/sql/citus--13.0-1--13.1-1.sql b/src/backend/distributed/sql/citus--13.0-1--13.1-1.sql index 25ac01057..0f70438e0 100644 --- a/src/backend/distributed/sql/citus--13.0-1--13.1-1.sql +++ b/src/backend/distributed/sql/citus--13.0-1--13.1-1.sql @@ -47,3 +47,4 @@ DROP VIEW IF EXISTS pg_catalog.citus_lock_waits; #include "udfs/citus_internal_update_relation_colocation/13.1-1.sql" #include "udfs/repl_origin_helper/13.1-1.sql" #include "udfs/citus_finish_pg_upgrade/13.1-1.sql" +#include "udfs/citus_is_primary_node/13.1-1.sql" diff --git a/src/backend/distributed/sql/downgrades/citus--13.1-1--13.0-1.sql b/src/backend/distributed/sql/downgrades/citus--13.1-1--13.0-1.sql index 53b480302..dd89fc249 100644 --- a/src/backend/distributed/sql/downgrades/citus--13.1-1--13.0-1.sql +++ b/src/backend/distributed/sql/downgrades/citus--13.1-1--13.0-1.sql @@ -11,6 +11,7 @@ DROP FUNCTION pg_catalog.citus_unmark_object_distributed(oid,oid,int,boolean); ALTER TABLE pg_catalog.pg_dist_transaction DROP COLUMN outer_xid; REVOKE USAGE ON SCHEMA citus_internal FROM PUBLIC; +DROP FUNCTION pg_catalog.citus_is_primary_node(); DROP FUNCTION citus_internal.add_colocation_metadata(int, int, int, regtype, oid); DROP FUNCTION citus_internal.add_object_metadata(text, text[], text[], integer, integer, boolean); DROP FUNCTION citus_internal.add_partition_metadata(regclass, "char", text, integer, "char"); diff --git a/src/backend/distributed/sql/udfs/citus_is_primary_node/13.1-1.sql b/src/backend/distributed/sql/udfs/citus_is_primary_node/13.1-1.sql new file mode 100644 index 000000000..deb1d50be --- /dev/null +++ b/src/backend/distributed/sql/udfs/citus_is_primary_node/13.1-1.sql @@ -0,0 +1,7 @@ +CREATE FUNCTION pg_catalog.citus_is_primary_node() + RETURNS bool + LANGUAGE c + STRICT +AS 'MODULE_PATHNAME', $$citus_is_primary_node$$; +COMMENT ON FUNCTION pg_catalog.citus_is_primary_node() + IS 'returns whether the current node is the primary node in the group'; diff --git a/src/backend/distributed/sql/udfs/citus_is_primary_node/latest.sql b/src/backend/distributed/sql/udfs/citus_is_primary_node/latest.sql new file mode 100644 index 000000000..deb1d50be --- /dev/null +++ b/src/backend/distributed/sql/udfs/citus_is_primary_node/latest.sql @@ -0,0 +1,7 @@ +CREATE FUNCTION pg_catalog.citus_is_primary_node() + RETURNS bool + LANGUAGE c + STRICT +AS 'MODULE_PATHNAME', $$citus_is_primary_node$$; +COMMENT ON FUNCTION pg_catalog.citus_is_primary_node() + IS 'returns whether the current node is the primary node in the group'; diff --git a/src/test/regress/expected/multi_cluster_management.out b/src/test/regress/expected/multi_cluster_management.out index 3eb549ab5..e6634d5c6 100644 --- a/src/test/regress/expected/multi_cluster_management.out +++ b/src/test/regress/expected/multi_cluster_management.out @@ -25,6 +25,15 @@ SELECT citus_is_coordinator(); t (1 row) +-- I am primary node (fails beacuse not set in pg_dist) +select citus_is_primary_node(); +WARNING: could not find the current node in pg_dist_node +DETAIL: If this is the coordinator node, consider adding it into the metadata by using citus_set_coordinator_host() UDF. Otherwise, if you're going to use this node as a worker node for a new cluster, make sure to add this node into the metadata from the coordinator by using citus_add_node() UDF. + citus_is_primary_node +--------------------------------------------------------------------- + +(1 row) + -- make sure coordinator is always in metadata. SELECT citus_set_coordinator_host('localhost'); citus_set_coordinator_host @@ -32,6 +41,13 @@ SELECT citus_set_coordinator_host('localhost'); (1 row) +-- I am primary node +select citus_is_primary_node(); + citus_is_primary_node +--------------------------------------------------------------------- + t +(1 row) + -- workers are not coordinator SELECT result FROM run_command_on_workers('SELECT citus_is_coordinator()'); result @@ -40,6 +56,14 @@ SELECT result FROM run_command_on_workers('SELECT citus_is_coordinator()'); f (2 rows) +-- primary workers are primary node +SELECT result FROM run_command_on_workers('SELECT citus_is_primary_node()'); + result +--------------------------------------------------------------------- + t + t +(2 rows) + -- get the active nodes SELECT master_get_active_worker_nodes(); master_get_active_worker_nodes diff --git a/src/test/regress/expected/multi_extension.out b/src/test/regress/expected/multi_extension.out index a00025e8c..51b2be416 100644 --- a/src/test/regress/expected/multi_extension.out +++ b/src/test/regress/expected/multi_extension.out @@ -1479,8 +1479,9 @@ SELECT * FROM multi_extension.print_extension_changes(); | function citus_internal.update_none_dist_table_metadata(oid,"char",bigint,boolean) void | function citus_internal.update_placement_metadata(bigint,integer,integer) void | function citus_internal.update_relation_colocation(oid,integer) void + | function citus_is_primary_node() boolean | function citus_unmark_object_distributed(oid,oid,integer,boolean) void -(26 rows) +(27 rows) DROP TABLE multi_extension.prev_objects, multi_extension.extension_diff; -- show running version diff --git a/src/test/regress/expected/upgrade_list_citus_objects.out b/src/test/regress/expected/upgrade_list_citus_objects.out index d5968f648..048e86c67 100644 --- a/src/test/regress/expected/upgrade_list_citus_objects.out +++ b/src/test/regress/expected/upgrade_list_citus_objects.out @@ -133,6 +133,7 @@ ORDER BY 1; function citus_internal_update_relation_colocation(oid,integer) function citus_is_clock_after(cluster_clock,cluster_clock) function citus_is_coordinator() + function citus_is_primary_node() function citus_isolation_test_session_is_blocked(integer,integer[]) function citus_job_cancel(bigint) function citus_job_list() @@ -388,6 +389,6 @@ ORDER BY 1; view citus_stat_tenants_local view pg_dist_shard_placement view time_partitions -(357 rows) +(358 rows) DROP TABLE extension_basic_types; diff --git a/src/test/regress/sql/multi_cluster_management.sql b/src/test/regress/sql/multi_cluster_management.sql index 86fbd15b6..a1e0e9b09 100644 --- a/src/test/regress/sql/multi_cluster_management.sql +++ b/src/test/regress/sql/multi_cluster_management.sql @@ -14,12 +14,21 @@ RESET citus.metadata_sync_mode; -- I am coordinator SELECT citus_is_coordinator(); +-- I am primary node (fails beacuse not set in pg_dist) +select citus_is_primary_node(); + -- make sure coordinator is always in metadata. SELECT citus_set_coordinator_host('localhost'); +-- I am primary node +select citus_is_primary_node(); + -- workers are not coordinator SELECT result FROM run_command_on_workers('SELECT citus_is_coordinator()'); +-- primary workers are primary node +SELECT result FROM run_command_on_workers('SELECT citus_is_primary_node()'); + -- get the active nodes SELECT master_get_active_worker_nodes();