diff options
Diffstat (limited to 'src/backend/libpq/be-pqexec.c')
-rw-r--r-- | src/backend/libpq/be-pqexec.c | 423 |
1 files changed, 0 insertions, 423 deletions
diff --git a/src/backend/libpq/be-pqexec.c b/src/backend/libpq/be-pqexec.c deleted file mode 100644 index 474da587792..00000000000 --- a/src/backend/libpq/be-pqexec.c +++ /dev/null @@ -1,423 +0,0 @@ -/*------------------------------------------------------------------------- - * - * be-pqexec.c - * support for executing POSTGRES commands and functions from a - * user-defined function in a backend. - * - * Portions Copyright (c) 1996-2000, PostgreSQL, Inc - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/Attic/be-pqexec.c,v 1.36 2000/07/07 21:12:53 tgl 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 "libpq/libpq.h" -#include "tcop/fastpath.h" -#include "tcop/tcopprot.h" -#include "utils/builtins.h" - -static 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 an array of PQArgBlock items. - * (length, if integer, and result-pointer) - * nargs : # of arguments in args array. - * - * This code scavenged 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) -{ - FmgrInfo flinfo; - FunctionCallInfoData fcinfo; - Datum retval; - int i; - - if (nargs > FUNC_MAX_ARGS) - elog(ERROR, "functions cannot have more than %d arguments", - FUNC_MAX_ARGS); - - /* ---------------- - * set up the argument block for the function manager - * ---------------- - */ - fmgr_info((Oid) fnid, &flinfo); - - MemSet(&fcinfo, 0, sizeof(fcinfo)); - fcinfo.flinfo = &flinfo; - fcinfo.nargs = nargs; - - for (i = 0; i < nargs; i++) - { - if (args[i].len == VAR_LENGTH_ARG) - fcinfo.arg[i] = (Datum) args[i].u.ptr; - else if ((Size) args[i].len > sizeof(int4)) - elog(ERROR, "arg_length of argument %d too long", i); - else - fcinfo.arg[i] = (Datum) args[i].u.integer; - } - - /* ---------------- - * call the postgres function manager - * ---------------- - */ - retval = FunctionCallInvoke(&fcinfo); - - /* ---------------- - * put the result in the buffer the user specified and - * return the proper code. - * ---------------- - */ - if (fcinfo.isnull) /* void retval */ - return "0"; - - if (result_is_int) - *result_buf = DatumGetInt32(retval); - else - memmove(result_buf, DatumGetPointer(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. - * - * XXX memory context manipulation is WRONG here --- the query needs - * to be executed in a context different from CurrentMemoryContext, - * perhaps a freshly created sub-context. If I were expecting that - * this code needs to work again, then I'd fix it. But actually I'm - * planning to rip out this entire module sometime soon... tgl 7/2000. - * ---------------- - */ - pg_exec_query_dest(query, Local, CurrentMemoryContext); - - /* ---------------- - * 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. - * ---------------- - */ -int -pqtest_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(len + 1); - memcpy(newstr, str, len); - newstr[len] = (char) 0; - return newstr; -} - -#define SKIP 0 -#define SCAN 1 - -static char spacestr[] = " "; - -static int -strparse(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 its string into a PQArgBlock and - * calls the specified function, which is assumed to return - * an integer value. - * ---------------- - */ -int -pqtest_PQfn(char *q) -{ - int k, - j, - i, - v, - f, - offsets; - char *fields[FUNC_MAX_ARGS]; - PQArgBlock pqargs[FUNC_MAX_ARGS]; - int res; - char *pqres; - - /* ---------------- - * parse q into fields - * ---------------- - */ - i = strparse(q, fields, &offsets, FUNC_MAX_ARGS); - 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 < FUNC_MAX_ARGS; 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 *) - DatumGetTextP(DirectFunctionCall1(textin, - CStringGetDatum(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 its test argument - * and decides which of pqtest_PQexec or pqtest_PQfn to call. - * ---------------- - */ -int32 -pqtest(struct varlena * vlena) -{ - char *q; - - /* ---------------- - * get the query - * ---------------- - */ - q = DatumGetCString(DirectFunctionCall1(textout, - PointerGetDatum(vlena))); - - switch (q[0]) - { - case '%': - return pqtest_PQfn(&q[1]); - break; - default: - return pqtest_PQexec(q); - break; - } - return 0; -} |