pl_handler.c

来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 226 行

C
226
字号
/*------------------------------------------------------------------------- * * pl_handler.c		- Handler for the PL/pgSQL *			  procedural language * * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.38 2008/01/01 19:46:00 momjian Exp $ * *------------------------------------------------------------------------- */#include "plpgsql.h"#include "pl.tab.h"#include "access/heapam.h"#include "catalog/pg_proc.h"#include "catalog/pg_type.h"#include "funcapi.h"#include "utils/builtins.h"#include "utils/guc.h"#include "utils/lsyscache.h"#include "utils/syscache.h"PG_MODULE_MAGIC;PLpgSQL_plugin **plugin_ptr = NULL;/* * _PG_init()			- library load-time initialization * * DO NOT make this static nor change its name! */void_PG_init(void){	/* Be sure we do initialization only once (should be redundant now) */	static bool inited = false;	if (inited)		return;	plpgsql_HashTableInit();	RegisterXactCallback(plpgsql_xact_cb, NULL);	RegisterSubXactCallback(plpgsql_subxact_cb, NULL);	/* Set up a rendezvous point with optional instrumentation plugin */	plugin_ptr = (PLpgSQL_plugin **) find_rendezvous_variable("PLpgSQL_plugin");	inited = true;}/* ---------- * plpgsql_call_handler * * The PostgreSQL function manager and trigger manager * call this function for execution of PL/pgSQL procedures. * ---------- */PG_FUNCTION_INFO_V1(plpgsql_call_handler);Datumplpgsql_call_handler(PG_FUNCTION_ARGS){	PLpgSQL_function *func;	Datum		retval;	int			rc;	/*	 * Connect to SPI manager	 */	if ((rc = SPI_connect()) != SPI_OK_CONNECT)		elog(ERROR, "SPI_connect failed: %s", SPI_result_code_string(rc));	/* Find or compile the function */	func = plpgsql_compile(fcinfo, false);	/* Mark the function as busy, so it can't be deleted from under us */	func->use_count++;	PG_TRY();	{		/*		 * Determine if called as function or trigger and call appropriate		 * subhandler		 */		if (CALLED_AS_TRIGGER(fcinfo))			retval = PointerGetDatum(plpgsql_exec_trigger(func,										   (TriggerData *) fcinfo->context));		else			retval = plpgsql_exec_function(func, fcinfo);	}	PG_CATCH();	{		/* Decrement use-count and propagate error */		func->use_count--;		PG_RE_THROW();	}	PG_END_TRY();	func->use_count--;	/*	 * Disconnect from SPI manager	 */	if ((rc = SPI_finish()) != SPI_OK_FINISH)		elog(ERROR, "SPI_finish failed: %s", SPI_result_code_string(rc));	return retval;}/* ---------- * plpgsql_validator * * This function attempts to validate a PL/pgSQL function at * CREATE FUNCTION time. * ---------- */PG_FUNCTION_INFO_V1(plpgsql_validator);Datumplpgsql_validator(PG_FUNCTION_ARGS){	Oid			funcoid = PG_GETARG_OID(0);	HeapTuple	tuple;	Form_pg_proc proc;	char		functyptype;	int			numargs;	Oid		   *argtypes;	char	  **argnames;	char	   *argmodes;	bool		istrigger = false;	int			i;	/* Get the new function's pg_proc entry */	tuple = SearchSysCache(PROCOID,						   ObjectIdGetDatum(funcoid),						   0, 0, 0);	if (!HeapTupleIsValid(tuple))		elog(ERROR, "cache lookup failed for function %u", funcoid);	proc = (Form_pg_proc) GETSTRUCT(tuple);	functyptype = get_typtype(proc->prorettype);	/* Disallow pseudotype result */	/* except for TRIGGER, RECORD, VOID, or polymorphic */	if (functyptype == TYPTYPE_PSEUDO)	{		/* we assume OPAQUE with no arguments means a trigger */		if (proc->prorettype == TRIGGEROID ||			(proc->prorettype == OPAQUEOID && proc->pronargs == 0))			istrigger = true;		else if (proc->prorettype != RECORDOID &&				 proc->prorettype != VOIDOID &&				 !IsPolymorphicType(proc->prorettype))			ereport(ERROR,					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),					 errmsg("plpgsql functions cannot return type %s",							format_type_be(proc->prorettype))));	}	/* Disallow pseudotypes in arguments (either IN or OUT) */	/* except for polymorphic */	numargs = get_func_arg_info(tuple,								&argtypes, &argnames, &argmodes);	for (i = 0; i < numargs; i++)	{		if (get_typtype(argtypes[i]) == TYPTYPE_PSEUDO)		{			if (!IsPolymorphicType(argtypes[i]))				ereport(ERROR,						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),						 errmsg("plpgsql functions cannot take type %s",								format_type_be(argtypes[i]))));		}	}	/* Postpone body checks if !check_function_bodies */	if (check_function_bodies)	{		FunctionCallInfoData fake_fcinfo;		FmgrInfo	flinfo;		TriggerData trigdata;		int			rc;		/*		 * Connect to SPI manager (is this needed for compilation?)		 */		if ((rc = SPI_connect()) != SPI_OK_CONNECT)			elog(ERROR, "SPI_connect failed: %s", SPI_result_code_string(rc));		/*		 * Set up a fake fcinfo with just enough info to satisfy		 * plpgsql_compile().		 */		MemSet(&fake_fcinfo, 0, sizeof(fake_fcinfo));		MemSet(&flinfo, 0, sizeof(flinfo));		fake_fcinfo.flinfo = &flinfo;		flinfo.fn_oid = funcoid;		flinfo.fn_mcxt = CurrentMemoryContext;		if (istrigger)		{			MemSet(&trigdata, 0, sizeof(trigdata));			trigdata.type = T_TriggerData;			fake_fcinfo.context = (Node *) &trigdata;		}		/* Test-compile the function */		plpgsql_compile(&fake_fcinfo, true);		/*		 * Disconnect from SPI manager		 */		if ((rc = SPI_finish()) != SPI_OK_FINISH)			elog(ERROR, "SPI_finish failed: %s", SPI_result_code_string(rc));	}	ReleaseSysCache(tuple);	PG_RETURN_VOID();}

⌨️ 快捷键说明

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