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

Implementation of the planner-time UCQ recogniser (descriptor extraction). More...

#include "postgres.h"
#include "nodes/parsenodes.h"
#include "nodes/nodeFuncs.h"
#include "nodes/makefuncs.h"
#include "nodes/pg_list.h"
#include "catalog/pg_type.h"
#include "lib/stringinfo.h"
#include "optimizer/clauses.h"
#include "parser/parsetree.h"
#include "rewrite/rewriteManip.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/ruleutils.h"
#include "joint_width_query.h"
#include "provsql_utils.h"
#include "qual_classify.h"
Include dependency graph for joint_width_query.c:

Go to the source code of this file.

Classes

struct  ColRef
 A column reference (range-table index, attribute number). More...
struct  ExistCtx
 Walker context: does any target-list Var reach a tracked atom? More...
struct  RelMerge
 A merge of relations across the disjuncts of a UCQ: distinct relation OIDs (first-seen order) with their element column-name lists. More...

Functions

static int colref_get (ColRef *cols, int *ncols, Index rtindex, AttrNumber attno)
 Find-or-add a (rtindex, attno) column node; returns its index.
static int uf_find (ColRef *cols, int i)
 Union-find root with path halving.
static void uf_union (ColRef *cols, int a, int b)
static bool collect_equalities (Node *qual, ColRef *cols, int *ncols, int **pairs, int *npairs, int *const_cols, Const **const_vals, int *nconst)
 Collect the equality structure of a WHERE / ON qual tree, over the shared qual_classify recognisers.
static void append_json_string (StringInfo buf, const char *s)
 Append s as a JSON string literal (escaping " and \).
static bool exist_walker (Node *node, void *vctx)
static bool collect_jointree (Node *n, Query *q, Index *atom_rti, Oid *atom_relid, int *natoms, List **qual_list)
 Recursively collect tracked base-relation atoms and the ON quals of a jointree item (a RangeTblRef or an inner JoinExpr).
static int relmerge_get (RelMerge *m, Oid oid, List *colnames)
 Find-or-add a relation; returns its global index.
static bool cq_is_existential (Query *cq, Index *atom_rti, int natoms)
 Does cq expose no tracked-atom variable in its target list (i.e.
static bool emit_cq_disjunct (const constants_t *constants, Query *cq, RelMerge *m, StringInfo dbuf, const int *head_resno, int n_heads)
 Extract one conjunctive query (a flat join over tracked base relations) as a UCQ disjunct, appending its {"n_vars":N,"atoms":[...]} object to dbuf and registering its relations in m (so atom "rel" indices are global).
static bool collect_union_arms (Node *node, Query *parent, List **arms)
 Collect the leaf arm subqueries of a UNION set-operation tree.
static int union_position_kind (Query *unionq, int resno)
 Classify a UNION output column (1-based resno): is it a per-answer head or a constant projection?
static char * build_union_descriptor (const constants_t *constants, Query *unionq, const int *head_resno, int n_heads)
 Build the descriptor for a UNION of conjunctive queries (a UCQ with more than one disjunct): one disjunct per arm, relations merged across arms.
char * provsql_joint_width_descriptor (const constants_t *constants, Query *q, bool *all_existential, List **head_var_idx, List **head_exprs)
 Build the joint-width descriptor for a recognised UCQ.

Detailed Description

Implementation of the planner-time UCQ recogniser (descriptor extraction).

See joint_width_query.h.

Definition in file joint_width_query.c.

Function Documentation

◆ append_json_string()

void append_json_string ( StringInfo buf,
const char * s )
static

Append s as a JSON string literal (escaping " and \).

Definition at line 108 of file joint_width_query.c.

Here is the caller graph for this function:

◆ build_union_descriptor()

char * build_union_descriptor ( const constants_t * constants,
Query * unionq,
const int * head_resno,
int n_heads )
static

Build the descriptor for a UNION of conjunctive queries (a UCQ with more than one disjunct): one disjunct per arm, relations merged across arms.

head_resno (length n_heads) gives the per-answer head output positions (canonically numbered in every arm); n_heads == 0 is the Boolean existence case. Returns NULL to decline.

Definition at line 498 of file joint_width_query.c.

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

◆ collect_equalities()

bool collect_equalities ( Node * qual,
ColRef * cols,
int * ncols,
int ** pairs,
int * npairs,
int * const_cols,
Const ** const_vals,
int * nconst )
static

Collect the equality structure of a WHERE / ON qual tree, over the shared qual_classify recognisers.

Every conjunct of the (AND-only) qual must be either a Var=Var join (its two columns unioned, recorded in pairs) or a Var=Const selection. A selection is recorded in const_cols / const_vals when const_cols is non-NULL (the caller pins the column's variable to the value); when NULL it makes the recogniser decline (the UNION arms, which cannot pin per disjunct, pass NULL). The constant must share the column's exact type: the pin is applied through the gather's text element dictionary, so a cross-type literal could mis-match its column's text form. Any other qual shape declines.

Definition at line 79 of file joint_width_query.c.

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

◆ collect_jointree()

bool collect_jointree ( Node * n,
Query * q,
Index * atom_rti,
Oid * atom_relid,
int * natoms,
List ** qual_list )
static

Recursively collect tracked base-relation atoms and the ON quals of a jointree item (a RangeTblRef or an inner JoinExpr).

Flattens a JOIN b ON ... (and nested inner joins) to the same atom set + equality quals as the comma/WHERE form. Declines (returns false) on an outer join, a non-relation RTE, an untracked relation, or any other item shape.

Definition at line 158 of file joint_width_query.c.

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

◆ collect_union_arms()

bool collect_union_arms ( Node * node,
Query * parent,
List ** arms )
static

Collect the leaf arm subqueries of a UNION set-operation tree.

Walks node (a SetOperationStmt tree); every internal node must be a SETOP_UNION (UNION or UNION ALL – both compute the same Boolean existence), and every leaf a RangeTblRef to an RTE_SUBQUERY arm. Appends each arm Query* to arms. Returns false to decline (INTERSECT / EXCEPT, or an unexpected leaf).

Definition at line 420 of file joint_width_query.c.

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

◆ colref_get()

int colref_get ( ColRef * cols,
int * ncols,
Index rtindex,
AttrNumber attno )
static

Find-or-add a (rtindex, attno) column node; returns its index.

Definition at line 36 of file joint_width_query.c.

Here is the caller graph for this function:

◆ cq_is_existential()

bool cq_is_existential ( Query * cq,
Index * atom_rti,
int natoms )
static

Does cq expose no tracked-atom variable in its target list (i.e.

it computes the Boolean existence of its CQ)?

atom_rti / natoms describe the tracked range-table entries of cq (as collected by collect_jointree).

Definition at line 223 of file joint_width_query.c.

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

◆ emit_cq_disjunct()

bool emit_cq_disjunct ( const constants_t * constants,
Query * cq,
RelMerge * m,
StringInfo dbuf,
const int * head_resno,
int n_heads )
static

Extract one conjunctive query (a flat join over tracked base relations) as a UCQ disjunct, appending its {"n_vars":N,"atoms":[...]} object to dbuf and registering its relations in m (so atom "rel" indices are global).

The per-disjunct variable space is local (variables 0..N-1 of this disjunct); the element dictionary that binds them to data values is shared across the whole UCQ by the gather.

head_resno (length n_heads) gives the arm output-column positions (1-based resno, aligned across the UNION's arms) of the per-answer head variables, in head order. Each is numbered CANONICALLY – head h becomes query variable h in every arm – so a single head_vars = [0,1,…] pins the head in every disjunct (the SQL ucq_joint_provenance_answer uses one head-variable index across all disjuncts). With n_heads == 0 the arm must be Boolean-existential. Returns false to decline.

Definition at line 260 of file joint_width_query.c.

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

◆ exist_walker()

bool exist_walker ( Node * node,
void * vctx )
static

Definition at line 131 of file joint_width_query.c.

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

◆ provsql_joint_width_descriptor()

char * provsql_joint_width_descriptor ( const constants_t * constants,
Query * q,
bool * all_existential,
List ** head_var_idx,
List ** head_exprs )

Build the joint-width descriptor for a recognised UCQ.

Recognises a conjunctive query over provenance-tracked base relations: a flat FROM list (or inner JOIN ... ON tree) of tracked RTE_RELATION entries, a WHERE that is a conjunction of equalities, no HAVING / window functions / sublinks / aggregates other than the provenance aggregation. The variable structure is the column equivalence relation induced by the Var = Var join equalities; a Var = Const selection pins that variable to the literal (the same Sel mechanism as a head). The per-answer heads are the GROUP BY keys (bare tracked columns); the SELECT list itself is arbitrary (a function of the keys), so what is displayed does not constrain recognition.

A UNION [ALL] of such conjunctive queries (the body of an aggregated subquery) is recognised as a genuine multi-disjunct UCQ: one disjunct per arm, relations merged across the arms. Both the Boolean existence and the per-answer form (a free-variable head exposed by every arm and grouped by the outer query) are handled; the head is numbered canonically so a single Sel-pin forces it across all disjuncts.

Parameters
constantsCached extension OIDs.
qThe parsed query (read-only).
all_existentialOutput: set to true iff no variable of the UCQ is exposed in the target list (the query computes the Boolean existence of the UCQ – the #P-hard case the substitution targets); false when output/grouped variables remain (a per-answer query).
head_var_idxOutput (may be NULL): when the query is per-answer and every exposed target column is a bare integer Var over a tracked atom, the List of the head variables' query-variable indices (Integer nodes), in output order, deduplicated; NIL if the heads cannot be cleanly extracted (the per-answer substitution then declines).
head_exprsOutput (may be NULL): parallel List of the target Var Expr exposing each head variable (the per-group head value at execution).
Returns
A palloc'd JSON descriptor string (the shape ucq_joint_provenance expects), or NULL when q is outside the recogniser's scope.

Definition at line 559 of file joint_width_query.c.

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

◆ relmerge_get()

int relmerge_get ( RelMerge * m,
Oid oid,
List * colnames )
static

Find-or-add a relation; returns its global index.

Definition at line 205 of file joint_width_query.c.

Here is the caller graph for this function:

◆ uf_find()

int uf_find ( ColRef * cols,
int i )
static

Union-find root with path halving.

Definition at line 49 of file joint_width_query.c.

Here is the caller graph for this function:

◆ uf_union()

void uf_union ( ColRef * cols,
int a,
int b )
static

Definition at line 58 of file joint_width_query.c.

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

◆ union_position_kind()

int union_position_kind ( Query * unionq,
int resno )
static

Classify a UNION output column (1-based resno): is it a per-answer head or a constant projection?

Returns
1 if every arm exposes a bare Var over a tracked base relation there (a real head, pinnable), 0 if every arm exposes a constant / non-tracked expression there (a Boolean projection like SELECT 1, to be ignored), -1 on a mixed or malformed column (the recogniser then declines).

Definition at line 452 of file joint_width_query.c.

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