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:
parent
c18cabe8ab
commit
48123de717
|
@ -1,6 +1,6 @@
|
||||||
<!--
|
<!--
|
||||||
Documentation of the system catalogs, directed toward PostgreSQL developers
|
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">
|
<chapter id="catalogs">
|
||||||
|
@ -168,6 +168,11 @@
|
||||||
<entry>operators</entry>
|
<entry>operators</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><link linkend="catalog-pg-pltemplate"><structname>pg_pltemplate</structname></link></entry>
|
||||||
|
<entry>template data for procedural languages</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link></entry>
|
<entry><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link></entry>
|
||||||
<entry>functions and procedures</entry>
|
<entry>functions and procedures</entry>
|
||||||
|
@ -3027,6 +3032,106 @@
|
||||||
</sect1>
|
</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">
|
<sect1 id="catalog-pg-proc">
|
||||||
<title><structname>pg_proc</structname></title>
|
<title><structname>pg_proc</structname></title>
|
||||||
|
|
||||||
|
|
|
@ -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
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
@ -48,22 +48,19 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
There are two forms of the <command>CREATE LANGUAGE</command> command.
|
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
|
language, and the <productname>PostgreSQL</productname> server consults
|
||||||
an internal table to determine the correct parameters. In
|
the <link linkend="catalog-pg-pltemplate"><structname>pg_pltemplate</structname></link>
|
||||||
the second form, the user supplies the language parameters along with
|
system catalog to determine the correct parameters. In the second form,
|
||||||
the language name. The second form must be used to create a language
|
the user supplies the language parameters along with the language name.
|
||||||
that is not present in the internal table, but this form is considered
|
The second form can be used to create a language that is not defined in
|
||||||
obsolescent. (It is expected that future releases of
|
<structname>pg_pltemplate</>, but this approach is considered obsolescent.
|
||||||
<productname>PostgreSQL</productname> will replace the internal table
|
|
||||||
with a system catalog that can be extended to support additional
|
|
||||||
languages.)
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
When the server finds an entry in its internal table for the given
|
When the server finds an entry in the <structname>pg_pltemplate</> catalog
|
||||||
language name, it will use the table data even if the given command
|
for the given language name, it will use the catalog data even if the
|
||||||
includes language parameters. This behavior simplifies loading of
|
command includes language parameters. This behavior simplifies loading of
|
||||||
old dump files, which are likely to contain out-of-date information
|
old dump files, which are likely to contain out-of-date information
|
||||||
about language support functions.
|
about language support functions.
|
||||||
</para>
|
</para>
|
||||||
|
@ -165,8 +162,8 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The <literal>TRUSTED</> option and the support function name(s) are
|
The <literal>TRUSTED</> option and the support function name(s) are
|
||||||
ignored if the server has information about the specified language
|
ignored if the server has an entry for the specified language
|
||||||
name in its internal table.
|
name in <structname>pg_pltemplate</>.
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
@ -207,9 +204,9 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The call handler function and the validator function (if any)
|
The call handler function and the validator function (if any)
|
||||||
must already exist if the server does not have information about
|
must already exist if the server does not have an entry for the language
|
||||||
the language in its internal table. But when there is an entry
|
in <structname>pg_pltemplate</>. But when there is an entry,
|
||||||
in the internal table, the functions need not already exist;
|
the functions need not already exist;
|
||||||
they will be automatically defined if not present in the database.
|
they will be automatically defined if not present in the database.
|
||||||
(This can result in <command>CREATE LANGUAGE</> failing, if the
|
(This can result in <command>CREATE LANGUAGE</> failing, if the
|
||||||
shared library that implements the language is not available in
|
shared library that implements the language is not available in
|
||||||
|
@ -239,8 +236,8 @@ CREATE LANGUAGE plpgsql;
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
For a language not known in the server's internal table, a sequence
|
For a language not known in the <structname>pg_pltemplate</> catalog, a
|
||||||
such as this is needed:
|
sequence such as this is needed:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
CREATE FUNCTION plsample_call_handler() RETURNS language_handler
|
CREATE FUNCTION plsample_call_handler() RETURNS language_handler
|
||||||
AS '$libdir/plsample'
|
AS '$libdir/plsample'
|
||||||
|
|
|
@ -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
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
@ -40,11 +40,9 @@ PostgreSQL documentation
|
||||||
<para>
|
<para>
|
||||||
<application>createlang</application> is a utility for adding a new
|
<application>createlang</application> is a utility for adding a new
|
||||||
programming language to a <productname>PostgreSQL</productname> database.
|
programming language to a <productname>PostgreSQL</productname> database.
|
||||||
<application>createlang</application> can handle all the languages
|
<application>createlang</application> is just a wrapper around the
|
||||||
supplied in the default <productname>PostgreSQL</> distribution, but
|
|
||||||
not languages provided by other parties. See
|
|
||||||
<xref linkend="sql-createlanguage" endterm="sql-createlanguage-title">
|
<xref linkend="sql-createlanguage" endterm="sql-createlanguage-title">
|
||||||
for additional information.
|
command, which see for additional information.
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#
|
#
|
||||||
# Makefile for backend/catalog
|
# 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_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_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_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_namespace.h pg_conversion.h pg_depend.h \
|
||||||
pg_authid.h pg_auth_members.h pg_tablespace.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 \
|
indexing.h \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* DESCRIPTION
|
||||||
* These routines take the parse tree and pick out the
|
* These routines take the parse tree and pick out the
|
||||||
|
@ -44,6 +44,7 @@
|
||||||
#include "catalog/pg_proc.h"
|
#include "catalog/pg_proc.h"
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
#include "commands/defrem.h"
|
#include "commands/defrem.h"
|
||||||
|
#include "commands/proclang.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "optimizer/cost.h"
|
#include "optimizer/cost.h"
|
||||||
#include "parser/parse_func.h"
|
#include "parser/parse_func.h"
|
||||||
|
@ -543,17 +544,11 @@ CreateFunction(CreateFunctionStmt *stmt)
|
||||||
PointerGetDatum(languageName),
|
PointerGetDatum(languageName),
|
||||||
0, 0, 0);
|
0, 0, 0);
|
||||||
if (!HeapTupleIsValid(languageTuple))
|
if (!HeapTupleIsValid(languageTuple))
|
||||||
/* Add any new languages to this list to invoke the hint. */
|
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||||
errmsg("language \"%s\" does not exist", languageName),
|
errmsg("language \"%s\" does not exist", languageName),
|
||||||
(strcmp(languageName, "plperl") == 0 ||
|
(PLTemplateExists(languageName) ?
|
||||||
strcmp(languageName, "plperlu") == 0 ||
|
errhint("Use CREATE LANGUAGE to load the language into the database.") : 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));
|
|
||||||
|
|
||||||
languageOid = HeapTupleGetOid(languageTuple);
|
languageOid = HeapTupleGetOid(languageTuple);
|
||||||
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
|
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
|
||||||
|
|
|
@ -7,18 +7,20 @@
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 "postgres.h"
|
||||||
|
|
||||||
|
#include "access/genam.h"
|
||||||
#include "access/heapam.h"
|
#include "access/heapam.h"
|
||||||
#include "catalog/dependency.h"
|
#include "catalog/dependency.h"
|
||||||
#include "catalog/indexing.h"
|
#include "catalog/indexing.h"
|
||||||
#include "catalog/namespace.h"
|
#include "catalog/namespace.h"
|
||||||
#include "catalog/pg_language.h"
|
#include "catalog/pg_language.h"
|
||||||
#include "catalog/pg_namespace.h"
|
#include "catalog/pg_namespace.h"
|
||||||
|
#include "catalog/pg_pltemplate.h"
|
||||||
#include "catalog/pg_proc.h"
|
#include "catalog/pg_proc.h"
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
#include "commands/proclang.h"
|
#include "commands/proclang.h"
|
||||||
|
@ -35,11 +37,10 @@
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
char *lanname; /* PL name */
|
bool tmpltrusted; /* trusted? */
|
||||||
bool lantrusted; /* trusted? */
|
char *tmplhandler; /* name of handler function */
|
||||||
char *lanhandler; /* name of handler function */
|
char *tmplvalidator; /* name of validator function, or NULL */
|
||||||
char *lanvalidator; /* name of validator function, or NULL */
|
char *tmpllibrary; /* path of shared library */
|
||||||
char *lanlibrary; /* path of shared library */
|
|
||||||
} PLTemplate;
|
} PLTemplate;
|
||||||
|
|
||||||
static void create_proc_lang(const char *languageName,
|
static void create_proc_lang(const char *languageName,
|
||||||
|
@ -90,12 +91,19 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
|
||||||
{
|
{
|
||||||
List *funcname;
|
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
|
* Find or create the handler function, which we force to be in
|
||||||
* the pg_catalog schema. If already present, it must have the
|
* the pg_catalog schema. If already present, it must have the
|
||||||
* correct return type.
|
* correct return type.
|
||||||
*/
|
*/
|
||||||
funcname = SystemFuncName(pltemplate->lanhandler);
|
funcname = SystemFuncName(pltemplate->tmplhandler);
|
||||||
handlerOid = LookupFuncName(funcname, 0, funcargtypes, true);
|
handlerOid = LookupFuncName(funcname, 0, funcargtypes, true);
|
||||||
if (OidIsValid(handlerOid))
|
if (OidIsValid(handlerOid))
|
||||||
{
|
{
|
||||||
|
@ -108,15 +116,15 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
handlerOid = ProcedureCreate(pltemplate->lanhandler,
|
handlerOid = ProcedureCreate(pltemplate->tmplhandler,
|
||||||
PG_CATALOG_NAMESPACE,
|
PG_CATALOG_NAMESPACE,
|
||||||
false, /* replace */
|
false, /* replace */
|
||||||
false, /* returnsSet */
|
false, /* returnsSet */
|
||||||
LANGUAGE_HANDLEROID,
|
LANGUAGE_HANDLEROID,
|
||||||
ClanguageId,
|
ClanguageId,
|
||||||
F_FMGR_C_VALIDATOR,
|
F_FMGR_C_VALIDATOR,
|
||||||
pltemplate->lanhandler,
|
pltemplate->tmplhandler,
|
||||||
pltemplate->lanlibrary,
|
pltemplate->tmpllibrary,
|
||||||
false, /* isAgg */
|
false, /* isAgg */
|
||||||
false, /* security_definer */
|
false, /* security_definer */
|
||||||
false, /* isStrict */
|
false, /* isStrict */
|
||||||
|
@ -131,22 +139,22 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
|
||||||
* Likewise for the validator, if required; but we don't care about
|
* Likewise for the validator, if required; but we don't care about
|
||||||
* its return type.
|
* its return type.
|
||||||
*/
|
*/
|
||||||
if (pltemplate->lanvalidator)
|
if (pltemplate->tmplvalidator)
|
||||||
{
|
{
|
||||||
funcname = SystemFuncName(pltemplate->lanvalidator);
|
funcname = SystemFuncName(pltemplate->tmplvalidator);
|
||||||
funcargtypes[0] = OIDOID;
|
funcargtypes[0] = OIDOID;
|
||||||
valOid = LookupFuncName(funcname, 1, funcargtypes, true);
|
valOid = LookupFuncName(funcname, 1, funcargtypes, true);
|
||||||
if (!OidIsValid(valOid))
|
if (!OidIsValid(valOid))
|
||||||
{
|
{
|
||||||
valOid = ProcedureCreate(pltemplate->lanvalidator,
|
valOid = ProcedureCreate(pltemplate->tmplvalidator,
|
||||||
PG_CATALOG_NAMESPACE,
|
PG_CATALOG_NAMESPACE,
|
||||||
false, /* replace */
|
false, /* replace */
|
||||||
false, /* returnsSet */
|
false, /* returnsSet */
|
||||||
VOIDOID,
|
VOIDOID,
|
||||||
ClanguageId,
|
ClanguageId,
|
||||||
F_FMGR_C_VALIDATOR,
|
F_FMGR_C_VALIDATOR,
|
||||||
pltemplate->lanvalidator,
|
pltemplate->tmplvalidator,
|
||||||
pltemplate->lanlibrary,
|
pltemplate->tmpllibrary,
|
||||||
false, /* isAgg */
|
false, /* isAgg */
|
||||||
false, /* security_definer */
|
false, /* security_definer */
|
||||||
false, /* isStrict */
|
false, /* isStrict */
|
||||||
|
@ -162,7 +170,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
|
||||||
|
|
||||||
/* ok, create it */
|
/* ok, create it */
|
||||||
create_proc_lang(languageName, handlerOid, valOid,
|
create_proc_lang(languageName, handlerOid, valOid,
|
||||||
pltemplate->lantrusted);
|
pltemplate->tmpltrusted);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -170,17 +178,13 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
|
||||||
* No template, so use the provided information. If there's
|
* No template, so use the provided information. If there's
|
||||||
* no handler clause, the user is trying to rely on a template
|
* no handler clause, the user is trying to rely on a template
|
||||||
* that we don't have, so complain accordingly.
|
* 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)
|
if (!stmt->plhandler)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||||
errmsg("unsupported language \"%s\"",
|
errmsg("unsupported language \"%s\"",
|
||||||
languageName),
|
languageName),
|
||||||
errdetail("Supported languages are plpgsql, pltcl, pltclu, "
|
errhint("The supported languages are listed in the pg_pltemplate system catalog.")));
|
||||||
"plperl, plperlu, and plpythonu.")));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lookup the PL handler function and check that it is of the expected
|
* 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.
|
* 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 *
|
static PLTemplate *
|
||||||
find_language_template(const char *languageName)
|
find_language_template(const char *languageName)
|
||||||
{
|
{
|
||||||
static PLTemplate templates[] = {
|
PLTemplate *result;
|
||||||
{ "plpgsql", true, "plpgsql_call_handler", "plpgsql_validator",
|
Relation rel;
|
||||||
"$libdir/plpgsql" },
|
SysScanDesc scan;
|
||||||
{ "pltcl", true, "pltcl_call_handler", NULL,
|
ScanKeyData key;
|
||||||
"$libdir/pltcl" },
|
HeapTuple tup;
|
||||||
{ "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;
|
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)
|
Form_pg_pltemplate tmpl = (Form_pg_pltemplate) GETSTRUCT(tup);
|
||||||
return ptr;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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 */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 200508152
|
#define CATALOG_VERSION_NO 200509081
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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));
|
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
|
#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));
|
DECLARE_UNIQUE_INDEX(pg_cast_oid_index,2660, on pg_cast using btree(oid oid_ops));
|
||||||
#define CastOidIndexId 2660
|
#define CastOidIndexId 2660
|
||||||
DECLARE_UNIQUE_INDEX(pg_cast_source_target_index,2661, on pg_cast using btree(castsource oid_ops, casttarget oid_ops));
|
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));
|
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
|
#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));
|
DECLARE_UNIQUE_INDEX(pg_proc_oid_index,2690, on pg_proc using btree(oid oid_ops));
|
||||||
#define ProcedureOidIndexId 2690
|
#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));
|
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));
|
DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index,2704, on pg_type using btree(typname name_ops, typnamespace oid_ops));
|
||||||
#define TypeNameNspIndexId 2704
|
#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 */
|
/* last step of initialization script: build the indexes declared above */
|
||||||
BUILD_INDICES
|
BUILD_INDICES
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
|
@ -15,5 +15,6 @@ extern void CreateProceduralLanguage(CreatePLangStmt *stmt);
|
||||||
extern void DropProceduralLanguage(DropPLangStmt *stmt);
|
extern void DropProceduralLanguage(DropPLangStmt *stmt);
|
||||||
extern void DropProceduralLanguageById(Oid langOid);
|
extern void DropProceduralLanguageById(Oid langOid);
|
||||||
extern void RenameLanguage(const char *oldname, const char *newname);
|
extern void RenameLanguage(const char *oldname, const char *newname);
|
||||||
|
extern bool PLTemplateExists(const char *languageName);
|
||||||
|
|
||||||
#endif /* PROCLANG_H */
|
#endif /* PROCLANG_H */
|
||||||
|
|
|
@ -55,6 +55,7 @@ SELECT relname, relhasindex
|
||||||
pg_namespace | t
|
pg_namespace | t
|
||||||
pg_opclass | t
|
pg_opclass | t
|
||||||
pg_operator | t
|
pg_operator | t
|
||||||
|
pg_pltemplate | t
|
||||||
pg_proc | t
|
pg_proc | t
|
||||||
pg_rewrite | t
|
pg_rewrite | t
|
||||||
pg_shdepend | t
|
pg_shdepend | t
|
||||||
|
@ -67,7 +68,7 @@ SELECT relname, relhasindex
|
||||||
shighway | t
|
shighway | t
|
||||||
tenk1 | t
|
tenk1 | t
|
||||||
tenk2 | t
|
tenk2 | t
|
||||||
(57 rows)
|
(58 rows)
|
||||||
|
|
||||||
--
|
--
|
||||||
-- another sanity check: every system catalog that has OIDs should have
|
-- another sanity check: every system catalog that has OIDs should have
|
||||||
|
|
Loading…
Reference in New Issue