<!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/create_language.sgml,v 1.39 2005/01/04 00:39:53 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_language.sgml,v 1.40 2005/09/05 23:50:48 tgl Exp $
PostgreSQL documentation
-->
<refsynopsisdiv>
<synopsis>
+CREATE [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</replaceable>
CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</replaceable>
HANDLER <replaceable class="parameter">call_handler</replaceable> [ VALIDATOR <replaceable>valfunction</replaceable> ]
</synopsis>
</para>
<para>
- Note that procedural languages are local to individual databases.
- To make a language available in all databases by default, it should
- be installed into the <literal>template1</literal> database.
+ There are two forms of the <command>CREATE LANGUAGE</command> command.
+ In the first form, the user merely supplies 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.)
+ </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
+ old dump files, which are likely to contain out-of-date information
+ about language support functions.
</para>
</refsect1>
</listitem>
</varlistentry>
</variablelist>
+
+ <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.
+ </para>
</refsect1>
<refsect1 id="sql-createlanguage-notes">
<title>Notes</title>
<para>
- This command normally should not be executed directly by users.
- For the procedural languages supplied in the
- <productname>PostgreSQL</productname> distribution, the <xref
- linkend="app-createlang"> program should be used, which will also
- install the correct call handler. (<command>createlang</command>
- will call <command>CREATE LANGUAGE</command> internally.)
+ The <xref linkend="app-createlang"> program is a simple wrapper around
+ the <command>CREATE LANGUAGE</> command. It eases
+ installation of procedural languages from the shell command line.
</para>
<para>
- In <productname>PostgreSQL</productname> versions before 7.3, it was
- necessary to declare handler functions as returning the placeholder
- type <type>opaque</>, rather than <type>language_handler</>.
- To support loading
- of old dump files, <command>CREATE LANGUAGE</> will accept a function
- declared as returning <type>opaque</>, but it will issue a notice and
- change the function's declared return type to <type>language_handler</>.
+ Use <xref linkend="sql-droplanguage" endterm="sql-droplanguage-title">, or better yet the <xref
+ linkend="app-droplang"> program, to drop procedural languages.
</para>
<para>
- Use the <xref linkend="sql-createfunction" endterm="sql-createfunction-title"> command to create a new
- function.
+ The system catalog <classname>pg_language</classname> (see <xref
+ linkend="catalog-pg-language">) records information about the
+ currently installed languages. Also, <command>createlang</command>
+ has an option to list the installed languages.
</para>
<para>
- Use <xref linkend="sql-droplanguage" endterm="sql-droplanguage-title">, or better yet the <xref
- linkend="app-droplang"> program, to drop procedural languages.
+ To create functions in a procedural language, a user must have the
+ <literal>USAGE</literal> privilege for the language. By default,
+ <literal>USAGE</> is granted to <literal>PUBLIC</> (i.e., everyone)
+ for trusted languages. This may be revoked if desired.
</para>
<para>
- The system catalog <classname>pg_language</classname> (see <xref
- linkend="catalog-pg-language">) records information about the
- currently installed languages. Also <command>createlang</command>
- has an option to list the installed languages.
+ Procedural languages are local to individual databases.
+ However, a language can be installed into the <literal>template1</literal>
+ database, which will cause it to be available automatically in
+ all subsequently-created databases.
</para>
<para>
- To be able to use a procedural language, a user must be granted the
- <literal>USAGE</literal> privilege. The
- <command>createlang</command> program automatically grants
- permissions to everyone if the language is known to be trusted.
+ 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;
+ 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
+ the installation.)
+ </para>
+
+ <para>
+ In <productname>PostgreSQL</productname> versions before 7.3, it was
+ necessary to declare handler functions as returning the placeholder
+ type <type>opaque</>, rather than <type>language_handler</>.
+ To support loading
+ of old dump files, <command>CREATE LANGUAGE</> will accept a function
+ declared as returning <type>opaque</>, but it will issue a notice and
+ change the function's declared return type to <type>language_handler</>.
</para>
</refsect1>
<title>Examples</title>
<para>
- The following two commands executed in sequence will register a new
- procedural language and the associated call handler.
+ The preferred way of creating any of the standard procedural languages
+ is just:
+<programlisting>
+CREATE LANGUAGE plpgsql;
+</programlisting>
+ </para>
+
+ <para>
+ For a language not known in the server's internal table, a sequence
+ such as this is needed:
<programlisting>
CREATE FUNCTION plsample_call_handler() RETURNS language_handler
AS '$libdir/plsample'
<!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/createlang.sgml,v 1.35 2005/06/21 04:02:31 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/createlang.sgml,v 1.36 2005/09/05 23:50:48 tgl Exp $
PostgreSQL documentation
-->
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.
- </para>
- <para>
- Although backend programming languages can be added directly using
- several <acronym>SQL</acronym> commands, it is recommended to use
- <application>createlang</application> because it performs a number
- of checks and is much easier to use. See
+ not languages provided by other parties. See
<xref linkend="sql-createlanguage" endterm="sql-createlanguage-title">
for additional information.
</para>
<term><replaceable class="parameter">langname</replaceable></term>
<listitem>
<para>
- Specifies the name of the procedural programming language to be
- defined.
+ Specifies the name of the procedural programming language to be
+ defined.
</para>
</listitem>
</varlistentry>
<term><option><optional>--dbname</> <replaceable class="parameter">dbname</replaceable></></term>
<listitem>
<para>
- Specifies to which database the language should be added.
+ Specifies to which database the language should be added.
The default is to use the database with the same name as the
current system user.
</para>
</listitem>
</varlistentry>
- <varlistentry>
- <term><option>-L <replaceable class="parameter">directory</replaceable></></term>
- <listitem>
- <para>
- Specifies the directory in which the language interpreter is
- to be found. The directory is normally found automatically; this
- option is primarily for debugging purposes.
- </para>
- </listitem>
- </varlistentry>
-
</variablelist>
</para>
<term><option>--host <replaceable class="parameter">host</replaceable></></term>
<listitem>
<para>
- Specifies the host name of the machine on which the
- server
- is running. If the value begins with a slash, it is used
- as the directory for the Unix domain socket.
+ Specifies the host name of the machine on which the
+ server
+ is running. If the value begins with a slash, it is used
+ as the directory for the Unix domain socket.
</para>
</listitem>
</varlistentry>
<term><option>--port <replaceable class="parameter">port</replaceable></></term>
<listitem>
<para>
- Specifies the TCP port or local Unix domain socket file
- extension on which the server
- is listening for connections.
+ Specifies the TCP port or local Unix domain socket file
+ extension on which the server
+ is listening for connections.
</para>
</listitem>
</varlistentry>
<!--
-$PostgreSQL: pgsql/doc/src/sgml/xplang.sgml,v 1.28 2004/12/30 21:45:37 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/xplang.sgml,v 1.29 2005/09/05 23:50:48 tgl Exp $
-->
<chapter id="xplang">
</para>
<para>
- For the languages supplied with the standard distribution, the
- program <xref linkend="app-createlang"> may be used to install the
- language instead of carrying out the details by hand. For
- example, to install the language
+ For the languages supplied with the standard distribution, it is
+ only necessary to execute <command>CREATE LANGUAGE</>
+ <replaceable>language_name</> to install the language into the
+ current database. Alternatively, the program <xref
+ linkend="app-createlang"> may be used to do this from the shell
+ command line. For example, to install the language
<application>PL/pgSQL</application> into the database
<literal>template1</>, use
<programlisting>
createlang plpgsql template1
</programlisting>
The manual procedure described below is only recommended for
- installing custom languages that <command>createlang</command>
+ installing custom languages that <command>CREATE LANGUAGE</command>
does not know about.
</para>
<para>
A procedural language is installed in a database in four steps,
- which must be carried out by a database superuser. The
- <command>createlang</command> program automates all but <xref
- linkend="xplang-install-cr1">.
+ which must be carried out by a database superuser. (For languages
+ known to <command>CREATE LANGUAGE</>, the second and third steps
+ can be omitted, because they will be carried out automatically
+ if needed.)
</para>
<step performance="required" id="xplang-install-cr1">
In a default <productname>PostgreSQL</productname> installation,
the handler for the <application>PL/pgSQL</application> language
is built and installed into the <quote>library</quote>
- directory. If <application>Tcl</> support is configured in, the handlers for
- <application>PL/Tcl</> and <application>PL/TclU</> are also built and installed in the same
- location. Likewise, the <application>PL/Perl</> and <application>PL/PerlU</> handlers are built
- and installed if Perl support is configured, and <application>PL/PythonU</> is
+ directory. If <application>Tcl</> support is configured in, the handlers
+ for <application>PL/Tcl</> and <application>PL/TclU</> are also built and
+ installed in the same location. Likewise, the <application>PL/Perl</> and
+ <application>PL/PerlU</> handlers are built and installed if Perl support
+ is configured, and the <application>PL/PythonU</> handler is
installed if Python support is configured.
</para>
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/proclang.c,v 1.60 2005/04/14 20:03:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/proclang.c,v 1.61 2005/09/05 23:50:48 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
-#include <ctype.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_proc.h"
#include "catalog/pg_type.h"
#include "commands/proclang.h"
#include "commands/defrem.h"
#include "fmgr.h"
#include "miscadmin.h"
+#include "parser/gramparse.h"
#include "parser/parse_func.h"
#include "utils/builtins.h"
+#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
+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 */
+} PLTemplate;
+
+static void create_proc_lang(const char *languageName,
+ Oid handlerOid, Oid valOid, bool trusted);
+static PLTemplate *find_language_template(const char *languageName);
+
+
/* ---------------------------------------------------------------------
* CREATE PROCEDURAL LANGUAGE
* ---------------------------------------------------------------------
CreateProceduralLanguage(CreatePLangStmt *stmt)
{
char *languageName;
- Oid procOid,
- valProcOid;
+ PLTemplate *pltemplate;
+ Oid handlerOid,
+ valOid;
Oid funcrettype;
Oid funcargtypes[1];
- NameData langname;
- char nulls[Natts_pg_language];
- Datum values[Natts_pg_language];
- Relation rel;
- HeapTuple tup;
- TupleDesc tupDesc;
- int i;
- ObjectAddress myself,
- referenced;
/*
* Check permission
errmsg("language \"%s\" already exists", languageName)));
/*
- * Lookup the PL handler function and check that it is of the expected
- * return type
+ * If we have template information for the language, ignore the supplied
+ * parameters (if any) and use the template information.
*/
- procOid = LookupFuncName(stmt->plhandler, 0, funcargtypes, false);
- funcrettype = get_func_rettype(procOid);
- if (funcrettype != LANGUAGE_HANDLEROID)
+ if ((pltemplate = find_language_template(languageName)) != NULL)
{
+ List *funcname;
+
/*
- * We allow OPAQUE just so we can load old dump files. When we
- * see a handler function declared OPAQUE, change it to
- * LANGUAGE_HANDLER.
+ * 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.
*/
- if (funcrettype == OPAQUEOID)
+ funcname = SystemFuncName(pltemplate->lanhandler);
+ handlerOid = LookupFuncName(funcname, 0, funcargtypes, true);
+ if (OidIsValid(handlerOid))
{
- ereport(WARNING,
- (errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("changing return type of function %s from \"opaque\" to \"language_handler\"",
- NameListToString(stmt->plhandler))));
- SetFunctionReturnType(procOid, LANGUAGE_HANDLEROID);
+ funcrettype = get_func_rettype(handlerOid);
+ if (funcrettype != LANGUAGE_HANDLEROID)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("function %s must return type \"language_handler\"",
+ NameListToString(funcname))));
}
else
- ereport(ERROR,
- (errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("function %s must return type \"language_handler\"",
- NameListToString(stmt->plhandler))));
- }
+ {
+ handlerOid = ProcedureCreate(pltemplate->lanhandler,
+ PG_CATALOG_NAMESPACE,
+ false, /* replace */
+ false, /* returnsSet */
+ LANGUAGE_HANDLEROID,
+ ClanguageId,
+ F_FMGR_C_VALIDATOR,
+ pltemplate->lanhandler,
+ pltemplate->lanlibrary,
+ false, /* isAgg */
+ false, /* security_definer */
+ false, /* isStrict */
+ PROVOLATILE_VOLATILE,
+ buildoidvector(funcargtypes, 0),
+ PointerGetDatum(NULL),
+ PointerGetDatum(NULL),
+ PointerGetDatum(NULL));
+ }
- /* validate the validator function */
- if (stmt->plvalidator)
- {
- funcargtypes[0] = OIDOID;
- valProcOid = LookupFuncName(stmt->plvalidator, 1, funcargtypes, false);
- /* return value is ignored, so we don't check the type */
+ /*
+ * Likewise for the validator, if required; but we don't care about
+ * its return type.
+ */
+ if (pltemplate->lanvalidator)
+ {
+ funcname = SystemFuncName(pltemplate->lanvalidator);
+ funcargtypes[0] = OIDOID;
+ valOid = LookupFuncName(funcname, 1, funcargtypes, true);
+ if (!OidIsValid(valOid))
+ {
+ valOid = ProcedureCreate(pltemplate->lanvalidator,
+ PG_CATALOG_NAMESPACE,
+ false, /* replace */
+ false, /* returnsSet */
+ VOIDOID,
+ ClanguageId,
+ F_FMGR_C_VALIDATOR,
+ pltemplate->lanvalidator,
+ pltemplate->lanlibrary,
+ false, /* isAgg */
+ false, /* security_definer */
+ false, /* isStrict */
+ PROVOLATILE_VOLATILE,
+ buildoidvector(funcargtypes, 1),
+ PointerGetDatum(NULL),
+ PointerGetDatum(NULL),
+ PointerGetDatum(NULL));
+ }
+ }
+ else
+ valOid = InvalidOid;
+
+ /* ok, create it */
+ create_proc_lang(languageName, handlerOid, valOid,
+ pltemplate->lantrusted);
}
else
- valProcOid = InvalidOid;
+ {
+ /*
+ * 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.")));
+
+ /*
+ * Lookup the PL handler function and check that it is of the expected
+ * return type
+ */
+ handlerOid = LookupFuncName(stmt->plhandler, 0, funcargtypes, false);
+ funcrettype = get_func_rettype(handlerOid);
+ if (funcrettype != LANGUAGE_HANDLEROID)
+ {
+ /*
+ * We allow OPAQUE just so we can load old dump files. When we
+ * see a handler function declared OPAQUE, change it to
+ * LANGUAGE_HANDLER. (This is probably obsolete and removable?)
+ */
+ if (funcrettype == OPAQUEOID)
+ {
+ ereport(WARNING,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("changing return type of function %s from \"opaque\" to \"language_handler\"",
+ NameListToString(stmt->plhandler))));
+ SetFunctionReturnType(handlerOid, LANGUAGE_HANDLEROID);
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("function %s must return type \"language_handler\"",
+ NameListToString(stmt->plhandler))));
+ }
+
+ /* validate the validator function */
+ if (stmt->plvalidator)
+ {
+ funcargtypes[0] = OIDOID;
+ valOid = LookupFuncName(stmt->plvalidator, 1, funcargtypes, false);
+ /* return value is ignored, so we don't check the type */
+ }
+ else
+ valOid = InvalidOid;
+
+ /* ok, create it */
+ create_proc_lang(languageName, handlerOid, valOid, stmt->pltrusted);
+ }
+}
+
+/*
+ * Guts of language creation.
+ */
+static void
+create_proc_lang(const char *languageName,
+ Oid handlerOid, Oid valOid, bool trusted)
+{
+ Relation rel;
+ TupleDesc tupDesc;
+ Datum values[Natts_pg_language];
+ char nulls[Natts_pg_language];
+ NameData langname;
+ HeapTuple tup;
+ ObjectAddress myself,
+ referenced;
/*
* Insert the new language into pg_language
*/
- for (i = 0; i < Natts_pg_language; i++)
- {
- nulls[i] = ' ';
- values[i] = (Datum) NULL;
- }
+ rel = heap_open(LanguageRelationId, RowExclusiveLock);
+ tupDesc = rel->rd_att;
- i = 0;
- namestrcpy(&langname, languageName);
- values[i++] = NameGetDatum(&langname); /* lanname */
- values[i++] = BoolGetDatum(true); /* lanispl */
- values[i++] = BoolGetDatum(stmt->pltrusted); /* lanpltrusted */
- values[i++] = ObjectIdGetDatum(procOid); /* lanplcallfoid */
- values[i++] = ObjectIdGetDatum(valProcOid); /* lanvalidator */
- nulls[i] = 'n'; /* lanacl */
+ memset(values, 0, sizeof(values));
+ memset(nulls, ' ', sizeof(nulls));
- rel = heap_open(LanguageRelationId, RowExclusiveLock);
+ namestrcpy(&langname, languageName);
+ values[Anum_pg_language_lanname - 1] = NameGetDatum(&langname);
+ values[Anum_pg_language_lanispl - 1] = BoolGetDatum(true);
+ values[Anum_pg_language_lanpltrusted - 1] = BoolGetDatum(trusted);
+ values[Anum_pg_language_lanplcallfoid - 1] = ObjectIdGetDatum(handlerOid);
+ values[Anum_pg_language_lanvalidator - 1] = ObjectIdGetDatum(valOid);
+ nulls[Anum_pg_language_lanacl - 1] = 'n';
- tupDesc = rel->rd_att;
tup = heap_formtuple(tupDesc, values, nulls);
simple_heap_insert(rel, tup);
/* dependency on the PL handler function */
referenced.classId = ProcedureRelationId;
- referenced.objectId = procOid;
+ referenced.objectId = handlerOid;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
/* dependency on the validator function, if any */
- if (OidIsValid(valProcOid))
+ if (OidIsValid(valOid))
{
referenced.classId = ProcedureRelationId;
- referenced.objectId = valProcOid;
+ referenced.objectId = valOid;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
heap_close(rel, RowExclusiveLock);
}
+/*
+ * 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++)
+ {
+ if (strcmp(languageName, ptr->lanname) == 0)
+ return ptr;
+ }
+ return NULL;
+}
+
/* ---------------------------------------------------------------------
* DROP PROCEDURAL LANGUAGE
errmsg("must be superuser to drop procedural language")));
/*
- * Translate the language name, check that this language exist and is
- * a PL
+ * Translate the language name, check that the language exists
*/
languageName = case_translate_language_name(stmt->plname);
HeapTuple tup;
Relation rel;
+ /* Translate both names for consistency with CREATE */
+ oldname = case_translate_language_name(oldname);
+ newname = case_translate_language_name(newname);
+
rel = heap_open(LanguageRelationId, RowExclusiveLock);
tup = SearchSysCacheCopy(LANGNAME,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("language \"%s\" already exists", newname)));
- /* must be superuser */
+ /* must be superuser, since we do not have owners for PLs */
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.509 2005/08/24 19:34:12 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.510 2005/09/05 23:50:48 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
CreatePLangStmt:
CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
- HANDLER handler_name opt_validator opt_lancompiler
+ {
+ CreatePLangStmt *n = makeNode(CreatePLangStmt);
+ n->plname = $5;
+ /* parameters are all to be supplied by system */
+ n->plhandler = NIL;
+ n->plvalidator = NIL;
+ n->pltrusted = false;
+ $$ = (Node *)n;
+ }
+ | CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
+ HANDLER handler_name opt_validator opt_lancompiler
{
CreatePLangStmt *n = makeNode(CreatePLangStmt);
n->plname = $5;
n->plhandler = $7;
n->plvalidator = $8;
n->pltrusted = $2;
+ /* LANCOMPILER is now ignored entirely */
$$ = (Node *)n;
}
;
| name attrs { $$ = lcons(makeString($1), $2); }
;
-opt_lancompiler:
- LANCOMPILER Sconst { $$ = $2; }
- | /*EMPTY*/ { $$ = ""; }
+opt_validator:
+ VALIDATOR handler_name { $$ = $2; }
+ | /*EMPTY*/ { $$ = NIL; }
;
-opt_validator:
- VALIDATOR handler_name { $$ = $2; }
- | /*EMPTY*/ { $$ = NULL; }
+opt_lancompiler:
+ LANCOMPILER Sconst { $$ = $2; }
+ | /*EMPTY*/ { $$ = NULL; }
;
DropPLangStmt:
* by PostgreSQL
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.419 2005/08/23 22:40:31 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.420 2005/09/05 23:50:48 tgl Exp $
*
*-------------------------------------------------------------------------
*/
int i_proargtypes;
int i_prorettype;
int i_proacl;
- int i_is_pl_handler;
/* Make sure we are in proper schema */
selectSourceSchema("pg_catalog");
if (g_fout->remoteVersion >= 70300)
{
- /*
- * For 7.3 and up, we consider it's user-defined if it's not in
- * pg_catalog. We also collect info on functions in pg_catalog, but
- * only if they are call handlers or validators for PL languages.
- */
appendPQExpBuffer(query,
"SELECT tableoid, oid, proname, prolang, "
"pronargs, proargtypes, prorettype, proacl, "
"pronamespace, "
- "(%s proowner) as rolname, "
- "CASE WHEN oid IN "
- " (select lanplcallfoid from pg_language "
- " where lanispl) THEN true "
- " WHEN oid IN "
- " (select lanvalidator from pg_language "
- " where lanispl) THEN true "
- " ELSE false END AS is_pl_handler "
+ "(%s proowner) as rolname "
"FROM pg_proc "
"WHERE NOT proisagg "
- "AND (pronamespace != "
- " (select oid from pg_namespace "
- " where nspname = 'pg_catalog')"
- " OR oid IN "
- " (select lanplcallfoid from pg_language "
- " where lanispl) "
- " OR oid IN "
- " (select lanvalidator from pg_language "
- " where lanispl))",
+ "AND pronamespace != "
+ "(select oid from pg_namespace"
+ " where nspname = 'pg_catalog')",
username_subquery);
}
else if (g_fout->remoteVersion >= 70100)
"pronargs, proargtypes, prorettype, "
"'{=X}' as proacl, "
"0::oid as pronamespace, "
- "(%s proowner) as rolname, "
- "false AS is_pl_handler "
+ "(%s proowner) as rolname "
"FROM pg_proc "
"where pg_proc.oid > '%u'::oid",
username_subquery,
"pronargs, proargtypes, prorettype, "
"'{=X}' as proacl, "
"0::oid as pronamespace, "
- "(%s proowner) as rolname, "
- "false AS is_pl_handler "
+ "(%s proowner) as rolname "
"FROM pg_proc "
"where pg_proc.oid > '%u'::oid",
username_subquery,
i_proargtypes = PQfnumber(res, "proargtypes");
i_prorettype = PQfnumber(res, "prorettype");
i_proacl = PQfnumber(res, "proacl");
- i_is_pl_handler = PQfnumber(res,"is_pl_handler");
for (i = 0; i < ntups; i++)
{
finfo[i].prorettype = atooid(PQgetvalue(res, i, i_prorettype));
finfo[i].proacl = strdup(PQgetvalue(res, i, i_proacl));
finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs));
- finfo[i].islanghandler =
- strcmp(PQgetvalue(res, i, i_is_pl_handler), "t") == 0;
if (finfo[i].nargs == 0)
finfo[i].argtypes = NULL;
else
{
PQExpBuffer defqry;
PQExpBuffer delqry;
+ bool useParams;
char *qlanname;
+ char *lanschema;
FuncInfo *funcInfo;
FuncInfo *validatorInfo = NULL;
return;
/*
- * Find the support functions, complaining if not there.
+ * Try to find the support function(s). It is not an error if we
+ * don't find them --- if the functions are in the pg_catalog schema,
+ * as is standard in 8.1 and up, then we won't have loaded them.
+ * (In this case we will emit a parameterless CREATE LANGUAGE command,
+ * which will require PL template knowledge in the backend to reload.)
*/
+
funcInfo = findFuncByOid(plang->lanplcallfoid);
- if (funcInfo == NULL)
- {
- write_msg(NULL, "WARNING: handler function for language \"%s\" not found\n",
- plang->dobj.name);
- return;
- }
+ if (funcInfo != NULL && !funcInfo->dobj.namespace->dump)
+ funcInfo = NULL; /* treat not-dumped same as not-found */
if (OidIsValid(plang->lanvalidator))
{
validatorInfo = findFuncByOid(plang->lanvalidator);
- if (validatorInfo == NULL)
- {
- write_msg(NULL, "WARNING: validator function for language \"%s\" not found\n",
- plang->dobj.name);
- return;
- }
+ if (validatorInfo != NULL && !validatorInfo->dobj.namespace->dump)
+ validatorInfo = NULL;
}
- /* Dump if we should, or if both support functions are dumpable */
- if (!shouldDumpProcLangs() &&
- !(funcInfo->dobj.namespace->dump &&
- (validatorInfo == NULL || validatorInfo->dobj.namespace->dump)))
+ /*
+ * If the functions are dumpable then emit a traditional CREATE LANGUAGE
+ * with parameters. Otherwise, dump only if shouldDumpProcLangs() says
+ * to dump it.
+ */
+ useParams = (funcInfo != NULL &&
+ (validatorInfo != NULL || !OidIsValid(plang->lanvalidator)));
+
+ if (!useParams && !shouldDumpProcLangs())
return;
defqry = createPQExpBuffer();
qlanname = strdup(fmtId(plang->dobj.name));
+ /*
+ * If dumping a HANDLER clause, treat the language as being in the
+ * handler function's schema; this avoids cluttering the HANDLER clause.
+ * Otherwise it doesn't really have a schema.
+ */
+ if (useParams)
+ lanschema = funcInfo->dobj.namespace->dobj.name;
+ else
+ lanschema = NULL;
+
appendPQExpBuffer(delqry, "DROP PROCEDURAL LANGUAGE %s;\n",
qlanname);
appendPQExpBuffer(defqry, "CREATE %sPROCEDURAL LANGUAGE %s",
- plang->lanpltrusted ? "TRUSTED " : "",
+ (useParams && plang->lanpltrusted) ? "TRUSTED " : "",
qlanname);
- appendPQExpBuffer(defqry, " HANDLER %s",
- fmtId(funcInfo->dobj.name));
- if (OidIsValid(plang->lanvalidator))
+ if (useParams)
{
- appendPQExpBuffer(defqry, " VALIDATOR ");
- /* Cope with possibility that validator is in different schema */
- if (validatorInfo->dobj.namespace != funcInfo->dobj.namespace)
- appendPQExpBuffer(defqry, "%s.",
- fmtId(validatorInfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(defqry, "%s",
- fmtId(validatorInfo->dobj.name));
+ appendPQExpBuffer(defqry, " HANDLER %s",
+ fmtId(funcInfo->dobj.name));
+ if (OidIsValid(plang->lanvalidator))
+ {
+ appendPQExpBuffer(defqry, " VALIDATOR ");
+ /* Cope with possibility that validator is in different schema */
+ if (validatorInfo->dobj.namespace != funcInfo->dobj.namespace)
+ appendPQExpBuffer(defqry, "%s.",
+ fmtId(validatorInfo->dobj.namespace->dobj.name));
+ appendPQExpBuffer(defqry, "%s",
+ fmtId(validatorInfo->dobj.name));
+ }
}
appendPQExpBuffer(defqry, ";\n");
- /*
- * We mark the PL's archive entry as being in the call handler's
- * namespace; this is what makes it OK to refer to the handler with
- * an unqualified name above.
- */
ArchiveEntry(fout, plang->dobj.catId, plang->dobj.dumpId,
plang->dobj.name,
- funcInfo->dobj.namespace->dobj.name, NULL, "",
+ lanschema, NULL, "",
false, "PROCEDURAL LANGUAGE",
defqry->data, delqry->data, NULL,
plang->dobj.dependencies, plang->dobj.nDeps,
/* Dump Proc Lang Comments */
resetPQExpBuffer(defqry);
-
appendPQExpBuffer(defqry, "LANGUAGE %s", qlanname);
dumpComment(fout, defqry->data,
NULL, "",
if (plang->lanpltrusted)
dumpACL(fout, plang->dobj.catId, plang->dobj.dumpId, "LANGUAGE",
qlanname, plang->dobj.name,
- funcInfo->dobj.namespace->dobj.name,
+ lanschema,
NULL, plang->lanacl);
free(qlanname);
char **argmodes = NULL;
char **argnames = NULL;
- if (dataOnly)
- return;
-
- /* Dump only funcs in dumpable namespaces, or needed language handlers */
- if (!finfo->dobj.namespace->dump &&
- (!finfo->islanghandler || !shouldDumpProcLangs()))
+ /* Dump only funcs in dumpable namespaces */
+ if (!finfo->dobj.namespace->dump || dataOnly)
return;
query = createPQExpBuffer();
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.120 2005/08/23 22:40:35 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.121 2005/09/05 23:50:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
Oid *argtypes;
Oid prorettype;
char *proacl;
- bool islanghandler;
} FuncInfo;
/* AggInfo is a superset of FuncInfo */
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/bin/scripts/createlang.c,v 1.19 2005/08/15 21:02:26 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/scripts/createlang.c,v 1.20 2005/09/05 23:50:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
-
#include "postgres_fe.h"
+
#include "common.h"
#include "print.h"
{"username", required_argument, NULL, 'U'},
{"password", no_argument, NULL, 'W'},
{"dbname", required_argument, NULL, 'd'},
- {"pglib", required_argument, NULL, 'L'},
{"echo", no_argument, NULL, 'e'},
{NULL, 0, NULL, 0}
};
char *username = NULL;
bool password = false;
bool echo = false;
- char *pglib = NULL;
char *langname = NULL;
char *p;
- bool handlerexists;
- bool validatorexists;
- bool trusted;
- char *handler;
- char *validator = NULL;
- char *object;
PQExpBufferData sql;
handle_help_version_opts(argc, argv, "createlang", help);
- while ((c = getopt_long(argc, argv, "lh:p:U:Wd:L:e", long_options, &optindex)) != -1)
+ while ((c = getopt_long(argc, argv, "lh:p:U:Wd:e", long_options, &optindex)) != -1)
{
switch (c)
{
case 'd':
dbname = optarg;
break;
- case 'L':
- pglib = optarg;
- break;
case 'e':
echo = true;
break;
exit(1);
}
- if (!pglib)
- pglib = "$libdir";
-
for (p = langname; *p; p++)
if (*p >= 'A' && *p <= 'Z')
*p += ('a' - 'A');
- if (strcmp(langname, "plpgsql") == 0)
- {
- trusted = true;
- handler = "plpgsql_call_handler";
- validator = "plpgsql_validator";
- object = "plpgsql";
- }
- else if (strcmp(langname, "pltcl") == 0)
- {
- trusted = true;
- handler = "pltcl_call_handler";
- object = "pltcl";
- }
- else if (strcmp(langname, "pltclu") == 0)
- {
- trusted = false;
- handler = "pltclu_call_handler";
- object = "pltcl";
- }
- else if (strcmp(langname, "plperl") == 0)
- {
- trusted = true;
- handler = "plperl_call_handler";
- validator = "plperl_validator";
- object = "plperl";
- }
- else if (strcmp(langname, "plperlu") == 0)
- {
- trusted = false;
- handler = "plperl_call_handler";
- validator = "plperl_validator";
- object = "plperl";
- }
- else if (strcmp(langname, "plpythonu") == 0)
- {
- trusted = false;
- handler = "plpython_call_handler";
- object = "plpython";
- }
- else
- {
- fprintf(stderr, _("%s: unsupported language \"%s\"\n"),
- progname, langname);
- fprintf(stderr, _("Supported languages are plpgsql, pltcl, pltclu, "
- "plperl, plperlu, and plpythonu.\n"));
- exit(1);
- }
-
conn = connectDatabase(dbname, host, port, username, password, progname);
/*
- * Force schema search path to be just pg_catalog, so that we don't
- * have to be paranoid about search paths below.
- */
- executeCommand(conn, "SET search_path = pg_catalog;",
- progname, echo);
-
- /*
* Make sure the language isn't already installed
*/
printfPQExpBuffer(&sql,
- "SELECT oid FROM pg_language WHERE lanname = '%s';",
+ "SELECT oid FROM pg_catalog.pg_language WHERE lanname = '%s';",
langname);
result = executeQuery(conn, sql.data, progname, echo);
if (PQntuples(result) > 0)
}
PQclear(result);
- /*
- * Check whether the call handler exists
- */
- printfPQExpBuffer(&sql, "SELECT oid FROM pg_proc WHERE proname = '%s' "
- "AND pronamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog') "
- "AND prorettype = 'language_handler'::regtype "
- "AND pronargs = 0;", handler);
- result = executeQuery(conn, sql.data, progname, echo);
- handlerexists = (PQntuples(result) > 0);
- PQclear(result);
-
- /*
- * Check whether the validator exists
- */
- if (validator)
- {
- printfPQExpBuffer(&sql, "SELECT oid FROM pg_proc WHERE proname = '%s' "
- "AND pronamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog') "
- "AND proargtypes[0] = 'oid'::regtype "
- "AND pronargs = 1;", validator);
- result = executeQuery(conn, sql.data, progname, echo);
- validatorexists = (PQntuples(result) > 0);
- PQclear(result);
- }
- else
- validatorexists = true; /* don't try to create it */
-
- /*
- * Create the function(s) and the language
- *
- * NOTE: the functions will be created in pg_catalog because
- * of our previous "SET search_path".
- */
- resetPQExpBuffer(&sql);
-
- if (!handlerexists)
- appendPQExpBuffer(&sql,
- "CREATE FUNCTION \"%s\" () RETURNS language_handler "
- "AS '%s/%s' LANGUAGE C;\n",
- handler, pglib, object);
-
- if (!validatorexists)
- appendPQExpBuffer(&sql,
- "CREATE FUNCTION \"%s\" (oid) RETURNS void "
- "AS '%s/%s' LANGUAGE C;\n",
- validator, pglib, object);
-
- appendPQExpBuffer(&sql,
- "CREATE %sLANGUAGE \"%s\" HANDLER \"%s\"",
- (trusted ? "TRUSTED " : ""), langname, handler);
-
- if (validator)
- appendPQExpBuffer(&sql, " VALIDATOR \"%s\"", validator);
-
- appendPQExpBuffer(&sql, ";\n");
+ printfPQExpBuffer(&sql, "CREATE LANGUAGE \"%s\";\n", langname);
if (echo)
printf("%s", sql.data);
printf(_(" -d, --dbname=DBNAME database to install language in\n"));
printf(_(" -e, --echo show the commands being sent to the server\n"));
printf(_(" -l, --list show a list of currently installed languages\n"));
- printf(_(" -L, --pglib=DIRECTORY find language interpreter file in DIRECTORY\n"));
printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
printf(_(" -p, --port=PORT database server port\n"));
printf(_(" -U, --username=USERNAME user name to connect as\n"));
#! /bin/sh
-# $PostgreSQL: pgsql/src/test/regress/pg_regress.sh,v 1.59 2005/07/17 18:28:45 tgl Exp $
+# $PostgreSQL: pgsql/src/test/regress/pg_regress.sh,v 1.60 2005/09/05 23:50:49 tgl Exp $
me=`basename $0`
: ${TMPDIR=/tmp}
: ${outputdir=.}
libdir='@libdir@'
-pkglibdir='@pkglibdir@'
bindir='@bindir@'
datadir='@datadir@'
host_platform='@host_tuple@'
if [ x"$temp_install" != x"" ]
then
if echo x"$temp_install" | grep -v '^x/' >/dev/null 2>&1; then
- case $host_platform in
- *-*-mingw32*)
- pkglibdir="`pwd -W`/$temp_install/install/$pkglibdir"
- temp_install="`pwd`/$temp_install"
- ;;
- *)
- temp_install="`pwd`/$temp_install"
- pkglibdir=$temp_install/install/$pkglibdir
- ;;
- esac
+ temp_install="`pwd`/$temp_install"
fi
bindir=$temp_install/install/$bindir
(exit 2); exit
fi
- # fix conversion shared objs path
- conv=$datadir/conversion_create.sql
- backup=$conv.bak
- mv $conv $backup
- sed -e "s@\$libdir@$pkglibdir@g" $backup > $conv
- rm $backup
-
message "initializing database system"
[ "$debug" = yes ] && initdb_options='--debug'
"$bindir/initdb" -D "$PGDATA" -L "$datadir" --noclean $initdb_options >"$LOGDIR/initdb.log" 2>&1
for lang in xyzzy $load_langs ; do
if [ "$lang" != "xyzzy" ]; then
message "installing $lang"
- "$bindir/createlang" -L "$pkglibdir" $psql_options $lang $dbname
+ "$bindir/createlang" $psql_options $lang $dbname
if [ $? -ne 0 ] && [ $? -ne 2 ]; then
echo "$me: createlang $lang failed"
(exit 2); exit