aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/proclang.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-09-08 20:07:42 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-09-08 20:07:42 +0000
commit48123de71792c367313542883f0e9df7d850c994 (patch)
tree741725c1242dd2b91aa42937ddb5a884bd826eb5 /src/backend/commands/proclang.c
parentc18cabe8ab1c035b9e10368d7358eaadbf026c4c (diff)
downloadpostgresql-48123de71792c367313542883f0e9df7d850c994.tar.gz
postgresql-48123de71792c367313542883f0e9df7d850c994.zip
Create the pg_pltemplate system catalog to hold template information
for procedural languages. This replaces the hard-wired table I had originally proposed as a stopgap solution. For the moment, the initial contents only include languages shipped with the core distribution.
Diffstat (limited to 'src/backend/commands/proclang.c')
-rw-r--r--src/backend/commands/proclang.c139
1 files changed, 89 insertions, 50 deletions
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 499523ae007..4155dc179ad 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -7,18 +7,20 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/proclang.c,v 1.61 2005/09/05 23:50:48 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/proclang.c,v 1.62 2005/09/08 20:07:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+#include "access/genam.h"
#include "access/heapam.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_language.h"
#include "catalog/pg_namespace.h"
+#include "catalog/pg_pltemplate.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "commands/proclang.h"
@@ -35,11 +37,10 @@
typedef struct
{
- char *lanname; /* PL name */
- bool lantrusted; /* trusted? */
- char *lanhandler; /* name of handler function */
- char *lanvalidator; /* name of validator function, or NULL */
- char *lanlibrary; /* path of shared library */
+ bool tmpltrusted; /* trusted? */
+ char *tmplhandler; /* name of handler function */
+ char *tmplvalidator; /* name of validator function, or NULL */
+ char *tmpllibrary; /* path of shared library */
} PLTemplate;
static void create_proc_lang(const char *languageName,
@@ -91,11 +92,18 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
List *funcname;
/*
+ * Give a notice if we are ignoring supplied parameters.
+ */
+ if (stmt->plhandler)
+ ereport(NOTICE,
+ (errmsg("using pg_pltemplate information instead of CREATE LANGUAGE parameters")));
+
+ /*
* Find or create the handler function, which we force to be in
* the pg_catalog schema. If already present, it must have the
* correct return type.
*/
- funcname = SystemFuncName(pltemplate->lanhandler);
+ funcname = SystemFuncName(pltemplate->tmplhandler);
handlerOid = LookupFuncName(funcname, 0, funcargtypes, true);
if (OidIsValid(handlerOid))
{
@@ -108,15 +116,15 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
}
else
{
- handlerOid = ProcedureCreate(pltemplate->lanhandler,
+ handlerOid = ProcedureCreate(pltemplate->tmplhandler,
PG_CATALOG_NAMESPACE,
false, /* replace */
false, /* returnsSet */
LANGUAGE_HANDLEROID,
ClanguageId,
F_FMGR_C_VALIDATOR,
- pltemplate->lanhandler,
- pltemplate->lanlibrary,
+ pltemplate->tmplhandler,
+ pltemplate->tmpllibrary,
false, /* isAgg */
false, /* security_definer */
false, /* isStrict */
@@ -131,22 +139,22 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
* Likewise for the validator, if required; but we don't care about
* its return type.
*/
- if (pltemplate->lanvalidator)
+ if (pltemplate->tmplvalidator)
{
- funcname = SystemFuncName(pltemplate->lanvalidator);
+ funcname = SystemFuncName(pltemplate->tmplvalidator);
funcargtypes[0] = OIDOID;
valOid = LookupFuncName(funcname, 1, funcargtypes, true);
if (!OidIsValid(valOid))
{
- valOid = ProcedureCreate(pltemplate->lanvalidator,
+ valOid = ProcedureCreate(pltemplate->tmplvalidator,
PG_CATALOG_NAMESPACE,
false, /* replace */
false, /* returnsSet */
VOIDOID,
ClanguageId,
F_FMGR_C_VALIDATOR,
- pltemplate->lanvalidator,
- pltemplate->lanlibrary,
+ pltemplate->tmplvalidator,
+ pltemplate->tmpllibrary,
false, /* isAgg */
false, /* security_definer */
false, /* isStrict */
@@ -162,7 +170,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
/* ok, create it */
create_proc_lang(languageName, handlerOid, valOid,
- pltemplate->lantrusted);
+ pltemplate->tmpltrusted);
}
else
{
@@ -170,17 +178,13 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
* No template, so use the provided information. If there's
* no handler clause, the user is trying to rely on a template
* that we don't have, so complain accordingly.
- *
- * XXX In 8.2, replace the detail message with a hint to look in
- * pg_pltemplate.
*/
if (!stmt->plhandler)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("unsupported language \"%s\"",
languageName),
- errdetail("Supported languages are plpgsql, pltcl, pltclu, "
- "plperl, plperlu, and plpythonu.")));
+ errhint("The supported languages are listed in the pg_pltemplate system catalog.")));
/*
* Lookup the PL handler function and check that it is of the expected
@@ -291,41 +295,76 @@ create_proc_lang(const char *languageName,
/*
* Look to see if we have template information for the given language name.
- *
- * XXX for PG 8.1, the template info is hard-wired. This is to be replaced
- * by a shared system catalog in 8.2.
- *
- * XXX if you add languages to this list, add them also to the errdetail
- * message above and the list in functioncmds.c. Those hard-wired lists
- * should go away in 8.2, also.
*/
static PLTemplate *
find_language_template(const char *languageName)
{
- static PLTemplate templates[] = {
- { "plpgsql", true, "plpgsql_call_handler", "plpgsql_validator",
- "$libdir/plpgsql" },
- { "pltcl", true, "pltcl_call_handler", NULL,
- "$libdir/pltcl" },
- { "pltclu", false, "pltclu_call_handler", NULL,
- "$libdir/pltcl" },
- { "plperl", true, "plperl_call_handler", "plperl_validator",
- "$libdir/plperl" },
- { "plperlu", false, "plperl_call_handler", "plperl_validator",
- "$libdir/plperl" },
- { "plpythonu", false, "plpython_call_handler", NULL,
- "$libdir/plpython" },
- { NULL, false, NULL, NULL, NULL }
- };
-
- PLTemplate *ptr;
-
- for (ptr = templates; ptr->lanname != NULL; ptr++)
+ PLTemplate *result;
+ Relation rel;
+ SysScanDesc scan;
+ ScanKeyData key;
+ HeapTuple tup;
+
+ rel = heap_open(PLTemplateRelationId, AccessShareLock);
+
+ ScanKeyInit(&key,
+ Anum_pg_pltemplate_tmplname,
+ BTEqualStrategyNumber, F_NAMEEQ,
+ NameGetDatum(languageName));
+ scan = systable_beginscan(rel, PLTemplateNameIndexId, true,
+ SnapshotNow, 1, &key);
+
+ tup = systable_getnext(scan);
+ if (HeapTupleIsValid(tup))
{
- if (strcmp(languageName, ptr->lanname) == 0)
- return ptr;
+ Form_pg_pltemplate tmpl = (Form_pg_pltemplate) GETSTRUCT(tup);
+ Datum datum;
+ bool isnull;
+
+ result = (PLTemplate *) palloc0(sizeof(PLTemplate));
+ result->tmpltrusted = tmpl->tmpltrusted;
+
+ /* Remaining fields are variable-width so we need heap_getattr */
+ datum = heap_getattr(tup, Anum_pg_pltemplate_tmplhandler,
+ RelationGetDescr(rel), &isnull);
+ if (!isnull)
+ result->tmplhandler =
+ DatumGetCString(DirectFunctionCall1(textout, datum));
+
+ datum = heap_getattr(tup, Anum_pg_pltemplate_tmplvalidator,
+ RelationGetDescr(rel), &isnull);
+ if (!isnull)
+ result->tmplvalidator =
+ DatumGetCString(DirectFunctionCall1(textout, datum));
+
+ datum = heap_getattr(tup, Anum_pg_pltemplate_tmpllibrary,
+ RelationGetDescr(rel), &isnull);
+ if (!isnull)
+ result->tmpllibrary =
+ DatumGetCString(DirectFunctionCall1(textout, datum));
+
+ /* Ignore template if handler or library info is missing */
+ if (!result->tmplhandler || !result->tmpllibrary)
+ result = NULL;
}
- return NULL;
+ else
+ result = NULL;
+
+ systable_endscan(scan);
+
+ heap_close(rel, AccessShareLock);
+
+ return result;
+}
+
+
+/*
+ * This just returns TRUE if we have a valid template for a given language
+ */
+bool
+PLTemplateExists(const char *languageName)
+{
+ return (find_language_template(languageName) != NULL);
}