📄 plpython.c
字号:
* arguments. */ proc->nargs = fcinfo->nargs; for (i = 0; i < fcinfo->nargs; i++) { HeapTuple argTypeTup; Form_pg_type argTypeStruct; argTypeTup = SearchSysCache(TYPEOID, ObjectIdGetDatum(procStruct->proargtypes[i]), 0, 0, 0); if (!HeapTupleIsValid(argTypeTup)) elog(ERROR, "cache lookup failed for type %u", procStruct->proargtypes[i]); argTypeStruct = (Form_pg_type) GETSTRUCT(argTypeTup); if (argTypeStruct->typrelid == InvalidOid) PLy_input_datum_func(&(proc->args[i]), procStruct->proargtypes[i], argTypeStruct); else { TupleTableSlot *slot = (TupleTableSlot *) fcinfo->arg[i]; PLy_input_tuple_funcs(&(proc->args[i]), slot->ttc_tupleDescriptor); } ReleaseSysCache(argTypeTup); } /* * get the text of the function. */ procDatum = DirectFunctionCall1(textout, PointerGetDatum(&procStruct->prosrc)); procSource = DatumGetCString(procDatum); PLy_procedure_compile(proc, procSource); pfree(procSource); proc->me = PyCObject_FromVoidPtr(proc, NULL); PyDict_SetItemString(PLy_procedure_cache, key, proc->me); RESTORE_EXC(); return proc;}voidPLy_procedure_compile(PLyProcedure * proc, const char *src){ PyObject *crv = NULL; char *msrc; enter(); proc->globals = PyDict_Copy(PLy_interp_globals); /* * SD is private preserved data between calls GD is global data shared * by all functions */ proc->statics = PyDict_New(); PyDict_SetItemString(proc->globals, "SD", proc->statics); /* * insert the function code into the interpreter */ msrc = PLy_procedure_munge_source(proc->pyname, src); crv = PyRun_String(msrc, Py_file_input, proc->globals, NULL); free(msrc); if ((crv != NULL) && (!PyErr_Occurred())) { int clen; char call[NAMEDATALEN + 256]; Py_DECREF(crv); /* * compile a call to the function */ clen = snprintf(call, sizeof(call), "%s()", proc->pyname); if ((clen < 0) || (clen >= sizeof(call))) elog(ERROR, "string would overflow buffer"); proc->code = Py_CompileString(call, "<string>", Py_eval_input); if ((proc->code != NULL) && (!PyErr_Occurred())) return; } else Py_XDECREF(crv); PLy_elog(ERROR, "could not compile function \"%s\"", proc->proname);}char *PLy_procedure_munge_source(const char *name, const char *src){ char *mrc, *mp; const char *sp; size_t mlen, plen; enter(); /* * room for function source and the def statement */ mlen = (strlen(src) * 2) + strlen(name) + 16; mrc = PLy_malloc(mlen); plen = snprintf(mrc, mlen, "def %s():\n\t", name); Assert(plen >= 0 && plen < mlen); sp = src; mp = mrc + plen; while (*sp != '\0') { if (*sp == '\n') { *mp++ = *sp++; *mp++ = '\t'; } else *mp++ = *sp++; } *mp++ = '\n'; *mp++ = '\n'; *mp = '\0'; if (mp > (mrc + mlen)) elog(FATAL, "buffer overrun in PLy_munge_source"); return mrc;}voidPLy_procedure_delete(PLyProcedure * proc){ int i; enter(); Py_XDECREF(proc->code); Py_XDECREF(proc->statics); Py_XDECREF(proc->globals); Py_XDECREF(proc->me); if (proc->proname) PLy_free(proc->proname); if (proc->pyname) PLy_free(proc->pyname); for (i = 0; i < proc->nargs; i++) if (proc->args[i].is_rel == 1) { if (proc->args[i].in.r.atts) PLy_free(proc->args[i].in.r.atts); if (proc->args[i].out.r.atts) PLy_free(proc->args[i].out.r.atts); } leave();}/* conversion functions. remember output from python is * input to postgresql, and vis versa. */voidPLy_input_tuple_funcs(PLyTypeInfo * arg, TupleDesc desc){ int i; enter(); if (arg->is_rel == 0) elog(ERROR, "PLyTypeInfo struct is initialized for a Datum"); arg->is_rel = 1; arg->in.r.natts = desc->natts; arg->in.r.atts = malloc(desc->natts * sizeof(PLyDatumToOb)); for (i = 0; i < desc->natts; i++) { HeapTuple typeTup; Form_pg_type typeStruct; if (desc->attrs[i]->attisdropped) continue; typeTup = SearchSysCache(TYPEOID, ObjectIdGetDatum(desc->attrs[i]->atttypid), 0, 0, 0); if (!HeapTupleIsValid(typeTup)) elog(ERROR, "cache lookup failed for type %u", desc->attrs[i]->atttypid); typeStruct = (Form_pg_type) GETSTRUCT(typeTup); PLy_input_datum_func2(&(arg->in.r.atts[i]), desc->attrs[i]->atttypid, typeStruct); ReleaseSysCache(typeTup); }}voidPLy_output_tuple_funcs(PLyTypeInfo * arg, TupleDesc desc){ int i; enter(); if (arg->is_rel == 0) elog(ERROR, "PLyTypeInfo struct is initialized for a Datum"); arg->is_rel = 1; arg->out.r.natts = desc->natts; arg->out.r.atts = malloc(desc->natts * sizeof(PLyDatumToOb)); for (i = 0; i < desc->natts; i++) { HeapTuple typeTup; Form_pg_type typeStruct; if (desc->attrs[i]->attisdropped) continue; typeTup = SearchSysCache(TYPEOID, ObjectIdGetDatum(desc->attrs[i]->atttypid), 0, 0, 0); if (!HeapTupleIsValid(typeTup)) elog(ERROR, "cache lookup failed for type %u", desc->attrs[i]->atttypid); typeStruct = (Form_pg_type) GETSTRUCT(typeTup); PLy_output_datum_func2(&(arg->out.r.atts[i]), typeStruct); ReleaseSysCache(typeTup); }}voidPLy_output_datum_func(PLyTypeInfo * arg, Form_pg_type typeStruct){ enter(); if (arg->is_rel == 1) elog(ERROR, "PLyTypeInfo struct is initialized for a Tuple"); arg->is_rel = 0; PLy_output_datum_func2(&(arg->out.d), typeStruct);}voidPLy_output_datum_func2(PLyObToDatum * arg, Form_pg_type typeStruct){ enter(); perm_fmgr_info(typeStruct->typinput, &arg->typfunc); arg->typelem = typeStruct->typelem; arg->typbyval = typeStruct->typbyval;}voidPLy_input_datum_func(PLyTypeInfo * arg, Oid typeOid, Form_pg_type typeStruct){ enter(); if (arg->is_rel == 1) elog(ERROR, "PLyTypeInfo struct is initialized for Tuple"); arg->is_rel = 0; PLy_input_datum_func2(&(arg->in.d), typeOid, typeStruct);}voidPLy_input_datum_func2(PLyDatumToOb * arg, Oid typeOid, Form_pg_type typeStruct){ /* Get the type's conversion information */ perm_fmgr_info(typeStruct->typoutput, &arg->typfunc); arg->typelem = typeStruct->typelem; arg->typbyval = typeStruct->typbyval; /* Determine which kind of Python object we will convert to */ switch (typeOid) { case BOOLOID: arg->func = PLyBool_FromString; break; case FLOAT4OID: case FLOAT8OID: case NUMERICOID: arg->func = PLyFloat_FromString; break; case INT2OID: case INT4OID: arg->func = PLyInt_FromString; break; case INT8OID: arg->func = PLyLong_FromString; break; default: arg->func = PLyString_FromString; break; }}voidPLy_typeinfo_init(PLyTypeInfo * arg){ arg->is_rel = -1; arg->in.r.natts = arg->out.r.natts = 0; arg->in.r.atts = NULL; arg->out.r.atts = NULL;}voidPLy_typeinfo_dealloc(PLyTypeInfo * arg){ if (arg->is_rel == 1) { if (arg->in.r.atts) PLy_free(arg->in.r.atts); if (arg->out.r.atts) PLy_free(arg->out.r.atts); }}/* assumes that a bool is always returned as a 't' or 'f' */PyObject *PLyBool_FromString(const char *src){ enter(); if (src[0] == 't') return PyInt_FromLong(1); return PyInt_FromLong(0);}PyObject *PLyFloat_FromString(const char *src){ double v; char *eptr; enter(); errno = 0; v = strtod(src, &eptr); if ((*eptr != '\0') || (errno)) return NULL; return PyFloat_FromDouble(v);}PyObject *PLyInt_FromString(const char *src){ long v; char *eptr; enter(); errno = 0; v = strtol(src, &eptr, 0); if ((*eptr != '\0') || (errno)) return NULL; return PyInt_FromLong(v);}PyObject *PLyLong_FromString(const char *src){ return PyLong_FromString((char *) src, NULL, 0);}PyObject *PLyString_FromString(const char *src){ return PyString_FromString(src);}PyObject *PLyDict_FromTuple(PLyTypeInfo * info, HeapTuple tuple, TupleDesc desc){ DECLARE_EXC(); PyObject *volatile dict; int i; enter(); if (info->is_rel != 1) elog(ERROR, "PLyTypeInfo structure describes a datum"); dict = PyDict_New(); if (dict == NULL) PLy_elog(ERROR, "could not create tuple dictionary"); SAVE_EXC(); if (TRAP_EXC()) { RESTORE_EXC(); Py_DECREF(dict); RERAISE_EXC(); } for (i = 0; i < info->in.r.natts; i++) { char *key, *vsrc; Datum vattr, vdat; bool is_null; PyObject *value; if (desc->attrs[i]->attisdropped) continue; key = NameStr(desc->attrs[i]->attname); vattr = heap_getattr(tuple, (i + 1), desc, &is_null); if ((is_null) || (info->in.r.atts[i].func == NULL)) PyDict_SetItemString(dict, key, Py_None); else { vdat = FunctionCall3(&info->in.r.atts[i].typfunc, vattr, ObjectIdGetDatum(info->in.r.atts[i].typelem), Int32GetDatum(desc->attrs[i]->atttypmod)); vsrc = DatumGetCString(vdat); /* * no exceptions allowed */ value = info->in.r.atts[i].func(vsrc); pfree(vsrc); PyDict_SetItemString(dict, key, value); Py_DECREF(value); } } RESTORE_EXC(); return dict;}/* initialization, some python variables function declared here *//* interface to postgresql elog */static PyObject *PLy_debug(PyObject *, PyObject *);static PyObject *PLy_log(PyObject *, PyObject *);static PyObject *PLy_info(PyObject *, PyObject *);static PyObject *PLy_notice(PyObject *, PyObject *);static PyObject *PLy_warning(PyObject *, PyObject *);static PyObject *PLy_error(PyObject *, PyObject *);static PyObject *PLy_fatal(PyObject *, PyObject *);/* PLyPlanObject, PLyResultObject and SPI interface */#define is_PLyPlanObject(x) ((x)->ob_type == &PLy_PlanType)static PyObject *PLy_plan_new(void);static void PLy_plan_dealloc(PyObject *);static PyObject *PLy_plan_getattr(PyObject *, char *);static PyObject *PLy_plan_status(PyObject *, PyObject *);static PyObject *PLy_result_new(void);static void PLy_result_dealloc(PyObject *);static PyObject *PLy_result_getattr(PyObject *, char *);#ifdef NOT_USED/* Appear to be unused */static PyObject *PLy_result_fetch(PyObject *, PyObject *);static PyObject *PLy_result_nrows(PyObject *, PyObject *);static PyObject *PLy_result_status(PyObject *, PyObject *);#endifstatic int PLy_result_length(PyObject *);static PyObject *PLy_result_item(PyObject *, int);static PyObject *PLy_result_slice(PyObject *, int, int);static int PLy_result_ass_item(PyObject *, int, PyObject *);static int PLy_result_ass_slice(PyObject *, int, int, PyObject *);static PyObject *PLy_spi_prepare(PyObject *, PyObject *);static PyObject *PLy_spi_execute(PyObject *, PyObject *);static const char *PLy_spi_error_string(int);static PyObject *PLy_spi_execute_query(char *query, int limit);static PyObject *PLy_spi_execute_plan(PyObject *, PyObject *, int);static PyObject *PLy_spi_execute_fetch_result(SPITupleTable *, int, int);static PyTypeObject PLy_PlanType = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "PLyPlan", /* tp_name */ sizeof(PLyPlanObject), /* tp_size */ 0, /* tp_itemsize */ /* * methods */ (destructor) PLy_plan_dealloc, /* tp_dealloc */ 0, /* tp_print */ (getattrfunc) PLy_plan_getattr, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, /* tp_xxx4 */ PLy_plan_doc, /* tp_doc */};static PyMethodDef PLy_plan_methods[] = { {"status", (PyCFunction) PLy_plan_status, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL}};static PySequenceMethods PLy_result_as_sequence = { (inquiry) PLy_result_length, /* sq_length */ (binaryfunc) 0, /* sq_concat */ (intargfunc) 0, /* sq_repeat */ (intargfunc) PLy_result_item, /* sq_item */ (intintargfunc) PLy_result_slice, /* sq_slice */ (intobjargproc) PLy_result_ass_item, /* sq_ass_item */ (intintobjargproc) PLy_result_ass_slice, /* sq_ass_slice */};static PyTypeObject PLy_ResultType = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "PLyResult", /* tp_name */ sizeof(PLyResultObject), /* tp_size */ 0, /* tp_itemsize */ /* * methods */ (destructor) PLy_result_dealloc, /* tp_dealloc */ 0, /* tp_print */ (getattrfunc) PLy_result_getattr, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ &PLy_result_as_sequence, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -