aboutsummaryrefslogtreecommitdiff
path: root/src/backend/catalog/pg_proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/catalog/pg_proc.c')
-rw-r--r--src/backend/catalog/pg_proc.c90
1 files changed, 60 insertions, 30 deletions
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index aa23a3be8c2..6ddc343aaa6 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.42 2000/04/12 17:14:56 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.43 2000/05/28 17:55:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -17,6 +17,7 @@
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/indexing.h"
+#include "catalog/pg_language.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "miscadmin.h"
@@ -24,7 +25,6 @@
#include "parser/parse_type.h"
#include "tcop/tcopprot.h"
#include "utils/builtins.h"
-#include "utils/fmgrtab.h"
#include "utils/lsyscache.h"
#include "utils/sets.h"
#include "utils/syscache.h"
@@ -41,8 +41,9 @@ ProcedureCreate(char *procedureName,
char *languageName,
char *prosrc,
char *probin,
- bool canCache,
bool trusted,
+ bool canCache,
+ bool isStrict,
int32 byte_pct,
int32 perbyte_cpu,
int32 percall_cpu,
@@ -74,6 +75,15 @@ ProcedureCreate(char *procedureName,
Assert(PointerIsValid(prosrc));
Assert(PointerIsValid(probin));
+ tup = SearchSysCacheTuple(LANGNAME,
+ PointerGetDatum(languageName),
+ 0, 0, 0);
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "ProcedureCreate: no such language '%s'", languageName);
+
+ languageObjectId = tup->t_data->t_oid;
+
parameterCount = 0;
MemSet(typev, 0, FUNC_MAX_ARGS * sizeof(Oid));
foreach(x, argList)
@@ -86,7 +96,7 @@ ProcedureCreate(char *procedureName,
if (strcmp(strVal(t), "opaque") == 0)
{
- if (strcmp(languageName, "sql") == 0)
+ if (languageObjectId == SQLlanguageId)
elog(ERROR, "ProcedureCreate: sql functions cannot take type \"opaque\"");
toid = 0;
}
@@ -120,7 +130,7 @@ ProcedureCreate(char *procedureName,
elog(ERROR, "ProcedureCreate: procedure %s already exists with same arguments",
procedureName);
- if (!strcmp(languageName, "sql"))
+ if (languageObjectId == SQLlanguageId)
{
/*
@@ -129,7 +139,7 @@ ProcedureCreate(char *procedureName,
* matches a function already in pg_proc. If so just return the
* OID of the existing set.
*/
- if (!strcmp(procedureName, GENERICSETNAME))
+ if (strcmp(procedureName, GENERICSETNAME) == 0)
{
#ifdef SETS_FIXED
/* ----------
@@ -138,7 +148,7 @@ ProcedureCreate(char *procedureName,
* have been removed. Instead a sequential heap scan
* or something better must get implemented. The reason
* for removing is that nbtree index crashes if sources
- * exceed 2K what's likely for procedural languages.
+ * exceed 2K --- what's likely for procedural languages.
*
* 1999/09/30 Jan
* ----------
@@ -158,18 +168,9 @@ ProcedureCreate(char *procedureName,
}
}
- tup = SearchSysCacheTuple(LANGNAME,
- PointerGetDatum(languageName),
- 0, 0, 0);
-
- if (!HeapTupleIsValid(tup))
- elog(ERROR, "ProcedureCreate: no such language %s", languageName);
-
- languageObjectId = tup->t_data->t_oid;
-
if (strcmp(returnTypeName, "opaque") == 0)
{
- if (strcmp(languageName, "sql") == 0)
+ if (languageObjectId == SQLlanguageId)
elog(ERROR, "ProcedureCreate: sql functions cannot return type \"opaque\"");
typeObjectId = 0;
}
@@ -181,16 +182,10 @@ ProcedureCreate(char *procedureName,
{
elog(NOTICE, "ProcedureCreate: type '%s' is not yet defined",
returnTypeName);
-#ifdef NOT_USED
- elog(NOTICE, "ProcedureCreate: creating a shell for type '%s'",
- returnTypeName);
-#endif
typeObjectId = TypeShellMake(returnTypeName);
if (!OidIsValid(typeObjectId))
- {
elog(ERROR, "ProcedureCreate: could not create type '%s'",
returnTypeName);
- }
}
else if (!defined)
{
@@ -219,7 +214,7 @@ ProcedureCreate(char *procedureName,
* procedure's text in the prosrc attribute.
*/
- if (strcmp(languageName, "sql") == 0)
+ if (languageObjectId == SQLlanguageId)
{
querytree_list = pg_parse_and_rewrite(prosrc, typev, parameterCount,
FALSE);
@@ -237,16 +232,50 @@ ProcedureCreate(char *procedureName,
* FUNCTION xyz AS '' LANGUAGE 'internal'. To preserve some modicum
* of backwards compatibility, accept an empty 'prosrc' value as
* meaning the supplied SQL function name.
+ *
+ * XXX: we could treat "internal" and "newinternal" language specs
+ * as equivalent, and take the actual language ID from the table of
+ * known builtin functions. Is that a better idea than making the
+ * user specify the right thing? Not sure.
*/
- if (strcmp(languageName, "internal") == 0)
+ if (languageObjectId == INTERNALlanguageId ||
+ languageObjectId == NEWINTERNALlanguageId)
{
+ Oid actualLangID;
+
if (strlen(prosrc) == 0)
prosrc = procedureName;
- if (fmgr_lookupByName(prosrc) == (func_ptr) NULL)
+ actualLangID = fmgr_internal_language(prosrc);
+ if (actualLangID == InvalidOid)
elog(ERROR,
- "ProcedureCreate: there is no builtin function named \"%s\"",
+ "ProcedureCreate: there is no builtin function named \"%s\"",
prosrc);
+ if (actualLangID != languageObjectId)
+ elog(ERROR,
+ "ProcedureCreate: \"%s\" is not %s internal function",
+ prosrc,
+ ((languageObjectId == INTERNALlanguageId) ?
+ "an old-style" : "a new-style"));
+ }
+
+ /*
+ * If this is a dynamically loadable procedure, make sure that the
+ * library file exists, is loadable, and contains the specified link
+ * symbol.
+ *
+ * We used to perform these checks only when the function was first
+ * called, but it seems friendlier to verify the library's validity
+ * at CREATE FUNCTION time.
+ */
+
+ if (languageObjectId == ClanguageId ||
+ languageObjectId == NEWClanguageId)
+ {
+ /* If link symbol is specified as "-", substitute procedure name */
+ if (strcmp(prosrc, "-") == 0)
+ prosrc = procedureName;
+ (void) load_external_function(probin, prosrc);
}
/*
@@ -265,9 +294,10 @@ ProcedureCreate(char *procedureName,
values[i++] = Int32GetDatum(GetUserId());
values[i++] = ObjectIdGetDatum(languageObjectId);
/* XXX isinherited is always false for now */
- values[i++] = Int8GetDatum((bool) 0);
+ values[i++] = Int8GetDatum((bool) false);
values[i++] = Int8GetDatum(trusted);
values[i++] = Int8GetDatum(canCache);
+ values[i++] = Int8GetDatum(isStrict);
values[i++] = UInt16GetDatum(parameterCount);
values[i++] = Int8GetDatum(returnsSet);
values[i++] = ObjectIdGetDatum(typeObjectId);
@@ -276,8 +306,8 @@ ProcedureCreate(char *procedureName,
values[i++] = Int32GetDatum(perbyte_cpu); /* properbyte_cpu */
values[i++] = Int32GetDatum(percall_cpu); /* propercall_cpu */
values[i++] = Int32GetDatum(outin_ratio); /* prooutin_ratio */
- values[i++] = (Datum) fmgr(F_TEXTIN, prosrc); /* prosrc */
- values[i++] = (Datum) fmgr(F_TEXTIN, probin); /* probin */
+ values[i++] = (Datum) textin(prosrc); /* prosrc */
+ values[i++] = (Datum) textin(probin); /* probin */
rel = heap_openr(ProcedureRelationName, RowExclusiveLock);