From dab0a9ad1ed0caafbe0091c7f9b043b5c1dc60a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=85=E7=A8=8B?= <517719039@qq.com> Date: Thu, 24 Apr 2025 11:04:03 +0800 Subject: [PATCH] =?UTF-8?q?D=E5=BA=93=E4=BA=8B=E5=8A=A1=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=E8=AF=AD=E5=8F=A5=E5=85=BC=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contrib/shark/expected/functions.out | 16 +- contrib/shark/expected/transaction.out | 1212 +++++++++++++++++ contrib/shark/parallel_schedule | 2 +- contrib/shark/sql/functions.sql | 16 +- contrib/shark/sql/transaction.sql | 346 +++++ .../shark/src/backend_parser/gram-tsql-decl.y | 8 +- .../shark/src/backend_parser/gram-tsql-rule.y | 86 +- contrib/shark/src/backend_parser/kwlist.h | 2 + .../backend_parser/scan-tsql-epilogue.l.cpp | 63 + .../src/backend_parser/scan-tsql-prologue.l.h | 1 + .../shark/src/backend_parser/scan-tsql-rule.l | 108 +- src/bin/psql/common.cpp | 2 + src/bin/psql/psqlscan.l | 2 + 13 files changed, 1825 insertions(+), 39 deletions(-) create mode 100644 contrib/shark/expected/transaction.out create mode 100644 contrib/shark/sql/transaction.sql diff --git a/contrib/shark/expected/functions.out b/contrib/shark/expected/functions.out index bd14c5aee4..0952fbe5df 100644 --- a/contrib/shark/expected/functions.out +++ b/contrib/shark/expected/functions.out @@ -78,7 +78,7 @@ select @@rowcount; 0 (1 row) -begin; +begin transaction; declare c1 cursor for select * from t1; select @@rowcount; rowcount @@ -98,7 +98,7 @@ select @@rowcount; 1 (1 row) -end; +rollback transaction; select abcd from t1; -- expect error ERROR: column "abcd" does not exist LINE 1: select abcd from t1; @@ -189,7 +189,7 @@ select rowcount_big(); 0 (1 row) -begin; +begin transaction; declare c1 cursor for select * from t1; select rowcount_big(); rowcount_big @@ -209,7 +209,7 @@ select rowcount_big(); 1 (1 row) -end; +rollback transaction; select abcd from t1; -- expect error ERROR: column "abcd" does not exist LINE 1: select abcd from t1; @@ -313,7 +313,7 @@ select @@spid; -- @@fetch_status -- single cursor -begin; +begin transaction; cursor c1 for select * from t1; fetch next from c1; c1 @@ -355,9 +355,9 @@ fetch next from c2; -- expect error ERROR: cursor "c2" does not exist select @@fetch_status; ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] -end; +rollback transaction; -- multi cursors -begin; +begin transaction; cursor c1 for select * from t1; cursor c2 for select * from t1; fetch next from c1; @@ -408,7 +408,7 @@ select @@fetch_status; 0 (1 row) -end; +rollback transaction; -- pl/pgsql usecases declare rowcount int; diff --git a/contrib/shark/expected/transaction.out b/contrib/shark/expected/transaction.out new file mode 100644 index 0000000000..9e73d057cd --- /dev/null +++ b/contrib/shark/expected/transaction.out @@ -0,0 +1,1212 @@ +create schema transaction_test; +set search_path = 'transaction_test'; +create table t1(c1 int); +begin tran; +insert into t1 values(1); +select * from t1 order by c1; + c1 +---- + 1 +(1 row) + +commit tran; +select * from t1 order by c1; + c1 +---- + 1 +(1 row) + +begin tran transaction1; +insert into t1 values(2); +select * from t1 order by c1; + c1 +---- + 1 + 2 +(2 rows) + +commit tran transaction1; +select * from t1 order by c1; + c1 +---- + 1 + 2 +(2 rows) + +begin tran transaction1; +insert into t1 values(3); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 +(3 rows) + +commit tran transaction2; +begin tran transaction1; +insert into t1 values(4); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 +(4 rows) + +commit tran; +begin tran; +insert into t1 values(5); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 +(5 rows) + +commit tran transaction2; +begin tran; +insert into t1 values(6); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 6 +(6 rows) + +rollback tran; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 +(5 rows) + +begin tran transaction1; +insert into t1 values(7); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 7 +(6 rows) + +rollback tran; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 +(5 rows) + +begin tran transaction1; +insert into t1 values(8); +save tran savepoint1; +insert into t1 values(9); +rollback tran savePoint1; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 +(6 rows) + +commit tran; +begin tran transaction1; +insert into t1 values(10); +save tran savepoint1; +insert into t1 values(11); +rollback tran; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 +(6 rows) + +begin tran; +save tran savePoint1; +insert into t1 values(12); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 12 +(7 rows) + +rollback tran savePoint1; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 +(6 rows) + +save tran savePoint2; +insert into t1 values(13); +save tran savePoint3; +insert into t1 values(14); +save tran savePoint4; +insert into t1 values(15); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 13 + 14 + 15 +(9 rows) + +rollback tran savePoint4; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 13 + 14 +(8 rows) + +rollback tran savePoint3; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 13 +(7 rows) + +rollback tran savePoint2; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 +(6 rows) + +commit tran; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 +(6 rows) + +begin tran; +save tran savePoint1; +drop table t1; +\d t1; +rollback tran savePoint1; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 +(6 rows) + +save tran savePoint5; +insert into t1 values(16); +save tran savePoint6; +insert into t1 values(17); +save tran savePoint7; +insert into t1 values(18); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 17 + 18 +(9 rows) + +rollback tran savePoint6; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 +(7 rows) + +commit tran; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 +(7 rows) + +begin tran; +insert into t1 values(19); +save tran savePoint8; +insert into t1 values(20); +save tran savePoint9; +insert into t1 values(21); +save tran savePoint10; +insert into t1 values(22); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 20 + 21 + 22 +(11 rows) + +rollback tran savePoint8; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 +(8 rows) + +commit tran; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 +(8 rows) + +begin tran transaction1; +save tran savePoint1; +insert into t1 values(23); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 23 +(9 rows) + +-- expect error +rollback tran savePoint2; +ERROR: no such savepoint +select * from t1 order by c1; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +rollback tran; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 +(8 rows) + +begin tran transaction1; +insert into t1 values(24); +begin tran transaction2; +WARNING: there is already a transaction in progress +insert into t1 values(25); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 24 + 25 +(10 rows) + +commit tran transaction2; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 24 + 25 +(10 rows) + +commit tran transaction1; +WARNING: there is no transaction in progress +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 24 + 25 +(10 rows) + +begin tran transaction1; +insert into t1 values(26); +begin tran transaction2; +WARNING: there is already a transaction in progress +insert into t1 values(27); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 24 + 25 + 26 + 27 +(12 rows) + +rollback tran; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 24 + 25 +(10 rows) + +rollback tran; +NOTICE: there is no transaction in progress +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 24 + 25 +(10 rows) + +begin tran transaction1; +insert into t1 values(28); +begin tran transaction2; +WARNING: there is already a transaction in progress +insert into t1 values(29); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 24 + 25 + 28 + 29 +(12 rows) + +commit tran transaction1; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 24 + 25 + 28 + 29 +(12 rows) + +commit tran transaction2; +WARNING: there is no transaction in progress +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 24 + 25 + 28 + 29 +(12 rows) + +truncate table t1; +begin tran; +insert into t1 values(1); +commit work; +select * from t1; + c1 +---- + 1 +(1 row) + +begin tran; +insert into t1 values(2); +rollback work; +select * from t1; + c1 +---- + 1 +(1 row) + +begin tran; +insert into t1 values(3); +commit; +select * from t1; + c1 +---- + 1 + 3 +(2 rows) + +begin tran; +insert into t1 values(4); +rollback; +select * from t1; + c1 +---- + 1 + 3 +(2 rows) + +truncate table t1; +begin transaction; +insert into t1 values(1); +select * from t1 order by c1; + c1 +---- + 1 +(1 row) + +commit transaction; +select * from t1 order by c1; + c1 +---- + 1 +(1 row) + +begin transaction transaction1; +insert into t1 values(2); +select * from t1 order by c1; + c1 +---- + 1 + 2 +(2 rows) + +commit transaction transaction1; +select * from t1 order by c1; + c1 +---- + 1 + 2 +(2 rows) + +begin transaction transaction1; +insert into t1 values(3); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 +(3 rows) + +commit transaction transaction2; +begin transaction transaction1; +insert into t1 values(4); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 +(4 rows) + +commit transaction; +begin transaction; +insert into t1 values(5); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 +(5 rows) + +commit transaction transaction2; +begin transaction; +insert into t1 values(6); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 6 +(6 rows) + +rollback transaction; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 +(5 rows) + +begin transaction transaction1; +insert into t1 values(7); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 7 +(6 rows) + +rollback transaction; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 +(5 rows) + +begin transaction transaction1; +insert into t1 values(8); +save transaction savepoint1; +insert into t1 values(9); +rollback transaction savePoint1; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 +(6 rows) + +commit transaction; +begin transaction transaction1; +insert into t1 values(10); +save transaction savepoint1; +insert into t1 values(11); +rollback transaction; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 +(6 rows) + +begin transaction; +save transaction savePoint1; +insert into t1 values(12); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 12 +(7 rows) + +rollback transaction savePoint1; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 +(6 rows) + +save transaction savePoint2; +insert into t1 values(13); +save transaction savePoint3; +insert into t1 values(14); +save transaction savePoint4; +insert into t1 values(15); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 13 + 14 + 15 +(9 rows) + +rollback transaction savePoint4; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 13 + 14 +(8 rows) + +rollback transaction savePoint3; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 13 +(7 rows) + +rollback transaction savePoint2; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 +(6 rows) + +commit transaction; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 +(6 rows) + +begin transaction; +save transaction savePoint1; +drop table t1; +\d t1; +rollback transaction savePoint1; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 +(6 rows) + +save transaction savePoint5; +insert into t1 values(16); +save transaction savePoint6; +insert into t1 values(17); +save transaction savePoint7; +insert into t1 values(18); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 17 + 18 +(9 rows) + +rollback transaction savePoint6; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 +(7 rows) + +commit transaction; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 +(7 rows) + +begin transaction; +insert into t1 values(19); +save transaction savePoint8; +insert into t1 values(20); +save transaction savePoint9; +insert into t1 values(21); +save transaction savePoint10; +insert into t1 values(22); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 20 + 21 + 22 +(11 rows) + +rollback transaction savePoint8; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 +(8 rows) + +commit transaction; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 +(8 rows) + +begin transaction transaction1; +save transaction savePoint1; +insert into t1 values(23); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 23 +(9 rows) + +-- expect error +rollback transaction savePoint2; +ERROR: no such savepoint +select * from t1 order by c1; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +rollback transaction; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 +(8 rows) + +begin transaction transaction1; +insert into t1 values(24); +begin transaction transaction2; +WARNING: there is already a transaction in progress +insert into t1 values(25); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 24 + 25 +(10 rows) + +commit transaction transaction2; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 24 + 25 +(10 rows) + +commit transaction transaction1; +WARNING: there is no transaction in progress +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 24 + 25 +(10 rows) + +begin transaction transaction1; +insert into t1 values(26); +begin transaction transaction2; +WARNING: there is already a transaction in progress +insert into t1 values(27); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 24 + 25 + 26 + 27 +(12 rows) + +rollback transaction; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 24 + 25 +(10 rows) + +rollback transaction; +NOTICE: there is no transaction in progress +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 24 + 25 +(10 rows) + +begin transaction transaction1; +insert into t1 values(28); +begin transaction transaction2; +WARNING: there is already a transaction in progress +insert into t1 values(29); +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 24 + 25 + 28 + 29 +(12 rows) + +commit transaction transaction1; +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 24 + 25 + 28 + 29 +(12 rows) + +commit transaction transaction2; +WARNING: there is no transaction in progress +select * from t1 order by c1; + c1 +---- + 1 + 2 + 3 + 4 + 5 + 8 + 16 + 19 + 24 + 25 + 28 + 29 +(12 rows) + +truncate table t1; +begin transaction; +insert into t1 values(1); +commit work; +select * from t1; + c1 +---- + 1 +(1 row) + +begin transaction; +insert into t1 values(2); +rollback work; +select * from t1; + c1 +---- + 1 +(1 row) + +begin transaction; +insert into t1 values(3); +commit; +select * from t1; + c1 +---- + 1 + 3 +(2 rows) + +begin transaction; +insert into t1 values(4); +rollback; +select * from t1; + c1 +---- + 1 + 3 +(2 rows) + +drop table t1; +drop schema transaction_test cascade; diff --git a/contrib/shark/parallel_schedule b/contrib/shark/parallel_schedule index 23bb475c99..c7801d17f2 100644 --- a/contrib/shark/parallel_schedule +++ b/contrib/shark/parallel_schedule @@ -6,7 +6,7 @@ test: objectproperty test: clustered_index insert_stmt sbr_test test: test_ddl_and_dml test: rotate-test-part2 rotate-test-part2_ci -test: functions +test: functions transaction test: test_dbcc test_dbcc_case_sen test: test_sysviews test: gs_dump_d_format rotate_part2_dump diff --git a/contrib/shark/sql/functions.sql b/contrib/shark/sql/functions.sql index 0cfeb391b8..5fc90073d3 100644 --- a/contrib/shark/sql/functions.sql +++ b/contrib/shark/sql/functions.sql @@ -26,12 +26,12 @@ select @@rowcount; reset enable_set_variable_b_format; select @@rowcount; -begin; +begin transaction; declare c1 cursor for select * from t1; select @@rowcount; fetch next from c1; select @@rowcount; -end; +rollback transaction; select abcd from t1; -- expect error select @@rowcount; @@ -57,12 +57,12 @@ select rowcount_big(); reset enable_set_variable_b_format; select rowcount_big(); -begin; +begin transaction; declare c1 cursor for select * from t1; select rowcount_big(); fetch next from c1; select rowcount_big(); -end; +rollback transaction; select abcd from t1; -- expect error select rowcount_big(); @@ -97,7 +97,7 @@ select @@spid; -- @@fetch_status -- single cursor -begin; +begin transaction; cursor c1 for select * from t1; fetch next from c1; @@ -109,10 +109,10 @@ select @@fetch_status; fetch next from c2; -- expect error select @@fetch_status; -end; +rollback transaction; -- multi cursors -begin; +begin transaction; cursor c1 for select * from t1; cursor c2 for select * from t1; @@ -124,7 +124,7 @@ fetch last from c1; select @@fetch_status; fetch next from c2; select @@fetch_status; -end; +rollback transaction; -- pl/pgsql usecases declare diff --git a/contrib/shark/sql/transaction.sql b/contrib/shark/sql/transaction.sql new file mode 100644 index 0000000000..170e23dfb9 --- /dev/null +++ b/contrib/shark/sql/transaction.sql @@ -0,0 +1,346 @@ +create schema transaction_test; +set search_path = 'transaction_test'; + +create table t1(c1 int); + +begin tran; +insert into t1 values(1); +select * from t1 order by c1; +commit tran; +select * from t1 order by c1; + +begin tran transaction1; +insert into t1 values(2); +select * from t1 order by c1; +commit tran transaction1; +select * from t1 order by c1; + +begin tran transaction1; +insert into t1 values(3); +select * from t1 order by c1; +commit tran transaction2; + +begin tran transaction1; +insert into t1 values(4); +select * from t1 order by c1; +commit tran; + +begin tran; +insert into t1 values(5); +select * from t1 order by c1; +commit tran transaction2; + +begin tran; +insert into t1 values(6); +select * from t1 order by c1; +rollback tran; +select * from t1 order by c1; + +begin tran transaction1; +insert into t1 values(7); +select * from t1 order by c1; +rollback tran; +select * from t1 order by c1; + +begin tran transaction1; +insert into t1 values(8); +save tran savepoint1; +insert into t1 values(9); +rollback tran savePoint1; +select * from t1 order by c1; +commit tran; + +begin tran transaction1; +insert into t1 values(10); +save tran savepoint1; +insert into t1 values(11); +rollback tran; +select * from t1 order by c1; + +begin tran; +save tran savePoint1; +insert into t1 values(12); +select * from t1 order by c1; +rollback tran savePoint1; +select * from t1 order by c1; +save tran savePoint2; +insert into t1 values(13); +save tran savePoint3; +insert into t1 values(14); +save tran savePoint4; +insert into t1 values(15); +select * from t1 order by c1; +rollback tran savePoint4; +select * from t1 order by c1; +rollback tran savePoint3; +select * from t1 order by c1; +rollback tran savePoint2; +select * from t1 order by c1; +commit tran; +select * from t1 order by c1; + +begin tran; +save tran savePoint1; +drop table t1; +\d t1; +rollback tran savePoint1; +select * from t1 order by c1; +save tran savePoint5; +insert into t1 values(16); +save tran savePoint6; +insert into t1 values(17); +save tran savePoint7; +insert into t1 values(18); +select * from t1 order by c1; +rollback tran savePoint6; +select * from t1 order by c1; +commit tran; +select * from t1 order by c1; + +begin tran; +insert into t1 values(19); +save tran savePoint8; +insert into t1 values(20); +save tran savePoint9; +insert into t1 values(21); +save tran savePoint10; +insert into t1 values(22); +select * from t1 order by c1; +rollback tran savePoint8; +select * from t1 order by c1; +commit tran; +select * from t1 order by c1; + +begin tran transaction1; +save tran savePoint1; +insert into t1 values(23); +select * from t1 order by c1; +-- expect error +rollback tran savePoint2; +select * from t1 order by c1; +rollback tran; +select * from t1 order by c1; + +begin tran transaction1; +insert into t1 values(24); +begin tran transaction2; +insert into t1 values(25); +select * from t1 order by c1; +commit tran transaction2; +select * from t1 order by c1; +commit tran transaction1; +select * from t1 order by c1; + +begin tran transaction1; +insert into t1 values(26); +begin tran transaction2; +insert into t1 values(27); +select * from t1 order by c1; +rollback tran; +select * from t1 order by c1; +rollback tran; +select * from t1 order by c1; + +begin tran transaction1; +insert into t1 values(28); +begin tran transaction2; +insert into t1 values(29); +select * from t1 order by c1; +commit tran transaction1; +select * from t1 order by c1; +commit tran transaction2; +select * from t1 order by c1; + +truncate table t1; +begin tran; +insert into t1 values(1); +commit work; +select * from t1; + +begin tran; +insert into t1 values(2); +rollback work; +select * from t1; + +begin tran; +insert into t1 values(3); +commit; +select * from t1; + +begin tran; +insert into t1 values(4); +rollback; +select * from t1; + +truncate table t1; +begin transaction; +insert into t1 values(1); +select * from t1 order by c1; +commit transaction; +select * from t1 order by c1; + +begin transaction transaction1; +insert into t1 values(2); +select * from t1 order by c1; +commit transaction transaction1; +select * from t1 order by c1; + +begin transaction transaction1; +insert into t1 values(3); +select * from t1 order by c1; +commit transaction transaction2; + +begin transaction transaction1; +insert into t1 values(4); +select * from t1 order by c1; +commit transaction; + +begin transaction; +insert into t1 values(5); +select * from t1 order by c1; +commit transaction transaction2; + +begin transaction; +insert into t1 values(6); +select * from t1 order by c1; +rollback transaction; +select * from t1 order by c1; + +begin transaction transaction1; +insert into t1 values(7); +select * from t1 order by c1; +rollback transaction; +select * from t1 order by c1; + +begin transaction transaction1; +insert into t1 values(8); +save transaction savepoint1; +insert into t1 values(9); +rollback transaction savePoint1; +select * from t1 order by c1; +commit transaction; + +begin transaction transaction1; +insert into t1 values(10); +save transaction savepoint1; +insert into t1 values(11); +rollback transaction; +select * from t1 order by c1; + +begin transaction; +save transaction savePoint1; +insert into t1 values(12); +select * from t1 order by c1; +rollback transaction savePoint1; +select * from t1 order by c1; +save transaction savePoint2; +insert into t1 values(13); +save transaction savePoint3; +insert into t1 values(14); +save transaction savePoint4; +insert into t1 values(15); +select * from t1 order by c1; +rollback transaction savePoint4; +select * from t1 order by c1; +rollback transaction savePoint3; +select * from t1 order by c1; +rollback transaction savePoint2; +select * from t1 order by c1; +commit transaction; +select * from t1 order by c1; + +begin transaction; +save transaction savePoint1; +drop table t1; +\d t1; +rollback transaction savePoint1; +select * from t1 order by c1; +save transaction savePoint5; +insert into t1 values(16); +save transaction savePoint6; +insert into t1 values(17); +save transaction savePoint7; +insert into t1 values(18); +select * from t1 order by c1; +rollback transaction savePoint6; +select * from t1 order by c1; +commit transaction; +select * from t1 order by c1; + +begin transaction; +insert into t1 values(19); +save transaction savePoint8; +insert into t1 values(20); +save transaction savePoint9; +insert into t1 values(21); +save transaction savePoint10; +insert into t1 values(22); +select * from t1 order by c1; +rollback transaction savePoint8; +select * from t1 order by c1; +commit transaction; +select * from t1 order by c1; + +begin transaction transaction1; +save transaction savePoint1; +insert into t1 values(23); +select * from t1 order by c1; +-- expect error +rollback transaction savePoint2; +select * from t1 order by c1; +rollback transaction; +select * from t1 order by c1; + +begin transaction transaction1; +insert into t1 values(24); +begin transaction transaction2; +insert into t1 values(25); +select * from t1 order by c1; +commit transaction transaction2; +select * from t1 order by c1; +commit transaction transaction1; +select * from t1 order by c1; + +begin transaction transaction1; +insert into t1 values(26); +begin transaction transaction2; +insert into t1 values(27); +select * from t1 order by c1; +rollback transaction; +select * from t1 order by c1; +rollback transaction; +select * from t1 order by c1; + +begin transaction transaction1; +insert into t1 values(28); +begin transaction transaction2; +insert into t1 values(29); +select * from t1 order by c1; +commit transaction transaction1; +select * from t1 order by c1; +commit transaction transaction2; +select * from t1 order by c1; + +truncate table t1; +begin transaction; +insert into t1 values(1); +commit work; +select * from t1; + +begin transaction; +insert into t1 values(2); +rollback work; +select * from t1; + +begin transaction; +insert into t1 values(3); +commit; +select * from t1; + +begin transaction; +insert into t1 values(4); +rollback; +select * from t1; + +drop table t1; +drop schema transaction_test cascade; diff --git a/contrib/shark/src/backend_parser/gram-tsql-decl.y b/contrib/shark/src/backend_parser/gram-tsql-decl.y index b284521b6a..c4d19e587a 100644 --- a/contrib/shark/src/backend_parser/gram-tsql-decl.y +++ b/contrib/shark/src/backend_parser/gram-tsql-decl.y @@ -1,12 +1,12 @@ %type tsql_stmtmulti -%type DBCCCheckIdentStmt DBCCStmt tsql_stmt tsql_CreateProcedureStmt tsql_IndexStmt +%type DBCCCheckIdentStmt DBCCStmt tsql_stmt tsql_CreateProcedureStmt tsql_IndexStmt tsql_TransactionStmt -%token CHECKIDENT DBCC NO_INFOMSGS NORESEED RESEED TSQL_CLUSTERED TSQL_NONCLUSTERED TSQL_COLUMNSTORE TSQL_PERSISTED TSQL_TOP TSQL_PERCENT +%token CHECKIDENT DBCC NO_INFOMSGS NORESEED RESEED SAVE TRAN TSQL_CLUSTERED TSQL_NONCLUSTERED TSQL_COLUMNSTORE TSQL_PERSISTED TSQL_TOP TSQL_PERCENT %type tsql_opt_clustered tsql_opt_columnstore %token TSQL_ATAT_IDENT %type opt_with_no_infomsgs %type TSQL_computed_column %type tsql_top_clause tsql_select_top_value %type tsql_opt_ties tsql_opt_percent -%type DirectColLabel -%type direct_label_keyword +%type DirectColLabel tsql_opt_transaction_name +%type direct_label_keyword tsql_transaction_keywords tsql_opt_work_keywords diff --git a/contrib/shark/src/backend_parser/gram-tsql-rule.y b/contrib/shark/src/backend_parser/gram-tsql-rule.y index 20ae2c4e5a..82761c6110 100644 --- a/contrib/shark/src/backend_parser/gram-tsql-rule.y +++ b/contrib/shark/src/backend_parser/gram-tsql-rule.y @@ -633,8 +633,8 @@ tsql_stmt : | CreateAsStmt | CreateAssertStmt | CreateCastStmt - | CreateContQueryStmt - | CreateStreamStmt + | CreateContQueryStmt + | CreateStreamStmt | CreateConversionStmt | CreateDomainStmt | CreateDirectoryStmt @@ -759,7 +759,7 @@ tsql_stmt : | ShutdownStmt | TimeCapsuleStmt | SnapshotStmt - | TransactionStmt + | tsql_TransactionStmt | TruncateStmt | UnlistenStmt | UpdateStmt @@ -1473,6 +1473,7 @@ direct_label_keyword: ABORT_P | ROWTYPE_P | RULE | SAMPLE + | SAVE | SAVEPOINT | SCHEDULE | SCHEMA @@ -1568,6 +1569,7 @@ direct_label_keyword: ABORT_P | TINYINT | TSQL_TOP | TRAILING + | TRAN | TRANSACTION | TRANSFORM | TREAT @@ -1638,4 +1640,80 @@ direct_label_keyword: ABORT_P | YEAR_MONTH_P | YES_P | ZONE - ; + ; + +tsql_opt_transaction_name: + ColId + | /*EMPTY*/ { $$ = NULL; } + ; + +tsql_transaction_keywords: + TRAN + | TRANSACTION + ; + +tsql_opt_work_keywords: + WORK + | /*EMPTY*/ { $$ = NULL; } + ; + +tsql_TransactionStmt: + START TRANSACTION transaction_mode_list_or_empty /*kernel forward compatible*/ + { + TransactionStmt *n = makeNode(TransactionStmt); + n->kind = TRANS_STMT_START; + n->options = $3; + $$ = (Node *)n; + } + | BEGIN_NON_ANOYBLOCK tsql_transaction_keywords tsql_opt_transaction_name + { + TransactionStmt *n = makeNode(TransactionStmt); + n->kind = TRANS_STMT_BEGIN; + n->options = NIL; + $$ = (Node *)n; + } + | COMMIT tsql_opt_work_keywords + { + TransactionStmt *n = makeNode(TransactionStmt); + n->kind = TRANS_STMT_COMMIT; + n->options = NIL; + $$ = (Node *)n; + } + | COMMIT tsql_transaction_keywords tsql_opt_transaction_name + { + TransactionStmt *n = makeNode(TransactionStmt); + n->kind = TRANS_STMT_COMMIT; + n->options = NIL; + $$ = (Node *)n; + } + | ROLLBACK tsql_opt_work_keywords + { + TransactionStmt *n = makeNode(TransactionStmt); + n->kind = TRANS_STMT_ROLLBACK; + n->options = NIL; + $$ = (Node *)n; + } + | ROLLBACK tsql_transaction_keywords tsql_opt_transaction_name + { + TransactionStmt *n = makeNode(TransactionStmt); + if ($3 == NULL) { + n->kind = TRANS_STMT_ROLLBACK; + n->options = NIL; + } else { + n->kind = TRANS_STMT_ROLLBACK_TO; + n->options = list_make1(makeDefElem("savepoint_name", + (Node *)makeString($3))); + } + $$ = (Node *)n; + } + | SAVE tsql_transaction_keywords ColId + { + TransactionStmt *n = makeNode(TransactionStmt); + n->kind = TRANS_STMT_SAVEPOINT; + n->options = list_make1(makeDefElem("savepoint_name", + (Node *)makeString($3))); + $$ = (Node *)n; + } + ; + + \ No newline at end of file diff --git a/contrib/shark/src/backend_parser/kwlist.h b/contrib/shark/src/backend_parser/kwlist.h index f7a37d046c..85be8c784f 100644 --- a/contrib/shark/src/backend_parser/kwlist.h +++ b/contrib/shark/src/backend_parser/kwlist.h @@ -584,6 +584,7 @@ PG_KEYWORD("rows", ROWS, UNRESERVED_KEYWORD, DIRECT_LABEL) PG_KEYWORD("rowtype", ROWTYPE_P, UNRESERVED_KEYWORD, DIRECT_LABEL) PG_KEYWORD("rule", RULE, UNRESERVED_KEYWORD, DIRECT_LABEL) PG_KEYWORD("sample", SAMPLE, UNRESERVED_KEYWORD, DIRECT_LABEL) +PG_KEYWORD("save", SAVE, UNRESERVED_KEYWORD, DIRECT_LABEL) PG_KEYWORD("savepoint", SAVEPOINT, UNRESERVED_KEYWORD, DIRECT_LABEL) PG_KEYWORD("schedule", SCHEDULE, UNRESERVED_KEYWORD, DIRECT_LABEL) PG_KEYWORD("schema", SCHEMA, UNRESERVED_KEYWORD, DIRECT_LABEL) @@ -683,6 +684,7 @@ PG_KEYWORD("tinyint", TINYINT, COL_NAME_KEYWORD, DIRECT_LABEL) PG_KEYWORD("to", TO, RESERVED_KEYWORD, AS_LABEL) PG_KEYWORD("top", TSQL_TOP, RESERVED_KEYWORD, DIRECT_LABEL) PG_KEYWORD("trailing", TRAILING, RESERVED_KEYWORD, DIRECT_LABEL) +PG_KEYWORD("tran", TRAN, UNRESERVED_KEYWORD, DIRECT_LABEL) PG_KEYWORD("transaction", TRANSACTION, UNRESERVED_KEYWORD, DIRECT_LABEL) PG_KEYWORD("transform", TRANSFORM, UNRESERVED_KEYWORD, DIRECT_LABEL) PG_KEYWORD("treat", TREAT, COL_NAME_KEYWORD, DIRECT_LABEL) diff --git a/contrib/shark/src/backend_parser/scan-tsql-epilogue.l.cpp b/contrib/shark/src/backend_parser/scan-tsql-epilogue.l.cpp index 122956e473..e3b2c4129c 100644 --- a/contrib/shark/src/backend_parser/scan-tsql-epilogue.l.cpp +++ b/contrib/shark/src/backend_parser/scan-tsql-epilogue.l.cpp @@ -114,3 +114,66 @@ bool IsTsqlAtatGlobalVar(const char* varname) (pg_strcasecmp("@@ROWCOUNT", varname) == 0) || (pg_strcasecmp("@@SPID", varname) == 0)); } + +static bool isTsqlTranStmt(const char *haystack, int haystack_len) +{ + char *tempstr = (char *)palloc0(haystack_len + 1); + char *temp = tempstr; + int line = 1; /* lineno of haystack which split by \0 */ + bool found_non_blank_char = false; /* mark if we find a non blank char after begin */ + errno_t rc = EOK; + + /* we have to make a copy, since haystack is const char* */ + rc = memcpy_s(tempstr, haystack_len + 1, haystack, haystack_len); + securec_check_ss(rc, "\0", "\0"); + + /* find if the 2nd line is prefixed by a valid transaction token */ + while (temp < tempstr + haystack_len) + { + /* there may be '\0' in the string, and should be skipped */ + if (*temp == '\0') + { + temp++; + line++; + /* we only search the 2nd line */ + if (line > 2) + break; + } + /* skip the blank char */ + else if (isspace(*temp)) + { + temp++; + } + else + { + /* we found a non blank char after begin, do further checking */ + if (line == 2) + found_non_blank_char = true; + /* For a transaction statement, all possible tokens after BEGIN are here */ + if (line == 2 && (pg_strncasecmp(temp, "transaction", strlen("transaction")) == 0 || + pg_strncasecmp(temp, "tran", strlen("tran")) == 0 || + pg_strncasecmp(temp, "work", strlen("work")) == 0 || + pg_strncasecmp(temp, "isolation", strlen("isolation")) == 0 || + pg_strncasecmp(temp, "read", strlen("read")) == 0 || + pg_strncasecmp(temp, "deferrable", strlen("deferrable")) == 0 || + pg_strncasecmp(temp, "not", strlen("not")) == 0 || + pg_strncasecmp(temp, ";", strlen(";")) == 0)) + { + FREE_POINTER(tempstr); + return true; + } + + temp += strlen(temp); + } + } + + FREE_POINTER (tempstr); + + /* + * if all the char after begin are blank + * it is a trans stmt + * else + * it is a anaynomous block stmt + */ + return found_non_blank_char ? false : true; +} \ No newline at end of file diff --git a/contrib/shark/src/backend_parser/scan-tsql-prologue.l.h b/contrib/shark/src/backend_parser/scan-tsql-prologue.l.h index 93b49fbfea..1de32257a3 100644 --- a/contrib/shark/src/backend_parser/scan-tsql-prologue.l.h +++ b/contrib/shark/src/backend_parser/scan-tsql-prologue.l.h @@ -39,3 +39,4 @@ const uint16 pgtsql_ScanKeywordTokens[] = { (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner) extern bool IsTsqlAtatGlobalVar(const char *varname); +static bool isTsqlTranStmt(const char *haystack, int haystack_len); diff --git a/contrib/shark/src/backend_parser/scan-tsql-rule.l b/contrib/shark/src/backend_parser/scan-tsql-rule.l index 2de41e31e8..a513f69c4a 100644 --- a/contrib/shark/src/backend_parser/scan-tsql-rule.l +++ b/contrib/shark/src/backend_parser/scan-tsql-rule.l @@ -65,17 +65,97 @@ } {set_identifier} { - SET_YYLLOC(); - char *set_ident = - downcase_truncate_identifier(yytext, yyleng, yyextra->warnOnTruncateIdent); - if (IsTsqlAtatGlobalVar(set_ident)) { - yylval->str = set_ident; - yyextra->ident_quoted = false; - return TSQL_ATAT_IDENT; - } else { - yyless(2); - yylval->str = pstrdup(yytext); - yyextra->is_hint_str = false; - return Op; - } - } \ No newline at end of file + SET_YYLLOC(); + char *set_ident = + downcase_truncate_identifier(yytext, yyleng, yyextra->warnOnTruncateIdent); + if (IsTsqlAtatGlobalVar(set_ident)) { + yylval->str = set_ident; + yyextra->ident_quoted = false; + return TSQL_ATAT_IDENT; + } else { + yyless(2); + yylval->str = pstrdup(yytext); + yyextra->is_hint_str = false; + return Op; + } + } + +{identifier} { + int kwnum; + char *ident; + + SET_YYLLOC(); + + /* Is it a keyword? */ + kwnum = ScanKeywordLookup(yytext, yyextra->keywordlist); + + yyextra->is_hint_str = false; + bool isPlpgsqlKeyword = yyextra->isPlpgsqlKeyWord; + bool need_ignore = (!isPlpgsqlKeyword && kwnum >= 0) ? + semtc_is_token_in_ignore_keyword_list(yyextra->keyword_tokens[kwnum], false) : false; + if (kwnum >= 0 && !need_ignore) + { + yylval->keyword = GetScanKeyword(kwnum, yyextra->keywordlist); + uint16 token = yyextra->keyword_tokens[kwnum]; + + /* Find the CREATE PROCEDURE syntax and set dolqstart. */ + if (token == CREATE) + { + yyextra->is_createstmt = true; + } + else if (token == TRIGGER && yyextra->is_createstmt) + { + /* Create trigger don't need set dolqstart */ + yyextra->is_createstmt = false; + } + else if ((token == (isPlpgsqlKeyword? yyextra->plKeywordValue->procedure : PROCEDURE) || + token == (isPlpgsqlKeyword? yyextra->plKeywordValue->function : FUNCTION)) + && (yyextra->is_createstmt)) + { + /* Make yyextra->dolqstart not NULL means its in a proc with $$. */ + yyextra->dolqstart = ""; + } + else if (token == (isPlpgsqlKeyword? yyextra->plKeywordValue->begin : BEGIN_P)) + { + if (!(u_sess->parser_cxt.isCreateFuncOrProc || u_sess->plsql_cxt.curr_compile_context != NULL)) { + /* cases that have to be a trans stmt and fall quickly */ + if (yyg->yy_hold_char == ';' || /* found ';' after 'begin' */ + yyg->yy_hold_char == '\0') /* found '\0' after 'begin' */ + return BEGIN_NON_ANOYBLOCK; + /* look for other transaction stmt */ + if (isTsqlTranStmt(yyextra->scanbuf, yyextra->scanbuflen)) + return BEGIN_NON_ANOYBLOCK; + } + } + else if (token == (isPlpgsqlKeyword? yyextra->plKeywordValue->select : SELECT) || + token == (isPlpgsqlKeyword? yyextra->plKeywordValue->update : UPDATE) || + token == (isPlpgsqlKeyword? yyextra->plKeywordValue->insert : INSERT) || + token == (isPlpgsqlKeyword? yyextra->plKeywordValue->Delete : DELETE_P) || + token == MERGE) + { + yyextra->is_hint_str = true; + } + + set_is_delimiter_name(yytext,yyscanner); + return token; + } + + /* + * No. Convert the identifier to lower case, and truncate + * if necessary. + */ + ident = downcase_truncate_identifier(yytext, yyleng, yyextra->warnOnTruncateIdent); + /* Is it _charset? */ + if (ident[0] == '_' && + ENABLE_MULTI_CHARSET && + pg_valid_server_encoding(ident + 1) >= 0) { + yylval->str = pstrdup(ident + 1); + yyextra->is_hint_str = false; + yyextra->ident_quoted = false; + return UNDERSCORE_CHARSET; + } + yylval->str = ident; + yyextra->ident_quoted = false; + set_is_delimiter_name(yytext,yyscanner); + return IDENT; + } diff --git a/src/bin/psql/common.cpp b/src/bin/psql/common.cpp index 1cbdf9f17e..213a026d18 100644 --- a/src/bin/psql/common.cpp +++ b/src/bin/psql/common.cpp @@ -2750,6 +2750,8 @@ DBFormatType GetDatabaseType() dbType = B_FORMAT; } else if (strcmp(compatibilityStr, "C") == 0) { dbType = C_FORMAT; + } else if (strcmp(compatibilityStr, "D") == 0) { + dbType = D_FORMAT; } else if (strcmp(compatibilityStr, "PG") == 0) { dbType = PG_FORMAT; } diff --git a/src/bin/psql/psqlscan.l b/src/bin/psql/psqlscan.l index 880f99a250..229ec24bcf 100644 --- a/src/bin/psql/psqlscan.l +++ b/src/bin/psql/psqlscan.l @@ -648,8 +648,10 @@ other . ECHO; if (lex_param->begin_state == BEGIN_UNDEFINED) { + DBFormatType dbType = GetDatabaseType(); /* For a transaction statement, all possible tokens after BEGIN are here */ if (IsTranscationTokens(yytext, "transaction") || + (dbType == D_FORMAT && IsTranscationTokens(yytext, "tran")) || IsTranscationTokens(yytext, "work") || IsTranscationTokens(yytext, "isolation") || IsTranscationTokens(yytext, "read") || -- Gitee