@clickup/pg-microsharding
Version:
Microshards support for PostgreSQL
58 lines • 3.38 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDump = getDump;
const compact_1 = __importDefault(require("lodash/compact"));
const partition_1 = __importDefault(require("lodash/partition"));
const names_1 = require("./names");
const quote_1 = require("./quote");
const runShell_1 = require("./runShell");
// The downside of turning this on is that, if we run pg_dump over the migrated
// shard, then it will emit "ALTER TABLE ... ADD CONSTRAINT ... NOT VALID" (i.e.
// PG remembers that the FKs were not validated). This is not the end of the
// world, but it's not worth the ~5% overall speedup this option gives.
const SKIP_FK_VALIDATION = false;
/**
* Runs pg_dump, does some basic parsing and returns the result.
*/
async function getDump({ fromDsn, schema, }) {
const preData = parseDump(await (0, runShell_1.runShell)(`${(0, names_1.pgDump)(fromDsn)} -n ${(0, quote_1.shellQuote)(schema)} --section=pre-data`, null, `Reading pre-data DDL (except indexes) for ${schema} from ${fromDsn}`));
const postDataAll = parseDump(await (0, runShell_1.runShell)(`${(0, names_1.pgDump)(fromDsn)} -n ${(0, quote_1.shellQuote)(schema)} --section=post-data`, null, `Reading post-data DDL (indexes, foreign keys) for ${schema} from ${fromDsn}`));
// For logical replication to work, each table on the subscription part must
// have an index that allows the logical worker to find the row it receives
// from the publication end. PostgreSQL 16+ can use regular indexes for that,
// but the earlier versions require the subscription end to have either a
// REPLICA IDENTITY or a PRIMARY KEY. Thus, we extract such indexes from the
// post-data section of the dump and create them before creating the
// subscription.
const [primaryKeys, postData] = (0, partition_1.default)(postDataAll, (entry) => entry.match(/^ALTER TABLE .* ADD CONSTRAINT .* PRIMARY KEY \([^)]+\);$/s) ||
entry.match(/^CREATE UNIQUE INDEX (.*?) ON .*\nALTER TABLE .*? REPLICA IDENTITY USING INDEX \1;$/s));
return {
preData: (0, quote_1.join)(preData, "\n"),
primaryKeys,
postData: (0, quote_1.join)(postData, "\n"),
};
}
/**
* The text generated by pg_dump consists of entries divided by 3 lines of
* "--"-comments. We split the dump into that entries, and only then analyze it
* in the further logic.
*/
function parseDump(dump) {
const entries = (0, compact_1.default)(dump
.split(/^--\n-- \w+[^\n]*\n--\n/m)
.map((entry) => entry.trim())
// Added in PG17+ and is not supported in earlier versions.
.map((entry) => entry.replace(/^SET transaction_timeout = [^\n]+/m, "-- $&"))
// If enabled, makes FKs creation instant: we don't need to check
// integrity at creation time, since the data on the source is already
// validated. (It will still check at tuples write time though.)
.map((entry) => SKIP_FK_VALIDATION
? entry.replace(/^(ALTER TABLE ONLY [^\n]+\n +ADD CONSTRAINT [^\n]+ FOREIGN KEY [^\n]+ REFERENCES [^\n]+)(;)$/s, "$1 NOT VALID$2")
: entry));
entries[0] = entries[0].replace(/\n\n+/gs, "\n");
return entries;
}
//# sourceMappingURL=getDump.js.map