Hello all, yesterday i ran into a small problem: http://andreas.scherbaum.la/blog/archives/346-create-language-if-not-exist.html and was bugged to create a patch for PostgreSQL. So here is a first version, still missing some things like documentation.
The attached patch for HEAD extends the CREATE LANGUAGE statement by an IF NOT EXISTS option which in effect changes the raised error into a notice. Before i continue working on this patch i would like to know if this extension has a chance to go into PG and what other changes i should apply (beside the missing documentation). Thank you -- Andreas 'ads' Scherbaum German PostgreSQL User Group
Index: src/backend/commands/proclang.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/proclang.c,v retrieving revision 1.77 diff -u -3 -p -r1.77 proclang.c --- src/backend/commands/proclang.c 27 Mar 2008 03:57:33 -0000 1.77 +++ src/backend/commands/proclang.c 29 Mar 2008 01:18:59 -0000 @@ -75,9 +75,20 @@ CreateProceduralLanguage(CreatePLangStmt if (SearchSysCacheExists(LANGNAME, PointerGetDatum(languageName), 0, 0, 0)) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("language \"%s\" already exists", languageName))); + { + if (!stmt->existing_ok) + { + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("language \"%s\" already exists", languageName))); + } + else + { + ereport(NOTICE, + (errmsg("language \"%s\" already exists, skipping", languageName))); + return; + } + } /* * If we have template information for the language, ignore the supplied Index: src/backend/parser/gram.y =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/parser/gram.y,v retrieving revision 2.611 diff -u -3 -p -r2.611 gram.y --- src/backend/parser/gram.y 28 Mar 2008 00:21:55 -0000 2.611 +++ src/backend/parser/gram.y 29 Mar 2008 01:19:03 -0000 @@ -195,7 +195,7 @@ static Node *makeXmlExpr(XmlExprOp op, c %type <ival> opt_lock lock_type cast_context %type <boolean> opt_force opt_or_replace opt_grant_grant_option opt_grant_admin_option - opt_nowait opt_if_exists + opt_nowait opt_if_exists opt_if_not_exists %type <list> OptRoleList %type <defelt> OptRoleElem @@ -2529,6 +2529,7 @@ CreatePLangStmt: n->plhandler = NIL; n->plvalidator = NIL; n->pltrusted = false; + n->existing_ok = false; $$ = (Node *)n; } | CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst @@ -2540,6 +2541,30 @@ CreatePLangStmt: n->plvalidator = $8; n->pltrusted = $2; /* LANCOMPILER is now ignored entirely */ + n->existing_ok = false; + $$ = (Node *)n; + } + | CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst IF_P NOT EXISTS + { + CreatePLangStmt *n = makeNode(CreatePLangStmt); + n->plname = $5; + /* parameters are all to be supplied by system */ + n->plhandler = NIL; + n->plvalidator = NIL; + n->pltrusted = false; + n->existing_ok = true; + $$ = (Node *)n; + } + | CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst + HANDLER handler_name opt_validator opt_lancompiler + { + CreatePLangStmt *n = makeNode(CreatePLangStmt); + n->plname = $5; + n->plhandler = $7; + n->plvalidator = $8; + n->pltrusted = $2; + /* LANCOMPILER is now ignored entirely */ + n->existing_ok = true; $$ = (Node *)n; } ; @@ -4493,6 +4518,10 @@ opt_if_exists: IF_P EXISTS { $$ = T | /*EMPTY*/ { $$ = FALSE; } ; +opt_if_not_exists: IF_P NOT EXISTS { $$ = TRUE; } + | /*EMPTY*/ { $$ = FALSE; } + ; + /***************************************************************************** * Index: src/include/nodes/parsenodes.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/nodes/parsenodes.h,v retrieving revision 1.361 diff -u -3 -p -r1.361 parsenodes.h --- src/include/nodes/parsenodes.h 21 Mar 2008 22:41:48 -0000 1.361 +++ src/include/nodes/parsenodes.h 29 Mar 2008 01:19:05 -0000 @@ -1262,6 +1262,7 @@ typedef struct CreatePLangStmt List *plhandler; /* PL call handler function (qual. name) */ List *plvalidator; /* optional validator function (qual. name) */ bool pltrusted; /* PL is trusted */ + bool existing_ok; /* skip error if already there? */ } CreatePLangStmt; typedef struct DropPLangStmt Index: src/interfaces/ecpg/preproc/preproc.y =================================================================== RCS file: /projects/cvsroot/pgsql/src/interfaces/ecpg/preproc/preproc.y,v retrieving revision 1.363 diff -u -3 -p -r1.363 preproc.y --- src/interfaces/ecpg/preproc/preproc.y 27 Mar 2008 07:56:00 -0000 1.363 +++ src/interfaces/ecpg/preproc/preproc.y 29 Mar 2008 01:19:09 -0000 @@ -593,7 +593,7 @@ add_typedef(char *name, char * dimension %type <str> CreatePLangStmt TriggerFuncArgs TriggerFuncArg simple_select %type <str> ViewStmt LoadStmt CreatedbStmt createdb_opt_item ExplainableStmt %type <str> createdb_opt_list opt_encoding OptInherit opt_equal -%type <str> privilege_list privilege privilege_target opt_if_exists +%type <str> privilege_list privilege privilege_target opt_if_exists opt_if_not_exists %type <str> opt_grant_grant_option cursor_options DropOwnedStmt %type <str> transaction_mode_list_or_empty transaction_mode_list %type <str> function_with_argtypes_list function_with_argtypes IntConstVar @@ -1878,6 +1878,11 @@ CreatePLangStmt: CREATE opt_trusted opt | CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst HANDLER handler_name opt_validator opt_lancompiler { $$ = cat_str(9, make_str("create"), $2, $3, make_str("language"), $5, make_str("handler"), $7, $8, $9); } + | CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst IF_P NOT EXISTS + { $$ = cat_str(6, make_str("create"), $2, $3, make_str("language"), $5, make_str("if not exists")); } + | CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst + HANDLER handler_name opt_validator opt_lancompiler IF_P NOT EXISTS + { $$ = cat_str(10, make_str("create"), $2, $3, make_str("language"), $5, make_str("handler"), $7, $8, $9, make_str("if not exists")); } ; opt_trusted: TRUSTED { $$ = make_str("trusted"); } @@ -2774,6 +2779,10 @@ opt_if_exists: IF_P EXISTS { $$ = make_s | /* EMPTY */ { $$ = EMPTY; } ; +opt_if_not_exists: IF_P NOT EXISTS { $$ = make_str("if not exists"); } + | /* EMPTY */ { $$ = EMPTY; } + ; + /***************************************************************************** * * QUERY:
-- Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-patches