We’re using constants in some constraints here, for example in cases where several servers are replicating to the same federating one: each origin server has his own schema, and all is replicated nicely on the central host, thanks to Londiste, as you might have guessed already.
For bare-metal recovery scripts, I’m working on how to change those
constants in the constraints, so that
pg_dump -s
plus some schema tweaking
would kick-start a server. Here’s a
PLpgSQL
snippet to do just that:
FOR rec IN EXECUTE
$s$
SELECT schemaname, tablename, conname, attnames, def
FROM (
SELECT n.nspname, c.relname, r.conname,
(select array_accum(attname)
from pg_attribute
where attrelid = c.oid and r.conkey @> array[attnum]) as attnames,
pg_catalog.pg_get_constraintdef(r.oid, true)
FROM pg_catalog.pg_constraint r
JOIN pg_class c on c.oid = r.conrelid
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE r.contype = 'c'
ORDER BY 1, 2, 3
) as cons(schemaname, tablename, conname, attnames, def)
WHERE attnames @> array['server']::name[]
$s$
LOOP
rec.def := replace(rec.def, 'server = ' || old_id,
'server = ' || new_id);
sql := 'ALTER TABLE ' || rec.schemaname || '.' || rec.tablename
|| ' DROP CONSTRAINT ' || rec.conname;
RAISE NOTICE '%', sql;
RETURN NEXT;
EXECUTE sql;
sql := 'ALTER TABLE ' || rec.schemaname || '.' || rec.tablename
|| ' ADD ' || rec.def;
RAISE NOTICE '%', sql;
RETURN NEXT;
EXECUTE sql;
END LOOP;
This relies on the fact that our constraints are on the column
server
. Why
would this be any better than a
sed
one-liner, would you ask me? I’m fed up
with having pseudo-parsing scripts and taking the risk that the simple
command will change data I didn’t want to edit. I want context aware tools,
pretty please, to
feel safe.
Otherwise I’d might have gone with
pg_dump -s| sed -e 's:\(server =\) 17:\1 18:'
but this one-liner already contains too much useless magic for my taste (the space before 17 ain’t in the group match to allow for having \1 18 in the right hand side. And this isn’t yet parametrized, and there I’ll need to talk to the database, as that’s were I store the servers name and their id (a bigserial — yes, the constraints are all generated from scripts). I don’t want to write an SQL parser and I don’t want to play loose, so the PLpgSQL approach is what I’m thinking as the best tool here. Opinionated answers get to my mailbox!