4 * src/pl/plpython/plpy_plpymodule.c
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"
16 #include "plpy_subxactobject.h"
18 #include "utils/builtins.h"
20 HTAB
*PLy_spi_exceptions
= NULL
;
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
);
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
);
42 /* A list of all known exceptions, generated from backend/utils/errcodes.txt */
43 typedef struct ExceptionMap
50 static const ExceptionMap exception_map
[] = {
51 #include "spiexceptions.h"
55 static PyMethodDef PLy_methods
[] = {
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
},
68 * create a stored plan
70 {"prepare", PLy_spi_prepare
, METH_VARARGS
, NULL
},
73 * execute a plan or query
75 {"execute", PLy_spi_execute
, METH_VARARGS
, NULL
},
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
},
85 * create the subtransaction context manager
87 {"subtransaction", PLy_subtransaction_new
, METH_NOARGS
, NULL
},
92 {"cursor", PLy_cursor
, METH_VARARGS
, NULL
},
97 {"commit", PLy_commit
, METH_NOARGS
, NULL
},
98 {"rollback", PLy_rollback
, METH_NOARGS
, NULL
},
100 {NULL
, NULL
, 0, NULL
}
103 static PyMethodDef PLy_exc_methods
[] = {
104 {NULL
, NULL
, 0, NULL
}
107 static PyModuleDef PLy_module
= {
108 PyModuleDef_HEAD_INIT
,
111 .m_methods
= PLy_methods
,
114 static PyModuleDef PLy_exc_module
= {
115 PyModuleDef_HEAD_INIT
,
116 .m_name
= "spiexceptions",
118 .m_methods
= PLy_exc_methods
,
122 * Must have external linkage, because PyMODINIT_FUNC does dllexport on
123 * Windows-like platforms.
130 m
= PyModule_Create(&PLy_module
);
134 PLy_add_exceptions(m
);
147 * initialize plpy module
149 PLy_plan_init_type();
150 PLy_result_init_type();
151 PLy_subtransaction_init_type();
152 PLy_cursor_init_type();
154 PyModule_Create(&PLy_module
);
156 /* PyDict_SetItemString(plpy, "PlanType", (PyObject *) &PLy_PlanType); */
159 * initialize main module, and add plpy
161 main_mod
= PyImport_AddModule("__main__");
162 main_dict
= PyModule_GetDict(main_mod
);
163 plpy_mod
= PyImport_AddModule("plpy");
164 if (plpy_mod
== NULL
)
165 PLy_elog(ERROR
, "could not import \"plpy\" module");
166 PyDict_SetItemString(main_dict
, "plpy", plpy_mod
);
167 if (PyErr_Occurred())
168 PLy_elog(ERROR
, "could not import \"plpy\" module");
172 PLy_add_exceptions(PyObject
*plpy
)
177 excmod
= PyModule_Create(&PLy_exc_module
);
179 PLy_elog(ERROR
, "could not create the spiexceptions module");
182 * PyModule_AddObject does not add a refcount to the object, for some odd
183 * reason; we must do that.
186 if (PyModule_AddObject(plpy
, "spiexceptions", excmod
) < 0)
187 PLy_elog(ERROR
, "could not add the spiexceptions module");
189 PLy_exc_error
= PLy_create_exception("plpy.Error", NULL
, NULL
,
191 PLy_exc_fatal
= PLy_create_exception("plpy.Fatal", NULL
, NULL
,
193 PLy_exc_spi_error
= PLy_create_exception("plpy.SPIError", NULL
, NULL
,
196 hash_ctl
.keysize
= sizeof(int);
197 hash_ctl
.entrysize
= sizeof(PLyExceptionEntry
);
198 PLy_spi_exceptions
= hash_create("PL/Python SPI exceptions", 256,
199 &hash_ctl
, HASH_ELEM
| HASH_BLOBS
);
201 PLy_generate_spi_exceptions(excmod
, PLy_exc_spi_error
);
205 * Create an exception object and add it to the module
208 PLy_create_exception(char *name
, PyObject
*base
, PyObject
*dict
,
209 const char *modname
, PyObject
*mod
)
213 exc
= PyErr_NewException(name
, base
, dict
);
215 PLy_elog(ERROR
, NULL
);
218 * PyModule_AddObject does not add a refcount to the object, for some odd
219 * reason; we must do that.
222 PyModule_AddObject(mod
, modname
, exc
);
225 * The caller will also store a pointer to the exception object in some
226 * permanent variable, so add another ref to account for that. This is
227 * probably excessively paranoid, but let's be sure.
234 * Add all the autogenerated exceptions as subclasses of SPIError
237 PLy_generate_spi_exceptions(PyObject
*mod
, PyObject
*base
)
241 for (i
= 0; exception_map
[i
].name
!= NULL
; i
++)
245 PLyExceptionEntry
*entry
;
247 PyObject
*dict
= PyDict_New();
250 PLy_elog(ERROR
, NULL
);
252 sqlstate
= PLyUnicode_FromString(unpack_sql_state(exception_map
[i
].sqlstate
));
253 if (sqlstate
== NULL
)
254 PLy_elog(ERROR
, "could not generate SPI exceptions");
256 PyDict_SetItemString(dict
, "sqlstate", sqlstate
);
259 exc
= PLy_create_exception(exception_map
[i
].name
, base
, dict
,
260 exception_map
[i
].classname
, mod
);
262 entry
= hash_search(PLy_spi_exceptions
, &exception_map
[i
].sqlstate
,
271 * the python interface to the elog function
272 * don't confuse these with PLy_elog
274 static PyObject
*PLy_output(volatile int level
, PyObject
*self
,
275 PyObject
*args
, PyObject
*kw
);
278 PLy_debug(PyObject
*self
, PyObject
*args
, PyObject
*kw
)
280 return PLy_output(DEBUG2
, self
, args
, kw
);
284 PLy_log(PyObject
*self
, PyObject
*args
, PyObject
*kw
)
286 return PLy_output(LOG
, self
, args
, kw
);
290 PLy_info(PyObject
*self
, PyObject
*args
, PyObject
*kw
)
292 return PLy_output(INFO
, self
, args
, kw
);
296 PLy_notice(PyObject
*self
, PyObject
*args
, PyObject
*kw
)
298 return PLy_output(NOTICE
, self
, args
, kw
);
302 PLy_warning(PyObject
*self
, PyObject
*args
, PyObject
*kw
)
304 return PLy_output(WARNING
, self
, args
, kw
);
308 PLy_error(PyObject
*self
, PyObject
*args
, PyObject
*kw
)
310 return PLy_output(ERROR
, self
, args
, kw
);
314 PLy_fatal(PyObject
*self
, PyObject
*args
, PyObject
*kw
)
316 return PLy_output(FATAL
, self
, args
, kw
);
320 PLy_quote_literal(PyObject
*self
, PyObject
*args
)
326 if (!PyArg_ParseTuple(args
, "s:quote_literal", &str
))
329 quoted
= quote_literal_cstr(str
);
330 ret
= PLyUnicode_FromString(quoted
);
337 PLy_quote_nullable(PyObject
*self
, PyObject
*args
)
343 if (!PyArg_ParseTuple(args
, "z:quote_nullable", &str
))
347 return PLyUnicode_FromString("NULL");
349 quoted
= quote_literal_cstr(str
);
350 ret
= PLyUnicode_FromString(quoted
);
357 PLy_quote_ident(PyObject
*self
, PyObject
*args
)
363 if (!PyArg_ParseTuple(args
, "s:quote_ident", &str
))
366 quoted
= quote_identifier(str
);
367 ret
= PLyUnicode_FromString(quoted
);
372 /* enforce cast of object to string */
374 object_to_string(PyObject
*obj
)
378 PyObject
*so
= PyObject_Str(obj
);
384 str
= pstrdup(PLyUnicode_AsString(so
));
395 PLy_output(volatile int level
, PyObject
*self
, PyObject
*args
, PyObject
*kw
)
398 char *volatile sqlstatestr
= NULL
;
399 char *volatile message
= NULL
;
400 char *volatile detail
= NULL
;
401 char *volatile hint
= NULL
;
402 char *volatile column_name
= NULL
;
403 char *volatile constraint_name
= NULL
;
404 char *volatile datatype_name
= NULL
;
405 char *volatile table_name
= NULL
;
406 char *volatile schema_name
= NULL
;
407 volatile MemoryContext oldcontext
;
410 PyObject
*volatile so
;
413 if (PyTuple_Size(args
) == 1)
416 * Treat single argument specially to avoid undesirable ('tuple',)
421 if (!PyArg_UnpackTuple(args
, "plpy.elog", 1, 1, &o
))
422 PLy_elog(ERROR
, "could not unpack arguments in plpy.elog");
423 so
= PyObject_Str(o
);
426 so
= PyObject_Str(args
);
428 if (so
== NULL
|| ((message
= PLyUnicode_AsString(so
)) == NULL
))
431 message
= dgettext(TEXTDOMAIN
, "could not parse error message in plpy.elog");
433 message
= pstrdup(message
);
439 while (PyDict_Next(kw
, &pos
, &key
, &value
))
441 char *keyword
= PLyUnicode_AsString(key
);
443 if (strcmp(keyword
, "message") == 0)
445 /* the message should not be overwritten */
446 if (PyTuple_Size(args
) != 0)
448 PLy_exception_set(PyExc_TypeError
, "argument 'message' given by name and position");
454 message
= object_to_string(value
);
456 else if (strcmp(keyword
, "detail") == 0)
457 detail
= object_to_string(value
);
458 else if (strcmp(keyword
, "hint") == 0)
459 hint
= object_to_string(value
);
460 else if (strcmp(keyword
, "sqlstate") == 0)
461 sqlstatestr
= object_to_string(value
);
462 else if (strcmp(keyword
, "schema_name") == 0)
463 schema_name
= object_to_string(value
);
464 else if (strcmp(keyword
, "table_name") == 0)
465 table_name
= object_to_string(value
);
466 else if (strcmp(keyword
, "column_name") == 0)
467 column_name
= object_to_string(value
);
468 else if (strcmp(keyword
, "datatype_name") == 0)
469 datatype_name
= object_to_string(value
);
470 else if (strcmp(keyword
, "constraint_name") == 0)
471 constraint_name
= object_to_string(value
);
474 PLy_exception_set(PyExc_TypeError
,
475 "'%s' is an invalid keyword argument for this function",
482 if (sqlstatestr
!= NULL
)
484 if (strlen(sqlstatestr
) != 5)
486 PLy_exception_set(PyExc_ValueError
, "invalid SQLSTATE code");
490 if (strspn(sqlstatestr
, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") != 5)
492 PLy_exception_set(PyExc_ValueError
, "invalid SQLSTATE code");
496 sqlstate
= MAKE_SQLSTATE(sqlstatestr
[0],
503 oldcontext
= CurrentMemoryContext
;
507 pg_verifymbstr(message
, strlen(message
), false);
509 pg_verifymbstr(detail
, strlen(detail
), false);
511 pg_verifymbstr(hint
, strlen(hint
), false);
512 if (schema_name
!= NULL
)
513 pg_verifymbstr(schema_name
, strlen(schema_name
), false);
514 if (table_name
!= NULL
)
515 pg_verifymbstr(table_name
, strlen(table_name
), false);
516 if (column_name
!= NULL
)
517 pg_verifymbstr(column_name
, strlen(column_name
), false);
518 if (datatype_name
!= NULL
)
519 pg_verifymbstr(datatype_name
, strlen(datatype_name
), false);
520 if (constraint_name
!= NULL
)
521 pg_verifymbstr(constraint_name
, strlen(constraint_name
), false);
524 ((sqlstate
!= 0) ? errcode(sqlstate
) : 0,
525 (message
!= NULL
) ? errmsg_internal("%s", message
) : 0,
526 (detail
!= NULL
) ? errdetail_internal("%s", detail
) : 0,
527 (hint
!= NULL
) ? errhint("%s", hint
) : 0,
528 (column_name
!= NULL
) ?
529 err_generic_string(PG_DIAG_COLUMN_NAME
, column_name
) : 0,
530 (constraint_name
!= NULL
) ?
531 err_generic_string(PG_DIAG_CONSTRAINT_NAME
, constraint_name
) : 0,
532 (datatype_name
!= NULL
) ?
533 err_generic_string(PG_DIAG_DATATYPE_NAME
, datatype_name
) : 0,
534 (table_name
!= NULL
) ?
535 err_generic_string(PG_DIAG_TABLE_NAME
, table_name
) : 0,
536 (schema_name
!= NULL
) ?
537 err_generic_string(PG_DIAG_SCHEMA_NAME
, schema_name
) : 0));
543 MemoryContextSwitchTo(oldcontext
);
544 edata
= CopyErrorData();
547 PLy_exception_set_with_details(PLy_exc_error
, edata
);
548 FreeErrorData(edata
);
555 * return a legal object so the interpreter will continue on its merry way