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