Enter
This commit is contained in:
parent
38591f1cda
commit
32c54300a3
|
|
@ -53,34 +53,34 @@
|
|||
*/
|
||||
static uint64 gen_usertable_hash_sum(Relation rel)
|
||||
{
|
||||
uint64 rel_hash = 0;
|
||||
bool is_null = false;
|
||||
int hash_natt = user_hash_attrno(rel->rd_att);
|
||||
uint64 rel_hash = 0;//初始化关系哈希和为零
|
||||
bool is_null = false;//初始化标志位为假
|
||||
int hash_natt = user_hash_attrno(rel->rd_att);//获取用户关系的哈希属性编号
|
||||
Assert(hash_natt >= 0);
|
||||
HeapTuple tuple;
|
||||
TupleDesc desc = rel->rd_att;
|
||||
Snapshot snapshot = GetActiveSnapshot();
|
||||
TableScanDesc scan;
|
||||
if (RELATION_CREATE_BUCKET(rel)) {
|
||||
Relation bucket_rel = NULL;
|
||||
oidvector *bucket_list = searchHashBucketByOid(rel->rd_bucketoid);
|
||||
for (int i = 0; i < bucket_list->dim1; i++) {
|
||||
bucket_rel = bucketGetRelation(rel, NULL, bucket_list->values[i]);
|
||||
scan = heap_beginscan(bucket_rel, snapshot, 0, NULL);
|
||||
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) {
|
||||
HeapTuple tuple;//用于存储关系的元组
|
||||
TupleDesc desc = rel->rd_att;//获取关系的元组描述
|
||||
Snapshot snapshot = GetActiveSnapshot();//活动快照
|
||||
TableScanDesc scan;//表扫描器
|
||||
if (RELATION_CREATE_BUCKET(rel)) {//如果关系是哈希分区表啊
|
||||
Relation bucket_rel = NULL;//初始化分区关系
|
||||
oidvector *bucket_list = searchHashBucketByOid(rel->rd_bucketoid);//获取哈希分区列表
|
||||
for (int i = 0; i < bucket_list->dim1; i++) {//遍历哈希分区列表
|
||||
bucket_rel = bucketGetRelation(rel, NULL, bucket_list->values[i]);//获取哈希分区关系
|
||||
scan = heap_beginscan(bucket_rel, snapshot, 0, NULL);//开始扫描分区表
|
||||
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) {//遍历分区表中的元组
|
||||
rel_hash += DatumGetUInt64(heap_getattr(tuple, hash_natt + 1, desc, &is_null));
|
||||
}
|
||||
heap_endscan(scan);
|
||||
}//获取哈希值累加到关系哈希和中
|
||||
heap_endscan(scan);//结束扫描
|
||||
bucketCloseRelation(bucket_rel);
|
||||
}
|
||||
} else {
|
||||
scan = heap_beginscan(rel, snapshot, 0, NULL);
|
||||
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) {
|
||||
} else {//如果关系不是哈希分区表
|
||||
scan = heap_beginscan(rel, snapshot, 0, NULL);//开始扫描关系
|
||||
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) {//遍历关系中的元组
|
||||
rel_hash += DatumGetUInt64(heap_getattr(tuple, hash_natt + 1, desc, &is_null));
|
||||
}
|
||||
heap_endscan(scan);
|
||||
heap_endscan(scan);//结束扫描
|
||||
}
|
||||
return rel_hash;
|
||||
return rel_hash;//返回关系哈希和
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -92,27 +92,27 @@ static uint64 gen_usertable_hash_sum(Relation rel)
|
|||
*/
|
||||
static uint64 get_usertable_hash_sum(Oid relid)
|
||||
{
|
||||
uint64 rel_hash = 0;
|
||||
uint64 rel_hash = 0;//初始化关系哈希和为零
|
||||
Relation rel = NULL;
|
||||
rel = heap_open(relid, AccessShareLock);
|
||||
if (!RelationIsPartitioned(rel)) {
|
||||
rel_hash = gen_usertable_hash_sum(rel);
|
||||
} else {
|
||||
List *partition_list = NIL;
|
||||
rel = heap_open(relid, AccessShareLock);//打开用户表关系并获取共享锁
|
||||
if (!RelationIsPartitioned(rel)) {//如果用户表不是分区表
|
||||
rel_hash = gen_usertable_hash_sum(rel);//调用函数
|
||||
} else {//如果是分区表
|
||||
List *partition_list = NIL;//初始化
|
||||
ListCell *lc = NULL;
|
||||
Partition part;
|
||||
Relation fake_rel;
|
||||
partition_list = relationGetPartitionList(rel, AccessShareLock);
|
||||
foreach (lc, partition_list) {
|
||||
part = (Partition)lfirst(lc);
|
||||
Partition part;//分区
|
||||
Relation fake_rel;//假分区关系
|
||||
partition_list = relationGetPartitionList(rel, AccessShareLock);//获取分区列表
|
||||
foreach (lc, partition_list) {//遍历分区列表
|
||||
part = (Partition)lfirst(lc);//获取分区
|
||||
fake_rel = partitionGetRelation(rel, part);
|
||||
rel_hash += gen_usertable_hash_sum(fake_rel);
|
||||
releaseDummyRelation(&fake_rel);
|
||||
rel_hash += gen_usertable_hash_sum(fake_rel);//调用函数计算分区关系哈希和并累加
|
||||
releaseDummyRelation(&fake_rel);//释放分区关系
|
||||
}
|
||||
releasePartitionList(rel, &partition_list, AccessShareLock);
|
||||
releasePartitionList(rel, &partition_list, AccessShareLock);// 释放分区列表
|
||||
}
|
||||
heap_close(rel, AccessShareLock);
|
||||
return rel_hash;
|
||||
heap_close(rel, AccessShareLock);// 关闭用户表关系并释放共享锁
|
||||
return rel_hash;// 返回关系哈希和
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -122,28 +122,28 @@ static uint64 get_usertable_hash_sum(Oid relid)
|
|||
*/
|
||||
static uint64 get_histtable_hash_sum(Oid hist_oid)
|
||||
{
|
||||
uint64 rel_hash = 0;
|
||||
bool is_null = false;
|
||||
Relation hist_rel;
|
||||
uint64 rel_hash = 0;// 初始化哈希差值为零
|
||||
bool is_null = false;// 初始化标志位为假
|
||||
Relation hist_rel;// 初始化历史表关系
|
||||
TableScanDesc scan;
|
||||
HeapTuple tuple;
|
||||
HeapTuple tuple; // 用于存储历史表中的元组
|
||||
Snapshot snapshot = GetActiveSnapshot();
|
||||
|
||||
hist_rel = heap_open(hist_oid, AccessShareLock);
|
||||
scan = heap_beginscan(hist_rel, snapshot, 0, NULL);
|
||||
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) {
|
||||
hist_rel = heap_open(hist_oid, AccessShareLock);// 打开历史表关系并获取共享锁
|
||||
scan = heap_beginscan(hist_rel, snapshot, 0, NULL); // 开始扫描历史表
|
||||
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) { // 遍历历史表中的元组
|
||||
Datum value = heap_getattr(tuple, USERCHAIN_COLUMN_HASH_INS + 1, hist_rel->rd_att, &is_null);
|
||||
if (!is_null) {
|
||||
rel_hash += DatumGetUInt64(value);
|
||||
if (!is_null) {// 如果不是空值
|
||||
rel_hash += DatumGetUInt64(value);// 累加到哈希差值中
|
||||
}
|
||||
|
||||
value = heap_getattr(tuple, USERCHAIN_COLUMN_HASH_DEL + 1, hist_rel->rd_att, &is_null);
|
||||
if (!is_null) {
|
||||
rel_hash -= DatumGetUInt64(value);
|
||||
if (!is_null) {// 如果不是空值
|
||||
rel_hash -= DatumGetUInt64(value); // 从哈希差值中减去
|
||||
}
|
||||
}
|
||||
heap_endscan(scan);
|
||||
heap_close(hist_rel, AccessShareLock);
|
||||
heap_endscan(scan);// 结束历史表扫描
|
||||
heap_close(hist_rel, AccessShareLock); // 关闭历史表关系并释放共享锁
|
||||
return rel_hash;
|
||||
}
|
||||
|
||||
|
|
@ -171,23 +171,23 @@ static bool has_ledger_consistent_privilege(Oid relid, Oid namespaceId)
|
|||
*/
|
||||
bool is_hist_hash_identity(Oid relid, uint64 *res_hash)
|
||||
{
|
||||
uint64 user_hash_sum;
|
||||
uint64 hist_hash_sum;
|
||||
uint64 user_hash_sum;// 用户表的哈希和
|
||||
uint64 hist_hash_sum;// 历史表的哈希和
|
||||
char hist_name[NAMEDATALEN];
|
||||
char *rel_name = get_rel_name(relid);
|
||||
if (!get_hist_name(relid, rel_name, hist_name)) {
|
||||
ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("get hist table name failed.")));
|
||||
char *rel_name = get_rel_name(relid);// 获取用户表的名称
|
||||
if (!get_hist_name(relid, rel_name, hist_name)) {// 获取历史表的名称
|
||||
ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("get hist table name failed."))); // 如果获取失败,则<EFBC8C><E58899><EFBFBD>错
|
||||
}
|
||||
Oid histoid = get_relname_relid(hist_name, PG_BLOCKCHAIN_NAMESPACE);
|
||||
if (!OidIsValid(histoid)) {
|
||||
ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("could not find hist table of \"%s\".", rel_name)));
|
||||
Oid histoid = get_relname_relid(hist_name, PG_BLOCKCHAIN_NAMESPACE);// 获取历史表的 OID
|
||||
if (!OidIsValid(histoid)) { // 如果 OID 无效
|
||||
ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("could not find hist table of \"%s\".", rel_name)));// 报错,找不到历史表
|
||||
}
|
||||
|
||||
user_hash_sum = get_usertable_hash_sum(relid);
|
||||
hist_hash_sum = get_histtable_hash_sum(histoid);
|
||||
user_hash_sum = get_usertable_hash_sum(relid); // 获取用户表的哈希总和
|
||||
hist_hash_sum = get_histtable_hash_sum(histoid); // 获取历史表的哈希总和
|
||||
|
||||
*res_hash = hist_hash_sum;
|
||||
return user_hash_sum == hist_hash_sum;
|
||||
*res_hash = hist_hash_sum; // 返回历史表的哈希和
|
||||
return user_hash_sum == hist_hash_sum; // 返回用户表哈希和和历史表哈希和是否相等的比较结果
|
||||
}
|
||||
|
||||
#ifdef ENABLE_MULTIPLE_NODES
|
||||
|
|
@ -201,28 +201,28 @@ bool is_hist_hash_identity(Oid relid, uint64 *res_hash)
|
|||
*/
|
||||
static void StrategyFuncAnd(ParallelFunctionState* state)
|
||||
{
|
||||
TupleTableSlot* slot = NULL;
|
||||
bool result = true;
|
||||
TupleTableSlot* slot = NULL;// 创建 TupleTableSlot 用于存储结果
|
||||
bool result = true;// 初始化结果为true
|
||||
|
||||
Assert(state);
|
||||
Assert(state->tupstore);
|
||||
Assert(state->tupdesc);
|
||||
slot = MakeSingleTupleTableSlot(state->tupdesc);
|
||||
Assert(state); // 断言 state 不为空
|
||||
Assert(state->tupstore);// 断言 tupstore 不为空
|
||||
Assert(state->tupdesc);// 断言 tupdesc 不为空
|
||||
slot = MakeSingleTupleTableSlot(state->tupdesc);// 创建单个 TupleTableSlot 用于存储数据
|
||||
|
||||
while (true) {
|
||||
bool isnull = false;
|
||||
|
||||
if (!tuplestore_gettupleslot(state->tupstore, true, false, slot))
|
||||
if (!tuplestore_gettupleslot(state->tupstore, true, false, slot)) // 从 tupstore 获取下一个结果,如果没有更多结果则退出循环
|
||||
break;
|
||||
|
||||
if (!DatumGetBool(tableam_tslot_getattr(slot, 1, &isnull))) {
|
||||
if (!DatumGetBool(tableam_tslot_getattr(slot, 1, &isnull))) {// 从 TupleTableSlot 中获取属性值,如果为 false 则将结果设置为 false 并退出循环
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
(void)ExecClearTuple(slot);
|
||||
(void)ExecClearTuple(slot); // 清空 TupleTableSlot
|
||||
}
|
||||
|
||||
state->result = result;
|
||||
state->result = result;// 将结果存储在并行函数状态中
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -235,31 +235,30 @@ static void StrategyFuncAnd(ParallelFunctionState* state)
|
|||
*/
|
||||
static void StrategyFuncUInt64Sum(ParallelFunctionState* state)
|
||||
{
|
||||
TupleTableSlot* slot = NULL;
|
||||
int64 result = 0;
|
||||
TupleTableSlot* slot = NULL;// 创建 TupleTableSlot 用于存储结果
|
||||
int64 result = 0;// 初始化结果为 0
|
||||
|
||||
Assert(state && state->tupstore && state->tupdesc);
|
||||
slot = MakeSingleTupleTableSlot(state->tupdesc);
|
||||
Assert(state && state->tupstore && state->tupdesc);// 断言 state、tupstore 和 tupdesc 不为空
|
||||
slot = MakeSingleTupleTableSlot(state->tupdesc);// 创建单个 TupleTableSlot 用于存储数据
|
||||
|
||||
while (true) {
|
||||
bool isnull = false;
|
||||
|
||||
if (!tuplestore_gettupleslot(state->tupstore, true, false, slot))
|
||||
if (!tuplestore_gettupleslot(state->tupstore, true, false, slot))// 从 tupstore 获取下一个结果,如果没有更多结果则退出循环
|
||||
break;
|
||||
|
||||
result += DatumGetUInt64(tableam_tslot_getattr(slot, 1, &isnull));
|
||||
ExecClearTuple(slot);
|
||||
result += DatumGetUInt64(tableam_tslot_getattr(slot, 1, &isnull));// 从 TupleTableSlot 中获取属性值并累加到结果中
|
||||
ExecClearTuple(slot);// 清空 TupleTableSlot
|
||||
}
|
||||
|
||||
state->result = result;
|
||||
state->result = result;// 将结果存储在并行函数状态中
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ledger_hist_check -- check whether user table hash and history table hash are equal
|
||||
* ledger_hist_check -- 检查用户表哈希和历史表哈希是否相等
|
||||
*
|
||||
* parameter1: user table name [type: text]
|
||||
* parameter2: namespace of user table [type: text]
|
||||
* parameter1: 用户表名 [类型: text]
|
||||
* parameter2: 用户表的命名空间 [类型: text]
|
||||
*/
|
||||
Datum ledger_hist_check(PG_FUNCTION_ARGS)
|
||||
{
|
||||
|
|
@ -269,30 +268,32 @@ Datum ledger_hist_check(PG_FUNCTION_ARGS)
|
|||
bool res = false;
|
||||
char *table_name;
|
||||
char *table_nsp;
|
||||
text *rel_nsp = PG_GETARG_TEXT_PP(0);
|
||||
text *rel_name = PG_GETARG_TEXT_PP(1);
|
||||
text *rel_nsp = PG_GETARG_TEXT_PP(0); // 获取第一个参数,用户表的命名空间
|
||||
text *rel_name = PG_GETARG_TEXT_PP(1); // 获取第二个参数,用户表名
|
||||
|
||||
table_nsp = text_to_cstring(rel_nsp);
|
||||
table_name = text_to_cstring(rel_name);
|
||||
nsp_oid = get_namespace_oid(table_nsp, false);
|
||||
relid = get_relname_relid(table_name, nsp_oid);
|
||||
ledger_usertable_check(relid, nsp_oid, table_name, table_nsp);
|
||||
|
||||
if (!has_ledger_consistent_privilege(relid, nsp_oid)) {
|
||||
|
||||
table_nsp = text_to_cstring(rel_nsp);// 将文本参数转换为 C 字符串
|
||||
table_name = text_to_cstring(rel_name);// 将文本参数转换为 C 字符串
|
||||
nsp_oid = get_namespace_oid(table_nsp, false);// 获取命名空间的 OID
|
||||
relid = get_relname_relid(table_name, nsp_oid);// 获取用户表的 OID
|
||||
ledger_usertable_check(relid, nsp_oid, table_name, table_nsp);// 检查用户表是否存在
|
||||
|
||||
if (!has_ledger_consistent_privilege(relid, nsp_oid)) { // 检查权限
|
||||
ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("Permission denied.")));
|
||||
}
|
||||
res = is_hist_hash_identity(relid, &res_hash);
|
||||
res = is_hist_hash_identity(relid, &res_hash);// 检查用户表哈希和历史表哈希是否相等
|
||||
|
||||
#ifdef ENABLE_MULTIPLE_NODES
|
||||
if (!IsConnFromCoord()) {
|
||||
StringInfoData buf;
|
||||
ParallelFunctionState* state = NULL;
|
||||
initStringInfo(&buf);
|
||||
if (!IsConnFromCoord()) {// 如果不是从协调器节点调用
|
||||
StringInfoData buf;// 创建一个字符串缓冲区
|
||||
ParallelFunctionState* state = NULL;// 创建并行函数状态
|
||||
initStringInfo(&buf);// 初始化字符串缓冲区
|
||||
appendStringInfo(&buf, "SELECT pg_catalog.ledger_hist_check('%s', '%s')", table_nsp, table_name);
|
||||
/* Get all hash diffs from DNs in distribute scenairo. */
|
||||
state = RemoteFunctionResultHandler(buf.data, NULL, StrategyFuncAnd);
|
||||
res &= state->result;
|
||||
FreeParallelFunctionState(state);
|
||||
res &= state->result;// 更新结果
|
||||
FreeParallelFunctionState(state);// 释放并行函数状态
|
||||
}
|
||||
#endif
|
||||
return BoolGetDatum(res);
|
||||
|
|
@ -309,19 +310,19 @@ static uint64 get_gchain_relhash_sum(Oid relid)
|
|||
HeapTuple tuple = NULL;
|
||||
|
||||
/* scan the gs_global_chain catalog by relid */
|
||||
Relation gchain_rel = heap_open(GsGlobalChainRelationId, AccessShareLock);
|
||||
Relation gchain_rel = heap_open(GsGlobalChainRelationId, AccessShareLock);// 打开 gs_global_chain 关系
|
||||
Form_gs_global_chain rdata = NULL;
|
||||
TableScanDesc scan = heap_beginscan(gchain_rel, SnapshotNow, 0, NULL);
|
||||
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) {
|
||||
rdata = (Form_gs_global_chain)GETSTRUCT(tuple);
|
||||
if (rdata == NULL || rdata->relid != relid) {
|
||||
TableScanDesc scan = heap_beginscan(gchain_rel, SnapshotNow, 0, NULL);// 创建表扫描描述符
|
||||
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) {// 循环遍历结果集
|
||||
rdata = (Form_gs_global_chain)GETSTRUCT(tuple);// 获取结果的数据结构
|
||||
if (rdata == NULL || rdata->relid != relid) {// 如果数据为空或者 OID 不匹配,则继续下一轮循环
|
||||
continue;
|
||||
}
|
||||
relhash += rdata->relhash;
|
||||
relhash += rdata->relhash;// 累加关系哈希值
|
||||
}
|
||||
heap_endscan(scan);
|
||||
heap_close(gchain_rel, AccessShareLock);
|
||||
return relhash;
|
||||
heap_endscan(scan);// 结束扫描
|
||||
heap_close(gchain_rel, AccessShareLock);// 关闭关系
|
||||
return relhash;// 返回关系哈希和
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -336,39 +337,39 @@ static uint64 get_gchain_relhash_sum(Oid relid)
|
|||
Datum get_dn_hist_relhash(PG_FUNCTION_ARGS)
|
||||
{
|
||||
#ifndef ENABLE_MULTIPLE_NODES
|
||||
DISTRIBUTED_FEATURE_NOT_SUPPORTED();
|
||||
DISTRIBUTED_FEATURE_NOT_SUPPORTED(); // 不支持分布式特性
|
||||
return UInt64GetDatum(0);
|
||||
#else
|
||||
if (!IsConnFromCoord()) {
|
||||
if (!IsConnFromCoord()) {// 如果不是从协调器节点调用
|
||||
ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("Permission denied.")));
|
||||
return UInt64GetDatum(0);
|
||||
}
|
||||
Oid user_relid;
|
||||
Oid nsp_oid;
|
||||
uint64 res_hash;
|
||||
text *rel_nsp = PG_GETARG_TEXT_PP(0);
|
||||
text *rel_name = PG_GETARG_TEXT_PP(1);
|
||||
text *rel_nsp = PG_GETARG_TEXT_PP(0);// 获取第一个参数,用户表的命名空间
|
||||
text *rel_name = PG_GETARG_TEXT_PP(1);// 获取第二个参数,用户表名
|
||||
char *table_name;
|
||||
char *table_nsp;
|
||||
|
||||
table_nsp = text_to_cstring(rel_nsp);
|
||||
table_name = text_to_cstring(rel_name);
|
||||
nsp_oid = get_namespace_oid(table_nsp, false);
|
||||
user_relid = get_relname_relid(table_name, nsp_oid);
|
||||
ledger_usertable_check(user_relid, nsp_oid, table_name, table_nsp);
|
||||
table_nsp = text_to_cstring(rel_nsp);// 将文本参数转换为 C 字符串
|
||||
table_name = text_to_cstring(rel_name);// 将文本参数转换为 C 字符串
|
||||
nsp_oid = get_namespace_oid(table_nsp, false);// 获取命名空间的 OID
|
||||
user_relid = get_relname_relid(table_name, nsp_oid);// 获取用户表的 OID
|
||||
ledger_usertable_check(user_relid, nsp_oid, table_name, table_nsp);// 检查用户表是否存在
|
||||
|
||||
if (!has_ledger_consistent_privilege(user_relid, nsp_oid)) {
|
||||
ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("Permission denied.")));
|
||||
}
|
||||
if (IS_PGXC_DATANODE) {
|
||||
if (!is_hist_hash_identity(user_relid, &res_hash)) {
|
||||
if (IS_PGXC_DATANODE) {// 如果当前节点是数据节点
|
||||
if (!is_hist_hash_identity(user_relid, &res_hash)) {// 检查用户表哈希和历史表哈希是否相等
|
||||
res_hash = 0;
|
||||
}
|
||||
} else {
|
||||
} else {// 如果当前节点是协调器节点
|
||||
res_hash = get_gchain_relhash_sum(user_relid);
|
||||
}
|
||||
|
||||
return UInt64GetDatum(res_hash);
|
||||
return UInt64GetDatum(res_hash);//返回结果
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue