-- Boundary checks that intentionally run outside `cargo pgrx test`. -- -- The pgrx test harness executes #[pg_test] bodies inside generated SQL -- functions. Nested ERROR catching and SET ROLE are not equivalent to the real -- client/server boundary there, so SQLSTATE preservation and restricted-role -- ACL checks live in this standalone script instead. -- -- NOTE: Prefer `run_sqlstate_acl_boundary.sh` for routine verification. -- This file keeps the SQL steps together, but client-side SQLSTATE assertions -- are more stable than nested DO/EXCEPTION blocks for pgrx extensions. CREATE EXTENSION IF NOT EXISTS graph; SELECT graph.reset(); SET graph.auto_load = off; DROP TABLE IF EXISTS public.graph_boundary_edges CASCADE; DROP TABLE IF EXISTS public.graph_boundary_nodes CASCADE; CREATE TABLE public.graph_boundary_nodes ( id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL, name TEXT NOT NULL, age INT NOT NULL, friend_id TEXT REFERENCES public.graph_boundary_nodes(id) ); CREATE TABLE public.graph_boundary_edges ( id BIGSERIAL PRIMARY KEY, from_id TEXT NOT NULL REFERENCES public.graph_boundary_nodes(id), to_id TEXT NOT NULL REFERENCES public.graph_boundary_nodes(id) ); INSERT INTO public.graph_boundary_nodes VALUES ('b', 't2', 'Bob', 20, NULL), ('a', 't1', 'Alice', 10, 'b'); INSERT INTO public.graph_boundary_edges (from_id, to_id) VALUES ('a', 'b'); DO $$ BEGIN PERFORM * FROM graph.traverse('public.graph_boundary_nodes'::regclass, 'a', 1); RAISE EXCEPTION 'expected PG003'; EXCEPTION WHEN SQLSTATE 'PG003' THEN NULL; END $$; SELECT graph.add_table('public.graph_boundary_nodes'::regclass, 'id', ARRAY['tenant_id', 'name', 'age']); SELECT graph.add_edge('public.graph_boundary_nodes'::regclass, 'friend_id', 'public.graph_boundary_nodes'::regclass, 'id', 'boundary', bidirectional := false); SELECT graph.add_filter_column('public.graph_boundary_nodes'::regclass, 'age'); SELECT * FROM graph.build(); DO $$ BEGIN PERFORM * FROM graph.traverse('public.graph_boundary_nodes'::regclass, 'missing', 1); RAISE EXCEPTION 'expected PG010'; EXCEPTION WHEN SQLSTATE 'PG010' THEN NULL; END $$; DO $$ BEGIN PERFORM * FROM graph.traverse('public.graph_boundary_nodes'::regclass, 'a', 1, NULL, '🔥 > 1'); RAISE EXCEPTION 'expected PG005'; EXCEPTION WHEN SQLSTATE 'PG005' THEN NULL; END $$; SET graph.enabled = off; DO $$ BEGIN PERFORM * FROM graph.traverse('public.graph_boundary_nodes'::regclass, 'a', 1); RAISE EXCEPTION 'expected 55000'; EXCEPTION WHEN SQLSTATE '55000' THEN NULL; END $$; SET graph.enabled = on; DROP ROLE IF EXISTS graph_boundary_restricted; CREATE ROLE graph_boundary_restricted; GRANT USAGE ON SCHEMA graph TO graph_boundary_restricted; GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA graph TO graph_boundary_restricted; GRANT SELECT ON public.graph_boundary_nodes TO graph_boundary_restricted; ALTER TABLE public.graph_boundary_nodes ENABLE ROW LEVEL SECURITY; CREATE POLICY graph_boundary_tenant_rls ON public.graph_boundary_nodes FOR SELECT TO graph_boundary_restricted USING (tenant_id = current_setting('graph.boundary_tenant', true)); DROP TABLE IF EXISTS public.graph_boundary_traversal_coords; CREATE TABLE public.graph_boundary_traversal_coords AS SELECT node_table, node_id, depth FROM graph.traverse('public.graph_boundary_nodes'::regclass, 'a', 1, hydrate := false); GRANT SELECT ON public.graph_boundary_traversal_coords TO graph_boundary_restricted; SET ROLE graph_boundary_restricted; SET graph.boundary_tenant = 't1'; DO $$ DECLARE topology_rows INTEGER; hydrated_rows INTEGER; BEGIN SELECT count(*) INTO topology_rows FROM public.graph_boundary_traversal_coords; SELECT count(*) INTO hydrated_rows FROM public.graph_boundary_traversal_coords g JOIN public.graph_boundary_nodes n ON n.id = g.node_id; IF topology_rows <> 2 OR hydrated_rows <> 1 THEN RAISE EXCEPTION 'expected topology_rows=2 and hydrated_rows=1, got %, %', topology_rows, hydrated_rows; END IF; END $$; RESET ROLE; SET ROLE graph_boundary_restricted; DO $$ BEGIN INSERT INTO graph._registered_tables (table_name, id_column) VALUES ('public.nope', 'id'); RAISE EXCEPTION 'expected 42501'; EXCEPTION WHEN insufficient_privilege THEN NULL; END $$; DO $$ BEGIN PERFORM graph.add_table('public.graph_boundary_nodes'::regclass, 'id'); RAISE EXCEPTION 'expected PG002'; EXCEPTION WHEN SQLSTATE 'PG002' THEN NULL; END $$; DO $$ BEGIN PERFORM * FROM graph.build(); RAISE EXCEPTION 'expected PG002'; EXCEPTION WHEN SQLSTATE 'PG002' THEN NULL; END $$; DO $$ BEGIN PERFORM * FROM graph.vacuum(); RAISE EXCEPTION 'expected PG002'; EXCEPTION WHEN SQLSTATE 'PG002' THEN NULL; END $$; DO $$ BEGIN PERFORM * FROM graph.maintenance(); RAISE EXCEPTION 'expected PG002'; EXCEPTION WHEN SQLSTATE 'PG002' THEN NULL; END $$; DO $$ BEGIN PERFORM graph.reset(); RAISE EXCEPTION 'expected PG002'; EXCEPTION WHEN SQLSTATE 'PG002' THEN NULL; END $$; DO $$ BEGIN PERFORM graph.enable_sync(); RAISE EXCEPTION 'expected PG002'; EXCEPTION WHEN SQLSTATE 'PG002' THEN NULL; END $$; DO $$ BEGIN PERFORM * FROM graph.apply_sync(); RAISE EXCEPTION 'expected PG002'; EXCEPTION WHEN SQLSTATE 'PG002' THEN NULL; END $$; DO $$ BEGIN PERFORM * FROM graph.connected_components(); RAISE EXCEPTION 'expected PG002'; EXCEPTION WHEN SQLSTATE 'PG002' THEN NULL; END $$; DO $$ BEGIN PERFORM * FROM graph.component_stats(); RAISE EXCEPTION 'expected PG002'; EXCEPTION WHEN SQLSTATE 'PG002' THEN NULL; END $$; RESET ROLE;