Skip to content

v0.99.13

Choose a tag to compare

@github-actions github-actions released this 07 Jun 05:07
· 3046 commits to main since this release

Cross-engine parity + table-scope completion. A no-PK table that carries a NOT-NULL UNIQUE key now migrates and syncs MySQL→Postgres without a manual schema change (it already worked MySQL→MySQL), and the v0.99.12 --include-table snapshot scope now also covers the PlanetScale cold-start resume and backup paths. Drop-in upgrade from v0.99.12 — no breaking API or CLI changes.

Fixed

  • A no-PK table with a NOT-NULL UNIQUE key now does an idempotent cold-start COPY on a Postgres target (cross-engine symmetry with MySQL). Previously such a table (e.g. a PlanetScale connections table: UNIQUE KEY id with no declared PRIMARY KEY) copied fine MySQL→MySQL — the MySQL writer promotes the unique key for an idempotent upsert — but was refused on a Postgres target (table "X" has no PRIMARY KEY and the target's idempotent bulk-copy writer does not support no-PK upsert), forcing a manual PRIMARY KEY addition on the source.

    The Postgres engine now mirrors MySQL: it picks a deterministic NOT-NULL UNIQUE index (every column NOT NULL, then fewest columns, then lexicographically smallest name), inline-promotes it as a CONSTRAINT … UNIQUE at CREATE TABLE so Postgres's ON CONFLICT (cols) has a real matching unique index to infer against while rows land, and keys both the cold-start COPY writer and the CDC applier's Insert on that key — so a re-applied Insert (an at-least-once CDC replay, or a VStream COPY catch-up re-emission) upserts idempotently instead of erroring with a unique violation or duplicating the row. A truly-keyless table (no PK, no NOT-NULL UNIQUE) is still refused loudly, matching MySQL. UPDATE/DELETE are unaffected (they identify the target row via the full before-image).

    Validated end-to-end MySQL→Postgres (zero-loss copy + idempotent replay, single- and composite-key) plus a pin-the-class unit matrix.

  • --include-table now scopes the PlanetScale (VStream) cold-start resume path too. v0.99.12 scoped the fresh cold-start snapshot COPY, but a process-restart resume of an interrupted cold-start still streamed the whole keyspace. The resumed COPY now carries the same table allowlist as a fresh one. Vitess's resume cursor (TablePKs) is per-table, so the scope composes with the cursor with no manual reconciliation — a table with a cursor entry resumes from it, an in-scope table without one starts fresh, and a de-scoped table simply stops being copied.

  • --include-table now scopes the PlanetScale (VStream) backup snapshot COPY too. sluice backup … --include-table X already restricted what was written, but the backup's VStream snapshot used the catch-all filter and streamed/buffered the whole keyspace — so a scoped backup of a small table coexisting with a large one could overflow --max-buffer-bytes (the same ADR-0071 over-stream v0.99.12 fixed for cold-start). The backup snapshot now scopes its COPY filter to the included tables via a new optional ir.TableScopedBackupSnapshotOpener. Postgres and vanilla MySQL read per-table and never over-stream, so they are unaffected (they fall back to the unchanged whole-snapshot path).

Compatibility

  • No breaking API or CLI changes. Drop-in from v0.99.12. The Postgres no-PK path only activates for tables that have a NOT-NULL UNIQUE key but no PRIMARY KEY (previously refused outright); existing PK tables emit byte-identical SQL. The resume/backup table-scope only changes the PlanetScale/VStream path — whole-keyspace runs (no --include-table) and all non-PlanetScale engines are unaffected. The new engine surfaces are additive: the optional ir.TableScopedBackupSnapshotOpener, and a tables parameter on the ir.SnapshotStreamResumer resume hook.

Who needs this

  • Anyone migrating a no-PK-but-unique-keyed table from MySQL/PlanetScale to Postgres. Before this you had to add a PRIMARY KEY on the source by hand; now the unique key is promoted automatically and the copy is idempotent on replay — matching the MySQL→MySQL behavior.
  • Anyone running scoped (--include-table) PlanetScale resumes or backups. The snapshot now copies only the tables you selected on the resume and backup paths too, so a large excluded table in the same keyspace can no longer overflow --max-buffer-bytes.

Install: brew install sluicesync/tap/sluice · go install sluicesync.dev/sluice/cmd/sluice@v0.99.13 · Container: ghcr.io/sluicesync/sluice:0.99.13
Full changelog: https://github.com/sluicesync/sluice/blob/main/CHANGELOG.md