From b36017fdb8551195f549c15a501fe1de7e8937ef Mon Sep 17 00:00:00 2001 From: l00584793 Date: Wed, 2 Sep 2020 14:57:23 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E7=B4=A2=E5=BC=95=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E5=88=97=E5=90=8D=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/backend/parser/parse_utilcmd.cpp | 22 ++++++++- .../expected/duplicate_column_index.out | 46 +++++++++++++++++++ src/test/regress/parallel_schedule10 | 3 +- .../regress/sql/duplicate_column_index.sql | 45 ++++++++++++++++++ 4 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 src/test/regress/expected/duplicate_column_index.out create mode 100644 src/test/regress/sql/duplicate_column_index.sql diff --git a/src/common/backend/parser/parse_utilcmd.cpp b/src/common/backend/parser/parse_utilcmd.cpp index 083da321b..0cd020a36 100644 --- a/src/common/backend/parser/parse_utilcmd.cpp +++ b/src/common/backend/parser/parse_utilcmd.cpp @@ -222,6 +222,7 @@ static List* DividePartitionStartEndInterval(ParseState* pstate, Form_pg_attribu Const* startVal, Const* endVal, Const* everyVal, Node* everyExpr, int* numPart, int maxNum); static void TryReuseFilenode(Relation rel, CreateStmtContext *ctx, bool clonepart); extern Node* makeAConst(Value* v, int location); +static bool IsElementExisted(List* indexElements, IndexElem* ielem); /* * transformCreateStmt - @@ -3120,7 +3121,7 @@ IndexStmt* transformIndexStmt(Oid relid, IndexStmt* stmt, const char* queryStrin /* we have to fix its collations too */ assign_expr_collations(pstate, stmt->whereClause); } - + List* indexElements = NIL; /* take care of any index expressions */ foreach (l, stmt->indexParams) { IndexElem* ielem = (IndexElem*)lfirst(l); @@ -3144,8 +3145,15 @@ IndexStmt* transformIndexStmt(Oid relid, IndexStmt* stmt, const char* queryStrin if (expression_returns_set(ielem->expr)) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("index expression cannot return a set"))); } + + if (IsElementExisted(indexElements, ielem)) { + ereport(ERROR, (errcode(ERRCODE_DUPLICATE_COLUMN), errmsg("duplicate column name"))); + } + indexElements = lappend(indexElements, (IndexElem*)ielem); } + list_free(indexElements); + /* * Check that only the base rel is mentioned. */ @@ -3177,6 +3185,18 @@ IndexStmt* transformIndexStmt(Oid relid, IndexStmt* stmt, const char* queryStrin return stmt; } +static bool IsElementExisted(List* indexElements, IndexElem* ielem) +{ + ListCell* lc = NULL; + foreach (lc, indexElements) { + IndexElem* theElement = (IndexElem*)lfirst(lc); + if (equal(theElement, ielem)) { + return true; + } + } + return false; +} + /* * transformRuleStmt - * transform a CREATE RULE Statement. The action is a list of parse diff --git a/src/test/regress/expected/duplicate_column_index.out b/src/test/regress/expected/duplicate_column_index.out new file mode 100644 index 000000000..060d9ec54 --- /dev/null +++ b/src/test/regress/expected/duplicate_column_index.out @@ -0,0 +1,46 @@ +--test duplicate keys can be created successfully +create table test_index(id int); +create index index_01 on test_index(id,id,id); +ERROR: duplicate column name +create index index_01 on test_index(id); +drop index if exists index_01; +create index index_01 on test_index using gin(to_tsvector('english', id), + to_tsvector('english', id)); +ERROR: duplicate column name +create index index_01 on test_index using gin(to_tsvector('english', id)); +drop index if exists index_01; +drop table if exists test_index; +create table test_index(id int) with (orientation=column); +create index index_01 on test_index using btree(id,id,id); +ERROR: duplicate column name +create index index_01 on test_index using btree(id); +drop index if exists index_01; +create index index_01 on test_index using psort(id,id,id); +ERROR: duplicate column name +create index index_01 on test_index using psort(id); +drop index if exists index_01; +create index index_01 on test_index using gin(to_tsvector('english', id), + to_tsvector('english', id),to_tsvector('english', id)); +ERROR: duplicate column name +create index index_01 on test_index using gin(to_tsvector('english', id)); +--test whether duplicate expression can be created successfully +drop table if exists test_index; +create table test_index(id int, id_1 int); +drop index if exists index_01; +NOTICE: index "index_01" does not exist, skipping +create index index_01 on test_index using btree(sin(id), sin(id)); +ERROR: duplicate column name +create index index_01 on test_index using btree(sin(id), sin(id_1)); +drop index if exists index_01; +create index index_01 on test_index using btree(sin(id), cos(id)); +drop index if exists index_01; +create index index_01 on test_index using gin(to_tsvector('english', sin(id)), + to_tsvector('english', sin(id))); +ERROR: duplicate column name +drop index if exists index_01; +NOTICE: index "index_01" does not exist, skipping +create index index_01 on test_index using gin(to_tsvector('english', sin(id)), + to_tsvector('english', sin(id_1))); +drop index if exists index_01; +create index index_01 on test_index using gin(to_tsvector('english', sin(id)), + to_tsvector('english', cos(id))); diff --git a/src/test/regress/parallel_schedule10 b/src/test/regress/parallel_schedule10 index 18186d1ef..5edc71597 100644 --- a/src/test/regress/parallel_schedule10 +++ b/src/test/regress/parallel_schedule10 @@ -75,4 +75,5 @@ test: with # run alter object to test pg_object #test: pg_object_test test: partition_foreign_key -test: partition_trigger \ No newline at end of file +test: partition_trigger +test: duplicate_column_index diff --git a/src/test/regress/sql/duplicate_column_index.sql b/src/test/regress/sql/duplicate_column_index.sql new file mode 100644 index 000000000..eb79329eb --- /dev/null +++ b/src/test/regress/sql/duplicate_column_index.sql @@ -0,0 +1,45 @@ +--test duplicate keys can be created successfully +create table test_index(id int); +create index index_01 on test_index(id,id,id); +create index index_01 on test_index(id); + +drop index if exists index_01; +create index index_01 on test_index using gin(to_tsvector('english', id), + to_tsvector('english', id)); +create index index_01 on test_index using gin(to_tsvector('english', id)); + + +drop index if exists index_01; +drop table if exists test_index; +create table test_index(id int) with (orientation=column); +create index index_01 on test_index using btree(id,id,id); +create index index_01 on test_index using btree(id); + +drop index if exists index_01; +create index index_01 on test_index using psort(id,id,id); +create index index_01 on test_index using psort(id); + +drop index if exists index_01; +create index index_01 on test_index using gin(to_tsvector('english', id), + to_tsvector('english', id),to_tsvector('english', id)); +create index index_01 on test_index using gin(to_tsvector('english', id)); + +--test whether duplicate expression can be created successfully +drop table if exists test_index; +create table test_index(id int, id_1 int); + +drop index if exists index_01; +create index index_01 on test_index using btree(sin(id), sin(id)); +create index index_01 on test_index using btree(sin(id), sin(id_1)); +drop index if exists index_01; +create index index_01 on test_index using btree(sin(id), cos(id)); + +drop index if exists index_01; +create index index_01 on test_index using gin(to_tsvector('english', sin(id)), + to_tsvector('english', sin(id))); +drop index if exists index_01; +create index index_01 on test_index using gin(to_tsvector('english', sin(id)), + to_tsvector('english', sin(id_1))); +drop index if exists index_01; +create index index_01 on test_index using gin(to_tsvector('english', sin(id)), + to_tsvector('english', cos(id)));