Skip to content

Commit 6d16ecc

Browse files
committed
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.
1 parent e403732 commit 6d16ecc

File tree

10 files changed

+47
-6
lines changed

10 files changed

+47
-6
lines changed

doc/src/sgml/ref/create_collation.sgml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@
1818

1919
<refsynopsisdiv>
2020
<synopsis>
21-
CREATE COLLATION <replaceable>name</replaceable> (
21+
CREATE COLLATION [ IF NOT EXISTS ] <replaceable>name</replaceable> (
2222
[ LOCALE = <replaceable>locale</replaceable>, ]
2323
[ LC_COLLATE = <replaceable>lc_collate</replaceable>, ]
2424
[ LC_CTYPE = <replaceable>lc_ctype</replaceable> ]
2525
)
26-
CREATE COLLATION <replaceable>name</replaceable> FROM <replaceable>existing_collation</replaceable>
26+
CREATE COLLATION [ IF NOT EXISTS ] <replaceable>name</replaceable> FROM <replaceable>existing_collation</replaceable>
2727
</synopsis>
2828
</refsynopsisdiv>
2929

@@ -47,6 +47,17 @@ CREATE COLLATION <replaceable>name</replaceable> FROM <replaceable>existing_coll
4747
<title>Parameters</title>
4848

4949
<variablelist>
50+
<varlistentry>
51+
<term><literal>IF NOT EXISTS</literal></term>
52+
<listitem>
53+
<para>
54+
Do not throw an error if a collation with the same name already exists.
55+
A notice is issued in this case. Note that there is no guarantee that
56+
the existing collation is anything like the one that would have been created.
57+
</para>
58+
</listitem>
59+
</varlistentry>
60+
5061
<varlistentry>
5162
<term><replaceable>name</replaceable></term>
5263

src/backend/commands/collationcmds.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
* CREATE COLLATION
3838
*/
3939
ObjectAddress
40-
DefineCollation(ParseState *pstate, List *names, List *parameters)
40+
DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_exists)
4141
{
4242
char *collName;
4343
Oid collNamespace;
@@ -137,7 +137,7 @@ DefineCollation(ParseState *pstate, List *names, List *parameters)
137137
GetDatabaseEncoding(),
138138
collcollate,
139139
collctype,
140-
false);
140+
if_not_exists);
141141

142142
if (!OidIsValid(newoid))
143143
return InvalidObjectAddress;

src/backend/nodes/copyfuncs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3105,6 +3105,7 @@ _copyDefineStmt(const DefineStmt *from)
31053105
COPY_NODE_FIELD(defnames);
31063106
COPY_NODE_FIELD(args);
31073107
COPY_NODE_FIELD(definition);
3108+
COPY_SCALAR_FIELD(if_not_exists);
31083109

31093110
return newnode;
31103111
}

src/backend/nodes/equalfuncs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,6 +1211,7 @@ _equalDefineStmt(const DefineStmt *a, const DefineStmt *b)
12111211
COMPARE_NODE_FIELD(defnames);
12121212
COMPARE_NODE_FIELD(args);
12131213
COMPARE_NODE_FIELD(definition);
1214+
COMPARE_SCALAR_FIELD(if_not_exists);
12141215

12151216
return true;
12161217
}

src/backend/parser/gram.y

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5610,6 +5610,16 @@ DefineStmt:
56105610
n->definition = $4;
56115611
$$ = (Node *)n;
56125612
}
5613+
| CREATE COLLATION IF_P NOT EXISTS any_name definition
5614+
{
5615+
DefineStmt *n = makeNode(DefineStmt);
5616+
n->kind = OBJECT_COLLATION;
5617+
n->args = NIL;
5618+
n->defnames = $6;
5619+
n->definition = $7;
5620+
n->if_not_exists = true;
5621+
$$ = (Node *)n;
5622+
}
56135623
| CREATE COLLATION any_name FROM any_name
56145624
{
56155625
DefineStmt *n = makeNode(DefineStmt);
@@ -5619,6 +5629,16 @@ DefineStmt:
56195629
n->definition = list_make1(makeDefElem("from", (Node *) $5, @5));
56205630
$$ = (Node *)n;
56215631
}
5632+
| CREATE COLLATION IF_P NOT EXISTS any_name FROM any_name
5633+
{
5634+
DefineStmt *n = makeNode(DefineStmt);
5635+
n->kind = OBJECT_COLLATION;
5636+
n->args = NIL;
5637+
n->defnames = $6;
5638+
n->definition = list_make1(makeDefElem("from", (Node *) $8, @8));
5639+
n->if_not_exists = true;
5640+
$$ = (Node *)n;
5641+
}
56225642
;
56235643

56245644
definition: '(' def_list ')' { $$ = $2; }

src/backend/tcop/utility.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1271,7 +1271,8 @@ ProcessUtilitySlow(ParseState *pstate,
12711271
Assert(stmt->args == NIL);
12721272
address = DefineCollation(pstate,
12731273
stmt->defnames,
1274-
stmt->definition);
1274+
stmt->definition,
1275+
stmt->if_not_exists);
12751276
break;
12761277
default:
12771278
elog(ERROR, "unrecognized define stmt type: %d",

src/include/commands/collationcmds.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#include "catalog/objectaddress.h"
1919
#include "nodes/parsenodes.h"
2020

21-
extern ObjectAddress DefineCollation(ParseState *pstate, List *names, List *parameters);
21+
extern ObjectAddress DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_exists);
2222
extern void IsThereCollationInNamespace(const char *collname, Oid nspOid);
2323

2424
#endif /* COLLATIONCMDS_H */

src/include/nodes/parsenodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2380,6 +2380,7 @@ typedef struct DefineStmt
23802380
List *defnames; /* qualified name (list of Value strings) */
23812381
List *args; /* a list of TypeName (if needed) */
23822382
List *definition; /* a list of DefElem */
2383+
bool if_not_exists; /* just do nothing if it already exists? */
23832384
} DefineStmt;
23842385

23852386
/* ----------------------

src/test/regress/expected/collate.linux.utf8.out

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,10 @@ END
963963
$$;
964964
CREATE COLLATION test0 FROM "C"; -- fail, duplicate name
965965
ERROR: collation "test0" for encoding "UTF8" already exists
966+
CREATE COLLATION IF NOT EXISTS test0 FROM "C"; -- ok, skipped
967+
NOTICE: collation "test0" for encoding "UTF8" already exists, skipping
968+
CREATE COLLATION IF NOT EXISTS test0 (locale = 'foo'); -- ok, skipped
969+
NOTICE: collation "test0" for encoding "UTF8" already exists, skipping
966970
do $$
967971
BEGIN
968972
EXECUTE 'CREATE COLLATION test1 (lc_collate = ' ||

src/test/regress/sql/collate.linux.utf8.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,8 @@ BEGIN
325325
END
326326
$$;
327327
CREATE COLLATION test0 FROM "C"; -- fail, duplicate name
328+
CREATE COLLATION IF NOT EXISTS test0 FROM "C"; -- ok, skipped
329+
CREATE COLLATION IF NOT EXISTS test0 (locale = 'foo'); -- ok, skipped
328330
do $$
329331
BEGIN
330332
EXECUTE 'CREATE COLLATION test1 (lc_collate = ' ||

0 commit comments

Comments
 (0)