UNPKG

@clickup/pg-microsharding

Version:
55 lines 3.34 kB
"use strict"; 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"); /** * Runs pg_dump, does some basic parsing and returns the result. * * By default, the tool does not validate FKs on the destination, since it's * implied they were already valid on the source. So the FKs on the destination * are created with "NOT VALID" clause. This speeds up microshards moving * severely. The downside is that, if we later run pg_dump over the migrated * destination shard, it will emit "ALTER TABLE ... ADD CONSTRAINT ... NOT * VALID" as well (i.e. PG remembers that the FKs were not validated). This is * not the end of the world, just inaccurate. */ async function getDump({ fromDsn, schema, validateFKs, }) { 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.map((entry) => entry.replace(/^(ALTER TABLE ONLY [^\n]+\n +ADD CONSTRAINT [^\n]+ FOREIGN KEY [^\n]+ REFERENCES [^\n]+?)(?: NOT VALID)?(;)$/s, (_, sql, end) => sql + (validateFKs ? "" : " NOT VALID") + end)), (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, "-- $&"))); entries[0] = entries[0].replace(/\n\n+/gs, "\n"); return entries; } //# sourceMappingURL=getDump.js.map