00001
00002
00003
00004
00005
00006
00007 #include "postgres.h"
00008
00009 #include "mb/pg_wchar.h"
00010 #include "utils/builtins.h"
00011
00012 #include "plpython.h"
00013
00014 #include "plpy_plpymodule.h"
00015
00016 #include "plpy_cursorobject.h"
00017 #include "plpy_elog.h"
00018 #include "plpy_planobject.h"
00019 #include "plpy_resultobject.h"
00020 #include "plpy_spi.h"
00021 #include "plpy_subxactobject.h"
00022
00023
00024 HTAB *PLy_spi_exceptions = NULL;
00025
00026
00027 static void PLy_add_exceptions(PyObject *plpy);
00028 static void PLy_generate_spi_exceptions(PyObject *mod, PyObject *base);
00029
00030
00031 static PyObject *PLy_debug(PyObject *self, PyObject *args);
00032 static PyObject *PLy_log(PyObject *self, PyObject *args);
00033 static PyObject *PLy_info(PyObject *self, PyObject *args);
00034 static PyObject *PLy_notice(PyObject *self, PyObject *args);
00035 static PyObject *PLy_warning(PyObject *self, PyObject *args);
00036 static PyObject *PLy_error(PyObject *self, PyObject *args);
00037 static PyObject *PLy_fatal(PyObject *self, PyObject *args);
00038 static PyObject *PLy_quote_literal(PyObject *self, PyObject *args);
00039 static PyObject *PLy_quote_nullable(PyObject *self, PyObject *args);
00040 static PyObject *PLy_quote_ident(PyObject *self, PyObject *args);
00041
00042
00043
00044 typedef struct ExceptionMap
00045 {
00046 char *name;
00047 char *classname;
00048 int sqlstate;
00049 } ExceptionMap;
00050
00051 static const ExceptionMap exception_map[] = {
00052 #include "spiexceptions.h"
00053 {NULL, NULL, 0}
00054 };
00055
00056 static PyMethodDef PLy_methods[] = {
00057
00058
00059
00060 {"debug", PLy_debug, METH_VARARGS, NULL},
00061 {"log", PLy_log, METH_VARARGS, NULL},
00062 {"info", PLy_info, METH_VARARGS, NULL},
00063 {"notice", PLy_notice, METH_VARARGS, NULL},
00064 {"warning", PLy_warning, METH_VARARGS, NULL},
00065 {"error", PLy_error, METH_VARARGS, NULL},
00066 {"fatal", PLy_fatal, METH_VARARGS, NULL},
00067
00068
00069
00070
00071 {"prepare", PLy_spi_prepare, METH_VARARGS, NULL},
00072
00073
00074
00075
00076 {"execute", PLy_spi_execute, METH_VARARGS, NULL},
00077
00078
00079
00080
00081 {"quote_literal", PLy_quote_literal, METH_VARARGS, NULL},
00082 {"quote_nullable", PLy_quote_nullable, METH_VARARGS, NULL},
00083 {"quote_ident", PLy_quote_ident, METH_VARARGS, NULL},
00084
00085
00086
00087
00088 {"subtransaction", PLy_subtransaction_new, METH_NOARGS, NULL},
00089
00090
00091
00092
00093 {"cursor", PLy_cursor, METH_VARARGS, NULL},
00094
00095 {NULL, NULL, 0, NULL}
00096 };
00097
00098 static PyMethodDef PLy_exc_methods[] = {
00099 {NULL, NULL, 0, NULL}
00100 };
00101
00102 #if PY_MAJOR_VERSION >= 3
00103 static PyModuleDef PLy_module = {
00104 PyModuleDef_HEAD_INIT,
00105 "plpy",
00106 NULL,
00107 -1,
00108 PLy_methods,
00109 };
00110
00111 static PyModuleDef PLy_exc_module = {
00112 PyModuleDef_HEAD_INIT,
00113 "spiexceptions",
00114 NULL,
00115 -1,
00116 PLy_exc_methods,
00117 NULL,
00118 NULL,
00119 NULL,
00120 NULL
00121 };
00122
00123
00124
00125
00126
00127 PyMODINIT_FUNC
00128 PyInit_plpy(void)
00129 {
00130 PyObject *m;
00131
00132 m = PyModule_Create(&PLy_module);
00133 if (m == NULL)
00134 return NULL;
00135
00136 PLy_add_exceptions(m);
00137
00138 return m;
00139 }
00140 #endif
00141
00142 void
00143 PLy_init_plpy(void)
00144 {
00145 PyObject *main_mod,
00146 *main_dict,
00147 *plpy_mod;
00148
00149 #if PY_MAJOR_VERSION < 3
00150 PyObject *plpy;
00151 #endif
00152
00153
00154
00155
00156 PLy_plan_init_type();
00157 PLy_result_init_type();
00158 PLy_subtransaction_init_type();
00159 PLy_cursor_init_type();
00160
00161 #if PY_MAJOR_VERSION >= 3
00162 PyModule_Create(&PLy_module);
00163
00164 #else
00165 plpy = Py_InitModule("plpy", PLy_methods);
00166 PLy_add_exceptions(plpy);
00167 #endif
00168
00169
00170
00171
00172
00173
00174 main_mod = PyImport_AddModule("__main__");
00175 main_dict = PyModule_GetDict(main_mod);
00176 plpy_mod = PyImport_AddModule("plpy");
00177 if (plpy_mod == NULL)
00178 PLy_elog(ERROR, "could not import \"plpy\" module");
00179 PyDict_SetItemString(main_dict, "plpy", plpy_mod);
00180 if (PyErr_Occurred())
00181 PLy_elog(ERROR, "could not import \"plpy\" module");
00182 }
00183
00184 static void
00185 PLy_add_exceptions(PyObject *plpy)
00186 {
00187 PyObject *excmod;
00188 HASHCTL hash_ctl;
00189
00190 #if PY_MAJOR_VERSION < 3
00191 excmod = Py_InitModule("spiexceptions", PLy_exc_methods);
00192 #else
00193 excmod = PyModule_Create(&PLy_exc_module);
00194 #endif
00195 if (PyModule_AddObject(plpy, "spiexceptions", excmod) < 0)
00196 PLy_elog(ERROR, "could not add the spiexceptions module");
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 Py_INCREF(excmod);
00209
00210 PLy_exc_error = PyErr_NewException("plpy.Error", NULL, NULL);
00211 PLy_exc_fatal = PyErr_NewException("plpy.Fatal", NULL, NULL);
00212 PLy_exc_spi_error = PyErr_NewException("plpy.SPIError", NULL, NULL);
00213
00214 if (PLy_exc_error == NULL ||
00215 PLy_exc_fatal == NULL ||
00216 PLy_exc_spi_error == NULL)
00217 PLy_elog(ERROR, "could not create the base SPI exceptions");
00218
00219 Py_INCREF(PLy_exc_error);
00220 PyModule_AddObject(plpy, "Error", PLy_exc_error);
00221 Py_INCREF(PLy_exc_fatal);
00222 PyModule_AddObject(plpy, "Fatal", PLy_exc_fatal);
00223 Py_INCREF(PLy_exc_spi_error);
00224 PyModule_AddObject(plpy, "SPIError", PLy_exc_spi_error);
00225
00226 memset(&hash_ctl, 0, sizeof(hash_ctl));
00227 hash_ctl.keysize = sizeof(int);
00228 hash_ctl.entrysize = sizeof(PLyExceptionEntry);
00229 hash_ctl.hash = tag_hash;
00230 PLy_spi_exceptions = hash_create("SPI exceptions", 256,
00231 &hash_ctl, HASH_ELEM | HASH_FUNCTION);
00232
00233 PLy_generate_spi_exceptions(excmod, PLy_exc_spi_error);
00234 }
00235
00236
00237
00238
00239 static void
00240 PLy_generate_spi_exceptions(PyObject *mod, PyObject *base)
00241 {
00242 int i;
00243
00244 for (i = 0; exception_map[i].name != NULL; i++)
00245 {
00246 bool found;
00247 PyObject *exc;
00248 PLyExceptionEntry *entry;
00249 PyObject *sqlstate;
00250 PyObject *dict = PyDict_New();
00251
00252 if (dict == NULL)
00253 PLy_elog(ERROR, "could not generate SPI exceptions");
00254
00255 sqlstate = PyString_FromString(unpack_sql_state(exception_map[i].sqlstate));
00256 if (sqlstate == NULL)
00257 PLy_elog(ERROR, "could not generate SPI exceptions");
00258
00259 PyDict_SetItemString(dict, "sqlstate", sqlstate);
00260 Py_DECREF(sqlstate);
00261 exc = PyErr_NewException(exception_map[i].name, base, dict);
00262 PyModule_AddObject(mod, exception_map[i].classname, exc);
00263 entry = hash_search(PLy_spi_exceptions, &exception_map[i].sqlstate,
00264 HASH_ENTER, &found);
00265 entry->exc = exc;
00266 Assert(!found);
00267 }
00268 }
00269
00270
00271
00272
00273
00274
00275 static PyObject *PLy_output(volatile int, PyObject *, PyObject *);
00276
00277 PyObject *
00278 PLy_debug(PyObject *self, PyObject *args)
00279 {
00280 return PLy_output(DEBUG2, self, args);
00281 }
00282
00283 PyObject *
00284 PLy_log(PyObject *self, PyObject *args)
00285 {
00286 return PLy_output(LOG, self, args);
00287 }
00288
00289 PyObject *
00290 PLy_info(PyObject *self, PyObject *args)
00291 {
00292 return PLy_output(INFO, self, args);
00293 }
00294
00295 PyObject *
00296 PLy_notice(PyObject *self, PyObject *args)
00297 {
00298 return PLy_output(NOTICE, self, args);
00299 }
00300
00301 PyObject *
00302 PLy_warning(PyObject *self, PyObject *args)
00303 {
00304 return PLy_output(WARNING, self, args);
00305 }
00306
00307 PyObject *
00308 PLy_error(PyObject *self, PyObject *args)
00309 {
00310 return PLy_output(ERROR, self, args);
00311 }
00312
00313 PyObject *
00314 PLy_fatal(PyObject *self, PyObject *args)
00315 {
00316 return PLy_output(FATAL, self, args);
00317 }
00318
00319 PyObject *
00320 PLy_quote_literal(PyObject *self, PyObject *args)
00321 {
00322 const char *str;
00323 char *quoted;
00324 PyObject *ret;
00325
00326 if (!PyArg_ParseTuple(args, "s", &str))
00327 return NULL;
00328
00329 quoted = quote_literal_cstr(str);
00330 ret = PyString_FromString(quoted);
00331 pfree(quoted);
00332
00333 return ret;
00334 }
00335
00336 PyObject *
00337 PLy_quote_nullable(PyObject *self, PyObject *args)
00338 {
00339 const char *str;
00340 char *quoted;
00341 PyObject *ret;
00342
00343 if (!PyArg_ParseTuple(args, "z", &str))
00344 return NULL;
00345
00346 if (str == NULL)
00347 return PyString_FromString("NULL");
00348
00349 quoted = quote_literal_cstr(str);
00350 ret = PyString_FromString(quoted);
00351 pfree(quoted);
00352
00353 return ret;
00354 }
00355
00356 PyObject *
00357 PLy_quote_ident(PyObject *self, PyObject *args)
00358 {
00359 const char *str;
00360 const char *quoted;
00361 PyObject *ret;
00362
00363 if (!PyArg_ParseTuple(args, "s", &str))
00364 return NULL;
00365
00366 quoted = quote_identifier(str);
00367 ret = PyString_FromString(quoted);
00368
00369 return ret;
00370 }
00371
00372 static PyObject *
00373 PLy_output(volatile int level, PyObject *self, PyObject *args)
00374 {
00375 PyObject *volatile so;
00376 char *volatile sv;
00377 volatile MemoryContext oldcontext;
00378
00379 if (PyTuple_Size(args) == 1)
00380 {
00381
00382
00383
00384
00385 PyObject *o;
00386
00387 if (!PyArg_UnpackTuple(args, "plpy.elog", 1, 1, &o))
00388 PLy_elog(ERROR, "could not unpack arguments in plpy.elog");
00389 so = PyObject_Str(o);
00390 }
00391 else
00392 so = PyObject_Str(args);
00393 if (so == NULL || ((sv = PyString_AsString(so)) == NULL))
00394 {
00395 level = ERROR;
00396 sv = dgettext(TEXTDOMAIN, "could not parse error message in plpy.elog");
00397 }
00398
00399 oldcontext = CurrentMemoryContext;
00400 PG_TRY();
00401 {
00402 pg_verifymbstr(sv, strlen(sv), false);
00403 elog(level, "%s", sv);
00404 }
00405 PG_CATCH();
00406 {
00407 ErrorData *edata;
00408
00409 MemoryContextSwitchTo(oldcontext);
00410 edata = CopyErrorData();
00411 FlushErrorState();
00412
00413
00414
00415
00416
00417 Py_XDECREF(so);
00418
00419
00420 PLy_exception_set(PLy_exc_error, "%s", edata->message);
00421 return NULL;
00422 }
00423 PG_END_TRY();
00424
00425 Py_XDECREF(so);
00426
00427
00428
00429
00430 Py_INCREF(Py_None);
00431 return Py_None;
00432 }