diff --git a/src/backend/distributed/utils/citus_ruleutils.c b/src/backend/distributed/utils/citus_ruleutils.c index d8adea88b..340657538 100644 --- a/src/backend/distributed/utils/citus_ruleutils.c +++ b/src/backend/distributed/utils/citus_ruleutils.c @@ -62,6 +62,8 @@ #include "utils/syscache.h" +static void deparse_index_columns(StringInfo buffer, List *indexParameterList, + List *deparseContext); static void AppendOptionListToString(StringInfo stringData, List *options); static void AppendStorageParametersToString(StringInfo stringBuffer, List *optionList); @@ -686,7 +688,6 @@ deparse_shard_index_statement(IndexStmt *origStmt, Oid distrelid, int64 shardid, IndexStmt *indexStmt = copyObject(origStmt); /* copy to avoid modifications */ char *relationName = indexStmt->relation->relname; char *indexName = indexStmt->idxname; - ListCell *indexParameterCell = NULL; List *deparseContext = NULL; /* extend relation and index name using shard identifier */ @@ -708,13 +709,42 @@ deparse_shard_index_statement(IndexStmt *origStmt, Oid distrelid, int64 shardid, /* index column or expression list begins here */ appendStringInfoChar(buffer, '('); + deparse_index_columns(buffer, indexStmt->indexParams, deparseContext); + appendStringInfoString(buffer, ") "); - foreach(indexParameterCell, indexStmt->indexParams) +#if PG_VERSION_NUM >= 110000 + + /* column/expressions for INCLUDE list */ + if (indexStmt->indexIncludingParams != NIL) + { + appendStringInfoString(buffer, "INCLUDE ("); + deparse_index_columns(buffer, indexStmt->indexIncludingParams, deparseContext); + appendStringInfoChar(buffer, ')'); + } +#endif + + AppendStorageParametersToString(buffer, indexStmt->options); + + if (indexStmt->whereClause != NULL) + { + appendStringInfo(buffer, "WHERE %s", deparse_expression(indexStmt->whereClause, + deparseContext, false, + false)); + } +} + + +/* deparse_index_columns appends index or include parameters to the provided buffer */ +static void +deparse_index_columns(StringInfo buffer, List *indexParameterList, List *deparseContext) +{ + ListCell *indexParameterCell = NULL; + foreach(indexParameterCell, indexParameterList) { IndexElem *indexElement = (IndexElem *) lfirst(indexParameterCell); /* use commas to separate subsequent elements */ - if (indexParameterCell != list_head(indexStmt->indexParams)) + if (indexParameterCell != list_head(indexParameterList)) { appendStringInfoChar(buffer, ','); } @@ -754,17 +784,6 @@ deparse_shard_index_statement(IndexStmt *origStmt, Oid distrelid, int64 shardid, appendStringInfo(buffer, "NULLS %s ", (nullsFirst ? "FIRST" : "LAST")); } } - - appendStringInfoString(buffer, ") "); - - AppendStorageParametersToString(buffer, indexStmt->options); - - if (indexStmt->whereClause != NULL) - { - appendStringInfo(buffer, "WHERE %s", deparse_expression(indexStmt->whereClause, - deparseContext, false, - false)); - } } diff --git a/src/test/regress/expected/multi_index_statements.out b/src/test/regress/expected/multi_index_statements.out index 30573cec8..4ad80ad4e 100644 --- a/src/test/regress/expected/multi_index_statements.out +++ b/src/test/regress/expected/multi_index_statements.out @@ -3,6 +3,13 @@ -- -- Check that we can run CREATE INDEX and DROP INDEX statements on distributed -- tables. +SHOW server_version \gset +SELECT substring(:'server_version', '\d+')::int AS major_version; + major_version +--------------- + 11 +(1 row) + -- -- CREATE TEST TABLES -- @@ -71,6 +78,7 @@ CREATE UNIQUE INDEX index_test_hash_index_a ON index_test_hash(a); CREATE UNIQUE INDEX index_test_hash_index_a_b ON index_test_hash(a,b); CREATE UNIQUE INDEX index_test_hash_index_a_b_partial ON index_test_hash(a,b) WHERE c IS NOT NULL; CREATE UNIQUE INDEX index_test_range_index_a_b_partial ON index_test_range(a,b) WHERE c IS NOT NULL; +CREATE UNIQUE INDEX index_test_hash_index_a_b_c ON index_test_hash(a) INCLUDE (b,c); RESET client_min_messages; -- Verify that we handle if not exists statements correctly CREATE INDEX lineitem_orderkey_index on lineitem(l_orderkey); @@ -102,6 +110,7 @@ SELECT * FROM pg_indexes WHERE tablename = 'lineitem' or tablename like 'index_t ------------+------------------+------------------------------------+------------+---------------------------------------------------------------------------------------------------------------------------- public | index_test_hash | index_test_hash_index_a | | CREATE UNIQUE INDEX index_test_hash_index_a ON public.index_test_hash USING btree (a) public | index_test_hash | index_test_hash_index_a_b | | CREATE UNIQUE INDEX index_test_hash_index_a_b ON public.index_test_hash USING btree (a, b) + public | index_test_hash | index_test_hash_index_a_b_c | | CREATE UNIQUE INDEX index_test_hash_index_a_b_c ON public.index_test_hash USING btree (a) INCLUDE (b, c) public | index_test_hash | index_test_hash_index_a_b_partial | | CREATE UNIQUE INDEX index_test_hash_index_a_b_partial ON public.index_test_hash USING btree (a, b) WHERE (c IS NOT NULL) public | index_test_range | index_test_range_index_a | | CREATE UNIQUE INDEX index_test_range_index_a ON public.index_test_range USING btree (a) public | index_test_range | index_test_range_index_a_b | | CREATE UNIQUE INDEX index_test_range_index_a_b ON public.index_test_range USING btree (a, b) @@ -115,7 +124,7 @@ SELECT * FROM pg_indexes WHERE tablename = 'lineitem' or tablename like 'index_t public | lineitem | lineitem_partkey_desc_index | | CREATE INDEX lineitem_partkey_desc_index ON public.lineitem USING btree (l_partkey DESC) public | lineitem | lineitem_pkey | | CREATE UNIQUE INDEX lineitem_pkey ON public.lineitem USING btree (l_orderkey, l_linenumber) public | lineitem | lineitem_time_index | | CREATE INDEX lineitem_time_index ON public.lineitem USING btree (l_shipdate) -(15 rows) +(16 rows) \c - - - :worker_1_port SELECT count(*) FROM pg_indexes WHERE tablename = (SELECT relname FROM pg_class WHERE relname LIKE 'lineitem%' ORDER BY relname LIMIT 1); @@ -127,7 +136,7 @@ SELECT count(*) FROM pg_indexes WHERE tablename = (SELECT relname FROM pg_class SELECT count(*) FROM pg_indexes WHERE tablename LIKE 'index_test_hash%'; count ------- - 24 + 32 (1 row) SELECT count(*) FROM pg_indexes WHERE tablename LIKE 'index_test_range%'; @@ -179,6 +188,7 @@ SELECT * FROM pg_indexes WHERE tablename = 'lineitem' or tablename like 'index_t ------------+------------------+------------------------------------+------------+---------------------------------------------------------------------------------------------------------------------------- public | index_test_hash | index_test_hash_index_a | | CREATE UNIQUE INDEX index_test_hash_index_a ON public.index_test_hash USING btree (a) public | index_test_hash | index_test_hash_index_a_b | | CREATE UNIQUE INDEX index_test_hash_index_a_b ON public.index_test_hash USING btree (a, b) + public | index_test_hash | index_test_hash_index_a_b_c | | CREATE UNIQUE INDEX index_test_hash_index_a_b_c ON public.index_test_hash USING btree (a) INCLUDE (b, c) public | index_test_hash | index_test_hash_index_a_b_partial | | CREATE UNIQUE INDEX index_test_hash_index_a_b_partial ON public.index_test_hash USING btree (a, b) WHERE (c IS NOT NULL) public | index_test_range | index_test_range_index_a | | CREATE UNIQUE INDEX index_test_range_index_a ON public.index_test_range USING btree (a) public | index_test_range | index_test_range_index_a_b | | CREATE UNIQUE INDEX index_test_range_index_a_b ON public.index_test_range USING btree (a, b) @@ -192,7 +202,7 @@ SELECT * FROM pg_indexes WHERE tablename = 'lineitem' or tablename like 'index_t public | lineitem | lineitem_partkey_desc_index | | CREATE INDEX lineitem_partkey_desc_index ON public.lineitem USING btree (l_partkey DESC) public | lineitem | lineitem_pkey | | CREATE UNIQUE INDEX lineitem_pkey ON public.lineitem USING btree (l_orderkey, l_linenumber) public | lineitem | lineitem_time_index | | CREATE INDEX lineitem_time_index ON public.lineitem USING btree (l_shipdate) -(15 rows) +(16 rows) -- -- DROP INDEX @@ -231,9 +241,10 @@ SELECT indrelid::regclass, indexrelid::regclass FROM pg_index WHERE indrelid = ( (0 rows) SELECT * FROM pg_indexes WHERE tablename LIKE 'index_test_%' ORDER BY indexname; - schemaname | tablename | indexname | tablespace | indexdef -------------+-----------+-----------+------------+---------- -(0 rows) + schemaname | tablename | indexname | tablespace | indexdef +------------+-----------------+-----------------------------+------------+---------------------------------------------------------------------------------------------------------- + public | index_test_hash | index_test_hash_index_a_b_c | | CREATE UNIQUE INDEX index_test_hash_index_a_b_c ON public.index_test_hash USING btree (a) INCLUDE (b, c) +(1 row) \c - - - :worker_1_port SELECT indrelid::regclass, indexrelid::regclass FROM pg_index WHERE indrelid = (SELECT relname FROM pg_class WHERE relname LIKE 'lineitem%' ORDER BY relname LIMIT 1)::regclass AND NOT indisprimary AND indexrelid::regclass::text NOT LIKE 'lineitem_time_index%'; @@ -242,9 +253,17 @@ SELECT indrelid::regclass, indexrelid::regclass FROM pg_index WHERE indrelid = ( (0 rows) SELECT * FROM pg_indexes WHERE tablename LIKE 'index_test_%' ORDER BY indexname; - schemaname | tablename | indexname | tablespace | indexdef -------------+-----------+-----------+------------+---------- -(0 rows) + schemaname | tablename | indexname | tablespace | indexdef +------------+------------------------+------------------------------------+------------+------------------------------------------------------------------------------------------------------------------------ + public | index_test_hash_102082 | index_test_hash_index_a_b_c_102082 | | CREATE UNIQUE INDEX index_test_hash_index_a_b_c_102082 ON public.index_test_hash_102082 USING btree (a) INCLUDE (b, c) + public | index_test_hash_102083 | index_test_hash_index_a_b_c_102083 | | CREATE UNIQUE INDEX index_test_hash_index_a_b_c_102083 ON public.index_test_hash_102083 USING btree (a) INCLUDE (b, c) + public | index_test_hash_102084 | index_test_hash_index_a_b_c_102084 | | CREATE UNIQUE INDEX index_test_hash_index_a_b_c_102084 ON public.index_test_hash_102084 USING btree (a) INCLUDE (b, c) + public | index_test_hash_102085 | index_test_hash_index_a_b_c_102085 | | CREATE UNIQUE INDEX index_test_hash_index_a_b_c_102085 ON public.index_test_hash_102085 USING btree (a) INCLUDE (b, c) + public | index_test_hash_102086 | index_test_hash_index_a_b_c_102086 | | CREATE UNIQUE INDEX index_test_hash_index_a_b_c_102086 ON public.index_test_hash_102086 USING btree (a) INCLUDE (b, c) + public | index_test_hash_102087 | index_test_hash_index_a_b_c_102087 | | CREATE UNIQUE INDEX index_test_hash_index_a_b_c_102087 ON public.index_test_hash_102087 USING btree (a) INCLUDE (b, c) + public | index_test_hash_102088 | index_test_hash_index_a_b_c_102088 | | CREATE UNIQUE INDEX index_test_hash_index_a_b_c_102088 ON public.index_test_hash_102088 USING btree (a) INCLUDE (b, c) + public | index_test_hash_102089 | index_test_hash_index_a_b_c_102089 | | CREATE UNIQUE INDEX index_test_hash_index_a_b_c_102089 ON public.index_test_hash_102089 USING btree (a) INCLUDE (b, c) +(8 rows) -- create index that will conflict with master operations CREATE INDEX CONCURRENTLY ith_b_idx_102089 ON index_test_hash_102089(b); diff --git a/src/test/regress/expected/multi_index_statements_0.out b/src/test/regress/expected/multi_index_statements_0.out index 5aade6198..70eb4e7cf 100644 --- a/src/test/regress/expected/multi_index_statements_0.out +++ b/src/test/regress/expected/multi_index_statements_0.out @@ -3,6 +3,13 @@ -- -- Check that we can run CREATE INDEX and DROP INDEX statements on distributed -- tables. +SHOW server_version \gset +SELECT substring(:'server_version', '\d+')::int AS major_version; + major_version +--------------- + 10 +(1 row) + -- -- CREATE TEST TABLES -- @@ -71,6 +78,10 @@ CREATE UNIQUE INDEX index_test_hash_index_a ON index_test_hash(a); CREATE UNIQUE INDEX index_test_hash_index_a_b ON index_test_hash(a,b); CREATE UNIQUE INDEX index_test_hash_index_a_b_partial ON index_test_hash(a,b) WHERE c IS NOT NULL; CREATE UNIQUE INDEX index_test_range_index_a_b_partial ON index_test_range(a,b) WHERE c IS NOT NULL; +CREATE UNIQUE INDEX index_test_hash_index_a_b_c ON index_test_hash(a) INCLUDE (b,c); +ERROR: syntax error at or near "INCLUDE" +LINE 1: ...index_test_hash_index_a_b_c ON index_test_hash(a) INCLUDE (b... + ^ RESET client_min_messages; -- Verify that we handle if not exists statements correctly CREATE INDEX lineitem_orderkey_index on lineitem(l_orderkey); @@ -98,23 +109,23 @@ CLUSTER local_table USING local_table_index; DROP TABLE local_table; -- Verify that all indexes got created on the master node and one of the workers SELECT * FROM pg_indexes WHERE tablename = 'lineitem' or tablename like 'index_test_%' ORDER BY indexname; - schemaname | tablename | indexname | tablespace | indexdef -------------+------------------+------------------------------------+------------+--------------------------------------------------------------------------------------------------------------------- - public | index_test_hash | index_test_hash_index_a | | CREATE UNIQUE INDEX index_test_hash_index_a ON index_test_hash USING btree (a) - public | index_test_hash | index_test_hash_index_a_b | | CREATE UNIQUE INDEX index_test_hash_index_a_b ON index_test_hash USING btree (a, b) - public | index_test_hash | index_test_hash_index_a_b_partial | | CREATE UNIQUE INDEX index_test_hash_index_a_b_partial ON index_test_hash USING btree (a, b) WHERE (c IS NOT NULL) - public | index_test_range | index_test_range_index_a | | CREATE UNIQUE INDEX index_test_range_index_a ON index_test_range USING btree (a) - public | index_test_range | index_test_range_index_a_b | | CREATE UNIQUE INDEX index_test_range_index_a_b ON index_test_range USING btree (a, b) - public | index_test_range | index_test_range_index_a_b_partial | | CREATE UNIQUE INDEX index_test_range_index_a_b_partial ON index_test_range USING btree (a, b) WHERE (c IS NOT NULL) - public | lineitem | lineitem_colref_index | | CREATE INDEX lineitem_colref_index ON lineitem USING btree (record_ne(lineitem.*, NULL::record)) - public | lineitem | lineitem_concurrently_index | | CREATE INDEX lineitem_concurrently_index ON lineitem USING btree (l_orderkey) - public | lineitem | lineitem_orderkey_hash_index | | CREATE INDEX lineitem_orderkey_hash_index ON lineitem USING hash (l_partkey) - public | lineitem | lineitem_orderkey_index | | CREATE INDEX lineitem_orderkey_index ON lineitem USING btree (l_orderkey) - public | lineitem | lineitem_orderkey_index_new | | CREATE INDEX lineitem_orderkey_index_new ON lineitem USING btree (l_orderkey) - public | lineitem | lineitem_partial_index | | CREATE INDEX lineitem_partial_index ON lineitem USING btree (l_shipdate) WHERE (l_shipdate < '01-01-1995'::date) - public | lineitem | lineitem_partkey_desc_index | | CREATE INDEX lineitem_partkey_desc_index ON lineitem USING btree (l_partkey DESC) - public | lineitem | lineitem_pkey | | CREATE UNIQUE INDEX lineitem_pkey ON lineitem USING btree (l_orderkey, l_linenumber) - public | lineitem | lineitem_time_index | | CREATE INDEX lineitem_time_index ON lineitem USING btree (l_shipdate) + schemaname | tablename | indexname | tablespace | indexdef +------------+------------------+------------------------------------+------------+---------------------------------------------------------------------------------------------------------------------------- + public | index_test_hash | index_test_hash_index_a | | CREATE UNIQUE INDEX index_test_hash_index_a ON public.index_test_hash USING btree (a) + public | index_test_hash | index_test_hash_index_a_b | | CREATE UNIQUE INDEX index_test_hash_index_a_b ON public.index_test_hash USING btree (a, b) + public | index_test_hash | index_test_hash_index_a_b_partial | | CREATE UNIQUE INDEX index_test_hash_index_a_b_partial ON public.index_test_hash USING btree (a, b) WHERE (c IS NOT NULL) + public | index_test_range | index_test_range_index_a | | CREATE UNIQUE INDEX index_test_range_index_a ON public.index_test_range USING btree (a) + public | index_test_range | index_test_range_index_a_b | | CREATE UNIQUE INDEX index_test_range_index_a_b ON public.index_test_range USING btree (a, b) + public | index_test_range | index_test_range_index_a_b_partial | | CREATE UNIQUE INDEX index_test_range_index_a_b_partial ON public.index_test_range USING btree (a, b) WHERE (c IS NOT NULL) + public | lineitem | lineitem_colref_index | | CREATE INDEX lineitem_colref_index ON public.lineitem USING btree (record_ne(lineitem.*, NULL::record)) + public | lineitem | lineitem_concurrently_index | | CREATE INDEX lineitem_concurrently_index ON public.lineitem USING btree (l_orderkey) + public | lineitem | lineitem_orderkey_hash_index | | CREATE INDEX lineitem_orderkey_hash_index ON public.lineitem USING hash (l_partkey) + public | lineitem | lineitem_orderkey_index | | CREATE INDEX lineitem_orderkey_index ON public.lineitem USING btree (l_orderkey) + public | lineitem | lineitem_orderkey_index_new | | CREATE INDEX lineitem_orderkey_index_new ON public.lineitem USING btree (l_orderkey) + public | lineitem | lineitem_partial_index | | CREATE INDEX lineitem_partial_index ON public.lineitem USING btree (l_shipdate) WHERE (l_shipdate < '01-01-1995'::date) + public | lineitem | lineitem_partkey_desc_index | | CREATE INDEX lineitem_partkey_desc_index ON public.lineitem USING btree (l_partkey DESC) + public | lineitem | lineitem_pkey | | CREATE UNIQUE INDEX lineitem_pkey ON public.lineitem USING btree (l_orderkey, l_linenumber) + public | lineitem | lineitem_time_index | | CREATE INDEX lineitem_time_index ON public.lineitem USING btree (l_shipdate) (15 rows) \c - - - :worker_1_port @@ -175,23 +186,23 @@ CREATE INDEX ON lineitem (l_orderkey); ERROR: creating index without a name on a distributed table is currently unsupported -- Verify that none of failed indexes got created on the master node SELECT * FROM pg_indexes WHERE tablename = 'lineitem' or tablename like 'index_test_%' ORDER BY indexname; - schemaname | tablename | indexname | tablespace | indexdef -------------+------------------+------------------------------------+------------+--------------------------------------------------------------------------------------------------------------------- - public | index_test_hash | index_test_hash_index_a | | CREATE UNIQUE INDEX index_test_hash_index_a ON index_test_hash USING btree (a) - public | index_test_hash | index_test_hash_index_a_b | | CREATE UNIQUE INDEX index_test_hash_index_a_b ON index_test_hash USING btree (a, b) - public | index_test_hash | index_test_hash_index_a_b_partial | | CREATE UNIQUE INDEX index_test_hash_index_a_b_partial ON index_test_hash USING btree (a, b) WHERE (c IS NOT NULL) - public | index_test_range | index_test_range_index_a | | CREATE UNIQUE INDEX index_test_range_index_a ON index_test_range USING btree (a) - public | index_test_range | index_test_range_index_a_b | | CREATE UNIQUE INDEX index_test_range_index_a_b ON index_test_range USING btree (a, b) - public | index_test_range | index_test_range_index_a_b_partial | | CREATE UNIQUE INDEX index_test_range_index_a_b_partial ON index_test_range USING btree (a, b) WHERE (c IS NOT NULL) - public | lineitem | lineitem_colref_index | | CREATE INDEX lineitem_colref_index ON lineitem USING btree (record_ne(lineitem.*, NULL::record)) - public | lineitem | lineitem_concurrently_index | | CREATE INDEX lineitem_concurrently_index ON lineitem USING btree (l_orderkey) - public | lineitem | lineitem_orderkey_hash_index | | CREATE INDEX lineitem_orderkey_hash_index ON lineitem USING hash (l_partkey) - public | lineitem | lineitem_orderkey_index | | CREATE INDEX lineitem_orderkey_index ON lineitem USING btree (l_orderkey) - public | lineitem | lineitem_orderkey_index_new | | CREATE INDEX lineitem_orderkey_index_new ON lineitem USING btree (l_orderkey) - public | lineitem | lineitem_partial_index | | CREATE INDEX lineitem_partial_index ON lineitem USING btree (l_shipdate) WHERE (l_shipdate < '01-01-1995'::date) - public | lineitem | lineitem_partkey_desc_index | | CREATE INDEX lineitem_partkey_desc_index ON lineitem USING btree (l_partkey DESC) - public | lineitem | lineitem_pkey | | CREATE UNIQUE INDEX lineitem_pkey ON lineitem USING btree (l_orderkey, l_linenumber) - public | lineitem | lineitem_time_index | | CREATE INDEX lineitem_time_index ON lineitem USING btree (l_shipdate) + schemaname | tablename | indexname | tablespace | indexdef +------------+------------------+------------------------------------+------------+---------------------------------------------------------------------------------------------------------------------------- + public | index_test_hash | index_test_hash_index_a | | CREATE UNIQUE INDEX index_test_hash_index_a ON public.index_test_hash USING btree (a) + public | index_test_hash | index_test_hash_index_a_b | | CREATE UNIQUE INDEX index_test_hash_index_a_b ON public.index_test_hash USING btree (a, b) + public | index_test_hash | index_test_hash_index_a_b_partial | | CREATE UNIQUE INDEX index_test_hash_index_a_b_partial ON public.index_test_hash USING btree (a, b) WHERE (c IS NOT NULL) + public | index_test_range | index_test_range_index_a | | CREATE UNIQUE INDEX index_test_range_index_a ON public.index_test_range USING btree (a) + public | index_test_range | index_test_range_index_a_b | | CREATE UNIQUE INDEX index_test_range_index_a_b ON public.index_test_range USING btree (a, b) + public | index_test_range | index_test_range_index_a_b_partial | | CREATE UNIQUE INDEX index_test_range_index_a_b_partial ON public.index_test_range USING btree (a, b) WHERE (c IS NOT NULL) + public | lineitem | lineitem_colref_index | | CREATE INDEX lineitem_colref_index ON public.lineitem USING btree (record_ne(lineitem.*, NULL::record)) + public | lineitem | lineitem_concurrently_index | | CREATE INDEX lineitem_concurrently_index ON public.lineitem USING btree (l_orderkey) + public | lineitem | lineitem_orderkey_hash_index | | CREATE INDEX lineitem_orderkey_hash_index ON public.lineitem USING hash (l_partkey) + public | lineitem | lineitem_orderkey_index | | CREATE INDEX lineitem_orderkey_index ON public.lineitem USING btree (l_orderkey) + public | lineitem | lineitem_orderkey_index_new | | CREATE INDEX lineitem_orderkey_index_new ON public.lineitem USING btree (l_orderkey) + public | lineitem | lineitem_partial_index | | CREATE INDEX lineitem_partial_index ON public.lineitem USING btree (l_shipdate) WHERE (l_shipdate < '01-01-1995'::date) + public | lineitem | lineitem_partkey_desc_index | | CREATE INDEX lineitem_partkey_desc_index ON public.lineitem USING btree (l_partkey DESC) + public | lineitem | lineitem_pkey | | CREATE UNIQUE INDEX lineitem_pkey ON public.lineitem USING btree (l_orderkey, l_linenumber) + public | lineitem | lineitem_time_index | | CREATE INDEX lineitem_time_index ON public.lineitem USING btree (l_shipdate) (15 rows) -- diff --git a/src/test/regress/expected/multi_index_statements_1.out b/src/test/regress/expected/multi_index_statements_1.out new file mode 100644 index 000000000..8628a1010 --- /dev/null +++ b/src/test/regress/expected/multi_index_statements_1.out @@ -0,0 +1,304 @@ +-- +-- MULTI_INDEX_STATEMENTS +-- +-- Check that we can run CREATE INDEX and DROP INDEX statements on distributed +-- tables. +SHOW server_version \gset +SELECT substring(:'server_version', '\d+')::int AS major_version; + major_version +--------------- + 9 +(1 row) + +-- +-- CREATE TEST TABLES +-- +SET citus.next_shard_id TO 102080; +CREATE TABLE index_test_range(a int, b int, c int); +SELECT create_distributed_table('index_test_range', 'a', 'range'); + create_distributed_table +-------------------------- + +(1 row) + +SELECT master_create_empty_shard('index_test_range'); + master_create_empty_shard +--------------------------- + 102080 +(1 row) + +SELECT master_create_empty_shard('index_test_range'); + master_create_empty_shard +--------------------------- + 102081 +(1 row) + +SET citus.shard_count TO 8; +SET citus.shard_replication_factor TO 2; +CREATE TABLE index_test_hash(a int, b int, c int); +SELECT create_distributed_table('index_test_hash', 'a', 'hash'); + create_distributed_table +-------------------------- + +(1 row) + +CREATE TABLE index_test_append(a int, b int, c int); +SELECT create_distributed_table('index_test_append', 'a', 'append'); + create_distributed_table +-------------------------- + +(1 row) + +SELECT master_create_empty_shard('index_test_append'); + master_create_empty_shard +--------------------------- + 102090 +(1 row) + +SELECT master_create_empty_shard('index_test_append'); + master_create_empty_shard +--------------------------- + 102091 +(1 row) + +-- +-- CREATE INDEX +-- +-- Verify that we can create different types of indexes +CREATE INDEX lineitem_orderkey_index ON lineitem (l_orderkey); +CREATE INDEX lineitem_partkey_desc_index ON lineitem (l_partkey DESC); +CREATE INDEX lineitem_partial_index ON lineitem (l_shipdate) + WHERE l_shipdate < '1995-01-01'; +CREATE INDEX lineitem_colref_index ON lineitem (record_ne(lineitem.*, NULL)); +SET client_min_messages = ERROR; -- avoid version dependant warning about WAL +CREATE INDEX lineitem_orderkey_hash_index ON lineitem USING hash (l_partkey); +CREATE UNIQUE INDEX index_test_range_index_a ON index_test_range(a); +CREATE UNIQUE INDEX index_test_range_index_a_b ON index_test_range(a,b); +CREATE UNIQUE INDEX index_test_hash_index_a ON index_test_hash(a); +CREATE UNIQUE INDEX index_test_hash_index_a_b ON index_test_hash(a,b); +CREATE UNIQUE INDEX index_test_hash_index_a_b_partial ON index_test_hash(a,b) WHERE c IS NOT NULL; +CREATE UNIQUE INDEX index_test_range_index_a_b_partial ON index_test_range(a,b) WHERE c IS NOT NULL; +CREATE UNIQUE INDEX index_test_hash_index_a_b_c ON index_test_hash(a) INCLUDE (b,c); +ERROR: syntax error at or near "INCLUDE" +LINE 1: ...index_test_hash_index_a_b_c ON index_test_hash(a) INCLUDE (b... + ^ +RESET client_min_messages; +-- Verify that we handle if not exists statements correctly +CREATE INDEX lineitem_orderkey_index on lineitem(l_orderkey); +ERROR: relation "lineitem_orderkey_index" already exists +CREATE INDEX IF NOT EXISTS lineitem_orderkey_index on lineitem(l_orderkey); +NOTICE: relation "lineitem_orderkey_index" already exists, skipping +CREATE INDEX IF NOT EXISTS lineitem_orderkey_index_new on lineitem(l_orderkey); +-- Verify if not exists behavior with an index with same name on a different table +CREATE INDEX lineitem_orderkey_index on index_test_hash(a); +ERROR: relation "lineitem_orderkey_index" already exists +CREATE INDEX IF NOT EXISTS lineitem_orderkey_index on index_test_hash(a); +NOTICE: relation "lineitem_orderkey_index" already exists, skipping +-- Verify that we can create indexes concurrently +CREATE INDEX CONCURRENTLY lineitem_concurrently_index ON lineitem (l_orderkey); +-- Verify that we warn out on CLUSTER command for distributed tables and no parameter +CLUSTER index_test_hash USING index_test_hash_index_a; +WARNING: not propagating CLUSTER command to worker nodes +CLUSTER; +WARNING: not propagating CLUSTER command to worker nodes +-- Verify that no-name local CREATE INDEX CONCURRENTLY works +CREATE TABLE local_table (id integer, name text); +CREATE INDEX CONCURRENTLY local_table_index ON local_table(id); +-- Vefify we don't warn out on CLUSTER command for local tables +CLUSTER local_table USING local_table_index; +DROP TABLE local_table; +-- Verify that all indexes got created on the master node and one of the workers +SELECT * FROM pg_indexes WHERE tablename = 'lineitem' or tablename like 'index_test_%' ORDER BY indexname; + schemaname | tablename | indexname | tablespace | indexdef +------------+------------------+------------------------------------+------------+---------------------------------------------------------------------------------------------------------------------------- + public | index_test_hash | index_test_hash_index_a | | CREATE UNIQUE INDEX index_test_hash_index_a ON public.index_test_hash USING btree (a) + public | index_test_hash | index_test_hash_index_a_b | | CREATE UNIQUE INDEX index_test_hash_index_a_b ON public.index_test_hash USING btree (a, b) + public | index_test_hash | index_test_hash_index_a_b_partial | | CREATE UNIQUE INDEX index_test_hash_index_a_b_partial ON public.index_test_hash USING btree (a, b) WHERE (c IS NOT NULL) + public | index_test_range | index_test_range_index_a | | CREATE UNIQUE INDEX index_test_range_index_a ON public.index_test_range USING btree (a) + public | index_test_range | index_test_range_index_a_b | | CREATE UNIQUE INDEX index_test_range_index_a_b ON public.index_test_range USING btree (a, b) + public | index_test_range | index_test_range_index_a_b_partial | | CREATE UNIQUE INDEX index_test_range_index_a_b_partial ON public.index_test_range USING btree (a, b) WHERE (c IS NOT NULL) + public | lineitem | lineitem_colref_index | | CREATE INDEX lineitem_colref_index ON public.lineitem USING btree (record_ne(lineitem.*, NULL::record)) + public | lineitem | lineitem_concurrently_index | | CREATE INDEX lineitem_concurrently_index ON public.lineitem USING btree (l_orderkey) + public | lineitem | lineitem_orderkey_hash_index | | CREATE INDEX lineitem_orderkey_hash_index ON public.lineitem USING hash (l_partkey) + public | lineitem | lineitem_orderkey_index | | CREATE INDEX lineitem_orderkey_index ON public.lineitem USING btree (l_orderkey) + public | lineitem | lineitem_orderkey_index_new | | CREATE INDEX lineitem_orderkey_index_new ON public.lineitem USING btree (l_orderkey) + public | lineitem | lineitem_partial_index | | CREATE INDEX lineitem_partial_index ON public.lineitem USING btree (l_shipdate) WHERE (l_shipdate < '01-01-1995'::date) + public | lineitem | lineitem_partkey_desc_index | | CREATE INDEX lineitem_partkey_desc_index ON public.lineitem USING btree (l_partkey DESC) + public | lineitem | lineitem_pkey | | CREATE UNIQUE INDEX lineitem_pkey ON public.lineitem USING btree (l_orderkey, l_linenumber) + public | lineitem | lineitem_time_index | | CREATE INDEX lineitem_time_index ON public.lineitem USING btree (l_shipdate) +(15 rows) + +\c - - - :worker_1_port +SELECT count(*) FROM pg_indexes WHERE tablename = (SELECT relname FROM pg_class WHERE relname LIKE 'lineitem%' ORDER BY relname LIMIT 1); + count +------- + 9 +(1 row) + +SELECT count(*) FROM pg_indexes WHERE tablename LIKE 'index_test_hash%'; + count +------- + 24 +(1 row) + +SELECT count(*) FROM pg_indexes WHERE tablename LIKE 'index_test_range%'; + count +------- + 6 +(1 row) + +SELECT count(*) FROM pg_indexes WHERE tablename LIKE 'index_test_append%'; + count +------- + 0 +(1 row) + +\c - - - :master_port +-- Verify that we error out on unsupported statement types +CREATE UNIQUE INDEX try_index ON lineitem (l_orderkey); +ERROR: creating unique indexes on append-partitioned tables is currently unsupported +CREATE INDEX try_index ON lineitem (l_orderkey) TABLESPACE newtablespace; +ERROR: specifying tablespaces with CREATE INDEX statements is currently unsupported +CREATE UNIQUE INDEX try_unique_range_index ON index_test_range(b); +ERROR: creating unique indexes on non-partition columns is currently unsupported +CREATE UNIQUE INDEX try_unique_range_index_partial ON index_test_range(b) WHERE c IS NOT NULL; +ERROR: creating unique indexes on non-partition columns is currently unsupported +CREATE UNIQUE INDEX try_unique_hash_index ON index_test_hash(b); +ERROR: creating unique indexes on non-partition columns is currently unsupported +CREATE UNIQUE INDEX try_unique_hash_index_partial ON index_test_hash(b) WHERE c IS NOT NULL; +ERROR: creating unique indexes on non-partition columns is currently unsupported +CREATE UNIQUE INDEX try_unique_append_index ON index_test_append(b); +ERROR: creating unique indexes on append-partitioned tables is currently unsupported +CREATE UNIQUE INDEX try_unique_append_index ON index_test_append(a); +ERROR: creating unique indexes on append-partitioned tables is currently unsupported +CREATE UNIQUE INDEX try_unique_append_index_a_b ON index_test_append(a,b); +ERROR: creating unique indexes on append-partitioned tables is currently unsupported +-- Verify that we error out in case of postgres errors on supported statement +-- types. +CREATE INDEX lineitem_orderkey_index ON lineitem (l_orderkey); +ERROR: relation "lineitem_orderkey_index" already exists +CREATE INDEX try_index ON lineitem USING gist (l_orderkey); +ERROR: data type bigint has no default operator class for access method "gist" +HINT: You must specify an operator class for the index or define a default operator class for the data type. +CREATE INDEX try_index ON lineitem (non_existent_column); +ERROR: column "non_existent_column" does not exist +CREATE INDEX ON lineitem (l_orderkey); +ERROR: creating index without a name on a distributed table is currently unsupported +-- Verify that none of failed indexes got created on the master node +SELECT * FROM pg_indexes WHERE tablename = 'lineitem' or tablename like 'index_test_%' ORDER BY indexname; + schemaname | tablename | indexname | tablespace | indexdef +------------+------------------+------------------------------------+------------+---------------------------------------------------------------------------------------------------------------------------- + public | index_test_hash | index_test_hash_index_a | | CREATE UNIQUE INDEX index_test_hash_index_a ON public.index_test_hash USING btree (a) + public | index_test_hash | index_test_hash_index_a_b | | CREATE UNIQUE INDEX index_test_hash_index_a_b ON public.index_test_hash USING btree (a, b) + public | index_test_hash | index_test_hash_index_a_b_partial | | CREATE UNIQUE INDEX index_test_hash_index_a_b_partial ON public.index_test_hash USING btree (a, b) WHERE (c IS NOT NULL) + public | index_test_range | index_test_range_index_a | | CREATE UNIQUE INDEX index_test_range_index_a ON public.index_test_range USING btree (a) + public | index_test_range | index_test_range_index_a_b | | CREATE UNIQUE INDEX index_test_range_index_a_b ON public.index_test_range USING btree (a, b) + public | index_test_range | index_test_range_index_a_b_partial | | CREATE UNIQUE INDEX index_test_range_index_a_b_partial ON public.index_test_range USING btree (a, b) WHERE (c IS NOT NULL) + public | lineitem | lineitem_colref_index | | CREATE INDEX lineitem_colref_index ON public.lineitem USING btree (record_ne(lineitem.*, NULL::record)) + public | lineitem | lineitem_concurrently_index | | CREATE INDEX lineitem_concurrently_index ON public.lineitem USING btree (l_orderkey) + public | lineitem | lineitem_orderkey_hash_index | | CREATE INDEX lineitem_orderkey_hash_index ON public.lineitem USING hash (l_partkey) + public | lineitem | lineitem_orderkey_index | | CREATE INDEX lineitem_orderkey_index ON public.lineitem USING btree (l_orderkey) + public | lineitem | lineitem_orderkey_index_new | | CREATE INDEX lineitem_orderkey_index_new ON public.lineitem USING btree (l_orderkey) + public | lineitem | lineitem_partial_index | | CREATE INDEX lineitem_partial_index ON public.lineitem USING btree (l_shipdate) WHERE (l_shipdate < '01-01-1995'::date) + public | lineitem | lineitem_partkey_desc_index | | CREATE INDEX lineitem_partkey_desc_index ON public.lineitem USING btree (l_partkey DESC) + public | lineitem | lineitem_pkey | | CREATE UNIQUE INDEX lineitem_pkey ON public.lineitem USING btree (l_orderkey, l_linenumber) + public | lineitem | lineitem_time_index | | CREATE INDEX lineitem_time_index ON public.lineitem USING btree (l_shipdate) +(15 rows) + +-- +-- DROP INDEX +-- +-- Verify that we can't drop multiple indexes in a single command +DROP INDEX lineitem_orderkey_index, lineitem_partial_index; +ERROR: cannot drop multiple distributed objects in a single command +HINT: Try dropping each object in a separate DROP command. +-- Verify that we can succesfully drop indexes +DROP INDEX lineitem_orderkey_index; +DROP INDEX lineitem_orderkey_index_new; +DROP INDEX lineitem_partkey_desc_index; +DROP INDEX lineitem_partial_index; +DROP INDEX lineitem_colref_index; +-- Verify that we handle if exists statements correctly +DROP INDEX non_existent_index; +ERROR: index "non_existent_index" does not exist +DROP INDEX IF EXISTS non_existent_index; +NOTICE: index "non_existent_index" does not exist, skipping +DROP INDEX IF EXISTS lineitem_orderkey_hash_index; +DROP INDEX lineitem_orderkey_hash_index; +ERROR: index "lineitem_orderkey_hash_index" does not exist +DROP INDEX index_test_range_index_a; +DROP INDEX index_test_range_index_a_b; +DROP INDEX index_test_range_index_a_b_partial; +DROP INDEX index_test_hash_index_a; +DROP INDEX index_test_hash_index_a_b; +DROP INDEX index_test_hash_index_a_b_partial; +-- Verify that we can drop indexes concurrently +DROP INDEX CONCURRENTLY lineitem_concurrently_index; +-- Verify that all the indexes are dropped from the master and one worker node. +-- As there's a primary key, so exclude those from this check. +SELECT indrelid::regclass, indexrelid::regclass FROM pg_index WHERE indrelid = (SELECT relname FROM pg_class WHERE relname LIKE 'lineitem%' ORDER BY relname LIMIT 1)::regclass AND NOT indisprimary AND indexrelid::regclass::text NOT LIKE 'lineitem_time_index%'; + indrelid | indexrelid +----------+------------ +(0 rows) + +SELECT * FROM pg_indexes WHERE tablename LIKE 'index_test_%' ORDER BY indexname; + schemaname | tablename | indexname | tablespace | indexdef +------------+-----------+-----------+------------+---------- +(0 rows) + +\c - - - :worker_1_port +SELECT indrelid::regclass, indexrelid::regclass FROM pg_index WHERE indrelid = (SELECT relname FROM pg_class WHERE relname LIKE 'lineitem%' ORDER BY relname LIMIT 1)::regclass AND NOT indisprimary AND indexrelid::regclass::text NOT LIKE 'lineitem_time_index%'; + indrelid | indexrelid +----------+------------ +(0 rows) + +SELECT * FROM pg_indexes WHERE tablename LIKE 'index_test_%' ORDER BY indexname; + schemaname | tablename | indexname | tablespace | indexdef +------------+-----------+-----------+------------+---------- +(0 rows) + +-- create index that will conflict with master operations +CREATE INDEX CONCURRENTLY ith_b_idx_102089 ON index_test_hash_102089(b); +\c - - - :master_port +-- should fail because worker index already exists +CREATE INDEX CONCURRENTLY ith_b_idx ON index_test_hash(b); +ERROR: CONCURRENTLY-enabled index command failed +DETAIL: CONCURRENTLY-enabled index commands can fail partially, leaving behind an INVALID index. +HINT: Use DROP INDEX CONCURRENTLY IF EXISTS to remove the invalid index, then retry the original command. +-- the failure results in an INVALID index +SELECT indisvalid AS "Index Valid?" FROM pg_index WHERE indexrelid='ith_b_idx'::regclass; + Index Valid? +-------------- + f +(1 row) + +-- we can clean it up and recreate with an DROP IF EXISTS +DROP INDEX CONCURRENTLY IF EXISTS ith_b_idx; +CREATE INDEX CONCURRENTLY ith_b_idx ON index_test_hash(b); +SELECT indisvalid AS "Index Valid?" FROM pg_index WHERE indexrelid='ith_b_idx'::regclass; + Index Valid? +-------------- + t +(1 row) + +\c - - - :worker_1_port +-- now drop shard index to test partial master DROP failure +DROP INDEX CONCURRENTLY ith_b_idx_102089; +\c - - - :master_port +DROP INDEX CONCURRENTLY ith_b_idx; +ERROR: CONCURRENTLY-enabled index command failed +DETAIL: CONCURRENTLY-enabled index commands can fail partially, leaving behind an INVALID index. +HINT: Use DROP INDEX CONCURRENTLY IF EXISTS to remove the invalid index, then retry the original command. +-- the failure results in an INVALID index +SELECT indisvalid AS "Index Valid?" FROM pg_index WHERE indexrelid='ith_b_idx'::regclass; + Index Valid? +-------------- + f +(1 row) + +-- final clean up +DROP INDEX CONCURRENTLY IF EXISTS ith_b_idx; +-- Drop created tables +DROP TABLE index_test_range; +DROP TABLE index_test_hash; +DROP TABLE index_test_append; diff --git a/src/test/regress/sql/multi_index_statements.sql b/src/test/regress/sql/multi_index_statements.sql index a656b0198..89fb7bc54 100644 --- a/src/test/regress/sql/multi_index_statements.sql +++ b/src/test/regress/sql/multi_index_statements.sql @@ -5,6 +5,9 @@ -- Check that we can run CREATE INDEX and DROP INDEX statements on distributed -- tables. +SHOW server_version \gset +SELECT substring(:'server_version', '\d+')::int AS major_version; + -- -- CREATE TEST TABLES -- @@ -49,6 +52,7 @@ CREATE UNIQUE INDEX index_test_hash_index_a ON index_test_hash(a); CREATE UNIQUE INDEX index_test_hash_index_a_b ON index_test_hash(a,b); CREATE UNIQUE INDEX index_test_hash_index_a_b_partial ON index_test_hash(a,b) WHERE c IS NOT NULL; CREATE UNIQUE INDEX index_test_range_index_a_b_partial ON index_test_range(a,b) WHERE c IS NOT NULL; +CREATE UNIQUE INDEX index_test_hash_index_a_b_c ON index_test_hash(a) INCLUDE (b,c); RESET client_min_messages; -- Verify that we handle if not exists statements correctly