diff --git a/src/gausskernel/storage/access/hash/hashpage.cpp b/src/gausskernel/storage/access/hash/hashpage.cpp index c3b7afe93b17fe38e6e61ececd21bf5588da5cab..aa96262c17fb7bb3b15173acacb3c4ee70a9d468 100644 --- a/src/gausskernel/storage/access/hash/hashpage.cpp +++ b/src/gausskernel/storage/access/hash/hashpage.cpp @@ -969,39 +969,46 @@ static bool _hash_alloc_buckets(Relation rel, BlockNumber firstblock, uint32 nbl if (lastblock < firstblock || lastblock == InvalidBlockNumber) return false; - if (IsSegmentFileNode(rel->rd_node)) { - Buffer buf = ReadBuffer(rel, P_NEW); -#ifdef USE_ASSERT_CHECKING - BufferDesc *buf_desc = GetBufferDescriptor(buf - 1); - Assert(buf_desc->tag.blockNum == lastblock); -#endif - ReleaseBuffer(buf); - } else { - page = (Page)zerobuf; - - /* - * Initialize the page. Just zeroing the page won't work; see - * _hash_freeovflpage for similar usage. We take care to make the special - * space valid for the benefit of tools such as pageinspect. - */ - _hash_pageinit(page, BLCKSZ); - - ovflopaque = (HashPageOpaque) PageGetSpecialPointer(page); - - ovflopaque->hasho_prevblkno = InvalidBlockNumber; - ovflopaque->hasho_nextblkno = InvalidBlockNumber; - ovflopaque->hasho_bucket = -1; - ovflopaque->hasho_flag = LH_UNUSED_PAGE; - ovflopaque->hasho_page_id = HASHO_PAGE_ID; - - if (RelationNeedsWAL(rel)) + /* change segment table insert hash table */ + page = (Page)zerobuf; + /* + * Initialize the page. Just zeroing the page won't work; see + * _hash_freeovflpage for similar usage. We take care to make the special + * space valid for the benefit of tools such as pageinspect. + */ + _hash_pageinit(page, BLCKSZ); + + ovflopaque = (HashPageOpaque) PageGetSpecialPointer(page); + + ovflopaque->hasho_prevblkno = InvalidBlockNumber; + ovflopaque->hasho_nextblkno = InvalidBlockNumber; + ovflopaque->hasho_bucket = -1; + ovflopaque->hasho_flag = LH_UNUSED_PAGE; + ovflopaque->hasho_page_id = HASHO_PAGE_ID; + PageSetChecksumInplace(zerobuf, lastblock); + + if (RelationNeedsWAL(rel)) log_newpage(&rel->rd_node, MAIN_FORKNUM, lastblock, zerobuf, true); + + if (IsSegmentFileNode(rel->rd_node)) { + Buffer buf; + for (int i = firstblock; i <= lastblock; i++) { + buf = ReadBuffer(rel, P_NEW); + ReleaseBuffer(buf); + } + buf = ReadBuffer(rel, lastblock); + LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE); + errno_t rel = memcpy_s(BufferGetPage(buf), BLCKSZ, page, BLCKSZ); + securec_check(rel, "", ""); + MarkBufferDirty(buf); + LockBuffer(buf, BUFFER_LOCK_UNLOCK); + ReleaseBuffer(buf); + } else { RelationOpenSmgr(rel); - PageSetChecksumInplace(zerobuf, lastblock); smgrextend(rel->rd_smgr, MAIN_FORKNUM, lastblock, zerobuf, false); } diff --git a/src/test/regress/expected/hash_index_001.out b/src/test/regress/expected/hash_index_001.out index 31d036597941c2d61e99d29aa6b517c0af98c4cd..b0f7c85b55919c23ff3b0fddbf5b60040c2271f7 100644 --- a/src/test/regress/expected/hash_index_001.out +++ b/src/test/regress/expected/hash_index_001.out @@ -240,3 +240,53 @@ select count(*) from hash_table_7; 1000 (1 row) +-- create hash index on segment table, update/delete +drop table if exists hash_table_8; +NOTICE: table "hash_table_8" does not exist, skipping +create table hash_table_8(id int, name varchar, sex varchar default 'male') with(segment = on); +create index hash_tb8_id1 on hash_table_8 using hash(id); +insert into hash_table_8 select generate_series(1, 1000), 'xxx', 'xxx'; +select count(*) from hash_table_8; + count +------- + 1000 +(1 row) + +update hash_table_8 set sex = tmp.sex from (values (10, 'xxx', 'female'), (20, 'xxx', 'female'), (30, 'xxx', 'female')) as tmp (id, name, sex) where hash_table_8.id = tmp.id; +select * from hash_table_8 where sex = 'female'; + id | name | sex +----+------+-------- + 10 | xxx | female + 20 | xxx | female + 30 | xxx | female +(3 rows) + +delete from hash_table_8 where sex = 'female'; +select * from hash_table_8 where sex = 'female'; + id | name | sex +----+------+----- +(0 rows) + +drop index hash_tb8_id1; +drop table hash_table_8; +-- create hash index on segment table, delete/vacuum +drop table if exists hash_table_9; +NOTICE: table "hash_table_9" does not exist, skipping +create table hash_table_9(id int, name varchar, sec varchar default 'male') with (segment = on); +create index hash_tb9_id1 on hash_table_9 using hash(id); +insert into hash_table_9 select generate_series(1, 1000), 'XXX', 'XXX'; +insert into hash_table_9 select generate_series(1, 200), 'AAA', 'AAA'; +select count(*) from hash_table_9 where name = 'AAA'; + count +------- + 200 +(1 row) + +delete from hash_table_9 where name = 'AAA'; +select * from hash_table_9 where name = 'AAA'; + id | name | sec +----+------+----- +(0 rows) + +drop index hash_tb9_id1; +drop table hash_table_9; diff --git a/src/test/regress/sql/hash_index_001.sql b/src/test/regress/sql/hash_index_001.sql index dc7fa80113e4b15caa496751bcde1035053c040b..9327d5e27f8a1a38ee107ddb0ff91be011ad2932 100644 --- a/src/test/regress/sql/hash_index_001.sql +++ b/src/test/regress/sql/hash_index_001.sql @@ -176,3 +176,28 @@ insert into hash_table_7 select random()*100, 'XXX', 'XXX' from generate_series( create index hash_t7_id1 on hash_table_7 using hash(id) with (fillfactor = 30); explain (costs off) select * from hash_table_7 where id = 80; select count(*) from hash_table_7; + +-- create hash index on segment table, update/delete +drop table if exists hash_table_8; +create table hash_table_8(id int, name varchar, sex varchar default 'male') with(segment = on); +create index hash_tb8_id1 on hash_table_8 using hash(id); +insert into hash_table_8 select generate_series(1, 1000), 'xxx', 'xxx'; +select count(*) from hash_table_8; +update hash_table_8 set sex = tmp.sex from (values (10, 'xxx', 'female'), (20, 'xxx', 'female'), (30, 'xxx', 'female')) as tmp (id, name, sex) where hash_table_8.id = tmp.id; +select * from hash_table_8 where sex = 'female'; +delete from hash_table_8 where sex = 'female'; +select * from hash_table_8 where sex = 'female'; +drop index hash_tb8_id1; +drop table hash_table_8; + +-- create hash index on segment table, delete/vacuum +drop table if exists hash_table_9; +create table hash_table_9(id int, name varchar, sec varchar default 'male') with (segment = on); +create index hash_tb9_id1 on hash_table_9 using hash(id); +insert into hash_table_9 select generate_series(1, 1000), 'XXX', 'XXX'; +insert into hash_table_9 select generate_series(1, 200), 'AAA', 'AAA'; +select count(*) from hash_table_9 where name = 'AAA'; +delete from hash_table_9 where name = 'AAA'; +select * from hash_table_9 where name = 'AAA'; +drop index hash_tb9_id1; +drop table hash_table_9;