Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Gpdb
提交
8cb53654
G
Gpdb
项目概览
Greenplum
/
Gpdb
通知
7
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
Gpdb
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
8cb53654
编写于
4月 06, 2012
作者:
S
Simon Riggs
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add DROP INDEX CONCURRENTLY [IF EXISTS], uses ShareUpdateExclusiveLock
上级
21cc5296
变更
14
隐藏空白更改
内联
并排
Showing
14 changed file
with
337 addition
and
26 deletion
+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
未找到文件。
doc/src/sgml/ref/drop_index.sgml
浏览文件 @
8cb53654
...
...
@@ -21,7 +21,7 @@ PostgreSQL documentation
<refsynopsisdiv>
<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>
</refsynopsisdiv>
...
...
@@ -49,6 +49,29 @@ DROP INDEX [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> [, ..
</listitem>
</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>
<term><replaceable class="PARAMETER">name</replaceable></term>
<listitem>
...
...
src/backend/catalog/dependency.c
浏览文件 @
8cb53654
...
...
@@ -174,8 +174,8 @@ static void reportDependentObjects(const ObjectAddresses *targetObjects,
const
ObjectAddress
*
origObject
);
static
void
deleteOneObject
(
const
ObjectAddress
*
object
,
Relation
depRel
,
int32
flags
);
static
void
doDeletion
(
const
ObjectAddress
*
object
);
static
void
AcquireDeletionLock
(
const
ObjectAddress
*
object
);
static
void
doDeletion
(
const
ObjectAddress
*
object
,
int
flags
);
static
void
AcquireDeletionLock
(
const
ObjectAddress
*
object
,
int
flags
);
static
void
ReleaseDeletionLock
(
const
ObjectAddress
*
object
);
static
bool
find_expr_references_walker
(
Node
*
node
,
find_expr_references_context
*
context
);
...
...
@@ -233,7 +233,7 @@ performDeletion(const ObjectAddress *object,
* Acquire deletion lock on the target object. (Ideally the caller has
* 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
...
...
@@ -317,7 +317,7 @@ performMultipleDeletions(const ObjectAddresses *objects,
* Acquire deletion lock on each target object. (Ideally the caller
* has done this already, but many places are sloppy about it.)
*/
AcquireDeletionLock
(
thisobj
);
AcquireDeletionLock
(
thisobj
,
flags
);
findDependentObjects
(
thisobj
,
DEPFLAG_ORIGINAL
,
...
...
@@ -351,7 +351,11 @@ performMultipleDeletions(const ObjectAddresses *objects,
/* And clean up */
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,
* Acquire deletion lock on the target object. (Ideally the caller has
* 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
...
...
@@ -631,7 +635,7 @@ findDependentObjects(const ObjectAddress *object,
* deletion of the owning object.)
*/
ReleaseDeletionLock
(
object
);
AcquireDeletionLock
(
&
otherObject
);
AcquireDeletionLock
(
&
otherObject
,
0
);
/*
* The owning object might have been deleted while we waited
...
...
@@ -726,7 +730,7 @@ findDependentObjects(const ObjectAddress *object,
/*
* 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
...
...
@@ -1044,10 +1048,17 @@ deleteOneObject(const ObjectAddress *object, Relation depRel, int flags)
deleteSharedDependencyRecordsFor
(
object
->
classId
,
object
->
objectId
,
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.
*/
doDeletion
(
object
);
doDeletion
(
object
,
flags
);
/*
* Delete any comments or security labels associated with this object.
...
...
@@ -1072,7 +1083,7 @@ deleteOneObject(const ObjectAddress *object, Relation depRel, int flags)
* doDeletion: actually delete a single object
*/
static
void
doDeletion
(
const
ObjectAddress
*
object
)
doDeletion
(
const
ObjectAddress
*
object
,
int
flags
)
{
switch
(
getObjectClass
(
object
))
{
...
...
@@ -1082,8 +1093,11 @@ doDeletion(const ObjectAddress *object)
if
(
relKind
==
RELKIND_INDEX
)
{
bool
concurrent
=
((
flags
&
PERFORM_DELETION_CONCURRENTLY
)
==
PERFORM_DELETION_CONCURRENTLY
);
Assert
(
object
->
objectSubId
==
0
);
index_drop
(
object
->
objectId
);
index_drop
(
object
->
objectId
,
concurrent
);
}
else
{
...
...
@@ -1219,10 +1233,15 @@ doDeletion(const ObjectAddress *object)
* shared-across-databases object, so we have no need for LockSharedObject.
*/
static
void
AcquireDeletionLock
(
const
ObjectAddress
*
object
)
AcquireDeletionLock
(
const
ObjectAddress
*
object
,
int
flags
)
{
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
/* assume we should lock the whole object not a sub-object */
LockDatabaseObject
(
object
->
classId
,
object
->
objectId
,
0
,
...
...
src/backend/catalog/index.c
浏览文件 @
8cb53654
...
...
@@ -1282,7 +1282,7 @@ index_constraint_create(Relation heapRelation,
* else associated dependencies won't be cleaned up.
*/
void
index_drop
(
Oid
indexId
)
index_drop
(
Oid
indexId
,
bool
concurrent
)
{
Oid
heapId
;
Relation
userHeapRelation
;
...
...
@@ -1290,6 +1290,12 @@ index_drop(Oid indexId)
Relation
indexRelation
;
HeapTuple
tuple
;
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
...
...
@@ -1302,16 +1308,128 @@ index_drop(Oid indexId)
* that will make them update their index lists.
*/
heapId
=
IndexGetRelation
(
indexId
,
false
);
userHeapRelation
=
heap_open
(
heapId
,
AccessExclusiveLock
);
userIndexRelation
=
index_open
(
indexId
,
AccessExclusiveLock
);
if
(
concurrent
)
{
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
* still have open queries using it in our own session.
* We might still have open queries using it in our own session.
*/
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
* them to relation locks on the heap.
...
...
@@ -1378,6 +1496,15 @@ index_drop(Oid indexId)
* Close owning rel, but keep lock
*/
heap_close
(
userHeapRelation
,
NoLock
);
/*
* Release the session locks before we go.
*/
if
(
concurrent
)
{
UnlockRelationIdForSession
(
&
heaprelid
,
ShareUpdateExclusiveLock
);
UnlockRelationIdForSession
(
&
indexrelid
,
ShareUpdateExclusiveLock
);
}
}
/* ----------------------------------------------------------------
...
...
src/backend/commands/tablecmds.c
浏览文件 @
8cb53654
...
...
@@ -239,6 +239,7 @@ struct DropRelationCallbackState
{
char
relkind
;
Oid
heapOid
;
bool
concurrent
;
};
/* Alter table target-type flags for ATSimplePermissions */
...
...
@@ -738,6 +739,21 @@ RemoveRelations(DropStmt *drop)
ObjectAddresses
*
objects
;
char
relkind
;
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
...
...
@@ -800,7 +816,8 @@ RemoveRelations(DropStmt *drop)
/* Look up the appropriate relation using namespace search. */
state
.
relkind
=
relkind
;
state
.
heapOid
=
InvalidOid
;
relOid
=
RangeVarGetRelidExtended
(
rel
,
AccessExclusiveLock
,
true
,
state
.
concurrent
=
drop
->
concurrent
;
relOid
=
RangeVarGetRelidExtended
(
rel
,
lockmode
,
true
,
false
,
RangeVarCallbackForDropRelation
,
(
void
*
)
&
state
);
...
...
@@ -820,7 +837,20 @@ RemoveRelations(DropStmt *drop)
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
);
}
...
...
@@ -837,9 +867,12 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
struct
DropRelationCallbackState
*
state
;
char
relkind
;
Form_pg_class
classform
;
LOCKMODE
heap_lockmode
;
state
=
(
struct
DropRelationCallbackState
*
)
arg
;
relkind
=
state
->
relkind
;
heap_lockmode
=
state
->
concurrent
?
ShareUpdateExclusiveLock
:
AccessExclusiveLock
;
/*
* 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,
*/
if
(
relOid
!=
oldRelOid
&&
OidIsValid
(
state
->
heapOid
))
{
UnlockRelationOid
(
state
->
heapOid
,
AccessExclusiveLock
);
UnlockRelationOid
(
state
->
heapOid
,
heap_lockmode
);
state
->
heapOid
=
InvalidOid
;
}
...
...
@@ -889,7 +922,7 @@ RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
{
state
->
heapOid
=
IndexGetRelation
(
relOid
,
true
);
if
(
OidIsValid
(
state
->
heapOid
))
LockRelationOid
(
state
->
heapOid
,
AccessExclusiveLock
);
LockRelationOid
(
state
->
heapOid
,
heap_lockmode
);
}
}
...
...
src/backend/nodes/copyfuncs.c
浏览文件 @
8cb53654
...
...
@@ -2751,6 +2751,7 @@ _copyDropStmt(const DropStmt *from)
COPY_SCALAR_FIELD
(
removeType
);
COPY_SCALAR_FIELD
(
behavior
);
COPY_SCALAR_FIELD
(
missing_ok
);
COPY_SCALAR_FIELD
(
concurrent
);
return
newnode
;
}
...
...
src/backend/nodes/equalfuncs.c
浏览文件 @
8cb53654
...
...
@@ -1189,6 +1189,7 @@ _equalDropStmt(const DropStmt *a, const DropStmt *b)
COMPARE_SCALAR_FIELD
(
removeType
);
COMPARE_SCALAR_FIELD
(
behavior
);
COMPARE_SCALAR_FIELD
(
missing_ok
);
COMPARE_SCALAR_FIELD
(
concurrent
);
return
true
;
}
...
...
src/backend/parser/gram.y
浏览文件 @
8cb53654
...
...
@@ -3276,6 +3276,7 @@ DropPLangStmt:
n->arguments = NIL;
n->behavior = $5;
n->missing_ok = false;
n->concurrent = false;
$$ = (Node *)n;
}
| DROP opt_procedural LANGUAGE IF_P EXISTS ColId_or_Sconst opt_drop_behavior
...
...
@@ -3285,6 +3286,7 @@ DropPLangStmt:
n->objects = list_make1(list_make1(makeString($6)));
n->behavior = $7;
n->missing_ok = true;
n->concurrent = false;
$$ = (Node *)n;
}
;
...
...
@@ -3680,6 +3682,7 @@ DropFdwStmt: DROP FOREIGN DATA_P WRAPPER name opt_drop_behavior
n->arguments = NIL;
n->missing_ok = false;
n->behavior = $6;
n->concurrent = false;
$$ = (Node *) n;
}
| 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
n->arguments = NIL;
n->missing_ok = true;
n->behavior = $8;
n->concurrent = false;
$$ = (Node *) n;
}
;
...
...
@@ -3840,6 +3844,7 @@ DropForeignServerStmt: DROP SERVER name opt_drop_behavior
n->arguments = NIL;
n->missing_ok = false;
n->behavior = $4;
n->concurrent = false;
$$ = (Node *) n;
}
| DROP SERVER IF_P EXISTS name opt_drop_behavior
...
...
@@ -3850,6 +3855,7 @@ DropForeignServerStmt: DROP SERVER name opt_drop_behavior
n->arguments = NIL;
n->missing_ok = true;
n->behavior = $6;
n->concurrent = false;
$$ = (Node *) n;
}
;
...
...
@@ -4237,6 +4243,7 @@ DropTrigStmt:
n->arguments = NIL;
n->behavior = $6;
n->missing_ok = false;
n->concurrent = false;
$$ = (Node *) n;
}
| DROP TRIGGER IF_P EXISTS name ON any_name opt_drop_behavior
...
...
@@ -4247,6 +4254,7 @@ DropTrigStmt:
n->arguments = NIL;
n->behavior = $8;
n->missing_ok = true;
n->concurrent = false;
$$ = (Node *) n;
}
;
...
...
@@ -4707,6 +4715,7 @@ DropOpClassStmt:
n->removeType = OBJECT_OPCLASS;
n->behavior = $7;
n->missing_ok = false;
n->concurrent = false;
$$ = (Node *) n;
}
| DROP OPERATOR CLASS IF_P EXISTS any_name USING access_method opt_drop_behavior
...
...
@@ -4717,6 +4726,7 @@ DropOpClassStmt:
n->removeType = OBJECT_OPCLASS;
n->behavior = $9;
n->missing_ok = true;
n->concurrent = false;
$$ = (Node *) n;
}
;
...
...
@@ -4730,6 +4740,7 @@ DropOpFamilyStmt:
n->removeType = OBJECT_OPFAMILY;
n->behavior = $7;
n->missing_ok = false;
n->concurrent = false;
$$ = (Node *) n;
}
| DROP OPERATOR FAMILY IF_P EXISTS any_name USING access_method opt_drop_behavior
...
...
@@ -4740,6 +4751,7 @@ DropOpFamilyStmt:
n->removeType = OBJECT_OPFAMILY;
n->behavior = $9;
n->missing_ok = true;
n->concurrent = false;
$$ = (Node *) n;
}
;
...
...
@@ -4790,6 +4802,7 @@ DropStmt: DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior
n->objects = $5;
n->arguments = NIL;
n->behavior = $6;
n->concurrent = false;
$$ = (Node *)n;
}
| 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
n->objects = $3;
n->arguments = NIL;
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;
}
;
...
...
@@ -6246,6 +6282,7 @@ RemoveFuncStmt:
n->arguments = list_make1(extractArgTypes($4));
n->behavior = $5;
n->missing_ok = false;
n->concurrent = false;
$$ = (Node *)n;
}
| DROP FUNCTION IF_P EXISTS func_name func_args opt_drop_behavior
...
...
@@ -6256,6 +6293,7 @@ RemoveFuncStmt:
n->arguments = list_make1(extractArgTypes($6));
n->behavior = $7;
n->missing_ok = true;
n->concurrent = false;
$$ = (Node *)n;
}
;
...
...
@@ -6269,6 +6307,7 @@ RemoveAggrStmt:
n->arguments = list_make1($4);
n->behavior = $5;
n->missing_ok = false;
n->concurrent = false;
$$ = (Node *)n;
}
| DROP AGGREGATE IF_P EXISTS func_name aggr_args opt_drop_behavior
...
...
@@ -6279,6 +6318,7 @@ RemoveAggrStmt:
n->arguments = list_make1($6);
n->behavior = $7;
n->missing_ok = true;
n->concurrent = false;
$$ = (Node *)n;
}
;
...
...
@@ -6292,6 +6332,7 @@ RemoveOperStmt:
n->arguments = list_make1($4);
n->behavior = $5;
n->missing_ok = false;
n->concurrent = false;
$$ = (Node *)n;
}
| DROP OPERATOR IF_P EXISTS any_operator oper_argtypes opt_drop_behavior
...
...
@@ -6302,6 +6343,7 @@ RemoveOperStmt:
n->arguments = list_make1($6);
n->behavior = $7;
n->missing_ok = true;
n->concurrent = false;
$$ = (Node *)n;
}
;
...
...
@@ -6418,6 +6460,7 @@ DropCastStmt: DROP CAST opt_if_exists '(' Typename AS Typename ')' opt_drop_beha
n->arguments = list_make1(list_make1($7));
n->behavior = $9;
n->missing_ok = $3;
n->concurrent = false;
$$ = (Node *)n;
}
;
...
...
@@ -7339,6 +7382,7 @@ DropRuleStmt:
n->arguments = NIL;
n->behavior = $6;
n->missing_ok = false;
n->concurrent = false;
$$ = (Node *) n;
}
| DROP RULE IF_P EXISTS name ON any_name opt_drop_behavior
...
...
@@ -7349,6 +7393,7 @@ DropRuleStmt:
n->arguments = NIL;
n->behavior = $8;
n->missing_ok = true;
n->concurrent = false;
$$ = (Node *) n;
}
;
...
...
src/backend/tcop/utility.c
浏览文件 @
8cb53654
...
...
@@ -631,10 +631,15 @@ standard_ProcessUtility(Node *parsetree,
case
T_DropStmt
:
switch
(((
DropStmt
*
)
parsetree
)
->
removeType
)
{
case
OBJECT_INDEX
:
if
(((
DropStmt
*
)
parsetree
)
->
concurrent
)
PreventTransactionChain
(
isTopLevel
,
"DROP INDEX CONCURRENTLY"
);
/* fall through */
case
OBJECT_TABLE
:
case
OBJECT_SEQUENCE
:
case
OBJECT_VIEW
:
case
OBJECT_INDEX
:
case
OBJECT_FOREIGN_TABLE
:
RemoveRelations
((
DropStmt
*
)
parsetree
);
break
;
...
...
src/backend/utils/cache/relcache.c
浏览文件 @
8cb53654
...
...
@@ -3355,6 +3355,12 @@ RelationGetIndexList(Relation relation)
oidvector
*
indclass
;
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 */
result
=
insert_ordered_oid
(
result
,
index
->
indexrelid
);
...
...
src/include/catalog/dependency.h
浏览文件 @
8cb53654
...
...
@@ -153,6 +153,7 @@ typedef enum ObjectClass
/* in dependency.c */
#define PERFORM_DELETION_INTERNAL 0x0001
#define PERFORM_DELETION_CONCURRENTLY 0x0002
extern
void
performDeletion
(
const
ObjectAddress
*
object
,
DropBehavior
behavior
,
int
flags
);
...
...
src/include/catalog/index.h
浏览文件 @
8cb53654
...
...
@@ -63,7 +63,7 @@ extern void index_constraint_create(Relation heapRelation,
bool
update_pgindex
,
bool
allow_system_table_mods
);
extern
void
index_drop
(
Oid
indexId
);
extern
void
index_drop
(
Oid
indexId
,
bool
concurrent
);
extern
IndexInfo
*
BuildIndexInfo
(
Relation
index
);
...
...
src/include/nodes/parsenodes.h
浏览文件 @
8cb53654
...
...
@@ -1909,6 +1909,7 @@ typedef struct DropStmt
ObjectType
removeType
;
/* object type */
DropBehavior
behavior
;
/* RESTRICT or CASCADE behavior */
bool
missing_ok
;
/* skip error if object is missing? */
bool
concurrent
;
/* drop index concurrently? */
}
DropStmt
;
/* ----------------------
...
...
src/test/regress/expected/create_index.out
浏览文件 @
8cb53654
...
...
@@ -2316,6 +2316,34 @@ Indexes:
"concur_index5" btree (f2) WHERE f1 = 'x'::text
"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;
--
-- Test ADD CONSTRAINT USING INDEX
...
...
src/test/regress/sql/create_index.sql
浏览文件 @
8cb53654
...
...
@@ -727,6 +727,27 @@ COMMIT;
\
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
;
--
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录