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

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * pg_proc.c
  4.  *   routines to support manipulation of the pg_proc relation
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.29.2.1 1999/08/02 05:56:55 scrappy Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include "postgres.h"
  15. #include "access/heapam.h"
  16. #include "catalog/catname.h"
  17. #include "catalog/indexing.h"
  18. #include "catalog/pg_proc.h"
  19. #include "catalog/pg_type.h"
  20. #include "miscadmin.h"
  21. #include "optimizer/planner.h"
  22. #include "parser/parse_type.h"
  23. #include "tcop/tcopprot.h"
  24. #include "utils/builtins.h"
  25. #include "utils/fmgrtab.h"
  26. #include "utils/lsyscache.h"
  27. #include "utils/sets.h"
  28. #include "utils/syscache.h"
  29. /* ----------------------------------------------------------------
  30.  * ProcedureCreate
  31.  * ----------------------------------------------------------------
  32.  */
  33. Oid
  34. ProcedureCreate(char *procedureName,
  35. bool returnsSet,
  36. char *returnTypeName,
  37. char *languageName,
  38. char *prosrc,
  39. char *probin,
  40. bool canCache,
  41. bool trusted,
  42. int32 byte_pct,
  43. int32 perbyte_cpu,
  44. int32 percall_cpu,
  45. int32 outin_ratio,
  46. List *argList,
  47. CommandDest dest)
  48. {
  49. int i;
  50. Relation rel;
  51. HeapTuple tup;
  52. bool defined;
  53. uint16 parameterCount;
  54. char nulls[Natts_pg_proc];
  55. Datum values[Natts_pg_proc];
  56. Oid languageObjectId;
  57. Oid typeObjectId;
  58. List    *x;
  59. List    *querytree_list;
  60. List    *plan_list;
  61. Oid typev[8];
  62. Oid relid;
  63. Oid toid;
  64. text    *prosrctext;
  65. NameData procname;
  66. TupleDesc tupDesc;
  67. /* ----------------
  68.  * sanity checks
  69.  * ----------------
  70.  */
  71. Assert(PointerIsValid(prosrc));
  72. Assert(PointerIsValid(probin));
  73. parameterCount = 0;
  74. MemSet(typev, 0, 8 * sizeof(Oid));
  75. foreach(x, argList)
  76. {
  77. Value    *t = lfirst(x);
  78. if (parameterCount == 8)
  79. elog(ERROR, "Procedures cannot take more than 8 arguments");
  80. if (strcmp(strVal(t), "opaque") == 0)
  81. {
  82. if (strcmp(languageName, "sql") == 0)
  83. elog(ERROR, "ProcedureCreate: sql functions cannot take type "opaque"");
  84. toid = 0;
  85. }
  86. else
  87. {
  88. toid = TypeGet(strVal(t), &defined);
  89. if (!OidIsValid(toid))
  90. {
  91. elog(ERROR, "ProcedureCreate: arg type '%s' is not defined",
  92.  strVal(t));
  93. }
  94. if (!defined)
  95. {
  96. elog(NOTICE, "ProcedureCreate: arg type '%s' is only a shell",
  97.  strVal(t));
  98. }
  99. }
  100. typev[parameterCount++] = toid;
  101. }
  102. tup = SearchSysCacheTuple(PRONAME,
  103.   PointerGetDatum(procedureName),
  104.   UInt16GetDatum(parameterCount),
  105.   PointerGetDatum(typev),
  106.   0);
  107. if (HeapTupleIsValid(tup))
  108. elog(ERROR, "ProcedureCreate: procedure %s already exists with same arguments",
  109.  procedureName);
  110. if (!strcmp(languageName, "sql"))
  111. {
  112. /*
  113.  * If this call is defining a set, check if the set is already
  114.  * defined by looking to see whether this call's function text
  115.  * matches a function already in pg_proc.  If so just return the
  116.  * OID of the existing set.
  117.  */
  118. if (!strcmp(procedureName, GENERICSETNAME))
  119. {
  120. prosrctext = textin(prosrc);
  121. tup = SearchSysCacheTuple(PROSRC,
  122.   PointerGetDatum(prosrctext),
  123.   0, 0, 0);
  124. pfree(prosrctext);
  125. if (HeapTupleIsValid(tup))
  126. return tup->t_data->t_oid;
  127. }
  128. }
  129. tup = SearchSysCacheTuple(LANNAME,
  130.   PointerGetDatum(languageName),
  131.   0, 0, 0);
  132. if (!HeapTupleIsValid(tup))
  133. elog(ERROR, "ProcedureCreate: no such language %s", languageName);
  134. languageObjectId = tup->t_data->t_oid;
  135. if (strcmp(returnTypeName, "opaque") == 0)
  136. {
  137. if (strcmp(languageName, "sql") == 0)
  138. elog(ERROR, "ProcedureCreate: sql functions cannot return type "opaque"");
  139. typeObjectId = 0;
  140. }
  141. else
  142. {
  143. typeObjectId = TypeGet(returnTypeName, &defined);
  144. if (!OidIsValid(typeObjectId))
  145. {
  146. elog(NOTICE, "ProcedureCreate: type '%s' is not yet defined",
  147.  returnTypeName);
  148. #ifdef NOT_USED
  149. elog(NOTICE, "ProcedureCreate: creating a shell for type '%s'",
  150.  returnTypeName);
  151. #endif
  152. typeObjectId = TypeShellMake(returnTypeName);
  153. if (!OidIsValid(typeObjectId))
  154. {
  155. elog(ERROR, "ProcedureCreate: could not create type '%s'",
  156.  returnTypeName);
  157. }
  158. }
  159. else if (!defined)
  160. {
  161. elog(NOTICE, "ProcedureCreate: return type '%s' is only a shell",
  162.  returnTypeName);
  163. }
  164. }
  165. /*
  166.  * don't allow functions of complex types that have the same name as
  167.  * existing attributes of the type
  168.  */
  169. if (parameterCount == 1 &&
  170. (toid = TypeGet(strVal(lfirst(argList)), &defined)) &&
  171. defined &&
  172. (relid = typeidTypeRelid(toid)) != 0 &&
  173. get_attnum(relid, procedureName) != InvalidAttrNumber)
  174. elog(ERROR, "method %s already an attribute of type %s",
  175.  procedureName, strVal(lfirst(argList)));
  176. /*
  177.  * If this is a postquel procedure, we parse it here in order to be
  178.  * sure that it contains no syntax errors. We should store the plan
  179.  * in an Inversion file for use later, but for now, we just store the
  180.  * procedure's text in the prosrc attribute.
  181.  */
  182. if (strcmp(languageName, "sql") == 0)
  183. {
  184. plan_list = pg_parse_and_plan(prosrc, typev, parameterCount,
  185.   &querytree_list, dest, FALSE);
  186. /* typecheck return value */
  187. pg_checkretval(typeObjectId, querytree_list);
  188. }
  189. /*
  190.  * If this is an internal procedure, check that the given internal
  191.  * function name (the 'prosrc' value) is a known builtin function.
  192.  *
  193.  * NOTE: in Postgres versions before 6.5, the SQL name of the created
  194.  * function could not be different from the internal name, and
  195.  * 'prosrc' wasn't used.  So there is code out there that does CREATE
  196.  * FUNCTION xyz AS '' LANGUAGE 'internal'. To preserve some modicum
  197.  * of backwards compatibility, accept an empty 'prosrc' value as
  198.  * meaning the supplied SQL function name.
  199.  */
  200. if (strcmp(languageName, "internal") == 0)
  201. {
  202. if (strlen(prosrc) == 0)
  203. prosrc = procedureName;
  204. if (fmgr_lookupByName(prosrc) == (func_ptr) NULL)
  205. elog(ERROR,
  206. "ProcedureCreate: there is no builtin function named "%s"",
  207.  prosrc);
  208. }
  209. /*
  210.  * All seems OK; prepare the tuple to be inserted into pg_proc.
  211.  */
  212. for (i = 0; i < Natts_pg_proc; ++i)
  213. {
  214. nulls[i] = ' ';
  215. values[i] = (Datum) NULL;
  216. }
  217. i = 0;
  218. namestrcpy(&procname, procedureName);
  219. values[i++] = NameGetDatum(&procname);
  220. values[i++] = Int32GetDatum(GetUserId());
  221. values[i++] = ObjectIdGetDatum(languageObjectId);
  222. /* XXX isinherited is always false for now */
  223. values[i++] = Int8GetDatum((bool) 0);
  224. /* XXX istrusted is always false for now */
  225. values[i++] = Int8GetDatum(trusted);
  226. values[i++] = Int8GetDatum(canCache);
  227. values[i++] = UInt16GetDatum(parameterCount);
  228. values[i++] = Int8GetDatum(returnsSet);
  229. values[i++] = ObjectIdGetDatum(typeObjectId);
  230. values[i++] = (Datum) typev;
  231. /*
  232.  * The following assignments of constants are made.  The real values
  233.  * will have to be extracted from the arglist someday soon.
  234.  */
  235. values[i++] = Int32GetDatum(byte_pct); /* probyte_pct */
  236. values[i++] = Int32GetDatum(perbyte_cpu); /* properbyte_cpu */
  237. values[i++] = Int32GetDatum(percall_cpu); /* propercall_cpu */
  238. values[i++] = Int32GetDatum(outin_ratio); /* prooutin_ratio */
  239. values[i++] = (Datum) fmgr(F_TEXTIN, prosrc); /* prosrc */
  240. values[i++] = (Datum) fmgr(F_TEXTIN, probin); /* probin */
  241. rel = heap_openr(ProcedureRelationName);
  242. tupDesc = rel->rd_att;
  243. tup = heap_formtuple(tupDesc,
  244.  values,
  245.  nulls);
  246. heap_insert(rel, tup);
  247. if (RelationGetForm(rel)->relhasindex)
  248. {
  249. Relation idescs[Num_pg_proc_indices];
  250. CatalogOpenIndices(Num_pg_proc_indices, Name_pg_proc_indices, idescs);
  251. CatalogIndexInsert(idescs, Num_pg_proc_indices, rel, tup);
  252. CatalogCloseIndices(Num_pg_proc_indices, idescs);
  253. }
  254. heap_close(rel);
  255. return tup->t_data->t_oid;
  256. }