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

📄 be-pqexec.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
字号:
/*------------------------------------------------------------------------- * * be-pqexec.c *	  support for executing POSTGRES commands and functions from a *	  user-defined function in a backend. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/libpq/be-pqexec.c,v 1.20 1999/02/13 23:15:41 momjian Exp $ * *------------------------------------------------------------------------- *//* * INTERFACE ROUTINES *		PQfn			- call a POSTGRES function *		PQexec			- execute a POSTGRES query * * NOTES *		These routines are compiled into the postgres backend. */#include <postgres.h>#include <nodes/pg_list.h>#include <tcop/dest.h>#include <tcop/fastpath.h>#include <tcop/tcopprot.h>#include <lib/dllist.h>#include <libpq/libpq.h>#include <fmgr.h>#include <utils/exc.h>#include <utils/builtins.h>#ifndef HAVE_MEMMOVE#include <regex/utils.h>#else#include <string.h>#endifstatic char *strmake(char *str, int len);/* ---------------------------------------------------------------- *						PQ interface routines * ---------------------------------------------------------------- *//* ---------------- *		PQfn -	Send a function call to the POSTGRES backend. * *		fnid			: function id *		result_buf		: pointer to result buffer (&int if integer) *		result_len		: length of return value. *		result_is_int	: If the result is an integer, this must be non-zero *		args			: pointer to a NULL terminated arg array. *						  (length, if integer, and result-pointer) *		nargs			: # of arguments in args array. * *		This code scavanged from HandleFunctionRequest() in tcop/fastpath.h * ---------------- */char *PQfn(int fnid,	 int *result_buf,			/* can't use void, dec compiler barfs */	 int result_len,	 int result_is_int,	 PQArgBlock *args,	 int nargs){	char	   *retval;			/* XXX - should be datum, maybe ? */	char	   *arg[8];	int			i;	/* ----------------	 *	fill args[] array	 * ----------------	 */	for (i = 0; i < nargs; i++)	{		if (args[i].len == VAR_LENGTH_ARG)			arg[i] = (char *) args[i].u.ptr;		else if (args[i].len > sizeof(int4))			elog(ERROR, "arg_length of argument %d too long", i);		else			arg[i] = (char *) args[i].u.integer;	}	/* ----------------	 *	call the postgres function manager	 * ----------------	 */	retval = (char *)		fmgr(fnid, arg[0], arg[1], arg[2], arg[3],			 arg[4], arg[5], arg[6], arg[7]);	/* ----------------	 *	put the result in the buffer the user specified and	 *	return the proper code.	 * ----------------	 */	if (retval == (char *) NULL)/* void retval */		return "0";	if (result_is_int)		*result_buf = (int) retval;	else		memmove(result_buf, retval, result_len);	return "G";}/* ---------------- *		PQexec -  Send a query to the POSTGRES backend * *		The return value is a string. *		If 0 or more tuples fetched from the backend, return "P portal-name". *		If a query is does not return tuples, return "C query-command". *		If there is an error: return "E error-message". * *		Note: if we get a serious error or an elog(ERROR), then PQexec never *		returns because the system longjmp's back to the main loop. * ---------------- */char *PQexec(char *query){	PortalEntry *entry = NULL;	char	   *result = NULL;	/* ----------------	 *	create a new portal and put it on top of the portal stack.	 * ----------------	 */	entry = (PortalEntry *) be_newportal();	be_portalpush(entry);	/* ----------------	 *	pg_exec_query_dest will put the query results in a portal which will	 *	end up on the top of the portal stack.	 * ----------------	 */	pg_exec_query_dest(query, Local, FALSE);	/* ----------------	 *	pop the portal off the portal stack and return the	 *	result.  Note if result is null, we return C.	 * ----------------	 */	entry = (PortalEntry *) be_portalpop();	result = entry->result;	if (result == NULL)	{		char	   *PQE = "Cnull PQexec result";		result = pstrdup(PQE);	}	if (result[0] != 'P')	{		/*		 * some successful command was executed, but it's not one where we		 * return the portal name so here we should be sure to clear out		 * the portal (since the caller has no handle on it)		 */		pbuf_close(entry->name);	}	return result;}/* ---------------------------------------------------------------- *						pqtest support * ---------------------------------------------------------------- *//* ---------------- *		pqtest_PQexec takes a text query and returns the number of *		tuples it returns.	Note: there is no need to PQclear() *		here - the memory will go away at end transaction. * ---------------- */intpqtest_PQexec(char *q){	PortalBuffer *a;	char	   *res;	int			t;	/* ----------------	 *	execute the postgres query	 * ----------------	 */	res = PQexec(q);	/* ----------------	 *	return number of tuples in portal or 0 if command returns no tuples.	 * ----------------	 */	t = 0;	switch (res[0])	{		case 'P':			a = PQparray(&res[1]);			if (a == NULL)				elog(ERROR, "pqtest_PQexec: PQparray could not find portal %s",					 res);			t = PQntuples(a);			break;		case 'C':			break;		default:			elog(NOTICE, "pqtest_PQexec: PQexec(%s) returns %s", q, res);			break;	}	return t;}/* ---------------- *		utilities for pqtest_PQfn() * ---------------- */static char *strmake(char *str, int len){	char	   *newstr;	if (str == NULL)		return NULL;	if (len <= 0)		len = strlen(str);	newstr = (char *) palloc((unsigned) len + 1);	StrNCpy(newstr, str, len + 1);	newstr[len] = (char) 0;	return newstr;}#define SKIP 0#define SCAN 1static char spacestr[] = " ";static intstrparse(char *s, char **fields, int *offsets, int maxfields){	int			len = strlen(s);	char	   *cp = s,			   *end = cp + len,			   *ep;	int			parsed = 0;	int			mode = SKIP,				i = 0;	if (*(end - 1) == '\n')		end--;	for (i = 0; i < maxfields; i++)		fields[i] = spacestr;	i = 0;	while (!parsed)	{		if (mode == SKIP)		{			while ((cp < end) &&				   (*cp == ' ' || *cp == '\t'))				cp++;			if (cp < end)				mode = SCAN;			else				parsed = 1;		}		else		{			ep = cp;			while ((ep < end) && (*ep != ' ' && *ep != '\t'))				ep++;			if (ep < end)				mode = SKIP;			else				parsed = 1;			fields[i] = strmake(cp, ep - cp);			if (offsets != NULL)				offsets[i] = cp - s;			i++;			cp = ep;			if (i > maxfields)				parsed = 1;		}	}	return i;}/* ---------------- *		pqtest_PQfn converts it's string into a PQArgBlock and *		calls the specified function, which is assumed to return *		an integer value. * ---------------- */intpqtest_PQfn(char *q){	int			k,				j,				i,				v,				f,				offsets;	char	   *fields[8];	PQArgBlock	pqargs[7];	int			res;	char	   *pqres;	/* ----------------	 *	parse q into fields	 * ----------------	 */	i = strparse(q, fields, &offsets, 8);	printf("pqtest_PQfn: strparse returns %d fields\n", i);		/* debug */	if (i == 0)		return -1;	/* ----------------	 *	get the function id	 * ----------------	 */	f = atoi(fields[0]);	printf("pqtest_PQfn: func is %d\n", f);		/* debug */	if (f == 0)		return -1;	/* ----------------	 *	build a PQArgBlock	 * ----------------	 */	for (j = 1; j < i && j < 8; j++)	{		k = j - 1;		v = atoi(fields[j]);		if (v != 0 || (v == 0 && fields[j][0] == '0'))		{			pqargs[k].len = sizeof(int4);			pqargs[k].u.integer = v;			printf("pqtest_PQfn: arg %d is int %d\n", k, v);	/* debug */		}		else		{			pqargs[k].len = VAR_LENGTH_ARG;			pqargs[k].u.ptr = (int *) textin(fields[j]);			printf("pqtest_PQfn: arg %d is text %s\n", k, fields[j]);	/* debug */		}	}	/* ----------------	 *	call PQfn	 * ----------------	 */	pqres = PQfn(f, &res, sizeof(int4), 1, pqargs, i - 1);	printf("pqtest_PQfn: pqres is %s\n", pqres);		/* debug */	/* ----------------	 *	free memory used	 * ----------------	 */	for (j = 0; j < i; j++)	{		pfree(fields[j]);		if (pqargs[j].len == VAR_LENGTH_ARG)			pfree(pqargs[j].u.ptr);	}	/* ----------------	 *	return result	 * ----------------	 */	printf("pqtest_PQfn: res is %d\n", res);	/* debugg */	return res;}/* ---------------- *		pqtest looks at the first character of it's test argument *		and decides which of pqtest_PQexec or pqtest_PQfn to call. * ---------------- */int32pqtest(struct varlena * vlena){	char	   *q;	/* ----------------	 *	get the query	 * ----------------	 */	q = textout(vlena);	if (q == NULL)		return -1;	switch (q[0])	{		case '%':			return pqtest_PQfn(&q[1]);			break;		default:			return pqtest_PQexec(q);			break;	}	return 0;}

⌨️ 快捷键说明

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