📄 plpython.c
字号:
0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_xxx4 */ PLy_result_doc, /* tp_doc */};#ifdef NOT_USED/* Appear to be unused */static PyMethodDef PLy_result_methods[] = { {"fetch", (PyCFunction) PLy_result_fetch, METH_VARARGS, NULL,}, {"nrows", (PyCFunction) PLy_result_nrows, METH_VARARGS, NULL}, {"status", (PyCFunction) PLy_result_status, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL}};#endifstatic PyMethodDef PLy_methods[] = { /* * logging methods */ {"debug", PLy_debug, METH_VARARGS, NULL}, {"log", PLy_log, METH_VARARGS, NULL}, {"info", PLy_info, METH_VARARGS, NULL}, {"notice", PLy_notice, METH_VARARGS, NULL}, {"warning", PLy_warning, METH_VARARGS, NULL}, {"error", PLy_error, METH_VARARGS, NULL}, {"fatal", PLy_fatal, METH_VARARGS, NULL}, /* * create a stored plan */ {"prepare", PLy_spi_prepare, METH_VARARGS, NULL}, /* * execute a plan or query */ {"execute", PLy_spi_execute, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL}};/* plan object methods */PyObject *PLy_plan_new(void){ PLyPlanObject *ob; enter(); if ((ob = PyObject_NEW(PLyPlanObject, &PLy_PlanType)) == NULL) return NULL; ob->plan = NULL; ob->nargs = 0; ob->types = NULL; ob->args = NULL; return (PyObject *) ob;}voidPLy_plan_dealloc(PyObject * arg){ PLyPlanObject *ob = (PLyPlanObject *) arg; enter(); if (ob->plan) SPI_freeplan(ob->plan); if (ob->types) PLy_free(ob->types); if (ob->args) { int i; for (i = 0; i < ob->nargs; i++) PLy_typeinfo_dealloc(&ob->args[i]); PLy_free(ob->args); } PyMem_DEL(arg); leave();}PyObject *PLy_plan_getattr(PyObject * self, char *name){ return Py_FindMethod(PLy_plan_methods, self, name);}PyObject *PLy_plan_status(PyObject * self, PyObject * args){ if (PyArg_ParseTuple(args, "")) { Py_INCREF(Py_True); return Py_True; /* return PyInt_FromLong(self->status); */ } PyErr_SetString(PLy_exc_error, "plan.status() takes no arguments"); return NULL;}/* result object methods */PyObject *PLy_result_new(void){ PLyResultObject *ob; enter(); if ((ob = PyObject_NEW(PLyResultObject, &PLy_ResultType)) == NULL) return NULL; /* ob->tuples = NULL; */ Py_INCREF(Py_None); ob->status = Py_None; ob->nrows = PyInt_FromLong(-1); ob->rows = PyList_New(0); return (PyObject *) ob;}voidPLy_result_dealloc(PyObject * arg){ PLyResultObject *ob = (PLyResultObject *) arg; enter(); Py_XDECREF(ob->nrows); Py_XDECREF(ob->rows); Py_XDECREF(ob->status); PyMem_DEL(ob);}PyObject *PLy_result_getattr(PyObject * self, char *attr){ return NULL;}#ifdef NOT_USED/* Appear to be unused */PyObject *PLy_result_fetch(PyObject * self, PyObject * args){ return NULL;}PyObject *PLy_result_nrows(PyObject * self, PyObject * args){ PLyResultObject *ob = (PLyResultObject *) self; Py_INCREF(ob->nrows); return ob->nrows;}PyObject *PLy_result_status(PyObject * self, PyObject * args){ PLyResultObject *ob = (PLyResultObject *) self; Py_INCREF(ob->status); return ob->status;}#endifintPLy_result_length(PyObject * arg){ PLyResultObject *ob = (PLyResultObject *) arg; return PyList_Size(ob->rows);}PyObject *PLy_result_item(PyObject * arg, int idx){ PyObject *rv; PLyResultObject *ob = (PLyResultObject *) arg; rv = PyList_GetItem(ob->rows, idx); if (rv != NULL) Py_INCREF(rv); return rv;}intPLy_result_ass_item(PyObject * arg, int idx, PyObject * item){ int rv; PLyResultObject *ob = (PLyResultObject *) arg; Py_INCREF(item); rv = PyList_SetItem(ob->rows, idx, item); return rv;}PyObject *PLy_result_slice(PyObject * arg, int lidx, int hidx){ PyObject *rv; PLyResultObject *ob = (PLyResultObject *) arg; rv = PyList_GetSlice(ob->rows, lidx, hidx); if (rv == NULL) return NULL; Py_INCREF(rv); return rv;}intPLy_result_ass_slice(PyObject * arg, int lidx, int hidx, PyObject * slice){ int rv; PLyResultObject *ob = (PLyResultObject *) arg; rv = PyList_SetSlice(ob->rows, lidx, hidx, slice); return rv;}/* SPI interface */PyObject *PLy_spi_prepare(PyObject * self, PyObject * args){ DECLARE_EXC(); PLyPlanObject *plan; PyObject *list = NULL; PyObject *volatile optr = NULL; char *query; void *tmpplan; enter(); if (!PyArg_ParseTuple(args, "s|O", &query, &list)) { PyErr_SetString(PLy_exc_spi_error, "Invalid arguments for plpy.prepare()"); return NULL; } if ((list) && (!PySequence_Check(list))) { PyErr_SetString(PLy_exc_spi_error, "Second argument in plpy.prepare() must be a sequence"); return NULL; } if ((plan = (PLyPlanObject *) PLy_plan_new()) == NULL) return NULL; SAVE_EXC(); if (TRAP_EXC()) { RESTORE_EXC(); Py_DECREF(plan); Py_XDECREF(optr); if (!PyErr_Occurred()) PyErr_SetString(PLy_exc_spi_error, "Unknown error in PLy_spi_prepare"); /* XXX this oughta be replaced with errcontext mechanism */ PLy_elog(WARNING, "in function %s:", PLy_procedure_name(PLy_last_procedure)); RERAISE_EXC(); } if (list != NULL) { int nargs, i; nargs = PySequence_Length(list); if (nargs > 0) { plan->nargs = nargs; plan->types = PLy_malloc(sizeof(Oid) * nargs); plan->values = PLy_malloc(sizeof(Datum) * nargs); plan->args = PLy_malloc(sizeof(PLyTypeInfo) * nargs); /* * the other loop might throw an exception, if PLyTypeInfo * member isn't properly initialized the Py_DECREF(plan) will * go boom */ for (i = 0; i < nargs; i++) { PLy_typeinfo_init(&plan->args[i]); plan->values[i] = (Datum) NULL; } for (i = 0; i < nargs; i++) { char *sptr; HeapTuple typeTup; Form_pg_type typeStruct; optr = PySequence_GetItem(list, i); if (!PyString_Check(optr)) { PyErr_SetString(PLy_exc_spi_error, "Type names must be strings."); RAISE_EXC(1); } sptr = PyString_AsString(optr); /* XXX should extend this to allow qualified type names */ typeTup = typenameType(makeTypeName(sptr)); Py_DECREF(optr); optr = NULL; /* this is important */ plan->types[i] = HeapTupleGetOid(typeTup); typeStruct = (Form_pg_type) GETSTRUCT(typeTup); if (typeStruct->typrelid == InvalidOid) PLy_output_datum_func(&plan->args[i], typeStruct); else { PyErr_SetString(PLy_exc_spi_error, "tuples not handled in plpy.prepare, yet."); RAISE_EXC(1); } ReleaseSysCache(typeTup); } } } plan->plan = SPI_prepare(query, plan->nargs, plan->types); if (plan->plan == NULL) { PLy_exception_set(PLy_exc_spi_error, "Unable to prepare plan. SPI_prepare failed -- %s.", PLy_spi_error_string(SPI_result)); RAISE_EXC(1); } /* transfer plan from procCxt to topCxt */ tmpplan = plan->plan; plan->plan = SPI_saveplan(tmpplan); SPI_freeplan(tmpplan); if (plan->plan == NULL) { PLy_exception_set(PLy_exc_spi_error, "Unable to save plan. SPI_saveplan failed -- %s.", PLy_spi_error_string(SPI_result)); RAISE_EXC(1); } RESTORE_EXC(); return (PyObject *) plan;}/* execute(query="select * from foo", limit=5) * execute(plan=plan, values=(foo, bar), limit=5) */PyObject *PLy_spi_execute(PyObject * self, PyObject * args){ char *query; PyObject *plan; PyObject *list = NULL; int limit = 0; enter();#ifdef NOT_USED /* * there should - hahaha - be an python exception set so just return * NULL. FIXME -- is this needed? */ if (PLy_restart_in_progress) return NULL;#endif if (PyArg_ParseTuple(args, "s|i", &query, &limit)) return PLy_spi_execute_query(query, limit); PyErr_Clear(); if ((PyArg_ParseTuple(args, "O|Oi", &plan, &list, &limit)) && (is_PLyPlanObject(plan))) { PyObject *rv = PLy_spi_execute_plan(plan, list, limit); return rv; } PyErr_SetString(PLy_exc_error, "Expected a query or plan."); return NULL;}PyObject *PLy_spi_execute_plan(PyObject * ob, PyObject * list, int limit){ DECLARE_EXC(); volatile int nargs; int i, rv; PLyPlanObject *plan; char *nulls; enter(); if (list != NULL) { if ((!PySequence_Check(list)) || (PyString_Check(list))) { char *msg = "plpy.execute() takes a sequence as its second argument"; PyErr_SetString(PLy_exc_spi_error, msg); return NULL; } nargs = PySequence_Length(list); } else nargs = 0; plan = (PLyPlanObject *) ob; if (nargs != plan->nargs) { char *sv; PyObject *so = PyObject_Str(list); sv = PyString_AsString(so); PLy_exception_set(PLy_exc_spi_error, "Expected sequence of %d arguments, got %d. %s", plan->nargs, nargs, sv); Py_DECREF(so); return NULL; } SAVE_EXC(); if (TRAP_EXC()) { RESTORE_EXC(); /* * cleanup plan->values array */ for (i = 0; i < nargs; i++) { if (!plan->args[i].out.d.typbyval && (plan->values[i] != (Datum) NULL)) { pfree(DatumGetPointer(plan->values[i])); plan->values[i] = (Datum) NULL; } } if (!PyErr_Occurred()) PyErr_SetString(PLy_exc_error, "Unknown error in PLy_spi_execute_plan"); PLy_elog(WARNING, "in function %s:", PLy_procedure_name(PLy_last_procedure)); RERAISE_EXC(); } if (nargs) { nulls = palloc((nargs + 1) * sizeof(char)); for (i = 0; i < nargs; i++) { PyObject *elem, *so; char *sv; elem = PySequence_GetItem(list, i); if (elem != Py_None) { so = PyObject_Str(elem); sv = PyString_AsString(so); /* * FIXME -- if this can elog, we have leak */ plan->values[i] = FunctionCall3(&(plan->args[i].out.d.typfunc), CStringGetDatum(sv), ObjectIdGetDatum(plan->args[i].out.d.typelem), Int32GetDatum(-1)); Py_DECREF(so); Py_DECREF(elem); nulls[i] = ' '; } else { Py_DECREF(elem); plan->values[i] = (Datum) 0; nulls[i] = 'n'; } } nulls[i] = '\0'; } else nulls = NULL; rv = SPI_execp(plan->plan, plan->values, nulls, limit); RESTORE_EXC(); for (i = 0; i < nargs; i++) { if (!plan->args[i].out.d.typbyval && (plan->values[i] != (Datum) NULL)) { pfree(DatumGetPointer(plan->values[i])); plan->values[i] = (Datum) NULL; } } if (rv < 0) { PLy_exception_set(PLy_exc_spi_error, "Unable to execute plan. SPI_execp failed -- %s", PLy_spi_error_string(rv)); return NULL; } return PLy_spi_execute_fetch_result(SPI_tuptable, SPI_processed, rv);}PyObject *PLy_spi_execute_query(char *query, int limit){ DECLARE_EXC(); int rv; SAVE_EXC(); if (TRAP_EXC()) { RESTORE_EXC(); if ((!PLy_restart_in_progress) && (!PyErr_Occurred())) PyErr_SetString(PLy_exc_spi_error, "Unknown error in PLy_spi_execute_query"); PLy_elog(WARNING, "in function %s:", PLy_procedure_name(PLy_last_procedure)); RERAISE_EXC(); } rv = SPI_exec(query, limit); RESTORE_EXC(); if (rv < 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -