From 0076f264b6f24854219d49b159602e2042c38ee7 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas <heikki.linnakangas@iki.fi> Date: Tue, 26 Aug 2014 16:05:18 +0300 Subject: [PATCH] Implement IF NOT EXISTS for CREATE SEQUENCE. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FabrÃzio de Royes Mello --- doc/src/sgml/ref/create_sequence.sgml | 14 +++++++++++++- src/backend/commands/sequence.c | 20 +++++++++++++++++++- src/backend/nodes/copyfuncs.c | 1 + src/backend/nodes/equalfuncs.c | 1 + src/backend/parser/gram.y | 11 +++++++++++ src/include/nodes/parsenodes.h | 1 + src/test/regress/expected/sequence.out | 2 ++ src/test/regress/sql/sequence.sql | 1 + 8 files changed, 49 insertions(+), 2 deletions(-) diff --git a/doc/src/sgml/ref/create_sequence.sgml b/doc/src/sgml/ref/create_sequence.sgml index b8468b5bb25..7292c3fa361 100644 --- a/doc/src/sgml/ref/create_sequence.sgml +++ b/doc/src/sgml/ref/create_sequence.sgml @@ -21,7 +21,7 @@ PostgreSQL documentation <refsynopsisdiv> <synopsis> -CREATE [ TEMPORARY | TEMP ] SEQUENCE <replaceable class="parameter">name</replaceable> [ INCREMENT [ BY ] <replaceable class="parameter">increment</replaceable> ] +CREATE [ TEMPORARY | TEMP ] [ IF NOT EXISTS ] SEQUENCE <replaceable class="parameter">name</replaceable> [ INCREMENT [ BY ] <replaceable class="parameter">increment</replaceable> ] [ MINVALUE <replaceable class="parameter">minvalue</replaceable> | NO MINVALUE ] [ MAXVALUE <replaceable class="parameter">maxvalue</replaceable> | NO MAXVALUE ] [ START [ WITH ] <replaceable class="parameter">start</replaceable> ] [ CACHE <replaceable class="parameter">cache</replaceable> ] [ [ NO ] CYCLE ] [ OWNED BY { <replaceable class="parameter">table_name</replaceable>.<replaceable class="parameter">column_name</replaceable> | NONE } ] @@ -89,6 +89,18 @@ SELECT * FROM <replaceable>name</replaceable>; </listitem> </varlistentry> + <varlistentry> + <term><literal>IF NOT EXISTS</literal></term> + <listitem> + <para> + Do not throw an error if a relation with the same name already exists. + A notice is issued in this case. Note that there is no guarantee that + the existing relation is anything like the sequence that would have + been created - it might not even be a sequence. + </para> + </listitem> + </varlistentry> + <varlistentry> <term><replaceable class="parameter">name</replaceable></term> <listitem> diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index e6084203a88..3b89dd009bc 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -122,6 +122,24 @@ DefineSequence(CreateSeqStmt *seq) (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("unlogged sequences are not supported"))); + /* + * If if_not_exists was given and a relation with the same name already + * exists, bail out. (Note: we needn't check this when not if_not_exists, + * because DefineRelation will complain anyway.) + */ + if (seq->if_not_exists) + { + RangeVarGetAndCheckCreationNamespace(seq->sequence, NoLock, &seqoid); + if (OidIsValid(seqoid)) + { + ereport(NOTICE, + (errcode(ERRCODE_DUPLICATE_TABLE), + errmsg("relation \"%s\" already exists, skipping", + seq->sequence->relname))); + return InvalidOid; + } + } + /* Check and set all option values */ init_params(seq->options, true, &new, &owned_by); @@ -210,7 +228,7 @@ DefineSequence(CreateSeqStmt *seq) stmt->options = NIL; stmt->oncommit = ONCOMMIT_NOOP; stmt->tablespacename = NULL; - stmt->if_not_exists = false; + stmt->if_not_exists = seq->if_not_exists; seqoid = DefineRelation(stmt, RELKIND_SEQUENCE, seq->ownerId); Assert(seqoid != InvalidOid); diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index f5ddc1ced7c..aa053a0f158 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -3330,6 +3330,7 @@ _copyCreateSeqStmt(const CreateSeqStmt *from) COPY_NODE_FIELD(sequence); COPY_NODE_FIELD(options); COPY_SCALAR_FIELD(ownerId); + COPY_SCALAR_FIELD(if_not_exists); return newnode; } diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index ccd6064bf7d..719923e02e7 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -1566,6 +1566,7 @@ _equalCreateSeqStmt(const CreateSeqStmt *a, const CreateSeqStmt *b) COMPARE_NODE_FIELD(sequence); COMPARE_NODE_FIELD(options); COMPARE_SCALAR_FIELD(ownerId); + COMPARE_SCALAR_FIELD(if_not_exists); return true; } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 71ce7ee2ddf..6f4d6455df6 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -3486,6 +3486,17 @@ CreateSeqStmt: n->sequence = $4; n->options = $5; n->ownerId = InvalidOid; + n->if_not_exists = false; + $$ = (Node *)n; + } + | CREATE OptTemp SEQUENCE IF_P NOT EXISTS qualified_name OptSeqOptList + { + CreateSeqStmt *n = makeNode(CreateSeqStmt); + $7->relpersistence = $2; + n->sequence = $7; + n->options = $8; + n->ownerId = InvalidOid; + n->if_not_exists = true; $$ = (Node *)n; } ; diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 28029fe69ee..d2c0b29c0d7 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1979,6 +1979,7 @@ typedef struct CreateSeqStmt RangeVar *sequence; /* the sequence to create */ List *options; Oid ownerId; /* ID of owner, or InvalidOid for default */ + bool if_not_exists; /* just do nothing if it already exists? */ } CreateSeqStmt; typedef struct AlterSeqStmt diff --git a/src/test/regress/expected/sequence.out b/src/test/regress/expected/sequence.out index 8fcb70015fb..a27b5fda045 100644 --- a/src/test/regress/expected/sequence.out +++ b/src/test/regress/expected/sequence.out @@ -91,6 +91,8 @@ SELECT nextval('serialTest2_f6_seq'); -- basic sequence operations using both text and oid references CREATE SEQUENCE sequence_test; +CREATE SEQUENCE IF NOT EXISTS sequence_test; +NOTICE: relation "sequence_test" already exists, skipping SELECT nextval('sequence_test'::text); nextval --------- diff --git a/src/test/regress/sql/sequence.sql b/src/test/regress/sql/sequence.sql index be5e9a97bf4..8d3b700f7da 100644 --- a/src/test/regress/sql/sequence.sql +++ b/src/test/regress/sql/sequence.sql @@ -59,6 +59,7 @@ SELECT nextval('serialTest2_f6_seq'); -- basic sequence operations using both text and oid references CREATE SEQUENCE sequence_test; +CREATE SEQUENCE IF NOT EXISTS sequence_test; SELECT nextval('sequence_test'::text); SELECT nextval('sequence_test'::regclass); -- GitLab