Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Gpdb
提交
367bc426
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,发现更多精彩内容 >>
提交
367bc426
编写于
7月 18, 2011
作者:
R
Robert Haas
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Avoid index rebuild for no-rewrite ALTER TABLE .. ALTER TYPE.
Noah Misch. Review and minor cosmetic changes by me.
上级
8f8a273c
变更
20
隐藏空白更改
内联
并排
Showing
20 changed file
with
348 addition
and
53 deletion
+348
-53
doc/src/sgml/xindex.sgml
doc/src/sgml/xindex.sgml
+7
-2
src/backend/bootstrap/bootparse.y
src/backend/bootstrap/bootparse.y
+3
-0
src/backend/catalog/heap.c
src/backend/catalog/heap.c
+15
-1
src/backend/catalog/index.c
src/backend/catalog/index.c
+4
-0
src/backend/catalog/storage.c
src/backend/catalog/storage.c
+6
-5
src/backend/catalog/toasting.c
src/backend/catalog/toasting.c
+1
-1
src/backend/commands/indexcmds.c
src/backend/commands/indexcmds.c
+208
-3
src/backend/commands/tablecmds.c
src/backend/commands/tablecmds.c
+82
-32
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/nodes/outfuncs.c
src/backend/nodes/outfuncs.c
+1
-0
src/backend/tcop/utility.c
src/backend/tcop/utility.c
+1
-0
src/backend/utils/cache/relcache.c
src/backend/utils/cache/relcache.c
+5
-6
src/backend/utils/cache/relmapper.c
src/backend/utils/cache/relmapper.c
+1
-1
src/include/catalog/heap.h
src/include/catalog/heap.h
+1
-0
src/include/catalog/index.h
src/include/catalog/index.h
+1
-0
src/include/catalog/storage.h
src/include/catalog/storage.h
+1
-1
src/include/commands/defrem.h
src/include/commands/defrem.h
+7
-1
src/include/nodes/parsenodes.h
src/include/nodes/parsenodes.h
+1
-0
src/include/utils/relcache.h
src/include/utils/relcache.h
+1
-0
未找到文件。
doc/src/sgml/xindex.sgml
浏览文件 @
367bc426
...
...
@@ -834,8 +834,10 @@ ALTER OPERATOR FAMILY integer_ops USING btree ADD
<para>
In a B-tree operator family, all the operators in the family must sort
compatibly, meaning that the transitive laws hold across all the data types
supported by the family: <quote>if A = B and B = C, then A =
C</>, and <quote>if A < B and B < C, then A < C</>. For each
supported by the family: <quote>if A = B and B = C, then A = C</>,
and <quote>if A < B and B < C, then A < C</>. Moreover, implicit
or binary coercion casts between types represented in the operator family
must not change the associated sort ordering. For each
operator in the family there must be a support function having the same
two input data types as the operator. It is recommended that a family be
complete, i.e., for each combination of data types, all operators are
...
...
@@ -851,6 +853,9 @@ ALTER OPERATOR FAMILY integer_ops USING btree ADD
by the family's equality operators, even when the values are of different
types. This is usually difficult to accomplish when the types have
different physical representations, but it can be done in some cases.
Furthermore, casting a value from one data type represented in the operator
family to another data type also represented in the operator family via
an implicit or binary coercion cast must not change the computed hash value.
Notice that there is only one support function per data type, not one
per equality operator. It is recommended that a family be complete, i.e.,
provide an equality operator for each combination of data types.
...
...
src/backend/bootstrap/bootparse.y
浏览文件 @
367bc426
...
...
@@ -217,6 +217,7 @@ Boot_CreateStmt:
PG_CATALOG_NAMESPACE,
shared_relation ? GLOBALTABLESPACE_OID : 0,
$3,
InvalidOid,
tupdesc,
RELKIND_RELATION,
RELPERSISTENCE_PERMANENT,
...
...
@@ -284,6 +285,7 @@ Boot_DeclareIndexStmt:
DefineIndex(makeRangeVar(NULL, $6, -1),
$3,
$4,
InvalidOid,
$8,
NULL,
$10,
...
...
@@ -302,6 +304,7 @@ Boot_DeclareUniqueIndexStmt:
DefineIndex(makeRangeVar(NULL, $7, -1),
$4,
$5,
InvalidOid,
$9,
NULL,
$11,
...
...
src/backend/catalog/heap.c
浏览文件 @
367bc426
...
...
@@ -229,7 +229,8 @@ SystemAttributeByName(const char *attname, bool relhasoids)
* heap_create - Create an uncataloged heap relation
*
* Note API change: the caller must now always provide the OID
* to use for the relation.
* to use for the relation. The relfilenode may (and, normally,
* should) be left unspecified.
*
* rel->rd_rel is initialized by RelationBuildLocalRelation,
* and is mostly zeroes at return.
...
...
@@ -240,6 +241,7 @@ heap_create(const char *relname,
Oid
relnamespace
,
Oid
reltablespace
,
Oid
relid
,
Oid
relfilenode
,
TupleDesc
tupDesc
,
char
relkind
,
char
relpersistence
,
...
...
@@ -296,6 +298,16 @@ heap_create(const char *relname,
break
;
}
/*
* Unless otherwise requested, the physical ID (relfilenode) is initially
* the same as the logical ID (OID). When the caller did specify a
* relfilenode, it already exists; do not attempt to create it.
*/
if
(
OidIsValid
(
relfilenode
))
create_storage
=
false
;
else
relfilenode
=
relid
;
/*
* Never allow a pg_class entry to explicitly specify the database's
* default tablespace in reltablespace; force it to zero instead. This
...
...
@@ -315,6 +327,7 @@ heap_create(const char *relname,
relnamespace
,
tupDesc
,
relid
,
relfilenode
,
reltablespace
,
shared_relation
,
mapped_relation
,
...
...
@@ -1103,6 +1116,7 @@ heap_create_with_catalog(const char *relname,
relnamespace
,
reltablespace
,
relid
,
InvalidOid
,
tupdesc
,
relkind
,
relpersistence
,
...
...
src/backend/catalog/index.c
浏览文件 @
367bc426
...
...
@@ -649,6 +649,8 @@ UpdateIndexRelation(Oid indexoid,
* indexRelationId: normally, pass InvalidOid to let this routine
* generate an OID for the index. During bootstrap this may be
* nonzero to specify a preselected OID.
* relFileNode: normally, pass InvalidOid to get new storage. May be
* nonzero to attach an existing valid build.
* indexInfo: same info executor uses to insert into the index
* indexColNames: column names to use for index (List of char *)
* accessMethodObjectId: OID of index AM to use
...
...
@@ -674,6 +676,7 @@ Oid
index_create
(
Relation
heapRelation
,
const
char
*
indexRelationName
,
Oid
indexRelationId
,
Oid
relFileNode
,
IndexInfo
*
indexInfo
,
List
*
indexColNames
,
Oid
accessMethodObjectId
,
...
...
@@ -813,6 +816,7 @@ index_create(Relation heapRelation,
namespaceId
,
tableSpaceId
,
indexRelationId
,
relFileNode
,
indexTupDesc
,
RELKIND_INDEX
,
relpersistence
,
...
...
src/backend/catalog/storage.c
浏览文件 @
367bc426
...
...
@@ -206,10 +206,13 @@ RelationDropStorage(Relation rel)
* The relation mapper fixes this by telling us to not delete such relations
* after all as part of its commit.
*
* We also use this to reuse an old build of an index during ALTER TABLE, this
* time removing the delete-at-commit entry.
*
* No-op if the relation is not among those scheduled for deletion.
*/
void
RelationPreserveStorage
(
RelFileNode
rnode
)
RelationPreserveStorage
(
RelFileNode
rnode
,
bool
atCommit
)
{
PendingRelDelete
*
pending
;
PendingRelDelete
*
prev
;
...
...
@@ -219,11 +222,9 @@ RelationPreserveStorage(RelFileNode rnode)
for
(
pending
=
pendingDeletes
;
pending
!=
NULL
;
pending
=
next
)
{
next
=
pending
->
next
;
if
(
RelFileNodeEquals
(
rnode
,
pending
->
relnode
))
if
(
RelFileNodeEquals
(
rnode
,
pending
->
relnode
)
&&
pending
->
atCommit
==
atCommit
)
{
/* we should only find delete-on-abort entries, else trouble */
if
(
pending
->
atCommit
)
elog
(
ERROR
,
"cannot preserve a delete-on-commit relation"
);
/* unlink and delete list entry */
if
(
prev
)
prev
->
next
=
next
;
...
...
src/backend/catalog/toasting.c
浏览文件 @
367bc426
...
...
@@ -274,7 +274,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, Datum reloptio
coloptions
[
0
]
=
0
;
coloptions
[
1
]
=
0
;
index_create
(
toast_rel
,
toast_idxname
,
toastIndexOid
,
index_create
(
toast_rel
,
toast_idxname
,
toastIndexOid
,
InvalidOid
,
indexInfo
,
list_make2
(
"chunk_id"
,
"chunk_seq"
),
BTREE_AM_OID
,
...
...
src/backend/commands/indexcmds.c
浏览文件 @
367bc426
...
...
@@ -72,6 +72,198 @@ static Oid GetIndexOpClass(List *opclass, Oid attrType,
static
char
*
ChooseIndexNameAddition
(
List
*
colnames
);
/*
* CheckIndexCompatible
* Determine whether an existing index definition is compatible with a
* prospective index definition, such that the existing index storage
* could become the storage of the new index, avoiding a rebuild.
*
* 'heapRelation': the relation the index would apply to.
* 'accessMethodName': name of the AM to use.
* 'attributeList': a list of IndexElem specifying columns and expressions
* to index on.
* 'exclusionOpNames': list of names of exclusion-constraint operators,
* or NIL if not an exclusion constraint.
*
* This is tailored to the needs of ALTER TABLE ALTER TYPE, which recreates
* any indexes that depended on a changing column from their pg_get_indexdef
* or pg_get_constraintdef definitions. We omit some of the sanity checks of
* DefineIndex. We assume that the old and new indexes have the same number
* of columns and that if one has an expression column or predicate, both do.
* Errors arising from the attribute list still apply.
*
* Most column type changes that can skip a table rewrite will not invalidate
* indexes. For btree and hash indexes, we assume continued validity when
* each column of an index would have the same operator family before and
* after the change. Since we do not document a contract for GIN or GiST
* operator families, we require an exact operator class match for them and
* for any other access methods.
*
* DefineIndex always verifies that each exclusion operator shares an operator
* family with its corresponding index operator class. For access methods
* having no operator family contract, confirm that the old and new indexes
* use the exact same exclusion operator. For btree and hash, there's nothing
* more to check.
*
* We do not yet implement a test to verify compatibility of expression
* columns or predicates, so assume any such index is incompatible.
*/
bool
CheckIndexCompatible
(
Oid
oldId
,
RangeVar
*
heapRelation
,
char
*
accessMethodName
,
List
*
attributeList
,
List
*
exclusionOpNames
)
{
bool
isconstraint
;
Oid
*
collationObjectId
;
Oid
*
classObjectId
;
Oid
accessMethodId
;
Oid
relationId
;
HeapTuple
tuple
;
Form_pg_am
accessMethodForm
;
bool
amcanorder
;
RegProcedure
amoptions
;
int16
*
coloptions
;
IndexInfo
*
indexInfo
;
int
numberOfAttributes
;
int
old_natts
;
bool
isnull
;
bool
family_am
;
bool
ret
=
true
;
oidvector
*
old_indclass
;
oidvector
*
old_indcollation
;
int
i
;
Datum
d
;
/* Caller should already have the relation locked in some way. */
relationId
=
RangeVarGetRelid
(
heapRelation
,
NoLock
,
false
,
false
);
/*
* We can pretend isconstraint = false unconditionally. It only serves to
* decide the text of an error message that should never happen for us.
*/
isconstraint
=
false
;
numberOfAttributes
=
list_length
(
attributeList
);
Assert
(
numberOfAttributes
>
0
);
Assert
(
numberOfAttributes
<=
INDEX_MAX_KEYS
);
/* look up the access method */
tuple
=
SearchSysCache1
(
AMNAME
,
PointerGetDatum
(
accessMethodName
));
if
(
!
HeapTupleIsValid
(
tuple
))
ereport
(
ERROR
,
(
errcode
(
ERRCODE_UNDEFINED_OBJECT
),
errmsg
(
"access method
\"
%s
\"
does not exist"
,
accessMethodName
)));
accessMethodId
=
HeapTupleGetOid
(
tuple
);
accessMethodForm
=
(
Form_pg_am
)
GETSTRUCT
(
tuple
);
amcanorder
=
accessMethodForm
->
amcanorder
;
amoptions
=
accessMethodForm
->
amoptions
;
ReleaseSysCache
(
tuple
);
/*
* Compute the operator classes, collations, and exclusion operators
* for the new index, so we can test whether it's compatible with the
* existing one. Note that ComputeIndexAttrs might fail here, but that's
* OK: DefineIndex would have called this function with the same arguments
* later on, and it would have failed then anyway.
*/
indexInfo
=
makeNode
(
IndexInfo
);
indexInfo
->
ii_Expressions
=
NIL
;
indexInfo
->
ii_ExpressionsState
=
NIL
;
indexInfo
->
ii_PredicateState
=
NIL
;
indexInfo
->
ii_ExclusionOps
=
NULL
;
indexInfo
->
ii_ExclusionProcs
=
NULL
;
indexInfo
->
ii_ExclusionStrats
=
NULL
;
collationObjectId
=
(
Oid
*
)
palloc
(
numberOfAttributes
*
sizeof
(
Oid
));
classObjectId
=
(
Oid
*
)
palloc
(
numberOfAttributes
*
sizeof
(
Oid
));
coloptions
=
(
int16
*
)
palloc
(
numberOfAttributes
*
sizeof
(
int16
));
ComputeIndexAttrs
(
indexInfo
,
collationObjectId
,
classObjectId
,
coloptions
,
attributeList
,
exclusionOpNames
,
relationId
,
accessMethodName
,
accessMethodId
,
amcanorder
,
isconstraint
);
/* Get the soon-obsolete pg_index tuple. */
tuple
=
SearchSysCache1
(
INDEXRELID
,
ObjectIdGetDatum
(
oldId
));
if
(
!
HeapTupleIsValid
(
tuple
))
elog
(
ERROR
,
"cache lookup failed for index %u"
,
oldId
);
/* We don't assess expressions or predicates; assume incompatibility. */
if
(
!
(
heap_attisnull
(
tuple
,
Anum_pg_index_indpred
)
&&
heap_attisnull
(
tuple
,
Anum_pg_index_indexprs
)))
{
ReleaseSysCache
(
tuple
);
return
false
;
}
/*
* If the old and new operator class of any index column differ in
* operator family or collation, regard the old index as incompatible.
* For access methods other than btree and hash, a family match has no
* defined meaning; require an exact operator class match.
*/
old_natts
=
((
Form_pg_index
)
GETSTRUCT
(
tuple
))
->
indnatts
;
Assert
(
old_natts
==
numberOfAttributes
);
d
=
SysCacheGetAttr
(
INDEXRELID
,
tuple
,
Anum_pg_index_indcollation
,
&
isnull
);
Assert
(
!
isnull
);
old_indcollation
=
(
oidvector
*
)
DatumGetPointer
(
d
);
d
=
SysCacheGetAttr
(
INDEXRELID
,
tuple
,
Anum_pg_index_indclass
,
&
isnull
);
Assert
(
!
isnull
);
old_indclass
=
(
oidvector
*
)
DatumGetPointer
(
d
);
family_am
=
accessMethodId
==
BTREE_AM_OID
||
accessMethodId
==
HASH_AM_OID
;
for
(
i
=
0
;
i
<
old_natts
;
i
++
)
{
Oid
old_class
=
old_indclass
->
values
[
i
];
Oid
new_class
=
classObjectId
[
i
];
if
(
!
(
old_indcollation
->
values
[
i
]
==
collationObjectId
[
i
]
&&
(
old_class
==
new_class
||
(
family_am
&&
(
get_opclass_family
(
old_class
)
==
get_opclass_family
(
new_class
))))))
{
ret
=
false
;
break
;
}
}
ReleaseSysCache
(
tuple
);
/*
* For btree and hash, exclusion operators need only fall in the same
* operator family; ComputeIndexAttrs already verified that much. If we
* get this far, we know that the index operator family has not changed,
* and we're done. For other access methods, require exact matches for
* all exclusion operators.
*/
if
(
ret
&&
!
family_am
&&
indexInfo
->
ii_ExclusionOps
!=
NULL
)
{
Relation
irel
;
Oid
*
old_operators
,
*
old_procs
;
uint16
*
old_strats
;
/* Caller probably already holds a stronger lock. */
irel
=
index_open
(
oldId
,
AccessShareLock
);
RelationGetExclusionInfo
(
irel
,
&
old_operators
,
&
old_procs
,
&
old_strats
);
for
(
i
=
0
;
i
<
old_natts
;
i
++
)
if
(
old_operators
[
i
]
!=
indexInfo
->
ii_ExclusionOps
[
i
])
{
ret
=
false
;
break
;
}
index_close
(
irel
,
NoLock
);
}
return
ret
;
}
/*
* DefineIndex
* Creates a new index.
...
...
@@ -81,6 +273,8 @@ static char *ChooseIndexNameAddition(List *colnames);
* that a nonconflicting default name should be picked.
* 'indexRelationId': normally InvalidOid, but during bootstrap can be
* nonzero to specify a preselected OID for the index.
* 'relFileNode': normally InvalidOid, but can be nonzero to specify existing
* storage constituting a valid build of this index.
* 'accessMethodName': name of the AM to use.
* 'tableSpaceName': name of the tablespace to create the index in.
* NULL specifies using the appropriate default.
...
...
@@ -103,11 +297,14 @@ static char *ChooseIndexNameAddition(List *colnames);
* it will be filled later.
* 'quiet': suppress the NOTICE chatter ordinarily provided for constraints.
* 'concurrent': avoid blocking writers to the table while building.
*
* Returns the OID of the created index.
*/
vo
id
O
id
DefineIndex
(
RangeVar
*
heapRelation
,
char
*
indexRelationName
,
Oid
indexRelationId
,
Oid
relFileNode
,
char
*
accessMethodName
,
char
*
tableSpaceName
,
List
*
attributeList
,
...
...
@@ -402,12 +599,18 @@ DefineIndex(RangeVar *heapRelation,
indexRelationName
,
RelationGetRelationName
(
rel
))));
}
/*
* A valid relFileNode implies that we already have a built form of the
* index. The caller should also decline any index build.
*/
Assert
(
!
OidIsValid
(
relFileNode
)
||
(
skip_build
&&
!
concurrent
));
/*
* Make the catalog entries for the index, including constraints. Then, if
* not skip_build || concurrent, actually build the index.
*/
indexRelationId
=
index_create
(
rel
,
indexRelationName
,
indexRelationId
,
index_create
(
rel
,
indexRelationName
,
indexRelationId
,
relFileNode
,
indexInfo
,
indexColNames
,
accessMethodId
,
tablespaceId
,
collationObjectId
,
classObjectId
,
...
...
@@ -421,7 +624,7 @@ DefineIndex(RangeVar *heapRelation,
{
/* Close the heap and we're done, in the non-concurrent case */
heap_close
(
rel
,
NoLock
);
return
;
return
indexRelationId
;
}
/* save lockrelid and locktag for below, then close rel */
...
...
@@ -709,6 +912,8 @@ DefineIndex(RangeVar *heapRelation,
* Last thing to do is release the session-level lock on the parent table.
*/
UnlockRelationIdForSession
(
&
heaprelid
,
ShareUpdateExclusiveLock
);
return
indexRelationId
;
}
...
...
src/backend/commands/tablecmds.c
浏览文件 @
367bc426
...
...
@@ -347,7 +347,9 @@ static bool ATColumnChangeRequiresRewrite(Node *expr, AttrNumber varattno);
static
void
ATExecAlterColumnType
(
AlteredTableInfo
*
tab
,
Relation
rel
,
AlterTableCmd
*
cmd
,
LOCKMODE
lockmode
);
static
void
ATPostAlterTypeCleanup
(
List
**
wqueue
,
AlteredTableInfo
*
tab
,
LOCKMODE
lockmode
);
static
void
ATPostAlterTypeParse
(
char
*
cmd
,
List
**
wqueue
,
LOCKMODE
lockmode
);
static
void
ATPostAlterTypeParse
(
Oid
oldId
,
char
*
cmd
,
List
**
wqueue
,
LOCKMODE
lockmode
,
bool
rewrite
);
static
void
TryReuseIndex
(
Oid
oldId
,
IndexStmt
*
stmt
);
static
void
change_owner_recurse_to_sequences
(
Oid
relationOid
,
Oid
newOwnerId
,
LOCKMODE
lockmode
);
static
void
ATExecClusterOn
(
Relation
rel
,
const
char
*
indexName
,
LOCKMODE
lockmode
);
...
...
@@ -5232,37 +5234,52 @@ ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
bool
check_rights
;
bool
skip_build
;
bool
quiet
;
Oid
new_index
;
Assert
(
IsA
(
stmt
,
IndexStmt
));
/* suppress schema rights check when rebuilding existing index */
check_rights
=
!
is_rebuild
;
/* skip index build if phase 3 will
have to rewrite table anyway
*/
skip_build
=
tab
->
rewrite
;
/* skip index build if phase 3 will
do it or we're reusing an old one
*/
skip_build
=
tab
->
rewrite
||
OidIsValid
(
stmt
->
oldNode
)
;
/* suppress notices when rebuilding existing index */
quiet
=
is_rebuild
;
/* The IndexStmt has already been through transformIndexStmt */
DefineIndex
(
stmt
->
relation
,
/* relation */
stmt
->
idxname
,
/* index name */
InvalidOid
,
/* no predefined OID */
stmt
->
accessMethod
,
/* am name */
stmt
->
tableSpace
,
stmt
->
indexParams
,
/* parameters */
(
Expr
*
)
stmt
->
whereClause
,
stmt
->
options
,
stmt
->
excludeOpNames
,
stmt
->
unique
,
stmt
->
primary
,
stmt
->
isconstraint
,
stmt
->
deferrable
,
stmt
->
initdeferred
,
true
,
/* is_alter_table */
check_rights
,
skip_build
,
quiet
,
false
);
new_index
=
DefineIndex
(
stmt
->
relation
,
/* relation */
stmt
->
idxname
,
/* index name */
InvalidOid
,
/* no predefined OID */
stmt
->
oldNode
,
stmt
->
accessMethod
,
/* am name */
stmt
->
tableSpace
,
stmt
->
indexParams
,
/* parameters */
(
Expr
*
)
stmt
->
whereClause
,
stmt
->
options
,
stmt
->
excludeOpNames
,
stmt
->
unique
,
stmt
->
primary
,
stmt
->
isconstraint
,
stmt
->
deferrable
,
stmt
->
initdeferred
,
true
,
/* is_alter_table */
check_rights
,
skip_build
,
quiet
,
false
);
/*
* If TryReuseIndex() stashed a relfilenode for us, we used it for the new
* index instead of building from scratch. The DROP of the old edition of
* this index will have scheduled the storage for deletion at commit, so
* cancel that pending deletion.
*/
if
(
OidIsValid
(
stmt
->
oldNode
))
{
Relation
irel
=
index_open
(
new_index
,
NoLock
);
RelationPreserveStorage
(
irel
->
rd_node
,
true
);
index_close
(
irel
,
NoLock
);
}
}
/*
...
...
@@ -7389,7 +7406,8 @@ static void
ATPostAlterTypeCleanup
(
List
**
wqueue
,
AlteredTableInfo
*
tab
,
LOCKMODE
lockmode
)
{
ObjectAddress
obj
;
ListCell
*
l
;
ListCell
*
def_item
;
ListCell
*
oid_item
;
/*
* Re-parse the index and constraint definitions, and attach them to the
...
...
@@ -7399,10 +7417,14 @@ ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode)
* that before dropping. It's safe because the parser won't actually look
* at the catalogs to detect the existing entry.
*/
foreach
(
l
,
tab
->
changedIndexDefs
)
ATPostAlterTypeParse
((
char
*
)
lfirst
(
l
),
wqueue
,
lockmode
);
foreach
(
l
,
tab
->
changedConstraintDefs
)
ATPostAlterTypeParse
((
char
*
)
lfirst
(
l
),
wqueue
,
lockmode
);
forboth
(
oid_item
,
tab
->
changedConstraintOids
,
def_item
,
tab
->
changedConstraintDefs
)
ATPostAlterTypeParse
(
lfirst_oid
(
oid_item
),
(
char
*
)
lfirst
(
def_item
),
wqueue
,
lockmode
,
tab
->
rewrite
);
forboth
(
oid_item
,
tab
->
changedIndexOids
,
def_item
,
tab
->
changedIndexDefs
)
ATPostAlterTypeParse
(
lfirst_oid
(
oid_item
),
(
char
*
)
lfirst
(
def_item
),
wqueue
,
lockmode
,
tab
->
rewrite
);
/*
* Now we can drop the existing constraints and indexes --- constraints
...
...
@@ -7412,18 +7434,18 @@ ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode)
* should be okay to use DROP_RESTRICT here, since nothing else should be
* depending on these objects.
*/
foreach
(
l
,
tab
->
changedConstraintOids
)
foreach
(
oid_item
,
tab
->
changedConstraintOids
)
{
obj
.
classId
=
ConstraintRelationId
;
obj
.
objectId
=
lfirst_oid
(
l
);
obj
.
objectId
=
lfirst_oid
(
oid_item
);
obj
.
objectSubId
=
0
;
performDeletion
(
&
obj
,
DROP_RESTRICT
);
}
foreach
(
l
,
tab
->
changedIndexOids
)
foreach
(
oid_item
,
tab
->
changedIndexOids
)
{
obj
.
classId
=
RelationRelationId
;
obj
.
objectId
=
lfirst_oid
(
l
);
obj
.
objectId
=
lfirst_oid
(
oid_item
);
obj
.
objectSubId
=
0
;
performDeletion
(
&
obj
,
DROP_RESTRICT
);
}
...
...
@@ -7435,7 +7457,8 @@ ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode)
}
static
void
ATPostAlterTypeParse
(
char
*
cmd
,
List
**
wqueue
,
LOCKMODE
lockmode
)
ATPostAlterTypeParse
(
Oid
oldId
,
char
*
cmd
,
List
**
wqueue
,
LOCKMODE
lockmode
,
bool
rewrite
)
{
List
*
raw_parsetree_list
;
List
*
querytree_list
;
...
...
@@ -7482,6 +7505,9 @@ ATPostAlterTypeParse(char *cmd, List **wqueue, LOCKMODE lockmode)
IndexStmt
*
stmt
=
(
IndexStmt
*
)
stm
;
AlterTableCmd
*
newcmd
;
if
(
!
rewrite
)
TryReuseIndex
(
oldId
,
stmt
);
rel
=
relation_openrv
(
stmt
->
relation
,
lockmode
);
tab
=
ATGetQueueEntry
(
wqueue
,
rel
);
newcmd
=
makeNode
(
AlterTableCmd
);
...
...
@@ -7506,6 +7532,10 @@ ATPostAlterTypeParse(char *cmd, List **wqueue, LOCKMODE lockmode)
switch
(
cmd
->
subtype
)
{
case
AT_AddIndex
:
Assert
(
IsA
(
cmd
->
def
,
IndexStmt
));
if
(
!
rewrite
)
TryReuseIndex
(
get_constraint_index
(
oldId
),
(
IndexStmt
*
)
cmd
->
def
);
cmd
->
subtype
=
AT_ReAddIndex
;
tab
->
subcmds
[
AT_PASS_OLD_INDEX
]
=
lappend
(
tab
->
subcmds
[
AT_PASS_OLD_INDEX
],
cmd
);
...
...
@@ -7529,6 +7559,26 @@ ATPostAlterTypeParse(char *cmd, List **wqueue, LOCKMODE lockmode)
}
}
/*
* Subroutine for ATPostAlterTypeParse(). Calls out to CheckIndexCompatible()
* for the real analysis, then mutates the IndexStmt based on that verdict.
*/
static
void
TryReuseIndex
(
Oid
oldId
,
IndexStmt
*
stmt
)
{
if
(
CheckIndexCompatible
(
oldId
,
stmt
->
relation
,
stmt
->
accessMethod
,
stmt
->
indexParams
,
stmt
->
excludeOpNames
))
{
Relation
irel
=
index_open
(
oldId
,
NoLock
);
stmt
->
oldNode
=
irel
->
rd_node
.
relNode
;
index_close
(
irel
,
NoLock
);
}
}
/*
* ALTER TABLE OWNER
...
...
src/backend/nodes/copyfuncs.c
浏览文件 @
367bc426
...
...
@@ -2807,6 +2807,7 @@ _copyIndexStmt(IndexStmt *from)
COPY_NODE_FIELD
(
whereClause
);
COPY_NODE_FIELD
(
excludeOpNames
);
COPY_SCALAR_FIELD
(
indexOid
);
COPY_SCALAR_FIELD
(
oldNode
);
COPY_SCALAR_FIELD
(
unique
);
COPY_SCALAR_FIELD
(
primary
);
COPY_SCALAR_FIELD
(
isconstraint
);
...
...
src/backend/nodes/equalfuncs.c
浏览文件 @
367bc426
...
...
@@ -1245,6 +1245,7 @@ _equalIndexStmt(IndexStmt *a, IndexStmt *b)
COMPARE_NODE_FIELD
(
whereClause
);
COMPARE_NODE_FIELD
(
excludeOpNames
);
COMPARE_SCALAR_FIELD
(
indexOid
);
COMPARE_SCALAR_FIELD
(
oldNode
);
COMPARE_SCALAR_FIELD
(
unique
);
COMPARE_SCALAR_FIELD
(
primary
);
COMPARE_SCALAR_FIELD
(
isconstraint
);
...
...
src/backend/nodes/outfuncs.c
浏览文件 @
367bc426
...
...
@@ -1976,6 +1976,7 @@ _outIndexStmt(StringInfo str, IndexStmt *node)
WRITE_NODE_FIELD
(
whereClause
);
WRITE_NODE_FIELD
(
excludeOpNames
);
WRITE_OID_FIELD
(
indexOid
);
WRITE_OID_FIELD
(
oldNode
);
WRITE_BOOL_FIELD
(
unique
);
WRITE_BOOL_FIELD
(
primary
);
WRITE_BOOL_FIELD
(
isconstraint
);
...
...
src/backend/tcop/utility.c
浏览文件 @
367bc426
...
...
@@ -953,6 +953,7 @@ standard_ProcessUtility(Node *parsetree,
DefineIndex
(
stmt
->
relation
,
/* relation */
stmt
->
idxname
,
/* index name */
InvalidOid
,
/* no predefined OID */
InvalidOid
,
/* no previous storage */
stmt
->
accessMethod
,
/* am name */
stmt
->
tableSpace
,
stmt
->
indexParams
,
/* parameters */
...
...
src/backend/utils/cache/relcache.c
浏览文件 @
367bc426
...
...
@@ -2395,6 +2395,7 @@ RelationBuildLocalRelation(const char *relname,
Oid
relnamespace
,
TupleDesc
tupDesc
,
Oid
relid
,
Oid
relfilenode
,
Oid
reltablespace
,
bool
shared_relation
,
bool
mapped_relation
,
...
...
@@ -2529,10 +2530,8 @@ RelationBuildLocalRelation(const char *relname,
/*
* Insert relation physical and logical identifiers (OIDs) into the right
* places. Note that the physical ID (relfilenode) is initially the same
* as the logical ID (OID); except that for a mapped relation, we set
* relfilenode to zero and rely on RelationInitPhysicalAddr to consult the
* map.
* places. For a mapped relation, we set relfilenode to zero and rely on
* RelationInitPhysicalAddr to consult the map.
*/
rel
->
rd_rel
->
relisshared
=
shared_relation
;
...
...
@@ -2547,10 +2546,10 @@ RelationBuildLocalRelation(const char *relname,
{
rel
->
rd_rel
->
relfilenode
=
InvalidOid
;
/* Add it to the active mapping information */
RelationMapUpdateMap
(
relid
,
rel
id
,
shared_relation
,
true
);
RelationMapUpdateMap
(
relid
,
rel
filenode
,
shared_relation
,
true
);
}
else
rel
->
rd_rel
->
relfilenode
=
rel
id
;
rel
->
rd_rel
->
relfilenode
=
rel
filenode
;
RelationInitLockInfo
(
rel
);
/* see lmgr.c */
...
...
src/backend/utils/cache/relmapper.c
浏览文件 @
367bc426
...
...
@@ -792,7 +792,7 @@ write_relmap_file(bool shared, RelMapFile *newmap,
rnode
.
spcNode
=
tsid
;
rnode
.
dbNode
=
dbid
;
rnode
.
relNode
=
newmap
->
mappings
[
i
].
mapfilenode
;
RelationPreserveStorage
(
rnode
);
RelationPreserveStorage
(
rnode
,
false
);
}
}
...
...
src/include/catalog/heap.h
浏览文件 @
367bc426
...
...
@@ -39,6 +39,7 @@ extern Relation heap_create(const char *relname,
Oid
relnamespace
,
Oid
reltablespace
,
Oid
relid
,
Oid
relfilenode
,
TupleDesc
tupDesc
,
char
relkind
,
char
relpersistence
,
...
...
src/include/catalog/index.h
浏览文件 @
367bc426
...
...
@@ -35,6 +35,7 @@ extern void index_check_primary_key(Relation heapRel,
extern
Oid
index_create
(
Relation
heapRelation
,
const
char
*
indexRelationName
,
Oid
indexRelationId
,
Oid
relFileNode
,
IndexInfo
*
indexInfo
,
List
*
indexColNames
,
Oid
accessMethodObjectId
,
...
...
src/include/catalog/storage.h
浏览文件 @
367bc426
...
...
@@ -22,7 +22,7 @@
extern
void
RelationCreateStorage
(
RelFileNode
rnode
,
char
relpersistence
);
extern
void
RelationDropStorage
(
Relation
rel
);
extern
void
RelationPreserveStorage
(
RelFileNode
rnode
);
extern
void
RelationPreserveStorage
(
RelFileNode
rnode
,
bool
atCommit
);
extern
void
RelationTruncate
(
Relation
rel
,
BlockNumber
nblocks
);
/*
...
...
src/include/commands/defrem.h
浏览文件 @
367bc426
...
...
@@ -18,9 +18,10 @@
/* commands/indexcmds.c */
extern
vo
id
DefineIndex
(
RangeVar
*
heapRelation
,
extern
O
id
DefineIndex
(
RangeVar
*
heapRelation
,
char
*
indexRelationName
,
Oid
indexRelationId
,
Oid
relFileNode
,
char
*
accessMethodName
,
char
*
tableSpaceName
,
List
*
attributeList
,
...
...
@@ -49,6 +50,11 @@ extern char *ChooseIndexName(const char *tabname, Oid namespaceId,
List
*
colnames
,
List
*
exclusionOpNames
,
bool
primary
,
bool
isconstraint
);
extern
List
*
ChooseIndexColumnNames
(
List
*
indexElems
);
extern
bool
CheckIndexCompatible
(
Oid
oldId
,
RangeVar
*
heapRelation
,
char
*
accessMethodName
,
List
*
attributeList
,
List
*
exclusionOpNames
);
extern
Oid
GetDefaultOpClass
(
Oid
type_id
,
Oid
am_id
);
/* commands/functioncmds.c */
...
...
src/include/nodes/parsenodes.h
浏览文件 @
367bc426
...
...
@@ -2062,6 +2062,7 @@ typedef struct IndexStmt
Node
*
whereClause
;
/* qualification (partial-index predicate) */
List
*
excludeOpNames
;
/* exclusion operator names, or NIL if none */
Oid
indexOid
;
/* OID of an existing index, if any */
Oid
oldNode
;
/* relfilenode of my former self */
bool
unique
;
/* is index unique? */
bool
primary
;
/* is index on primary key? */
bool
isconstraint
;
/* is it from a CONSTRAINT clause? */
...
...
src/include/utils/relcache.h
浏览文件 @
367bc426
...
...
@@ -67,6 +67,7 @@ extern Relation RelationBuildLocalRelation(const char *relname,
Oid
relnamespace
,
TupleDesc
tupDesc
,
Oid
relid
,
Oid
relfilenode
,
Oid
reltablespace
,
bool
shared_relation
,
bool
mapped_relation
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录