summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/ref/create_index.sgml5
-rw-r--r--doc/src/sgml/ref/drop_index.sgml5
-rw-r--r--src/backend/catalog/index.c9
-rw-r--r--src/backend/commands/indexcmds.c27
-rw-r--r--src/backend/commands/tablecmds.c18
-rw-r--r--src/test/regress/expected/create_index.out25
-rw-r--r--src/test/regress/sql/create_index.sql25
7 files changed, 106 insertions, 8 deletions
diff --git a/doc/src/sgml/ref/create_index.sgml b/doc/src/sgml/ref/create_index.sgml
index e9f47c44145..da8acfaf9a6 100644
--- a/doc/src/sgml/ref/create_index.sgml
+++ b/doc/src/sgml/ref/create_index.sgml
@@ -123,6 +123,11 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] <replaceable class=
&mdash; see <xref linkend="SQL-CREATEINDEX-CONCURRENTLY"
endterm="SQL-CREATEINDEX-CONCURRENTLY-title">.
</para>
+ <para>
+ For temporary tables, <command>CREATE INDEX</command> is always
+ non-concurrent, as no other session can access them, and
+ non-concurrent index creation is cheaper.
+ </para>
</listitem>
</varlistentry>
diff --git a/doc/src/sgml/ref/drop_index.sgml b/doc/src/sgml/ref/drop_index.sgml
index 6fe108ded25..4c0c48ab1ea 100644
--- a/doc/src/sgml/ref/drop_index.sgml
+++ b/doc/src/sgml/ref/drop_index.sgml
@@ -58,6 +58,11 @@ DROP INDEX [ CONCURRENTLY ] [ IF EXISTS ] <replaceable class="PARAMETER">name</r
performed within a transaction block, but
<command>DROP INDEX CONCURRENTLY</> cannot.
</para>
+ <para>
+ For temporary tables, <command>DROP INDEX</command> is always
+ non-concurrent, as no other session can access them, and
+ non-concurrent index drop is cheaper.
+ </para>
</listitem>
</varlistentry>
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 9386485db23..4e901c39a67 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -1362,6 +1362,15 @@ index_drop(Oid indexId, bool concurrent)
LOCKMODE lockmode;
/*
+ * A temporary relation uses a non-concurrent DROP. Other backends can't
+ * access a temporary relation, so there's no harm in grabbing a stronger
+ * lock (see comments in RemoveRelations), and a non-concurrent DROP is
+ * more efficient.
+ */
+ Assert(get_rel_persistence(indexId) != RELPERSISTENCE_TEMP ||
+ !concurrent);
+
+ /*
* To drop an index safely, we must grab exclusive lock on its parent
* table. Exclusive lock on the index alone is insufficient because
* another backend might be about to execute a query on the parent table.
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 756d30c2770..71a76159cd9 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -310,6 +310,7 @@ DefineIndex(Oid relationId,
bool skip_build,
bool quiet)
{
+ bool concurrent;
char *indexRelationName;
char *accessMethodName;
Oid *typeObjectId;
@@ -341,6 +342,18 @@ DefineIndex(Oid relationId,
int i;
/*
+ * Force non-concurrent build on temporary relations, even if CONCURRENTLY
+ * was requested. Other backends can't access a temporary relation, so
+ * there's no harm in grabbing a stronger lock, and a non-concurrent DROP
+ * is more efficient. Do this before any use of the concurrent option is
+ * done.
+ */
+ if (stmt->concurrent && get_rel_persistence(relationId) != RELPERSISTENCE_TEMP)
+ concurrent = true;
+ else
+ concurrent = false;
+
+ /*
* count attributes in index
*/
numberOfAttributes = list_length(stmt->indexParams);
@@ -365,7 +378,7 @@ DefineIndex(Oid relationId,
* relation. To avoid lock upgrade hazards, that lock should be at least
* as strong as the one we take here.
*/
- lockmode = stmt->concurrent ? ShareUpdateExclusiveLock : ShareLock;
+ lockmode = concurrent ? ShareUpdateExclusiveLock : ShareLock;
rel = heap_open(relationId, lockmode);
relationId = RelationGetRelid(rel);
@@ -557,8 +570,8 @@ DefineIndex(Oid relationId,
indexInfo->ii_ExclusionStrats = NULL;
indexInfo->ii_Unique = stmt->unique;
/* In a concurrent build, mark it not-ready-for-inserts */
- indexInfo->ii_ReadyForInserts = !stmt->concurrent;
- indexInfo->ii_Concurrent = stmt->concurrent;
+ indexInfo->ii_ReadyForInserts = !concurrent;
+ indexInfo->ii_Concurrent = concurrent;
indexInfo->ii_BrokenHotChain = false;
typeObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
@@ -644,7 +657,7 @@ DefineIndex(Oid relationId,
* A valid stmt->oldNode implies that we already have a built form of the
* index. The caller should also decline any index build.
*/
- Assert(!OidIsValid(stmt->oldNode) || (skip_build && !stmt->concurrent));
+ Assert(!OidIsValid(stmt->oldNode) || (skip_build && !concurrent));
/*
* Make the catalog entries for the index, including constraints. Then, if
@@ -658,8 +671,8 @@ DefineIndex(Oid relationId,
coloptions, reloptions, stmt->primary,
stmt->isconstraint, stmt->deferrable, stmt->initdeferred,
allowSystemTableMods,
- skip_build || stmt->concurrent,
- stmt->concurrent, !check_rights,
+ skip_build || concurrent,
+ concurrent, !check_rights,
stmt->if_not_exists);
ObjectAddressSet(address, RelationRelationId, indexRelationId);
@@ -675,7 +688,7 @@ DefineIndex(Oid relationId,
CreateComments(indexRelationId, RelationRelationId, 0,
stmt->idxcomment);
- if (!stmt->concurrent)
+ if (!concurrent)
{
/* Close the heap and we're done, in the non-concurrent case */
heap_close(rel, NoLock);
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index d0f2f7c8eb9..9c6ca7ff9c7 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -816,7 +816,11 @@ RemoveRelations(DropStmt *drop)
/* DROP CONCURRENTLY uses a weaker lock, and has some restrictions */
if (drop->concurrent)
{
- flags |= PERFORM_DELETION_CONCURRENTLY;
+ /*
+ * Note that for temporary relations this lock may get upgraded
+ * later on, but as no other session can access a temporary
+ * relation, this is actually fine.
+ */
lockmode = ShareUpdateExclusiveLock;
Assert(drop->removeType == OBJECT_INDEX);
if (list_length(drop->objects) != 1)
@@ -907,6 +911,18 @@ RemoveRelations(DropStmt *drop)
continue;
}
+ /*
+ * Decide if concurrent mode needs to be used here or not. The
+ * relation persistence cannot be known without its OID.
+ */
+ if (drop->concurrent &&
+ get_rel_persistence(relOid) != RELPERSISTENCE_TEMP)
+ {
+ Assert(list_length(drop->objects) == 1 &&
+ drop->removeType == OBJECT_INDEX);
+ flags |= PERFORM_DELETION_CONCURRENTLY;
+ }
+
/* OK, we're ready to delete this one */
obj.classId = RelationRelationId;
obj.objectId = relOid;
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 1db29f81e46..66be26735d7 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2519,6 +2519,31 @@ Indexes:
"concur_index5" btree (f2) WHERE f1 = 'x'::text
"std_index" btree (f2)
+-- Temporary tables with concurrent builds and on-commit actions
+-- CONCURRENTLY used with CREATE INDEX and DROP INDEX is ignored.
+-- PRESERVE ROWS, the default.
+CREATE TEMP TABLE concur_temp (f1 int, f2 text)
+ ON COMMIT PRESERVE ROWS;
+INSERT INTO concur_temp VALUES (1, 'foo'), (2, 'bar');
+CREATE INDEX CONCURRENTLY concur_temp_ind ON concur_temp(f1);
+DROP INDEX CONCURRENTLY concur_temp_ind;
+DROP TABLE concur_temp;
+-- ON COMMIT DROP
+BEGIN;
+CREATE TEMP TABLE concur_temp (f1 int, f2 text)
+ ON COMMIT DROP;
+INSERT INTO concur_temp VALUES (1, 'foo'), (2, 'bar');
+-- Fails when running in a transaction.
+CREATE INDEX CONCURRENTLY concur_temp_ind ON concur_temp(f1);
+ERROR: CREATE INDEX CONCURRENTLY cannot run inside a transaction block
+COMMIT;
+-- ON COMMIT DELETE ROWS
+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 INDEX CONCURRENTLY concur_temp_ind;
+DROP TABLE concur_temp;
--
-- Try some concurrent index drops
--
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index 74bb3665965..73763327aca 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -795,6 +795,31 @@ VACUUM FULL concur_heap;
REINDEX TABLE concur_heap;
\d concur_heap
+-- Temporary tables with concurrent builds and on-commit actions
+-- CONCURRENTLY used with CREATE INDEX and DROP INDEX is ignored.
+-- PRESERVE ROWS, the default.
+CREATE TEMP TABLE concur_temp (f1 int, f2 text)
+ ON COMMIT PRESERVE ROWS;
+INSERT INTO concur_temp VALUES (1, 'foo'), (2, 'bar');
+CREATE INDEX CONCURRENTLY concur_temp_ind ON concur_temp(f1);
+DROP INDEX CONCURRENTLY concur_temp_ind;
+DROP TABLE concur_temp;
+-- ON COMMIT DROP
+BEGIN;
+CREATE TEMP TABLE concur_temp (f1 int, f2 text)
+ ON COMMIT DROP;
+INSERT INTO concur_temp VALUES (1, 'foo'), (2, 'bar');
+-- Fails when running in a transaction.
+CREATE INDEX CONCURRENTLY concur_temp_ind ON concur_temp(f1);
+COMMIT;
+-- ON COMMIT DELETE ROWS
+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 INDEX CONCURRENTLY concur_temp_ind;
+DROP TABLE concur_temp;
+
--
-- Try some concurrent index drops
--