Configure une table pour la réplication. Sur l'origine, ceci implique d'ajouter le trigger "logTrigger()" sur la table. Sur un nœud abonné, ceci implique de désactiver les triggers et les règles, et d'ajouter le trigger qui interdit l'accès aux tables répliquées.
declare
p_tab_id alias for $1;
v_no_id int4;
v_tab_row record;
v_tab_fqname text;
v_tab_attkind text;
v_n int4;
v_trec record;
v_tgbad boolean;
begin
-- ----
-- Grab the central configuration lock
-- ----
lock table sl_config_lock;
-- ----
-- Get our local node ID
-- ----
v_no_id := getLocalNodeId('_schemadoc');
-- ----
-- Get the sl_table row and the current origin of the table.
-- Verify that the table currently is NOT in altered state.
-- ----
select T.tab_reloid, T.tab_set, T.tab_idxname, T.tab_altered,
S.set_origin, PGX.indexrelid,
slon_quote_brute(PGN.nspname) || '.' ||
slon_quote_brute(PGC.relname) as tab_fqname
into v_tab_row
from sl_table T, sl_set S,
"pg_catalog".pg_class PGC, "pg_catalog".pg_namespace PGN,
"pg_catalog".pg_index PGX, "pg_catalog".pg_class PGXC
where T.tab_id = p_tab_id
and T.tab_set = S.set_id
and T.tab_reloid = PGC.oid
and PGC.relnamespace = PGN.oid
and PGX.indrelid = T.tab_reloid
and PGX.indexrelid = PGXC.oid
and PGXC.relname = T.tab_idxname
for update;
if not found then
raise exception 'Slony-I: alterTableForReplication(): Table with id % not found', p_tab_id;
end if;
v_tab_fqname = v_tab_row.tab_fqname;
if v_tab_row.tab_altered then
raise exception 'Slony-I: alterTableForReplication(): Table % is already in altered state',
v_tab_fqname;
end if;
v_tab_attkind := determineAttKindUnique(v_tab_row.tab_fqname,
v_tab_row.tab_idxname);
execute 'lock table ' || v_tab_fqname || ' in access exclusive mode';
-- ----
-- Procedures are different on origin and subscriber
-- ----
if v_no_id = v_tab_row.set_origin then
-- ----
-- On the Origin we add the log trigger to the table and done
-- ----
execute 'create trigger "_schemadoc_logtrigger_' ||
p_tab_id || '" after insert or update or delete on ' ||
v_tab_fqname || ' for each row execute procedure
logTrigger (''_schemadoc'', ''' ||
p_tab_id || ''', ''' ||
v_tab_attkind || ''');';
else
-- ----
-- On the subscriber the thing is a bit more difficult. We want
-- to disable all user- and foreign key triggers and rules.
-- ----
-- ----
-- Check to see if there are any trigger conflicts...
-- ----
v_tgbad := 'false';
for v_trec in
select pc.relname, tg1.tgname from
"pg_catalog".pg_trigger tg1,
"pg_catalog".pg_trigger tg2,
"pg_catalog".pg_class pc,
"pg_catalog".pg_index pi,
sl_table tab
where
tg1.tgname = tg2.tgname and -- Trigger names match
tg1.tgrelid = tab.tab_reloid and -- trigger 1 is on the table
pi.indexrelid = tg2.tgrelid and -- trigger 2 is on the index
pi.indrelid = tab.tab_reloid and -- indexes table is this table
pc.oid = tab.tab_reloid
loop
raise notice 'Slony-I: alterTableForReplication(): multiple instances of trigger % on table %',
v_trec.tgname, v_trec.relname;
v_tgbad := 'true';
end loop;
if v_tgbad then
raise exception 'Slony-I: Unable to disable triggers';
end if;
-- ----
-- Disable all existing triggers
-- ----
update "pg_catalog".pg_trigger
set tgrelid = v_tab_row.indexrelid
where tgrelid = v_tab_row.tab_reloid
and not exists (
select true from sl_table TAB,
sl_trigger TRIG
where TAB.tab_reloid = tgrelid
and TAB.tab_id = TRIG.trig_tabid
and TRIG.trig_tgname = tgname
);
get diagnostics v_n = row_count;
if v_n > 0 then
update "pg_catalog".pg_class
set reltriggers = reltriggers - v_n
where oid = v_tab_row.tab_reloid;
end if;
-- ----
-- Disable all existing rules
-- ----
update "pg_catalog".pg_rewrite
set ev_class = v_tab_row.indexrelid
where ev_class = v_tab_row.tab_reloid;
get diagnostics v_n = row_count;
if v_n > 0 then
update "pg_catalog".pg_class
set relhasrules = false
where oid = v_tab_row.tab_reloid;
end if;
-- ----
-- Add the trigger that denies write access to replicated tables
-- ----
execute 'create trigger "_schemadoc_denyaccess_' ||
p_tab_id || '" before insert or update or delete on ' ||
v_tab_fqname || ' for each row execute procedure
denyAccess (''_schemadoc'');';
end if;
-- ----
-- Mark the table altered in our configuration
-- ----
update sl_table
set tab_altered = true where tab_id = p_tab_id;
return p_tab_id;
end;