From bb7cffcc3b44f6f523097ff754d2b71d29751750 Mon Sep 17 00:00:00 2001 From: playrest Date: Mon, 13 Feb 2023 15:07:59 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E9=98=B2=E7=AF=A1=E6=94=B9?= =?UTF-8?q?=E5=88=86=E5=8C=BA=E8=A1=A8insert=E6=97=B6=EF=BC=8C=E5=85=A8?= =?UTF-8?q?=E5=B1=80=E7=B4=A2=E5=BC=95tableoid=E4=B8=BA0=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/gausskernel/optimizer/commands/copy.cpp | 2 +- .../runtime/executor/nodeModifyTable.cpp | 10 +- .../runtime/opfusion/opfusion_insert.cpp | 2 +- .../runtime/opfusion/opfusion_update.cpp | 2 +- .../security/gs_ledger/userchain.cpp | 6 +- src/include/gs_ledger/userchain.h | 2 +- .../regress/input/ledger_table_case.source | 81 +++++++++ .../regress/output/ledger_table_case.source | 166 ++++++++++++++++++ 8 files changed, 261 insertions(+), 10 deletions(-) diff --git a/src/gausskernel/optimizer/commands/copy.cpp b/src/gausskernel/optimizer/commands/copy.cpp index 9287a44ba..0d6081f53 100644 --- a/src/gausskernel/optimizer/commands/copy.cpp +++ b/src/gausskernel/optimizer/commands/copy.cpp @@ -4794,7 +4794,7 @@ uint64 CopyFrom(CopyState cstate) tuple = slot->tts_tuple; } if (rel_isblockchain) { - tuple = set_user_tuple_hash((HeapTuple)tuple, resultRelationDesc, true); + tuple = set_user_tuple_hash((HeapTuple)tuple, resultRelationDesc, slot, true); } /* Check the constraints of the tuple */ diff --git a/src/gausskernel/runtime/executor/nodeModifyTable.cpp b/src/gausskernel/runtime/executor/nodeModifyTable.cpp index 95a145abf..8ba0599d4 100644 --- a/src/gausskernel/runtime/executor/nodeModifyTable.cpp +++ b/src/gausskernel/runtime/executor/nodeModifyTable.cpp @@ -1103,7 +1103,7 @@ TupleTableSlot* ExecInsertT(ModifyTableState* state, TupleTableSlot* slot, Tuple */ if (rel_isblockchain) { MemoryContext old_context = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); - tuple = set_user_tuple_hash((HeapTuple)tuple, result_relation_desc); + tuple = set_user_tuple_hash((HeapTuple)tuple, result_relation_desc, slot); (void)MemoryContextSwitchTo(old_context); } @@ -1289,7 +1289,7 @@ TupleTableSlot* ExecInsertT(ModifyTableState* state, TupleTableSlot* slot, Tuple result_relation_desc->rd_tam_ops); if (rel_isblockchain) { MemoryContext old_context = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); - tuple = set_user_tuple_hash((HeapTuple)tuple, result_relation_desc); + tuple = set_user_tuple_hash((HeapTuple)tuple, result_relation_desc, NULL); (void)MemoryContextSwitchTo(old_context); } if (tuple != NULL) { @@ -2282,7 +2282,7 @@ lreplace: if (result_relation_desc->rd_isblockchain) { MemoryContext old_context = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); hash_del = get_user_tupleid_hash(fake_relation, tupleid); - tuple = set_user_tuple_hash((HeapTuple)tuple, fake_relation); + tuple = set_user_tuple_hash((HeapTuple)tuple, fake_relation, slot); (void)MemoryContextSwitchTo(old_context); } @@ -2588,7 +2588,7 @@ lreplace: if (result_relation_desc->rd_isblockchain) { MemoryContext old_context = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); hash_del = get_user_tupleid_hash(fake_relation, tupleid); - tuple = set_user_tuple_hash((HeapTuple)tuple, fake_relation); + tuple = set_user_tuple_hash((HeapTuple)tuple, fake_relation, slot); (void)MemoryContextSwitchTo(old_context); } @@ -3012,7 +3012,7 @@ ldelete: } if (result_relation_desc->rd_isblockchain) { MemoryContext old_context = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); - tuple = set_user_tuple_hash((HeapTuple)tuple, fake_insert_relation); + tuple = set_user_tuple_hash((HeapTuple)tuple, fake_insert_relation, slot); (void)MemoryContextSwitchTo(old_context); } diff --git a/src/gausskernel/runtime/opfusion/opfusion_insert.cpp b/src/gausskernel/runtime/opfusion/opfusion_insert.cpp index fbe68dec7..d72847e18 100644 --- a/src/gausskernel/runtime/opfusion/opfusion_insert.cpp +++ b/src/gausskernel/runtime/opfusion/opfusion_insert.cpp @@ -344,7 +344,7 @@ unsigned long InsertFusion::ExecInsert(Relation rel, ResultRelInfo* result_rel_i if (rel_isblockchain && (!RelationIsUstoreFormat(rel))) { HeapTuple tmp_tuple = (HeapTuple)tuple; MemoryContext old_context = MemoryContextSwitchTo(m_local.m_tmpContext); - tuple = set_user_tuple_hash(tmp_tuple, target_rel); + tuple = set_user_tuple_hash(tmp_tuple, target_rel, NULL); (void)ExecStoreTuple(tuple, m_local.m_reslot, InvalidBuffer, false); m_local.m_ledger_hash_exist = hist_table_record_insert(target_rel, (HeapTuple)tuple, &m_local.m_ledger_relhash); (void)MemoryContextSwitchTo(old_context); diff --git a/src/gausskernel/runtime/opfusion/opfusion_update.cpp b/src/gausskernel/runtime/opfusion/opfusion_update.cpp index 08dfa807b..069859bed 100644 --- a/src/gausskernel/runtime/opfusion/opfusion_update.cpp +++ b/src/gausskernel/runtime/opfusion/opfusion_update.cpp @@ -336,7 +336,7 @@ lreplace: HeapTuple tmp_tup = (HeapTuple)tup; MemoryContext oldContext = MemoryContextSwitchTo(m_local.m_tmpContext); hash_del = get_user_tuple_hash((HeapTuple)oldtup, RelationGetDescr(ledger_dest_rel)); - tup = set_user_tuple_hash(tmp_tup, ledger_dest_rel); + tup = set_user_tuple_hash(tmp_tup, ledger_dest_rel, NULL); (void)MemoryContextSwitchTo(oldContext); tableam_tops_free_tuple(tmp_tup); } diff --git a/src/gausskernel/security/gs_ledger/userchain.cpp b/src/gausskernel/security/gs_ledger/userchain.cpp index b08ab8f40..0ee0495b9 100644 --- a/src/gausskernel/security/gs_ledger/userchain.cpp +++ b/src/gausskernel/security/gs_ledger/userchain.cpp @@ -329,7 +329,7 @@ static uint64 gen_user_tuple_hash(Relation rel, HeapTuple tuple) * Note: if hash_exists is true, we should recompute * tuple hash and compare with tuplehash of itself. */ -HeapTuple set_user_tuple_hash(HeapTuple tup, Relation rel, bool hash_exists) +HeapTuple set_user_tuple_hash(HeapTuple tup, Relation rel, TupleTableSlot *slot, bool hash_exists) { uint64 row_hash = gen_user_tuple_hash(rel, tup); int hash_attrno = user_hash_attrno(rel->rd_att); @@ -353,6 +353,10 @@ HeapTuple set_user_tuple_hash(HeapTuple tup, Relation rel, bool hash_exists) replaces[hash_attrno] = true; HeapTuple newtup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, replaces); + if (slot) { + ExecStoreTuple((Tuple)newtup, slot, InvalidBuffer, false); + } + pfree_ext(values); pfree_ext(nulls); pfree_ext(replaces); diff --git a/src/include/gs_ledger/userchain.h b/src/include/gs_ledger/userchain.h index 4580b9e50..dfb110b17 100644 --- a/src/include/gs_ledger/userchain.h +++ b/src/include/gs_ledger/userchain.h @@ -38,7 +38,7 @@ void rename_hist_by_newnsp(Oid user_relid, const char *new_nsp_name); void rename_histlist_by_newnsp(List *usertable_oid_list, const char *new_nsp_name); /* DML support for user table */ -HeapTuple set_user_tuple_hash(HeapTuple tup, Relation rel, bool hash_exists = false); +HeapTuple set_user_tuple_hash(HeapTuple tup, Relation rel, TupleTableSlot *slot, bool hash_exists = false); int user_hash_attrno(const TupleDesc rd_att); uint64 get_user_tuple_hash(HeapTuple tuple, TupleDesc desc); uint64 get_user_tupleid_hash(Relation relation, ItemPointer tupleid); diff --git a/src/test/regress/input/ledger_table_case.source b/src/test/regress/input/ledger_table_case.source index 89187b3e9..a05e9cc7a 100644 --- a/src/test/regress/input/ledger_table_case.source +++ b/src/test/regress/input/ledger_table_case.source @@ -537,6 +537,87 @@ CREATE TYPE bc_compress_type AS (name text, salary numeric); CREATE TABLE ledgernsp.bad_tb(a bc_compress_type); DROP TYPE bc_compress_type; +---------------------------------------------------------------------- +-- TEST CASE 015. partition table. -- +---------------------------------------------------------------------- +CREATE TABLE ledgernsp.t_partition_range( + id number primary key not null, + partition_key int, + col2 varchar2(20)) +partition by range(partition_key) +( + partition p1 values less than (100), + partition p2 values less than(200), + partition p3 values less than(300) +); +\d ledgernsp.t_partition_range + +set enable_opfusion = off; +set enable_seqscan = off; +set enable_bitmapscan = off; +INSERT INTO ledgernsp.t_partition_range VALUES(1,50,'p1'); +INSERT INTO ledgernsp.t_partition_range VALUES(2,100,'p2'); +INSERT INTO ledgernsp.t_partition_range VALUES(3,250,'p3'); +select *, hash from ledgernsp.t_partition_range; + +UPDATE ledgernsp.t_partition_range SET partition_key=100 where id=1; +select *, hash from ledgernsp.t_partition_range; +DELETE FROM ledgernsp.t_partition_range WHERE id=1; +select *, hash from ledgernsp.t_partition_range; +explain (costs off) select /*+ indexonlyscan(t_partition_range t_partition_range_pkey) */ id from ledgernsp.t_partition_range; +select /*+ indexonlyscan(t_partition_range t_partition_range_pkey) */ id from ledgernsp.t_partition_range; + +create index ledgernsp.i_t_partition_range on ledgernsp.t_partition_range(partition_key) local; +INSERT INTO ledgernsp.t_partition_range VALUES (11,50,'p1'), (12,100,'p2'), (13,250,'p3'); +INSERT INTO ledgernsp.t_partition_range VALUES (101,50,'p1'), (102,100,'p2'), (103,250,'p3'); +select *, hash from ledgernsp.t_partition_range; +delete from ledgernsp.t_partition_range where id > 100; +copy ledgernsp.t_partition_range from stdin; +101 50 p1 83b92ed57e516174 +102 100 p2 3b9a1b6282e79e4c +103 250 p3 0c2b84ca1d32c8f2 +\. + +select /*+ indexonlyscan(t_partition_range t_partition_range_pkey) */ id from ledgernsp.t_partition_range; + +delete from ledgernsp.t_partition_range where id in (11, 12); +delete from ledgernsp.t_partition_range where partition_key in (50, 100, 250); +set enable_opfusion = on; +INSERT INTO ledgernsp.t_partition_range VALUES (11,50,'p1'), (12,100,'p2'), (13,250,'p3'); +copy ledgernsp.t_partition_range from stdin; +101 50 p1 83b92ed57e516174 +102 100 p2 3b9a1b6282e79e4c +103 250 p3 0c2b84ca1d32c8f2 +\. + +select *, hash from ledgernsp.t_partition_range; +select /*+ indexonlyscan(t_partition_range t_partition_range_pkey) */ id from ledgernsp.t_partition_range; +explain (costs off) select /*+ indexonlyscan(t_partition_range i_t_partition_range) */ partition_key from ledgernsp.t_partition_range where partition_key = 100; +select /*+ indexonlyscan(t_partition_range i_t_partition_range) */ partition_key from ledgernsp.t_partition_range where partition_key = 100; + +delete from ledgernsp.t_partition_range where id in (11, 12); +delete from ledgernsp.t_partition_range where partition_key in (50, 100, 250); + +drop table if exists ledgernsp.t_partition_range; +reset enable_opfusion; +reset enable_seqscan; +reset enable_bitmapscan; + +-- not support subpartition table +CREATE TABLE ledgernsp.t_subpartition( + id number primary key not null, + partition_key int, + subpartition_key varchar2(20)) +partition by range(partition_key) +subpartition by hash(subpartition_key) +( + partition p1 values less than (100), + partition p2 values less than(200), + partition p3 values less than(300) +); +drop table if exists ledgernsp.t_subpartition; + + ---------------------------------------------------------------------- -- TEST CASE 016. index can not contain "hash" column. -- ---------------------------------------------------------------------- diff --git a/src/test/regress/output/ledger_table_case.source b/src/test/regress/output/ledger_table_case.source index beeb151a2..d01fa95b6 100644 --- a/src/test/regress/output/ledger_table_case.source +++ b/src/test/regress/output/ledger_table_case.source @@ -1113,6 +1113,172 @@ CREATE TABLE ledgernsp.bad_tb(a bc_compress_type); ERROR: Unsupport column type "bc_compress_type" of ledger user table. DROP TYPE bc_compress_type; ---------------------------------------------------------------------- +-- TEST CASE 015. partition table. -- +---------------------------------------------------------------------- +CREATE TABLE ledgernsp.t_partition_range( + id number primary key not null, + partition_key int, + col2 varchar2(20)) +partition by range(partition_key) +( + partition p1 values less than (100), + partition p2 values less than(200), + partition p3 values less than(300) +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_partition_range_pkey" for table "t_partition_range" +\d ledgernsp.t_partition_range + Table "ledgernsp.t_partition_range" + Column | Type | Modifiers +---------------+-----------------------+----------- + id | numeric | not null + partition_key | integer | + col2 | character varying(20) | + hash | hash16 | +Indexes: + "t_partition_range_pkey" PRIMARY KEY, btree (id) TABLESPACE pg_default +Partition By RANGE(partition_key) +Number of partitions: 3 (View pg_partition to check each partition range.) + +set enable_opfusion = off; +set enable_seqscan = off; +set enable_bitmapscan = off; +INSERT INTO ledgernsp.t_partition_range VALUES(1,50,'p1'); +INSERT INTO ledgernsp.t_partition_range VALUES(2,100,'p2'); +INSERT INTO ledgernsp.t_partition_range VALUES(3,250,'p3'); +select *, hash from ledgernsp.t_partition_range; + id | partition_key | col2 | hash +----+---------------+------+------------------ + 1 | 50 | p1 | d8f1b97ffe23e540 + 2 | 100 | p2 | c6d00b47c7008be0 + 3 | 250 | p3 | 079397057329db5f +(3 rows) + +UPDATE ledgernsp.t_partition_range SET partition_key=100 where id=1; +select *, hash from ledgernsp.t_partition_range; + id | partition_key | col2 | hash +----+---------------+------+------------------ + 2 | 100 | p2 | c6d00b47c7008be0 + 1 | 100 | p1 | 850a29600863ff7c + 3 | 250 | p3 | 079397057329db5f +(3 rows) + +DELETE FROM ledgernsp.t_partition_range WHERE id=1; +select *, hash from ledgernsp.t_partition_range; + id | partition_key | col2 | hash +----+---------------+------+------------------ + 2 | 100 | p2 | c6d00b47c7008be0 + 3 | 250 | p3 | 079397057329db5f +(2 rows) + +explain (costs off) select /*+ indexonlyscan(t_partition_range t_partition_range_pkey) */ id from ledgernsp.t_partition_range; + QUERY PLAN +------------------------------------------------------------------- + Index Only Scan using t_partition_range_pkey on t_partition_range +(1 row) + +select /*+ indexonlyscan(t_partition_range t_partition_range_pkey) */ id from ledgernsp.t_partition_range; + id +---- + 2 + 3 +(2 rows) + +create index ledgernsp.i_t_partition_range on ledgernsp.t_partition_range(partition_key) local; +INSERT INTO ledgernsp.t_partition_range VALUES (11,50,'p1'), (12,100,'p2'), (13,250,'p3'); +INSERT INTO ledgernsp.t_partition_range VALUES (101,50,'p1'), (102,100,'p2'), (103,250,'p3'); +select *, hash from ledgernsp.t_partition_range; + id | partition_key | col2 | hash +-----+---------------+------+------------------ + 11 | 50 | p1 | 406945c1b1ad4f30 + 101 | 50 | p1 | 83b92ed57e516174 + 2 | 100 | p2 | c6d00b47c7008be0 + 12 | 100 | p2 | 3a1e393393ca9af9 + 102 | 100 | p2 | 3b9a1b6282e79e4c + 3 | 250 | p3 | 079397057329db5f + 13 | 250 | p3 | 123323c3e7c57bd7 + 103 | 250 | p3 | 0c2b84ca1d32c8f2 +(8 rows) + +delete from ledgernsp.t_partition_range where id > 100; +copy ledgernsp.t_partition_range from stdin; +select /*+ indexonlyscan(t_partition_range t_partition_range_pkey) */ id from ledgernsp.t_partition_range; + id +----- + 2 + 3 + 11 + 12 + 13 + 101 + 102 + 103 +(8 rows) + +delete from ledgernsp.t_partition_range where id in (11, 12); +delete from ledgernsp.t_partition_range where partition_key in (50, 100, 250); +set enable_opfusion = on; +INSERT INTO ledgernsp.t_partition_range VALUES (11,50,'p1'), (12,100,'p2'), (13,250,'p3'); +copy ledgernsp.t_partition_range from stdin; +select *, hash from ledgernsp.t_partition_range; + id | partition_key | col2 | hash +-----+---------------+------+------------------ + 11 | 50 | p1 | 406945c1b1ad4f30 + 101 | 50 | p1 | 83b92ed57e516174 + 12 | 100 | p2 | 3a1e393393ca9af9 + 102 | 100 | p2 | 3b9a1b6282e79e4c + 13 | 250 | p3 | 123323c3e7c57bd7 + 103 | 250 | p3 | 0c2b84ca1d32c8f2 +(6 rows) + +select /*+ indexonlyscan(t_partition_range t_partition_range_pkey) */ id from ledgernsp.t_partition_range; + id +----- + 11 + 12 + 13 + 101 + 102 + 103 +(6 rows) + +explain (costs off) select /*+ indexonlyscan(t_partition_range i_t_partition_range) */ partition_key from ledgernsp.t_partition_range where partition_key = 100; + QUERY PLAN +---------------------------------------------------------------------------- + Partitioned Index Only Scan using i_t_partition_range on t_partition_range + Index Cond: (partition_key = 100) + Selected Partitions: 2 +(3 rows) + +select /*+ indexonlyscan(t_partition_range i_t_partition_range) */ partition_key from ledgernsp.t_partition_range where partition_key = 100; + partition_key +--------------- + 100 + 100 +(2 rows) + +delete from ledgernsp.t_partition_range where id in (11, 12); +delete from ledgernsp.t_partition_range where partition_key in (50, 100, 250); +drop table if exists ledgernsp.t_partition_range; +reset enable_opfusion; +reset enable_seqscan; +reset enable_bitmapscan; +-- not support subpartition table +CREATE TABLE ledgernsp.t_subpartition( + id number primary key not null, + partition_key int, + subpartition_key varchar2(20)) +partition by range(partition_key) +subpartition by hash(subpartition_key) +( + partition p1 values less than (100), + partition p2 values less than(200), + partition p3 values less than(300) +); +ERROR: Un-support feature +DETAIL: Subpartition table does not support ledger user table. +drop table if exists ledgernsp.t_subpartition; +NOTICE: table "t_subpartition" does not exist, skipping +---------------------------------------------------------------------- -- TEST CASE 016. index can not contain "hash" column. -- ---------------------------------------------------------------------- create table ledgernsp.t_col_hash(id int, "Hash" int, unique (hash)); -- error