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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * fmgr.c
  4.  *   Interface routines for the table-driven function manager.
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.28.2.1 1999/08/02 05:25:06 scrappy Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include "postgres.h"
  15. #include "catalog/pg_language.h"
  16. #include "catalog/pg_proc.h"
  17. #include "commands/trigger.h"
  18. #include "utils/builtins.h"
  19. #include "utils/fmgrtab.h"
  20. #include "utils/syscache.h"
  21. /*
  22.  * Interface for PL functions
  23.  *
  24.  * XXX: use of global fmgr_pl_finfo variable is really ugly.  FIXME
  25.  */
  26. static char *
  27. fmgr_pl(char *arg0,...)
  28. {
  29. va_list pvar;
  30. FmgrValues values;
  31. int n_arguments = fmgr_pl_finfo->fn_nargs;
  32. bool isNull = false;
  33. int i;
  34. memset(&values, 0, sizeof(values));
  35. if (n_arguments > 0)
  36. {
  37. values.data[0] = arg0;
  38. if (n_arguments > 1)
  39. {
  40. if (n_arguments > MAXFMGRARGS)
  41. elog(ERROR, "fmgr_pl: function %u: too many arguments (%d > %d)",
  42.  fmgr_pl_finfo->fn_oid, n_arguments, MAXFMGRARGS);
  43. va_start(pvar, arg0);
  44. for (i = 1; i < n_arguments; i++)
  45. values.data[i] = va_arg(pvar, char *);
  46. va_end(pvar);
  47. }
  48. }
  49. /* Call the PL handler */
  50. CurrentTriggerData = NULL;
  51. return (*(fmgr_pl_finfo->fn_plhandler)) (fmgr_pl_finfo,
  52.  &values,
  53.  &isNull);
  54. }
  55. /*
  56.  * Interface for untrusted functions
  57.  */
  58. static char *
  59. fmgr_untrusted(char *arg0,...)
  60. {
  61. /*
  62.  * Currently these are unsupported.  Someday we might do something
  63.  * like forking a subprocess to execute 'em.
  64.  */
  65. elog(ERROR, "Untrusted functions not supported.");
  66. return NULL; /* keep compiler happy */
  67. }
  68. /*
  69.  * Interface for SQL-language functions
  70.  */
  71. static char *
  72. fmgr_sql(char *arg0,...)
  73. {
  74. /*
  75.  * XXX It'd be really nice to support SQL functions anywhere that
  76.  * builtins are supported. What would we have to do?  What pitfalls
  77.  * are there?
  78.  */
  79. elog(ERROR, "SQL-language function not supported in this context.");
  80. return NULL; /* keep compiler happy */
  81. }
  82. /*
  83.  * fmgr_c is not really for C functions only; it can be called for functions
  84.  * in any language.  Many parts of the system use this entry point if they
  85.  * want to pass the arguments in an array rather than as explicit arguments.
  86.  */
  87. char *
  88. fmgr_c(FmgrInfo *finfo,
  89.    FmgrValues *values,
  90.    bool *isNull)
  91. {
  92. char    *returnValue = (char *) NULL;
  93. int n_arguments = finfo->fn_nargs;
  94. func_ptr user_fn = fmgr_faddr(finfo);
  95. /*
  96.  * If finfo contains a PL handler for this function, call that
  97.  * instead.
  98.  */
  99. if (finfo->fn_plhandler != NULL)
  100. return (*(finfo->fn_plhandler)) (finfo, values, isNull);
  101. if (user_fn == (func_ptr) NULL)
  102. elog(ERROR, "Internal error: fmgr_c received NULL function pointer.");
  103. switch (n_arguments)
  104. {
  105. case 0:
  106. returnValue = (*user_fn) ();
  107. break;
  108. case 1:
  109. /* NullValue() uses isNull to check if args[0] is NULL */
  110. returnValue = (*user_fn) (values->data[0], isNull);
  111. break;
  112. case 2:
  113. returnValue = (*user_fn) (values->data[0], values->data[1]);
  114. break;
  115. case 3:
  116. returnValue = (*user_fn) (values->data[0], values->data[1],
  117.   values->data[2]);
  118. break;
  119. case 4:
  120. returnValue = (*user_fn) (values->data[0], values->data[1],
  121.   values->data[2], values->data[3]);
  122. break;
  123. case 5:
  124. returnValue = (*user_fn) (values->data[0], values->data[1],
  125.   values->data[2], values->data[3],
  126.   values->data[4]);
  127. break;
  128. case 6:
  129. returnValue = (*user_fn) (values->data[0], values->data[1],
  130.   values->data[2], values->data[3],
  131.   values->data[4], values->data[5]);
  132. break;
  133. case 7:
  134. returnValue = (*user_fn) (values->data[0], values->data[1],
  135.   values->data[2], values->data[3],
  136.   values->data[4], values->data[5],
  137.   values->data[6]);
  138. break;
  139. case 8:
  140. returnValue = (*user_fn) (values->data[0], values->data[1],
  141.   values->data[2], values->data[3],
  142.   values->data[4], values->data[5],
  143.   values->data[6], values->data[7]);
  144. break;
  145. case 9:
  146. /*
  147.  * XXX Note that functions with >8 arguments can only be
  148.  * called from inside the system, not from the user level,
  149.  * since the catalogs only store 8 argument types for user
  150.  * type-checking!
  151.  */
  152. returnValue = (*user_fn) (values->data[0], values->data[1],
  153.   values->data[2], values->data[3],
  154.   values->data[4], values->data[5],
  155.   values->data[6], values->data[7],
  156.   values->data[8]);
  157. break;
  158. default:
  159. elog(ERROR, "fmgr_c: function %u: too many arguments (%d > %d)",
  160.  finfo->fn_oid, n_arguments, MAXFMGRARGS);
  161. break;
  162. }
  163. return returnValue;
  164. }
  165. /*
  166.  * Expand a regproc OID into an FmgrInfo cache struct.
  167.  */
  168. void
  169. fmgr_info(Oid procedureId, FmgrInfo *finfo)
  170. {
  171. FmgrCall   *fcp;
  172. HeapTuple procedureTuple;
  173. FormData_pg_proc *procedureStruct;
  174. HeapTuple languageTuple;
  175. Form_pg_language languageStruct;
  176. Oid language;
  177. char    *prosrc;
  178. finfo->fn_addr = NULL;
  179. finfo->fn_plhandler = NULL;
  180. finfo->fn_oid = procedureId;
  181. if ((fcp = fmgr_isbuiltin(procedureId)) != NULL)
  182. {
  183. /*
  184.  * Fast path for builtin functions: don't bother consulting
  185.  * pg_proc
  186.  */
  187. finfo->fn_addr = fcp->func;
  188. finfo->fn_nargs = fcp->nargs;
  189. }
  190. else
  191. {
  192. procedureTuple = SearchSysCacheTuple(PROOID,
  193.    ObjectIdGetDatum(procedureId),
  194.  0, 0, 0);
  195. if (!HeapTupleIsValid(procedureTuple))
  196. {
  197. elog(ERROR, "fmgr_info: function %u: cache lookup failed",
  198.  procedureId);
  199. }
  200. procedureStruct = (FormData_pg_proc *) GETSTRUCT(procedureTuple);
  201. if (!procedureStruct->proistrusted)
  202. {
  203. finfo->fn_addr = (func_ptr) fmgr_untrusted;
  204. finfo->fn_nargs = procedureStruct->pronargs;
  205. return;
  206. }
  207. language = procedureStruct->prolang;
  208. switch (language)
  209. {
  210. case INTERNALlanguageId:
  211. /*
  212.  * For an ordinary builtin function, we should never get
  213.  * here because the isbuiltin() search above will have
  214.  * succeeded. However, if the user has done a CREATE
  215.  * FUNCTION to create an alias for a builtin function, we
  216.  * end up here.  In that case we have to look up the
  217.  * function by name.  The name of the internal function is
  218.  * stored in prosrc (it doesn't have to be the same as the
  219.  * name of the alias!)
  220.  */
  221. prosrc = textout(&(procedureStruct->prosrc));
  222. finfo->fn_addr = fmgr_lookupByName(prosrc);
  223. if (!finfo->fn_addr)
  224. elog(ERROR, "fmgr_info: function %s not in internal table",
  225.  prosrc);
  226. finfo->fn_nargs = procedureStruct->pronargs;
  227. pfree(prosrc);
  228. break;
  229. case ClanguageId:
  230. finfo->fn_addr = fmgr_dynamic(procedureId, &(finfo->fn_nargs));
  231. break;
  232. case SQLlanguageId:
  233. finfo->fn_addr = (func_ptr) fmgr_sql;
  234. finfo->fn_nargs = procedureStruct->pronargs;
  235. break;
  236. default:
  237. /*
  238.  * Might be a created procedural language Lookup the
  239.  * syscache for the language and check the lanispl flag If
  240.  * this is the case, we return a NULL function pointer and
  241.  * the number of arguments from the procedure.
  242.  */
  243. languageTuple = SearchSysCacheTuple(LANOID,
  244.   ObjectIdGetDatum(procedureStruct->prolang),
  245. 0, 0, 0);
  246. if (!HeapTupleIsValid(languageTuple))
  247. {
  248. elog(ERROR, "fmgr_info: %s %u",
  249.  "Cache lookup for language failed",
  250.  DatumGetObjectId(procedureStruct->prolang));
  251. }
  252. languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
  253. if (languageStruct->lanispl)
  254. {
  255. FmgrInfo plfinfo;
  256. fmgr_info(languageStruct->lanplcallfoid, &plfinfo);
  257. finfo->fn_addr = (func_ptr) fmgr_pl;
  258. finfo->fn_plhandler = plfinfo.fn_addr;
  259. finfo->fn_nargs = procedureStruct->pronargs;
  260. }
  261. else
  262. {
  263. elog(ERROR, "fmgr_info: function %u: unknown language %d",
  264.  procedureId, language);
  265. }
  266. break;
  267. }
  268. }
  269. }
  270. /*
  271.  * fmgr - return the value of a function call
  272.  *
  273.  * If the function is a system routine, it's compiled in, so call
  274.  * it directly.
  275.  *
  276.  * Otherwise pass it to the the appropriate 'language' function caller.
  277.  *
  278.  * Returns the return value of the invoked function if succesful,
  279.  * 0 if unsuccessful.
  280.  */
  281. char *
  282. fmgr(Oid procedureId,...)
  283. {
  284. va_list pvar;
  285. int i;
  286. int pronargs;
  287. FmgrValues values;
  288. FmgrInfo finfo;
  289. bool isNull = false;
  290. fmgr_info(procedureId, &finfo);
  291. pronargs = finfo.fn_nargs;
  292. if (pronargs > MAXFMGRARGS)
  293. elog(ERROR, "fmgr: function %u: too many arguments (%d > %d)",
  294.  procedureId, pronargs, MAXFMGRARGS);
  295. va_start(pvar, procedureId);
  296. for (i = 0; i < pronargs; ++i)
  297. values.data[i] = va_arg(pvar, char *);
  298. va_end(pvar);
  299. /* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */
  300. return fmgr_c(&finfo, &values, &isNull);
  301. }
  302. /*
  303.  * This is just a version of fmgr() in which the hacker can prepend a C
  304.  * function pointer.  This routine is not normally called; generally,
  305.  * if you have all of this information you're likely to just jump through
  306.  * the pointer, but it's available for use with macros in fmgr.h if you
  307.  * want this routine to do sanity-checking for you.
  308.  *
  309.  * funcinfo, n_arguments, args...
  310.  */
  311. #ifdef TRACE_FMGR_PTR
  312. char *
  313. fmgr_ptr(FmgrInfo *finfo,...)
  314. {
  315. va_list pvar;
  316. int i;
  317. int n_arguments;
  318. FmgrInfo local_finfo;
  319. FmgrValues values;
  320. bool isNull = false;
  321. local_finfo->fn_addr = finfo->fn_addr;
  322. local_finfo->fn_plhandler = finfo->fn_plhandler;
  323. local_finfo->fn_oid = finfo->fn_oid;
  324. va_start(pvar, finfo);
  325. n_arguments = va_arg(pvar, int);
  326. local_finfo->fn_nargs = n_arguments;
  327. if (n_arguments > MAXFMGRARGS)
  328. {
  329. elog(ERROR, "fmgr_ptr: function %u: too many arguments (%d > %d)",
  330.  func_id, n_arguments, MAXFMGRARGS);
  331. }
  332. for (i = 0; i < n_arguments; ++i)
  333. values.data[i] = va_arg(pvar, char *);
  334. va_end(pvar);
  335. /* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */
  336. return fmgr_c(&local_finfo, &values, &isNull);
  337. }
  338. #endif
  339. /*
  340.  * This routine is not well thought out.  When I get around to adding a
  341.  * function pointer field to FuncIndexInfo, it will be replace by calls
  342.  * to fmgr_c().
  343.  */
  344. char *
  345. fmgr_array_args(Oid procedureId, int nargs, char *args[], bool *isNull)
  346. {
  347. FmgrInfo finfo;
  348. fmgr_info(procedureId, &finfo);
  349. finfo.fn_nargs = nargs;
  350. /* XXX see WAY_COOL_ORTHOGONAL_FUNCTIONS */
  351. return fmgr_c(&finfo,
  352.   (FmgrValues *) args,
  353.   isNull);
  354. }