be-pqexec.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:8k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * be-pqexec.c
  4.  *   support for executing POSTGRES commands and functions from a
  5.  *   user-defined function in a backend.
  6.  *
  7.  * Copyright (c) 1994, Regents of the University of California
  8.  *
  9.  *
  10.  * IDENTIFICATION
  11.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/libpq/be-pqexec.c,v 1.20 1999/02/13 23:15:41 momjian Exp $
  12.  *
  13.  *-------------------------------------------------------------------------
  14.  */
  15. /*
  16.  * INTERFACE ROUTINES
  17.  * PQfn - call a POSTGRES function
  18.  * PQexec - execute a POSTGRES query
  19.  *
  20.  * NOTES
  21.  * These routines are compiled into the postgres backend.
  22.  */
  23. #include <postgres.h>
  24. #include <nodes/pg_list.h>
  25. #include <tcop/dest.h>
  26. #include <tcop/fastpath.h>
  27. #include <tcop/tcopprot.h>
  28. #include <lib/dllist.h>
  29. #include <libpq/libpq.h>
  30. #include <fmgr.h>
  31. #include <utils/exc.h>
  32. #include <utils/builtins.h>
  33. #ifndef HAVE_MEMMOVE
  34. #include <regex/utils.h>
  35. #else
  36. #include <string.h>
  37. #endif
  38. static char *strmake(char *str, int len);
  39. /* ----------------------------------------------------------------
  40.  * PQ interface routines
  41.  * ----------------------------------------------------------------
  42.  */
  43. /* ----------------
  44.  * PQfn - Send a function call to the POSTGRES backend.
  45.  *
  46.  * fnid : function id
  47.  * result_buf : pointer to result buffer (&int if integer)
  48.  * result_len : length of return value.
  49.  * result_is_int : If the result is an integer, this must be non-zero
  50.  * args : pointer to a NULL terminated arg array.
  51.  *   (length, if integer, and result-pointer)
  52.  * nargs : # of arguments in args array.
  53.  *
  54.  * This code scavanged from HandleFunctionRequest() in tcop/fastpath.h
  55.  * ----------------
  56.  */
  57. char *
  58. PQfn(int fnid,
  59.  int *result_buf, /* can't use void, dec compiler barfs */
  60.  int result_len,
  61.  int result_is_int,
  62.  PQArgBlock *args,
  63.  int nargs)
  64. {
  65. char    *retval; /* XXX - should be datum, maybe ? */
  66. char    *arg[8];
  67. int i;
  68. /* ----------------
  69.  * fill args[] array
  70.  * ----------------
  71.  */
  72. for (i = 0; i < nargs; i++)
  73. {
  74. if (args[i].len == VAR_LENGTH_ARG)
  75. arg[i] = (char *) args[i].u.ptr;
  76. else if (args[i].len > sizeof(int4))
  77. elog(ERROR, "arg_length of argument %d too long", i);
  78. else
  79. arg[i] = (char *) args[i].u.integer;
  80. }
  81. /* ----------------
  82.  * call the postgres function manager
  83.  * ----------------
  84.  */
  85. retval = (char *)
  86. fmgr(fnid, arg[0], arg[1], arg[2], arg[3],
  87.  arg[4], arg[5], arg[6], arg[7]);
  88. /* ----------------
  89.  * put the result in the buffer the user specified and
  90.  * return the proper code.
  91.  * ----------------
  92.  */
  93. if (retval == (char *) NULL)/* void retval */
  94. return "0";
  95. if (result_is_int)
  96. *result_buf = (int) retval;
  97. else
  98. memmove(result_buf, retval, result_len);
  99. return "G";
  100. }
  101. /* ----------------
  102.  * PQexec -  Send a query to the POSTGRES backend
  103.  *
  104.  * The return value is a string.
  105.  * If 0 or more tuples fetched from the backend, return "P portal-name".
  106.  * If a query is does not return tuples, return "C query-command".
  107.  * If there is an error: return "E error-message".
  108.  *
  109.  * Note: if we get a serious error or an elog(ERROR), then PQexec never
  110.  * returns because the system longjmp's back to the main loop.
  111.  * ----------------
  112.  */
  113. char *
  114. PQexec(char *query)
  115. {
  116. PortalEntry *entry = NULL;
  117. char    *result = NULL;
  118. /* ----------------
  119.  * create a new portal and put it on top of the portal stack.
  120.  * ----------------
  121.  */
  122. entry = (PortalEntry *) be_newportal();
  123. be_portalpush(entry);
  124. /* ----------------
  125.  * pg_exec_query_dest will put the query results in a portal which will
  126.  * end up on the top of the portal stack.
  127.  * ----------------
  128.  */
  129. pg_exec_query_dest(query, Local, FALSE);
  130. /* ----------------
  131.  * pop the portal off the portal stack and return the
  132.  * result.  Note if result is null, we return C.
  133.  * ----------------
  134.  */
  135. entry = (PortalEntry *) be_portalpop();
  136. result = entry->result;
  137. if (result == NULL)
  138. {
  139. char    *PQE = "Cnull PQexec result";
  140. result = pstrdup(PQE);
  141. }
  142. if (result[0] != 'P')
  143. {
  144. /*
  145.  * some successful command was executed, but it's not one where we
  146.  * return the portal name so here we should be sure to clear out
  147.  * the portal (since the caller has no handle on it)
  148.  */
  149. pbuf_close(entry->name);
  150. }
  151. return result;
  152. }
  153. /* ----------------------------------------------------------------
  154.  * pqtest support
  155.  * ----------------------------------------------------------------
  156.  */
  157. /* ----------------
  158.  * pqtest_PQexec takes a text query and returns the number of
  159.  * tuples it returns. Note: there is no need to PQclear()
  160.  * here - the memory will go away at end transaction.
  161.  * ----------------
  162.  */
  163. int
  164. pqtest_PQexec(char *q)
  165. {
  166. PortalBuffer *a;
  167. char    *res;
  168. int t;
  169. /* ----------------
  170.  * execute the postgres query
  171.  * ----------------
  172.  */
  173. res = PQexec(q);
  174. /* ----------------
  175.  * return number of tuples in portal or 0 if command returns no tuples.
  176.  * ----------------
  177.  */
  178. t = 0;
  179. switch (res[0])
  180. {
  181. case 'P':
  182. a = PQparray(&res[1]);
  183. if (a == NULL)
  184. elog(ERROR, "pqtest_PQexec: PQparray could not find portal %s",
  185.  res);
  186. t = PQntuples(a);
  187. break;
  188. case 'C':
  189. break;
  190. default:
  191. elog(NOTICE, "pqtest_PQexec: PQexec(%s) returns %s", q, res);
  192. break;
  193. }
  194. return t;
  195. }
  196. /* ----------------
  197.  * utilities for pqtest_PQfn()
  198.  * ----------------
  199.  */
  200. static char *
  201. strmake(char *str, int len)
  202. {
  203. char    *newstr;
  204. if (str == NULL)
  205. return NULL;
  206. if (len <= 0)
  207. len = strlen(str);
  208. newstr = (char *) palloc((unsigned) len + 1);
  209. StrNCpy(newstr, str, len + 1);
  210. newstr[len] = (char) 0;
  211. return newstr;
  212. }
  213. #define SKIP 0
  214. #define SCAN 1
  215. static char spacestr[] = " ";
  216. static int
  217. strparse(char *s, char **fields, int *offsets, int maxfields)
  218. {
  219. int len = strlen(s);
  220. char    *cp = s,
  221.    *end = cp + len,
  222.    *ep;
  223. int parsed = 0;
  224. int mode = SKIP,
  225. i = 0;
  226. if (*(end - 1) == 'n')
  227. end--;
  228. for (i = 0; i < maxfields; i++)
  229. fields[i] = spacestr;
  230. i = 0;
  231. while (!parsed)
  232. {
  233. if (mode == SKIP)
  234. {
  235. while ((cp < end) &&
  236.    (*cp == ' ' || *cp == 't'))
  237. cp++;
  238. if (cp < end)
  239. mode = SCAN;
  240. else
  241. parsed = 1;
  242. }
  243. else
  244. {
  245. ep = cp;
  246. while ((ep < end) && (*ep != ' ' && *ep != 't'))
  247. ep++;
  248. if (ep < end)
  249. mode = SKIP;
  250. else
  251. parsed = 1;
  252. fields[i] = strmake(cp, ep - cp);
  253. if (offsets != NULL)
  254. offsets[i] = cp - s;
  255. i++;
  256. cp = ep;
  257. if (i > maxfields)
  258. parsed = 1;
  259. }
  260. }
  261. return i;
  262. }
  263. /* ----------------
  264.  * pqtest_PQfn converts it's string into a PQArgBlock and
  265.  * calls the specified function, which is assumed to return
  266.  * an integer value.
  267.  * ----------------
  268.  */
  269. int
  270. pqtest_PQfn(char *q)
  271. {
  272. int k,
  273. j,
  274. i,
  275. v,
  276. f,
  277. offsets;
  278. char    *fields[8];
  279. PQArgBlock pqargs[7];
  280. int res;
  281. char    *pqres;
  282. /* ----------------
  283.  * parse q into fields
  284.  * ----------------
  285.  */
  286. i = strparse(q, fields, &offsets, 8);
  287. printf("pqtest_PQfn: strparse returns %d fieldsn", i); /* debug */
  288. if (i == 0)
  289. return -1;
  290. /* ----------------
  291.  * get the function id
  292.  * ----------------
  293.  */
  294. f = atoi(fields[0]);
  295. printf("pqtest_PQfn: func is %dn", f); /* debug */
  296. if (f == 0)
  297. return -1;
  298. /* ----------------
  299.  * build a PQArgBlock
  300.  * ----------------
  301.  */
  302. for (j = 1; j < i && j < 8; j++)
  303. {
  304. k = j - 1;
  305. v = atoi(fields[j]);
  306. if (v != 0 || (v == 0 && fields[j][0] == '0'))
  307. {
  308. pqargs[k].len = sizeof(int4);
  309. pqargs[k].u.integer = v;
  310. printf("pqtest_PQfn: arg %d is int %dn", k, v); /* debug */
  311. }
  312. else
  313. {
  314. pqargs[k].len = VAR_LENGTH_ARG;
  315. pqargs[k].u.ptr = (int *) textin(fields[j]);
  316. printf("pqtest_PQfn: arg %d is text %sn", k, fields[j]); /* debug */
  317. }
  318. }
  319. /* ----------------
  320.  * call PQfn
  321.  * ----------------
  322.  */
  323. pqres = PQfn(f, &res, sizeof(int4), 1, pqargs, i - 1);
  324. printf("pqtest_PQfn: pqres is %sn", pqres); /* debug */
  325. /* ----------------
  326.  * free memory used
  327.  * ----------------
  328.  */
  329. for (j = 0; j < i; j++)
  330. {
  331. pfree(fields[j]);
  332. if (pqargs[j].len == VAR_LENGTH_ARG)
  333. pfree(pqargs[j].u.ptr);
  334. }
  335. /* ----------------
  336.  * return result
  337.  * ----------------
  338.  */
  339. printf("pqtest_PQfn: res is %dn", res); /* debugg */
  340. return res;
  341. }
  342. /* ----------------
  343.  * pqtest looks at the first character of it's test argument
  344.  * and decides which of pqtest_PQexec or pqtest_PQfn to call.
  345.  * ----------------
  346.  */
  347. int32
  348. pqtest(struct varlena * vlena)
  349. {
  350. char    *q;
  351. /* ----------------
  352.  * get the query
  353.  * ----------------
  354.  */
  355. q = textout(vlena);
  356. if (q == NULL)
  357. return -1;
  358. switch (q[0])
  359. {
  360. case '%':
  361. return pqtest_PQfn(&q[1]);
  362. break;
  363. default:
  364. return pqtest_PQexec(q);
  365. break;
  366. }
  367. return 0;
  368. }