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

📄 plpython.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
			}			else			{				modvalues[i] = (Datum) 0;				modnulls[i] = 'n';			}			Py_DECREF(plval);			plval = NULL;		}		rtup = SPI_modifytuple(tdata->tg_relation, otup, natts,							   modattrs, modvalues, modnulls);		if (rtup == NULL)			elog(ERROR, "SPI_modifytuple failed -- error %d", SPI_result);	}	PG_CATCH();	{		Py_XDECREF(plntup);		Py_XDECREF(plkeys);		Py_XDECREF(plval);		Py_XDECREF(plstr);		if (modnulls)			pfree(modnulls);		if (modvalues)			pfree(modvalues);		if (modattrs)			pfree(modattrs);		PG_RE_THROW();	}	PG_END_TRY();	Py_DECREF(plntup);	Py_DECREF(plkeys);	pfree(modattrs);	pfree(modvalues);	pfree(modnulls);	return rtup;}static PyObject *PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure * proc, HeapTuple *rv){	TriggerData *tdata = (TriggerData *) fcinfo->context;	PyObject   *pltname,			   *pltevent,			   *pltwhen,			   *pltlevel,			   *pltrelid;	PyObject   *pltargs,			   *pytnew,			   *pytold;	PyObject   *volatile pltdata = NULL;	char	   *stroid;	PG_TRY();	{		pltdata = PyDict_New();		if (!pltdata)			PLy_elog(ERROR, "could not build arguments for trigger procedure");		pltname = PyString_FromString(tdata->tg_trigger->tgname);		PyDict_SetItemString(pltdata, "name", pltname);		Py_DECREF(pltname);		stroid = DatumGetCString(DirectFunctionCall1(oidout,							   ObjectIdGetDatum(tdata->tg_relation->rd_id)));		pltrelid = PyString_FromString(stroid);		PyDict_SetItemString(pltdata, "relid", pltrelid);		Py_DECREF(pltrelid);		pfree(stroid);		if (TRIGGER_FIRED_BEFORE(tdata->tg_event))			pltwhen = PyString_FromString("BEFORE");		else if (TRIGGER_FIRED_AFTER(tdata->tg_event))			pltwhen = PyString_FromString("AFTER");		else		{			elog(ERROR, "unrecognized WHEN tg_event: %u", tdata->tg_event);			pltwhen = NULL;		/* keep compiler quiet */		}		PyDict_SetItemString(pltdata, "when", pltwhen);		Py_DECREF(pltwhen);		if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))		{			pltlevel = PyString_FromString("ROW");			PyDict_SetItemString(pltdata, "level", pltlevel);			Py_DECREF(pltlevel);			if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event))			{				pltevent = PyString_FromString("INSERT");				PyDict_SetItemString(pltdata, "old", Py_None);				pytnew = PLyDict_FromTuple(&(proc->result), tdata->tg_trigtuple,										   tdata->tg_relation->rd_att);				PyDict_SetItemString(pltdata, "new", pytnew);				Py_DECREF(pytnew);				*rv = tdata->tg_trigtuple;			}			else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))			{				pltevent = PyString_FromString("DELETE");				PyDict_SetItemString(pltdata, "new", Py_None);				pytold = PLyDict_FromTuple(&(proc->result), tdata->tg_trigtuple,										   tdata->tg_relation->rd_att);				PyDict_SetItemString(pltdata, "old", pytold);				Py_DECREF(pytold);				*rv = tdata->tg_trigtuple;			}			else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))			{				pltevent = PyString_FromString("UPDATE");				pytnew = PLyDict_FromTuple(&(proc->result), tdata->tg_newtuple,										   tdata->tg_relation->rd_att);				PyDict_SetItemString(pltdata, "new", pytnew);				Py_DECREF(pytnew);				pytold = PLyDict_FromTuple(&(proc->result), tdata->tg_trigtuple,										   tdata->tg_relation->rd_att);				PyDict_SetItemString(pltdata, "old", pytold);				Py_DECREF(pytold);				*rv = tdata->tg_newtuple;			}			else			{				elog(ERROR, "unrecognized OP tg_event: %u", tdata->tg_event);				pltevent = NULL;	/* keep compiler quiet */			}			PyDict_SetItemString(pltdata, "event", pltevent);			Py_DECREF(pltevent);		}		else if (TRIGGER_FIRED_FOR_STATEMENT(tdata->tg_event))		{			pltlevel = PyString_FromString("STATEMENT");			PyDict_SetItemString(pltdata, "level", pltlevel);			Py_DECREF(pltlevel);			PyDict_SetItemString(pltdata, "old", Py_None);			PyDict_SetItemString(pltdata, "new", Py_None);			*rv = NULL;			if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event))				pltevent = PyString_FromString("INSERT");			else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))				pltevent = PyString_FromString("DELETE");			else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))				pltevent = PyString_FromString("UPDATE");			else			{				elog(ERROR, "unrecognized OP tg_event: %u", tdata->tg_event);				pltevent = NULL;	/* keep compiler quiet */			}			PyDict_SetItemString(pltdata, "event", pltevent);			Py_DECREF(pltevent);		}		else			elog(ERROR, "unrecognized LEVEL tg_event: %u", tdata->tg_event);		if (tdata->tg_trigger->tgnargs)		{			/*			 * all strings...			 */			int			i;			PyObject   *pltarg;			pltargs = PyList_New(tdata->tg_trigger->tgnargs);			for (i = 0; i < tdata->tg_trigger->tgnargs; i++)			{				pltarg = PyString_FromString(tdata->tg_trigger->tgargs[i]);				/*				 * stolen, don't Py_DECREF				 */				PyList_SetItem(pltargs, i, pltarg);			}		}		else		{			Py_INCREF(Py_None);			pltargs = Py_None;		}		PyDict_SetItemString(pltdata, "args", pltargs);		Py_DECREF(pltargs);	}	PG_CATCH();	{		Py_XDECREF(pltdata);		PG_RE_THROW();	}	PG_END_TRY();	return pltdata;}/* function handler and friends */static DatumPLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure * proc){	Datum		rv;	PyObject   *volatile plargs = NULL;	PyObject   *volatile plrv = NULL;	PyObject   *volatile plrv_so = NULL;	char	   *plrv_sc;	PG_TRY();	{		plargs = PLy_function_build_args(fcinfo, proc);		plrv = PLy_procedure_call(proc, "args", plargs);		Assert(plrv != NULL);		Assert(!PLy_error_in_progress);		/*		 * Disconnect from SPI manager and then create the return values datum		 * (if the input function does a palloc for it this must not be		 * allocated in the SPI memory context because SPI_finish would free		 * it).		 */		if (SPI_finish() != SPI_OK_FINISH)			elog(ERROR, "SPI_finish failed");		/*		 * convert the python PyObject to a postgresql Datum		 */		if (plrv == Py_None)		{			fcinfo->isnull = true;			rv = (Datum) NULL;		}		else		{			fcinfo->isnull = false;			plrv_so = PyObject_Str(plrv);			if (!plrv_so)				PLy_elog(ERROR, "function \"%s\" could not create return value", proc->proname);			plrv_sc = PyString_AsString(plrv_so);			rv = FunctionCall3(&proc->result.out.d.typfunc,							   PointerGetDatum(plrv_sc),							 ObjectIdGetDatum(proc->result.out.d.typioparam),							   Int32GetDatum(-1));		}	}	PG_CATCH();	{		Py_XDECREF(plargs);		Py_XDECREF(plrv);		Py_XDECREF(plrv_so);		PG_RE_THROW();	}	PG_END_TRY();	Py_XDECREF(plargs);	Py_DECREF(plrv);	Py_XDECREF(plrv_so);	return rv;}static PyObject *PLy_procedure_call(PLyProcedure * proc, char *kargs, PyObject * vargs){	PyObject   *rv;	PyDict_SetItemString(proc->globals, kargs, vargs);	rv = PyEval_EvalCode((PyCodeObject *) proc->code,						 proc->globals, proc->globals);	/*	 * If there was an error in a PG callback, propagate that no matter what	 * Python claims about its success.	 */	if (PLy_error_in_progress)	{		ErrorData  *edata = PLy_error_in_progress;		PLy_error_in_progress = NULL;		ReThrowError(edata);	}	if ((rv == NULL) || (PyErr_Occurred()))	{		Py_XDECREF(rv);		PLy_elog(ERROR, "function \"%s\" failed", proc->proname);	}	return rv;}static PyObject *PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure * proc){	PyObject   *volatile arg = NULL;	PyObject   *volatile args = NULL;	int			i;	PG_TRY();	{		args = PyList_New(proc->nargs);		for (i = 0; i < proc->nargs; i++)		{			if (proc->args[i].is_rowtype > 0)			{				if (fcinfo->argnull[i])					arg = NULL;				else				{					HeapTupleHeader td;					Oid			tupType;					int32		tupTypmod;					TupleDesc	tupdesc;					HeapTupleData tmptup;					td = DatumGetHeapTupleHeader(fcinfo->arg[i]);					/* Extract rowtype info and find a tupdesc */					tupType = HeapTupleHeaderGetTypeId(td);					tupTypmod = HeapTupleHeaderGetTypMod(td);					tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);					tupdesc = CreateTupleDescCopy(tupdesc);					/* Set up I/O funcs if not done yet */					if (proc->args[i].is_rowtype != 1)						PLy_input_tuple_funcs(&(proc->args[i]), tupdesc);					/* Build a temporary HeapTuple control structure */					tmptup.t_len = HeapTupleHeaderGetDatumLength(td);					tmptup.t_data = td;					arg = PLyDict_FromTuple(&(proc->args[i]), &tmptup, tupdesc);					FreeTupleDesc(tupdesc);				}			}			else			{				if (fcinfo->argnull[i])					arg = NULL;				else				{					char	   *ct;					Datum		dt;					dt = FunctionCall3(&(proc->args[i].in.d.typfunc),									   fcinfo->arg[i],							 ObjectIdGetDatum(proc->args[i].in.d.typioparam),									   Int32GetDatum(-1));					ct = DatumGetCString(dt);					arg = (proc->args[i].in.d.func) (ct);					pfree(ct);				}			}			if (arg == NULL)			{				Py_INCREF(Py_None);				arg = Py_None;			}			/*			 * FIXME -- error check this			 */			PyList_SetItem(args, i, arg);			arg = NULL;		}	}	PG_CATCH();	{		Py_XDECREF(arg);		Py_XDECREF(args);		PG_RE_THROW();	}	PG_END_TRY();	return args;}/* * PLyProcedure functions *//* PLy_procedure_get: returns a cached PLyProcedure, or creates, stores and * returns a new PLyProcedure.	fcinfo is the call info, tgreloid is the * relation OID when calling a trigger, or InvalidOid (zero) for ordinary * function calls. */static PLyProcedure *PLy_procedure_get(FunctionCallInfo fcinfo, Oid tgreloid){	Oid			fn_oid;	HeapTuple	procTup;	char		key[128];	PyObject   *plproc;	PLyProcedure *proc = NULL;	int			rv;	fn_oid = fcinfo->flinfo->fn_oid;	procTup = SearchSysCache(PROCOID,							 ObjectIdGetDatum(fn_oid),							 0, 0, 0);	if (!HeapTupleIsValid(procTup))		elog(ERROR, "cache lookup failed for function %u", fn_oid);	rv = snprintf(key, sizeof(key), "%u_%u", fn_oid, tgreloid);	if ((rv >= sizeof(key)) || (rv < 0))		elog(ERROR, "key too long");	plproc = PyDict_GetItemString(PLy_procedure_cache, key);	if (plproc != NULL)	{		Py_INCREF(plproc);		if (!PyCObject_Check(plproc))			elog(FATAL, "expected a PyCObject, didn't get one");		proc = PyCObject_AsVoidPtr(plproc);		if (proc->me != plproc)			elog(FATAL, "proc->me != plproc");		/* did we find an up-to-date cache entry? */		if (proc->fn_xmin != HeapTupleHeaderGetXmin(procTup->t_data) ||			proc->fn_cmin != HeapTupleHeaderGetCmin(procTup->t_data))		{			Py_DECREF(plproc);			proc = NULL;		}	}	if (proc == NULL)		proc = PLy_procedure_create(fcinfo, tgreloid, procTup, key);	ReleaseSysCache(procTup);	return proc;}static PLyProcedure *PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid,					 HeapTuple procTup, char *key){	char		procName[NAMEDATALEN + 256];	Form_pg_proc procStruct;	PLyProcedure *volatile proc;	char	   *volatile procSource = NULL;	Datum		prosrcdatum;	bool		isnull;	int			i,				rv;	procStruct = (Form_pg_proc) GETSTRUCT(procTup);	if (OidIsValid(tgreloid))		rv = snprintf(procName, sizeof(procName),					  "__plpython_procedure_%s_%u_trigger_%u",					  NameStr(procStruct->proname),					  fcinfo->flinfo->fn_oid,					  tgreloid);	else		rv = snprintf(procName, sizeof(procName),					  "__plpython_procedure_%s_%u",					  NameStr(procStruct->proname),					  fcinfo->flinfo->fn_oid);	if ((rv >= sizeof(procName)) || (rv < 0))		elog(ERROR, "procedure name would overrun buffer");	proc = PLy_malloc(sizeof(PLyProcedure));	proc->proname = PLy_malloc(strlen(NameStr(procStruct->proname)) + 1);	strcpy(proc->proname, NameStr(procStruct->proname));	proc->pyname = PLy_malloc(strlen(procName) + 1);	strcpy(proc->pyname, procName);	proc->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);	proc->fn_cmin = HeapTupleHeaderGetCmin(procTup->t_data);	/* Remember if function is STABLE/IMMUTABLE */	proc->fn_readonly =		(procStruct->provolatile != PROVOLATILE_VOLATILE);	PLy_typeinfo_init(&proc->result);	for (i = 0; i < FUNC_MAX_ARGS; i++)		PLy_typeinfo_init(&proc->args[i]);	proc->nargs = 0;	proc->code = proc->statics = NULL;	proc->globals = proc->me = NULL;	PG_TRY();	{		/*		 * get information required for output conversion of the return value,		 * but only if this isn't a trigger.		 */		if (!CALLED_AS_TRIGGER(fcinfo))		{			HeapTuple	rvTypeTup;			Form_pg_type rvTypeStruct;			rvTypeTup = SearchSysCache(TYPEOID,									ObjectIdGetDatum(procStruct->prorettype),									   0, 0, 0);			if (!HeapTupleIsValid(rvTypeTup))				elog(ERROR, "cache lookup failed for type %u",					 procStruct->prorettype);			rvTypeStruct = (Form_pg_type) GETSTRUCT(rvTypeTup);			/* Disallow pseudotype result */			if (rvTypeStruct->typtype == 'p')			{				if (procStruct->prorettype == TRIGGEROID)					ereport(ERROR,							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),							 errmsg("trigger functions may only be called as triggers")));				else					ereport(ERROR,							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),						   errmsg("plpython functions cannot return type %s",								  format_type_be(procStruct->prorettype))));			}			if (rvTypeStruct->typtype == 'c')				ereport(ERROR,						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

⌨️ 快捷键说明

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