ProvSQL C/C++ API
Adding support for provenance and uncertainty management to PostgreSQL databases
Loading...
Searching...
No Matches
provsql_utils.c File Reference

OID lookup, constants cache, and utility functions for ProvSQL. More...

#include "postgres.h"
#include "access/htup_details.h"
#include "access/heapam.h"
#include "access/genam.h"
#include "miscadmin.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_attribute.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_index.h"
#include "catalog/pg_type.h"
#include "catalog/pg_enum.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_operator.h"
#include "fmgr.h"
#include "nodes/value.h"
#include "parser/parse_func.h"
#include "utils/fmgroids.h"
#include "utils/syscache.h"
#include "utils/lsyscache.h"
#include "utils/inval.h"
#include <string.h>
#include "provsql_utils.h"
Include dependency graph for provsql_utils.c:

Go to the source code of this file.

Classes

struct  table_info_cache_entry
struct  ancestry_cache_entry
struct  key_cache_entry

Macros

#define table_open(r, l)
#define table_close(r, l)
#define CheckOid(o)
#define GET_GATE_TYPE_OID(x)
#define GET_GATE_TYPE_OID_OPTIONAL(x)

Functions

static Oid binary_oper_exact (List *opname, Oid arg1, Oid arg2)
 Look up an exactly matching binary operator OID.
Oid find_equality_operator (Oid ltypeId, Oid rtypeId)
 Find the equality operator OID for two given types.
static Oid get_func_oid (char *s)
 Return the OID of a globally qualified function named s.
static Oid get_provsql_func_oid (char *s)
 Return the OID of a provsql-schema function named s.
static void OperatorGet (const char *operatorName, Oid operatorNamespace, Oid leftObjectId, Oid rightObjectId, Oid *operatorObjectId, Oid *functionObjectId)
 Retrieve operator and function OIDs for a named operator.
static Oid get_enum_oid (Oid enumtypoid, const char *label)
 Return the OID of a specific enum label within an enum type.
static constants_t initialize_constants (bool failure_if_not_possible)
 Query the system catalogs to populate a fresh constants_t.
constants_t get_constants (bool failure_if_not_possible)
 Retrieve the cached OID constants for the current database.
static int table_info_cache_find (Oid relid, int *insert_at)
 Find relid in the cache.
static void table_info_cache_insert (int pos, Oid relid, bool present, const ProvenanceTableInfo *info)
 Insert a fresh entry at pos (which must be the value returned by the most recent table_info_cache_find that reported a miss).
static void invalidate_table_info_cache_callback (Datum arg, Oid relid)
 Relcache callback: PostgreSQL fires this whenever a relation's relcache entry is invalidated (locally or via shared invalidation from another backend).
bool provsql_lookup_table_info (Oid relid, ProvenanceTableInfo *out)
 Look up per-table provenance metadata with a backend-local cache.
static int ancestry_cache_find (Oid relid, int *insert_at)
static void ancestry_cache_insert (int pos, Oid relid, bool present, uint16 ancestor_n, const Oid *ancestors)
static void invalidate_ancestry_cache_callback (Datum arg, Oid relid)
bool provsql_lookup_ancestry (Oid relid, uint16 *ancestor_n_out, Oid *ancestors_out)
 Look up the base-ancestor set of a tracked relation.
static int key_cache_find (Oid relid, int *insert_at)
static void key_cache_insert (int pos, Oid relid, const ProvenanceRelationKeys *keys)
static void invalidate_key_cache_callback (Datum arg, Oid relid)
static bool fetch_relation_keys (Oid relid, ProvenanceRelationKeys *out)
 Read the PRIMARY-KEY and NOT-NULL-UNIQUE keys of relid from the system catalogs.
bool provsql_lookup_relation_keys (Oid relid, ProvenanceRelationKeys *out)
 Look up the PRIMARY-KEY and NOT-NULL-UNIQUE keys of a relation with a backend-local cache.
Datum reset_constants_cache (PG_FUNCTION_ARGS)
 SQL function to invalidate the OID constants cache.

Variables

const char * gate_type_name []
 Names of gate types.
static database_constants_tconstants_cache
 Per-database OID constants cache (sorted by database OID).
static unsigned constants_cache_len =0
 Number of valid entries in constants_cache.
static table_info_cache_entrytable_info_cache = NULL
 Sorted by relid.
static unsigned table_info_cache_len = 0
static bool table_info_callback_registered = false
static ancestry_cache_entryancestry_cache = NULL
static unsigned ancestry_cache_len = 0
static bool ancestry_callback_registered = false
static key_cache_entrykey_cache = NULL
static unsigned key_cache_len = 0
static bool key_cache_callback_registered = false

Detailed Description

OID lookup, constants cache, and utility functions for ProvSQL.

Implements the functions declared in provsql_utils.h:

The constants cache is a sorted, dynamically-grown array of database_constants_t records (one per PostgreSQL database OID) stored in process-local memory and searched with binary search. The reset_constants_cache() SQL function forces a cache invalidation for the current database, which is needed after ALTER EXTENSION.

Several helper functions (get_func_oid, get_provsql_func_oid, OperatorGet, get_enum_oid, binary_oper_exact) are adapted from PostgreSQL source code that is not exported as a public API.

Definition in file provsql_utils.c.

Macro Definition Documentation

◆ CheckOid

#define CheckOid ( o)
Value:
if(constants.o==InvalidOid) { \
if(failure_if_not_possible) \
provsql_error("Could not initialize provsql constants"); \
else \
return constants; }

◆ GET_GATE_TYPE_OID

#define GET_GATE_TYPE_OID ( x)
Value:
{ \
constants.GATE_TYPE_TO_OID[gate_ ## x] = get_enum_oid( \
constants.OID_TYPE_GATE_TYPE, \
#x); \
if(constants.GATE_TYPE_TO_OID[gate_ ## x]==InvalidOid) \
provsql_error("Could not initialize provsql gate type " #x); }
static Oid get_enum_oid(Oid enumtypoid, const char *label)
Return the OID of a specific enum label within an enum type.

◆ GET_GATE_TYPE_OID_OPTIONAL

#define GET_GATE_TYPE_OID_OPTIONAL ( x)
Value:
{ \
constants.GATE_TYPE_TO_OID[gate_ ## x] = get_enum_oid( \
constants.OID_TYPE_GATE_TYPE, \
#x); }

◆ table_close

#define table_close ( r,
l )
Value:
heap_close((r), (l))

Definition at line 28 of file provsql_utils.c.

◆ table_open

#define table_open ( r,
l )
Value:
heap_open((r), (l))

Definition at line 27 of file provsql_utils.c.

Function Documentation

◆ ancestry_cache_find()

int ancestry_cache_find ( Oid relid,
int * insert_at )
static

Definition at line 725 of file provsql_utils.c.

Here is the caller graph for this function:

◆ ancestry_cache_insert()

void ancestry_cache_insert ( int pos,
Oid relid,
bool present,
uint16 ancestor_n,
const Oid * ancestors )
static

Definition at line 741 of file provsql_utils.c.

Here is the caller graph for this function:

◆ binary_oper_exact()

Oid binary_oper_exact ( List * opname,
Oid arg1,
Oid arg2 )
static

Look up an exactly matching binary operator OID.

Copied and adapted from parse_oper.c (PostgreSQL internals, not exported). Returns InvalidOid if no exact match exists.

Parameters
opnameQualified operator name (a List of String nodes).
arg1OID of the left operand type.
arg2OID of the right operand type.
Returns
OID of the matching operator, or InvalidOid.

Definition at line 89 of file provsql_utils.c.

Here is the caller graph for this function:

◆ fetch_relation_keys()

bool fetch_relation_keys ( Oid relid,
ProvenanceRelationKeys * out )
static

Read the PRIMARY-KEY and NOT-NULL-UNIQUE keys of relid from the system catalogs.

Scans pg_constraint for entries with conrelid = relid and contype IN ('p','u'), then resolves each constraint's column list via pg_index.indkey (the constraint's index is recorded in pg_constraint.conindid). For UNIQUE constraints, verifies every constituent column has pg_attribute.attnotnull = true; UNIQUE-with-NULLABLE constraints are rejected (UNIQUE allows multiple rows with NULL in PostgreSQL, so the attr FD does not hold without NOT NULL).

Stores up to PROVSQL_KEY_CACHE_MAX_KEYS keys; subsequent keys are silently dropped. Skips constraints whose column count exceeds PROVSQL_KEY_CACHE_MAX_KEY_COLS. Both elisions are conservatively safe (the §2 detector simply does not see the dropped FDs).

Definition at line 926 of file provsql_utils.c.

Here is the caller graph for this function:

◆ find_equality_operator()

Oid find_equality_operator ( Oid ltypeId,
Oid rtypeId )

Find the equality operator OID for two given types.

Searches pg_operator for the = operator that accepts ltypeId on the left and rtypeId on the right.

Parameters
ltypeIdOID of the left operand type.
rtypeIdOID of the right operand type.
Returns
The operator OID, or InvalidOid if none is found.

Definition at line 129 of file provsql_utils.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_constants()

constants_t get_constants ( bool failure_if_not_possible)

Retrieve the cached OID constants for the current database.

On first call (or after a cache miss) this function looks up the OIDs of all ProvSQL-specific types, functions, and operators in the system catalogs and stores them in a per-database cache. Subsequent calls return the cached values without touching the catalogs.

Parameters
failure_if_not_possibleIf true, call provsql_error when the ProvSQL schema cannot be found (e.g. the extension is not installed in the current database). If false, return a constants_t with ok==false instead of aborting.
Returns
A constants_t whose ok field is true on success.

Definition at line 530 of file provsql_utils.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_enum_oid()

Oid get_enum_oid ( Oid enumtypoid,
const char * label )
static

Return the OID of a specific enum label within an enum type.

Parameters
enumtypoidOID of the enum type (e.g. provenance_gate).
labelC-string label of the enum value to look up.
Returns
OID of the enum label's pg_enum row, or InvalidOid if the label is not present.

Definition at line 274 of file provsql_utils.c.

◆ get_func_oid()

Oid get_func_oid ( char * s)
static

Return the OID of a globally qualified function named s.

Looks up the function in the default search path. Returns 0 if no matching function is found.

Parameters
sFunction name (unqualified).
Returns
OID of the function, or 0 if not found.

Definition at line 169 of file provsql_utils.c.

Here is the caller graph for this function:

◆ get_provsql_func_oid()

Oid get_provsql_func_oid ( char * s)
static

Return the OID of a provsql-schema function named s.

Looks up the function in the provsql schema. Returns 0 if not found.

Parameters
sFunction name (without schema prefix).
Returns
OID of the function, or 0 if not found.

Definition at line 195 of file provsql_utils.c.

Here is the caller graph for this function:

◆ initialize_constants()

constants_t initialize_constants ( bool failure_if_not_possible)
static

Query the system catalogs to populate a fresh constants_t.

Performs all OID lookups required by ProvSQL in a single pass through the system caches. The CheckOid() macro aborts (or returns early, depending on failure_if_not_possible) if any OID resolves to InvalidOid.

Parameters
failure_if_not_possibleIf true, raise a provsql_error when any OID cannot be resolved. If false, return a constants_t with ok==false instead.
Returns
Fully populated constants_t on success, or ok==false on failure when failure_if_not_possible is false.

Abort or return early if OID field o of constants is invalid.

Look up the OID of provenance_gate enum value x and store it in constants.

Like GET_GATE_TYPE_OID but tolerates a missing enum value.

Used for gate types added in releases newer than the oldest schema the extension_upgrade test exercises (currently 1.0.0). An intermediate state where a 1.0.0 database has been bound to a newer shared library is possible (e.g. between CREATE EXTENSION VERSION and ALTER EXTENSION UPDATE) and must not abort get_constants – the missing OID stays InvalidOid and any attempt to actually create such a gate fails later in create_gate's "Invalid gate type" branch. When the upgrade scripts catch up, the lookup succeeds and the gate becomes usable normally. No state for InvalidOid is stored, so the field keeps its zero-init value (which is InvalidOid).

Definition at line 310 of file provsql_utils.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ invalidate_ancestry_cache_callback()

void invalidate_ancestry_cache_callback ( Datum arg,
Oid relid )
static

Definition at line 763 of file provsql_utils.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ invalidate_key_cache_callback()

void invalidate_key_cache_callback ( Datum arg,
Oid relid )
static

Definition at line 893 of file provsql_utils.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ invalidate_table_info_cache_callback()

void invalidate_table_info_cache_callback ( Datum arg,
Oid relid )
static

Relcache callback: PostgreSQL fires this whenever a relation's relcache entry is invalidated (locally or via shared invalidation from another backend).

relid == InvalidOid means "invalidate everything."

Definition at line 635 of file provsql_utils.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ key_cache_find()

int key_cache_find ( Oid relid,
int * insert_at )
static

Definition at line 856 of file provsql_utils.c.

Here is the caller graph for this function:

◆ key_cache_insert()

void key_cache_insert ( int pos,
Oid relid,
const ProvenanceRelationKeys * keys )
static

Definition at line 872 of file provsql_utils.c.

Here is the caller graph for this function:

◆ OperatorGet()

void OperatorGet ( const char * operatorName,
Oid operatorNamespace,
Oid leftObjectId,
Oid rightObjectId,
Oid * operatorObjectId,
Oid * functionObjectId )
static

Retrieve operator and function OIDs for a named operator.

Copied and adapted from pg_operator.c (PostgreSQL internals, not exported). Looks up the operator by name, namespace, and operand types in the system cache.

Parameters
operatorNameOperator symbol string (e.g. "<>").
operatorNamespaceOID of the schema containing the operator.
leftObjectIdOID of the left operand type.
rightObjectIdOID of the right operand type.
operatorObjectIdOutput: OID of the operator, or 0 if not found.
functionObjectIdOutput: OID of the underlying function, or 0.

Definition at line 227 of file provsql_utils.c.

Here is the caller graph for this function:

◆ provsql_lookup_ancestry()

bool provsql_lookup_ancestry ( Oid relid,
uint16 * ancestor_n_out,
Oid * ancestors_out )

Look up the base-ancestor set of a tracked relation.

Per-backend cached over IPC. Returns the ancestor set when relid is tracked and the registry has a non-empty entry for it. false either when relid has no metadata record at all (the relation was never run through add_provenance / repair_key) or when the record exists but ancestor_n == 0 (the CTAS hook hasn't populated the lineage yet, or the registry was explicitly cleared). The two failure modes share the false return because both make the safe-query rewriter take the conservative refuse path – there is no use case for treating them differently.

Backed by the same per-backend cache as provsql_lookup_table_info and invalidated through the same relcache-invalidation callback, so concurrent set_ancestors / add_provenance / repair_key calls in other backends are reflected here without polling.

Parameters
relidpg_class OID of the relation to look up.
ancestor_n_outOn true return, count of valid entries in ancestors_out.
ancestors_outOn true return, the sorted-deduplicated ancestor OIDs (caller-allocated buffer of PROVSQL_TABLE_INFO_MAX_ANCESTORS Oid).
Returns
true on a non-empty ancestor set; false otherwise.

Definition at line 777 of file provsql_utils.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ provsql_lookup_relation_keys()

bool provsql_lookup_relation_keys ( Oid relid,
ProvenanceRelationKeys * out )

Look up the PRIMARY-KEY and NOT-NULL-UNIQUE keys of a relation with a backend-local cache.

Companion to provsql_lookup_table_info. The cache lives in a separate backing array with its own relcache-invalidation callback so that a future ALTER TABLE that adds / drops a constraint refreshes the next lookup without polling. Returns true when the relation has at least one PRIMARY KEY or NOT-NULL UNIQUE constraint; false otherwise (in which case *out is filled with key_n = 0). Safe to call from the planner hot path.

Parameters
relidpg_class OID of the relation to inspect.
outFilled on return. out->relid is set to relid regardless of return value; out->keys holds up to PROVSQL_KEY_CACHE_MAX_KEYS keys.

Definition at line 1014 of file provsql_utils.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ provsql_lookup_table_info()

bool provsql_lookup_table_info ( Oid relid,
ProvenanceTableInfo * out )

Look up per-table provenance metadata with a backend-local cache.

Resolves to a cached value when the relation's relcache entry has not been invalidated since the last fetch; otherwise issues one 's' IPC to the background worker. The cache is invalidated via CacheRegisterRelcacheCallback, so concurrent add_provenance / repair_key / remove_provenance in other backends are reflected here without polling.

Safe to call from the planner hot path.

Parameters
relidpg_class OID of the relation to look up.
outOn true return, filled with the stored record.
Returns
true if a record exists for relid, false otherwise.

Definition at line 649 of file provsql_utils.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ reset_constants_cache()

Datum reset_constants_cache ( PG_FUNCTION_ARGS )

SQL function to invalidate the OID constants cache.

Forces a fresh OID lookup for the current database on the next call to get_constants(). Must be called after ALTER EXTENSION provsql UPDATE to ensure cached OIDs are refreshed.

Returns
Void datum.

Definition at line 1062 of file provsql_utils.c.

Here is the call graph for this function:

◆ table_info_cache_find()

int table_info_cache_find ( Oid relid,
int * insert_at )
static

Find relid in the cache.

Returns the index on hit; otherwise -1 and writes the insertion point to *insert_at.

Definition at line 590 of file provsql_utils.c.

Here is the caller graph for this function:

◆ table_info_cache_insert()

void table_info_cache_insert ( int pos,
Oid relid,
bool present,
const ProvenanceTableInfo * info )
static

Insert a fresh entry at pos (which must be the value returned by the most recent table_info_cache_find that reported a miss).

Definition at line 608 of file provsql_utils.c.

Here is the caller graph for this function:

Variable Documentation

◆ ancestry_cache

ancestry_cache_entry* ancestry_cache = NULL
static

Definition at line 721 of file provsql_utils.c.

◆ ancestry_cache_len

unsigned ancestry_cache_len = 0
static

Definition at line 722 of file provsql_utils.c.

◆ ancestry_callback_registered

bool ancestry_callback_registered = false
static

Definition at line 723 of file provsql_utils.c.

◆ constants_cache

database_constants_t* constants_cache
static

Per-database OID constants cache (sorted by database OID).

Definition at line 527 of file provsql_utils.c.

◆ constants_cache_len

unsigned constants_cache_len =0
static

Number of valid entries in constants_cache.

Definition at line 528 of file provsql_utils.c.

◆ gate_type_name

const char* gate_type_name[]
Initial value:
= {
"input",
"plus",
"times",
"monus",
"project",
"zero",
"one",
"eq",
"agg",
"semimod",
"cmp",
"delta",
"value",
"mulinput",
"update",
"rv",
"arith",
"mixture",
"assumed_boolean",
"invalid"
}

Names of gate types.

Definition at line 54 of file provsql_utils.c.

◆ key_cache

key_cache_entry* key_cache = NULL
static

Definition at line 852 of file provsql_utils.c.

◆ key_cache_callback_registered

bool key_cache_callback_registered = false
static

Definition at line 854 of file provsql_utils.c.

◆ key_cache_len

unsigned key_cache_len = 0
static

Definition at line 853 of file provsql_utils.c.

◆ table_info_cache

table_info_cache_entry* table_info_cache = NULL
static

Sorted by relid.

Definition at line 584 of file provsql_utils.c.

◆ table_info_cache_len

unsigned table_info_cache_len = 0
static

Definition at line 585 of file provsql_utils.c.

◆ table_info_callback_registered

bool table_info_callback_registered = false
static

Definition at line 586 of file provsql_utils.c.