Bug-fix release addressing issue #18. Follows 4.4.1 (issue #17) and completes the hardening of the in-line masking engine so a mask can never abort or corrupt a clone.
Highlights
A mask that would break a clone is now clamped or skipped with a WARNING (the column is left unmasked) instead of failing:
| Hazard | Before | Now |
|---|---|---|
constant/partial/hash/random_int longer than varchar(N)/char(N) |
ERROR: value too long for type character varying(N) |
Clamped with left(…, N) so it always fits |
constant ('REDACTED') on an integer/numeric column |
ERROR: invalid input syntax for type integer |
Applied only if the literal is a valid number, else skipped |
null on a NOT NULL column |
ERROR: null value … violates not-null constraint |
Skipped |
collapsing mask (name/constant/null) or random_int on a UNIQUE/PRIMARY KEY column |
ERROR: duplicate key value violates unique constraint |
Only the injective hash is applied; others skipped |
any mask on a FOREIGN KEY column |
broken referential integrity | Skipped |
pgclone.discover_sensitive() and pgclone.masking_report() now only suggest strategies the engine will actually apply: foreign-key columns are omitted, and UNIQUE/PRIMARY KEY or NOT NULL sensitive columns are steered to hash — so a generated mask file is safe to apply verbatim.
A masked view (pgclone.create_masking_policy()) enforces no table constraints, so only the type/constant checks apply there.
Masking keys and numeric columns
- Masking numeric columns is supported via
random_int/hash; a textconstanton a numeric column is what used to fail and is now skipped. - Integer primary/unique/foreign keys generally should not be masked — no built-in strategy both fits an integer and preserves the constraint, so they are left unmasked (integer PK/UQ) or skipped (FK). For referentially-consistent key masking, apply
hashto the same text column across parent and child (matching values hash identically).
Compatibility
- No SQL signature changes — the fix is entirely in the C masking engine.
sql/pgclone--4.4.1--4.4.2.sqlonly bumps the installed version. - Behavior change is limited to masks that previously crashed the clone or violated a constraint; masks that already worked are unaffected.
- Synchronous paths only, as with the rest of the masking feature (
*_asyncjobs ignore"mask"/"masks"). - Pure C-string/libpq implementation; identical behavior on PostgreSQL 14–18.
Upgrade
ALTER EXTENSION pgclone UPDATE TO '4.4.2';Or a fresh install: make install then CREATE EXTENSION pgclone;
Tests
pgTAP group 27 (12 new tests, plan 95 → 107) plus mask18_parent / mask18_child fixtures covering length clamping, constant-on-numeric, uniqueness (name skipped, hash distinct-preserving), NOT NULL and FK skips. Loopback DDL suite 47/47.
Full changelog: see CHANGELOG.md ([4.4.2]).