Veil2
Postgres extension for VPD implementations
query.c
Go to the documentation of this file.
1 
15 #include <stdio.h>
16 #include "postgres.h"
17 #include "catalog/pg_type.h"
18 #include "executor/spi.h"
19 #include "access/xact.h"
20 #include "veil2.h"
21 
22 
37 void
38 veil2_spi_connect(bool *p_pushed, const char *msg)
39 {
40  int result = SPI_connect();
41  if (result == SPI_ERROR_CONNECT) {
42  SPI_push();
43  *p_pushed = true;
44  result = SPI_connect();
45  }
46  else {
47  *p_pushed = false;
48  }
49  if (result != SPI_OK_CONNECT) {
50  ereport(ERROR,
51  (errcode(ERRCODE_INTERNAL_ERROR),
52  errmsg("%s", msg),
53  errdetail("SPI_connect() failed, returning %d.", result)));
54  }
55 }
56 
65 void
66 veil2_spi_finish(bool pushed, const char *msg)
67 {
68  int spi_result = SPI_finish();
69  if (pushed) {
70  SPI_pop();
71  }
72  if (spi_result != SPI_OK_FINISH) {
73  ereport(ERROR,
74  (errcode(ERRCODE_INTERNAL_ERROR),
75  errmsg("%s", msg),
76  errdetail("SPI_finish() failed, returning %d.", spi_result)));
77  }
78 }
79 
100 static void
101 prepare_query(const char *qry,
102  int nargs,
103  Oid *argtypes,
104  Datum *args,
105  const char *nulls,
106  bool read_only,
107  void **saved_plan)
108 {
109  void *plan;
110  int exec_result;
111 
112  if (saved_plan && *saved_plan) {
113  /* A previously prepared plan is available, so use it */
114  plan = *saved_plan;
115  }
116  else {
117  if (!(plan = SPI_prepare(qry, nargs, argtypes))) {
118  ereport(ERROR,
119  (errcode(ERRCODE_INTERNAL_ERROR),
120  errmsg("prepare_query fails"),
121  errdetail("SPI_prepare('%s') returns NULL "
122  "(SPI_result = %d)",
123  qry, SPI_result)));
124  }
125 
126  if (saved_plan) {
127  /* We have somewhere to put the saved plan, so save it. */
128  *saved_plan = SPI_saveplan(plan);
129  }
130  }
131 
132  exec_result = SPI_execute_plan(plan, args, nulls, read_only, 0);
133  if (exec_result < 0) {
134  ereport(ERROR,
135  (errcode(ERRCODE_INTERNAL_ERROR),
136  errmsg("prepare_query fails"),
137  errdetail("SPI_execute_plan('%s') returns error %d",
138  qry, exec_result)));
139  }
140 }
141 
164 int
165 veil2_query_wn(const char *qry,
166  int nargs,
167  Oid *argtypes,
168  Datum *args,
169  const char *nulls,
170  bool read_only,
171  void **saved_plan,
172  Fetch_fn process_row,
173  void *fn_param)
174 {
175  int row;
176  int fetched;
177  int processed = 0;
178  bool cntinue;
179  SPITupleTable *tuptab;
180 
181  prepare_query(qry, nargs, argtypes, args, nulls, read_only, saved_plan);
182  fetched = SPI_processed;
183  tuptab = SPI_tuptable;
184  if (process_row) {
185  for(row = 0; row < fetched; row++) {
186  processed++;
187  /* Process a row using the processor function */
188  cntinue = process_row(tuptab->vals[row],
189  tuptab->tupdesc,
190  fn_param);
191  if (!cntinue) {
192  break;
193  }
194  }
195  }
196  return processed;
197 }
198 
217 int
218 veil2_query(const char *qry,
219  int nargs,
220  Oid *argtypes,
221  Datum *args,
222  bool read_only,
223  void **saved_plan,
224  Fetch_fn process_row,
225  void *fn_param)
226 {
227  return veil2_query_wn(qry, nargs, argtypes, args, NULL,
228  read_only, saved_plan, process_row, fn_param);
229 }
230 
241 static bool
242 fetch_one_bool(HeapTuple tuple, TupleDesc tupdesc, void *p_result)
243 {
244  bool is_null = false;
245  bool col = DatumGetBool(SPI_getbinval(tuple, tupdesc, 1, &is_null));
246  *((bool *) p_result) = col;
247 
248  return false;
249 }
250 
266 bool
267 veil2_bool_from_query(const char *qry,
268  int nargs,
269  Oid *argtypes,
270  Datum *args,
271  void **saved_plan,
272  bool *result)
273 {
274  int rows;
275  rows = veil2_query(qry, nargs, argtypes, args, false, saved_plan,
276  fetch_one_bool, (void *) result);
277  return (rows > 0);
278 }
279 
static bool fetch_one_bool(HeapTuple tuple, TupleDesc tupdesc, void *p_result)
Definition: query.c:242
static void prepare_query(const char *qry, int nargs, Oid *argtypes, Datum *args, const char *nulls, bool read_only, void **saved_plan)
Definition: query.c:101
Main header file for veil2.
void veil2_spi_finish(bool pushed, const char *msg)
Definition: query.c:66
int veil2_query_wn(const char *qry, int nargs, Oid *argtypes, Datum *args, const char *nulls, bool read_only, void **saved_plan, Fetch_fn process_row, void *fn_param)
Definition: query.c:165
bool() Fetch_fn(HeapTuple, TupleDesc, void *)
Definition: veil2.h:20
bool veil2_bool_from_query(const char *qry, int nargs, Oid *argtypes, Datum *args, void **saved_plan, bool *result)
Definition: query.c:267
int veil2_query(const char *qry, int nargs, Oid *argtypes, Datum *args, bool read_only, void **saved_plan, Fetch_fn process_row, void *fn_param)
Definition: query.c:218
void veil2_spi_connect(bool *p_pushed, const char *msg)
Definition: query.c:38