00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <stdio.h>
00017 #include "postgres.h"
00018 #include "catalog/pg_type.h"
00019 #include "executor/spi.h"
00020 #include "veil_version.h"
00021 #include "access/xact.h"
00022 #include "veil_funcs.h"
00023
00024
00025
00026
00027
00028 typedef bool (Fetch_fn)(HeapTuple, TupleDesc, void *);
00029
00030
00031
00032
00033
00034
00035 #define FETCH_SIZE 20
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 int
00046 vl_spi_connect(bool *p_pushed)
00047 {
00048 int result = SPI_connect();
00049 if (result == SPI_ERROR_CONNECT) {
00050 SPI_push();
00051 *p_pushed = TRUE;
00052 return SPI_connect();
00053 }
00054 *p_pushed = FALSE;
00055 return result;
00056 }
00057
00058
00059
00060
00061 int
00062 vl_spi_finish(bool pushed)
00063 {
00064 int spi_result = SPI_finish();
00065 if (pushed) {
00066 SPI_pop();
00067 }
00068 return spi_result;
00069 }
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 static void
00086 prepare_query(const char *qry,
00087 int nargs,
00088 Oid *argtypes,
00089 Datum *args,
00090 bool read_only,
00091 void **saved_plan)
00092 {
00093 void *plan;
00094 int exec_result;
00095
00096 if (saved_plan && *saved_plan) {
00097
00098 plan = *saved_plan;
00099 }
00100 else {
00101 if (!(plan = SPI_prepare(qry, nargs, argtypes))) {
00102 ereport(ERROR,
00103 (errcode(ERRCODE_INTERNAL_ERROR),
00104 errmsg("prepare_query fails"),
00105 errdetail("SPI_prepare('%s') returns NULL "
00106 "(SPI_result = %d)",
00107 qry, SPI_result)));
00108 }
00109
00110 if (saved_plan) {
00111
00112 *saved_plan = SPI_saveplan(plan);
00113 }
00114 }
00115
00116 exec_result = SPI_execute_plan(plan, args, NULL, read_only, 0);
00117 if (exec_result < 0) {
00118 ereport(ERROR,
00119 (errcode(ERRCODE_INTERNAL_ERROR),
00120 errmsg("prepare_query fails"),
00121 errdetail("SPI_execute_plan('%s') returns error %d",
00122 qry, exec_result)));
00123 }
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 static int
00151 query(const char *qry,
00152 int nargs,
00153 Oid *argtypes,
00154 Datum *args,
00155 bool read_only,
00156 void **saved_plan,
00157 Fetch_fn process_row,
00158 void *fn_param)
00159 {
00160 int row;
00161 int fetched;
00162 int processed = 0;
00163 bool cntinue;
00164 SPITupleTable *tuptab;
00165
00166 prepare_query(qry, nargs, argtypes, args, read_only, saved_plan);
00167 fetched = SPI_processed;
00168 tuptab = SPI_tuptable;
00169 for(row = 0; row < fetched; row++) {
00170 processed++;
00171
00172 cntinue = process_row(tuptab->vals[row],
00173 tuptab->tupdesc,
00174 fn_param);
00175 if (!cntinue) {
00176 break;
00177 }
00178 }
00179 return processed;
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 static bool
00194 fetch_one_bool(HeapTuple tuple, TupleDesc tupdesc, void *p_result)
00195 {
00196 static bool ignore_this = false;
00197 bool col = DatumGetBool(SPI_getbinval(tuple, tupdesc, 1, &ignore_this));
00198 *((bool *) p_result) = col;
00199
00200 return false;
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 static bool
00214 fetch_one_str(HeapTuple tuple, TupleDesc tupdesc, void *p_result)
00215 {
00216 char *col = SPI_getvalue(tuple, tupdesc, 1);
00217 char **p_str = (char **) p_result;
00218 *p_str = col;
00219
00220 return false;
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 bool
00232 vl_bool_from_query(const char *qry,
00233 bool *result)
00234 {
00235 int rows;
00236 Oid argtypes[0];
00237 Datum args[0];
00238 rows = query(qry, 0, argtypes, args, false, NULL,
00239 fetch_one_bool, (void *)result);
00240 return (rows > 0);
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 static bool
00253 str_from_oid_query(const char *qry,
00254 const Oid param,
00255 char *result)
00256 {
00257 int rows;
00258 Oid argtypes[1] = {OIDOID};
00259 Datum args[1];
00260
00261 args[0] = ObjectIdGetDatum(param);
00262 rows = query(qry, 1, argtypes, args, false, NULL,
00263 fetch_one_str, (void *)result);
00264 return (rows > 0);
00265 }
00266
00267
00268
00269
00270
00271
00272
00273
00274 extern bool
00275 vl_db_exists(Oid db_id)
00276 {
00277 char dbname[NAMEDATALEN + 1];
00278
00279 return str_from_oid_query("select datname from pg_database where oid = $1",
00280 db_id, dbname);
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 static bool
00294 exec_init_fn(HeapTuple tuple, TupleDesc tupdesc, void *p_param)
00295 {
00296 char *col = SPI_getvalue(tuple, tupdesc, 1);
00297 char *qry = palloc(strlen(col) + 15);
00298 bool pushed;
00299 bool result;
00300 bool found;
00301 int ok;
00302
00303 (void) sprintf(qry, "select %s(%s)", col,
00304 *((bool *) p_param)? "true": "false");
00305
00306 ok = vl_spi_connect(&pushed);
00307 if (ok != SPI_OK_CONNECT) {
00308 ereport(ERROR,
00309 (errcode(ERRCODE_INTERNAL_ERROR),
00310 errmsg("failed to execute exec_init_fn() (1)"),
00311 errdetail("SPI_connect() failed, returning %d.", ok)));
00312 }
00313
00314 found = vl_bool_from_query(qry, &result);
00315
00316
00317 ok = vl_spi_finish(pushed);
00318 if (ok != SPI_OK_FINISH) {
00319 ereport(ERROR,
00320 (errcode(ERRCODE_INTERNAL_ERROR),
00321 errmsg("failed to execute exec_init_fn() (2)"),
00322 errdetail("SPI_finish() failed, returning %d.", ok)));
00323 }
00324
00325 return true;
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 int
00337 vl_call_init_fns(bool param)
00338 {
00339 Oid argtypes[0];
00340 Datum args[0];
00341 char *qry = "select fn_name from veil.veil_init_fns order by priority";
00342 bool pushed;
00343 int rows;
00344 int ok;
00345
00346 ok = vl_spi_connect(&pushed);
00347 if (ok != SPI_OK_CONNECT) {
00348 ereport(ERROR,
00349 (errcode(ERRCODE_INTERNAL_ERROR),
00350 errmsg("failed to execute vl_call_init_fns() (1)"),
00351 errdetail("SPI_connect() failed, returning %d.", ok)));
00352 }
00353
00354 rows = query(qry, 0, argtypes, args, false, NULL,
00355 exec_init_fn, (void *) ¶m);
00356
00357 ok = vl_spi_finish(pushed);
00358 if (ok != SPI_OK_FINISH) {
00359 ereport(ERROR,
00360 (errcode(ERRCODE_INTERNAL_ERROR),
00361 errmsg("failed to execute vl_call_init_fns() (2)"),
00362 errdetail("SPI_finish() failed, returning %d.", ok)));
00363 }
00364 return rows;
00365 }