Commit e0dedd05 authored by Tom Lane's avatar Tom Lane

Implement a preliminary 'template' facility for procedural languages,

as per my recent proposal.  For now the template data is hard-wired in
proclang.c --- this should be replaced later by a new shared system
catalog, but we don't want to force initdb during 8.1 beta.  This change
lets us cleanly load existing dump files even if they contain outright
wrong information about a PL's support functions, such as a wrong path
to the shared library or a missing validator function.  Also, we can
revert the recent kluges to make pg_dump dump PL support functions that
are stored in pg_catalog.
While at it, I removed the code in pg_regress that replaced $libdir
with a hardcoded path for temporary installations.  This is no longer
needed given our support for relocatable installations.
parent e35e6b1c
<!-- <!--
$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 PostgreSQL documentation
--> -->
...@@ -20,6 +20,7 @@ PostgreSQL documentation ...@@ -20,6 +20,7 @@ PostgreSQL documentation
<refsynopsisdiv> <refsynopsisdiv>
<synopsis> <synopsis>
CREATE [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</replaceable>
CREATE [ TRUSTED ] [ 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> ] HANDLER <replaceable class="parameter">call_handler</replaceable> [ VALIDATOR <replaceable>valfunction</replaceable> ]
</synopsis> </synopsis>
...@@ -46,9 +47,25 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</ ...@@ -46,9 +47,25 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</
</para> </para>
<para> <para>
Note that procedural languages are local to individual databases. There are two forms of the <command>CREATE LANGUAGE</command> command.
To make a language available in all databases by default, it should In the first form, the user merely supplies the name of the desired
be installed into the <literal>template1</literal> database. 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> </para>
</refsect1> </refsect1>
...@@ -145,52 +162,68 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</ ...@@ -145,52 +162,68 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </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>
<refsect1 id="sql-createlanguage-notes"> <refsect1 id="sql-createlanguage-notes">
<title>Notes</title> <title>Notes</title>
<para> <para>
This command normally should not be executed directly by users. The <xref linkend="app-createlang"> program is a simple wrapper around
For the procedural languages supplied in the the <command>CREATE LANGUAGE</> command. It eases
<productname>PostgreSQL</productname> distribution, the <xref installation of procedural languages from the shell command line.
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.)
</para> </para>
<para> <para>
In <productname>PostgreSQL</productname> versions before 7.3, it was Use <xref linkend="sql-droplanguage" endterm="sql-droplanguage-title">, or better yet the <xref
necessary to declare handler functions as returning the placeholder linkend="app-droplang"> program, to drop procedural languages.
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> </para>
<para> <para>
Use the <xref linkend="sql-createfunction" endterm="sql-createfunction-title"> command to create a new The system catalog <classname>pg_language</classname> (see <xref
function. 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>
<para> <para>
Use <xref linkend="sql-droplanguage" endterm="sql-droplanguage-title">, or better yet the <xref To create functions in a procedural language, a user must have the
linkend="app-droplang"> program, to drop procedural languages. <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>
<para> <para>
The system catalog <classname>pg_language</classname> (see <xref Procedural languages are local to individual databases.
linkend="catalog-pg-language">) records information about the However, a language can be installed into the <literal>template1</literal>
currently installed languages. Also <command>createlang</command> database, which will cause it to be available automatically in
has an option to list the installed languages. all subsequently-created databases.
</para> </para>
<para> <para>
To be able to use a procedural language, a user must be granted the The call handler function and the validator function (if any)
<literal>USAGE</literal> privilege. The must already exist if the server does not have information about
<command>createlang</command> program automatically grants the language in its internal table. But when there is an entry
permissions to everyone if the language is known to be trusted. 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> </para>
</refsect1> </refsect1>
...@@ -198,8 +231,16 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</ ...@@ -198,8 +231,16 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</
<title>Examples</title> <title>Examples</title>
<para> <para>
The following two commands executed in sequence will register a new The preferred way of creating any of the standard procedural languages
procedural language and the associated call handler. 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> <programlisting>
CREATE FUNCTION plsample_call_handler() RETURNS language_handler CREATE FUNCTION plsample_call_handler() RETURNS language_handler
AS '$libdir/plsample' 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 PostgreSQL documentation
--> -->
...@@ -42,13 +42,7 @@ PostgreSQL documentation ...@@ -42,13 +42,7 @@ PostgreSQL documentation
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> can handle all the languages
supplied in the default <productname>PostgreSQL</> distribution, but supplied in the default <productname>PostgreSQL</> distribution, but
not languages provided by other parties. not languages provided by other parties. See
</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
<xref linkend="sql-createlanguage" endterm="sql-createlanguage-title"> <xref linkend="sql-createlanguage" endterm="sql-createlanguage-title">
for additional information. for additional information.
</para> </para>
...@@ -104,17 +98,6 @@ PostgreSQL documentation ...@@ -104,17 +98,6 @@ PostgreSQL documentation
</listitem> </listitem>
</varlistentry> </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> </variablelist>
</para> </para>
......
<!-- <!--
$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"> <chapter id="xplang">
...@@ -59,17 +59,19 @@ $PostgreSQL: pgsql/doc/src/sgml/xplang.sgml,v 1.28 2004/12/30 21:45:37 tgl Exp $ ...@@ -59,17 +59,19 @@ $PostgreSQL: pgsql/doc/src/sgml/xplang.sgml,v 1.28 2004/12/30 21:45:37 tgl Exp $
</para> </para>
<para> <para>
For the languages supplied with the standard distribution, the For the languages supplied with the standard distribution, it is
program <xref linkend="app-createlang"> may be used to install the only necessary to execute <command>CREATE LANGUAGE</>
language instead of carrying out the details by hand. For <replaceable>language_name</> to install the language into the
example, to install the language 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 <application>PL/pgSQL</application> into the database
<literal>template1</>, use <literal>template1</>, use
<programlisting> <programlisting>
createlang plpgsql template1 createlang plpgsql template1
</programlisting> </programlisting>
The manual procedure described below is only recommended for 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. does not know about.
</para> </para>
...@@ -80,9 +82,10 @@ createlang plpgsql template1 ...@@ -80,9 +82,10 @@ createlang plpgsql template1
<para> <para>
A procedural language is installed in a database in four steps, A procedural language is installed in a database in four steps,
which must be carried out by a database superuser. The which must be carried out by a database superuser. (For languages
<command>createlang</command> program automates all but <xref known to <command>CREATE LANGUAGE</>, the second and third steps
linkend="xplang-install-cr1">. can be omitted, because they will be carried out automatically
if needed.)
</para> </para>
<step performance="required" id="xplang-install-cr1"> <step performance="required" id="xplang-install-cr1">
...@@ -202,10 +205,11 @@ CREATE TRUSTED PROCEDURAL LANGUAGE plpgsql ...@@ -202,10 +205,11 @@ CREATE TRUSTED PROCEDURAL LANGUAGE plpgsql
In a default <productname>PostgreSQL</productname> installation, In a default <productname>PostgreSQL</productname> installation,
the handler for the <application>PL/pgSQL</application> language the handler for the <application>PL/pgSQL</application> language
is built and installed into the <quote>library</quote> is built and installed into the <quote>library</quote>
directory. If <application>Tcl</> support is configured in, the handlers for directory. If <application>Tcl</> support is configured in, the handlers
<application>PL/Tcl</> and <application>PL/TclU</> are also built and installed in the same for <application>PL/Tcl</> and <application>PL/TclU</> are also built and
location. Likewise, the <application>PL/Perl</> and <application>PL/PerlU</> handlers are built installed in the same location. Likewise, the <application>PL/Perl</> and
and installed if Perl support is configured, and <application>PL/PythonU</> is <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. installed if Python support is configured.
</para> </para>
......
...@@ -7,31 +7,46 @@ ...@@ -7,31 +7,46 @@
* 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.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 "postgres.h"
#include <ctype.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_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"
#include "commands/defrem.h" #include "commands/defrem.h"
#include "fmgr.h" #include "fmgr.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "parser/gramparse.h"
#include "parser/parse_func.h" #include "parser/parse_func.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/syscache.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 * CREATE PROCEDURAL LANGUAGE
* --------------------------------------------------------------------- * ---------------------------------------------------------------------
...@@ -40,19 +55,11 @@ void ...@@ -40,19 +55,11 @@ void
CreateProceduralLanguage(CreatePLangStmt *stmt) CreateProceduralLanguage(CreatePLangStmt *stmt)
{ {
char *languageName; char *languageName;
Oid procOid, PLTemplate *pltemplate;
valProcOid; Oid handlerOid,
valOid;
Oid funcrettype; Oid funcrettype;
Oid funcargtypes[1]; 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 * Check permission
...@@ -75,18 +82,118 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) ...@@ -75,18 +82,118 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
(errcode(ERRCODE_DUPLICATE_OBJECT), (errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("language \"%s\" already exists", languageName))); errmsg("language \"%s\" already exists", languageName)));
/*
* If we have template information for the language, ignore the supplied
* parameters (if any) and use the template information.
*/
if ((pltemplate = find_language_template(languageName)) != NULL)
{
List *funcname;
/*
* 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);
handlerOid = LookupFuncName(funcname, 0, funcargtypes, true);
if (OidIsValid(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
{
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));
}
/*
* 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
{
/*
* 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 * Lookup the PL handler function and check that it is of the expected
* return type * return type
*/ */
procOid = LookupFuncName(stmt->plhandler, 0, funcargtypes, false); handlerOid = LookupFuncName(stmt->plhandler, 0, funcargtypes, false);
funcrettype = get_func_rettype(procOid); funcrettype = get_func_rettype(handlerOid);
if (funcrettype != LANGUAGE_HANDLEROID) if (funcrettype != LANGUAGE_HANDLEROID)
{ {
/* /*
* We allow OPAQUE just so we can load old dump files. When we * We allow OPAQUE just so we can load old dump files. When we
* see a handler function declared OPAQUE, change it to * see a handler function declared OPAQUE, change it to
* LANGUAGE_HANDLER. * LANGUAGE_HANDLER. (This is probably obsolete and removable?)
*/ */
if (funcrettype == OPAQUEOID) if (funcrettype == OPAQUEOID)
{ {
...@@ -94,7 +201,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) ...@@ -94,7 +201,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
(errcode(ERRCODE_WRONG_OBJECT_TYPE), (errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("changing return type of function %s from \"opaque\" to \"language_handler\"", errmsg("changing return type of function %s from \"opaque\" to \"language_handler\"",
NameListToString(stmt->plhandler)))); NameListToString(stmt->plhandler))));
SetFunctionReturnType(procOid, LANGUAGE_HANDLEROID); SetFunctionReturnType(handlerOid, LANGUAGE_HANDLEROID);
} }
else else
ereport(ERROR, ereport(ERROR,
...@@ -107,33 +214,50 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) ...@@ -107,33 +214,50 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
if (stmt->plvalidator) if (stmt->plvalidator)
{ {
funcargtypes[0] = OIDOID; funcargtypes[0] = OIDOID;
valProcOid = LookupFuncName(stmt->plvalidator, 1, funcargtypes, false); valOid = LookupFuncName(stmt->plvalidator, 1, funcargtypes, false);
/* return value is ignored, so we don't check the type */ /* return value is ignored, so we don't check the type */
} }
else else
valProcOid = InvalidOid; 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 * Insert the new language into pg_language
*/ */
for (i = 0; i < Natts_pg_language; i++) rel = heap_open(LanguageRelationId, RowExclusiveLock);
{ tupDesc = rel->rd_att;
nulls[i] = ' ';
values[i] = (Datum) NULL;
}
i = 0; memset(values, 0, sizeof(values));
namestrcpy(&langname, languageName); memset(nulls, ' ', sizeof(nulls));
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 */
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); tup = heap_formtuple(tupDesc, values, nulls);
simple_heap_insert(rel, tup); simple_heap_insert(rel, tup);
...@@ -149,15 +273,15 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) ...@@ -149,15 +273,15 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
/* dependency on the PL handler function */ /* dependency on the PL handler function */
referenced.classId = ProcedureRelationId; referenced.classId = ProcedureRelationId;
referenced.objectId = procOid; referenced.objectId = handlerOid;
referenced.objectSubId = 0; referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
/* dependency on the validator function, if any */ /* dependency on the validator function, if any */
if (OidIsValid(valProcOid)) if (OidIsValid(valOid))
{ {
referenced.classId = ProcedureRelationId; referenced.classId = ProcedureRelationId;
referenced.objectId = valProcOid; referenced.objectId = valOid;
referenced.objectSubId = 0; referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
} }
...@@ -165,6 +289,45 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) ...@@ -165,6 +289,45 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
heap_close(rel, RowExclusiveLock); 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 * DROP PROCEDURAL LANGUAGE
...@@ -186,8 +349,7 @@ DropProceduralLanguage(DropPLangStmt *stmt) ...@@ -186,8 +349,7 @@ DropProceduralLanguage(DropPLangStmt *stmt)
errmsg("must be superuser to drop procedural language"))); errmsg("must be superuser to drop procedural language")));
/* /*
* Translate the language name, check that this language exist and is * Translate the language name, check that the language exists
* a PL
*/ */
languageName = case_translate_language_name(stmt->plname); languageName = case_translate_language_name(stmt->plname);
...@@ -244,6 +406,10 @@ RenameLanguage(const char *oldname, const char *newname) ...@@ -244,6 +406,10 @@ RenameLanguage(const char *oldname, const char *newname)
HeapTuple tup; HeapTuple tup;
Relation rel; 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); rel = heap_open(LanguageRelationId, RowExclusiveLock);
tup = SearchSysCacheCopy(LANGNAME, tup = SearchSysCacheCopy(LANGNAME,
...@@ -262,7 +428,7 @@ RenameLanguage(const char *oldname, const char *newname) ...@@ -262,7 +428,7 @@ RenameLanguage(const char *oldname, const char *newname)
(errcode(ERRCODE_DUPLICATE_OBJECT), (errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("language \"%s\" already exists", newname))); errmsg("language \"%s\" already exists", newname)));
/* must be superuser */ /* must be superuser, since we do not have owners for PLs */
if (!superuser()) if (!superuser())
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * 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 * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -2303,6 +2303,16 @@ IntegerOnly: SignedIconst { $$ = makeInteger($1); }; ...@@ -2303,6 +2303,16 @@ IntegerOnly: SignedIconst { $$ = makeInteger($1); };
CreatePLangStmt: CreatePLangStmt:
CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
{
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 HANDLER handler_name opt_validator opt_lancompiler
{ {
CreatePLangStmt *n = makeNode(CreatePLangStmt); CreatePLangStmt *n = makeNode(CreatePLangStmt);
...@@ -2310,6 +2320,7 @@ CreatePLangStmt: ...@@ -2310,6 +2320,7 @@ CreatePLangStmt:
n->plhandler = $7; n->plhandler = $7;
n->plvalidator = $8; n->plvalidator = $8;
n->pltrusted = $2; n->pltrusted = $2;
/* LANCOMPILER is now ignored entirely */
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
...@@ -2328,13 +2339,13 @@ handler_name: ...@@ -2328,13 +2339,13 @@ handler_name:
| name attrs { $$ = lcons(makeString($1), $2); } | name attrs { $$ = lcons(makeString($1), $2); }
; ;
opt_lancompiler:
LANCOMPILER Sconst { $$ = $2; }
| /*EMPTY*/ { $$ = ""; }
;
opt_validator: opt_validator:
VALIDATOR handler_name { $$ = $2; } VALIDATOR handler_name { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
;
opt_lancompiler:
LANCOMPILER Sconst { $$ = $2; }
| /*EMPTY*/ { $$ = NULL; } | /*EMPTY*/ { $$ = NULL; }
; ;
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* by PostgreSQL * by PostgreSQL
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2295,7 +2295,6 @@ getFuncs(int *numFuncs) ...@@ -2295,7 +2295,6 @@ getFuncs(int *numFuncs)
int i_proargtypes; int i_proargtypes;
int i_prorettype; int i_prorettype;
int i_proacl; int i_proacl;
int i_is_pl_handler;
/* Make sure we are in proper schema */ /* Make sure we are in proper schema */
selectSourceSchema("pg_catalog"); selectSourceSchema("pg_catalog");
...@@ -2304,34 +2303,16 @@ getFuncs(int *numFuncs) ...@@ -2304,34 +2303,16 @@ getFuncs(int *numFuncs)
if (g_fout->remoteVersion >= 70300) 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, appendPQExpBuffer(query,
"SELECT tableoid, oid, proname, prolang, " "SELECT tableoid, oid, proname, prolang, "
"pronargs, proargtypes, prorettype, proacl, " "pronargs, proargtypes, prorettype, proacl, "
"pronamespace, " "pronamespace, "
"(%s proowner) as rolname, " "(%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 "
"FROM pg_proc " "FROM pg_proc "
"WHERE NOT proisagg " "WHERE NOT proisagg "
"AND (pronamespace != " "AND pronamespace != "
" (select oid from pg_namespace " "(select oid from pg_namespace"
" where nspname = 'pg_catalog')" " where nspname = 'pg_catalog')",
" OR oid IN "
" (select lanplcallfoid from pg_language "
" where lanispl) "
" OR oid IN "
" (select lanvalidator from pg_language "
" where lanispl))",
username_subquery); username_subquery);
} }
else if (g_fout->remoteVersion >= 70100) else if (g_fout->remoteVersion >= 70100)
...@@ -2341,8 +2322,7 @@ getFuncs(int *numFuncs) ...@@ -2341,8 +2322,7 @@ getFuncs(int *numFuncs)
"pronargs, proargtypes, prorettype, " "pronargs, proargtypes, prorettype, "
"'{=X}' as proacl, " "'{=X}' as proacl, "
"0::oid as pronamespace, " "0::oid as pronamespace, "
"(%s proowner) as rolname, " "(%s proowner) as rolname "
"false AS is_pl_handler "
"FROM pg_proc " "FROM pg_proc "
"where pg_proc.oid > '%u'::oid", "where pg_proc.oid > '%u'::oid",
username_subquery, username_subquery,
...@@ -2358,8 +2338,7 @@ getFuncs(int *numFuncs) ...@@ -2358,8 +2338,7 @@ getFuncs(int *numFuncs)
"pronargs, proargtypes, prorettype, " "pronargs, proargtypes, prorettype, "
"'{=X}' as proacl, " "'{=X}' as proacl, "
"0::oid as pronamespace, " "0::oid as pronamespace, "
"(%s proowner) as rolname, " "(%s proowner) as rolname "
"false AS is_pl_handler "
"FROM pg_proc " "FROM pg_proc "
"where pg_proc.oid > '%u'::oid", "where pg_proc.oid > '%u'::oid",
username_subquery, username_subquery,
...@@ -2385,7 +2364,6 @@ getFuncs(int *numFuncs) ...@@ -2385,7 +2364,6 @@ getFuncs(int *numFuncs)
i_proargtypes = PQfnumber(res, "proargtypes"); i_proargtypes = PQfnumber(res, "proargtypes");
i_prorettype = PQfnumber(res, "prorettype"); i_prorettype = PQfnumber(res, "prorettype");
i_proacl = PQfnumber(res, "proacl"); i_proacl = PQfnumber(res, "proacl");
i_is_pl_handler = PQfnumber(res,"is_pl_handler");
for (i = 0; i < ntups; i++) for (i = 0; i < ntups; i++)
{ {
...@@ -2402,8 +2380,6 @@ getFuncs(int *numFuncs) ...@@ -2402,8 +2380,6 @@ getFuncs(int *numFuncs)
finfo[i].prorettype = atooid(PQgetvalue(res, i, i_prorettype)); finfo[i].prorettype = atooid(PQgetvalue(res, i, i_prorettype));
finfo[i].proacl = strdup(PQgetvalue(res, i, i_proacl)); finfo[i].proacl = strdup(PQgetvalue(res, i, i_proacl));
finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs)); 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) if (finfo[i].nargs == 0)
finfo[i].argtypes = NULL; finfo[i].argtypes = NULL;
else else
...@@ -5131,7 +5107,9 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang) ...@@ -5131,7 +5107,9 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
{ {
PQExpBuffer defqry; PQExpBuffer defqry;
PQExpBuffer delqry; PQExpBuffer delqry;
bool useParams;
char *qlanname; char *qlanname;
char *lanschema;
FuncInfo *funcInfo; FuncInfo *funcInfo;
FuncInfo *validatorInfo = NULL; FuncInfo *validatorInfo = NULL;
...@@ -5139,31 +5117,33 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang) ...@@ -5139,31 +5117,33 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
return; 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); funcInfo = findFuncByOid(plang->lanplcallfoid);
if (funcInfo == NULL) if (funcInfo != NULL && !funcInfo->dobj.namespace->dump)
{ funcInfo = NULL; /* treat not-dumped same as not-found */
write_msg(NULL, "WARNING: handler function for language \"%s\" not found\n",
plang->dobj.name);
return;
}
if (OidIsValid(plang->lanvalidator)) if (OidIsValid(plang->lanvalidator))
{ {
validatorInfo = findFuncByOid(plang->lanvalidator); validatorInfo = findFuncByOid(plang->lanvalidator);
if (validatorInfo == NULL) if (validatorInfo != NULL && !validatorInfo->dobj.namespace->dump)
{ validatorInfo = NULL;
write_msg(NULL, "WARNING: validator function for language \"%s\" not found\n",
plang->dobj.name);
return;
}
} }
/* Dump if we should, or if both support functions are dumpable */ /*
if (!shouldDumpProcLangs() && * If the functions are dumpable then emit a traditional CREATE LANGUAGE
!(funcInfo->dobj.namespace->dump && * with parameters. Otherwise, dump only if shouldDumpProcLangs() says
(validatorInfo == NULL || validatorInfo->dobj.namespace->dump))) * to dump it.
*/
useParams = (funcInfo != NULL &&
(validatorInfo != NULL || !OidIsValid(plang->lanvalidator)));
if (!useParams && !shouldDumpProcLangs())
return; return;
defqry = createPQExpBuffer(); defqry = createPQExpBuffer();
...@@ -5171,12 +5151,24 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang) ...@@ -5171,12 +5151,24 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
qlanname = strdup(fmtId(plang->dobj.name)); 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", appendPQExpBuffer(delqry, "DROP PROCEDURAL LANGUAGE %s;\n",
qlanname); qlanname);
appendPQExpBuffer(defqry, "CREATE %sPROCEDURAL LANGUAGE %s", appendPQExpBuffer(defqry, "CREATE %sPROCEDURAL LANGUAGE %s",
plang->lanpltrusted ? "TRUSTED " : "", (useParams && plang->lanpltrusted) ? "TRUSTED " : "",
qlanname); qlanname);
if (useParams)
{
appendPQExpBuffer(defqry, " HANDLER %s", appendPQExpBuffer(defqry, " HANDLER %s",
fmtId(funcInfo->dobj.name)); fmtId(funcInfo->dobj.name));
if (OidIsValid(plang->lanvalidator)) if (OidIsValid(plang->lanvalidator))
...@@ -5189,16 +5181,12 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang) ...@@ -5189,16 +5181,12 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
appendPQExpBuffer(defqry, "%s", appendPQExpBuffer(defqry, "%s",
fmtId(validatorInfo->dobj.name)); fmtId(validatorInfo->dobj.name));
} }
}
appendPQExpBuffer(defqry, ";\n"); 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, ArchiveEntry(fout, plang->dobj.catId, plang->dobj.dumpId,
plang->dobj.name, plang->dobj.name,
funcInfo->dobj.namespace->dobj.name, NULL, "", lanschema, NULL, "",
false, "PROCEDURAL LANGUAGE", false, "PROCEDURAL LANGUAGE",
defqry->data, delqry->data, NULL, defqry->data, delqry->data, NULL,
plang->dobj.dependencies, plang->dobj.nDeps, plang->dobj.dependencies, plang->dobj.nDeps,
...@@ -5206,7 +5194,6 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang) ...@@ -5206,7 +5194,6 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
/* Dump Proc Lang Comments */ /* Dump Proc Lang Comments */
resetPQExpBuffer(defqry); resetPQExpBuffer(defqry);
appendPQExpBuffer(defqry, "LANGUAGE %s", qlanname); appendPQExpBuffer(defqry, "LANGUAGE %s", qlanname);
dumpComment(fout, defqry->data, dumpComment(fout, defqry->data,
NULL, "", NULL, "",
...@@ -5215,7 +5202,7 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang) ...@@ -5215,7 +5202,7 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
if (plang->lanpltrusted) if (plang->lanpltrusted)
dumpACL(fout, plang->dobj.catId, plang->dobj.dumpId, "LANGUAGE", dumpACL(fout, plang->dobj.catId, plang->dobj.dumpId, "LANGUAGE",
qlanname, plang->dobj.name, qlanname, plang->dobj.name,
funcInfo->dobj.namespace->dobj.name, lanschema,
NULL, plang->lanacl); NULL, plang->lanacl);
free(qlanname); free(qlanname);
...@@ -5359,12 +5346,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo) ...@@ -5359,12 +5346,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
char **argmodes = NULL; char **argmodes = NULL;
char **argnames = NULL; char **argnames = NULL;
if (dataOnly) /* Dump only funcs in dumpable namespaces */
return; if (!finfo->dobj.namespace->dump || dataOnly)
/* Dump only funcs in dumpable namespaces, or needed language handlers */
if (!finfo->dobj.namespace->dump &&
(!finfo->islanghandler || !shouldDumpProcLangs()))
return; return;
query = createPQExpBuffer(); query = createPQExpBuffer();
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,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/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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -132,7 +132,6 @@ typedef struct _funcInfo ...@@ -132,7 +132,6 @@ typedef struct _funcInfo
Oid *argtypes; Oid *argtypes;
Oid prorettype; Oid prorettype;
char *proacl; char *proacl;
bool islanghandler;
} FuncInfo; } FuncInfo;
/* AggInfo is a superset of FuncInfo */ /* AggInfo is a superset of FuncInfo */
......
...@@ -5,12 +5,12 @@ ...@@ -5,12 +5,12 @@
* 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/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 "postgres_fe.h"
#include "common.h" #include "common.h"
#include "print.h" #include "print.h"
...@@ -28,7 +28,6 @@ main(int argc, char *argv[]) ...@@ -28,7 +28,6 @@ main(int argc, char *argv[])
{"username", required_argument, NULL, 'U'}, {"username", required_argument, NULL, 'U'},
{"password", no_argument, NULL, 'W'}, {"password", no_argument, NULL, 'W'},
{"dbname", required_argument, NULL, 'd'}, {"dbname", required_argument, NULL, 'd'},
{"pglib", required_argument, NULL, 'L'},
{"echo", no_argument, NULL, 'e'}, {"echo", no_argument, NULL, 'e'},
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
}; };
...@@ -44,16 +43,9 @@ main(int argc, char *argv[]) ...@@ -44,16 +43,9 @@ main(int argc, char *argv[])
char *username = NULL; char *username = NULL;
bool password = false; bool password = false;
bool echo = false; bool echo = false;
char *pglib = NULL;
char *langname = NULL; char *langname = NULL;
char *p; char *p;
bool handlerexists;
bool validatorexists;
bool trusted;
char *handler;
char *validator = NULL;
char *object;
PQExpBufferData sql; PQExpBufferData sql;
...@@ -65,7 +57,7 @@ main(int argc, char *argv[]) ...@@ -65,7 +57,7 @@ main(int argc, char *argv[])
handle_help_version_opts(argc, argv, "createlang", help); 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) switch (c)
{ {
...@@ -87,9 +79,6 @@ main(int argc, char *argv[]) ...@@ -87,9 +79,6 @@ main(int argc, char *argv[])
case 'd': case 'd':
dbname = optarg; dbname = optarg;
break; break;
case 'L':
pglib = optarg;
break;
case 'e': case 'e':
echo = true; echo = true;
break; break;
...@@ -165,75 +154,17 @@ main(int argc, char *argv[]) ...@@ -165,75 +154,17 @@ main(int argc, char *argv[])
exit(1); exit(1);
} }
if (!pglib)
pglib = "$libdir";
for (p = langname; *p; p++) for (p = langname; *p; p++)
if (*p >= 'A' && *p <= 'Z') if (*p >= 'A' && *p <= 'Z')
*p += ('a' - 'A'); *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); 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 * Make sure the language isn't already installed
*/ */
printfPQExpBuffer(&sql, printfPQExpBuffer(&sql,
"SELECT oid FROM pg_language WHERE lanname = '%s';", "SELECT oid FROM pg_catalog.pg_language WHERE lanname = '%s';",
langname); langname);
result = executeQuery(conn, sql.data, progname, echo); result = executeQuery(conn, sql.data, progname, echo);
if (PQntuples(result) > 0) if (PQntuples(result) > 0)
...@@ -247,61 +178,7 @@ main(int argc, char *argv[]) ...@@ -247,61 +178,7 @@ main(int argc, char *argv[])
} }
PQclear(result); PQclear(result);
/* printfPQExpBuffer(&sql, "CREATE LANGUAGE \"%s\";\n", langname);
* 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");
if (echo) if (echo)
printf("%s", sql.data); printf("%s", sql.data);
...@@ -330,7 +207,6 @@ help(const char *progname) ...@@ -330,7 +207,6 @@ help(const char *progname)
printf(_(" -d, --dbname=DBNAME database to install language in\n")); printf(_(" -d, --dbname=DBNAME database to install language in\n"));
printf(_(" -e, --echo show the commands being sent to the server\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, --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(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
printf(_(" -p, --port=PORT database server port\n")); printf(_(" -p, --port=PORT database server port\n"));
printf(_(" -U, --username=USERNAME user name to connect as\n")); printf(_(" -U, --username=USERNAME user name to connect as\n"));
......
#! /bin/sh #! /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` me=`basename $0`
: ${TMPDIR=/tmp} : ${TMPDIR=/tmp}
...@@ -84,7 +84,6 @@ fi ...@@ -84,7 +84,6 @@ fi
: ${outputdir=.} : ${outputdir=.}
libdir='@libdir@' libdir='@libdir@'
pkglibdir='@pkglibdir@'
bindir='@bindir@' bindir='@bindir@'
datadir='@datadir@' datadir='@datadir@'
host_platform='@host_tuple@' host_platform='@host_tuple@'
...@@ -322,16 +321,7 @@ LOGDIR=$outputdir/log ...@@ -322,16 +321,7 @@ LOGDIR=$outputdir/log
if [ x"$temp_install" != x"" ] if [ x"$temp_install" != x"" ]
then then
if echo x"$temp_install" | grep -v '^x/' >/dev/null 2>&1; 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" temp_install="`pwd`/$temp_install"
pkglibdir=$temp_install/install/$pkglibdir
;;
esac
fi fi
bindir=$temp_install/install/$bindir bindir=$temp_install/install/$bindir
...@@ -412,13 +402,6 @@ then ...@@ -412,13 +402,6 @@ then
(exit 2); exit (exit 2); exit
fi 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" message "initializing database system"
[ "$debug" = yes ] && initdb_options='--debug' [ "$debug" = yes ] && initdb_options='--debug'
"$bindir/initdb" -D "$PGDATA" -L "$datadir" --noclean $initdb_options >"$LOGDIR/initdb.log" 2>&1 "$bindir/initdb" -D "$PGDATA" -L "$datadir" --noclean $initdb_options >"$LOGDIR/initdb.log" 2>&1
...@@ -586,7 +569,7 @@ if [ "$enable_shared" = yes ]; then ...@@ -586,7 +569,7 @@ if [ "$enable_shared" = yes ]; then
for lang in xyzzy $load_langs ; do for lang in xyzzy $load_langs ; do
if [ "$lang" != "xyzzy" ]; then if [ "$lang" != "xyzzy" ]; then
message "installing $lang" message "installing $lang"
"$bindir/createlang" -L "$pkglibdir" $psql_options $lang $dbname "$bindir/createlang" $psql_options $lang $dbname
if [ $? -ne 0 ] && [ $? -ne 2 ]; then if [ $? -ne 0 ] && [ $? -ne 2 ]; then
echo "$me: createlang $lang failed" echo "$me: createlang $lang failed"
(exit 2); exit (exit 2); exit
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment