Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions _codeql_detected_source_root
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same also happened to me - I wonder why copilot keep posting this file to the PRs

36 changes: 35 additions & 1 deletion src/backend/distributed/commands/index.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "catalog/index.h"
#include "catalog/namespace.h"
#include "catalog/pg_class.h"
#include "catalog/pg_index.h"
#include "catalog/pg_namespace.h"
#include "commands/defrem.h"
#include "commands/tablecmds.h"
Expand Down Expand Up @@ -853,8 +854,41 @@ PostprocessIndexStmt(Node *node, const char *queryString)

PushActiveSnapshot(GetTransactionSnapshot());

/*
* If IF NOT EXISTS was used and the index already exists (is valid),
* skip invalidating it to prevent invalidating pre-existing indexes.
*/
bool index_was_already_valid = false;
if (indexStmt->if_not_exists)
{
/*
* Check the current validity state of the index. If it's already valid,
* it means the index existed before this command and PostgreSQL skipped
* creation. We should not invalidate it in this case.
*
* Note: SearchSysCache1 returns NULL if the index doesn't exist in the
* catalog yet, indicating it was just created. HeapTupleIsValid handles
* this case by returning false.
*/
HeapTuple indexTuple = SearchSysCache1(INDEXRELID,
ObjectIdGetDatum(indexRelationId));
if (HeapTupleIsValid(indexTuple))
{
Form_pg_index indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
if (indexForm->indisvalid)
{
/* Index was already valid, so it existed before this command */
index_was_already_valid = true;
}
ReleaseSysCache(indexTuple);
}
}

/* mark index as invalid, in-place (cannot be rolled back) */
index_set_state_flags(indexRelationId, INDEX_DROP_CLEAR_VALID);
if (!index_was_already_valid)
{
index_set_state_flags(indexRelationId, INDEX_DROP_CLEAR_VALID);
}
PopActiveSnapshot();

/* re-open a transaction command from here on out */
Expand Down
19 changes: 19 additions & 0 deletions src/test/regress/expected/multi_index_statements.out
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,25 @@ CREATE INDEX lineitem_orderkey_index on public.nation(n_nationkey);
ERROR: relation "lineitem_orderkey_index" already exists
CREATE INDEX IF NOT EXISTS lineitem_orderkey_index on public.nation(n_nationkey);
NOTICE: relation "lineitem_orderkey_index" already exists, skipping
-- Verify that CREATE INDEX CONCURRENTLY IF NOT EXISTS doesn't invalidate existing index
CREATE INDEX CONCURRENTLY lineitem_concurrent_if_not_exists_test ON public.lineitem (l_partkey);
-- Verify the index is valid
SELECT indisvalid FROM pg_index WHERE indexrelid = 'public.lineitem_concurrent_if_not_exists_test'::regclass;
indisvalid
---------------------------------------------------------------------
t
(1 row)

-- Run the same command again with IF NOT EXISTS
CREATE INDEX CONCURRENTLY IF NOT EXISTS lineitem_concurrent_if_not_exists_test ON public.lineitem (l_partkey);
NOTICE: relation "lineitem_concurrent_if_not_exists_test" already exists, skipping
-- Verify the index is still valid (not invalidated)
SELECT indisvalid FROM pg_index WHERE indexrelid = 'public.lineitem_concurrent_if_not_exists_test'::regclass;
indisvalid
---------------------------------------------------------------------
t
(1 row)

-- Verify that we can create indexes concurrently
CREATE INDEX CONCURRENTLY lineitem_concurrently_index ON public.lineitem (l_orderkey);
-- Verify that no-name local CREATE INDEX CONCURRENTLY works
Expand Down
9 changes: 9 additions & 0 deletions src/test/regress/sql/multi_index_statements.sql
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ CREATE INDEX IF NOT EXISTS lineitem_orderkey_index_new on public.lineitem(l_orde
CREATE INDEX lineitem_orderkey_index on public.nation(n_nationkey);
CREATE INDEX IF NOT EXISTS lineitem_orderkey_index on public.nation(n_nationkey);

-- Verify that CREATE INDEX CONCURRENTLY IF NOT EXISTS doesn't invalidate existing index
CREATE INDEX CONCURRENTLY lineitem_concurrent_if_not_exists_test ON public.lineitem (l_partkey);
-- Verify the index is valid
SELECT indisvalid FROM pg_index WHERE indexrelid = 'public.lineitem_concurrent_if_not_exists_test'::regclass;
-- Run the same command again with IF NOT EXISTS
CREATE INDEX CONCURRENTLY IF NOT EXISTS lineitem_concurrent_if_not_exists_test ON public.lineitem (l_partkey);
-- Verify the index is still valid (not invalidated)
SELECT indisvalid FROM pg_index WHERE indexrelid = 'public.lineitem_concurrent_if_not_exists_test'::regclass;

-- Verify that we can create indexes concurrently
CREATE INDEX CONCURRENTLY lineitem_concurrently_index ON public.lineitem (l_orderkey);

Expand Down