Skip to content

The vault access method

A table access method is a struct of function pointers — TableAmRoutine — that PostgreSQL consults for everything it does with a table's storage. CREATE ACCESS METHOD registers a function that returns one.


Construction

The routine is built by copying heap's wholesale and then overriding specific members:

heap_methods = GetHeapamTableAmRoutine();
memcpy(&vault_methods, heap_methods, sizeof(TableAmRoutine));

Anything not deliberately replaced is heap's behaviour by construction, rather than by remembering to assign it.


The enforcement callbacks

Five callbacks can modify a row, and all five are overridden:

Callback Reached by
tuple_insert INSERT
multi_insert COPY FROM
tuple_insert_speculative INSERT ... ON CONFLICT
tuple_update UPDATE, MERGE, ON CONFLICT DO UPDATE
tuple_delete DELETE, MERGE

All five matter. COPY FROM never touches tuple_insert — it goes through multi_insert. Overriding only the three obvious callbacks would leave COPY writing freely into a table granting no insert.


The identity shims

Two further callbacks are overridden for a reason that has nothing to do with enforcement.

heap_getnext() contains a safety check that rejects any relation whose access method routine is not pointer-identical to heap's own. Its comment is explicit that the pointer, rather than the access method's OID, is compared — which supports an access method that is heap, but not one that wraps it.

Two of heap's own callbacks reach that function:

  • index_build_range_scan — every index build, so every PRIMARY KEY
  • index_validate_scanCREATE INDEX CONCURRENTLY

Delegating them unmodified fails. The shims present the relation as heap for exactly the duration of the delegated call, wrapped in PG_TRY/PG_FINALLY so an error cannot leave the relation permanently claiming to be a heap table.

The alternative would have been copying several hundred lines of heap's HOT-chain and snapshot handling into this extension, and re-verifying it against every PostgreSQL release.


TOAST

A vault table's TOAST relation inherits the vault access method, but this is harmless: PostgreSQL's TOAST code calls heap_insert and simple_heap_delete directly rather than going through the access method layer, and reads via index scans rather than heap_getnext.

No exemption is needed, and none should be added.