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

@ -1,6 +1,6 @@
<!--
Documentation of the system catalogs, directed toward PostgreSQL developers
$PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.112 2005/08/24 17:24:17 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.113 2005/09/08 20:07:41 tgl Exp $
-->
<chapter id="catalogs">
@ -168,6 +168,11 @@
<entry>operators</entry>
</row>
<row>
<entry><link linkend="catalog-pg-pltemplate"><structname>pg_pltemplate</structname></link></entry>
<entry>template data for procedural languages</entry>
</row>
<row>
<entry><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link></entry>
<entry>functions and procedures</entry>
@ -3027,6 +3032,106 @@
</sect1>
<sect1 id="catalog-pg-pltemplate">
<title><structname>pg_pltemplate</structname></title>
<indexterm zone="catalog-pg-pltemplate">
<primary>pg_pltemplate</primary>
</indexterm>
<para>
The catalog <structname>pg_pltemplate</structname> stores
<quote>template</> information for procedural languages.
A template for a language allows the language to be created in a
particular database by a simple <command>CREATE LANGUAGE</> command,
with no need to specify implementation details.
</para>
<para>
Unlike most system catalogs, <structname>pg_pltemplate</structname>
is shared across all databases of a cluster: there is only one
copy of <structname>pg_pltemplate</structname> per cluster, not
one per database. This allows the information to be accessible in
each database as it is needed.
</para>
<table>
<title><structname>pg_pltemplate</> Columns</title>
<tgroup cols=4>
<thead>
<row>
<entry>Name</entry>
<entry>Type</entry>
<entry>References</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><structfield>tmplname</structfield></entry>
<entry><type>name</type></entry>
<entry></entry>
<entry>Name of the language this template is for</entry>
</row>
<row>
<entry><structfield>tmpltrusted</structfield></entry>
<entry><type>boolean</type></entry>
<entry></entry>
<entry>True if language is considered trusted</entry>
</row>
<row>
<entry><structfield>tmplhandler</structfield></entry>
<entry><type>text</type></entry>
<entry></entry>
<entry>Name of call handler function</entry>
</row>
<row>
<entry><structfield>tmplvalidator</structfield></entry>
<entry><type>text</type></entry>
<entry></entry>
<entry>Name of validator function, or NULL if none</entry>
</row>
<row>
<entry><structfield>tmpllibrary</structfield></entry>
<entry><type>text</type></entry>
<entry></entry>
<entry>Path of shared library that implements language</entry>
</row>
<row>
<entry><structfield>tmplacl</structfield></entry>
<entry><type>aclitem[]</type></entry>
<entry></entry>
<entry>Access privileges for template (not yet used)</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
There are not currently any commands that manipulate procedural language
templates; to change the built-in information, a superuser must modify
the table using ordinary INSERT, DELETE, or UPDATE commands. It is
likely that a future release of <productname>PostgreSQL</productname>
will offer commands to change the entries in a cleaner fashion.
</para>
<para>
When implemented, the <structfield>tmplacl</structfield> field will provide
access control for the template itself (i.e., the right to create a
language using it), not for the languages created from the template.
</para>
</sect1>
<sect1 id="catalog-pg-proc">
<title><structname>pg_proc</structname></title>

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/create_language.sgml,v 1.40 2005/09/05 23:50:48 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/create_language.sgml,v 1.41 2005/09/08 20:07:41 tgl Exp $
PostgreSQL documentation
-->
@ -48,22 +48,19 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</
<para>
There are two forms of the <command>CREATE LANGUAGE</command> command.
In the first form, the user merely supplies the name of the desired
In the first form, the user supplies just the name of the desired
language, and the <productname>PostgreSQL</productname> server consults
an internal table to determine the correct parameters. In
the second form, the user supplies the language parameters along with
the language name. The second form must be used to create a language
that is not present in the internal table, but this form is considered
obsolescent. (It is expected that future releases of
<productname>PostgreSQL</productname> will replace the internal table
with a system catalog that can be extended to support additional
languages.)
the <link linkend="catalog-pg-pltemplate"><structname>pg_pltemplate</structname></link>
system catalog to determine the correct parameters. In the second form,
the user supplies the language parameters along with the language name.
The second form can be used to create a language that is not defined in
<structname>pg_pltemplate</>, but this approach is considered obsolescent.
</para>
<para>
When the server finds an entry in its internal table for the given
language name, it will use the table data even if the given command
includes language parameters. This behavior simplifies loading of
When the server finds an entry in the <structname>pg_pltemplate</> catalog
for the given language name, it will use the catalog data even if the
command includes language parameters. This behavior simplifies loading of
old dump files, which are likely to contain out-of-date information
about language support functions.
</para>
@ -165,8 +162,8 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</
<para>
The <literal>TRUSTED</> option and the support function name(s) are
ignored if the server has information about the specified language
name in its internal table.
ignored if the server has an entry for the specified language
name in <structname>pg_pltemplate</>.
</para>
</refsect1>
@ -207,9 +204,9 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</
<para>
The call handler function and the validator function (if any)
must already exist if the server does not have information about
the language in its internal table. But when there is an entry
in the internal table, the functions need not already exist;
must already exist if the server does not have an entry for the language
in <structname>pg_pltemplate</>. But when there is an entry,
the functions need not already exist;
they will be automatically defined if not present in the database.
(This can result in <command>CREATE LANGUAGE</> failing, if the
shared library that implements the language is not available in
@ -239,8 +236,8 @@ CREATE LANGUAGE plpgsql;
</para>
<para>
For a language not known in the server's internal table, a sequence
such as this is needed:
For a language not known in the <structname>pg_pltemplate</> catalog, a
sequence such as this is needed:
<programlisting>
CREATE FUNCTION plsample_call_handler() RETURNS language_handler
AS '$libdir/plsample'

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/createlang.sgml,v 1.36 2005/09/05 23:50:48 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/createlang.sgml,v 1.37 2005/09/08 20:07:41 tgl Exp $
PostgreSQL documentation
-->
@ -40,11 +40,9 @@ PostgreSQL documentation
<para>
<application>createlang</application> is a utility for adding a new
programming language to a <productname>PostgreSQL</productname> database.
<application>createlang</application> can handle all the languages
supplied in the default <productname>PostgreSQL</> distribution, but
not languages provided by other parties. See
<application>createlang</application> is just a wrapper around the
<xref linkend="sql-createlanguage" endterm="sql-createlanguage-title">
for additional information.
command, which see for additional information.
</para>
</refsect1>

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