📄 plpython.c
字号:
} } if (rv < 0) { PLy_exception_set(PLy_exc_spi_error, "SPI_execute_plan failed: %s", SPI_result_code_string(rv)); return NULL; } return PLy_spi_execute_fetch_result(SPI_tuptable, SPI_processed, rv);}static PyObject *PLy_spi_execute_query(char *query, long limit){ int rv; MemoryContext oldcontext; oldcontext = CurrentMemoryContext; PG_TRY(); { rv = SPI_execute(query, PLy_curr_procedure->fn_readonly, limit); } PG_CATCH(); { MemoryContextSwitchTo(oldcontext); PLy_error_in_progress = CopyErrorData(); FlushErrorState(); if (!PyErr_Occurred()) PyErr_SetString(PLy_exc_spi_error, "Unknown error in PLy_spi_execute_query"); /* XXX this oughta be replaced with errcontext mechanism */ PLy_elog(WARNING, "in function %s:", PLy_procedure_name(PLy_curr_procedure)); return NULL; } PG_END_TRY(); if (rv < 0) { PLy_exception_set(PLy_exc_spi_error, "SPI_execute failed: %s", SPI_result_code_string(rv)); return NULL; } return PLy_spi_execute_fetch_result(SPI_tuptable, SPI_processed, rv);}static PyObject *PLy_spi_execute_fetch_result(SPITupleTable *tuptable, int rows, int status){ PLyResultObject *result; MemoryContext oldcontext; result = (PLyResultObject *) PLy_result_new(); Py_DECREF(result->status); result->status = PyInt_FromLong(status); if (status == SPI_OK_UTILITY) { Py_DECREF(result->nrows); result->nrows = PyInt_FromLong(0); } else if (status != SPI_OK_SELECT) { Py_DECREF(result->nrows); result->nrows = PyInt_FromLong(rows); } else { PLyTypeInfo args; int i; PLy_typeinfo_init(&args); Py_DECREF(result->nrows); result->nrows = PyInt_FromLong(rows); oldcontext = CurrentMemoryContext; PG_TRY(); { if (rows) { Py_DECREF(result->rows); result->rows = PyList_New(rows); PLy_input_tuple_funcs(&args, tuptable->tupdesc); for (i = 0; i < rows; i++) { PyObject *row = PLyDict_FromTuple(&args, tuptable->vals[i], tuptable->tupdesc); PyList_SetItem(result->rows, i, row); } PLy_typeinfo_dealloc(&args); SPI_freetuptable(tuptable); } } PG_CATCH(); { MemoryContextSwitchTo(oldcontext); PLy_error_in_progress = CopyErrorData(); FlushErrorState(); if (!PyErr_Occurred()) PyErr_SetString(PLy_exc_error, "Unknown error in PLy_spi_execute_fetch_result"); Py_DECREF(result); PLy_typeinfo_dealloc(&args); return NULL; } PG_END_TRY(); } return (PyObject *) result;}/* * language handler and interpreter initialization *//* * plpython_init() - Initialize everything that can be * safely initialized during postmaster * startup. * * DO NOT make this static --- it has to be callable by preload */voidplpython_init(void){ static volatile int init_active = 0; /* Do initialization only once */ if (!PLy_first_call) return; if (init_active) elog(FATAL, "initialization of language module failed"); init_active = 1; Py_Initialize(); PLy_init_interp(); PLy_init_plpy(); if (PyErr_Occurred()) PLy_elog(FATAL, "untrapped error in initialization"); PLy_procedure_cache = PyDict_New(); if (PLy_procedure_cache == NULL) PLy_elog(ERROR, "could not create procedure cache"); PLy_first_call = 0;}static voidPLy_init_all(void){ /* Execute postmaster-startup safe initialization */ if (PLy_first_call) plpython_init(); /* * Any other initialization that must be done each time a new backend * starts -- currently none */}static voidPLy_init_interp(void){ PyObject *mainmod; mainmod = PyImport_AddModule("__main__"); if ((mainmod == NULL) || (PyErr_Occurred())) PLy_elog(ERROR, "could not import \"__main__\" module."); Py_INCREF(mainmod); PLy_interp_globals = PyModule_GetDict(mainmod); PLy_interp_safe_globals = PyDict_New(); PyDict_SetItemString(PLy_interp_globals, "GD", PLy_interp_safe_globals); Py_DECREF(mainmod); if ((PLy_interp_globals == NULL) || (PyErr_Occurred())) PLy_elog(ERROR, "could not initialize globals");}static voidPLy_init_plpy(void){ PyObject *main_mod, *main_dict, *plpy_mod; PyObject *plpy, *plpy_dict; /* * initialize plpy module */ PLy_PlanType.ob_type = PLy_ResultType.ob_type = &PyType_Type; plpy = Py_InitModule("plpy", PLy_methods); plpy_dict = PyModule_GetDict(plpy); /* PyDict_SetItemString(plpy, "PlanType", (PyObject *) &PLy_PlanType); */ PLy_exc_error = PyErr_NewException("plpy.Error", NULL, NULL); PLy_exc_fatal = PyErr_NewException("plpy.Fatal", NULL, NULL); PLy_exc_spi_error = PyErr_NewException("plpy.SPIError", NULL, NULL); PyDict_SetItemString(plpy_dict, "Error", PLy_exc_error); PyDict_SetItemString(plpy_dict, "Fatal", PLy_exc_fatal); PyDict_SetItemString(plpy_dict, "SPIError", PLy_exc_spi_error); /* * initialize main module, and add plpy */ main_mod = PyImport_AddModule("__main__"); main_dict = PyModule_GetDict(main_mod); plpy_mod = PyImport_AddModule("plpy"); PyDict_SetItemString(main_dict, "plpy", plpy_mod); if (PyErr_Occurred()) elog(ERROR, "could not init plpy");}/* the python interface to the elog function * don't confuse these with PLy_elog */static PyObject *PLy_output(int, PyObject *, PyObject *);static PyObject *PLy_debug(PyObject * self, PyObject * args){ return PLy_output(DEBUG2, self, args);}static PyObject *PLy_log(PyObject * self, PyObject * args){ return PLy_output(LOG, self, args);}static PyObject *PLy_info(PyObject * self, PyObject * args){ return PLy_output(INFO, self, args);}static PyObject *PLy_notice(PyObject * self, PyObject * args){ return PLy_output(NOTICE, self, args);}static PyObject *PLy_warning(PyObject * self, PyObject * args){ return PLy_output(WARNING, self, args);}static PyObject *PLy_error(PyObject * self, PyObject * args){ return PLy_output(ERROR, self, args);}static PyObject *PLy_fatal(PyObject * self, PyObject * args){ return PLy_output(FATAL, self, args);}static PyObject *PLy_output(volatile int level, PyObject * self, PyObject * args){ PyObject *so; char *volatile sv; MemoryContext oldcontext; so = PyObject_Str(args); if ((so == NULL) || ((sv = PyString_AsString(so)) == NULL)) { level = ERROR; sv = "Unable to parse error message in `plpy.elog'"; } oldcontext = CurrentMemoryContext; PG_TRY(); { elog(level, "%s", sv); } PG_CATCH(); { MemoryContextSwitchTo(oldcontext); PLy_error_in_progress = CopyErrorData(); FlushErrorState(); Py_XDECREF(so); /* * returning NULL here causes the python interpreter to bail. when * control passes back to PLy_procedure_call, we check for PG * exceptions and re-throw the error. */ PyErr_SetString(PLy_exc_error, sv); return NULL; } PG_END_TRY(); Py_XDECREF(so); /* * return a legal object so the interpreter will continue on its merry way */ Py_INCREF(Py_None); return Py_None;}/* * Get the last procedure name called by the backend ( the innermost, * If a plpython procedure call calls the backend and the backend calls * another plpython procedure ) * * NB: this returns SQL name, not the internal Python procedure name */static char *PLy_procedure_name(PLyProcedure * proc){ if (proc == NULL) return "<unknown procedure>"; return proc->proname;}/* output a python traceback/exception via the postgresql elog * function. not pretty. */static voidPLy_exception_set(PyObject * exc, const char *fmt,...){ char buf[1024]; va_list ap; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); PyErr_SetString(exc, buf);}/* Emit a PG error or notice, together with any available info about the * current Python error. This should be used to propagate Python errors * into PG. */static voidPLy_elog(int elevel, const char *fmt,...){ va_list ap; char *xmsg, *emsg; int xlevel; xmsg = PLy_traceback(&xlevel); va_start(ap, fmt); emsg = PLy_vprintf(fmt, ap); va_end(ap); PG_TRY(); { ereport(elevel, (errmsg("plpython: %s", emsg), (xmsg) ? errdetail("%s", xmsg) : 0)); } PG_CATCH(); { PLy_free(emsg); if (xmsg) PLy_free(xmsg); PG_RE_THROW(); } PG_END_TRY(); PLy_free(emsg); if (xmsg) PLy_free(xmsg);}static char *PLy_traceback(int *xlevel){ PyObject *e, *v, *tb; PyObject *eob, *vob = NULL; char *vstr, *estr, *xstr = NULL; /* * get the current exception */ PyErr_Fetch(&e, &v, &tb); /* * oops, no exception, return */ if (e == NULL) { *xlevel = WARNING; return NULL; } PyErr_NormalizeException(&e, &v, &tb); Py_XDECREF(tb); eob = PyObject_Str(e); if ((v) && ((vob = PyObject_Str(v)) != NULL)) vstr = PyString_AsString(vob); else vstr = "Unknown"; /* * I'm not sure what to do if eob is NULL here -- we can't call PLy_elog * because that function calls us, so we could end up with infinite * recursion. I'm not even sure if eob could be NULL here -- would an * Assert() be more appropriate? */ estr = eob ? PyString_AsString(eob) : "Unknown Exception"; xstr = PLy_printf("%s: %s", estr, vstr); Py_DECREF(eob); Py_XDECREF(vob); Py_XDECREF(v); /* * intuit an appropriate error level based on the exception type */ if ((PLy_exc_error) && (PyErr_GivenExceptionMatches(e, PLy_exc_error))) *xlevel = ERROR; else if ((PLy_exc_fatal) && (PyErr_GivenExceptionMatches(e, PLy_exc_fatal))) *xlevel = FATAL; else *xlevel = ERROR; Py_DECREF(e); return xstr;}static char *PLy_printf(const char *fmt,...){ va_list ap; char *emsg; va_start(ap, fmt); emsg = PLy_vprintf(fmt, ap); va_end(ap); return emsg;}static char *PLy_vprintf(const char *fmt, va_list ap){ size_t blen; int bchar, tries = 2; char *buf; blen = strlen(fmt) * 2; if (blen < 256) blen = 256; buf = PLy_malloc(blen * sizeof(char)); while (1) { bchar = vsnprintf(buf, blen, fmt, ap); if ((bchar > 0) && (bchar < blen)) return buf; if (tries-- <= 0) break; if (blen > 0) blen = bchar + 1; else blen *= 2; buf = PLy_realloc(buf, blen); } PLy_free(buf); return NULL;}/* python module code *//* some dumb utility functions */static void *PLy_malloc(size_t bytes){ void *ptr = malloc(bytes); if (ptr == NULL) ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); return ptr;}static void *PLy_realloc(void *optr, size_t bytes){ void *nptr = realloc(optr, bytes); if (nptr == NULL) ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); return nptr;}/* define this away */static voidPLy_free(void *ptr){ free(ptr);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -