Age Owner TLA Line data Source code
1 : /*
2 : * PL/Python main entry points
3 : *
4 : * src/pl/plpython/plpy_main.c
5 : */
6 :
7 : #include "postgres.h"
8 :
9 : #include "access/htup_details.h"
10 : #include "catalog/pg_proc.h"
11 : #include "catalog/pg_type.h"
12 : #include "commands/trigger.h"
13 : #include "executor/spi.h"
14 : #include "miscadmin.h"
15 : #include "plpy_elog.h"
16 : #include "plpy_exec.h"
17 : #include "plpy_main.h"
18 : #include "plpy_plpymodule.h"
19 : #include "plpy_procedure.h"
20 : #include "plpy_subxactobject.h"
21 : #include "plpython.h"
22 : #include "utils/guc.h"
23 : #include "utils/memutils.h"
24 : #include "utils/rel.h"
25 : #include "utils/syscache.h"
26 :
27 : /*
28 : * exported functions
29 : */
30 :
4130 peter_e 31 CBC 23 : PG_MODULE_MAGIC;
4130 peter_e 32 ECB :
398 andres 33 CBC 26 : PG_FUNCTION_INFO_V1(plpython3_validator);
398 andres 34 GIC 26 : PG_FUNCTION_INFO_V1(plpython3_call_handler);
35 8 : PG_FUNCTION_INFO_V1(plpython3_inline_handler);
36 :
37 :
38 : static bool PLy_procedure_is_trigger(Form_pg_proc procStruct);
39 : static void plpython_error_callback(void *arg);
40 : static void plpython_inline_error_callback(void *arg);
41 : static void PLy_init_interp(void);
42 :
43 : static PLyExecutionContext *PLy_push_execution_context(bool atomic_context);
44 : static void PLy_pop_execution_context(void);
45 :
46 : /* static state for Python library conflict detection */
47 : static int *plpython_version_bitmask_ptr = NULL;
48 : static int plpython_version_bitmask = 0;
49 :
50 : /* initialize global variables */
51 : PyObject *PLy_interp_globals = NULL;
52 :
53 : /* this doesn't need to be global; use PLy_current_execution_context() */
54 : static PLyExecutionContext *PLy_execution_contexts = NULL;
55 :
4130 peter_e 56 ECB :
57 : void
4130 peter_e 58 GIC 23 : _PG_init(void)
59 : {
60 : int **bitmask_ptr;
61 :
62 : /*
63 : * Set up a shared bitmask variable telling which Python version(s) are
64 : * loaded into this process's address space. If there's more than one, we
65 : * cannot call into libpython for fear of causing crashes. But postpone
66 : * the actual failure for later, so that operations like pg_restore can
67 : * load more than one plpython library so long as they don't try to do
68 : * anything much with the language.
69 : *
70 : * While we only support Python 3 these days, somebody might create an
71 : * out-of-tree version adding back support for Python 2. Conflicts with
398 andres 72 ECB : * such an extension should be detected.
2645 tgl 73 : */
2645 tgl 74 CBC 23 : bitmask_ptr = (int **) find_rendezvous_variable("plpython_version_bitmask");
2645 tgl 75 GIC 23 : if (!(*bitmask_ptr)) /* am I the first? */
2645 tgl 76 CBC 23 : *bitmask_ptr = &plpython_version_bitmask;
77 : /* Retain pointer to the agreed-on shared variable ... */
78 23 : plpython_version_bitmask_ptr = *bitmask_ptr;
79 : /* ... and announce my presence */
2645 tgl 80 GIC 23 : *plpython_version_bitmask_ptr |= (1 << PY_MAJOR_VERSION);
81 :
82 : /*
83 : * This should be safe even in the presence of conflicting plpythons, and
84 : * it's necessary to do it before possibly throwing a conflict error, or
2645 tgl 85 ECB : * the error message won't get localized.
86 : */
2645 tgl 87 GIC 23 : pg_bindtextdomain(TEXTDOMAIN);
88 23 : }
89 :
90 : /*
91 : * Perform one-time setup of PL/Python, after checking for a conflict
92 : * with other versions of Python.
2645 tgl 93 ECB : */
94 : static void
2645 tgl 95 GIC 925 : PLy_initialize(void)
96 : {
97 : static bool inited = false;
98 :
99 : /*
100 : * Check for multiple Python libraries before actively doing anything with
101 : * libpython. This must be repeated on each entry to PL/Python, in case a
102 : * conflicting library got loaded since we last looked.
103 : *
104 : * It is attractive to weaken this error from FATAL to ERROR, but there
2645 tgl 105 ECB : * would be corner cases, so it seems best to be conservative.
2645 tgl 106 EUB : */
2645 tgl 107 GIC 925 : if (*plpython_version_bitmask_ptr != (1 << PY_MAJOR_VERSION))
2645 tgl 108 UIC 0 : ereport(FATAL,
109 : (errmsg("multiple Python libraries are present in session"),
110 : errdetail("Only one Python major version can be used in one session.")));
2645 tgl 111 ECB :
112 : /* The rest should only be done once per session */
2645 tgl 113 GIC 925 : if (inited)
2645 tgl 114 CBC 902 : return;
4130 peter_e 115 ECB :
4130 peter_e 116 CBC 23 : PyImport_AppendInittab("plpy", PyInit_plpy);
117 23 : Py_Initialize();
118 23 : PyImport_ImportModule("plpy");
119 23 : PLy_init_interp();
4130 peter_e 120 GBC 23 : PLy_init_plpy();
4130 peter_e 121 GIC 23 : if (PyErr_Occurred())
4130 peter_e 122 LBC 0 : PLy_elog(FATAL, "untrapped error in initialization");
123 :
4130 peter_e 124 CBC 23 : init_procedure_caches();
125 :
126 23 : explicit_subtransactions = NIL;
127 :
4044 tgl 128 23 : PLy_execution_contexts = NULL;
129 :
4130 peter_e 130 GIC 23 : inited = true;
131 : }
132 :
133 : /*
134 : * This should be called only once, from PLy_initialize. Initialize the Python
135 : * interpreter and global data.
4130 peter_e 136 ECB : */
137 : static void
4130 peter_e 138 GIC 23 : PLy_init_interp(void)
139 : {
140 : static PyObject *PLy_interp_safe_globals = NULL;
4130 peter_e 141 ECB : PyObject *mainmod;
142 :
4130 peter_e 143 GBC 23 : mainmod = PyImport_AddModule("__main__");
4130 peter_e 144 CBC 23 : if (mainmod == NULL || PyErr_Occurred())
4130 peter_e 145 LBC 0 : PLy_elog(ERROR, "could not import \"__main__\" module");
4130 peter_e 146 CBC 23 : Py_INCREF(mainmod);
147 23 : PLy_interp_globals = PyModule_GetDict(mainmod);
4130 peter_e 148 GBC 23 : PLy_interp_safe_globals = PyDict_New();
4044 tgl 149 CBC 23 : if (PLy_interp_safe_globals == NULL)
1986 peter_e 150 LBC 0 : PLy_elog(ERROR, NULL);
4130 peter_e 151 CBC 23 : PyDict_SetItemString(PLy_interp_globals, "GD", PLy_interp_safe_globals);
4130 peter_e 152 GBC 23 : Py_DECREF(mainmod);
4130 peter_e 153 CBC 23 : if (PLy_interp_globals == NULL || PyErr_Occurred())
4130 peter_e 154 UIC 0 : PLy_elog(ERROR, "could not initialize globals");
4130 peter_e 155 GIC 23 : }
4130 peter_e 156 ECB :
157 : Datum
398 andres 158 CBC 237 : plpython3_validator(PG_FUNCTION_ARGS)
159 : {
4130 peter_e 160 GIC 237 : Oid funcoid = PG_GETARG_OID(0);
161 : HeapTuple tuple;
162 : Form_pg_proc procStruct;
4130 peter_e 163 ECB : bool is_trigger;
4130 peter_e 164 EUB :
3338 noah 165 GIC 237 : if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
3338 noah 166 LBC 0 : PG_RETURN_VOID();
3338 noah 167 ECB :
4130 peter_e 168 GIC 237 : if (!check_function_bodies)
169 1 : PG_RETURN_VOID();
2645 tgl 170 ECB :
171 : /* Do this only after making sure we need to do something */
2645 tgl 172 GIC 236 : PLy_initialize();
4130 peter_e 173 ECB :
174 : /* Get the new function's pg_proc entry */
4130 peter_e 175 GBC 236 : tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
4130 peter_e 176 CBC 236 : if (!HeapTupleIsValid(tuple))
4130 peter_e 177 UIC 0 : elog(ERROR, "cache lookup failed for function %u", funcoid);
4130 peter_e 178 CBC 236 : procStruct = (Form_pg_proc) GETSTRUCT(tuple);
179 :
180 236 : is_trigger = PLy_procedure_is_trigger(procStruct);
181 :
4130 peter_e 182 GIC 236 : ReleaseSysCache(tuple);
4130 peter_e 183 ECB :
184 : /* We can't validate triggers against any particular table ... */
3726 tgl 185 CBC 236 : PLy_procedure_get(funcoid, InvalidOid, is_trigger);
186 :
4130 peter_e 187 GIC 235 : PG_RETURN_VOID();
188 : }
4130 peter_e 189 ECB :
190 : Datum
398 andres 191 GIC 668 : plpython3_call_handler(PG_FUNCTION_ARGS)
192 : {
193 : bool nonatomic;
194 : Datum retval;
195 : PLyExecutionContext *exec_ctx;
4130 peter_e 196 ECB : ErrorContextCallback plerrcontext;
197 :
2645 tgl 198 CBC 668 : PLy_initialize();
2645 tgl 199 ECB :
1903 peter_e 200 CBC 1390 : nonatomic = fcinfo->context &&
1903 peter_e 201 GIC 676 : IsA(fcinfo->context, CallContext) &&
202 8 : !castNode(CallContext, fcinfo->context)->atomic;
1903 peter_e 203 ECB :
4044 tgl 204 EUB : /* Note: SPI_finish() happens in plpy_exec.c, which is dubious design */
1903 peter_e 205 GIC 668 : if (SPI_connect_ext(nonatomic ? SPI_OPT_NONATOMIC : 0) != SPI_OK_CONNECT)
4130 peter_e 206 UIC 0 : elog(ERROR, "SPI_connect failed");
207 :
208 : /*
209 : * Push execution context onto stack. It is important that this get
210 : * popped again, so avoid putting anything that could throw error between
1880 tgl 211 ECB : * here and the PG_TRY.
212 : */
1903 peter_e 213 CBC 668 : exec_ctx = PLy_push_execution_context(!nonatomic);
214 :
4130 215 668 : PG_TRY();
216 : {
3726 tgl 217 GIC 668 : Oid funcoid = fcinfo->flinfo->fn_oid;
218 : PLyProcedure *proc;
219 :
220 : /*
221 : * Setup error traceback support for ereport(). Note that the PG_TRY
222 : * structure pops this for us again at exit, so we needn't do that
223 : * explicitly, nor do we risk the callback getting called after we've
1880 tgl 224 ECB : * destroyed the exec_ctx.
225 : */
1880 tgl 226 CBC 668 : plerrcontext.callback = plpython_error_callback;
227 668 : plerrcontext.arg = exec_ctx;
1880 tgl 228 GIC 668 : plerrcontext.previous = error_context_stack;
1880 tgl 229 CBC 668 : error_context_stack = &plerrcontext;
1880 tgl 230 ECB :
4130 peter_e 231 CBC 668 : if (CALLED_AS_TRIGGER(fcinfo))
4130 peter_e 232 GIC 37 : {
3726 tgl 233 46 : Relation tgrel = ((TriggerData *) fcinfo->context)->tg_relation;
4130 peter_e 234 ECB : HeapTuple trv;
235 :
3726 tgl 236 CBC 46 : proc = PLy_procedure_get(funcoid, RelationGetRelid(tgrel), true);
4044 237 46 : exec_ctx->curr_proc = proc;
4130 peter_e 238 GIC 46 : trv = PLy_exec_trigger(fcinfo, proc);
239 37 : retval = PointerGetDatum(trv);
240 : }
4130 peter_e 241 ECB : else
242 : {
3726 tgl 243 CBC 622 : proc = PLy_procedure_get(funcoid, InvalidOid, false);
4044 tgl 244 GIC 619 : exec_ctx->curr_proc = proc;
4130 peter_e 245 619 : retval = PLy_exec_function(fcinfo, proc);
4130 peter_e 246 ECB : }
247 : }
4130 peter_e 248 CBC 85 : PG_CATCH();
4130 peter_e 249 ECB : {
4044 tgl 250 CBC 85 : PLy_pop_execution_context();
4130 peter_e 251 GIC 85 : PyErr_Clear();
4130 peter_e 252 CBC 85 : PG_RE_THROW();
253 : }
4130 peter_e 254 GIC 583 : PG_END_TRY();
4130 peter_e 255 ECB :
256 : /* Destroy the execution context */
4044 tgl 257 CBC 583 : PLy_pop_execution_context();
258 :
4130 peter_e 259 GIC 583 : return retval;
260 : }
4130 peter_e 261 ECB :
262 : Datum
398 andres 263 CBC 21 : plpython3_inline_handler(PG_FUNCTION_ARGS)
4130 peter_e 264 ECB : {
1534 andres 265 GIC 21 : LOCAL_FCINFO(fake_fcinfo, 0);
4130 peter_e 266 21 : InlineCodeBlock *codeblock = (InlineCodeBlock *) DatumGetPointer(PG_GETARG_DATUM(0));
267 : FmgrInfo flinfo;
268 : PLyProcedure proc;
269 : PLyExecutionContext *exec_ctx;
4130 peter_e 270 ECB : ErrorContextCallback plerrcontext;
271 :
2645 tgl 272 GIC 21 : PLy_initialize();
2645 tgl 273 ECB :
4044 tgl 274 EUB : /* Note: SPI_finish() happens in plpy_exec.c, which is dubious design */
1903 peter_e 275 GIC 21 : if (SPI_connect_ext(codeblock->atomic ? 0 : SPI_OPT_NONATOMIC) != SPI_OK_CONNECT)
4130 peter_e 276 LBC 0 : elog(ERROR, "SPI_connect failed");
4130 peter_e 277 ECB :
1534 andres 278 CBC 105 : MemSet(fcinfo, 0, SizeForFunctionCallInfo(0));
4130 peter_e 279 147 : MemSet(&flinfo, 0, sizeof(flinfo));
1534 andres 280 21 : fake_fcinfo->flinfo = &flinfo;
4130 peter_e 281 GIC 21 : flinfo.fn_oid = InvalidOid;
4130 peter_e 282 CBC 21 : flinfo.fn_mcxt = CurrentMemoryContext;
4130 peter_e 283 ECB :
4130 peter_e 284 GIC 861 : MemSet(&proc, 0, sizeof(PLyProcedure));
2712 tgl 285 21 : proc.mcxt = AllocSetContextCreate(TopMemoryContext,
2712 tgl 286 ECB : "__plpython_inline_block",
2416 287 : ALLOCSET_DEFAULT_SIZES);
2712 tgl 288 GIC 21 : proc.pyname = MemoryContextStrdup(proc.mcxt, "__plpython_inline_block");
2905 peter_e 289 21 : proc.langid = codeblock->langOid;
290 :
291 : /*
292 : * This is currently sufficient to get PLy_exec_function to work, but
1970 tgl 293 ECB : * someday we might need to be honest and use PLy_output_setup_func.
294 : */
1970 tgl 295 GIC 21 : proc.result.typoid = VOIDOID;
296 :
297 : /*
298 : * Push execution context onto stack. It is important that this get
299 : * popped again, so avoid putting anything that could throw error between
1880 tgl 300 ECB : * here and the PG_TRY.
301 : */
1903 peter_e 302 CBC 21 : exec_ctx = PLy_push_execution_context(codeblock->atomic);
303 :
4130 peter_e 304 GIC 21 : PG_TRY();
305 : {
306 : /*
307 : * Setup error traceback support for ereport().
308 : * plpython_inline_error_callback doesn't currently need exec_ctx, but
1880 tgl 309 ECB : * for consistency with plpython_call_handler we do it the same way.
310 : */
1880 tgl 311 CBC 21 : plerrcontext.callback = plpython_inline_error_callback;
312 21 : plerrcontext.arg = exec_ctx;
1880 tgl 313 GIC 21 : plerrcontext.previous = error_context_stack;
1880 tgl 314 CBC 21 : error_context_stack = &plerrcontext;
1880 tgl 315 ECB :
4130 peter_e 316 CBC 21 : PLy_procedure_compile(&proc, codeblock->source_text);
4044 tgl 317 GIC 21 : exec_ctx->curr_proc = &proc;
1534 andres 318 CBC 21 : PLy_exec_function(fake_fcinfo, &proc);
319 : }
4130 peter_e 320 11 : PG_CATCH();
4130 peter_e 321 ECB : {
4044 tgl 322 CBC 11 : PLy_pop_execution_context();
4130 peter_e 323 11 : PLy_procedure_delete(&proc);
4130 peter_e 324 GIC 11 : PyErr_Clear();
4130 peter_e 325 CBC 11 : PG_RE_THROW();
326 : }
4130 peter_e 327 GIC 10 : PG_END_TRY();
4130 peter_e 328 ECB :
329 : /* Destroy the execution context */
4044 tgl 330 GIC 10 : PLy_pop_execution_context();
4130 peter_e 331 ECB :
332 : /* Now clean up the transient procedure we made */
4044 tgl 333 CBC 10 : PLy_procedure_delete(&proc);
334 :
4130 peter_e 335 GIC 10 : PG_RETURN_VOID();
336 : }
4130 peter_e 337 ECB :
338 : static bool
3955 bruce 339 CBC 236 : PLy_procedure_is_trigger(Form_pg_proc procStruct)
340 : {
1130 tgl 341 GIC 236 : return (procStruct->prorettype == TRIGGEROID);
342 : }
4130 peter_e 343 ECB :
344 : static void
4130 peter_e 345 CBC 443 : plpython_error_callback(void *arg)
346 : {
1880 tgl 347 443 : PLyExecutionContext *exec_ctx = (PLyExecutionContext *) arg;
348 :
4044 349 443 : if (exec_ctx->curr_proc)
1956 peter_e 350 ECB : {
1956 peter_e 351 GIC 440 : if (exec_ctx->curr_proc->is_procedure)
352 4 : errcontext("PL/Python procedure \"%s\"",
1956 peter_e 353 ECB : PLy_procedure_name(exec_ctx->curr_proc));
354 : else
1956 peter_e 355 GIC 436 : errcontext("PL/Python function \"%s\"",
1956 peter_e 356 ECB : PLy_procedure_name(exec_ctx->curr_proc));
357 : }
4130 peter_e 358 GIC 443 : }
4130 peter_e 359 ECB :
360 : static void
4130 peter_e 361 CBC 28 : plpython_inline_error_callback(void *arg)
4130 peter_e 362 ECB : {
4130 peter_e 363 GIC 28 : errcontext("PL/Python anonymous code block");
364 28 : }
4044 tgl 365 ECB :
366 : PLyExecutionContext *
4044 tgl 367 CBC 1400 : PLy_current_execution_context(void)
4044 tgl 368 EUB : {
4044 tgl 369 GIC 1400 : if (PLy_execution_contexts == NULL)
4044 tgl 370 LBC 0 : elog(ERROR, "no Python function is currently executing");
371 :
4044 tgl 372 GIC 1400 : return PLy_execution_contexts;
373 : }
4044 tgl 374 ECB :
375 : MemoryContext
2712 tgl 376 GIC 779 : PLy_get_scratch_context(PLyExecutionContext *context)
377 : {
378 : /*
379 : * A scratch context might never be needed in a given plpython procedure,
2712 tgl 380 ECB : * so allocate it on first request.
381 : */
2712 tgl 382 CBC 779 : if (context->scratch_ctx == NULL)
2712 tgl 383 GIC 433 : context->scratch_ctx =
384 433 : AllocSetContextCreate(TopTransactionContext,
2712 tgl 385 ECB : "PL/Python scratch context",
386 : ALLOCSET_DEFAULT_SIZES);
2712 tgl 387 GIC 779 : return context->scratch_ctx;
388 : }
2712 tgl 389 ECB :
390 : static PLyExecutionContext *
1903 peter_e 391 GIC 689 : PLy_push_execution_context(bool atomic_context)
392 : {
393 : PLyExecutionContext *context;
394 :
1903 peter_e 395 ECB : /* Pick a memory context similar to what SPI uses. */
396 : context = (PLyExecutionContext *)
1903 peter_e 397 CBC 689 : MemoryContextAlloc(atomic_context ? TopTransactionContext : PortalContext,
1903 peter_e 398 ECB : sizeof(PLyExecutionContext));
4044 tgl 399 CBC 689 : context->curr_proc = NULL;
2712 400 689 : context->scratch_ctx = NULL;
4044 401 689 : context->next = PLy_execution_contexts;
4044 tgl 402 GIC 689 : PLy_execution_contexts = context;
403 689 : return context;
404 : }
4044 tgl 405 ECB :
406 : static void
4044 tgl 407 CBC 689 : PLy_pop_execution_context(void)
408 : {
3955 bruce 409 689 : PLyExecutionContext *context = PLy_execution_contexts;
4044 tgl 410 EUB :
4044 tgl 411 GIC 689 : if (context == NULL)
4044 tgl 412 LBC 0 : elog(ERROR, "no Python function is currently executing");
413 :
4044 tgl 414 CBC 689 : PLy_execution_contexts = context->next;
4044 tgl 415 ECB :
2712 tgl 416 CBC 689 : if (context->scratch_ctx)
417 416 : MemoryContextDelete(context->scratch_ctx);
2712 tgl 418 GIC 689 : pfree(context);
4044 419 689 : }
|