Midwess
Learn

PgPaw is intentionally read-only. It accepts one PostgreSQL SELECT statement over tables that exist in the local replica.

Accepted shape

select id, email
from users
where id = 7;

Joins are allowed:

select u.id, u.email, count(o.id) as order_count
from users u
left join orders o on o.user_id = u.id
where u.id = 7
group by u.id, u.email;

Rejected input

PgPaw rejects:

  • SQL parse failures;
  • multiple statements;
  • writes: insert, update, delete, merge;
  • DDL: create, alter, drop;
  • select into;
  • locking reads: for update, for share;
  • references to tables outside the replicated publication;
  • side-effecting functions, including nextval, setval, and advisory lock functions;
  • volatile reads, including now, random, random_normal, clock_timestamp, timeofday, statement_timestamp, gen_random_uuid, and uuid_generate_v4.

Rejected query example:

select nextval('orders_id_seq');

Response:

{
  "name": "RejectedError",
  "message": "function `nextval` has side effects and cannot be cached"
}

Extracted metadata

For accepted SQL, PgPaw records:

Field Meaning
fingerprint Opaque implementation fingerprint for the parsed statement.
tables Lowercase table names, excluding CTE aliases.
eq_filters Literal equality filters from the outer WHERE expression.
sql Original SQL string used for execution.

The fingerprint appears in logs and snapshot URLs, but clients should treat it as opaque.

Equality filters and cache precision

PgPaw can narrow cache invalidation when the query has a literal equality filter:

where id = 7

For a single-table query:

  • equality on the primary key anchors the version to that row;
  • equality on any replicated column can anchor if the table uses REPLICA IDENTITY FULL;
  • otherwise the query falls back to table-level invalidation.

Broad queries and joins use table-level invalidation.

Practical guidance

  • Include primary key columns in live queries when possible.
  • Use deterministic SQL. Avoid time and random functions.
  • Keep private data protected with Postgres RLS and grants, not application-side filtering after PgPaw.
  • If a table is missing, check the publication first.