From 3dfe9dee3f0ac68be0e842664384357c46865acf Mon Sep 17 00:00:00 2001 From: TotaJ Date: Mon, 20 Dec 2021 10:06:57 +0800 Subject: [PATCH] Tuple lock fit logical deocde --- .../storage/replication/logical/decode.cpp | 26 +- src/test/regress/expected/rule_test.out | 694 +++++++++--------- src/test/regress/sql/rule_test.sql | 452 ++++++------ 3 files changed, 592 insertions(+), 580 deletions(-) diff --git a/src/gausskernel/storage/replication/logical/decode.cpp b/src/gausskernel/storage/replication/logical/decode.cpp index ce9ed0789..095e654fd 100644 --- a/src/gausskernel/storage/replication/logical/decode.cpp +++ b/src/gausskernel/storage/replication/logical/decode.cpp @@ -873,15 +873,21 @@ static void DecodeUpdate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) Size datalen_old; Size tuplelen_old; char *data_old = NULL; + Size heapUpdateSize; + if ((XLogRecGetInfo(r) & XLOG_TUPLE_LOCK_UPGRADE_FLAG) == 0) { + heapUpdateSize = SizeOfOldHeapUpdate; + } else { + heapUpdateSize = SizeOfHeapUpdate; + } /* adapt 64 xid, if this tuple is the first tuple of a new page */ bool is_init = (XLogRecGetInfo(r) & XLOG_HEAP_INIT_PAGE) != 0; /* caution, remaining data in record is not aligned */ - data_old = (char *)xlrec + SizeOfHeapUpdate; + data_old = (char *)xlrec + heapUpdateSize; if (is_init) { - datalen_old = XLogRecGetDataLen(r) - SizeOfHeapUpdate - sizeof(TransactionId); + datalen_old = XLogRecGetDataLen(r) - heapUpdateSize - sizeof(TransactionId); } else { - datalen_old = XLogRecGetDataLen(r) - SizeOfHeapUpdate; + datalen_old = XLogRecGetDataLen(r) - heapUpdateSize; } tuplelen_old = datalen_old - SizeOfHeapHeader; if (tuplelen_old == 0 && !AllocSizeIsValid(tuplelen_old)) { @@ -1054,8 +1060,14 @@ static void DecodeDelete(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) ReorderBufferChange *change = NULL; RelFileNode target_node; int rc = 0; - xlrec = (xl_heap_delete *)GetXlrec(r); + Size heapDeleteSize; + if ((XLogRecGetInfo(r) & XLOG_TUPLE_LOCK_UPGRADE_FLAG) == 0) { + heapDeleteSize = SizeOfOldHeapDelete; + } else { + heapDeleteSize = SizeOfHeapDelete; + } + xlrec = (xl_heap_delete *)GetXlrec(r); /* only interested in our database */ XLogRecGetBlockTag(r, 0, &target_node, NULL, NULL); if (target_node.dbNode != ctx->slot->data.database) @@ -1064,7 +1076,7 @@ static void DecodeDelete(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) if (FilterByOrigin(ctx, XLogRecGetOrigin(r))) return; - Size datalen = XLogRecGetDataLen(r) - SizeOfHeapDelete; + Size datalen = XLogRecGetDataLen(r) - heapDeleteSize; if (datalen == 0 && !AllocSizeIsValid(datalen)) { ereport(WARNING, (errmsg("tuplelen is invalid(%lu), tuplelen, don't decode it", datalen))); return; @@ -1077,10 +1089,10 @@ static void DecodeDelete(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) /* old primary key stored */ if (xlrec->flags & XLH_DELETE_CONTAINS_OLD) { - Assert(XLogRecGetDataLen(r) > (SizeOfHeapDelete + SizeOfHeapHeader)); + Assert(XLogRecGetDataLen(r) > (heapDeleteSize + SizeOfHeapHeader)); change->data.tp.oldtuple = ReorderBufferGetTupleBuf(ctx->reorder, datalen); - DecodeXLogTuple((char *)xlrec + SizeOfHeapDelete, datalen, change->data.tp.oldtuple); + DecodeXLogTuple((char *)xlrec + heapDeleteSize, datalen, change->data.tp.oldtuple); } change->data.tp.clear_toast_afterwards = true; diff --git a/src/test/regress/expected/rule_test.out b/src/test/regress/expected/rule_test.out index 686c608e4..c697e7418 100644 --- a/src/test/regress/expected/rule_test.out +++ b/src/test/regress/expected/rule_test.out @@ -1,347 +1,347 @@ --- --- RULES TEST --- --- --- Tables and rules for the view test --- -create table rule_test1_table (a int4, b int4); -create view tv1 as select * from rule_test1_table; -create rule tv1_ins as on insert to tv1 do instead - insert into rule_test1_table values (new.a, new.b); -create rule tv1_upd as on update to tv1 do instead - update rule_test1_table set a = new.a, b = new.b - where a = old.a; -create rule tv1_del as on delete to tv1 do instead - delete from rule_test1_table where a = old.a; --- insert values -insert into tv1 values (1, 11); -insert into tv1 values (2, 12); -select * from tv1; - a | b ----+---- - 1 | 11 - 2 | 12 -(2 rows) - --- update values -update tv1 set a = 10 where b = 11; -update tv1 set a = 12 , b = 22 where b = 12; -select * from tv1; - a | b -----+---- - 10 | 11 - 12 | 22 -(2 rows) - --- delete values -delete from tv1 where a = 10; -select * from tv1; - a | b -----+---- - 12 | 22 -(1 row) - -drop rule if exists tv1_ins on tv1; -drop rule if exists tv1_upd on tv1; -drop rule if exists tv1_del on tv1; -drop view if exists tv1; -drop table if exists rule_test1_table; --- --- Tables and rules for the constraint update/delete/insert test --- -create table ttsystem (sysname text, sysdesc text); -create table ttadmin (pname text, sysname text); -create table ttperon (pname text, pdesc text); -create table ttinterface (sysname text, ifname text); -create rule usys_ins as on insert to ttsystem do also ( - insert into ttinterface values (new.sysname,''); - insert into ttadmin values ('',new.sysname); - ); -create rule usys_del as on delete to ttsystem do also ( - delete from ttinterface where sysname = old.sysname; - delete from ttadmin where sysname = old.sysname; - ); -create rule usys_upd as on update to ttsystem do also ( - update ttinterface set sysname = new.sysname - where sysname = old.sysname; - update ttadmin set sysname = new.sysname - where sysname = old.sysname - ); -create rule upers_ins as on insert to ttperon do also ( - insert into ttadmin values (new.pname,''); - ); -create rule upers_del as on delete to ttperon do also - delete from ttadmin where pname = old.pname; -create rule upers_upd as on update to ttperon do also - update ttadmin set pname = new.pname where pname = old.pname; - --- test 1 -insert into ttsystem values ('winxi', 'Linux Jan Wieck'); -insert into ttsystem values ('notjw', 'Qu Yan'); -insert into ttsystem values ('yuyan', 'Fileserver'); -insert into ttinterface values ('winxi', 'dola'); -insert into ttinterface values ('winxi', 'eth1'); -insert into ttinterface values ('notjw', 'dola'); -insert into ttinterface values ('yuyan', 'dola'); -insert into ttperon values ('jw', 'Jan Wieck'); -insert into ttperon values ('bm', 'Bruce Momjian'); -insert into ttadmin values ('jw', 'winxi'); -insert into ttadmin values ('jw', 'notjw'); -insert into ttadmin values ('bm', 'yuyan'); -select * from ttsystem; - sysname | sysdesc ----------+----------------- - winxi | Linux Jan Wieck - notjw | Qu Yan - yuyan | Fileserver -(3 rows) - -select * from ttinterface; - sysname | ifname ----------+-------- - winxi | - notjw | - yuyan | - winxi | dola - winxi | eth1 - notjw | dola - yuyan | dola -(7 rows) - -select * from ttperon; - pname | pdesc --------+--------------- - jw | Jan Wieck - bm | Bruce Momjian -(2 rows) - -select * from ttadmin; - pname | sysname --------+--------- - | winxi - | notjw - | yuyan - jw | - bm | - jw | winxi - jw | notjw - bm | yuyan -(8 rows) - --- test 2 -update ttsystem set sysname = 'pluto' where sysname = 'yuyan'; -select * from ttinterface; - sysname | ifname ----------+-------- - winxi | - notjw | - winxi | dola - winxi | eth1 - notjw | dola - pluto | - pluto | dola -(7 rows) - -select * from ttadmin; - pname | sysname --------+--------- - | winxi - | notjw - jw | - bm | - jw | winxi - jw | notjw - | pluto - bm | pluto -(8 rows) - -update ttperon set pname = 'jwieck' where pdesc = 'Jan Wieck'; -select * from ttadmin order by pname, sysname; - pname | sysname ---------+--------- - bm | pluto - bm | - jwieck | notjw - jwieck | winxi - jwieck | - | notjw - | pluto - | winxi -(8 rows) - -delete from ttsystem where sysname = 'winxi'; -select * from ttinterface; - sysname | ifname ----------+-------- - notjw | - notjw | dola - pluto | - pluto | dola -(4 rows) - -select * from ttadmin; - pname | sysname ---------+--------- - | notjw - bm | - | pluto - bm | pluto - jwieck | - jwieck | notjw -(6 rows) - -delete from ttperon where pname = 'bm'; -select * from ttadmin; - pname | sysname ---------+--------- - | notjw - | pluto - jwieck | - jwieck | notjw -(4 rows) - -drop rule if exists usys_upd on ttsystem; -drop rule if exists usys_del on ttsystem; -drop rule if exists usys_ins on ttsystem; -drop rule if exists upers_upd on ttperon; -drop rule if exists upers_del on ttperon; -drop rule if exists upers_ins on ttperon; -drop table if exists ttsystem; -drop table if exists ttinterface; -drop table if exists ttperon; -drop table if exists ttadmin; --- --- Tables and rules for the logging test --- -create table temp (ename char(20), salary money); -create table templog (ename char(20), action char(10), newsal money, oldsal money); -create rule temp_ins as on insert to temp do - insert into templog values (new.ename, 'hired', new.salary, '0.00'); -create rule temp_upd as on update to temp where new.salary != old.salary do - insert into templog values (new.ename, 'honored', new.salary, old.salary); -create rule temp_del as on delete to temp do - insert into templog values (old.ename, 'fired', '0.00', old.salary); -insert into temp values ('tyu', '45.00'); -insert into temp values ('asd', '90.00'); -select * from templog; - ename | action | newsal | oldsal -----------------------+------------+--------+-------- - tyu | hired | $45.00 | $0.00 - asd | hired | $90.00 | $0.00 -(2 rows) - -update temp set salary = salary * 2 where ename = 'tyu'; -select * from templog; - ename | action | newsal | oldsal -----------------------+------------+--------+-------- - tyu | hired | $45.00 | $0.00 - asd | hired | $90.00 | $0.00 - tyu | honored | $90.00 | $45.00 -(3 rows) - -delete from temp where ename = 'tyu'; -select * from templog; - ename | action | newsal | oldsal -----------------------+------------+--------+-------- - tyu | hired | $45.00 | $0.00 - asd | hired | $90.00 | $0.00 - tyu | honored | $90.00 | $45.00 - tyu | fired | $0.00 | $90.00 -(4 rows) - -select * from temp; - ename | salary -----------------------+-------- - asd | $90.00 -(1 row) - -drop rule if exists temp_ins on temp; -drop rule if exists temp_upd on temp; -drop rule if exists temp_del on temp; -drop table if exists temp; -drop table if exists templog; --- --- Rules for condition --- rule test --- -create table test4 (a int4, b text); -create table test5 (a int4, b text); -create table test6 (a int4, b text); -create rule test4_ins1 as on insert to test4 - where new.a >= 10 and new.a < 20 do instead - insert into test5 values (new.a, new.b); -create rule test4_ins2 as on insert to test4 - where new.a >= 20 and new.a < 30 do - insert into test6 values (new.a, new.b); --- test -insert into test4 values (5, 'huijioa'); -insert into test4 values (15, 'afhuvbn'); -insert into test4 values (25, 'qwerty'); -insert into test4 values (35, 'zxcvbn'); -select * from test4; - a | b -----+--------- - 5 | huijioa - 25 | qwerty - 35 | zxcvbn -(3 rows) - -select * from test5; - a | b -----+--------- - 15 | afhuvbn -(1 row) - -select * from test6; - a | b -----+-------- - 25 | qwerty -(1 row) - -drop rule if exists test4_ins1 on test4; -drop rule if exists test4_ins2 on test4; -drop table if exists test4; -drop table if exists test5; -drop table if exists test6; --- --- Tables and rules for select --- -create table ttt1 (a int4, b text); -create table ttt2 (a int4, b text); -create rule "_RETURN" as on select to ttt1 do instead ( - select * from ttt2; - ); --- test -insert into ttt1 values (1, 'hello'); -insert into ttt2 values (10, 'world'); -select * from ttt1; - a | b -----+------- - 10 | world -(1 row) - -drop table if exists ttt1; -drop table if exists ttt2; --- --- Tables and rules for question --- -create table test_statement(id int); -create table escapetest (ts varchar(50)); -create rule r1 as on insert to escapetest do ( - delete from test_statement; - insert into test_statement values (1); - insert into test_statement values (2); - ); - --- test -insert into escapetest(ts) values (NULL); -select * from test_statement; - id ----- - 1 - 2 -(2 rows) - -drop rule if exists r1 on escapetest; -drop table if exists test_statement; -drop table if exists escapetest; +-- +-- RULES TEST +-- +-- +-- Tables and rules for the view test +-- +create table rule_test1_table (a int4, b int4); +create view tv1 as select * from rule_test1_table; +create rule tv1_ins as on insert to tv1 do instead + insert into rule_test1_table values (new.a, new.b); +create rule tv1_upd as on update to tv1 do instead + update rule_test1_table set a = new.a, b = new.b + where a = old.a; +create rule tv1_del as on delete to tv1 do instead + delete from rule_test1_table where a = old.a; +-- insert values +insert into tv1 values (1, 11); +insert into tv1 values (2, 12); +select * from tv1; + a | b +---+---- + 1 | 11 + 2 | 12 +(2 rows) + +-- update values +update tv1 set a = 10 where b = 11; +update tv1 set a = 12 , b = 22 where b = 12; +select * from tv1; + a | b +----+---- + 10 | 11 + 12 | 22 +(2 rows) + +-- delete values +delete from tv1 where a = 10; +select * from tv1; + a | b +----+---- + 12 | 22 +(1 row) + +drop rule if exists tv1_ins on tv1; +drop rule if exists tv1_upd on tv1; +drop rule if exists tv1_del on tv1; +drop view if exists tv1; +drop table if exists rule_test1_table; +-- +-- Tables and rules for the constraint update/delete/insert test +-- +create table ttsystem (sysname text, sysdesc text); +create table ttadmin (pname text, sysname text); +create table ttperon (pname text, pdesc text); +create table ttinterface (sysname text, ifname text); +create rule usys_ins as on insert to ttsystem do also ( + insert into ttinterface values (new.sysname,''); + insert into ttadmin values ('',new.sysname); + ); +create rule usys_del as on delete to ttsystem do also ( + delete from ttinterface where sysname = old.sysname; + delete from ttadmin where sysname = old.sysname; + ); +create rule usys_upd as on update to ttsystem do also ( + update ttinterface set sysname = new.sysname + where sysname = old.sysname; + update ttadmin set sysname = new.sysname + where sysname = old.sysname + ); +create rule upers_ins as on insert to ttperon do also ( + insert into ttadmin values (new.pname,''); + ); +create rule upers_del as on delete to ttperon do also + delete from ttadmin where pname = old.pname; +create rule upers_upd as on update to ttperon do also + update ttadmin set pname = new.pname where pname = old.pname; + +-- test 1 +insert into ttsystem values ('winxi', 'Linux Jan Wieck'); +insert into ttsystem values ('notjw', 'Qu Yan'); +insert into ttsystem values ('yuyan', 'Fileserver'); +insert into ttinterface values ('winxi', 'dola'); +insert into ttinterface values ('winxi', 'eth1'); +insert into ttinterface values ('notjw', 'dola'); +insert into ttinterface values ('yuyan', 'dola'); +insert into ttperon values ('jw', 'Jan Wieck'); +insert into ttperon values ('bm', 'Bruce Momjian'); +insert into ttadmin values ('jw', 'winxi'); +insert into ttadmin values ('jw', 'notjw'); +insert into ttadmin values ('bm', 'yuyan'); +select * from ttsystem; + sysname | sysdesc +---------+----------------- + winxi | Linux Jan Wieck + notjw | Qu Yan + yuyan | Fileserver +(3 rows) + +select * from ttinterface; + sysname | ifname +---------+-------- + winxi | + notjw | + yuyan | + winxi | dola + winxi | eth1 + notjw | dola + yuyan | dola +(7 rows) + +select * from ttperon; + pname | pdesc +-------+--------------- + jw | Jan Wieck + bm | Bruce Momjian +(2 rows) + +select * from ttadmin; + pname | sysname +-------+--------- + | winxi + | notjw + | yuyan + jw | + bm | + jw | winxi + jw | notjw + bm | yuyan +(8 rows) + +-- test 2 +update ttsystem set sysname = 'pluto' where sysname = 'yuyan'; +select * from ttinterface; + sysname | ifname +---------+-------- + winxi | + notjw | + winxi | dola + winxi | eth1 + notjw | dola + pluto | + pluto | dola +(7 rows) + +select * from ttadmin; + pname | sysname +-------+--------- + | winxi + | notjw + jw | + bm | + jw | winxi + jw | notjw + | pluto + bm | pluto +(8 rows) + +update ttperon set pname = 'jwieck' where pdesc = 'Jan Wieck'; +select * from ttadmin order by pname, sysname; + pname | sysname +--------+--------- + bm | pluto + bm | + jwieck | notjw + jwieck | winxi + jwieck | + | notjw + | pluto + | winxi +(8 rows) + +delete from ttsystem where sysname = 'winxi'; +select * from ttinterface; + sysname | ifname +---------+-------- + notjw | + notjw | dola + pluto | + pluto | dola +(4 rows) + +select * from ttadmin; + pname | sysname +--------+--------- + | notjw + bm | + | pluto + bm | pluto + jwieck | + jwieck | notjw +(6 rows) + +delete from ttperon where pname = 'bm'; +select * from ttadmin; + pname | sysname +--------+--------- + | notjw + | pluto + jwieck | + jwieck | notjw +(4 rows) + +drop rule if exists usys_upd on ttsystem; +drop rule if exists usys_del on ttsystem; +drop rule if exists usys_ins on ttsystem; +drop rule if exists upers_upd on ttperon; +drop rule if exists upers_del on ttperon; +drop rule if exists upers_ins on ttperon; +drop table if exists ttsystem; +drop table if exists ttinterface; +drop table if exists ttperon; +drop table if exists ttadmin; +-- +-- Tables and rules for the logging test +-- +create table temp (ename char(20), salary money); +create table templog (ename char(20), action char(10), newsal money, oldsal money); +create rule temp_ins as on insert to temp do + insert into templog values (new.ename, 'hired', new.salary, '0.00'); +create rule temp_upd as on update to temp where new.salary != old.salary do + insert into templog values (new.ename, 'honored', new.salary, old.salary); +create rule temp_del as on delete to temp do + insert into templog values (old.ename, 'fired', '0.00', old.salary); +insert into temp values ('tyu', '45.00'); +insert into temp values ('asd', '90.00'); +select * from templog; + ename | action | newsal | oldsal +----------------------+------------+--------+-------- + tyu | hired | $45.00 | $0.00 + asd | hired | $90.00 | $0.00 +(2 rows) + +update temp set salary = salary * 2 where ename = 'tyu'; +select * from templog; + ename | action | newsal | oldsal +----------------------+------------+--------+-------- + tyu | hired | $45.00 | $0.00 + asd | hired | $90.00 | $0.00 + tyu | honored | $90.00 | $45.00 +(3 rows) + +delete from temp where ename = 'tyu'; +select * from templog; + ename | action | newsal | oldsal +----------------------+------------+--------+-------- + tyu | hired | $45.00 | $0.00 + asd | hired | $90.00 | $0.00 + tyu | honored | $90.00 | $45.00 + tyu | fired | $0.00 | $90.00 +(4 rows) + +select * from temp; + ename | salary +----------------------+-------- + asd | $90.00 +(1 row) + +drop rule if exists temp_ins on temp; +drop rule if exists temp_upd on temp; +drop rule if exists temp_del on temp; +drop table if exists temp; +drop table if exists templog; +-- +-- Rules for condition +-- rule test +-- +create table test4 (a int4, b text); +create table test5 (a int4, b text); +create table test6 (a int4, b text); +create rule test4_ins1 as on insert to test4 + where new.a >= 10 and new.a < 20 do instead + insert into test5 values (new.a, new.b); +create rule test4_ins2 as on insert to test4 + where new.a >= 20 and new.a < 30 do + insert into test6 values (new.a, new.b); +-- test +insert into test4 values (5, 'huijioa'); +insert into test4 values (15, 'afhuvbn'); +insert into test4 values (25, 'qwerty'); +insert into test4 values (35, 'zxcvbn'); +select * from test4; + a | b +----+--------- + 5 | huijioa + 25 | qwerty + 35 | zxcvbn +(3 rows) + +select * from test5; + a | b +----+--------- + 15 | afhuvbn +(1 row) + +select * from test6; + a | b +----+-------- + 25 | qwerty +(1 row) + +drop rule if exists test4_ins1 on test4; +drop rule if exists test4_ins2 on test4; +drop table if exists test4; +drop table if exists test5; +drop table if exists test6; +-- +-- Tables and rules for select +-- +create table ttt1 (a int4, b text); +create table ttt2 (a int4, b text); +create rule "_RETURN" as on select to ttt1 do instead ( + select * from ttt2; + ); +-- test +insert into ttt1 values (1, 'hello'); +insert into ttt2 values (10, 'world'); +select * from ttt1; + a | b +----+------- + 10 | world +(1 row) + +drop table if exists ttt1; +drop table if exists ttt2; +-- +-- Tables and rules for question +-- +create table test_statement(id int); +create table escapetest (ts varchar(50)); +create rule r1 as on insert to escapetest do ( + delete from test_statement; + insert into test_statement values (1); + insert into test_statement values (2); + ); + +-- test +insert into escapetest(ts) values (NULL); +select * from test_statement; + id +---- + 1 + 2 +(2 rows) + +drop rule if exists r1 on escapetest; +drop table if exists test_statement; +drop table if exists escapetest; diff --git a/src/test/regress/sql/rule_test.sql b/src/test/regress/sql/rule_test.sql index bc9ed3115..5547c09af 100644 --- a/src/test/regress/sql/rule_test.sql +++ b/src/test/regress/sql/rule_test.sql @@ -1,226 +1,226 @@ --- --- RULES TEST --- - --- --- Tables and rules for the view test --- -create table rule_test1_table (a int4, b int4); -create view tv1 as select * from rule_test1_table; -create rule tv1_ins as on insert to tv1 do instead - insert into rule_test1_table values (new.a, new.b); -create rule tv1_upd as on update to tv1 do instead - update rule_test1_table set a = new.a, b = new.b - where a = old.a; -create rule tv1_del as on delete to tv1 do instead - delete from rule_test1_table where a = old.a; - --- insert values -insert into tv1 values (1, 11); -insert into tv1 values (2, 12); -select * from tv1; - --- update values -update tv1 set a = 10 where b = 11; -update tv1 set a = 12 , b = 22 where b = 12; -select * from tv1; - --- delete values -delete from tv1 where a = 10; -select * from tv1; - -drop rule if exists tv1_ins on tv1; -drop rule if exists tv1_upd on tv1; -drop rule if exists tv1_del on tv1; -drop view if exists tv1; -drop table if exists rule_test1_table; - - --- --- Tables and rules for the constraint update/delete/insert test --- -create table ttsystem (sysname text, sysdesc text); -create table ttadmin (pname text, sysname text); -create table ttperon (pname text, pdesc text); -create table ttinterface (sysname text, ifname text); - -create rule usys_ins as on insert to ttsystem do also ( - insert into ttinterface values (new.sysname,''); - insert into ttadmin values ('',new.sysname); - ); - -create rule usys_del as on delete to ttsystem do also ( - delete from ttinterface where sysname = old.sysname; - delete from ttadmin where sysname = old.sysname; - ); - -create rule usys_upd as on update to ttsystem do also ( - update ttinterface set sysname = new.sysname - where sysname = old.sysname; - update ttadmin set sysname = new.sysname - where sysname = old.sysname - ); - -create rule upers_ins as on insert to ttperon do also ( - insert into ttadmin values (new.pname,''); - ); - -create rule upers_del as on delete to ttperon do also - delete from ttadmin where pname = old.pname; - -create rule upers_upd as on update to ttperon do also - update ttadmin set pname = new.pname where pname = old.pname; - --- test 1 -insert into ttsystem values ('winxi', 'Linux Jan Wieck'); -insert into ttsystem values ('notjw', 'Qu Yan'); -insert into ttsystem values ('yuyan', 'Fileserver'); - -insert into ttinterface values ('winxi', 'dola'); -insert into ttinterface values ('winxi', 'eth1'); -insert into ttinterface values ('notjw', 'dola'); -insert into ttinterface values ('yuyan', 'dola'); - -insert into ttperon values ('jw', 'Jan Wieck'); -insert into ttperon values ('bm', 'Bruce Momjian'); - -insert into ttadmin values ('jw', 'winxi'); -insert into ttadmin values ('jw', 'notjw'); -insert into ttadmin values ('bm', 'yuyan'); - -select * from ttsystem; -select * from ttinterface; -select * from ttperon; -select * from ttadmin; - --- test 2 -update ttsystem set sysname = 'pluto' where sysname = 'yuyan'; -select * from ttinterface; -select * from ttadmin; - -update ttperon set pname = 'jwieck' where pdesc = 'Jan Wieck'; -select * from ttadmin order by pname, sysname; - -delete from ttsystem where sysname = 'winxi'; -select * from ttinterface; -select * from ttadmin; - -delete from ttperon where pname = 'bm'; -select * from ttadmin; - -drop rule if exists usys_upd on ttsystem; -drop rule if exists usys_del on ttsystem; -drop rule if exists usys_ins on ttsystem; -drop rule if exists upers_upd on ttperon; -drop rule if exists upers_del on ttperon; -drop rule if exists upers_ins on ttperon; -drop table if exists ttsystem; -drop table if exists ttinterface; -drop table if exists ttperon; -drop table if exists ttadmin; - --- --- Tables and rules for the logging test --- -create table temp (ename char(20), salary money); -create table templog (ename char(20), action char(10), newsal money, oldsal money); - -create rule temp_ins as on insert to temp do - insert into templog values (new.ename, 'hired', new.salary, '0.00'); - -create rule temp_upd as on update to temp where new.salary != old.salary do - insert into templog values (new.ename, 'honored', new.salary, old.salary); - -create rule temp_del as on delete to temp do - insert into templog values (old.ename, 'fired', '0.00', old.salary); - -insert into temp values ('tyu', '45.00'); -insert into temp values ('asd', '90.00'); -select * from templog; - -update temp set salary = salary * 2 where ename = 'tyu'; -select * from templog; - -delete from temp where ename = 'tyu'; -select * from templog; - -select * from temp; - -drop rule if exists temp_ins on temp; -drop rule if exists temp_upd on temp; -drop rule if exists temp_del on temp; -drop table if exists temp; -drop table if exists templog; - --- --- Rules for condition --- rule test --- -create table test4 (a int4, b text); -create table test5 (a int4, b text); -create table test6 (a int4, b text); - -create rule test4_ins1 as on insert to test4 - where new.a >= 10 and new.a < 20 do instead - insert into test5 values (new.a, new.b); - -create rule test4_ins2 as on insert to test4 - where new.a >= 20 and new.a < 30 do - insert into test6 values (new.a, new.b); - - --- test -insert into test4 values (5, 'huijioa'); -insert into test4 values (15, 'afhuvbn'); -insert into test4 values (25, 'qwerty'); -insert into test4 values (35, 'zxcvbn'); - -select * from test4; -select * from test5; -select * from test6; - -drop rule if exists test4_ins1 on test4; -drop rule if exists test4_ins2 on test4; -drop table if exists test4; -drop table if exists test5; -drop table if exists test6; - --- --- Tables and rules for select --- -create table ttt1 (a int4, b text); -create table ttt2 (a int4, b text); - -create rule "_RETURN" as on select to ttt1 do instead ( - select * from ttt2; - ); - --- test -insert into ttt1 values (1, 'hello'); -insert into ttt2 values (10, 'world'); -select * from ttt1; - -drop table if exists ttt1; -drop table if exists ttt2; - --- --- Tables and rules for question --- - -create table test_statement(id int); -create table escapetest (ts varchar(50)); -create rule r1 as on insert to escapetest do ( - delete from test_statement; - insert into test_statement values (1); - insert into test_statement values (2); - ); - --- test -insert into escapetest(ts) values (NULL); -select * from test_statement; - -drop rule if exists r1 on escapetest; -drop table if exists test_statement; -drop table if exists escapetest; - - +-- +-- RULES TEST +-- + +-- +-- Tables and rules for the view test +-- +create table rule_test1_table (a int4, b int4); +create view tv1 as select * from rule_test1_table; +create rule tv1_ins as on insert to tv1 do instead + insert into rule_test1_table values (new.a, new.b); +create rule tv1_upd as on update to tv1 do instead + update rule_test1_table set a = new.a, b = new.b + where a = old.a; +create rule tv1_del as on delete to tv1 do instead + delete from rule_test1_table where a = old.a; + +-- insert values +insert into tv1 values (1, 11); +insert into tv1 values (2, 12); +select * from tv1; + +-- update values +update tv1 set a = 10 where b = 11; +update tv1 set a = 12 , b = 22 where b = 12; +select * from tv1; + +-- delete values +delete from tv1 where a = 10; +select * from tv1; + +drop rule if exists tv1_ins on tv1; +drop rule if exists tv1_upd on tv1; +drop rule if exists tv1_del on tv1; +drop view if exists tv1; +drop table if exists rule_test1_table; + + +-- +-- Tables and rules for the constraint update/delete/insert test +-- +create table ttsystem (sysname text, sysdesc text); +create table ttadmin (pname text, sysname text); +create table ttperon (pname text, pdesc text); +create table ttinterface (sysname text, ifname text); + +create rule usys_ins as on insert to ttsystem do also ( + insert into ttinterface values (new.sysname,''); + insert into ttadmin values ('',new.sysname); + ); + +create rule usys_del as on delete to ttsystem do also ( + delete from ttinterface where sysname = old.sysname; + delete from ttadmin where sysname = old.sysname; + ); + +create rule usys_upd as on update to ttsystem do also ( + update ttinterface set sysname = new.sysname + where sysname = old.sysname; + update ttadmin set sysname = new.sysname + where sysname = old.sysname + ); + +create rule upers_ins as on insert to ttperon do also ( + insert into ttadmin values (new.pname,''); + ); + +create rule upers_del as on delete to ttperon do also + delete from ttadmin where pname = old.pname; + +create rule upers_upd as on update to ttperon do also + update ttadmin set pname = new.pname where pname = old.pname; + +-- test 1 +insert into ttsystem values ('winxi', 'Linux Jan Wieck'); +insert into ttsystem values ('notjw', 'Qu Yan'); +insert into ttsystem values ('yuyan', 'Fileserver'); + +insert into ttinterface values ('winxi', 'dola'); +insert into ttinterface values ('winxi', 'eth1'); +insert into ttinterface values ('notjw', 'dola'); +insert into ttinterface values ('yuyan', 'dola'); + +insert into ttperon values ('jw', 'Jan Wieck'); +insert into ttperon values ('bm', 'Bruce Momjian'); + +insert into ttadmin values ('jw', 'winxi'); +insert into ttadmin values ('jw', 'notjw'); +insert into ttadmin values ('bm', 'yuyan'); + +select * from ttsystem; +select * from ttinterface; +select * from ttperon; +select * from ttadmin; + +-- test 2 +update ttsystem set sysname = 'pluto' where sysname = 'yuyan'; +select * from ttinterface; +select * from ttadmin; + +update ttperon set pname = 'jwieck' where pdesc = 'Jan Wieck'; +select * from ttadmin order by pname, sysname; + +delete from ttsystem where sysname = 'winxi'; +select * from ttinterface; +select * from ttadmin; + +delete from ttperon where pname = 'bm'; +select * from ttadmin; + +drop rule if exists usys_upd on ttsystem; +drop rule if exists usys_del on ttsystem; +drop rule if exists usys_ins on ttsystem; +drop rule if exists upers_upd on ttperon; +drop rule if exists upers_del on ttperon; +drop rule if exists upers_ins on ttperon; +drop table if exists ttsystem; +drop table if exists ttinterface; +drop table if exists ttperon; +drop table if exists ttadmin; + +-- +-- Tables and rules for the logging test +-- +create table temp (ename char(20), salary money); +create table templog (ename char(20), action char(10), newsal money, oldsal money); + +create rule temp_ins as on insert to temp do + insert into templog values (new.ename, 'hired', new.salary, '0.00'); + +create rule temp_upd as on update to temp where new.salary != old.salary do + insert into templog values (new.ename, 'honored', new.salary, old.salary); + +create rule temp_del as on delete to temp do + insert into templog values (old.ename, 'fired', '0.00', old.salary); + +insert into temp values ('tyu', '45.00'); +insert into temp values ('asd', '90.00'); +select * from templog; + +update temp set salary = salary * 2 where ename = 'tyu'; +select * from templog; + +delete from temp where ename = 'tyu'; +select * from templog; + +select * from temp; + +drop rule if exists temp_ins on temp; +drop rule if exists temp_upd on temp; +drop rule if exists temp_del on temp; +drop table if exists temp; +drop table if exists templog; + +-- +-- Rules for condition +-- rule test +-- +create table test4 (a int4, b text); +create table test5 (a int4, b text); +create table test6 (a int4, b text); + +create rule test4_ins1 as on insert to test4 + where new.a >= 10 and new.a < 20 do instead + insert into test5 values (new.a, new.b); + +create rule test4_ins2 as on insert to test4 + where new.a >= 20 and new.a < 30 do + insert into test6 values (new.a, new.b); + + +-- test +insert into test4 values (5, 'huijioa'); +insert into test4 values (15, 'afhuvbn'); +insert into test4 values (25, 'qwerty'); +insert into test4 values (35, 'zxcvbn'); + +select * from test4; +select * from test5; +select * from test6; + +drop rule if exists test4_ins1 on test4; +drop rule if exists test4_ins2 on test4; +drop table if exists test4; +drop table if exists test5; +drop table if exists test6; + +-- +-- Tables and rules for select +-- +create table ttt1 (a int4, b text); +create table ttt2 (a int4, b text); + +create rule "_RETURN" as on select to ttt1 do instead ( + select * from ttt2; + ); + +-- test +insert into ttt1 values (1, 'hello'); +insert into ttt2 values (10, 'world'); +select * from ttt1; + +drop table if exists ttt1; +drop table if exists ttt2; + +-- +-- Tables and rules for question +-- + +create table test_statement(id int); +create table escapetest (ts varchar(50)); +create rule r1 as on insert to escapetest do ( + delete from test_statement; + insert into test_statement values (1); + insert into test_statement values (2); + ); + +-- test +insert into escapetest(ts) values (NULL); +select * from test_statement; + +drop rule if exists r1 on escapetest; +drop table if exists test_statement; +drop table if exists escapetest; + +