1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +03:00

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.
This commit is contained in:
Tom Lane
2005-09-08 20:07:42 +00:00
parent c18cabe8ab
commit 48123de717
11 changed files with 311 additions and 93 deletions

View File

@ -2,7 +2,7 @@
#
# Makefile for backend/catalog
#
# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.56 2005/07/14 05:13:39 tgl Exp $
# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.57 2005/09/08 20:07:41 tgl Exp $
#
#-------------------------------------------------------------------------
@ -32,8 +32,9 @@ POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\
pg_operator.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \
pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \
pg_rewrite.h pg_trigger.h pg_listener.h pg_description.h pg_cast.h \
pg_namespace.h pg_conversion.h pg_database.h pg_shdepend.h \
pg_authid.h pg_auth_members.h pg_tablespace.h pg_depend.h \
pg_namespace.h pg_conversion.h pg_depend.h \
pg_database.h pg_tablespace.h pg_pltemplate.h \
pg_authid.h pg_auth_members.h pg_shdepend.h \
indexing.h \
)

View File

@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.66 2005/08/22 17:38:20 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.67 2005/09/08 20:07:41 tgl Exp $
*
* DESCRIPTION
* These routines take the parse tree and pick out the
@ -44,6 +44,7 @@
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "commands/proclang.h"
#include "miscadmin.h"
#include "optimizer/cost.h"
#include "parser/parse_func.h"
@ -543,17 +544,11 @@ CreateFunction(CreateFunctionStmt *stmt)
PointerGetDatum(languageName),
0, 0, 0);
if (!HeapTupleIsValid(languageTuple))
/* Add any new languages to this list to invoke the hint. */
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("language \"%s\" does not exist", languageName),
(strcmp(languageName, "plperl") == 0 ||
strcmp(languageName, "plperlu") == 0 ||
strcmp(languageName, "plpgsql") == 0 ||
strcmp(languageName, "plpythonu") == 0 ||
strcmp(languageName, "pltcl") == 0 ||
strcmp(languageName, "pltclu") == 0) ?
errhint("You need to use \"createlang\" to load the language into the database.") : 0));
(PLTemplateExists(languageName) ?
errhint("Use CREATE LANGUAGE to load the language into the database.") : 0)));
languageOid = HeapTupleGetOid(languageTuple);
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);

View File

@ -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,
@ -90,12 +91,19 @@ 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 *result;
Relation rel;
SysScanDesc scan;
ScanKeyData key;
HeapTuple tup;
PLTemplate *ptr;
rel = heap_open(PLTemplateRelationId, AccessShareLock);
for (ptr = templates; ptr->lanname != NULL; ptr++)
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);
}

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.300 2005/08/15 23:00:14 momjian Exp $
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.301 2005/09/08 20:07:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200508152
#define CATALOG_VERSION_NO 200509081
#endif

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.90 2005/07/14 05:13:42 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.91 2005/09/08 20:07:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -93,6 +93,9 @@ DECLARE_UNIQUE_INDEX(pg_auth_members_role_member_index,2694, on pg_auth_members
DECLARE_UNIQUE_INDEX(pg_auth_members_member_role_index,2695, on pg_auth_members using btree(member oid_ops, roleid oid_ops));
#define AuthMemMemRoleIndexId 2695
DECLARE_UNIQUE_INDEX(pg_autovacuum_vacrelid_index,1250, on pg_autovacuum using btree(vacrelid oid_ops));
#define AutovacuumRelidIndexId 1250
DECLARE_UNIQUE_INDEX(pg_cast_oid_index,2660, on pg_cast using btree(oid oid_ops));
#define CastOidIndexId 2660
DECLARE_UNIQUE_INDEX(pg_cast_source_target_index,2661, on pg_cast using btree(castsource oid_ops, casttarget oid_ops));
@ -169,6 +172,9 @@ DECLARE_UNIQUE_INDEX(pg_operator_oid_index,2688, on pg_operator using btree(oid
DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index,2689, on pg_operator using btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops));
#define OperatorNameNspIndexId 2689
DECLARE_UNIQUE_INDEX(pg_pltemplate_name_index,1137, on pg_pltemplate using btree(tmplname name_ops));
#define PLTemplateNameIndexId 1137
DECLARE_UNIQUE_INDEX(pg_proc_oid_index,2690, on pg_proc using btree(oid oid_ops));
#define ProcedureOidIndexId 2690
DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index,2691, on pg_proc using btree(proname name_ops, proargtypes oidvector_ops, pronamespace oid_ops));
@ -210,9 +216,6 @@ DECLARE_UNIQUE_INDEX(pg_type_oid_index,2703, on pg_type using btree(oid oid_ops)
DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index,2704, on pg_type using btree(typname name_ops, typnamespace oid_ops));
#define TypeNameNspIndexId 2704
DECLARE_UNIQUE_INDEX(pg_autovacuum_vacrelid_index,1250, on pg_autovacuum using btree(vacrelid oid_ops));
#define AutovacuumRelidIndexId 1250
/* last step of initialization script: build the indexes declared above */
BUILD_INDICES

View File

@ -0,0 +1,78 @@
/*-------------------------------------------------------------------------
*
* pg_pltemplate.h
* definition of the system "PL template" relation (pg_pltemplate)
* along with the relation's initial contents.
*
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_pltemplate.h,v 1.1 2005/09/08 20:07:42 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
* information from the DATA() statements.
*
*-------------------------------------------------------------------------
*/
#ifndef PG_PLTEMPLATE_H
#define PG_PLTEMPLATE_H
/* ----------------
* postgres.h contains the system type definitions and the
* CATALOG(), BKI_BOOTSTRAP and DATA() sugar words so this file
* can be read by both genbki.sh and the C compiler.
* ----------------
*/
/* ----------------
* pg_pltemplate definition. cpp turns this into
* typedef struct FormData_pg_pltemplate
* ----------------
*/
#define PLTemplateRelationId 1136
CATALOG(pg_pltemplate,1136) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
{
NameData tmplname; /* name of PL */
bool tmpltrusted; /* PL is trusted? */
text tmplhandler; /* name of call handler function */
text tmplvalidator; /* name of validator function, or NULL */
text tmpllibrary; /* path of shared library */
aclitem tmplacl[1]; /* access privileges for template */
} FormData_pg_pltemplate;
/* ----------------
* Form_pg_pltemplate corresponds to a pointer to a row with
* the format of pg_pltemplate relation.
* ----------------
*/
typedef FormData_pg_pltemplate *Form_pg_pltemplate;
/* ----------------
* compiler constants for pg_pltemplate
* ----------------
*/
#define Natts_pg_pltemplate 6
#define Anum_pg_pltemplate_tmplname 1
#define Anum_pg_pltemplate_tmpltrusted 2
#define Anum_pg_pltemplate_tmplhandler 3
#define Anum_pg_pltemplate_tmplvalidator 4
#define Anum_pg_pltemplate_tmpllibrary 5
#define Anum_pg_pltemplate_tmplacl 6
/* ----------------
* initial contents of pg_pltemplate
* ----------------
*/
DATA(insert ( "plpgsql" t "plpgsql_call_handler" "plpgsql_validator" "$libdir/plpgsql" _null_ ));
DATA(insert ( "pltcl" t "pltcl_call_handler" _null_ "$libdir/pltcl" _null_ ));
DATA(insert ( "pltclu" f "pltclu_call_handler" _null_ "$libdir/pltcl" _null_ ));
DATA(insert ( "plperl" t "plperl_call_handler" "plperl_validator" "$libdir/plperl" _null_ ));
DATA(insert ( "plperlu" f "plperl_call_handler" "plperl_validator" "$libdir/plperl" _null_ ));
DATA(insert ( "plpythonu" f "plpython_call_handler" _null_ "$libdir/plpython" _null_ ));
#endif /* PG_PLTEMPLATE_H */

View File

@ -15,5 +15,6 @@ extern void CreateProceduralLanguage(CreatePLangStmt *stmt);
extern void DropProceduralLanguage(DropPLangStmt *stmt);
extern void DropProceduralLanguageById(Oid langOid);
extern void RenameLanguage(const char *oldname, const char *newname);
extern bool PLTemplateExists(const char *languageName);
#endif /* PROCLANG_H */

View File

@ -55,6 +55,7 @@ SELECT relname, relhasindex
pg_namespace | t
pg_opclass | t
pg_operator | t
pg_pltemplate | t
pg_proc | t
pg_rewrite | t
pg_shdepend | t
@ -67,7 +68,7 @@ SELECT relname, relhasindex
shighway | t
tenk1 | t
tenk2 | t
(57 rows)
(58 rows)
--
-- another sanity check: every system catalog that has OIDs should have