ProvSQL C/C++ API
Adding support for provenance and uncertainty management to PostgreSQL databases
Loading...
Searching...
No Matches
safe_query_cert.c
Go to the documentation of this file.
1/**
2 * @file safe_query_cert.c
3 * @brief Serialise / parse for the inversion-free tractability certificate.
4 *
5 * The recipe travels from the planner (which builds it in @c safe_query.c) to
6 * the evaluator (@c probability_evaluate.cpp) as the @c extra string of the
7 * annotation gate wrapping the provenance root. The wire format is a compact,
8 * space-separated list of integers, prefixed by @c SAFE_CERT_EXTRA_PREFIX_RECIPE
9 * ('C') so a consumer can tell a recipe apart from a per-input order key ('K'):
10 *
11 * C kind nclasses root_class natoms maxarity
12 * <class_topo_order[0..nclasses-1]>
13 * <atom_relation_rank[0..natoms-1]>
14 * <atom_col_class[0..natoms*maxarity-1]>
15 *
16 * A per-input order key uses the sibling @c SAFE_CERT_EXTRA_PREFIX_KEY ('K')
17 * form @c "K<factor> <root_len>:<root><sec_len>:<sec>", length-prefixed so the
18 * class values may be arbitrary text (see @c safe_cert_key_serialise).
19 *
20 * All functions are pure (no SPI / no catalog access) so the parsers are safe
21 * to call from the C++ evaluation side.
22 */
23#include "postgres.h"
24#include "lib/stringinfo.h"
25#include "utils/palloc.h"
26
27#include "safe_query_cert.h"
28
29#include <stdlib.h>
30#include <string.h>
31
32char *safe_cert_serialise(const SafeCert *cert)
33{
34 StringInfoData s;
35 int i, ncol;
36
37 if (cert == NULL)
38 return NULL;
39
40 initStringInfo(&s);
41 appendStringInfoChar(&s, SAFE_CERT_EXTRA_PREFIX_RECIPE);
42 appendStringInfo(&s, "%d %d %d %d %d",
43 (int) cert->kind, cert->nclasses, cert->root_class,
44 cert->natoms, cert->maxarity);
45 for (i = 0; i < cert->nclasses; i++)
46 appendStringInfo(&s, " %d", cert->class_topo_order[i]);
47 for (i = 0; i < cert->natoms; i++)
48 appendStringInfo(&s, " %d", cert->atom_relation_rank[i]);
49 ncol = cert->natoms * cert->maxarity;
50 for (i = 0; i < ncol; i++)
51 appendStringInfo(&s, " %d", cert->atom_col_class[i]);
52 return s.data;
53}
54
55SafeCert *safe_cert_parse(const char *str)
56{
57 const char *p;
58 char *end;
59 SafeCert *cert;
60 int i, ncol;
61 long v;
62
63 if (str == NULL || str[0] != SAFE_CERT_EXTRA_PREFIX_RECIPE)
64 return NULL;
65
66 p = str + 1;
67 cert = (SafeCert *) palloc0(sizeof(SafeCert));
68
69 /* helper: read the next integer, bailing (return NULL) on malformed input */
70#define READ_INT(dst) \
71 do { \
72 v = strtol(p, &end, 10); \
73 if (end == p) { pfree(cert); return NULL; } \
74 (dst) = (int) v; \
75 p = end; \
76 } while (0)
77
78 {
79 int kind;
80 READ_INT(kind);
81 cert->kind = (SafeCertKind) kind;
82 READ_INT(cert->nclasses);
83 READ_INT(cert->root_class);
84 READ_INT(cert->natoms);
85 READ_INT(cert->maxarity);
86 }
87
88 if (cert->nclasses < 0 || cert->natoms < 0 || cert->maxarity < 0) {
89 pfree(cert);
90 return NULL;
91 }
92
93 cert->class_topo_order = (int *) palloc(sizeof(int) * (cert->nclasses > 0 ? cert->nclasses : 1));
94 for (i = 0; i < cert->nclasses; i++)
95 READ_INT(cert->class_topo_order[i]);
96
97 cert->atom_relation_rank = (int *) palloc(sizeof(int) * (cert->natoms > 0 ? cert->natoms : 1));
98 for (i = 0; i < cert->natoms; i++)
100
101 ncol = cert->natoms * cert->maxarity;
102 cert->atom_col_class = (int *) palloc(sizeof(int) * (ncol > 0 ? ncol : 1));
103 for (i = 0; i < ncol; i++)
104 READ_INT(cert->atom_col_class[i]);
105
106#undef READ_INT
107
108 return cert;
109}
110
111char *safe_cert_key_serialise(const char *root, size_t root_len,
112 const char *sec, size_t sec_len, int factor)
113{
114 StringInfoData s;
115 initStringInfo(&s);
116 appendStringInfoChar(&s, SAFE_CERT_EXTRA_PREFIX_KEY);
117 appendStringInfo(&s, "%d %zu:", factor, root_len);
118 appendBinaryStringInfo(&s, root, (int) root_len);
119 appendStringInfo(&s, "%zu:", sec_len);
120 appendBinaryStringInfo(&s, sec, (int) sec_len);
121 return s.data;
122}
123
124bool safe_cert_key_parse(const char *str, SafeCertKey *out)
125{
126 const char *p, *limit;
127 char *end;
128 SafeCertKey k;
129 long n;
130
131 if (str == NULL || str[0] != SAFE_CERT_EXTRA_PREFIX_KEY)
132 return false;
133
134 p = str + 1;
135 limit = p + strlen(p);
136
137 /* factor, then a single separating space */
138 k.factor = (int) strtol(p, &end, 10);
139 if (end == p || *end != ' ') return false;
140 p = end + 1;
141
142 /* root: <byte-length>:<bytes> */
143 n = strtol(p, &end, 10);
144 if (end == p || n < 0 || *end != ':') return false;
145 p = end + 1;
146 if ((size_t)(limit - p) < (size_t) n) return false;
147 k.root = p;
148 k.root_len = (size_t) n;
149 p += n;
150
151 /* sec: <byte-length>:<bytes> */
152 n = strtol(p, &end, 10);
153 if (end == p || n < 0 || *end != ':') return false;
154 p = end + 1;
155 if ((size_t)(limit - p) < (size_t) n) return false;
156 k.sec = p;
157 k.sec_len = (size_t) n;
158
159 if (out != NULL)
160 *out = k;
161 return true;
162}
char * safe_cert_key_serialise(const char *root, size_t root_len, const char *sec, size_t sec_len, int factor)
Serialise a per-input order key to a compact K-prefixed string (palloc'd).
SafeCert * safe_cert_parse(const char *str)
Parse a C-prefixed recipe string (as produced by safe_cert_serialise and read back from an annotation...
char * safe_cert_serialise(const SafeCert *cert)
Serialise a SafeCert recipe to a compact, C-prefixed string (palloc'd in the current memory context).
#define READ_INT(dst)
bool safe_cert_key_parse(const char *str, SafeCertKey *out)
Parse a K-prefixed order-key string into out.
Tractability certificate for the inversion-free UCQ(OBDD) path.
SafeCertKind
Kind of tractability certificate carried on the provenance root.
#define SAFE_CERT_EXTRA_PREFIX_KEY
Input: per-variable order key.
#define SAFE_CERT_EXTRA_PREFIX_RECIPE
Discriminator prefixes for the annotation gate's extra payload.
const char * sec
const char * root
Query-derived order recipe for the structured-d-DNNF builder.
int nclasses
Number of (compacted) equivalence classes.
int * atom_col_class
Flattened [natoms][maxarity]: compacted class anchored at (atom, column), or -1.
int root_class
Compacted id of the root class (touches every atom).
int natoms
Number of atoms (range-table entries).
SafeCertKind kind
int maxarity
Stride of atom_col_class (max columns per atom seen).
int * class_topo_order
Length nclasses: classes in G_prec topological order, root first.
int * atom_relation_rank
Length natoms: relation-symbol tie-break rank per atom.