Re-encrypts one encrypted field with its active key.
The runner processes rows in primary-key order and commits one transaction
per batch. It does not lock rows while it decrypts and encrypts them. Instead,
each update includes WHERE field = ^old_ciphertext. PostgreSQL writes the
replacement only if the stored bytes still match the bytes that the runner
read.
This optimistic check is safe because the database stores the complete ciphertext bytes. A concurrent application write changes those bytes and makes the rotation update affect zero rows. The runner then leaves the concurrent value intact. Run the rotation again before removing an old key so that rows skipped during concurrent writes are checked again.
Query shapes beyond plain where clauses are rejected. Ordering, limits,
joins, explicit locks, and other structural expressions would change the
runner's keyset-pagination semantics.
Summary
Functions
Re-encrypts field in schema and returns the number of rows updated.
Functions
@spec run(module(), module(), atom(), keyword()) :: non_neg_integer()
Re-encrypts field in schema and returns the number of rows updated.
The field must use Encrypted, and the schema must have exactly one
primary key.
Options
:batch_size— rows read per transaction; defaults to 100:timeout— transaction and query timeout; defaults to 15 seconds:query— a query containing onlywhereclauses onschema
Rows already using the active key are left unchanged. A row changed by another writer after selection is also left unchanged because its ciphertext no longer matches the optimistic update predicate.