diff --git a/doc/src/sgml/ref/create_sequence.sgmlin b/doc/src/sgml/ref/create_sequence.sgmlin index 8ef9fd308..7520fd49b 100644 --- a/doc/src/sgml/ref/create_sequence.sgmlin +++ b/doc/src/sgml/ref/create_sequence.sgmlin @@ -16,7 +16,7 @@ -CREATE [ LARGE ] SEQUENCE name [ INCREMENT [ BY ] increment ] +CREATE [ LARGE ] SEQUENCE [ IF NOT EXISTS ] name [ INCREMENT [ BY ] increment ] [ MINVALUE minvalue | NO MINVALUE | NOMINVALUE] [ MAXVALUE maxvalue | NO MAXVALUE | NOMAXVALUE] [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE | NOCYCLE] [ OWNED BY { table_name.column_name | NONE } ]; diff --git a/src/common/backend/nodes/copyfuncs.cpp b/src/common/backend/nodes/copyfuncs.cpp index 018742ef0..2340f2cda 100644 --- a/src/common/backend/nodes/copyfuncs.cpp +++ b/src/common/backend/nodes/copyfuncs.cpp @@ -5901,6 +5901,7 @@ static CreateSeqStmt* _copyCreateSeqStmt(const CreateSeqStmt* from) COPY_SCALAR_FIELD(uuid); COPY_SCALAR_FIELD(canCreateTempSeq); COPY_SCALAR_FIELD(is_large); + COPY_SCALAR_FIELD(missing_ok); return newnode; } diff --git a/src/common/backend/nodes/equalfuncs.cpp b/src/common/backend/nodes/equalfuncs.cpp index 0395e0e99..f6264d368 100644 --- a/src/common/backend/nodes/equalfuncs.cpp +++ b/src/common/backend/nodes/equalfuncs.cpp @@ -1893,6 +1893,7 @@ static bool _equalCreateSeqStmt(const CreateSeqStmt* a, const CreateSeqStmt* b) COMPARE_SCALAR_FIELD(uuid); COMPARE_SCALAR_FIELD(canCreateTempSeq); COMPARE_SCALAR_FIELD(is_large); + COMPARE_SCALAR_FIELD(missing_ok); return true; } diff --git a/src/common/backend/parser/gram.y b/src/common/backend/parser/gram.y index 332202531..9cc50cd8f 100644 --- a/src/common/backend/parser/gram.y +++ b/src/common/backend/parser/gram.y @@ -9861,6 +9861,34 @@ CreateSeqStmt: n->sequence = $5; n->options = $6; + n->missing_ok = false; + n->ownerId = InvalidOid; +/* PGXC_BEGIN */ + n->is_serial = false; +/* PGXC_END */ + n->uuid = 0; + n->canCreateTempSeq = false; + $$ = (Node *)n; + } + | CREATE OptTemp opt_large_seq SEQUENCE IF_P NOT EXISTS qualified_name OptSeqOptList + { + CreateSeqStmt *n = makeNode(CreateSeqStmt); + $8->relpersistence = $2; + n->is_large = $3; +#ifdef ENABLE_MULTIPLE_NODES + if (n->is_large) { + const char* message = "large sequence is not supported."; + InsertErrorMessage(message, u_sess->plsql_cxt.plpgsql_yylloc); + ereport(ERROR, + (errmodule(MOD_PARSER), + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("large sequence is not supported."))); + } +#endif + + n->sequence = $8; + n->options = $9; + n->missing_ok = true; n->ownerId = InvalidOid; /* PGXC_BEGIN */ n->is_serial = false; diff --git a/src/gausskernel/optimizer/commands/sequence/sequence.cpp b/src/gausskernel/optimizer/commands/sequence/sequence.cpp index 3255a854c..8dd21db7c 100644 --- a/src/gausskernel/optimizer/commands/sequence/sequence.cpp +++ b/src/gausskernel/optimizer/commands/sequence/sequence.cpp @@ -821,6 +821,18 @@ static ObjectAddress DefineSequence(CreateSeqStmt* seq) bool isUseLocalSeq = false; Oid namespaceOid = InvalidOid; ObjectAddress address; + Oid existing_relid = InvalidOid; + Oid namespaceId = InvalidOid; + char rel_kind = large ? RELKIND_LARGE_SEQUENCE : RELKIND_SEQUENCE; + + if (seq->missing_ok) { + namespaceId = RangeVarGetAndCheckCreationNamespace(seq->sequence, NoLock, &existing_relid, rel_kind); + if (existing_relid != InvalidOid) { + char* namespace_of_existing_rel = get_namespace_name(namespaceId); + ereport(NOTICE, (errmodule(MOD_COMMAND), errmsg("relation \"%s\" already exists in schema \"%s\", skipping", seq->sequence->relname, namespace_of_existing_rel))); + return InvalidObjectAddress; + } + } #ifdef PGXC /* PGXC_COORD */ GTM_Sequence start_value = 1; @@ -996,7 +1008,6 @@ static ObjectAddress DefineSequence(CreateSeqStmt* seq) stmt->tablespacename = NULL; stmt->if_not_exists = false; stmt->charset = PG_INVALID_ENCODING; - char rel_kind = large ? RELKIND_LARGE_SEQUENCE : RELKIND_SEQUENCE; address = DefineRelation(stmt, rel_kind, seq->ownerId, NULL); seqoid = address.objectId; Assert(seqoid != InvalidOid); diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index fe7e86ae9..d87df917a 100755 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1131,6 +1131,7 @@ typedef struct CreateSeqStmt { int64 uuid; /* UUID of the sequence, mark unique sequence globally */ bool canCreateTempSeq; /* create sequence when "create table (like )" */ bool is_large; + bool missing_ok; /* skip error if a Sequence is exists */ } CreateSeqStmt; typedef struct AlterSeqStmt { diff --git a/src/test/regress/expected/test_create_sequence_if_not_exists.out b/src/test/regress/expected/test_create_sequence_if_not_exists.out new file mode 100644 index 000000000..a4cea9e39 --- /dev/null +++ b/src/test/regress/expected/test_create_sequence_if_not_exists.out @@ -0,0 +1,14 @@ +create schema create_sequence_if_not_exists; +set current_schema = create_sequence_if_not_exists; +create sequence seq start with 1; +create sequence seq start with 1; +ERROR: relation "seq" already exists in schema "create_sequence_if_not_exists" +DETAIL: creating new table with existing name in the same schema +create sequence if not exists seq start with 1; +NOTICE: relation "seq" already exists in schema "create_sequence_if_not_exists", skipping +drop sequence seq; +create sequence if not exists seq start with 1; +create sequence if not exists seq start with 2; +NOTICE: relation "seq" already exists in schema "create_sequence_if_not_exists", skipping +drop sequence seq; +drop schema create_sequence_if_not_exists; diff --git a/src/test/regress/parallel_schedule0 b/src/test/regress/parallel_schedule0 index d3135fa2d..0f387ca1f 100644 --- a/src/test/regress/parallel_schedule0 +++ b/src/test/regress/parallel_schedule0 @@ -639,7 +639,7 @@ test: copy_new_gram copy_gbk_test copy_gb18030_test # Another group of parallel tests # ---------- test: create_function_3 vacuum -test: drop_if_exists drop_database test_if_not_exists test_create_index_if_not_exists +test: drop_if_exists drop_database test_if_not_exists test_create_index_if_not_exists test_create_sequence_if_not_exists #test: constraints #test: errors subplan_base diff --git a/src/test/regress/parallel_schedule0A b/src/test/regress/parallel_schedule0A index 7ef668d0b..0259fd6ff 100644 --- a/src/test/regress/parallel_schedule0A +++ b/src/test/regress/parallel_schedule0A @@ -436,7 +436,7 @@ test: stable_function_shippable # Another group of parallel tests # ---------- test: create_function_3 vacuum -test: drop_if_exists drop_database test_if_not_exists test_create_index_if_not_exists +test: drop_if_exists drop_database test_if_not_exists test_create_index_if_not_exists test_create_sequence_if_not_exists #test: constraints #test: errors subplan_base diff --git a/src/test/regress/sql/test_create_sequence_if_not_exists.sql b/src/test/regress/sql/test_create_sequence_if_not_exists.sql new file mode 100644 index 000000000..42f7de9cd --- /dev/null +++ b/src/test/regress/sql/test_create_sequence_if_not_exists.sql @@ -0,0 +1,12 @@ +create schema create_sequence_if_not_exists; +set current_schema = create_sequence_if_not_exists; + +create sequence seq start with 1; +create sequence seq start with 1; + +create sequence if not exists seq start with 1; +drop sequence seq; +create sequence if not exists seq start with 1; +create sequence if not exists seq start with 2; +drop sequence seq; +drop schema create_sequence_if_not_exists; \ No newline at end of file