diff --git a/README.md b/README.md index 413133a..a37372f 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,12 @@ replicated to other nodes. This is essential for `migrate_to_native()`: its deletes from the lolor tables would otherwise replicate while the native re-creation stayed local, destroying large objects on the other nodes. +Even with spock, migration is refused if a non-spock logical replication slot +(e.g. `pgoutput`, `wal2json`) exists, since repair mode only suppresses spock's +own output plugin and those consumers would still decode the migration DML: +`migrate_to_native()` raises an `ERROR`, while `migrate_from_native()` warns and +returns -1 without doing anything. Drop the offending slots before migrating. + Without spock, the migration DML cannot be excluded from logical decoding, so both functions refuse to migrate while logical replication slots exist in the database: `migrate_from_native()` raises a `WARNING` and returns -1 without diff --git a/docs/index.md b/docs/index.md index dd1627e..0232b6f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -64,6 +64,12 @@ to other nodes. This is essential for `migrate_to_native()`: its deletes from the lolor tables would otherwise replicate while the native re-creation stayed local, destroying large objects on the other nodes. +Even with spock, migration is refused if a non-spock logical replication slot +(e.g. `pgoutput`, `wal2json`) exists, since repair mode only suppresses spock's +own output plugin and those consumers would still decode the migration DML: +`migrate_to_native()` raises an `ERROR`, while `migrate_from_native()` warns and +returns -1 without doing anything. Drop the offending slots before migrating. + Without spock, the migration DML cannot be excluded from logical decoding, so both functions refuse to migrate while logical replication slots exist in the database: `migrate_from_native()` raises a `WARNING` and returns -1 without diff --git a/docs/lolor_release_notes.md b/docs/lolor_release_notes.md index 47691f0..1373901 100644 --- a/docs/lolor_release_notes.md +++ b/docs/lolor_release_notes.md @@ -6,7 +6,7 @@ * `lolor.migrate_from_native()` migrates existing native large objects into lolor storage. This is a manual step (run after `CREATE EXTENSION lolor`) and requires superuser privileges. * `lolor.migrate_to_native()` migrates lolor large objects back to native storage. * Reverse migration runs automatically on `DROP EXTENSION lolor`, so large objects are never lost when the extension is removed. - * When the spock extension is installed, both migration functions run under `spock.repair_mode()`, so the row-shuffling migration DML is not replicated to other nodes. Without spock, the functions refuse to migrate while logical replication slots exist in the database: `migrate_from_native()` warns and returns -1, `migrate_to_native()` (and therefore `DROP EXTENSION lolor`) raises an error. + * With the spock extension installed, both migration functions run under `spock.repair_mode()` so migration is replication-safe. If a logical replication slot that spock cannot suppress is present — a non-spock slot, or any logical slot when spock is absent — the functions refuse to migrate rather than risk losing objects. * Migration is node-local: native large objects are never replicated, so each node holds an independent set and `migrate_from_native()` migrates only the local node's objects. Run it on every node that holds native large objects, for example via `spock.replicate_ddl('SELECT lolor.migrate_from_native()')`. Migrated objects keep their original native OIDs, which are not node-encoded and can collide across nodes if different nodes hold different objects under the same OID; newly created large objects are collision-free, since new OIDs are node-encoded via `lolor.node` and checked against existing rows. * Expanded test coverage: TAP tests for dump/restore, streaming and logical replication, and standby promotion; regression tests for `lo_lseek`, `lo_tell`, and `lo_truncate`. * Security hardening: addressed Codacy/Flawfinder warnings.