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