Age Owner Branch data TLA Line data Source code
1 : : /*
2 : : * the plpy module
3 : : *
4 : : * src/pl/plpython/plpy_plpymodule.c
5 : : */
6 : :
7 : : #include "postgres.h"
8 : :
9 : : #include "mb/pg_wchar.h"
10 : : #include "plpy_cursorobject.h"
11 : : #include "plpy_elog.h"
12 : : #include "plpy_planobject.h"
13 : : #include "plpy_plpymodule.h"
14 : : #include "plpy_resultobject.h"
15 : : #include "plpy_spi.h"
16 : : #include "plpy_subxactobject.h"
17 : : #include "plpy_util.h"
18 : : #include "utils/builtins.h"
19 : :
20 : : HTAB *PLy_spi_exceptions = NULL;
21 : :
22 : :
23 : : static void PLy_add_exceptions(PyObject *plpy);
24 : : static PyObject *PLy_create_exception(char *name,
25 : : PyObject *base, PyObject *dict,
26 : : const char *modname, PyObject *mod);
27 : : static void PLy_generate_spi_exceptions(PyObject *mod, PyObject *base);
28 : :
29 : : /* module functions */
30 : : static PyObject *PLy_debug(PyObject *self, PyObject *args, PyObject *kw);
31 : : static PyObject *PLy_log(PyObject *self, PyObject *args, PyObject *kw);
32 : : static PyObject *PLy_info(PyObject *self, PyObject *args, PyObject *kw);
33 : : static PyObject *PLy_notice(PyObject *self, PyObject *args, PyObject *kw);
34 : : static PyObject *PLy_warning(PyObject *self, PyObject *args, PyObject *kw);
35 : : static PyObject *PLy_error(PyObject *self, PyObject *args, PyObject *kw);
36 : : static PyObject *PLy_fatal(PyObject *self, PyObject *args, PyObject *kw);
37 : : static PyObject *PLy_quote_literal(PyObject *self, PyObject *args);
38 : : static PyObject *PLy_quote_nullable(PyObject *self, PyObject *args);
39 : : static PyObject *PLy_quote_ident(PyObject *self, PyObject *args);
40 : :
41 : :
42 : : /* A list of all known exceptions, generated from backend/utils/errcodes.txt */
43 : : typedef struct ExceptionMap
44 : : {
45 : : char *name;
46 : : char *classname;
47 : : int sqlstate;
48 : : } ExceptionMap;
49 : :
50 : : static const ExceptionMap exception_map[] = {
51 : : #include "spiexceptions.h"
52 : : {NULL, NULL, 0}
53 : : };
54 : :
55 : : static PyMethodDef PLy_methods[] = {
56 : : /*
57 : : * logging methods
58 : : */
59 : : {"debug", (PyCFunction) (pg_funcptr_t) PLy_debug, METH_VARARGS | METH_KEYWORDS, NULL},
60 : : {"log", (PyCFunction) (pg_funcptr_t) PLy_log, METH_VARARGS | METH_KEYWORDS, NULL},
61 : : {"info", (PyCFunction) (pg_funcptr_t) PLy_info, METH_VARARGS | METH_KEYWORDS, NULL},
62 : : {"notice", (PyCFunction) (pg_funcptr_t) PLy_notice, METH_VARARGS | METH_KEYWORDS, NULL},
63 : : {"warning", (PyCFunction) (pg_funcptr_t) PLy_warning, METH_VARARGS | METH_KEYWORDS, NULL},
64 : : {"error", (PyCFunction) (pg_funcptr_t) PLy_error, METH_VARARGS | METH_KEYWORDS, NULL},
65 : : {"fatal", (PyCFunction) (pg_funcptr_t) PLy_fatal, METH_VARARGS | METH_KEYWORDS, NULL},
66 : :
67 : : /*
68 : : * create a stored plan
69 : : */
70 : : {"prepare", PLy_spi_prepare, METH_VARARGS, NULL},
71 : :
72 : : /*
73 : : * execute a plan or query
74 : : */
75 : : {"execute", PLy_spi_execute, METH_VARARGS, NULL},
76 : :
77 : : /*
78 : : * escaping strings
79 : : */
80 : : {"quote_literal", PLy_quote_literal, METH_VARARGS, NULL},
81 : : {"quote_nullable", PLy_quote_nullable, METH_VARARGS, NULL},
82 : : {"quote_ident", PLy_quote_ident, METH_VARARGS, NULL},
83 : :
84 : : /*
85 : : * create the subtransaction context manager
86 : : */
87 : : {"subtransaction", PLy_subtransaction_new, METH_NOARGS, NULL},
88 : :
89 : : /*
90 : : * create a cursor
91 : : */
92 : : {"cursor", PLy_cursor, METH_VARARGS, NULL},
93 : :
94 : : /*
95 : : * transaction control
96 : : */
97 : : {"commit", PLy_commit, METH_NOARGS, NULL},
98 : : {"rollback", PLy_rollback, METH_NOARGS, NULL},
99 : :
100 : : {NULL, NULL, 0, NULL}
101 : : };
102 : :
103 : : static PyMethodDef PLy_exc_methods[] = {
104 : : {NULL, NULL, 0, NULL}
105 : : };
106 : :
107 : : static PyModuleDef PLy_module = {
108 : : PyModuleDef_HEAD_INIT,
109 : : .m_name = "plpy",
110 : : .m_size = -1,
111 : : .m_methods = PLy_methods,
112 : : };
113 : :
114 : : static PyModuleDef PLy_exc_module = {
115 : : PyModuleDef_HEAD_INIT,
116 : : .m_name = "spiexceptions",
117 : : .m_size = -1,
118 : : .m_methods = PLy_exc_methods,
119 : : };
120 : :
121 : : /*
122 : : * Must have external linkage, because PyMODINIT_FUNC does dllexport on
123 : : * Windows-like platforms.
124 : : */
125 : : PyMODINIT_FUNC
5201 peter_e@gmx.net 126 :CBC 23 : PyInit_plpy(void)
127 : : {
128 : : PyObject *m;
129 : :
130 : 23 : m = PyModule_Create(&PLy_module);
131 [ - + ]: 23 : if (m == NULL)
5201 peter_e@gmx.net 132 :UBC 0 : return NULL;
133 : :
5201 peter_e@gmx.net 134 :CBC 23 : PLy_add_exceptions(m);
135 : :
136 : 23 : PLy_plan_init_type();
137 : 23 : PLy_result_init_type();
138 : 23 : PLy_subtransaction_init_type();
139 : 23 : PLy_cursor_init_type();
140 : :
59 peter@eisentraut.org 141 :GNC 23 : return m;
5201 peter_e@gmx.net 142 :ECB (23) : }
143 : :
144 : : static void
5201 peter_e@gmx.net 145 :CBC 23 : PLy_add_exceptions(PyObject *plpy)
146 : : {
147 : : PyObject *excmod;
148 : : HASHCTL hash_ctl;
149 : :
3383 tgl@sss.pgh.pa.us 150 : 23 : PLy_exc_error = PLy_create_exception("plpy.Error", NULL, NULL,
151 : : "Error", plpy);
152 : 23 : PLy_exc_fatal = PLy_create_exception("plpy.Fatal", NULL, NULL,
153 : : "Fatal", plpy);
154 : 23 : PLy_exc_spi_error = PLy_create_exception("plpy.SPIError", NULL, NULL,
155 : : "SPIError", plpy);
156 : :
59 peter@eisentraut.org 157 :GNC 23 : excmod = PyModule_Create(&PLy_exc_module);
158 [ - + ]: 23 : if (excmod == NULL)
59 peter@eisentraut.org 159 :UNC 0 : PLy_elog(ERROR, "could not create the spiexceptions module");
160 : :
5201 peter_e@gmx.net 161 :CBC 23 : hash_ctl.keysize = sizeof(int);
162 : 23 : hash_ctl.entrysize = sizeof(PLyExceptionEntry);
3383 tgl@sss.pgh.pa.us 163 : 23 : PLy_spi_exceptions = hash_create("PL/Python SPI exceptions", 256,
164 : : &hash_ctl, HASH_ELEM | HASH_BLOBS);
165 : :
5201 peter_e@gmx.net 166 : 23 : PLy_generate_spi_exceptions(excmod, PLy_exc_spi_error);
167 : :
59 peter@eisentraut.org 168 [ - + ]:GNC 23 : if (PyModule_AddObject(plpy, "spiexceptions", excmod) < 0)
169 : : {
59 peter@eisentraut.org 170 :UNC 0 : Py_XDECREF(excmod);
171 : 0 : PLy_elog(ERROR, "could not add the spiexceptions module");
172 : : }
5201 peter_e@gmx.net 173 :CBC 23 : }
174 : :
175 : : /*
176 : : * Create an exception object and add it to the module
177 : : *
178 : : * The created exception object is also returned.
179 : : */
180 : : static PyObject *
3383 tgl@sss.pgh.pa.us 181 : 5842 : PLy_create_exception(char *name, PyObject *base, PyObject *dict,
182 : : const char *modname, PyObject *mod)
183 : : {
184 : : PyObject *exc;
185 : :
186 : 5842 : exc = PyErr_NewException(name, base, dict);
187 [ - + ]: 5842 : if (exc == NULL)
3057 peter_e@gmx.net 188 :UBC 0 : PLy_elog(ERROR, NULL);
189 : :
190 : : /*
191 : : * PyModule_AddObject() (below) steals the reference to exc, but we also
192 : : * want to return the value from this function, so add another ref to
193 : : * account for that. (The caller will store a pointer to the exception
194 : : * object in some permanent variable.)
195 : : */
196 : : Py_INCREF(exc);
197 : :
59 peter@eisentraut.org 198 [ - + ]:GNC 5842 : if (PyModule_AddObject(mod, modname, exc) < 0)
199 : : {
59 peter@eisentraut.org 200 :UNC 0 : Py_XDECREF(exc);
201 : 0 : PLy_elog(ERROR, "could not add exception %s", name);
202 : : }
203 : :
3383 tgl@sss.pgh.pa.us 204 :CBC 5842 : return exc;
205 : : }
206 : :
207 : : /*
208 : : * Add all the autogenerated exceptions as subclasses of SPIError
209 : : */
210 : : static void
5201 peter_e@gmx.net 211 : 23 : PLy_generate_spi_exceptions(PyObject *mod, PyObject *base)
212 : : {
213 : : int i;
214 : :
215 [ + + ]: 5796 : for (i = 0; exception_map[i].name != NULL; i++)
216 : : {
217 : : bool found;
218 : : PyObject *exc;
219 : : PLyExceptionEntry *entry;
220 : : PyObject *sqlstate;
221 : 5773 : PyObject *dict = PyDict_New();
222 : :
5115 tgl@sss.pgh.pa.us 223 [ - + ]: 5773 : if (dict == NULL)
3057 peter_e@gmx.net 224 :UBC 0 : PLy_elog(ERROR, NULL);
225 : :
1469 andres@anarazel.de 226 :CBC 5773 : sqlstate = PLyUnicode_FromString(unpack_sql_state(exception_map[i].sqlstate));
5115 tgl@sss.pgh.pa.us 227 [ - + ]: 5773 : if (sqlstate == NULL)
5115 tgl@sss.pgh.pa.us 228 :UBC 0 : PLy_elog(ERROR, "could not generate SPI exceptions");
229 : :
5201 peter_e@gmx.net 230 :CBC 5773 : PyDict_SetItemString(dict, "sqlstate", sqlstate);
231 : : Py_DECREF(sqlstate);
232 : :
3383 tgl@sss.pgh.pa.us 233 : 5773 : exc = PLy_create_exception(exception_map[i].name, base, dict,
234 : 5773 : exception_map[i].classname, mod);
235 : :
5201 peter_e@gmx.net 236 : 5773 : entry = hash_search(PLy_spi_exceptions, &exception_map[i].sqlstate,
237 : : HASH_ENTER, &found);
238 [ - + ]: 5773 : Assert(!found);
3383 tgl@sss.pgh.pa.us 239 : 5773 : entry->exc = exc;
240 : : }
5201 peter_e@gmx.net 241 : 23 : }
242 : :
243 : :
244 : : /*
245 : : * the python interface to the elog function
246 : : * don't confuse these with PLy_elog
247 : : */
248 : : static PyObject *PLy_output(volatile int level, PyObject *self,
249 : : PyObject *args, PyObject *kw);
250 : :
251 : : static PyObject *
3628 teodor@sigaev.ru 252 : 2 : PLy_debug(PyObject *self, PyObject *args, PyObject *kw)
253 : : {
254 : 2 : return PLy_output(DEBUG2, self, args, kw);
255 : : }
256 : :
257 : : static PyObject *
258 : 2 : PLy_log(PyObject *self, PyObject *args, PyObject *kw)
259 : : {
260 : 2 : return PLy_output(LOG, self, args, kw);
261 : : }
262 : :
263 : : static PyObject *
264 : 112 : PLy_info(PyObject *self, PyObject *args, PyObject *kw)
265 : : {
266 : 112 : return PLy_output(INFO, self, args, kw);
267 : : }
268 : :
269 : : static PyObject *
270 : 215 : PLy_notice(PyObject *self, PyObject *args, PyObject *kw)
271 : : {
272 : 215 : return PLy_output(NOTICE, self, args, kw);
273 : : }
274 : :
275 : : static PyObject *
276 : 5 : PLy_warning(PyObject *self, PyObject *args, PyObject *kw)
277 : : {
278 : 5 : return PLy_output(WARNING, self, args, kw);
279 : : }
280 : :
281 : : static PyObject *
282 : 11 : PLy_error(PyObject *self, PyObject *args, PyObject *kw)
283 : : {
284 : 11 : return PLy_output(ERROR, self, args, kw);
285 : : }
286 : :
287 : : static PyObject *
3628 teodor@sigaev.ru 288 :UBC 0 : PLy_fatal(PyObject *self, PyObject *args, PyObject *kw)
289 : : {
290 : 0 : return PLy_output(FATAL, self, args, kw);
291 : : }
292 : :
293 : : static PyObject *
5201 peter_e@gmx.net 294 :CBC 6 : PLy_quote_literal(PyObject *self, PyObject *args)
295 : : {
296 : : const char *str;
297 : : char *quoted;
298 : : PyObject *ret;
299 : :
3426 300 [ - + ]: 6 : if (!PyArg_ParseTuple(args, "s:quote_literal", &str))
5201 peter_e@gmx.net 301 :UBC 0 : return NULL;
302 : :
5201 peter_e@gmx.net 303 :CBC 6 : quoted = quote_literal_cstr(str);
1469 andres@anarazel.de 304 : 6 : ret = PLyUnicode_FromString(quoted);
5201 peter_e@gmx.net 305 : 6 : pfree(quoted);
306 : :
307 : 6 : return ret;
308 : : }
309 : :
310 : : static PyObject *
311 : 6 : PLy_quote_nullable(PyObject *self, PyObject *args)
312 : : {
313 : : const char *str;
314 : : char *quoted;
315 : : PyObject *ret;
316 : :
3426 317 [ - + ]: 6 : if (!PyArg_ParseTuple(args, "z:quote_nullable", &str))
5201 peter_e@gmx.net 318 :UBC 0 : return NULL;
319 : :
5201 peter_e@gmx.net 320 [ + + ]:CBC 6 : if (str == NULL)
1469 andres@anarazel.de 321 : 1 : return PLyUnicode_FromString("NULL");
322 : :
5201 peter_e@gmx.net 323 : 5 : quoted = quote_literal_cstr(str);
1469 andres@anarazel.de 324 : 5 : ret = PLyUnicode_FromString(quoted);
5201 peter_e@gmx.net 325 : 5 : pfree(quoted);
326 : :
327 : 5 : return ret;
328 : : }
329 : :
330 : : static PyObject *
331 : 3 : PLy_quote_ident(PyObject *self, PyObject *args)
332 : : {
333 : : const char *str;
334 : : const char *quoted;
335 : : PyObject *ret;
336 : :
3426 337 [ - + ]: 3 : if (!PyArg_ParseTuple(args, "s:quote_ident", &str))
5201 peter_e@gmx.net 338 :UBC 0 : return NULL;
339 : :
5201 peter_e@gmx.net 340 :CBC 3 : quoted = quote_identifier(str);
1469 andres@anarazel.de 341 : 3 : ret = PLyUnicode_FromString(quoted);
342 : :
5201 peter_e@gmx.net 343 : 3 : return ret;
344 : : }
345 : :
346 : : /* enforce cast of object to string (returns a palloc'd string or NULL) */
347 : : static char *
3628 teodor@sigaev.ru 348 : 58 : object_to_string(PyObject *obj)
349 : : {
350 [ + - ]: 58 : if (obj)
351 : : {
3566 rhaas@postgresql.org 352 : 58 : PyObject *so = PyObject_Str(obj);
353 : :
3628 teodor@sigaev.ru 354 [ + - ]: 58 : if (so != NULL)
355 : : {
356 : : char *str;
357 : :
144 tgl@sss.pgh.pa.us 358 :GNC 58 : str = PLyUnicode_AsString(so);
359 : : Py_DECREF(so);
360 : :
3628 teodor@sigaev.ru 361 :CBC 58 : return str;
362 : : }
363 : : }
364 : :
3628 teodor@sigaev.ru 365 :UBC 0 : return NULL;
366 : : }
367 : :
368 : : static PyObject *
3628 teodor@sigaev.ru 369 :CBC 347 : PLy_output(volatile int level, PyObject *self, PyObject *args, PyObject *kw)
370 : : {
3566 rhaas@postgresql.org 371 : 347 : int sqlstate = 0;
372 : 347 : char *volatile sqlstatestr = NULL;
373 : 347 : char *volatile message = NULL;
374 : 347 : char *volatile detail = NULL;
375 : 347 : char *volatile hint = NULL;
3564 peter_e@gmx.net 376 : 347 : char *volatile column_name = NULL;
377 : 347 : char *volatile constraint_name = NULL;
378 : 347 : char *volatile datatype_name = NULL;
379 : 347 : char *volatile table_name = NULL;
380 : 347 : char *volatile schema_name = NULL;
381 : : volatile MemoryContext oldcontext;
382 : : PyObject *key,
383 : : *value;
384 : : PyObject *volatile so;
3566 rhaas@postgresql.org 385 : 347 : Py_ssize_t pos = 0;
386 : :
5201 peter_e@gmx.net 387 [ + + ]: 347 : if (PyTuple_Size(args) == 1)
388 : : {
389 : : /*
390 : : * Treat single argument specially to avoid undesirable ('tuple',)
391 : : * decoration.
392 : : */
393 : : PyObject *o;
394 : :
5115 tgl@sss.pgh.pa.us 395 [ - + ]: 261 : if (!PyArg_UnpackTuple(args, "plpy.elog", 1, 1, &o))
5115 tgl@sss.pgh.pa.us 396 :UBC 0 : PLy_elog(ERROR, "could not unpack arguments in plpy.elog");
5201 peter_e@gmx.net 397 :CBC 261 : so = PyObject_Str(o);
398 : : }
399 : : else
400 : 86 : so = PyObject_Str(args);
401 : :
1469 andres@anarazel.de 402 [ + - - + ]: 347 : if (so == NULL || ((message = PLyUnicode_AsString(so)) == NULL))
403 : : {
5201 peter_e@gmx.net 404 :UBC 0 : level = ERROR;
3628 teodor@sigaev.ru 405 : 0 : message = dgettext(TEXTDOMAIN, "could not parse error message in plpy.elog");
406 : : }
3625 tgl@sss.pgh.pa.us 407 :CBC 347 : message = pstrdup(message);
408 : :
3628 teodor@sigaev.ru 409 : 347 : Py_XDECREF(so);
410 : :
411 [ + + ]: 347 : if (kw != NULL)
412 : : {
413 [ + + ]: 80 : while (PyDict_Next(kw, &pos, &key, &value))
414 : : {
1469 andres@anarazel.de 415 : 61 : char *keyword = PLyUnicode_AsString(key);
416 : :
3628 teodor@sigaev.ru 417 [ + + ]: 61 : if (strcmp(keyword, "message") == 0)
418 : : {
419 : : /* the message should not be overwritten */
420 [ + + ]: 9 : if (PyTuple_Size(args) != 0)
421 : : {
3216 alvherre@alvh.no-ip. 422 : 2 : PLy_exception_set(PyExc_TypeError, "argument 'message' given by name and position");
3543 peter_e@gmx.net 423 : 2 : return NULL;
424 : : }
425 : :
3625 tgl@sss.pgh.pa.us 426 [ + - ]: 7 : if (message)
427 : 7 : pfree(message);
3628 teodor@sigaev.ru 428 : 7 : message = object_to_string(value);
429 : : }
430 [ + + ]: 52 : else if (strcmp(keyword, "detail") == 0)
431 : 15 : detail = object_to_string(value);
432 [ + + ]: 37 : else if (strcmp(keyword, "hint") == 0)
433 : 7 : hint = object_to_string(value);
434 [ + + ]: 30 : else if (strcmp(keyword, "sqlstate") == 0)
435 : 7 : sqlstatestr = object_to_string(value);
3564 peter_e@gmx.net 436 [ + + ]: 23 : else if (strcmp(keyword, "schema_name") == 0)
437 : 4 : schema_name = object_to_string(value);
438 [ + + ]: 19 : else if (strcmp(keyword, "table_name") == 0)
439 : 5 : table_name = object_to_string(value);
440 [ + + ]: 14 : else if (strcmp(keyword, "column_name") == 0)
441 : 4 : column_name = object_to_string(value);
442 [ + + ]: 10 : else if (strcmp(keyword, "datatype_name") == 0)
443 : 5 : datatype_name = object_to_string(value);
444 [ + + ]: 5 : else if (strcmp(keyword, "constraint_name") == 0)
445 : 4 : constraint_name = object_to_string(value);
446 : : else
447 : : {
3543 448 : 1 : PLy_exception_set(PyExc_TypeError,
449 : : "'%s' is an invalid keyword argument for this function",
450 : : keyword);
451 : 1 : return NULL;
452 : : }
453 : : }
454 : : }
455 : :
3628 teodor@sigaev.ru 456 [ + + ]: 344 : if (sqlstatestr != NULL)
457 : : {
458 [ + + ]: 7 : if (strlen(sqlstatestr) != 5)
459 : : {
3543 peter_e@gmx.net 460 : 1 : PLy_exception_set(PyExc_ValueError, "invalid SQLSTATE code");
461 : 1 : return NULL;
462 : : }
463 : :
3628 teodor@sigaev.ru 464 [ - + ]: 6 : if (strspn(sqlstatestr, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") != 5)
465 : : {
3543 peter_e@gmx.net 466 :UBC 0 : PLy_exception_set(PyExc_ValueError, "invalid SQLSTATE code");
467 : 0 : return NULL;
468 : : }
469 : :
3628 teodor@sigaev.ru 470 :CBC 6 : sqlstate = MAKE_SQLSTATE(sqlstatestr[0],
471 : : sqlstatestr[1],
472 : : sqlstatestr[2],
473 : : sqlstatestr[3],
474 : : sqlstatestr[4]);
475 : : }
476 : :
5201 peter_e@gmx.net 477 : 343 : oldcontext = CurrentMemoryContext;
478 [ + + ]: 343 : PG_TRY();
479 : : {
3628 teodor@sigaev.ru 480 [ + - ]: 343 : if (message != NULL)
481 : 343 : pg_verifymbstr(message, strlen(message), false);
482 [ + + ]: 343 : if (detail != NULL)
483 : 15 : pg_verifymbstr(detail, strlen(detail), false);
484 [ + + ]: 343 : if (hint != NULL)
485 : 7 : pg_verifymbstr(hint, strlen(hint), false);
3564 peter_e@gmx.net 486 [ + + ]: 343 : if (schema_name != NULL)
487 : 4 : pg_verifymbstr(schema_name, strlen(schema_name), false);
488 [ + + ]: 343 : if (table_name != NULL)
489 : 5 : pg_verifymbstr(table_name, strlen(table_name), false);
490 [ + + ]: 343 : if (column_name != NULL)
491 : 4 : pg_verifymbstr(column_name, strlen(column_name), false);
492 [ + + ]: 343 : if (datatype_name != NULL)
493 : 5 : pg_verifymbstr(datatype_name, strlen(datatype_name), false);
494 [ + + ]: 343 : if (constraint_name != NULL)
495 : 4 : pg_verifymbstr(constraint_name, strlen(constraint_name), false);
496 : :
3628 teodor@sigaev.ru 497 [ + + + + : 343 : ereport(level,
+ - + + +
+ + + + +
+ + + + +
+ ]
498 : : ((sqlstate != 0) ? errcode(sqlstate) : 0,
499 : : (message != NULL) ? errmsg_internal("%s", message) : 0,
500 : : (detail != NULL) ? errdetail_internal("%s", detail) : 0,
501 : : (hint != NULL) ? errhint("%s", hint) : 0,
502 : : (column_name != NULL) ?
503 : : err_generic_string(PG_DIAG_COLUMN_NAME, column_name) : 0,
504 : : (constraint_name != NULL) ?
505 : : err_generic_string(PG_DIAG_CONSTRAINT_NAME, constraint_name) : 0,
506 : : (datatype_name != NULL) ?
507 : : err_generic_string(PG_DIAG_DATATYPE_NAME, datatype_name) : 0,
508 : : (table_name != NULL) ?
509 : : err_generic_string(PG_DIAG_TABLE_NAME, table_name) : 0,
510 : : (schema_name != NULL) ?
511 : : err_generic_string(PG_DIAG_SCHEMA_NAME, schema_name) : 0));
512 : : }
5201 peter_e@gmx.net 513 : 11 : PG_CATCH();
514 : : {
515 : : ErrorData *edata;
516 : :
517 : 11 : MemoryContextSwitchTo(oldcontext);
518 : 11 : edata = CopyErrorData();
519 : 11 : FlushErrorState();
520 : :
3628 teodor@sigaev.ru 521 : 11 : PLy_exception_set_with_details(PLy_exc_error, edata);
522 : 11 : FreeErrorData(edata);
523 : :
5201 peter_e@gmx.net 524 : 11 : return NULL;
525 : : }
526 [ - + ]: 332 : PG_END_TRY();
527 : :
528 : : /*
529 : : * return a legal object so the interpreter will continue on its merry way
530 : : */
3089 531 : 332 : Py_RETURN_NONE;
532 : : }
|