create or replace function dr_role()
returns text
language plpgsql
volatile
as $$
declare
guc_value text;
guc_norm text;
probe_id bigint;
begin
---------------------------------------------------------------------------
-- 0. Check yb_non_ddl_txn_for_sys_tables_allowed
-- When this GUC is enabled, writes may succeed even on DR replicas,
-- so write-based detection becomes unreliable.
---------------------------------------------------------------------------
begin
guc_value := current_setting('yb_non_ddl_txn_for_sys_tables_allowed', true);
exception
when undefined_object then
guc_value := 'false'; -- GUC not present on this YB version
when others then
guc_value := null;
end;
guc_norm := lower(coalesce(guc_value, 'false'));
if guc_norm not in ('off', 'false', '0', 'no') then
return 'UNKNOWN';
end if;
---------------------------------------------------------------------------
-- 1. Verify probe table exists
---------------------------------------------------------------------------
perform 1
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
where n.nspname = 'dr_meta'
and c.relname = 'dr_role_probe';
if not found then
return 'UNKNOWN';
end if;
---------------------------------------------------------------------------
-- 2. Perform the write probe
-- On PRIMARY :
-- - INSERT works (or triggers unique_violation)
-- - DELETE cleans up so the table stays empty
--
-- On REPLICA :
-- - INSERT raises the xCluster DR error
-- - Return REPLICA and do NOT try to delete
---------------------------------------------------------------------------
probe_id := (random() * 1000000000000)::bigint; -- 0 .. 1e12
begin
insert into dr_meta.dr_role_probe(id) values (probe_id);
-- Primary: clean up
delete from dr_meta.dr_role_probe;
return 'PRIMARY';
exception
when unique_violation then
-- Still primary: clean up
delete from dr_meta.dr_role_probe;
return 'PRIMARY';
when others then
if sqlerrm like '%Data modification is forbidden on database that is the target of a transactional xCluster replication%' then
return 'REPLICA';
else
return 'UNKNOWN';
end if;
end;
end;
$$;