Attached is a preliminary patch for the "PL template" facility I
proposed a couple days ago.  This is a stripped-down implementation
that just hardwires a lookup table in proclang.c, instead of putting
the data into a system catalog as should happen in 8.2.  It's not
ready to apply yet because I haven't touched pg_dump or the
documentation, but I thought I'd put it up for comment.

Note that the patch disables createlang's -L option.  I can't see that
that option has any use anymore; it used to be needed by pg_regress
for testing temporary installations, but since we put in the
auto-package-relocation support, $libdir works fine.  Anyone still
see a need for it?

One small annoyance is that since createlang no longer knows what
languages are supported, it gives a fairly unhelpful error message
if you misspell:

$ createlang plprl
createlang: language installation failed: ERROR:  no handler specified for 
procedural language

This could of course be fixed properly if the pltemplate system catalog
existed, but in the meantime it seems we need a kluge.  I hate to
duplicate the list of known PLs in both the backend and createlang
... anyone have a better idea?

                        regards, tom lane

*** src/backend/commands/proclang.c.orig        Thu Apr 14 16:03:24 2005
--- src/backend/commands/proclang.c     Fri Sep  2 19:51:06 2005
***************
*** 13,37 ****
   */
  #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_proc.h"
  #include "catalog/pg_type.h"
  #include "commands/proclang.h"
  #include "commands/defrem.h"
  #include "fmgr.h"
  #include "miscadmin.h"
  #include "parser/parse_func.h"
  #include "utils/builtins.h"
  #include "utils/lsyscache.h"
  #include "utils/syscache.h"
  
  
  /* ---------------------------------------------------------------------
   * CREATE PROCEDURAL LANGUAGE
   * ---------------------------------------------------------------------
--- 13,52 ----
   */
  #include "postgres.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
   * ---------------------------------------------------------------------
***************
*** 40,58 ****
  CreateProceduralLanguage(CreatePLangStmt *stmt)
  {
        char       *languageName;
!       Oid                     procOid,
!                               valProcOid;
        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
--- 55,65 ----
  CreateProceduralLanguage(CreatePLangStmt *stmt)
  {
        char       *languageName;
!       PLTemplate *pltemplate;
!       Oid                     handlerOid,
!                               valOid;
        Oid                     funcrettype;
        Oid                     funcargtypes[1];
  
        /*
         * Check permission
***************
*** 76,139 ****
                                 errmsg("language \"%s\" already exists", 
languageName)));
  
        /*
!        * Lookup the PL handler function and check that it is of the expected
!        * return type
         */
!       procOid = LookupFuncName(stmt->plhandler, 0, funcargtypes, false);
!       funcrettype = get_func_rettype(procOid);
!       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.
                 */
!               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(procOid, 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;
!               valProcOid = LookupFuncName(stmt->plvalidator, 1, funcargtypes, 
false);
!               /* return value is ignored, so we don't check the type */
        }
        else
!               valProcOid = InvalidOid;
  
        /*
         * Insert the new language into pg_language
         */
!       for (i = 0; i < Natts_pg_language; i++)
!       {
!               nulls[i] = ' ';
!               values[i] = (Datum) NULL;
!       }
  
!       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 */
  
!       rel = heap_open(LanguageRelationId, RowExclusiveLock);
  
-       tupDesc = rel->rd_att;
        tup = heap_formtuple(tupDesc, values, nulls);
  
        simple_heap_insert(rel, tup);
--- 83,256 ----
                                 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.  There MUST be
!                * a handler clause.
!                */
!               if (!stmt->plhandler)
!                       ereport(ERROR,
!                                       
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
!                                        errmsg("no handler specified for 
procedural language")));
! 
!               /*
!                * 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
         */
!       rel = heap_open(LanguageRelationId, RowExclusiveLock);
!       tupDesc = rel->rd_att;
  
!       memset(values, 0, sizeof(values));
!       memset(nulls, ' ', sizeof(nulls));
  
!       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';
  
        tup = heap_formtuple(tupDesc, values, nulls);
  
        simple_heap_insert(rel, tup);
***************
*** 149,163 ****
  
        /* dependency on the PL handler function */
        referenced.classId = ProcedureRelationId;
!       referenced.objectId = procOid;
        referenced.objectSubId = 0;
        recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
  
        /* dependency on the validator function, if any */
!       if (OidIsValid(valProcOid))
        {
                referenced.classId = ProcedureRelationId;
!               referenced.objectId = valProcOid;
                referenced.objectSubId = 0;
                recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
        }
--- 266,280 ----
  
        /* dependency on the PL handler function */
        referenced.classId = ProcedureRelationId;
!       referenced.objectId = handlerOid;
        referenced.objectSubId = 0;
        recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
  
        /* dependency on the validator function, if any */
!       if (OidIsValid(valOid))
        {
                referenced.classId = ProcedureRelationId;
!               referenced.objectId = valOid;
                referenced.objectSubId = 0;
                recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
        }
***************
*** 165,170 ****
--- 282,322 ----
        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.
+  */
+ 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
***************
*** 186,193 ****
                           errmsg("must be superuser to drop procedural 
language")));
  
        /*
!        * Translate the language name, check that this language exist and is
!        * a PL
         */
        languageName = case_translate_language_name(stmt->plname);
  
--- 338,344 ----
                           errmsg("must be superuser to drop procedural 
language")));
  
        /*
!        * Translate the language name, check that the language exists
         */
        languageName = case_translate_language_name(stmt->plname);
  
***************
*** 244,249 ****
--- 395,404 ----
        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,
***************
*** 262,268 ****
                                (errcode(ERRCODE_DUPLICATE_OBJECT),
                                 errmsg("language \"%s\" already exists", 
newname)));
  
!       /* must be superuser */
        if (!superuser())
                ereport(ERROR,
                                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
--- 417,423 ----
                                (errcode(ERRCODE_DUPLICATE_OBJECT),
                                 errmsg("language \"%s\" already exists", 
newname)));
  
!       /* must be superuser, since we do not have owners for PLs */
        if (!superuser())
                ereport(ERROR,
                                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
*** src/backend/parser/gram.y.orig      Wed Aug 24 15:34:33 2005
--- src/backend/parser/gram.y   Fri Sep  2 18:48:27 2005
***************
*** 194,200 ****
                                index_name name function_name file_name
  
  %type <list>  func_name handler_name qual_Op qual_all_Op subquery_Op
!                               opt_class opt_validator
  
  %type <range> qualified_name OptConstrFromTable
  
--- 194,200 ----
                                index_name name function_name file_name
  
  %type <list>  func_name handler_name qual_Op qual_all_Op subquery_Op
!                               opt_class opt_handler opt_validator
  
  %type <range> qualified_name OptConstrFromTable
  
***************
*** 2303,2315 ****
  
  CreatePLangStmt:
                        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;
                                $$ = (Node *)n;
                        }
                ;
--- 2303,2316 ----
  
  CreatePLangStmt:
                        CREATE opt_trusted opt_procedural LANGUAGE 
ColId_or_Sconst
!                       opt_handler opt_validator opt_lancompiler
                        {
                                CreatePLangStmt *n = makeNode(CreatePLangStmt);
                                n->plname = $5;
!                               n->plhandler = $6;
!                               n->plvalidator = $7;
                                n->pltrusted = $2;
+                               /* LANCOMPILER is now ignored entirely */
                                $$ = (Node *)n;
                        }
                ;
***************
*** 2319,2324 ****
--- 2320,2335 ----
                        | /*EMPTY*/                                             
                { $$ = FALSE; }
                ;
  
+ opt_handler:
+                       HANDLER handler_name                                    
{ $$ = $2; }
+                       | /*EMPTY*/                                             
                { $$ = NIL; }
+               ;
+ 
+ opt_validator:
+                       VALIDATOR handler_name                                  
{ $$ = $2; }
+                       | /*EMPTY*/                                             
                { $$ = NIL; }
+               ;
+ 
  /* This ought to be just func_name, but that causes reduce/reduce conflicts
   * (CREATE LANGUAGE is the only place where func_name isn't followed by '(').
   * Work around by using simple names, instead.
***************
*** 2330,2341 ****
  
  opt_lancompiler:
                        LANCOMPILER Sconst                                      
        { $$ = $2; }
!                       | /*EMPTY*/                                             
                { $$ = ""; }
!               ;
! 
! opt_validator:
!                       VALIDATOR handler_name { $$ = $2; }
!                       | /*EMPTY*/ { $$ = NULL; }
                ;
  
  DropPLangStmt:
--- 2341,2347 ----
  
  opt_lancompiler:
                        LANCOMPILER Sconst                                      
        { $$ = $2; }
!                       | /*EMPTY*/                                             
                { $$ = NULL; }
                ;
  
  DropPLangStmt:
*** src/bin/scripts/createlang.c.orig   Mon Aug 15 17:02:26 2005
--- src/bin/scripts/createlang.c        Fri Sep  2 20:14:32 2005
***************
*** 9,16 ****
   *
   *-------------------------------------------------------------------------
   */
- 
  #include "postgres_fe.h"
  #include "common.h"
  #include "print.h"
  
--- 9,16 ----
   *
   *-------------------------------------------------------------------------
   */
  #include "postgres_fe.h"
+ 
  #include "common.h"
  #include "print.h"
  
***************
*** 48,59 ****
        char       *langname = NULL;
  
        char       *p;
-       bool            handlerexists;
-       bool            validatorexists;
-       bool            trusted;
-       char       *handler;
-       char       *validator = NULL;
-       char       *object;
  
        PQExpBufferData sql;
  
--- 48,53 ----
***************
*** 88,94 ****
                                dbname = optarg;
                                break;
                        case 'L':
!                               pglib = optarg;
                                break;
                        case 'e':
                                echo = true;
--- 82,88 ----
                                dbname = optarg;
                                break;
                        case 'L':
!                               pglib = optarg;                         /* 
obsolete, ignored */
                                break;
                        case 'e':
                                echo = true;
***************
*** 165,239 ****
                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';", 
                                          langname);
        result = executeQuery(conn, sql.data, progname, echo);
        if (PQntuples(result) > 0)
--- 159,175 ----
                exit(1);
        }
  
        for (p = langname; *p; p++)
                if (*p >= 'A' && *p <= 'Z')
                        *p += ('a' - 'A');
  
        conn = connectDatabase(dbname, host, port, username, password, 
progname);
  
        /*
         * Make sure the language isn't already installed
         */
        printfPQExpBuffer(&sql, 
!                                         "SELECT oid FROM 
pg_catalog.pg_language WHERE lanname = '%s';", 
                                          langname);
        result = executeQuery(conn, sql.data, progname, echo);
        if (PQntuples(result) > 0)
***************
*** 247,307 ****
        }
        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");
  
        if (echo)
                printf("%s", sql.data);
--- 183,189 ----
        }
        PQclear(result);
  
!       printfPQExpBuffer(&sql, "CREATE LANGUAGE \"%s\";\n", langname);
  
        if (echo)
                printf("%s", sql.data);
***************
*** 330,336 ****
        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"));
--- 212,217 ----
---------------------------(end of broadcast)---------------------------
TIP 1: if posting/reading through Usenet, please send an appropriate
       subscribe-nomail command to [EMAIL PROTECTED] so that your
       message can get through to the mailing list cleanly

Reply via email to