Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
8cb53654
Commit
8cb53654
authored
Apr 06, 2012
by
Simon Riggs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add DROP INDEX CONCURRENTLY [IF EXISTS], uses ShareUpdateExclusiveLock
parent
21cc5296
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
337 additions
and
26 deletions
+337
-26
doc/src/sgml/ref/drop_index.sgml
doc/src/sgml/ref/drop_index.sgml
+24
-1
src/backend/catalog/dependency.c
src/backend/catalog/dependency.c
+32
-13
src/backend/catalog/index.c
src/backend/catalog/index.c
+133
-6
src/backend/commands/tablecmds.c
src/backend/commands/tablecmds.c
+37
-4
src/backend/nodes/copyfuncs.c
src/backend/nodes/copyfuncs.c
+1
-0
src/backend/nodes/equalfuncs.c
src/backend/nodes/equalfuncs.c
+1
-0
src/backend/parser/gram.y
src/backend/parser/gram.y
+45
-0
src/backend/tcop/utility.c
src/backend/tcop/utility.c
+6
-1
src/backend/utils/cache/relcache.c
src/backend/utils/cache/relcache.c
+6
-0
src/include/catalog/dependency.h
src/include/catalog/dependency.h
+1
-0
src/include/catalog/index.h
src/include/catalog/index.h
+1
-1
src/include/nodes/parsenodes.h
src/include/nodes/parsenodes.h
+1
-0
src/test/regress/expected/create_index.out
src/test/regress/expected/create_index.out
+28
-0
src/test/regress/sql/create_index.sql
src/test/regress/sql/create_index.sql
+21
-0
No files found.
doc/src/sgml/ref/drop_index.sgml
View file @
8cb53654
...
@@ -21,7 +21,7 @@ PostgreSQL documentation
...
@@ -21,7 +21,7 @@ PostgreSQL documentation
<refsynopsisdiv>
<refsynopsisdiv>
<synopsis>
<synopsis>
DROP INDEX [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> [, ...] [ CASCADE | RESTRICT ]
DROP INDEX [
CONCURRENTLY ] [
IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> [, ...] [ CASCADE | RESTRICT ]
</synopsis>
</synopsis>
</refsynopsisdiv>
</refsynopsisdiv>
...
@@ -49,6 +49,29 @@ DROP INDEX [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> [, ..
...
@@ -49,6 +49,29 @@ DROP INDEX [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> [, ..
</listitem>
</listitem>
</varlistentry>
</varlistentry>
<varlistentry>
<term><literal>CONCURRENTLY</literal></term>
<listitem>
<para>
When this option is used, <productname>PostgreSQL</> will drop the
index without taking any locks that prevent concurrent selects, inserts,
updates, or deletes on the table; whereas a standard index drop
waits for a lock that locks out everything on the table until it's done.
Concurrent drop index is a two stage process. First, we mark the index
both invalid and not ready then commit the change. Next we wait until
there are no users locking the table who can see the index.
</para>
<para>
There are several caveats to be aware of when using this option.
Only one index name can be specified if the <literal>CONCURRENTLY</literal>
parameter is specified. Regular <command>DROP INDEX</> command can be
performed within a transaction block, but
<command>DROP INDEX CONCURRENTLY</> cannot.
The CASCADE option is not supported when dropping an index concurrently.
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry>
<term><replaceable class="PARAMETER">name</replaceable></term>
<term><replaceable class="PARAMETER">name</replaceable></term>
<listitem>
<listitem>
...
...
src/backend/catalog/dependency.c
View file @
8cb53654
...
@@ -174,8 +174,8 @@ static void reportDependentObjects(const ObjectAddresses *targetObjects,
...
@@ -174,8 +174,8 @@ static void reportDependentObjects(const ObjectAddresses *targetObjects,
const
ObjectAddress
*
origObject
);
const
ObjectAddress
*
origObject
);
static
void
deleteOneObject
(
const
ObjectAddress
*
object
,
static
void
deleteOneObject
(
const
ObjectAddress
*
object
,
Relation
depRel
,
int32
flags
);
Relation
depRel
,
int32
flags
);
static
void
doDeletion
(
const
ObjectAddress
*
object
);
static
void
doDeletion
(
const
ObjectAddress
*
object
,
int
flags
);
static
void
AcquireDeletionLock
(
const
ObjectAddress
*
object
);
static
void
AcquireDeletionLock
(
const
ObjectAddress
*
object
,
int
flags
);
static
void
ReleaseDeletionLock
(
const
ObjectAddress
*
object
);
static
void
ReleaseDeletionLock
(
const
ObjectAddress
*
object
);
static
bool
find_expr_references_walker
(
Node
*
node
,
static
bool
find_expr_references_walker
(
Node
*
node
,
find_expr_references_context
*
context
);
find_expr_references_context
*
context
);
...
@@ -233,7 +233,7 @@ performDeletion(const ObjectAddress *object,
...
@@ -233,7 +233,7 @@ performDeletion(const ObjectAddress *object,
* Acquire deletion lock on the target object. (Ideally the caller has
* Acquire deletion lock on the target object. (Ideally the caller has
* done this already, but many places are sloppy about it.)
* done this already, but many places are sloppy about it.)
*/
*/
AcquireDeletionLock
(
object
);
AcquireDeletionLock
(
object
,
0
);
/*
/*
* Construct a list of objects to delete (ie, the given object plus
* Construct a list of objects to delete (ie, the given object plus
...
@@ -317,7 +317,7 @@ performMultipleDeletions(const ObjectAddresses *objects,
...
@@ -317,7 +317,7 @@ performMultipleDeletions(const ObjectAddresses *objects,
* Acquire deletion lock on each target object. (Ideally the caller
* Acquire deletion lock on each target object. (Ideally the caller
* has done this already, but many places are sloppy about it.)
* has done this already, but many places are sloppy about it.)
*/
*/
AcquireDeletionLock
(
thisobj
);
AcquireDeletionLock
(
thisobj
,
flags
);
findDependentObjects
(
thisobj
,
findDependentObjects
(
thisobj
,
DEPFLAG_ORIGINAL
,
DEPFLAG_ORIGINAL
,
...
@@ -351,7 +351,11 @@ performMultipleDeletions(const ObjectAddresses *objects,
...
@@ -351,7 +351,11 @@ performMultipleDeletions(const ObjectAddresses *objects,
/* And clean up */
/* And clean up */
free_object_addresses
(
targetObjects
);
free_object_addresses
(
targetObjects
);
heap_close
(
depRel
,
RowExclusiveLock
);
/*
* We closed depRel earlier in deleteOneObject if doing a drop concurrently
*/
if
((
flags
&
PERFORM_DELETION_CONCURRENTLY
)
!=
PERFORM_DELETION_CONCURRENTLY
)
heap_close
(
depRel
,
RowExclusiveLock
);
}
}
/*
/*
...
@@ -381,7 +385,7 @@ deleteWhatDependsOn(const ObjectAddress *object,
...
@@ -381,7 +385,7 @@ deleteWhatDependsOn(const ObjectAddress *object,
* Acquire deletion lock on the target object. (Ideally the caller has
* Acquire deletion lock on the target object. (Ideally the caller has
* done this already, but many places are sloppy about it.)
* done this already, but many places are sloppy about it.)
*/
*/
AcquireDeletionLock
(
object
);
AcquireDeletionLock
(
object
,
0
);
/*
/*
* Construct a list of objects to delete (ie, the given object plus
* Construct a list of objects to delete (ie, the given object plus
...
@@ -631,7 +635,7 @@ findDependentObjects(const ObjectAddress *object,
...
@@ -631,7 +635,7 @@ findDependentObjects(const ObjectAddress *object,
* deletion of the owning object.)
* deletion of the owning object.)
*/
*/
ReleaseDeletionLock
(
object
);
ReleaseDeletionLock
(
object
);
AcquireDeletionLock
(
&
otherObject
);
AcquireDeletionLock
(
&
otherObject
,
0
);
/*
/*
* The owning object might have been deleted while we waited
* The owning object might have been deleted while we waited
...
@@ -726,7 +730,7 @@ findDependentObjects(const ObjectAddress *object,
...
@@ -726,7 +730,7 @@ findDependentObjects(const ObjectAddress *object,
/*
/*
* Must lock the dependent object before recursing to it.
* Must lock the dependent object before recursing to it.
*/
*/
AcquireDeletionLock
(
&
otherObject
);
AcquireDeletionLock
(
&
otherObject
,
0
);
/*
/*
* The dependent object might have been deleted while we waited to
* The dependent object might have been deleted while we waited to
...
@@ -1044,10 +1048,17 @@ deleteOneObject(const ObjectAddress *object, Relation depRel, int flags)
...
@@ -1044,10 +1048,17 @@ deleteOneObject(const ObjectAddress *object, Relation depRel, int flags)
deleteSharedDependencyRecordsFor
(
object
->
classId
,
object
->
objectId
,
deleteSharedDependencyRecordsFor
(
object
->
classId
,
object
->
objectId
,
object
->
objectSubId
);
object
->
objectSubId
);
/*
* Close depRel if we are doing a drop concurrently because it
* commits the transaction, so we don't want dangling references.
*/
if
((
flags
&
PERFORM_DELETION_CONCURRENTLY
)
==
PERFORM_DELETION_CONCURRENTLY
)
heap_close
(
depRel
,
RowExclusiveLock
);
/*
/*
* Now delete the object itself, in an object-type-dependent way.
* Now delete the object itself, in an object-type-dependent way.
*/
*/
doDeletion
(
object
);
doDeletion
(
object
,
flags
);
/*
/*
* Delete any comments or security labels associated with this object.
* Delete any comments or security labels associated with this object.
...
@@ -1072,7 +1083,7 @@ deleteOneObject(const ObjectAddress *object, Relation depRel, int flags)
...
@@ -1072,7 +1083,7 @@ deleteOneObject(const ObjectAddress *object, Relation depRel, int flags)
* doDeletion: actually delete a single object
* doDeletion: actually delete a single object
*/
*/
static
void
static
void
doDeletion
(
const
ObjectAddress
*
object
)
doDeletion
(
const
ObjectAddress
*
object
,
int
flags
)
{
{
switch
(
getObjectClass
(
object
))
switch
(
getObjectClass
(
object
))
{
{
...
@@ -1082,8 +1093,11 @@ doDeletion(const ObjectAddress *object)
...
@@ -1082,8 +1093,11 @@ doDeletion(const ObjectAddress *object)
if
(
relKind
==
RELKIND_INDEX
)
if
(
relKind
==
RELKIND_INDEX
)
{
{
bool
concurrent
=
((
flags
&
PERFORM_DELETION_CONCURRENTLY
)
==
PERFORM_DELETION_CONCURRENTLY
);
Assert
(
object
->
objectSubId
==
0
);
Assert
(
object
->
objectSubId
==
0
);
index_drop
(
object
->
objectId
);
index_drop
(
object
->
objectId
,
concurrent
);
}
}
else
else
{
{
...
@@ -1219,10 +1233,15 @@ doDeletion(const ObjectAddress *object)
...
@@ -1219,10 +1233,15 @@ doDeletion(const ObjectAddress *object)
* shared-across-databases object, so we have no need for LockSharedObject.
* shared-across-databases object, so we have no need for LockSharedObject.
*/
*/
static
void
static
void
AcquireDeletionLock
(
const
ObjectAddress
*
object
)
AcquireDeletionLock
(
const
ObjectAddress
*
object
,
int
flags
)
{
{
if
(
object
->
classId
==
RelationRelationId
)
if
(
object
->
classId
==
RelationRelationId
)
LockRelationOid
(
object
->
objectId
,
AccessExclusiveLock
);
{
if
((
flags
&
PERFORM_DELETION_CONCURRENTLY
)
==
PERFORM_DELETION_CONCURRENTLY
)
LockRelationOid
(
object
->
objectId
,
ShareUpdateExclusiveLock
);
else
LockRelationOid
(
object
->
objectId
,
AccessExclusiveLock
);
}
else
else
/* assume we should lock the whole object not a sub-object */
/* assume we should lock the whole object not a sub-object */
LockDatabaseObject
(
object
->
classId
,
object
->
objectId
,
0
,
LockDatabaseObject
(
object
->
classId
,
object
->
objectId
,
0
,
...
...
src/backend/catalog/index.c
View file @
8cb53654
...
@@ -1282,7 +1282,7 @@ index_constraint_create(Relation heapRelation,
...
@@ -1282,7 +1282,7 @@ index_constraint_create(Relation heapRelation,
* else associated dependencies won't be cleaned up.
* else associated dependencies won't be cleaned up.
*/
*/
void
void
index_drop
(
Oid
indexId
)
index_drop
(
Oid
indexId
,
bool
concurrent
)
{
{
Oid
heapId
;
Oid
heapId
;
Relation
userHeapRelation
;
Relation
userHeapRelation
;
...
@@ -1290,6 +1290,12 @@ index_drop(Oid indexId)
...
@@ -1290,6 +1290,12 @@ index_drop(Oid indexId)
Relation
indexRelation
;
Relation
indexRelation
;
HeapTuple
tuple
;
HeapTuple
tuple
;
bool
hasexprs
;
bool
hasexprs
;
LockRelId
heaprelid
,
indexrelid
;
LOCKTAG
heaplocktag
,
indexlocktag
;
VirtualTransactionId
*
old_lockholders
;
Form_pg_index
indexForm
;
/*
/*
* To drop an index safely, we must grab exclusive lock on its parent
* To drop an index safely, we must grab exclusive lock on its parent
...
@@ -1302,16 +1308,128 @@ index_drop(Oid indexId)
...
@@ -1302,16 +1308,128 @@ index_drop(Oid indexId)
* that will make them update their index lists.
* that will make them update their index lists.
*/
*/
heapId
=
IndexGetRelation
(
indexId
,
false
);
heapId
=
IndexGetRelation
(
indexId
,
false
);
userHeapRelation
=
heap_open
(
heapId
,
AccessExclusiveLock
);
if
(
concurrent
)
{
userIndexRelation
=
index_open
(
indexId
,
AccessExclusiveLock
);
userHeapRelation
=
heap_open
(
heapId
,
ShareUpdateExclusiveLock
);
userIndexRelation
=
index_open
(
indexId
,
ShareUpdateExclusiveLock
);
}
else
{
userHeapRelation
=
heap_open
(
heapId
,
AccessExclusiveLock
);
userIndexRelation
=
index_open
(
indexId
,
AccessExclusiveLock
);
}
/*
/*
* There can no longer be anyone *else* touching the index, but we might
* We might still have open queries using it in our own session.
* still have open queries using it in our own session.
*/
*/
CheckTableNotInUse
(
userIndexRelation
,
"DROP INDEX"
);
CheckTableNotInUse
(
userIndexRelation
,
"DROP INDEX"
);
/*
* Drop Index concurrently is similar in many ways to creating an
* index concurrently, so some actions are similar to DefineIndex()
*/
if
(
concurrent
)
{
/*
* Mark index invalid by updating its pg_index entry
*
* Don't Assert(indexForm->indisvalid) because we may be trying to
* clear up after an error when trying to create an index which left
* the index invalid
*/
indexRelation
=
heap_open
(
IndexRelationId
,
RowExclusiveLock
);
tuple
=
SearchSysCacheCopy1
(
INDEXRELID
,
ObjectIdGetDatum
(
indexId
));
if
(
!
HeapTupleIsValid
(
tuple
))
elog
(
ERROR
,
"cache lookup failed for index %u"
,
indexId
);
indexForm
=
(
Form_pg_index
)
GETSTRUCT
(
tuple
);
indexForm
->
indisvalid
=
false
;
/* make unusable for queries */
indexForm
->
indisready
=
false
;
/* make invisible to changes */
simple_heap_update
(
indexRelation
,
&
tuple
->
t_self
,
tuple
);
CatalogUpdateIndexes
(
indexRelation
,
tuple
);
heap_close
(
indexRelation
,
RowExclusiveLock
);
/*
* Invalidate the relcache for the table, so that after this
* transaction we will refresh the index list. Forgetting just the
* index is not enough.
*/
CacheInvalidateRelcache
(
userHeapRelation
);
/* save lockrelid and locktag for below, then close but keep locks */
heaprelid
=
userHeapRelation
->
rd_lockInfo
.
lockRelId
;
SET_LOCKTAG_RELATION
(
heaplocktag
,
heaprelid
.
dbId
,
heaprelid
.
relId
);
heap_close
(
userHeapRelation
,
NoLock
);
indexrelid
=
userIndexRelation
->
rd_lockInfo
.
lockRelId
;
SET_LOCKTAG_RELATION
(
indexlocktag
,
indexrelid
.
dbId
,
indexrelid
.
relId
);
index_close
(
userIndexRelation
,
NoLock
);
/*
* For a concurrent drop, it's important to make the catalog entries
* visible to other transactions before we drop the index. The index
* will be marked not indisvalid, so that no one else tries to either
* insert into it or use it for queries.
*
* We must commit our current transaction so that the index update becomes
* visible; then start another. Note that all the data structures we just
* built are lost in the commit. The only data we keep past here are the
* relation IDs.
*
* Before committing, get a session-level lock on the table, to ensure
* that neither it nor the index can be dropped before we finish. This
* cannot block, even if someone else is waiting for access, because we
* already have the same lock within our transaction.
*/
LockRelationIdForSession
(
&
heaprelid
,
ShareUpdateExclusiveLock
);
LockRelationIdForSession
(
&
indexrelid
,
ShareUpdateExclusiveLock
);
PopActiveSnapshot
();
CommitTransactionCommand
();
StartTransactionCommand
();
/*
* Now we must wait until no running transaction could have the table open
* with the old list of indexes. To do this, inquire which xacts
* currently would conflict with AccessExclusiveLock on the table -- ie,
* which ones have a lock of any kind on the table. Then wait for each of
* these xacts to commit or abort. Note we do not need to worry about
* xacts that open the table for writing after this point; they will see
* the index as invalid when they open the relation.
*
* Note: the reason we use actual lock acquisition here, rather than just
* checking the ProcArray and sleeping, is that deadlock is possible if
* one of the transactions in question is blocked trying to acquire an
* exclusive lock on our table. The lock code will detect deadlock and
* error out properly.
*
* Note: GetLockConflicts() never reports our own xid, hence we need not
* check for that. Also, prepared xacts are not reported, which is fine
* since they certainly aren't going to do anything more.
*/
old_lockholders
=
GetLockConflicts
(
&
heaplocktag
,
AccessExclusiveLock
);
while
(
VirtualTransactionIdIsValid
(
*
old_lockholders
))
{
VirtualXactLock
(
*
old_lockholders
,
true
);
old_lockholders
++
;
}
/*
* Re-open relations to allow us to complete our actions.
*
* At this point, nothing should be accessing the index, but lets
* leave nothing to chance and grab AccessExclusiveLock on the index
* before the physical deletion.
*/
userHeapRelation
=
heap_open
(
heapId
,
ShareUpdateExclusiveLock
);
userIndexRelation
=
index_open
(
indexId
,
AccessExclusiveLock
);
}
/*
/*
* All predicate locks on the index are about to be made invalid. Promote
* All predicate locks on the index are about to be made invalid. Promote
* them to relation locks on the heap.
* them to relation locks on the heap.
...
@@ -1378,6 +1496,15 @@ index_drop(Oid indexId)
...
@@ -1378,6 +1496,15 @@ index_drop(Oid indexId)
* Close owning rel, but keep lock
* Close owning rel, but keep lock
*/
*/
heap_close
(
userHeapRelation
,
NoLock
);
heap_close
(
userHeapRelation
,
NoLock
);
/*
* Release the session locks before we go.
*/
if
(
concurrent
)
{
UnlockRelationIdForSession
(
&
heaprelid
,
ShareUpdateExclusiveLock
);
UnlockRelationIdForSession
(
&
indexrelid
,
ShareUpdateExclusiveLock
);
}
}
}
/* ----------------------------------------------------------------
/* ----------------------------------------------------------------
...
...
src/backend/commands/tablecmds.c
View file @
8cb53654
...
@@ -239,6 +239,7 @@ struct DropRelationCallbackState
...
@@ -239,6 +239,7 @@ struct DropRelationCallbackState
{
{
char
relkind
;
char
relkind
;
Oid
heapOid
;
Oid
heapOid
;
bool
concurrent
;
};
};
/* Alter table target-type flags for ATSimplePermissions */
/* Alter table target-type flags for ATSimplePermissions */
...
@@ -738,6 +739,21 @@ RemoveRelations(DropStmt *drop)
...
@@ -738,6 +739,21 @@ RemoveRelations(DropStmt *drop)
ObjectAddresses
*
objects
;
ObjectAddresses
*
objects
;
char
relkind
;
char
relkind
;
ListCell
*
cell
;
ListCell
*
cell
;
int
flags
=
0
;
LOCKMODE
lockmode
=
AccessExclusiveLock
;
if
(
drop
->
concurrent
)
{
lockmode
=
ShareUpdateExclusiveLock
;
if
(
list_length
(
drop
->
objects
)
>
1
)
ereport
(
ERROR
,
(
errcode
(
ERRCODE_FEATURE_NOT_SUPPORTED
),
errmsg
(
"DROP INDEX CONCURRENTLY does not support dropping multiple objects"
)));
if
(
drop
->
behavior
==
DROP_CASCADE
)
ereport
(
ERROR
,
(
errcode
(
ERRCODE_FEATURE_NOT_SUPPORTED
),
errmsg
(
"DROP INDEX CONCURRENTLY does not support CASCADE"
)));
}
/*
/*
* First we identify all the relations, then we delete them in a single
* First we identify all the relations, then we delete them in a single
...
@@ -800,7 +816,8 @@ RemoveRelations(DropStmt *drop)
...
@@ -800,7 +816,8 @@ RemoveRelations(DropStmt *drop)
/* Look up the appropriate relation using namespace search. */
/* Look up the appropriate relation using namespace search. */
state
.
relkind
=
relkind
;
state
.
relkind
=
relkind
;
state
.
heapOid
=
InvalidOid
;
state
.
heapOid
=
InvalidOid
;
relOid
=
RangeVarGetRelidExtended
(
rel
,
AccessExclusiveLock
,
true
,
state
.
concurrent
=
drop
->
concurrent
;
relOid
=
RangeVarGetRelidExtended
(
rel
,
lockmode
,
true
,
false
,
false
,
RangeVarCallbackForDropRelation
,
RangeVarCallbackForDropRelation
,
(
void
*
)
&
state
);
(
void
*
)
&
state
);
...
@@ -820,7 +837,20 @@ RemoveRelations(DropStmt *drop)
...
@@ -820,7 +837,20 @@ RemoveRelations(DropStmt *drop)
add_exact_object_address
(
&
obj
,
objects
);
add_exact_object_address
(
&
obj
,
objects
);
}
}
performMultipleDeletions
(
objects
,
drop
->
behavior
,
0
);
/*
* Set options and check further requirements for concurrent drop
*/
if
(
drop
->
concurrent
)
{
/*
* Confirm that concurrent behaviour is restricted in grammar.
*/
Assert
(
drop
->
removeType
==
OBJECT_INDEX
);
flags
|=
PERFORM_DELETION_CONCURRENTLY
;
}
performMultipleDeletions
(
objects
,
drop
->
behavior
,
flags
);
free_object_addresses
(
objects
);
free_object_addresses
(
objects
);
}
}
...
@@ -837,9 +867,12 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
...
@@ -837,9 +867,12 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
struct
DropRelationCallbackState
*
state
;
struct
DropRelationCallbackState
*
state
;
char
relkind
;
char
relkind
;
Form_pg_class
classform
;
Form_pg_class
classform
;
LOCKMODE
heap_lockmode
;
state
=
(
struct
DropRelationCallbackState
*
)
arg
;
state
=
(
struct
DropRelationCallbackState
*
)
arg
;
relkind
=
state
->
relkind
;
relkind
=
state
->
relkind
;
heap_lockmode
=
state
->
concurrent
?
ShareUpdateExclusiveLock
:
AccessExclusiveLock
;
/*
/*
* If we previously locked some other index's heap, and the name we're
* If we previously locked some other index's heap, and the name we're
...
@@ -848,7 +881,7 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
...
@@ -848,7 +881,7 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
*/
*/
if
(
relOid
!=
oldRelOid
&&
OidIsValid
(
state
->
heapOid
))
if
(
relOid
!=
oldRelOid
&&
OidIsValid
(
state
->
heapOid
))
{
{
UnlockRelationOid
(
state
->
heapOid
,
AccessExclusiveLock
);
UnlockRelationOid
(
state
->
heapOid
,
heap_lockmode
);
state
->
heapOid
=
InvalidOid
;
state
->
heapOid
=
InvalidOid
;
}
}
...
@@ -889,7 +922,7 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
...
@@ -889,7 +922,7 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
{
{
state
->
heapOid
=
IndexGetRelation
(
relOid
,
true
);
state
->
heapOid
=
IndexGetRelation
(
relOid
,
true
);
if
(
OidIsValid
(
state
->
heapOid
))
if
(
OidIsValid
(
state
->
heapOid
))
LockRelationOid
(
state
->
heapOid
,
AccessExclusiveLock
);
LockRelationOid
(
state
->
heapOid
,
heap_lockmode
);
}
}
}
}
...
...
src/backend/nodes/copyfuncs.c
View file @
8cb53654
...
@@ -2751,6 +2751,7 @@ _copyDropStmt(const DropStmt *from)
...
@@ -2751,6 +2751,7 @@ _copyDropStmt(const DropStmt *from)
COPY_SCALAR_FIELD
(
removeType
);
COPY_SCALAR_FIELD
(
removeType
);
COPY_SCALAR_FIELD
(
behavior
);
COPY_SCALAR_FIELD
(
behavior
);
COPY_SCALAR_FIELD
(
missing_ok
);
COPY_SCALAR_FIELD
(
missing_ok
);
COPY_SCALAR_FIELD
(
concurrent
);
return
newnode
;
return
newnode
;
}
}
...
...
src/backend/nodes/equalfuncs.c
View file @
8cb53654
...
@@ -1189,6 +1189,7 @@ _equalDropStmt(const DropStmt *a, const DropStmt *b)
...
@@ -1189,6 +1189,7 @@ _equalDropStmt(const DropStmt *a, const DropStmt *b)
COMPARE_SCALAR_FIELD
(
removeType
);
COMPARE_SCALAR_FIELD
(
removeType
);
COMPARE_SCALAR_FIELD
(
behavior
);
COMPARE_SCALAR_FIELD
(
behavior
);
COMPARE_SCALAR_FIELD
(
missing_ok
);
COMPARE_SCALAR_FIELD
(
missing_ok
);
COMPARE_SCALAR_FIELD
(
concurrent
);
return
true
;
return
true
;
}
}
...
...
src/backend/parser/gram.y
View file @
8cb53654
...
@@ -3276,6 +3276,7 @@ DropPLangStmt:
...
@@ -3276,6 +3276,7 @@ DropPLangStmt:
n->arguments = NIL;
n->arguments = NIL;
n->behavior = $5;
n->behavior = $5;
n->missing_ok = false;
n->missing_ok = false;
n->concurrent = false;
$$ = (Node *)n;
$$ = (Node *)n;
}
}
| DROP opt_procedural LANGUAGE IF_P EXISTS ColId_or_Sconst opt_drop_behavior
| DROP opt_procedural LANGUAGE IF_P EXISTS ColId_or_Sconst opt_drop_behavior
...
@@ -3285,6 +3286,7 @@ DropPLangStmt:
...
@@ -3285,6 +3286,7 @@ DropPLangStmt:
n->objects = list_make1(list_make1(makeString($6)));
n->objects = list_make1(list_make1(makeString($6)));
n->behavior = $7;
n->behavior = $7;
n->missing_ok = true;
n->missing_ok = true;
n->concurrent = false;
$$ = (Node *)n;
$$ = (Node *)n;
}
}
;
;
...
@@ -3680,6 +3682,7 @@ DropFdwStmt: DROP FOREIGN DATA_P WRAPPER name opt_drop_behavior
...
@@ -3680,6 +3682,7 @@ DropFdwStmt: DROP FOREIGN DATA_P WRAPPER name opt_drop_behavior
n->arguments = NIL;
n->arguments = NIL;
n->missing_ok = false;
n->missing_ok = false;
n->behavior = $6;
n->behavior = $6;
n->concurrent = false;
$$ = (Node *) n;
$$ = (Node *) n;
}
}
| DROP FOREIGN DATA_P WRAPPER IF_P EXISTS name opt_drop_behavior
| DROP FOREIGN DATA_P WRAPPER IF_P EXISTS name opt_drop_behavior
...
@@ -3690,6 +3693,7 @@ DropFdwStmt: DROP FOREIGN DATA_P WRAPPER name opt_drop_behavior
...
@@ -3690,6 +3693,7 @@ DropFdwStmt: DROP FOREIGN DATA_P WRAPPER name opt_drop_behavior
n->arguments = NIL;
n->arguments = NIL;
n->missing_ok = true;
n->missing_ok = true;
n->behavior = $8;
n->behavior = $8;
n->concurrent = false;
$$ = (Node *) n;
$$ = (Node *) n;
}
}
;
;
...
@@ -3840,6 +3844,7 @@ DropForeignServerStmt: DROP SERVER name opt_drop_behavior
...
@@ -3840,6 +3844,7 @@ DropForeignServerStmt: DROP SERVER name opt_drop_behavior
n->arguments = NIL;
n->arguments = NIL;
n->missing_ok = false;
n->missing_ok = false;
n->behavior = $4;
n->behavior = $4;
n->concurrent = false;
$$ = (Node *) n;
$$ = (Node *) n;
}
}
| DROP SERVER IF_P EXISTS name opt_drop_behavior
| DROP SERVER IF_P EXISTS name opt_drop_behavior
...
@@ -3850,6 +3855,7 @@ DropForeignServerStmt: DROP SERVER name opt_drop_behavior
...
@@ -3850,6 +3855,7 @@ DropForeignServerStmt: DROP SERVER name opt_drop_behavior
n->arguments = NIL;
n->arguments = NIL;
n->missing_ok = true;
n->missing_ok = true;
n->behavior = $6;
n->behavior = $6;
n->concurrent = false;
$$ = (Node *) n;
$$ = (Node *) n;
}
}
;
;
...
@@ -4237,6 +4243,7 @@ DropTrigStmt:
...
@@ -4237,6 +4243,7 @@ DropTrigStmt:
n->arguments = NIL;
n->arguments = NIL;
n->behavior = $6;
n->behavior = $6;
n->missing_ok = false;
n->missing_ok = false;
n->concurrent = false;
$$ = (Node *) n;
$$ = (Node *) n;
}
}
| DROP TRIGGER IF_P EXISTS name ON any_name opt_drop_behavior
| DROP TRIGGER IF_P EXISTS name ON any_name opt_drop_behavior
...
@@ -4247,6 +4254,7 @@ DropTrigStmt:
...
@@ -4247,6 +4254,7 @@ DropTrigStmt:
n->arguments = NIL;
n->arguments = NIL;
n->behavior = $8;
n->behavior = $8;
n->missing_ok = true;
n->missing_ok = true;
n->concurrent = false;
$$ = (Node *) n;
$$ = (Node *) n;
}
}
;
;
...
@@ -4707,6 +4715,7 @@ DropOpClassStmt:
...
@@ -4707,6 +4715,7 @@ DropOpClassStmt:
n->removeType = OBJECT_OPCLASS;
n->removeType = OBJECT_OPCLASS;
n->behavior = $7;
n->behavior = $7;
n->missing_ok = false;
n->missing_ok = false;
n->concurrent = false;
$$ = (Node *) n;
$$ = (Node *) n;
}
}
| DROP OPERATOR CLASS IF_P EXISTS any_name USING access_method opt_drop_behavior
| DROP OPERATOR CLASS IF_P EXISTS any_name USING access_method opt_drop_behavior
...
@@ -4717,6 +4726,7 @@ DropOpClassStmt:
...
@@ -4717,6 +4726,7 @@ DropOpClassStmt:
n->removeType = OBJECT_OPCLASS;
n->removeType = OBJECT_OPCLASS;
n->behavior = $9;
n->behavior = $9;
n->missing_ok = true;
n->missing_ok = true;
n->concurrent = false;
$$ = (Node *) n;
$$ = (Node *) n;
}
}
;
;
...
@@ -4730,6 +4740,7 @@ DropOpFamilyStmt:
...
@@ -4730,6 +4740,7 @@ DropOpFamilyStmt:
n->removeType = OBJECT_OPFAMILY;
n->removeType = OBJECT_OPFAMILY;
n->behavior = $7;
n->behavior = $7;
n->missing_ok = false;
n->missing_ok = false;
n->concurrent = false;
$$ = (Node *) n;
$$ = (Node *) n;
}
}
| DROP OPERATOR FAMILY IF_P EXISTS any_name USING access_method opt_drop_behavior
| DROP OPERATOR FAMILY IF_P EXISTS any_name USING access_method opt_drop_behavior
...
@@ -4740,6 +4751,7 @@ DropOpFamilyStmt:
...
@@ -4740,6 +4751,7 @@ DropOpFamilyStmt:
n->removeType = OBJECT_OPFAMILY;
n->removeType = OBJECT_OPFAMILY;
n->behavior = $9;
n->behavior = $9;
n->missing_ok = true;
n->missing_ok = true;
n->concurrent = false;
$$ = (Node *) n;
$$ = (Node *) n;
}
}
;
;
...
@@ -4790,6 +4802,7 @@ DropStmt: DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior
...
@@ -4790,6 +4802,7 @@ DropStmt: DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior
n->objects = $5;
n->objects = $5;
n->arguments = NIL;
n->arguments = NIL;
n->behavior = $6;
n->behavior = $6;
n->concurrent = false;
$$ = (Node *)n;
$$ = (Node *)n;
}
}
| DROP drop_type any_name_list opt_drop_behavior
| DROP drop_type any_name_list opt_drop_behavior
...
@@ -4800,6 +4813,29 @@ DropStmt: DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior
...
@@ -4800,6 +4813,29 @@ DropStmt: DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior
n->objects = $3;
n->objects = $3;
n->arguments = NIL;
n->arguments = NIL;
n->behavior = $4;
n->behavior = $4;
n->concurrent = false;
$$ = (Node *)n;
}
| DROP INDEX CONCURRENTLY any_name_list opt_drop_behavior
{
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_INDEX;
n->missing_ok = FALSE;
n->objects = $4;
n->arguments = NIL;
n->behavior = $5;
n->concurrent = true;
$$ = (Node *)n;
}
| DROP INDEX CONCURRENTLY IF_P EXISTS any_name_list opt_drop_behavior
{
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_INDEX;
n->missing_ok = FALSE;
n->objects = $6;
n->arguments = NIL;
n->behavior = $7;
n->concurrent = true;
$$ = (Node *)n;
$$ = (Node *)n;
}
}
;
;
...
@@ -6246,6 +6282,7 @@ RemoveFuncStmt:
...
@@ -6246,6 +6282,7 @@ RemoveFuncStmt:
n->arguments = list_make1(extractArgTypes($4));
n->arguments = list_make1(extractArgTypes($4));
n->behavior = $5;
n->behavior = $5;
n->missing_ok = false;
n->missing_ok = false;
n->concurrent = false;
$$ = (Node *)n;
$$ = (Node *)n;
}
}
| DROP FUNCTION IF_P EXISTS func_name func_args opt_drop_behavior
| DROP FUNCTION IF_P EXISTS func_name func_args opt_drop_behavior
...
@@ -6256,6 +6293,7 @@ RemoveFuncStmt:
...
@@ -6256,6 +6293,7 @@ RemoveFuncStmt:
n->arguments = list_make1(extractArgTypes($6));
n->arguments = list_make1(extractArgTypes($6));
n->behavior = $7;
n->behavior = $7;
n->missing_ok = true;
n->missing_ok = true;
n->concurrent = false;
$$ = (Node *)n;
$$ = (Node *)n;
}
}
;
;
...
@@ -6269,6 +6307,7 @@ RemoveAggrStmt:
...
@@ -6269,6 +6307,7 @@ RemoveAggrStmt:
n->arguments = list_make1($4);
n->arguments = list_make1($4);
n->behavior = $5;
n->behavior = $5;
n->missing_ok = false;
n->missing_ok = false;
n->concurrent = false;
$$ = (Node *)n;
$$ = (Node *)n;
}
}
| DROP AGGREGATE IF_P EXISTS func_name aggr_args opt_drop_behavior
| DROP AGGREGATE IF_P EXISTS func_name aggr_args opt_drop_behavior
...
@@ -6279,6 +6318,7 @@ RemoveAggrStmt:
...
@@ -6279,6 +6318,7 @@ RemoveAggrStmt:
n->arguments = list_make1($6);
n->arguments = list_make1($6);
n->behavior = $7;
n->behavior = $7;
n->missing_ok = true;
n->missing_ok = true;
n->concurrent = false;
$$ = (Node *)n;
$$ = (Node *)n;
}
}
;
;
...
@@ -6292,6 +6332,7 @@ RemoveOperStmt:
...
@@ -6292,6 +6332,7 @@ RemoveOperStmt:
n->arguments = list_make1($4);
n->arguments = list_make1($4);
n->behavior = $5;
n->behavior = $5;
n->missing_ok = false;
n->missing_ok = false;
n->concurrent = false;
$$ = (Node *)n;
$$ = (Node *)n;
}
}
| DROP OPERATOR IF_P EXISTS any_operator oper_argtypes opt_drop_behavior
| DROP OPERATOR IF_P EXISTS any_operator oper_argtypes opt_drop_behavior
...
@@ -6302,6 +6343,7 @@ RemoveOperStmt:
...
@@ -6302,6 +6343,7 @@ RemoveOperStmt:
n->arguments = list_make1($6);
n->arguments = list_make1($6);
n->behavior = $7;
n->behavior = $7;
n->missing_ok = true;
n->missing_ok = true;
n->concurrent = false;
$$ = (Node *)n;
$$ = (Node *)n;
}
}
;
;
...
@@ -6418,6 +6460,7 @@ DropCastStmt: DROP CAST opt_if_exists '(' Typename AS Typename ')' opt_drop_beha
...
@@ -6418,6 +6460,7 @@ DropCastStmt: DROP CAST opt_if_exists '(' Typename AS Typename ')' opt_drop_beha
n->arguments = list_make1(list_make1($7));
n->arguments = list_make1(list_make1($7));
n->behavior = $9;
n->behavior = $9;
n->missing_ok = $3;
n->missing_ok = $3;
n->concurrent = false;
$$ = (Node *)n;
$$ = (Node *)n;
}
}
;
;
...
@@ -7339,6 +7382,7 @@ DropRuleStmt:
...
@@ -7339,6 +7382,7 @@ DropRuleStmt:
n->arguments = NIL;
n->arguments = NIL;
n->behavior = $6;
n->behavior = $6;
n->missing_ok = false;
n->missing_ok = false;
n->concurrent = false;
$$ = (Node *) n;
$$ = (Node *) n;
}
}
| DROP RULE IF_P EXISTS name ON any_name opt_drop_behavior
| DROP RULE IF_P EXISTS name ON any_name opt_drop_behavior
...
@@ -7349,6 +7393,7 @@ DropRuleStmt:
...
@@ -7349,6 +7393,7 @@ DropRuleStmt:
n->arguments = NIL;
n->arguments = NIL;
n->behavior = $8;
n->behavior = $8;
n->missing_ok = true;
n->missing_ok = true;
n->concurrent = false;
$$ = (Node *) n;
$$ = (Node *) n;
}
}
;
;
...
...
src/backend/tcop/utility.c
View file @
8cb53654
...
@@ -631,10 +631,15 @@ standard_ProcessUtility(Node *parsetree,
...
@@ -631,10 +631,15 @@ standard_ProcessUtility(Node *parsetree,
case
T_DropStmt
:
case
T_DropStmt
:
switch
(((
DropStmt
*
)
parsetree
)
->
removeType
)
switch
(((
DropStmt
*
)
parsetree
)
->
removeType
)
{
{
case
OBJECT_INDEX
:
if
(((
DropStmt
*
)
parsetree
)
->
concurrent
)
PreventTransactionChain
(
isTopLevel
,
"DROP INDEX CONCURRENTLY"
);
/* fall through */
case
OBJECT_TABLE
:
case
OBJECT_TABLE
:
case
OBJECT_SEQUENCE
:
case
OBJECT_SEQUENCE
:
case
OBJECT_VIEW
:
case
OBJECT_VIEW
:
case
OBJECT_INDEX
:
case
OBJECT_FOREIGN_TABLE
:
case
OBJECT_FOREIGN_TABLE
:
RemoveRelations
((
DropStmt
*
)
parsetree
);
RemoveRelations
((
DropStmt
*
)
parsetree
);
break
;
break
;
...
...
src/backend/utils/cache/relcache.c
View file @
8cb53654
...
@@ -3355,6 +3355,12 @@ RelationGetIndexList(Relation relation)
...
@@ -3355,6 +3355,12 @@ RelationGetIndexList(Relation relation)
oidvector
*
indclass
;
oidvector
*
indclass
;
bool
isnull
;
bool
isnull
;
/*
* Ignore any indexes that are currently being dropped
*/
if
(
!
index
->
indisvalid
&&
!
index
->
indisready
)
continue
;
/* Add index's OID to result list in the proper order */
/* Add index's OID to result list in the proper order */
result
=
insert_ordered_oid
(
result
,
index
->
indexrelid
);
result
=
insert_ordered_oid
(
result
,
index
->
indexrelid
);
...
...
src/include/catalog/dependency.h
View file @
8cb53654
...
@@ -153,6 +153,7 @@ typedef enum ObjectClass
...
@@ -153,6 +153,7 @@ typedef enum ObjectClass
/* in dependency.c */
/* in dependency.c */
#define PERFORM_DELETION_INTERNAL 0x0001
#define PERFORM_DELETION_INTERNAL 0x0001
#define PERFORM_DELETION_CONCURRENTLY 0x0002
extern
void
performDeletion
(
const
ObjectAddress
*
object
,
extern
void
performDeletion
(
const
ObjectAddress
*
object
,
DropBehavior
behavior
,
int
flags
);
DropBehavior
behavior
,
int
flags
);
...
...
src/include/catalog/index.h
View file @
8cb53654
...
@@ -63,7 +63,7 @@ extern void index_constraint_create(Relation heapRelation,
...
@@ -63,7 +63,7 @@ extern void index_constraint_create(Relation heapRelation,
bool
update_pgindex
,
bool
update_pgindex
,
bool
allow_system_table_mods
);
bool
allow_system_table_mods
);
extern
void
index_drop
(
Oid
indexId
);
extern
void
index_drop
(
Oid
indexId
,
bool
concurrent
);
extern
IndexInfo
*
BuildIndexInfo
(
Relation
index
);
extern
IndexInfo
*
BuildIndexInfo
(
Relation
index
);
...
...
src/include/nodes/parsenodes.h
View file @
8cb53654
...
@@ -1909,6 +1909,7 @@ typedef struct DropStmt
...
@@ -1909,6 +1909,7 @@ typedef struct DropStmt
ObjectType
removeType
;
/* object type */
ObjectType
removeType
;
/* object type */
DropBehavior
behavior
;
/* RESTRICT or CASCADE behavior */
DropBehavior
behavior
;
/* RESTRICT or CASCADE behavior */
bool
missing_ok
;
/* skip error if object is missing? */
bool
missing_ok
;
/* skip error if object is missing? */
bool
concurrent
;
/* drop index concurrently? */
}
DropStmt
;
}
DropStmt
;
/* ----------------------
/* ----------------------
...
...
src/test/regress/expected/create_index.out
View file @
8cb53654
...
@@ -2316,6 +2316,34 @@ Indexes:
...
@@ -2316,6 +2316,34 @@ Indexes:
"concur_index5" btree (f2) WHERE f1 = 'x'::text
"concur_index5" btree (f2) WHERE f1 = 'x'::text
"std_index" btree (f2)
"std_index" btree (f2)
--
-- Try some concurrent index drops
--
DROP INDEX CONCURRENTLY "concur_index2"; -- works
DROP INDEX CONCURRENTLY IF EXISTS "concur_index2"; -- notice
ERROR: index "concur_index2" does not exist
-- failures
DROP INDEX CONCURRENTLY "concur_index2", "concur_index3";
ERROR: DROP INDEX CONCURRENTLY does not support dropping multiple objects
BEGIN;
DROP INDEX CONCURRENTLY "concur_index5";
ERROR: DROP INDEX CONCURRENTLY cannot run inside a transaction block
ROLLBACK;
-- successes
DROP INDEX CONCURRENTLY IF EXISTS "concur_index3";
DROP INDEX CONCURRENTLY "concur_index4";
DROP INDEX CONCURRENTLY "concur_index5";
DROP INDEX CONCURRENTLY "concur_index1";
DROP INDEX CONCURRENTLY "concur_heap_expr_idx";
\d concur_heap
Table "public.concur_heap"
Column | Type | Modifiers
--------+------+-----------
f1 | text |
f2 | text |
Indexes:
"std_index" btree (f2)
DROP TABLE concur_heap;
DROP TABLE concur_heap;
--
--
-- Test ADD CONSTRAINT USING INDEX
-- Test ADD CONSTRAINT USING INDEX
...
...
src/test/regress/sql/create_index.sql
View file @
8cb53654
...
@@ -727,6 +727,27 @@ COMMIT;
...
@@ -727,6 +727,27 @@ COMMIT;
\
d
concur_heap
\
d
concur_heap
--
-- Try some concurrent index drops
--
DROP
INDEX
CONCURRENTLY
"concur_index2"
;
-- works
DROP
INDEX
CONCURRENTLY
IF
EXISTS
"concur_index2"
;
-- notice
-- failures
DROP
INDEX
CONCURRENTLY
"concur_index2"
,
"concur_index3"
;
BEGIN
;
DROP
INDEX
CONCURRENTLY
"concur_index5"
;
ROLLBACK
;
-- successes
DROP
INDEX
CONCURRENTLY
IF
EXISTS
"concur_index3"
;
DROP
INDEX
CONCURRENTLY
"concur_index4"
;
DROP
INDEX
CONCURRENTLY
"concur_index5"
;
DROP
INDEX
CONCURRENTLY
"concur_index1"
;
DROP
INDEX
CONCURRENTLY
"concur_heap_expr_idx"
;
\
d
concur_heap
DROP
TABLE
concur_heap
;
DROP
TABLE
concur_heap
;
--
--
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment