blob: d30621b197d54c9fb0ea23484a6b46262ffead47 [file] [log] [blame]
--
-- DISTRIBUTED TRANSACTIONS
--
--SET debug_print_full_dtm=true;
--
-- start_matchsubs
--
-- # create a match/subs expression
--
-- m/(ERROR|WARNING|CONTEXT|NOTICE):.*The previous session was reset because its gang was disconnected/
-- s/session id \=\s*\d+/session id \= DUMMY/gm
--
-- end_matchsubs
--
--
-- We want to have an error between the point where all segments are prepared and our decision
-- to write the Distributed Commit record.
--
-- start_ignore
BEGIN;
DROP TABLE IF EXISTS distxact1_1;
NOTICE: table "distxact1_1" does not exist, skipping
DROP TABLE IF EXISTS distxact1_2;
NOTICE: table "distxact1_2" does not exist, skipping
DROP TABLE IF EXISTS distxact1_3;
NOTICE: table "distxact1_3" does not exist, skipping
DROP TABLE IF EXISTS distxact1_4;
NOTICE: table "distxact1_4" does not exist, skipping
CREATE TABLE distxact1_1 (a int) DISTRIBUTED BY (a);
CREATE TABLE distxact1_2 (a int) DISTRIBUTED BY (a);
CREATE TABLE distxact1_3 (a int) DISTRIBUTED BY (a);
CREATE TABLE distxact1_4 (a int) DISTRIBUTED BY (a);
COMMIT;
-- end_ignore
set optimizer_print_missing_stats = off;
BEGIN;
INSERT INTO distxact1_1 VALUES (1);
INSERT INTO distxact1_1 VALUES (2);
INSERT INTO distxact1_1 VALUES (3);
INSERT INTO distxact1_1 VALUES (4);
INSERT INTO distxact1_1 VALUES (5);
INSERT INTO distxact1_1 VALUES (6);
INSERT INTO distxact1_1 VALUES (7);
INSERT INTO distxact1_1 VALUES (8);
SET debug_abort_after_distributed_prepared = true;
COMMIT;
ERROR: Raise an error as directed by Debug_abort_after_distributed_prepared
RESET debug_abort_after_distributed_prepared;
SELECT * FROM distxact1_1;
a
---
(0 rows)
--
-- We want to have an error during the prepare which will cause a Abort-Some-Prepared broadcast
-- to cleanup.
--
BEGIN;
INSERT INTO distxact1_2 VALUES (21);
INSERT INTO distxact1_2 VALUES (22);
INSERT INTO distxact1_2 VALUES (23);
INSERT INTO distxact1_2 VALUES (24);
INSERT INTO distxact1_2 VALUES (25);
INSERT INTO distxact1_2 VALUES (26);
INSERT INTO distxact1_2 VALUES (27);
INSERT INTO distxact1_2 VALUES (28);
SET debug_dtm_action_segment=1;
SET debug_dtm_action = "fail_begin_command";
SET debug_dtm_action_target = "protocol";
SET debug_dtm_action_protocol = "prepare";
COMMIT;
ERROR: Raise ERROR for debug_dtm_action = 2, debug_dtm_action_protocol = Distributed Prepare (seg1 127.0.0.1:40001 pid=25677)
RESET debug_dtm_action;
RESET debug_dtm_action_target;
RESET debug_dtm_action_protocol;
SELECT * FROM distxact1_2;
a
---
(0 rows)
--
-- We want to have an error during the commit-prepared broadcast which will cause a
-- Retry-Commit-Prepared broadcast to cleanup.
--
BEGIN;
INSERT INTO distxact1_3 VALUES (31);
INSERT INTO distxact1_3 VALUES (32);
INSERT INTO distxact1_3 VALUES (33);
INSERT INTO distxact1_3 VALUES (34);
INSERT INTO distxact1_3 VALUES (35);
INSERT INTO distxact1_3 VALUES (36);
INSERT INTO distxact1_3 VALUES (37);
INSERT INTO distxact1_3 VALUES (38);
SET debug_dtm_action_segment=1;
SET debug_dtm_action = "fail_begin_command";
SET debug_dtm_action_target = "protocol";
SET debug_dtm_action_protocol = "commit_prepared";
COMMIT;
WARNING: the distributed transaction 'Commit Prepared' broadcast failed to one or more segments. Retrying ... try 1
DETAIL: gid=66802167, state=Retry Commit Prepared
NOTICE: Releasing segworker group to retry broadcast.
SELECT * FROM distxact1_3;
a
----
38
32
31
33
34
35
36
37
(8 rows)
RESET debug_dtm_action_segment;
RESET debug_dtm_action;
RESET debug_dtm_action_target;
RESET debug_dtm_action_protocol;
--
-- VARIANT of we want to have an error between the point where all segments are prepared and our decision
-- to write the Distributed Commit record. Cause problem during abort-prepared broadcast.
--
BEGIN;
INSERT INTO distxact1_4 VALUES (41);
INSERT INTO distxact1_4 VALUES (42);
INSERT INTO distxact1_4 VALUES (43);
INSERT INTO distxact1_4 VALUES (44);
INSERT INTO distxact1_4 VALUES (45);
INSERT INTO distxact1_4 VALUES (46);
INSERT INTO distxact1_4 VALUES (47);
INSERT INTO distxact1_4 VALUES (48);
SET debug_dtm_action_segment=1;
SET debug_abort_after_distributed_prepared = true;
SET debug_dtm_action = "fail_begin_command";
SET debug_dtm_action_target = "protocol";
SET debug_dtm_action_protocol = "abort_prepared";
COMMIT;
WARNING: the distributed transaction broadcast failed to one or more segments
DETAIL: gid=66802193, state=Notifying Abort Prepared
ERROR: Raise an error as directed by Debug_abort_after_distributed_prepared
SELECT * FROM distxact1_4;
a
---
(0 rows)
RESET debug_dtm_action_segment;
RESET debug_abort_after_distributed_prepared;
RESET debug_dtm_action;
RESET debug_dtm_action_target;
RESET debug_dtm_action_protocol;
--
-- Fail general commands
--
--
-- Invoke a failure during a CREATE TABLE command.
--
--SET debug_print_full_dtm=true;
SET debug_dtm_action_segment=1;
SET debug_dtm_action = "fail_begin_command";
SET debug_dtm_action_target = "sql";
SET debug_dtm_action_sql_command_tag = "MPPEXEC UTILITY";
CREATE TABLE distxact2_1 (a int);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Apache Cloudberry data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
ERROR: Raise ERROR for debug_dtm_action = 2, commandTag = MPPEXEC UTILITY (seg1 127.0.1.1:25433 pid=1127)
RESET debug_dtm_action_segment;
RESET debug_dtm_action_sql_command_tag;
RESET debug_dtm_action;
RESET debug_dtm_action_target;
SELECT * FROM distxact2_1;
ERROR: relation "distxact2_1" does not exist
LINE 1: SELECT * FROM distxact2_1;
^
-- Should succeed
CREATE TABLE distxact2_1 (a int);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Apache Cloudberry data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
DROP TABLE distxact2_1;
--
-- Invoke a failure during a CREATE TABLE command.
-- Action_Target = 2 is SQL.
--
SET debug_dtm_action_segment=1;
SET debug_dtm_action = "fail_end_command";
SET debug_dtm_action_target = "sql";
SET debug_dtm_action_sql_command_tag = "MPPEXEC UTILITY";
CREATE TABLE distxact2_2 (a int);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Apache Cloudberry data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
ERROR: Raise ERROR for debug_dtm_action = 3, commandTag = MPPEXEC UTILITY (seg1 127.0.1.1:25433 pid=1127)
RESET debug_dtm_action_segment;
RESET debug_dtm_action_sql_command_tag;
RESET debug_dtm_action;
RESET debug_dtm_action_target;
SELECT * FROM distxact2_2;
ERROR: relation "distxact2_2" does not exist
LINE 1: SELECT * FROM distxact2_2;
^
-- Should succeed
CREATE TABLE distxact2_2 (a int);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Apache Cloudberry data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
DROP TABLE distxact2_2;
--
-- xact.c DTM related dispatches
--
--
-- Invoke a failure during a SAVEPOINT command.
--
--SET debug_print_full_dtm=true;
SET debug_dtm_action_segment=1;
SET debug_dtm_action = "fail_begin_command";
SET debug_dtm_action_target = "sql";
SET debug_dtm_action_sql_command_tag = "SAVEPOINT";
BEGIN;
CREATE TABLE distxact3_1 (a int);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Apache Cloudberry data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
SAVEPOINT s;
ERROR: Raise ERROR for debug_dtm_action = 2, commandTag = SAVEPOINT (seg1 127.0.1.1:25433 pid=1127)
ROLLBACK;
RESET debug_dtm_action_segment;
RESET debug_dtm_action_sql_command_tag;
RESET debug_dtm_action;
RESET debug_dtm_action_target;
SELECT * FROM distxact3_1;
ERROR: relation "distxact3_1" does not exist
LINE 1: SELECT * FROM distxact3_1;
^
-- Should succeed
CREATE TABLE distxact3_1 (a int);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Apache Cloudberry data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
DROP TABLE distxact3_1;
--
-- Invoke a failure during a RELEASE SAVEPOINT command.
--
--SET debug_print_full_dtm=true;
SET debug_dtm_action_segment=1;
SET debug_dtm_action = "fail_begin_command";
SET debug_dtm_action_target = "sql";
SET debug_dtm_action_sql_command_tag = "RELEASE";
BEGIN;
CREATE TABLE distxact3_2 (a int);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Apache Cloudberry data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
SAVEPOINT s;
INSERT INTO distxact3_2 VALUES (21);
INSERT INTO distxact3_2 VALUES (22);
INSERT INTO distxact3_2 VALUES (23);
INSERT INTO distxact3_2 VALUES (24);
INSERT INTO distxact3_2 VALUES (25);
INSERT INTO distxact3_2 VALUES (26);
INSERT INTO distxact3_2 VALUES (27);
INSERT INTO distxact3_2 VALUES (28);
RELEASE SAVEPOINT s;
ERROR: Raise ERROR for debug_dtm_action = 2, commandTag = RELEASE (seg1 127.0.1.1:25433 pid=1127)
ROLLBACK;
RESET debug_dtm_action_segment;
RESET debug_dtm_action_sql_command_tag;
RESET debug_dtm_action;
RESET debug_dtm_action_target;
SELECT * FROM distxact3_2;
ERROR: relation "distxact3_2" does not exist
LINE 1: SELECT * FROM distxact3_2;
^
-- Should succeed
CREATE TABLE distxact3_2 (a int);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Apache Cloudberry data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
DROP TABLE distxact3_2;
--
-- Invoke a failure during a ROLLBACK TO SAVEPOINT command.
--
--SET debug_print_full_dtm=true;
SET debug_dtm_action_segment=1;
SET debug_dtm_action = "fail_begin_command";
SET debug_dtm_action_target = "sql";
SET debug_dtm_action_sql_command_tag = "ROLLBACK";
BEGIN;
CREATE TABLE distxact3_3 (a int);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Apache Cloudberry data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
SAVEPOINT s;
INSERT INTO distxact3_3 VALUES (31);
INSERT INTO distxact3_3 VALUES (32);
INSERT INTO distxact3_3 VALUES (33);
INSERT INTO distxact3_3 VALUES (34);
INSERT INTO distxact3_3 VALUES (35);
INSERT INTO distxact3_3 VALUES (36);
INSERT INTO distxact3_3 VALUES (37);
INSERT INTO distxact3_3 VALUES (38);
ROLLBACK TO SAVEPOINT s;
ERROR: Raise ERROR for debug_dtm_action = 2, commandTag = ROLLBACK (seg1 127.0.1.1:25433 pid=1127)
ROLLBACK;
RESET debug_dtm_action_segment;
RESET debug_dtm_action_sql_command_tag;
RESET debug_dtm_action;
RESET debug_dtm_action_target;
SELECT * FROM distxact3_3;
ERROR: relation "distxact3_3" does not exist
LINE 1: SELECT * FROM distxact3_3;
^
-- Should succeed
CREATE TABLE distxact3_3 (a int);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Apache Cloudberry data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
DROP TABLE distxact3_3;
RESET debug_print_full_dtm;
-- Test cursor/serializable interaction.
-- MPP-3227: pg_dump does this exact sequence.
-- for each table in a database.
drop table if exists dtmcurse_foo;
NOTICE: table "dtmcurse_foo" does not exist, skipping
drop table if exists dtmcurse_bar;
NOTICE: table "dtmcurse_bar" does not exist, skipping
create table dtmcurse_foo (a int, b int);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Apache Cloudberry data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
insert into dtmcurse_foo values (1,2);
insert into dtmcurse_foo values (2,2);
create table dtmcurse_bar as select * from dtmcurse_foo distributed by (b);
begin;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
DECLARE cursor1 CURSOR FOR SELECT * FROM ONLY dtmcurse_foo order by a;
fetch 1 from cursor1;
a | b
---+---
1 | 2
(1 row)
close cursor1;
-- MPP-3227: second declare would hang waiting for snapshot,
-- should work just like the first.
DECLARE cursor1 CURSOR FOR SELECT * FROM ONLY dtmcurse_bar order by a;
fetch 1 from cursor1;
a | b
---+---
1 | 2
(1 row)
close cursor1;
abort;
-- MPP-4504: cursor + InitPlan
begin;
declare c1 cursor for select * from dtmcurse_foo where a = (select min(a) from dtmcurse_foo);
fetch 1 from c1;
a | b
---+---
1 | 2
(1 row)
close c1;
end;
drop table if exists dtmcurse_foo;
drop table if exists dtmcurse_bar;
-- Test distribute transaction if 'COMMIT/END' is included in a multi-queries command.
\! psql postgres -Xc "begin;end; create table dtx_test1(c1 int); drop table dtx_test1;"
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'c1' as the Apache Cloudberry data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
DROP TABLE
-- Test two phase commit for extended query
\! ./twophase_pqexecparams dbname=regression
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'i' as the Apache Cloudberry data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
WARNING: the distributed transaction 'Commit Prepared' broadcast failed to one or more segments. Retrying ... try 1
DETAIL: gid=66802449, state=Retry Commit Prepared
NOTICE: Releasing segworker group to retry broadcast.
result: INSERT 0 2
--
-- Subtransactions with partition table DDLs.
--
BEGIN;
Create table subt_alter_part_tab_ao1 (
i int, x text, c char, v varchar, d date, n numeric,
t timestamp without time zone, tz time with time zone)
with (appendonly=true, orientation=column) distributed by (i)
partition by range (i)
(partition p1 start(1) end(5),
partition p2 start(5) end(8),
partition p3 start(8) end(10));
Savepoint sp1;
Alter table subt_alter_part_tab_ao1 add partition p4 start(10) end(14);
Alter table subt_alter_part_tab_ao1 add default partition def_part;
Insert into subt_alter_part_tab_ao1 values(
generate_series(1,15), 'create table with subtransactions', 's',
'subtransaction table', '12-11-2012', 3, '2012-10-09 10:23:54',
'2011-08-19 10:23:54+02');
Savepoint sp2; -- child of sp1
Select count(*) from subt_alter_part_tab_ao1;
count
-------
15
(1 row)
Alter table subt_alter_part_tab_ao1 drop partition p3;
Select count(*) from subt_alter_part_tab_ao1;
count
-------
13
(1 row)
select count(*) = 0 as passed from subt_alter_part_tab_ao1
where i >= 8 and i < 10;
passed
--------
t
(1 row)
Savepoint sp3; -- child of sp2
Alter table subt_alter_part_tab_ao1 drop default partition;
release savepoint sp3; -- commit sp3
Select count(*) from subt_alter_part_tab_ao1;
count
-------
11
(1 row)
select count(*) = 0 as passed from subt_alter_part_tab_ao1 where i > 13;
passed
--------
t
(1 row)
savepoint sp4; -- child of sp2
Create table exg_pt_ao1(i int, x text,c char,v varchar, d date, n numeric,
t timestamp without time zone, tz time with time zone) distributed by (i);
Insert into exg_pt_ao1 values (
7, 'to be exchanged', 's', 'partition table', '12-11-2012', 3,
'2012-10-09 10:23:54', '2011-08-19 10:23:54+02');
Alter table subt_alter_part_tab_ao1 exchange partition p2
with table exg_pt_ao1;
select count(*) = 1 as passed from subt_alter_part_tab_ao1
where i >= 5 and i < 8;
passed
--------
t
(1 row)
rollback to sp4;
select count(*) > 1 as passed from subt_alter_part_tab_ao1
where i >= 5 and i < 8;
passed
--------
t
(1 row)
Alter table subt_alter_part_tab_ao1 split partition p4 at (13) into
(partition splita,partition splitb);
select count(*) from subt_alter_part_tab_ao1;
count
-------
11
(1 row)
savepoint sp5; -- child of sp4
Alter table subt_alter_part_tab_ao1 drop partition splita;
Select count(*) from subt_alter_part_tab_ao1;
count
-------
8
(1 row)
rollback to sp5;
Select count(*) from subt_alter_part_tab_ao1;
count
-------
11
(1 row)
Alter table subt_alter_part_tab_ao1 drop partition splita;
rollback to sp2; -- should abort committed child sp3
COMMIT;
Select count(*) = 15 as passed from subt_alter_part_tab_ao1;
passed
--------
t
(1 row)
select count(*) > 0 as passed from subt_alter_part_tab_ao1 where i > 13;
passed
--------
t
(1 row)
-- DML should work after the subtransaction business.
Insert into subt_alter_part_tab_ao1 values(
generate_series(1,15), 'create table with subtransactions', 's',
'subtransaction table', '12-11-2012', 3, '2012-10-09 10:23:54',
'2011-08-19 10:23:54+02');
Select count(*) = 30 as passed from subt_alter_part_tab_ao1;
passed
--------
t
(1 row)
--
-- Subtransactions with DDL/DMLs on append-optimized tables.
--
BEGIN;
Create table subt_alter_table_ao1 (col0 int)
with (appendonly=true) distributed by (col0);
Create table subt_alter_table_co1 (col0 int)
with (appendonly=true, orientation=column) distributed by (col0);
Insert into subt_alter_table_ao1 values(generate_series(1,5));
Insert into subt_alter_table_co1 values(generate_series(1,5));
Savepoint sp1;
-- Add column, update, commit subtransaction.
Alter table subt_alter_table_ao1 add column col1 int default 10;
update subt_alter_table_ao1 set col1 = col0;
Alter table subt_alter_table_co1 add column col1 int default 10;
update subt_alter_table_co1 set col1 = col0;
release savepoint sp1;
-- Alter column type, update, rollback subtransaction.
Savepoint sp2;
Alter table subt_alter_table_ao1 drop column col1;
insert into subt_alter_table_ao1 values (6), (7);
select count(attnum) = 1 as passed from pg_attribute
where attrelid = 'subt_alter_table_ao1'::regclass
and attisdropped = true;
passed
--------
t
(1 row)
Alter table subt_alter_table_co1 alter column col1 type float;
update subt_alter_table_co1 set col1 = col0/10::float;
select count(*) = 5 as passed from subt_alter_table_co1 where col1 < 1;
passed
--------
t
(1 row)
rollback to sp2;
select count(attnum) = 0 as passed from pg_attribute
where attrelid = 'subt_alter_table_ao1'::regclass
and attisdropped = true;
passed
--------
t
(1 row)
select count(*) = 0 as passed from subt_alter_table_co1 where col1 < 1;
passed
--------
t
(1 row)
COMMIT;
select count(attnum) = 0 as passed from pg_attribute
where attrelid = 'subt_alter_table_ao1'::regclass
and attisdropped = true;
passed
--------
t
(1 row)
select count(*) = 0 as passed from subt_alter_table_co1 where col1 < 1;
passed
--------
t
(1 row)
--
-- Subtransactions with reindex and truncate.
--
BEGIN;
-- Enforce index usage for this test.
set enable_seqscan=false;
set enable_indexscan=true;
set enable_bitmapscan=true;
Create table subt_reindex_heap (i int, x text, n numeric, b box)
distributed by (i);
Create index bt_ri_heap on subt_reindex_heap (x);
Create index bm_ri_heap on subt_reindex_heap using bitmap (n);
Create index gist_ri_heap on subt_reindex_heap using gist (b);
Create Unique index unique_ri_heap on subt_reindex_heap (i);
Create table subt_reindex_ao (i int, x text, n numeric, b box)
with(appendonly=true) distributed by (i);
Create index bt_ri_ao on subt_reindex_ao (x);
Create index bm_ri_ao on subt_reindex_ao using bitmap (n);
Create index gist_ri_ao on subt_reindex_ao using gist (b);
Create table subt_reindex_co (i int, x text, n numeric, b box)
with(appendonly=true, orientation=column) distributed by (i);
Create index bt_ri_co on subt_reindex_co (x);
Create index bm_ri_co on subt_reindex_co using bitmap (n);
Create index gist_ri_co on subt_reindex_co using gist (b);
savepoint sp1;
Insert into subt_reindex_heap select i, 'heap '||i, 2,
('(0,'||i||', 1,'||i+1||')')::box from generate_series(1,5)i;
Insert into subt_reindex_ao select i, 'AO '||i, 2,
('(0,'||i||', 1,'||i+1||')')::box from generate_series(1,5)i;
Insert into subt_reindex_co select i, 'CO '||i, 2,
('(0,'||i||', 1,'||i+1||')')::box from generate_series(1,5)i;
savepoint sp2; -- child of sp1
Insert into subt_reindex_heap values
(6, 'heap 6', 3, '((0,0), (1,1))');
Insert into subt_reindex_ao values
(5, 'AO 5', 3, '((0,0), (1,1))');
Insert into subt_reindex_co values
(5, 'CO 5', 3, '((0,0), (1,1))');
update subt_reindex_heap set n = -i where n = 3;
update subt_reindex_ao set n = -i where n = 3;
update subt_reindex_co set n = -i where n = 3;
savepoint sp3; -- child of sp2;
REINDEX index bm_ri_heap;
REINDEX index bm_ri_ao;
REINDEX index bm_ri_co;
select count(*) = 1 as passed from subt_reindex_heap where n < 0;
passed
--------
t
(1 row)
select count(*) = 1 as passed from subt_reindex_ao where n < 0;
passed
--------
t
(1 row)
select count(*) = 1 as passed from subt_reindex_co where n < 0;
passed
--------
t
(1 row)
release savepoint sp3; -- commit sp3
savepoint sp4; -- child of sp2
REINDEX index unique_ri_heap;
REINDEX index bt_ri_ao;
REINDEX index bm_ri_ao;
REINDEX index gist_ri_ao;
REINDEX index bt_ri_co;
REINDEX index bm_ri_co;
REINDEX index gist_ri_co;
savepoint sp5; -- child of sp4
select count(*) = 1 as passed from subt_reindex_heap where x = 'heap 2';
passed
--------
t
(1 row)
select count(*) = 1 as passed from subt_reindex_ao where x = 'AO 3';
passed
--------
t
(1 row)
select count(*) = 1 as passed from subt_reindex_co where x = 'CO 4';
passed
--------
t
(1 row)
select 0/0;
ERROR: division by zero
rollback to sp4;
select count(*) = 1 as passed from subt_reindex_heap where i = 1;
passed
--------
t
(1 row)
select count(*) = 2 as passed from subt_reindex_ao where i = 5;
passed
--------
t
(1 row)
select count(*) = 2 as passed from subt_reindex_co where i = 5;
passed
--------
t
(1 row)
update subt_reindex_heap set x = 'heap sp4', b = '((1,1),(4,4))'
where i = 2;
update subt_reindex_ao set x = 'AO sp4', b = '((1,1),(4,4))'
where i = 2;
update subt_reindex_co set x = 'CO sp4', b = '((1,1),(4,4))'
where i = 2;
savepoint sp6; -- child of sp4
REINDEX index bt_ri_heap;
REINDEX index bm_ri_heap;
REINDEX index gist_ri_heap;
REINDEX index unique_ri_heap;
REINDEX index bt_ri_ao;
REINDEX index bt_ri_ao;
REINDEX index gist_ri_ao;
REINDEX index bt_ri_co;
REINDEX index bt_ri_co;
REINDEX index gist_ri_co;
release savepoint sp6;
select count(*) = 1 as passed from subt_reindex_heap
where b = '((1,1), (4,4))';
passed
--------
t
(1 row)
select count(*) = 1 as passed from subt_reindex_ao
where b = '((1,1), (4,4))';
passed
--------
t
(1 row)
select count(*) = 1 as passed from subt_reindex_co
where b = '((1,1), (4,4))';
passed
--------
t
(1 row)
rollback to sp2;
select count(*) = 5 as passed from subt_reindex_heap
where n = 2;
passed
--------
t
(1 row)
select count(*) = 5 as passed from subt_reindex_ao
where n = 2;
passed
--------
t
(1 row)
select count(*) = 5 as passed from subt_reindex_co
where n = 2;
passed
--------
t
(1 row)
select count(*) = 0 as passed from subt_reindex_ao
where x = 'AO sp4';
passed
--------
t
(1 row)
-- truncate cases
savepoint sp7; -- child of sp2
truncate subt_reindex_heap;
truncate subt_reindex_ao;
savepoint sp8; -- child of sp7
truncate subt_reindex_co;
select count(*) = 0 as passed from subt_reindex_heap where i < 7;
passed
--------
t
(1 row)
select count(*) = 0 as passed from subt_reindex_ao where i < 6;
passed
--------
t
(1 row)
select count(*) = 0 as passed from subt_reindex_co where i < 6;
passed
--------
t
(1 row)
rollback to sp8;
update subt_reindex_co set x = 'CO sp8', b = '((1,1),(8,8))'
where i = 2;
release savepoint sp7; -- commit sp7
-- Test rollback of truncate in a committed subtransaction.
rollback to sp2;
COMMIT;
select count(*) = 5 as passed from subt_reindex_heap;
passed
--------
t
(1 row)
select count(*) = 5 as passed from subt_reindex_ao;
passed
--------
t
(1 row)
select count(*) = 5 as passed from subt_reindex_co;
passed
--------
t
(1 row)
-- GPDB has a limitation on REINDEX of catalog tables: you cannot do it in
-- a transaction block. Check for that.
\c postgres
begin;
reindex table pg_class;
ERROR: REINDEX of a catalog table cannot run inside a transaction block
commit;
\c regression
--
-- Check that committing a subtransaction releases the lock on the
-- subtransaction's XID.
--
-- It's not too bad if it doesn't, because if anyone wants to wait for the
-- subtransaction and sees that it's been committed already, they will wait
-- for the top transaction XID instead. So even though the lock on the sub-XID
-- is released at RELEASE SAVEPOINT, logically it's held until the end of
-- the top transaction anyway. But releasing the lock early saves space in
-- the lock table. (We had a silly bug once upon a time in GPDB where we failed
-- to release the lock.)
--
BEGIN;
CREATE TEMPORARY TABLE foo (i integer);
DO $$
declare
i int;
begin
for i in 1..100 loop
begin
insert into foo values (i);
exception
when others then raise 'got error';
end;
end loop;
end;
$$;
SELECT CASE WHEN count(*) < 50 THEN 'not many XID locks'
ELSE 'lots of XID locks: ' || count(*) END
FROM pg_locks WHERE locktype='transactionid';
case
--------------------
not many XID locks
(1 row)
ROLLBACK;
-- Test that exported snapshots are cleared upon abort. In Cloudberry,
-- exported snapshots are cleared earlier than PostgreSQL during
-- abort.
begin;
select count(1) = 1 from pg_catalog.pg_export_snapshot();
?column?
----------
t
(1 row)
select pg_cancel_backend(pg_backend_pid());
ERROR: canceling statement due to user request
rollback;
-- Test a bug that a two-phase subtransaction is considered as one-phase.
set optimizer = off; -- orca optimizes value scan so the output is different between orca and postgres optimizer.
truncate distxact1_4;
set test_print_direct_dispatch_info = true;
begin;
savepoint sp1;
insert into distxact1_4 values (2),(1);
INFO: (slice 0) Dispatch command to ALL contents: 0 1 2
INFO: (slice 1) Dispatch command to SINGLE content
release sp1;
end;
INFO: Distributed transaction command 'Distributed Prepare' to ALL contents: 0 1 2
INFO: Distributed transaction command 'Distributed Commit Prepared' to ALL contents: 0 1 2
reset test_print_direct_dispatch_info;
reset optimizer;
select count(gp_segment_id) from distxact1_4 group by gp_segment_id; -- sanity check: tuples should be in > 1 segments
count
-------
1
1
(2 rows)
-- Tests for AND CHAIN
CREATE TABLE abc (a int);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Apache Cloudberry data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
-- set nondefault value so we have something to override below
SET default_transaction_read_only = on;
START TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ WRITE, DEFERRABLE;
SHOW transaction_isolation;
transaction_isolation
-----------------------
repeatable read
(1 row)
SHOW transaction_read_only;
transaction_read_only
-----------------------
off
(1 row)
SHOW transaction_deferrable;
transaction_deferrable
------------------------
on
(1 row)
INSERT INTO abc VALUES (1);
INSERT INTO abc VALUES (2);
COMMIT AND CHAIN; -- TBLOCK_END
SHOW transaction_isolation;
transaction_isolation
-----------------------
repeatable read
(1 row)
SHOW transaction_read_only;
transaction_read_only
-----------------------
off
(1 row)
SHOW transaction_deferrable;
transaction_deferrable
------------------------
on
(1 row)
INSERT INTO abc VALUES ('error');
ERROR: invalid input syntax for type integer: "error"
LINE 1: INSERT INTO abc VALUES ('error');
^
INSERT INTO abc VALUES (3); -- check it's really aborted
ERROR: current transaction is aborted, commands ignored until end of transaction block
COMMIT AND CHAIN; -- TBLOCK_ABORT_END
SHOW transaction_isolation;
transaction_isolation
-----------------------
repeatable read
(1 row)
SHOW transaction_read_only;
transaction_read_only
-----------------------
off
(1 row)
SHOW transaction_deferrable;
transaction_deferrable
------------------------
on
(1 row)
INSERT INTO abc VALUES (4);
COMMIT;
START TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ WRITE, DEFERRABLE;
SHOW transaction_isolation;
transaction_isolation
-----------------------
repeatable read
(1 row)
SHOW transaction_read_only;
transaction_read_only
-----------------------
off
(1 row)
SHOW transaction_deferrable;
transaction_deferrable
------------------------
on
(1 row)
SAVEPOINT x;
INSERT INTO abc VALUES ('error');
ERROR: invalid input syntax for type integer: "error"
LINE 1: INSERT INTO abc VALUES ('error');
^
COMMIT AND CHAIN; -- TBLOCK_ABORT_PENDING
SHOW transaction_isolation;
transaction_isolation
-----------------------
repeatable read
(1 row)
SHOW transaction_read_only;
transaction_read_only
-----------------------
off
(1 row)
SHOW transaction_deferrable;
transaction_deferrable
------------------------
on
(1 row)
INSERT INTO abc VALUES (5);
COMMIT;
START TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ WRITE, DEFERRABLE;
SHOW transaction_isolation;
transaction_isolation
-----------------------
repeatable read
(1 row)
SHOW transaction_read_only;
transaction_read_only
-----------------------
off
(1 row)
SHOW transaction_deferrable;
transaction_deferrable
------------------------
on
(1 row)
SAVEPOINT x;
COMMIT AND CHAIN; -- TBLOCK_SUBCOMMIT
SHOW transaction_isolation;
transaction_isolation
-----------------------
repeatable read
(1 row)
SHOW transaction_read_only;
transaction_read_only
-----------------------
off
(1 row)
SHOW transaction_deferrable;
transaction_deferrable
------------------------
on
(1 row)
COMMIT;
-- not allowed outside a transaction block
COMMIT AND CHAIN; -- error
ERROR: COMMIT AND CHAIN can only be used in transaction blocks
ROLLBACK AND CHAIN; -- error
ERROR: ROLLBACK AND CHAIN can only be used in transaction blocks
SELECT * FROM abc ORDER BY 1;
a
---
1
2
4
5
(4 rows)
RESET default_transaction_read_only;
DROP TABLE abc;
-- Explicit transaction block will send Distributed Commit, even if there is only SET command in it.
-- On the other hand, implicit transaction block involving only SET command will not send it.
create table tbl_dtx(a int, b int) distributed by (a);
insert into tbl_dtx values(1,1);
create or replace function dtx_set_bug()
returns void
language plpgsql
as $function$
begin
execute 'update tbl_dtx set b = 1 where a = 1;';
set optimizer=off;
end;
$function$;
set Test_print_direct_dispatch_info = true;
-- 1. explicit BEGIN/END
begin;
set optimizer=false;
end;
INFO: Distributed transaction command 'Distributed Commit (one-phase)' to ALL contents: 0 1 2
-- 2. implicit transaction block with just SET
set optimizer=false;
-- 3. still implicit transaction block, but with UPDATE that will send DTX protocol command to *some* QEs
-- due to direct dispatch. Planner needs to be used for direct dispatch here.
-- This is to verify that the QEs that are not involved in the UDPATE won't receive DTX protocol command
-- that they are not supposed to see.
select dtx_set_bug();
INFO: (slice 0) Dispatch command to SINGLE content
INFO: Distributed transaction command 'Distributed Commit (one-phase)' to SINGLE content
dtx_set_bug
-------------
(1 row)
reset Test_print_direct_dispatch_info;