diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/commands/proclang.c | 83 | ||||
-rw-r--r-- | src/backend/nodes/copyfuncs.c | 3 | ||||
-rw-r--r-- | src/backend/nodes/equalfuncs.c | 3 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 24 | ||||
-rw-r--r-- | src/include/nodes/parsenodes.h | 3 |
5 files changed, 78 insertions, 38 deletions
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index e51675ee11d..34f33670c3e 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/proclang.c,v 1.89 2010/02/14 18:42:14 rhaas Exp $ + * $PostgreSQL: pgsql/src/backend/commands/proclang.c,v 1.90 2010/02/23 22:51:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -17,7 +17,6 @@ #include "access/heapam.h" #include "catalog/dependency.h" #include "catalog/indexing.h" -#include "catalog/pg_authid.h" #include "catalog/pg_language.h" #include "catalog/pg_namespace.h" #include "catalog/pg_pltemplate.h" @@ -49,7 +48,7 @@ typedef struct char *tmpllibrary; /* path of shared library */ } PLTemplate; -static void create_proc_lang(const char *languageName, +static void create_proc_lang(const char *languageName, bool replace, Oid languageOwner, Oid handlerOid, Oid inlineOid, Oid valOid, bool trusted); static PLTemplate *find_language_template(const char *languageName); @@ -73,16 +72,10 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) Oid funcargtypes[1]; /* - * Translate the language name and check that this language doesn't - * already exist + * Translate the language name to lower case */ languageName = case_translate_language_name(stmt->plname); - if (SearchSysCacheExists1(LANGNAME, PointerGetDatum(languageName))) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - 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. @@ -232,7 +225,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) valOid = InvalidOid; /* ok, create it */ - create_proc_lang(languageName, GetUserId(), handlerOid, inlineOid, + create_proc_lang(languageName, stmt->replace, GetUserId(), + handlerOid, inlineOid, valOid, pltemplate->tmpltrusted); } else @@ -306,7 +300,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) valOid = InvalidOid; /* ok, create it */ - create_proc_lang(languageName, GetUserId(), handlerOid, inlineOid, + create_proc_lang(languageName, stmt->replace, GetUserId(), + handlerOid, inlineOid, valOid, stmt->pltrusted); } } @@ -315,7 +310,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) * Guts of language creation. */ static void -create_proc_lang(const char *languageName, +create_proc_lang(const char *languageName, bool replace, Oid languageOwner, Oid handlerOid, Oid inlineOid, Oid valOid, bool trusted) { @@ -323,19 +318,21 @@ create_proc_lang(const char *languageName, TupleDesc tupDesc; Datum values[Natts_pg_language]; bool nulls[Natts_pg_language]; + bool replaces[Natts_pg_language]; NameData langname; + HeapTuple oldtup; HeapTuple tup; + bool is_update; ObjectAddress myself, referenced; - /* - * Insert the new language into pg_language - */ rel = heap_open(LanguageRelationId, RowExclusiveLock); - tupDesc = rel->rd_att; + tupDesc = RelationGetDescr(rel); + /* Prepare data to be inserted */ memset(values, 0, sizeof(values)); memset(nulls, false, sizeof(nulls)); + memset(replaces, true, sizeof(replaces)); namestrcpy(&langname, languageName); values[Anum_pg_language_lanname - 1] = NameGetDatum(&langname); @@ -347,24 +344,62 @@ create_proc_lang(const char *languageName, values[Anum_pg_language_lanvalidator - 1] = ObjectIdGetDatum(valOid); nulls[Anum_pg_language_lanacl - 1] = true; - tup = heap_form_tuple(tupDesc, values, nulls); + /* Check for pre-existing definition */ + oldtup = SearchSysCache1(LANGNAME, PointerGetDatum(languageName)); - simple_heap_insert(rel, tup); + if (HeapTupleIsValid(oldtup)) + { + /* There is one; okay to replace it? */ + if (!replace) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("language \"%s\" already exists", languageName))); + if (!pg_language_ownercheck(HeapTupleGetOid(oldtup), languageOwner)) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE, + languageName); + /* + * Do not change existing ownership or permissions. Note + * dependency-update code below has to agree with this decision. + */ + replaces[Anum_pg_language_lanowner - 1] = false; + replaces[Anum_pg_language_lanacl - 1] = false; + + /* Okay, do it... */ + tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces); + simple_heap_update(rel, &tup->t_self, tup); + + ReleaseSysCache(oldtup); + is_update = true; + } + else + { + /* Creating a new language */ + tup = heap_form_tuple(tupDesc, values, nulls); + simple_heap_insert(rel, tup); + is_update = false; + } + + /* Need to update indexes for either the insert or update case */ CatalogUpdateIndexes(rel, tup); /* - * Create dependencies for language + * Create dependencies for the new language. If we are updating an + * existing language, first delete any existing pg_depend entries. + * (However, since we are not changing ownership or permissions, the + * shared dependencies do *not* need to change, and we leave them alone.) */ myself.classId = LanguageRelationId; myself.objectId = HeapTupleGetOid(tup); myself.objectSubId = 0; + if (is_update) + deleteDependencyRecordsFor(myself.classId, myself.objectId); + /* dependency on owner of language */ - referenced.classId = AuthIdRelationId; - referenced.objectId = languageOwner; - referenced.objectSubId = 0; - recordSharedDependencyOn(&myself, &referenced, SHARED_DEPENDENCY_OWNER); + if (!is_update) + recordDependencyOnOwner(myself.classId, myself.objectId, + languageOwner); /* dependency on the PL handler function */ referenced.classId = ProcedureRelationId; diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 371d1f245eb..22d24ef21a5 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.462 2010/02/16 22:34:43 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.463 2010/02/23 22:51:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -3237,6 +3237,7 @@ _copyCreatePLangStmt(CreatePLangStmt *from) { CreatePLangStmt *newnode = makeNode(CreatePLangStmt); + COPY_SCALAR_FIELD(replace); COPY_STRING_FIELD(plname); COPY_NODE_FIELD(plhandler); COPY_NODE_FIELD(plinline); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 7dfc1969f5d..9a05bcc1c0f 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -22,7 +22,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.383 2010/02/16 22:34:43 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.384 2010/02/23 22:51:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1710,6 +1710,7 @@ _equalDropPropertyStmt(DropPropertyStmt *a, DropPropertyStmt *b) static bool _equalCreatePLangStmt(CreatePLangStmt *a, CreatePLangStmt *b) { + COMPARE_SCALAR_FIELD(replace); COMPARE_STRING_FIELD(plname); COMPARE_NODE_FIELD(plhandler); COMPARE_NODE_FIELD(plinline); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 94b28bf3d89..368586a95e6 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.710 2010/02/17 04:19:39 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.711 2010/02/23 22:51:42 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -2882,16 +2882,17 @@ NumericOnly: /***************************************************************************** * * QUERIES : - * CREATE PROCEDURAL LANGUAGE ... - * DROP PROCEDURAL LANGUAGE ... + * CREATE [OR REPLACE] [TRUSTED] [PROCEDURAL] LANGUAGE ... + * DROP [PROCEDURAL] LANGUAGE ... * *****************************************************************************/ CreatePLangStmt: - CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst + CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE ColId_or_Sconst { CreatePLangStmt *n = makeNode(CreatePLangStmt); - n->plname = $5; + n->replace = $2; + n->plname = $6; /* parameters are all to be supplied by system */ n->plhandler = NIL; n->plinline = NIL; @@ -2899,15 +2900,16 @@ CreatePLangStmt: n->pltrusted = false; $$ = (Node *)n; } - | CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst + | CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE ColId_or_Sconst HANDLER handler_name opt_inline_handler opt_validator { CreatePLangStmt *n = makeNode(CreatePLangStmt); - n->plname = $5; - n->plhandler = $7; - n->plinline = $8; - n->plvalidator = $9; - n->pltrusted = $2; + n->replace = $2; + n->plname = $6; + n->plhandler = $8; + n->plinline = $9; + n->plvalidator = $10; + n->pltrusted = $3; $$ = (Node *)n; } ; diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index ca229c8e23d..5a5c040c251 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -13,7 +13,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.430 2010/02/16 22:34:57 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.431 2010/02/23 22:51:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1623,6 +1623,7 @@ typedef struct CreateTrigStmt typedef struct CreatePLangStmt { NodeTag type; + bool replace; /* T => replace if already exists */ char *plname; /* PL name */ List *plhandler; /* PL call handler function (qual. name) */ List *plinline; /* optional inline function (qual. name) */ |