Commit 6d16ecc6 authored by Peter Eisentraut's avatar Peter Eisentraut

Add CREATE COLLATION IF NOT EXISTS clause

The core of the functionality was already implemented when
pg_import_system_collations was added.  This just exposes it as an
option in the SQL command.
parent e403732e
...@@ -18,12 +18,12 @@ ...@@ -18,12 +18,12 @@
<refsynopsisdiv> <refsynopsisdiv>
<synopsis> <synopsis>
CREATE COLLATION <replaceable>name</replaceable> ( CREATE COLLATION [ IF NOT EXISTS ] <replaceable>name</replaceable> (
[ LOCALE = <replaceable>locale</replaceable>, ] [ LOCALE = <replaceable>locale</replaceable>, ]
[ LC_COLLATE = <replaceable>lc_collate</replaceable>, ] [ LC_COLLATE = <replaceable>lc_collate</replaceable>, ]
[ LC_CTYPE = <replaceable>lc_ctype</replaceable> ] [ LC_CTYPE = <replaceable>lc_ctype</replaceable> ]
) )
CREATE COLLATION <replaceable>name</replaceable> FROM <replaceable>existing_collation</replaceable> CREATE COLLATION [ IF NOT EXISTS ] <replaceable>name</replaceable> FROM <replaceable>existing_collation</replaceable>
</synopsis> </synopsis>
</refsynopsisdiv> </refsynopsisdiv>
...@@ -47,6 +47,17 @@ CREATE COLLATION <replaceable>name</replaceable> FROM <replaceable>existing_coll ...@@ -47,6 +47,17 @@ CREATE COLLATION <replaceable>name</replaceable> FROM <replaceable>existing_coll
<title>Parameters</title> <title>Parameters</title>
<variablelist> <variablelist>
<varlistentry>
<term><literal>IF NOT EXISTS</literal></term>
<listitem>
<para>
Do not throw an error if a collation with the same name already exists.
A notice is issued in this case. Note that there is no guarantee that
the existing collation is anything like the one that would have been created.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><replaceable>name</replaceable></term> <term><replaceable>name</replaceable></term>
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* CREATE COLLATION * CREATE COLLATION
*/ */
ObjectAddress ObjectAddress
DefineCollation(ParseState *pstate, List *names, List *parameters) DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_exists)
{ {
char *collName; char *collName;
Oid collNamespace; Oid collNamespace;
...@@ -137,7 +137,7 @@ DefineCollation(ParseState *pstate, List *names, List *parameters) ...@@ -137,7 +137,7 @@ DefineCollation(ParseState *pstate, List *names, List *parameters)
GetDatabaseEncoding(), GetDatabaseEncoding(),
collcollate, collcollate,
collctype, collctype,
false); if_not_exists);
if (!OidIsValid(newoid)) if (!OidIsValid(newoid))
return InvalidObjectAddress; return InvalidObjectAddress;
......
...@@ -3105,6 +3105,7 @@ _copyDefineStmt(const DefineStmt *from) ...@@ -3105,6 +3105,7 @@ _copyDefineStmt(const DefineStmt *from)
COPY_NODE_FIELD(defnames); COPY_NODE_FIELD(defnames);
COPY_NODE_FIELD(args); COPY_NODE_FIELD(args);
COPY_NODE_FIELD(definition); COPY_NODE_FIELD(definition);
COPY_SCALAR_FIELD(if_not_exists);
return newnode; return newnode;
} }
......
...@@ -1211,6 +1211,7 @@ _equalDefineStmt(const DefineStmt *a, const DefineStmt *b) ...@@ -1211,6 +1211,7 @@ _equalDefineStmt(const DefineStmt *a, const DefineStmt *b)
COMPARE_NODE_FIELD(defnames); COMPARE_NODE_FIELD(defnames);
COMPARE_NODE_FIELD(args); COMPARE_NODE_FIELD(args);
COMPARE_NODE_FIELD(definition); COMPARE_NODE_FIELD(definition);
COMPARE_SCALAR_FIELD(if_not_exists);
return true; return true;
} }
......
...@@ -5610,6 +5610,16 @@ DefineStmt: ...@@ -5610,6 +5610,16 @@ DefineStmt:
n->definition = $4; n->definition = $4;
$$ = (Node *)n; $$ = (Node *)n;
} }
| CREATE COLLATION IF_P NOT EXISTS any_name definition
{
DefineStmt *n = makeNode(DefineStmt);
n->kind = OBJECT_COLLATION;
n->args = NIL;
n->defnames = $6;
n->definition = $7;
n->if_not_exists = true;
$$ = (Node *)n;
}
| CREATE COLLATION any_name FROM any_name | CREATE COLLATION any_name FROM any_name
{ {
DefineStmt *n = makeNode(DefineStmt); DefineStmt *n = makeNode(DefineStmt);
...@@ -5619,6 +5629,16 @@ DefineStmt: ...@@ -5619,6 +5629,16 @@ DefineStmt:
n->definition = list_make1(makeDefElem("from", (Node *) $5, @5)); n->definition = list_make1(makeDefElem("from", (Node *) $5, @5));
$$ = (Node *)n; $$ = (Node *)n;
} }
| CREATE COLLATION IF_P NOT EXISTS any_name FROM any_name
{
DefineStmt *n = makeNode(DefineStmt);
n->kind = OBJECT_COLLATION;
n->args = NIL;
n->defnames = $6;
n->definition = list_make1(makeDefElem("from", (Node *) $8, @8));
n->if_not_exists = true;
$$ = (Node *)n;
}
; ;
definition: '(' def_list ')' { $$ = $2; } definition: '(' def_list ')' { $$ = $2; }
......
...@@ -1271,7 +1271,8 @@ ProcessUtilitySlow(ParseState *pstate, ...@@ -1271,7 +1271,8 @@ ProcessUtilitySlow(ParseState *pstate,
Assert(stmt->args == NIL); Assert(stmt->args == NIL);
address = DefineCollation(pstate, address = DefineCollation(pstate,
stmt->defnames, stmt->defnames,
stmt->definition); stmt->definition,
stmt->if_not_exists);
break; break;
default: default:
elog(ERROR, "unrecognized define stmt type: %d", elog(ERROR, "unrecognized define stmt type: %d",
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include "catalog/objectaddress.h" #include "catalog/objectaddress.h"
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
extern ObjectAddress DefineCollation(ParseState *pstate, List *names, List *parameters); extern ObjectAddress DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_exists);
extern void IsThereCollationInNamespace(const char *collname, Oid nspOid); extern void IsThereCollationInNamespace(const char *collname, Oid nspOid);
#endif /* COLLATIONCMDS_H */ #endif /* COLLATIONCMDS_H */
...@@ -2380,6 +2380,7 @@ typedef struct DefineStmt ...@@ -2380,6 +2380,7 @@ typedef struct DefineStmt
List *defnames; /* qualified name (list of Value strings) */ List *defnames; /* qualified name (list of Value strings) */
List *args; /* a list of TypeName (if needed) */ List *args; /* a list of TypeName (if needed) */
List *definition; /* a list of DefElem */ List *definition; /* a list of DefElem */
bool if_not_exists; /* just do nothing if it already exists? */
} DefineStmt; } DefineStmt;
/* ---------------------- /* ----------------------
......
...@@ -963,6 +963,10 @@ END ...@@ -963,6 +963,10 @@ END
$$; $$;
CREATE COLLATION test0 FROM "C"; -- fail, duplicate name CREATE COLLATION test0 FROM "C"; -- fail, duplicate name
ERROR: collation "test0" for encoding "UTF8" already exists ERROR: collation "test0" for encoding "UTF8" already exists
CREATE COLLATION IF NOT EXISTS test0 FROM "C"; -- ok, skipped
NOTICE: collation "test0" for encoding "UTF8" already exists, skipping
CREATE COLLATION IF NOT EXISTS test0 (locale = 'foo'); -- ok, skipped
NOTICE: collation "test0" for encoding "UTF8" already exists, skipping
do $$ do $$
BEGIN BEGIN
EXECUTE 'CREATE COLLATION test1 (lc_collate = ' || EXECUTE 'CREATE COLLATION test1 (lc_collate = ' ||
......
...@@ -325,6 +325,8 @@ BEGIN ...@@ -325,6 +325,8 @@ BEGIN
END END
$$; $$;
CREATE COLLATION test0 FROM "C"; -- fail, duplicate name CREATE COLLATION test0 FROM "C"; -- fail, duplicate name
CREATE COLLATION IF NOT EXISTS test0 FROM "C"; -- ok, skipped
CREATE COLLATION IF NOT EXISTS test0 (locale = 'foo'); -- ok, skipped
do $$ do $$
BEGIN BEGIN
EXECUTE 'CREATE COLLATION test1 (lc_collate = ' || EXECUTE 'CREATE COLLATION test1 (lc_collate = ' ||
......
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