⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 plpython.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
					 errmsg("plpython functions cannot return tuples yet")));			else				PLy_output_datum_func(&proc->result, rvTypeTup);			ReleaseSysCache(rvTypeTup);		}		else		{			/*			 * input/output conversion for trigger tuples.	use the result			 * TypeInfo variable to store the tuple conversion info.			 */			TriggerData *tdata = (TriggerData *) fcinfo->context;			PLy_input_tuple_funcs(&(proc->result), tdata->tg_relation->rd_att);			PLy_output_tuple_funcs(&(proc->result), tdata->tg_relation->rd_att);		}		/*		 * now get information required for input conversion of the procedure's		 * arguments.		 */		proc->nargs = fcinfo->nargs;		for (i = 0; i < fcinfo->nargs; i++)		{			HeapTuple	argTypeTup;			Form_pg_type argTypeStruct;			argTypeTup = SearchSysCache(TYPEOID,						 ObjectIdGetDatum(procStruct->proargtypes.values[i]),										0, 0, 0);			if (!HeapTupleIsValid(argTypeTup))				elog(ERROR, "cache lookup failed for type %u",					 procStruct->proargtypes.values[i]);			argTypeStruct = (Form_pg_type) GETSTRUCT(argTypeTup);			/* Disallow pseudotype argument */			if (argTypeStruct->typtype == 'p')				ereport(ERROR,						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),						 errmsg("plpython functions cannot take type %s",						format_type_be(procStruct->proargtypes.values[i]))));			if (argTypeStruct->typtype != 'c')				PLy_input_datum_func(&(proc->args[i]),									 procStruct->proargtypes.values[i],									 argTypeTup);			else				proc->args[i].is_rowtype = 2;	/* still need to set I/O funcs */			ReleaseSysCache(argTypeTup);		}		/*		 * get the text of the function.		 */		prosrcdatum = SysCacheGetAttr(PROCOID, procTup,									  Anum_pg_proc_prosrc, &isnull);		if (isnull)			elog(ERROR, "null prosrc");		procSource = DatumGetCString(DirectFunctionCall1(textout,														 prosrcdatum));		PLy_procedure_compile(proc, procSource);		pfree(procSource);		proc->me = PyCObject_FromVoidPtr(proc, NULL);		PyDict_SetItemString(PLy_procedure_cache, key, proc->me);	}	PG_CATCH();	{		PLy_procedure_delete(proc);		if (procSource)			pfree(procSource);		PG_RE_THROW();	}	PG_END_TRY();	return proc;}static voidPLy_procedure_compile(PLyProcedure * proc, const char *src){	PyObject   *crv = NULL;	char	   *msrc;	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);}static char *PLy_procedure_munge_source(const char *name, const char *src){	char	   *mrc,			   *mp;	const char *sp;	size_t		mlen,				plen;	/*	 * 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 == '\r' && *(sp + 1) == '\n')			sp++;		if (*sp == '\n' || *sp == '\r')		{			*mp++ = '\n';			*mp++ = '\t';			sp++;		}		else			*mp++ = *sp++;	}	*mp++ = '\n';	*mp++ = '\n';	*mp = '\0';	if (mp > (mrc + mlen))		elog(FATAL, "buffer overrun in PLy_munge_source");	return mrc;}static voidPLy_procedure_delete(PLyProcedure * proc){	int			i;	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_rowtype == 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);		}}/* conversion functions.  remember output from python is * input to postgresql, and vis versa. */static voidPLy_input_tuple_funcs(PLyTypeInfo * arg, TupleDesc desc){	int			i;	if (arg->is_rowtype == 0)		elog(ERROR, "PLyTypeInfo struct is initialized for a Datum");	arg->is_rowtype = 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;		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);		PLy_input_datum_func2(&(arg->in.r.atts[i]),							  desc->attrs[i]->atttypid,							  typeTup);		ReleaseSysCache(typeTup);	}}static voidPLy_output_tuple_funcs(PLyTypeInfo * arg, TupleDesc desc){	int			i;	if (arg->is_rowtype == 0)		elog(ERROR, "PLyTypeInfo struct is initialized for a Datum");	arg->is_rowtype = 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;		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);		PLy_output_datum_func2(&(arg->out.r.atts[i]), typeTup);		ReleaseSysCache(typeTup);	}}static voidPLy_output_datum_func(PLyTypeInfo * arg, HeapTuple typeTup){	if (arg->is_rowtype > 0)		elog(ERROR, "PLyTypeInfo struct is initialized for a Tuple");	arg->is_rowtype = 0;	PLy_output_datum_func2(&(arg->out.d), typeTup);}static voidPLy_output_datum_func2(PLyObToDatum * arg, HeapTuple typeTup){	Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);	perm_fmgr_info(typeStruct->typinput, &arg->typfunc);	arg->typioparam = getTypeIOParam(typeTup);	arg->typbyval = typeStruct->typbyval;}static voidPLy_input_datum_func(PLyTypeInfo * arg, Oid typeOid, HeapTuple typeTup){	if (arg->is_rowtype > 0)		elog(ERROR, "PLyTypeInfo struct is initialized for Tuple");	arg->is_rowtype = 0;	PLy_input_datum_func2(&(arg->in.d), typeOid, typeTup);}static voidPLy_input_datum_func2(PLyDatumToOb * arg, Oid typeOid, HeapTuple typeTup){	Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);	/* Get the type's conversion information */	perm_fmgr_info(typeStruct->typoutput, &arg->typfunc);	arg->typioparam = getTypeIOParam(typeTup);	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;	}}static voidPLy_typeinfo_init(PLyTypeInfo * arg){	arg->is_rowtype = -1;	arg->in.r.natts = arg->out.r.natts = 0;	arg->in.r.atts = NULL;	arg->out.r.atts = NULL;}static voidPLy_typeinfo_dealloc(PLyTypeInfo * arg){	if (arg->is_rowtype == 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' */static PyObject *PLyBool_FromString(const char *src){	if (src[0] == 't')		return PyInt_FromLong(1);	return PyInt_FromLong(0);}static PyObject *PLyFloat_FromString(const char *src){	double		v;	char	   *eptr;	errno = 0;	v = strtod(src, &eptr);	if ((*eptr != '\0') || (errno))		return NULL;	return PyFloat_FromDouble(v);}static PyObject *PLyInt_FromString(const char *src){	long		v;	char	   *eptr;	errno = 0;	v = strtol(src, &eptr, 0);	if ((*eptr != '\0') || (errno))		return NULL;	return PyInt_FromLong(v);}static PyObject *PLyLong_FromString(const char *src){	return PyLong_FromString((char *) src, NULL, 0);}static PyObject *PLyString_FromString(const char *src){	return PyString_FromString(src);}static PyObject *PLyDict_FromTuple(PLyTypeInfo * info, HeapTuple tuple, TupleDesc desc){	PyObject   *volatile dict;	int			i;	if (info->is_rowtype != 1)		elog(ERROR, "PLyTypeInfo structure describes a datum");	dict = PyDict_New();	if (dict == NULL)		PLy_elog(ERROR, "could not create tuple dictionary");	PG_TRY();	{		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].typioparam),								   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);			}		}	}	PG_CATCH();	{		Py_DECREF(dict);		PG_RE_THROW();	}	PG_END_TRY();	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 *);static PyObject *PLy_result_nrows(PyObject *, PyObject *);static PyObject *PLy_result_status(PyObject *, PyObject *);static 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 PyObject *PLy_spi_execute_query(char *query, long limit);static PyObject *PLy_spi_execute_plan(PyObject *, PyObject *, long);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", PLy_plan_status, METH_VARARGS, NULL},	{NULL, NULL, 0, NULL}};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -