diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 374e2d0efe..7de36ca7e2 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -550,6 +550,15 @@ DefineIndex(Oid relationId,
lockmode = stmt->concurrent ? ShareUpdateExclusiveLock : ShareLock;
rel = table_open(relationId, lockmode);
+ /*
+ * Ignore concurrent index creation for temporary tables. Such
+ * relations only work with the current session, so they are not
+ * subject to concurrency problems. Using a non-concurrent build
+ * is also more performant.
+ */
+ if (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
+ stmt->concurrent = false;
+
namespaceId = RelationGetNamespace(rel);
/* Ensure that it makes sense to index this kind of relation */
@@ -2349,7 +2358,12 @@ ReindexIndex(RangeVar *indexRelation, int options, bool concurrent)
persistence = irel->rd_rel->relpersistence;
index_close(irel, NoLock);
- if (concurrent)
+ /*
+ * For temporary indexes, ignore concurrent reindexes. Such relations
+ * only work with the session assigned to them, so they are not subject
+ * to concurrent concerns, and a non-concurrent reindex is more efficient.
+ */
+ if (concurrent && persistence != RELPERSISTENCE_TEMP)
ReindexRelationConcurrently(indOid, options);
else
reindex_index(indOid, false, persistence,
@@ -2442,7 +2456,12 @@ ReindexTable(RangeVar *relation, int options, bool concurrent)
0,
RangeVarCallbackOwnsTable, NULL);
- if (concurrent)
+ /*
+ * For temporary tables, ignore concurrent reindexes. Such relations
+ * only work with the session assigned to them, so they are not subject
+ * to concurrent concerns, and a non-concurrent reindex is more efficient.
+ */
+ if (concurrent && get_rel_persistence(heapOid) != RELPERSISTENCE_TEMP)
{
result = ReindexRelationConcurrently(heapOid, options);
@@ -2648,7 +2667,14 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind,
/* functions in indexes may want a snapshot set */
PushActiveSnapshot(GetTransactionSnapshot());
- if (concurrent)
+ /*
+ * For temporary relations, ignore concurrent reindexes. Such
+ * relations only work with the session assigned to them, so they
+ * are not subject to concurrent concerns, and a non-concurrent
+ * reindex is more efficient.
+ */
+ if (concurrent &&
+ get_rel_persistence(relid) != RELPERSISTENCE_TEMP)
{
(void) ReindexRelationConcurrently(relid, options);
/* ReindexRelationConcurrently() does the verbose output */
@@ -2771,6 +2797,9 @@ ReindexRelationConcurrently(Oid relationOid, int options)
/* Open relation to get its indexes */
heapRelation = table_open(relationOid, ShareUpdateExclusiveLock);
+ /* Temporary tables are not processed concurrently */
+ Assert(heapRelation->rd_rel->relpersistence != RELPERSISTENCE_TEMP);
+
/* Add all the valid indexes of relation to list */
foreach(lc, RelationGetIndexList(heapRelation))
{
@@ -2864,6 +2893,9 @@ ReindexRelationConcurrently(Oid relationOid, int options)
/* Save the list of relation OIDs in private context */
oldcontext = MemoryContextSwitchTo(private_context);
+ /* Temporary tables are not processed concurrently */
+ Assert(get_rel_persistence(heapId) != RELPERSISTENCE_TEMP);
+
/* Track the heap relation of this index for session locks */
heapRelationIds = list_make1_oid(heapId);
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 1cdb7a9663..112188862b 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -1398,6 +1398,17 @@ Indexes:
"concur_index5" btree (f2) WHERE f1 = 'x'::text
"std_index" btree (f2)
+-- Temporary tables with concurrent builds
+CREATE TEMP TABLE concur_temp (f1 int, f2 text);
+INSERT INTO concur_temp VALUES (1, 'foo'), (2, 'bar');
+CREATE INDEX CONCURRENTLY concur_temp_ind ON concur_temp(f1);
+DROP TABLE concur_temp;
+-- On-commit actions
+CREATE TEMP TABLE concur_temp (f1 int, f2 text)
+ ON COMMIT DELETE ROWS;
+INSERT INTO concur_temp VALUES (1, 'foo'), (2, 'bar');
+CREATE INDEX CONCURRENTLY concur_temp_ind ON concur_temp(f1);
+DROP TABLE concur_temp;
--
-- Try some concurrent index drops
--
@@ -2368,6 +2379,43 @@ SELECT pg_get_indexdef('concur_exprs_index_pred_2'::regclass);
(1 row)
DROP TABLE concur_exprs_tab;
+-- Temporary tables, where CONCURRENTLY is ignored.
+CREATE TEMP TABLE concur_temp_tab_1 (c1 int, c2 text);
+INSERT INTO concur_temp_tab_1 VALUES (1, 'foo'), (2, 'bar');
+CREATE INDEX concur_temp_ind_1 ON concur_temp_tab_1(c2);
+REINDEX TABLE CONCURRENTLY concur_temp_tab_1;
+REINDEX INDEX CONCURRENTLY concur_temp_ind_1;
+-- Still fails in transaction blocks
+BEGIN;
+REINDEX INDEX CONCURRENTLY concur_temp_ind_1;
+ERROR: REINDEX CONCURRENTLY cannot run inside a transaction block
+COMMIT;
+-- On-commit actions. PRESERVE ROWS is the default, tested above.
+CREATE TEMP TABLE concur_temp_tab_2 (c1 int, c2 text)
+ ON COMMIT DELETE ROWS;
+CREATE INDEX concur_temp_ind_2 ON concur_temp_tab_2(c2);
+REINDEX TABLE CONCURRENTLY concur_temp_tab_2;
+REINDEX INDEX CONCURRENTLY concur_temp_ind_2;
+-- REINDEX SCHEMA processes all temporary relations
+CREATE TABLE reindex_temp_before AS
+SELECT oid, relname, relfilenode, relkind, reltoastrelid
+ FROM pg_class
+ WHERE relname IN ('concur_temp_ind_1', 'concur_temp_ind_2');
+SELECT pg_my_temp_schema()::regnamespace as temp_schema_name \gset
+REINDEX SCHEMA :temp_schema_name;
+SELECT b.relname,
+ b.relkind,
+ CASE WHEN a.relfilenode = b.relfilenode THEN 'relfilenode is unchanged'
+ ELSE 'relfilenode has changed' END
+ FROM reindex_temp_before b JOIN pg_class a ON b.oid = a.oid
+ ORDER BY 1;
+ relname | relkind | case
+-------------------+---------+-------------------------
+ concur_temp_ind_1 | i | relfilenode has changed
+ concur_temp_ind_2 | i | relfilenode has changed
+(2 rows)
+
+DROP TABLE concur_temp_tab_1, concur_temp_tab_2, reindex_temp_before;
--
-- REINDEX SCHEMA
--
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index 76598085f7..94764b832a 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -489,6 +489,18 @@ VACUUM FULL concur_heap;
REINDEX TABLE concur_heap;
\d concur_heap
+-- Temporary tables with concurrent builds
+CREATE TEMP TABLE concur_temp (f1 int, f2 text);
+INSERT INTO concur_temp VALUES (1, 'foo'), (2, 'bar');
+CREATE INDEX CONCURRENTLY concur_temp_ind ON concur_temp(f1);
+DROP TABLE concur_temp;
+-- On-commit actions
+CREATE TEMP TABLE concur_temp (f1 int, f2 text)
+ ON COMMIT DELETE ROWS;
+INSERT INTO concur_temp VALUES (1, 'foo'), (2, 'bar');
+CREATE INDEX CONCURRENTLY concur_temp_ind ON concur_temp(f1);
+DROP TABLE concur_temp;
+
--
-- Try some concurrent index drops
--
@@ -954,6 +966,37 @@ SELECT pg_get_indexdef('concur_exprs_index_pred'::regclass);
SELECT pg_get_indexdef('concur_exprs_index_pred_2'::regclass);
DROP TABLE concur_exprs_tab;
+-- Temporary tables, where CONCURRENTLY is ignored.
+CREATE TEMP TABLE concur_temp_tab_1 (c1 int, c2 text);
+INSERT INTO concur_temp_tab_1 VALUES (1, 'foo'), (2, 'bar');
+CREATE INDEX concur_temp_ind_1 ON concur_temp_tab_1(c2);
+REINDEX TABLE CONCURRENTLY concur_temp_tab_1;
+REINDEX INDEX CONCURRENTLY concur_temp_ind_1;
+-- Still fails in transaction blocks
+BEGIN;
+REINDEX INDEX CONCURRENTLY concur_temp_ind_1;
+COMMIT;
+-- On-commit actions. PRESERVE ROWS is the default, tested above.
+CREATE TEMP TABLE concur_temp_tab_2 (c1 int, c2 text)
+ ON COMMIT DELETE ROWS;
+CREATE INDEX concur_temp_ind_2 ON concur_temp_tab_2(c2);
+REINDEX TABLE CONCURRENTLY concur_temp_tab_2;
+REINDEX INDEX CONCURRENTLY concur_temp_ind_2;
+-- REINDEX SCHEMA processes all temporary relations
+CREATE TABLE reindex_temp_before AS
+SELECT oid, relname, relfilenode, relkind, reltoastrelid
+ FROM pg_class
+ WHERE relname IN ('concur_temp_ind_1', 'concur_temp_ind_2');
+SELECT pg_my_temp_schema()::regnamespace as temp_schema_name \gset
+REINDEX SCHEMA :temp_schema_name;
+SELECT b.relname,
+ b.relkind,
+ CASE WHEN a.relfilenode = b.relfilenode THEN 'relfilenode is unchanged'
+ ELSE 'relfilenode has changed' END
+ FROM reindex_temp_before b JOIN pg_class a ON b.oid = a.oid
+ ORDER BY 1;
+DROP TABLE concur_temp_tab_1, concur_temp_tab_2, reindex_temp_before;
+
--
-- REINDEX SCHEMA
--
diff --git a/doc/src/sgml/ref/create_index.sgml b/doc/src/sgml/ref/create_index.sgml
index 629a31ef79..e26f450846 100644
--- a/doc/src/sgml/ref/create_index.sgml
+++ b/doc/src/sgml/ref/create_index.sgml
@@ -129,6 +129,9 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] .
+
+ This option is ignored for temporary relations.
+
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index 10881ab03a..e5d2b1a06e 100644
--- a/doc/src/sgml/ref/reindex.sgml
+++ b/doc/src/sgml/ref/reindex.sgml
@@ -162,6 +162,9 @@ REINDEX [ ( VERBOSE ) ] { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } [ CONCURR
— see .
+
+ This option is ignored for temporary relations.
+