feat(postgres): read as of a snapshot another session holds · DBDiff/DBDiff@4ff6b22 · GitHub
Skip to content

Commit 4ff6b22

Browse files
jasdeepkhalsaclaude
andcommitted
feat(postgres): read as of a snapshot another session holds
--source-snapshot and --target-snapshot take a snapshot another session exported with pg_export_snapshot() and holds open, and read that side as of it instead of one of DBDiff's own: a tool that reads the same databases itself, and runs DBDiff as one part of it, sees one instant throughout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 1cc4778 commit 4ff6b22

5 files changed

Lines changed: 46 additions & 2 deletions

File tree

‎README.md‎

Lines changed: 1 addition & 0 deletions

‎src/DB/DBManager.php‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ public function connect($params): void {
7171
PostgresSessionOptions::apply($this->capsule->getConnection($key));
7272

7373
if ($this->driver === 'pgsql' && ($params->snapshot ?? true)) {
74-
$this->holdSnapshot($key, $config);
74+
$given = $key === 'source' ? ($params->sourceSnapshot ?? null) : ($params->targetSnapshot ?? null);
75+
$given ? $this->joinSnapshot($key, $given) : $this->holdSnapshot($key, $config);
7576
}
7677
}
7778
if ($this->driver === 'pgsql') {
@@ -82,6 +83,17 @@ public function connect($params): void {
8283
}
8384
}
8485

86+
/**
87+
* Read `$side` as of a snapshot another session exported and holds — a
88+
* tool running DBDiff as one part of a larger read, so all of it sees the
89+
* same instant.
90+
*/
91+
private function joinSnapshot(string $side, string $id): void {
92+
if (PostgresSnapshot::join($this->getDB($side), $id, $side)) {
93+
$this->snapshots[$side] = $id;
94+
}
95+
}
96+
8597
/**
8698
* Read `$side` as of one instant: a second connection exports its
8799
* snapshot and keeps it open, and the one DBDiff reads with joins it —

‎src/Migration/Command/DiffCommand.php‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ protected function configure(): void
9999
->addOption('renames', null, InputOption::VALUE_REQUIRED,
100100
'PostgreSQL: "auto" (default) renames a column or table whose only difference is its name, '
101101
. 'keeping its data, where exactly one such pair exists; "off" drops and adds instead.', 'auto')
102+
->addOption('source-snapshot', null, InputOption::VALUE_REQUIRED,
103+
'PostgreSQL: read the source as of this snapshot, exported by a session that holds it open.')
104+
->addOption('target-snapshot', null, InputOption::VALUE_REQUIRED,
105+
'PostgreSQL: read the target as of this snapshot, exported by a session that holds it open.')
102106
->addOption('no-snapshot', null, InputOption::VALUE_NONE,
103107
'PostgreSQL: read each query on its own, rather than each side as of one instant. '
104108
. 'The snapshot keeps what the diff reads locked until it ends, as pg_dump does.');
@@ -173,6 +177,8 @@ private function buildParams(InputInterface $input): DefaultParams
173177
$params->allowDestructive = (bool) $input->getOption('allow-destructive');
174178
$params->renames = $input->getOption('renames') === 'off' ? 'off' : 'auto';
175179
$params->snapshot = !$input->getOption('no-snapshot');
180+
$params->sourceSnapshot = $input->getOption('source-snapshot') ?: null;
181+
$params->targetSnapshot = $input->getOption('target-snapshot') ?: null;
176182

177183
if ($input->getOption('tables')) {
178184
$params->tables = array_map('trim', explode(',', $input->getOption('tables')));

‎src/Params/DefaultParams.php‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,14 @@ class DefaultParams {
156156
*/
157157
public bool $snapshot = true;
158158

159+
/*
160+
PostgreSQL: a snapshot another session exported (pg_export_snapshot) and
161+
holds open, to read the source or target as of instead of one of
162+
DBDiff's own.
163+
*/
164+
public ?string $sourceSnapshot = null;
165+
public ?string $targetSnapshot = null;
166+
159167
/*
160168
The penultimate parameter is what to compare: db1.table1:db2.table3 or​ db1:db2
161169
This tool can compare just one table or all tables (entire db) from the database

‎tests/SnapshotPostgresTest.php‎

Lines changed: 18 additions & 1 deletion

0 commit comments

Comments
 (0)