From 84f7c879d7c55297c7b2ea00f47cae452c073f46 Mon Sep 17 00:00:00 2001 From: openGaussDev Date: Fri, 4 Mar 2022 17:43:12 +0800 Subject: [PATCH] use case Offering: openGaussDev More detail: use case Match-id-fbe61ca0327bfa20855dacf6b6c9f91cc876f671 --- src/common/backend/utils/adt/varlena.cpp | 2 +- src/include/access/tuptoaster.h | 19 +++- src/test/regress/expected/huge_clob.out | 118 ++++++++++++++--------- src/test/regress/sql/huge_clob.sql | 95 +++++++++++------- 4 files changed, 146 insertions(+), 88 deletions(-) diff --git a/src/common/backend/utils/adt/varlena.cpp b/src/common/backend/utils/adt/varlena.cpp index 2ba2ce1ae..5d0b49711 100644 --- a/src/common/backend/utils/adt/varlena.cpp +++ b/src/common/backend/utils/adt/varlena.cpp @@ -746,7 +746,7 @@ static Datum text_length_huge(Datum str) */ Datum textlen(PG_FUNCTION_ARGS) { - Datum str = PG_GETARG_DATUM(0); + Datum str = fetch_real_lob_if_need(PG_GETARG_DATUM(0)); if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)DatumGetTextPP(str))) { return text_length_huge(str); diff --git a/src/include/access/tuptoaster.h b/src/include/access/tuptoaster.h index e30a0823f..bd313b3f2 100644 --- a/src/include/access/tuptoaster.h +++ b/src/include/access/tuptoaster.h @@ -275,12 +275,27 @@ extern Size toast_datum_size(Datum value); extern bool toastrel_valueid_exists(Relation toastrel, Oid valueid); +extern bool create_toast_by_sid(Oid *toastOid); +extern Oid get_toast_oid(); extern varlena* toast_huge_write_datum_slice(struct varlena* attr1, struct varlena* attr2, int64 sliceoffset, int32 length); extern varlena* toast_pointer_fetch_data(TupleTableSlot* varSlot, Form_pg_attribute attr, int varNumber); extern Datum fetch_lob_value_from_tuple(varatt_lob_pointer* lob_pointer, Oid update_oid, bool* is_null, bool* is_huge_clob = NULL); -extern bool create_toast_by_sid(Oid *toastOid); -extern Oid get_toast_oid(); + +inline Datum fetch_real_lob_if_need(Datum toast_pointer) +{ + Datum ret = toast_pointer; + if (VARATT_IS_EXTERNAL_LOB(toast_pointer)) { + bool isNull = false; + struct varatt_lob_pointer* lob_pointer = (varatt_lob_pointer*)(VARDATA_EXTERNAL(toast_pointer)); + ret = fetch_lob_value_from_tuple(lob_pointer, InvalidOid, &isNull, NULL); + if (unlikely(isNull)) { + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Invalid lob pointer."))); + } + } + return ret; +} #endif /* TUPTOASTER_H */ diff --git a/src/test/regress/expected/huge_clob.out b/src/test/regress/expected/huge_clob.out index 8c9dd1bcf..7438ade02 100644 --- a/src/test/regress/expected/huge_clob.out +++ b/src/test/regress/expected/huge_clob.out @@ -11,12 +11,36 @@ drop schema if exists huge_clob; NOTICE: schema "huge_clob" does not exist, skipping create schema huge_clob; set current_schema = huge_clob; -create table bigclobtbl031(c1 int,c2 clob,c3 clob,c4 blob,c5 date,c6 timestamp,c7 varchar2); -insert into bigclobtbl031 values(generate_series(1,5),repeat('AAAA11111aaaaaaaaaaaaaaaaa',1000000),repeat('abdededfj12345679ujik',1000000),hextoraw(repeat('12345678990abcdef',1000)),sysdate,to_timestamp('','yyyy-mm-dd hh24:mi:ss.ff6'),7000); -update bigclobtbl031 set c2=c2||c2||c2||c2||c2; -update bigclobtbl031 set c2=c2||c2||c2||c2||c2; -update bigclobtbl031 set c2=c2||c2; -update bigclobtbl031 set c3='clobclob3'; +drop table if exists cloblongtbl; +NOTICE: table "cloblongtbl" does not exist, skipping +create table cloblongtbl (a int, b clob, c clob); +-- insert data less than 1G +insert into cloblongtbl values (generate_series(1,4),repeat('唐李白床前明月光,疑是地上霜,举头望明月,低头思故乡',5000000),repeat('唐李白床前明月光,疑是地上霜,举头望明月,低头思故乡',5000000)); +update cloblongtbl set b = b||b; +update cloblongtbl set c = c||c; +-- b > 1G && c < 1G when a = 2 +update cloblongtbl set b = b||b where a = 2; +-- b < 1G && c > 1G when a = 3 +update cloblongtbl set c = c||c where a = 3; +-- b > 1G && c > 1G when a = 4 +update cloblongtbl set b = b||b where a = 4; +update cloblongtbl set c = c||c where a = 4; +select a, length(b || c) from cloblongtbl order by 1; + a | length +---+------------ + 1 | 520000000 + 2 | 780000000 + 3 | 780000000 + 4 | 1040000000 +(4 rows) + +-- reset data for other test +update cloblongtbl set b = b || b where a = 1; +update cloblongtbl set b = b || b where a = 3; +update cloblongtbl set c='cloblessthan1G' where a = 1; +update cloblongtbl set c='cloblessthan1G' where a = 2; +update cloblongtbl set c='cloblessthan1G' where a = 3; +update cloblongtbl set c='cloblessthan1G' where a = 4; --I1.clob in create or replace procedure pro_cb4_031(c1 clob,c2 clob) is @@ -33,8 +57,8 @@ create or replace procedure pro_cb4_031_1 is v1 clob; v2 clob; begin -execute immediate 'select c2 from bigclobtbl031 where c1=1' into v1; -execute immediate 'select c3 from bigclobtbl031 where c1=1' into v2; +execute immediate 'select b from cloblongtbl where a=1' into v1; +execute immediate 'select c from cloblongtbl where a=1' into v2; pro_cb4_031(v1,v2); end; / @@ -49,8 +73,8 @@ is v1 clob; v2 clob; begin -execute immediate 'select c2 from bigclobtbl031 where c1=1' into v1; -execute immediate 'select c3 from bigclobtbl031 where c1=1' into v2; +execute immediate 'select b from cloblongtbl where a=1' into v1; +execute immediate 'select c from cloblongtbl where a=1' into v2; c1:=v1; c2:=v2; end; @@ -79,8 +103,8 @@ is v1 clob; v2 clob; begin -execute immediate 'select c3 from bigclobtbl031 where c1=1' into v1; -execute immediate 'select c3 from bigclobtbl031 where c1=2' into v2; +execute immediate 'select c from cloblongtbl where a=1' into v1; +execute immediate 'select c from cloblongtbl where a=2' into v2; c1:=v1; c2:=v2; end; @@ -96,8 +120,8 @@ is v1 clob; v2 clob; begin -execute immediate 'select c2 from bigclobtbl031 where c1=1' into v1; -execute immediate 'select c3 from bigclobtbl031 where c1=1' into v2; +execute immediate 'select b from cloblongtbl where a=1' into v1; +execute immediate 'select c from cloblongtbl where a=1' into v2; c1:=v1; c2:=v2; end; @@ -127,12 +151,12 @@ v1 clob; v2 clob; v3 clob; begin -execute immediate 'select c3 from bigclobtbl031 where c1=1' into v1; -execute immediate 'select c3 from bigclobtbl031 where c1=2' into v2; -execute immediate 'select c3 from bigclobtbl031 where c1=3' into v3; +execute immediate 'select c from cloblongtbl where a=1' into v1; +execute immediate 'select c from cloblongtbl where a=2' into v2; +execute immediate 'select c from cloblongtbl where a=3' into v3; c1:=v1; c2:=v2; -c3:=v3||'clob3clob3clob3clob3'; +c3:=v3||'clobclobclobclob'; end; / create or replace procedure pro_cb4_031_1 is @@ -163,8 +187,8 @@ type ty1 is table of clob; v1 ty1; begin for i in 1..10 loop -execute immediate 'select c2 from bigclobtbl031 where c1='||i into v1(i); -update bigclobtbl030 set c3=v1(i)||v1(i) where c1=i; +execute immediate 'select b from cloblongtbl where a='||i into v1(i); +update cloblongtbl set c=v1(i)||v1(i) where a=i; end loop; end; / @@ -177,27 +201,27 @@ type ty1 is varray(10) of clob; v1 ty1; begin for i in 1..10 loop -execute immediate 'select c2 from bigclobtbl031 where c1='||i into v1(i); -update bigclobtbl030 set c3=v1(i)||v1(i) where c1=i; +execute immediate 'select b from cloblongtbl where a='||i into v1(i); +update cloblongtbl set c=v1(i)||v1(i) where a=i; end loop; end; / call pro_cb4_031(); ERROR: huge clob do not support as array element. CONTEXT: PL/pgSQL function pro_cb4_031() line 6 at EXECUTE statement -select c1,c2,length(c2),c3,length(c3) from bigclobtbl031 where c1>5 and c1<10 order by 1,2,3,4,5; - c1 | c2 | length | c3 | length -----+----+--------+----+-------- +select a,b,length(b),c,length(c) from cloblongtbl where a>5 and a<10 order by 1,2,3,4,5; + a | b | length | c | length +---+---+--------+---+-------- (0 rows) -update bigclobtbl031 set c3='clob3clob3'; +update cloblongtbl set c='cloblessthan1G'; ERROR: tuple concurrently updated --I6.record create or replace procedure pro_cb4_031 is type ty1 is record(c1 int,c2 clob); v1 ty1; begin -execute immediate 'select c2 from bigclobtbl031 where c1=1' into v1.c2; +execute immediate 'select b from cloblongtbl where a=1' into v1.c2; end; / call pro_cb4_031(); @@ -212,7 +236,7 @@ v1 clob; v2 clob; v3 clob; v4 int; -cursor cor1 is select c2 from bigclobtbl031 where c1=1; +cursor cor1 is select b from cloblongtbl where a=1; begin open cor1; loop @@ -229,30 +253,28 @@ end; call pro_cb4_037(); ERROR: huge clob do not support as record element. CONTEXT: PL/pgSQL function pro_cb4_037() line 10 at FETCH -drop table if exists cloblongtbl; -NOTICE: table "cloblongtbl" does not exist, skipping -create table cloblongtbl (a int, b clob, c clob); -insert into cloblongtbl values (generate_series(1,4),repeat('唐李白床前明月光,疑是地上霜,举头望明月,低头思故乡',5000000),repeat('唐李白床前明月光,疑是地上霜,举头望明月,低头思故乡',5000000)); -update cloblongtbl set b = b||b; -update cloblongtbl set c = c||c; -update cloblongtbl set b = b||b where a = 2; -update cloblongtbl set c = c||c where a = 3; -update cloblongtbl set b = b||b where a = 4; -update cloblongtbl set c = c||c where a = 4; -select a, length(b || c) from cloblongtbl order by 1; - a | length ----+------------ - 1 | 520000000 - 2 | 780000000 - 3 | 780000000 - 4 | 1040000000 -(4 rows) +create or replace procedure test_self_update is +v1 clob; +begin +execute immediate 'select b from cloblongtbl where a=1' into v1; +update cloblongtbl set b=v1 where a=1; +savepoint aaa; +update cloblongtbl set b=v1 where a=2; +rollback to aaa; +commit; +end; +/ +call test_self_update(); + test_self_update +------------------ + +(1 row) drop table if exists cloblongtbl; -- clean drop schema if exists huge_clob cascade; NOTICE: drop cascades to 4 other objects -DETAIL: drop cascades to table bigclobtbl031 -drop cascades to function pro_cb4_031_1() +DETAIL: drop cascades to function pro_cb4_031_1() drop cascades to function pro_cb4_031() drop cascades to function pro_cb4_037() +drop cascades to function test_self_update() diff --git a/src/test/regress/sql/huge_clob.sql b/src/test/regress/sql/huge_clob.sql index 34b9de6f9..b7b1b9355 100644 --- a/src/test/regress/sql/huge_clob.sql +++ b/src/test/regress/sql/huge_clob.sql @@ -7,12 +7,29 @@ drop schema if exists huge_clob; create schema huge_clob; set current_schema = huge_clob; -create table bigclobtbl031(c1 int,c2 clob,c3 clob,c4 blob,c5 date,c6 timestamp,c7 varchar2); -insert into bigclobtbl031 values(generate_series(1,5),repeat('AAAA11111aaaaaaaaaaaaaaaaa',1000000),repeat('abdededfj12345679ujik',1000000),hextoraw(repeat('12345678990abcdef',1000)),sysdate,to_timestamp('','yyyy-mm-dd hh24:mi:ss.ff6'),7000); -update bigclobtbl031 set c2=c2||c2||c2||c2||c2; -update bigclobtbl031 set c2=c2||c2||c2||c2||c2; -update bigclobtbl031 set c2=c2||c2; -update bigclobtbl031 set c3='clobclob3'; +drop table if exists cloblongtbl; +create table cloblongtbl (a int, b clob, c clob); +-- insert data less than 1G +insert into cloblongtbl values (generate_series(1,4),repeat('唐李白床前明月光,疑是地上霜,举头望明月,低头思故乡',5000000),repeat('唐李白床前明月光,疑是地上霜,举头望明月,低头思故乡',5000000)); +update cloblongtbl set b = b||b; +update cloblongtbl set c = c||c; +-- b > 1G && c < 1G when a = 2 +update cloblongtbl set b = b||b where a = 2; +-- b < 1G && c > 1G when a = 3 +update cloblongtbl set c = c||c where a = 3; +-- b > 1G && c > 1G when a = 4 +update cloblongtbl set b = b||b where a = 4; +update cloblongtbl set c = c||c where a = 4; +select a, length(b || c) from cloblongtbl order by 1; + +-- reset data for other test +update cloblongtbl set b = b || b where a = 1; +update cloblongtbl set b = b || b where a = 3; +update cloblongtbl set c='cloblessthan1G' where a = 1; +update cloblongtbl set c='cloblessthan1G' where a = 2; +update cloblongtbl set c='cloblessthan1G' where a = 3; +update cloblongtbl set c='cloblessthan1G' where a = 4; + --I1.clob in create or replace procedure pro_cb4_031(c1 clob,c2 clob) @@ -31,8 +48,8 @@ create or replace procedure pro_cb4_031_1 is v1 clob; v2 clob; begin -execute immediate 'select c2 from bigclobtbl031 where c1=1' into v1; -execute immediate 'select c3 from bigclobtbl031 where c1=1' into v2; +execute immediate 'select b from cloblongtbl where a=1' into v1; +execute immediate 'select c from cloblongtbl where a=1' into v2; pro_cb4_031(v1,v2); end; / @@ -45,8 +62,8 @@ is v1 clob; v2 clob; begin -execute immediate 'select c2 from bigclobtbl031 where c1=1' into v1; -execute immediate 'select c3 from bigclobtbl031 where c1=1' into v2; +execute immediate 'select b from cloblongtbl where a=1' into v1; +execute immediate 'select c from cloblongtbl where a=1' into v2; c1:=v1; c2:=v2; end; @@ -74,8 +91,8 @@ is v1 clob; v2 clob; begin -execute immediate 'select c3 from bigclobtbl031 where c1=1' into v1; -execute immediate 'select c3 from bigclobtbl031 where c1=2' into v2; +execute immediate 'select c from cloblongtbl where a=1' into v1; +execute immediate 'select c from cloblongtbl where a=2' into v2; c1:=v1; c2:=v2; end; @@ -89,8 +106,8 @@ is v1 clob; v2 clob; begin -execute immediate 'select c2 from bigclobtbl031 where c1=1' into v1; -execute immediate 'select c3 from bigclobtbl031 where c1=1' into v2; +execute immediate 'select b from cloblongtbl where a=1' into v1; +execute immediate 'select c from cloblongtbl where a=1' into v2; c1:=v1; c2:=v2; end; @@ -119,12 +136,12 @@ v1 clob; v2 clob; v3 clob; begin -execute immediate 'select c3 from bigclobtbl031 where c1=1' into v1; -execute immediate 'select c3 from bigclobtbl031 where c1=2' into v2; -execute immediate 'select c3 from bigclobtbl031 where c1=3' into v3; +execute immediate 'select c from cloblongtbl where a=1' into v1; +execute immediate 'select c from cloblongtbl where a=2' into v2; +execute immediate 'select c from cloblongtbl where a=3' into v3; c1:=v1; c2:=v2; -c3:=v3||'clob3clob3clob3clob3'; +c3:=v3||'clobclobclobclob'; end; / @@ -153,8 +170,8 @@ type ty1 is table of clob; v1 ty1; begin for i in 1..10 loop -execute immediate 'select c2 from bigclobtbl031 where c1='||i into v1(i); -update bigclobtbl030 set c3=v1(i)||v1(i) where c1=i; +execute immediate 'select b from cloblongtbl where a='||i into v1(i); +update cloblongtbl set c=v1(i)||v1(i) where a=i; end loop; end; / @@ -167,21 +184,21 @@ type ty1 is varray(10) of clob; v1 ty1; begin for i in 1..10 loop -execute immediate 'select c2 from bigclobtbl031 where c1='||i into v1(i); -update bigclobtbl030 set c3=v1(i)||v1(i) where c1=i; +execute immediate 'select b from cloblongtbl where a='||i into v1(i); +update cloblongtbl set c=v1(i)||v1(i) where a=i; end loop; end; / call pro_cb4_031(); -select c1,c2,length(c2),c3,length(c3) from bigclobtbl031 where c1>5 and c1<10 order by 1,2,3,4,5; -update bigclobtbl031 set c3='clob3clob3'; +select a,b,length(b),c,length(c) from cloblongtbl where a>5 and a<10 order by 1,2,3,4,5; +update cloblongtbl set c='cloblessthan1G'; --I6.record create or replace procedure pro_cb4_031 is type ty1 is record(c1 int,c2 clob); v1 ty1; begin -execute immediate 'select c2 from bigclobtbl031 where c1=1' into v1.c2; +execute immediate 'select b from cloblongtbl where a=1' into v1.c2; end; / @@ -193,7 +210,7 @@ v1 clob; v2 clob; v3 clob; v4 int; -cursor cor1 is select c2 from bigclobtbl031 where c1=1; +cursor cor1 is select b from cloblongtbl where a=1; begin open cor1; loop @@ -210,16 +227,20 @@ end; call pro_cb4_037(); -drop table if exists cloblongtbl; -create table cloblongtbl (a int, b clob, c clob); -insert into cloblongtbl values (generate_series(1,4),repeat('唐李白床前明月光,疑是地上霜,举头望明月,低头思故乡',5000000),repeat('唐李白床前明月光,疑是地上霜,举头望明月,低头思故乡',5000000)); -update cloblongtbl set b = b||b; -update cloblongtbl set c = c||c; -update cloblongtbl set b = b||b where a = 2; -update cloblongtbl set c = c||c where a = 3; -update cloblongtbl set b = b||b where a = 4; -update cloblongtbl set c = c||c where a = 4; -select a, length(b || c) from cloblongtbl order by 1; +create or replace procedure test_self_update is +v1 clob; +begin +execute immediate 'select b from cloblongtbl where a=1' into v1; +update cloblongtbl set b=v1 where a=1; +savepoint aaa; +update cloblongtbl set b=v1 where a=2; +rollback to aaa; +commit; +end; +/ + +call test_self_update(); + drop table if exists cloblongtbl; -- clean -drop schema if exists huge_clob cascade; \ No newline at end of file +drop schema if exists huge_clob cascade;