diff --git a/src/test/isolation/expected/gtt-sequence.out b/src/test/isolation/expected/gtt-sequence.out new file mode 100644 index 00000000000..31db2ebd423 --- /dev/null +++ b/src/test/isolation/expected/gtt-sequence.out @@ -0,0 +1,48 @@ +unused step name: s1_seq_restart +Parsed test spec with 2 sessions + +starting permutation: s1_seq_next s2_seq_next s1_seq_next +step s1_seq_next: select nextval('gtt_with_seq_c2_seq'); +nextval +------- + 1 +(1 row) + +step s2_seq_next: select nextval('gtt_with_seq_c2_seq'); +nextval +------- + 1 +(1 row) + +step s1_seq_next: select nextval('gtt_with_seq_c2_seq'); +nextval +------- + 2 +(1 row) + + +starting permutation: s1_select s2_select s1_insert s2_insert s1_select s2_select +step s1_select: select * from gtt_with_seq order by c1,c2; +c1|c2 +--+-- +(0 rows) + +step s2_select: select * from gtt_with_seq order by c1,c2; +c1|c2 +--+-- +(0 rows) + +step s1_insert: insert into gtt_with_seq values(1); +step s2_insert: insert into gtt_with_seq values(10); +step s1_select: select * from gtt_with_seq order by c1,c2; +c1|c2 +--+-- + 1| 3 +(1 row) + +step s2_select: select * from gtt_with_seq order by c1,c2; +c1|c2 +--+-- +10| 1 +(1 row) + diff --git a/src/test/isolation/expected/gtt-table.out b/src/test/isolation/expected/gtt-table.out new file mode 100644 index 00000000000..5825773aa12 --- /dev/null +++ b/src/test/isolation/expected/gtt-table.out @@ -0,0 +1,675 @@ +Parsed test spec with 3 sessions + +starting permutation: s1_update_d +step s1_update_d: update gtt_on_commit_delete_row set b = 'update' + +starting permutation: s1_select_d s1_insert_d s1_select_d +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+- +(0 rows) + +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+- +(0 rows) + + +starting permutation: s1_select_d s1_begin s1_insert_d s1_select_d s1_commit s1_select_d +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+- +(0 rows) + +step s1_begin: begin +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+----- +1|test1 +(1 row) + +step s1_commit: commit +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+- +(0 rows) + + +starting permutation: s1_select_d s1_begin s1_insert_d s1_select_d s1_rollback s1_select_d +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+- +(0 rows) + +step s1_begin: begin +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+----- +1|test1 +(1 row) + +step s1_rollback: rollback +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+- +(0 rows) + + +starting permutation: s1_select_d s1_insert_d s1_select_d s1_truncate_d s1_select_d +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+- +(0 rows) + +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+- +(0 rows) + +step s1_truncate_d: truncate gtt_on_commit_delete_row +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+- +(0 rows) + + +starting permutation: s1_select_d s1_insert_d s1_begin s1_insert_d s1_select_d s1_truncate_d s1_select_d s1_insert_d s1_select_d s1_commit s1_select_d +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+- +(0 rows) + +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_begin: begin +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+----- +2|test1 +(1 row) + +step s1_truncate_d: truncate gtt_on_commit_delete_row +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+- +(0 rows) + +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+----- +3|test1 +(1 row) + +step s1_commit: commit +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+- +(0 rows) + + +starting permutation: s1_select_d s1_insert_d s1_begin s1_insert_d s1_select_d s1_truncate_d s1_select_d s1_insert_d s1_select_d s1_rollback s1_select_d +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+- +(0 rows) + +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_begin: begin +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+----- +2|test1 +(1 row) + +step s1_truncate_d: truncate gtt_on_commit_delete_row +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+- +(0 rows) + +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+----- +3|test1 +(1 row) + +step s1_rollback: rollback +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+- +(0 rows) + + +starting permutation: s1_insert_d s1_select_d s1_begin s1_insert_d s1_select_d s1_save_1 s1_truncate_d s1_insert_d s1_select_d s1_save_2 s1_truncate_d s1_insert_d s1_select_d s1_save_3 s1_rollback_to_save_2 s1_select_d s1_insert_d s1_select_d s1_commit s1_select_d +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+- +(0 rows) + +step s1_begin: begin +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+----- +2|test1 +(1 row) + +step s1_save_1: SAVEPOINT save1 +step s1_truncate_d: truncate gtt_on_commit_delete_row +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+----- +3|test1 +(1 row) + +step s1_save_2: SAVEPOINT save2 +step s1_truncate_d: truncate gtt_on_commit_delete_row +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+----- +4|test1 +(1 row) + +step s1_save_3: SAVEPOINT save3 +step s1_rollback_to_save_2: rollback to savepoint save2 +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+----- +3|test1 +(1 row) + +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+----- +3|test1 +5|test1 +(2 rows) + +step s1_commit: commit +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+- +(0 rows) + + +starting permutation: s1_insert_d s1_select_d s1_begin s1_insert_d s1_select_d s1_save_1 s1_truncate_d s1_insert_d s1_select_d s1_save_2 s1_truncate_d s1_insert_d s1_select_d s1_save_3 s1_rollback_to_save_2 s1_select_d s1_insert_d s1_select_d s1_rollback s1_select_d +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+- +(0 rows) + +step s1_begin: begin +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+----- +2|test1 +(1 row) + +step s1_save_1: SAVEPOINT save1 +step s1_truncate_d: truncate gtt_on_commit_delete_row +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+----- +3|test1 +(1 row) + +step s1_save_2: SAVEPOINT save2 +step s1_truncate_d: truncate gtt_on_commit_delete_row +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+----- +4|test1 +(1 row) + +step s1_save_3: SAVEPOINT save3 +step s1_rollback_to_save_2: rollback to savepoint save2 +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+----- +3|test1 +(1 row) + +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+----- +3|test1 +5|test1 +(2 rows) + +step s1_rollback: rollback +step s1_select_d: select a,b from gtt_on_commit_delete_row order by a,b +a|b +-+- +(0 rows) + + +starting permutation: s2_update_p +step s2_update_p: update gtt_on_commit_preserve_row set b = 'update' + +starting permutation: s2_select_p s2_insert_p s2_select_p +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+- +(0 rows) + +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test10 +(1 row) + + +starting permutation: s2_select_p s2_begin s2_insert_p s2_select_p s2_commit s2_select_p +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+- +(0 rows) + +step s2_begin: begin +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test10 +(1 row) + +step s2_commit: commit +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test10 +(1 row) + + +starting permutation: s2_select_p s2_begin s2_insert_p s2_select_p s2_rollback s2_select_p +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+- +(0 rows) + +step s2_begin: begin +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test10 +(1 row) + +step s2_rollback: rollback +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+- +(0 rows) + + +starting permutation: s2_select_p s2_insert_p s2_select_p s2_truncate_p s2_select_p +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+- +(0 rows) + +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test10 +(1 row) + +step s2_truncate_p: truncate gtt_on_commit_preserve_row +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+- +(0 rows) + + +starting permutation: s2_select_p s2_insert_p s2_begin s2_insert_p s2_select_p s2_truncate_p s2_select_p s2_insert_p s2_select_p s2_commit s2_select_p +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+- +(0 rows) + +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s2_begin: begin +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test10 +2|test10 +(2 rows) + +step s2_truncate_p: truncate gtt_on_commit_preserve_row +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+- +(0 rows) + +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +3|test10 +(1 row) + +step s2_commit: commit +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +3|test10 +(1 row) + + +starting permutation: s2_select_p s2_insert_p s2_begin s2_insert_p s2_select_p s2_truncate_p s2_select_p s2_insert_p s2_select_p s2_rollback s2_select_p +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+- +(0 rows) + +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s2_begin: begin +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test10 +2|test10 +(2 rows) + +step s2_truncate_p: truncate gtt_on_commit_preserve_row +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+- +(0 rows) + +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +3|test10 +(1 row) + +step s2_rollback: rollback +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test10 +(1 row) + + +starting permutation: s2_insert_p s2_select_p s2_begin s2_insert_p s2_select_p s2_save_1 s2_truncate_p s2_insert_p s2_select_p s2_save_2 s2_truncate_p s2_insert_p s2_select_p s2_save_3 s2_rollback_to_save_2 s2_select_p s2_insert_p s2_select_p s2_commit s2_select_p +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test10 +(1 row) + +step s2_begin: begin +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test10 +2|test10 +(2 rows) + +step s2_save_1: SAVEPOINT save1 +step s2_truncate_p: truncate gtt_on_commit_preserve_row +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +3|test10 +(1 row) + +step s2_save_2: SAVEPOINT save2 +step s2_truncate_p: truncate gtt_on_commit_preserve_row +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +4|test10 +(1 row) + +step s2_save_3: SAVEPOINT save3 +step s2_rollback_to_save_2: rollback to savepoint save2 +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +3|test10 +(1 row) + +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +3|test10 +5|test10 +(2 rows) + +step s2_commit: commit +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +3|test10 +5|test10 +(2 rows) + + +starting permutation: s2_insert_p s2_select_p s2_begin s2_insert_p s2_select_p s2_save_1 s2_truncate_p s2_insert_p s2_select_p s2_save_2 s2_truncate_p s2_insert_p s2_select_p s2_save_3 s2_rollback_to_save_2 s2_select_p s2_insert_p s2_select_p s2_rollback s2_select_p +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test10 +(1 row) + +step s2_begin: begin +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test10 +2|test10 +(2 rows) + +step s2_save_1: SAVEPOINT save1 +step s2_truncate_p: truncate gtt_on_commit_preserve_row +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +3|test10 +(1 row) + +step s2_save_2: SAVEPOINT save2 +step s2_truncate_p: truncate gtt_on_commit_preserve_row +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +4|test10 +(1 row) + +step s2_save_3: SAVEPOINT save3 +step s2_rollback_to_save_2: rollback to savepoint save2 +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +3|test10 +(1 row) + +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +3|test10 +5|test10 +(2 rows) + +step s2_rollback: rollback +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test10 +(1 row) + + +starting permutation: s1_insert_p s2_insert_p s1_select_p s2_select_p +step s1_insert_p: insert into gtt_on_commit_preserve_row (b) values('test20') +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s1_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test20 +(1 row) + +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test10 +(1 row) + + +starting permutation: s1_begin s2_begin s1_insert_p s2_insert_p s1_truncate_p s2_truncate_p s1_commit s2_commit s1_select_p s2_select_p +step s1_begin: begin +step s2_begin: begin +step s1_insert_p: insert into gtt_on_commit_preserve_row (b) values('test20') +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s1_truncate_p: truncate gtt_on_commit_preserve_row +step s2_truncate_p: truncate gtt_on_commit_preserve_row +step s1_commit: commit +step s2_commit: commit +step s1_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+- +(0 rows) + +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+- +(0 rows) + + +starting permutation: s1_begin s1_insert_d s2_insert_d s1_truncate_d s2_insert_d s1_commit +step s1_begin: begin +step s1_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s2_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_truncate_d: truncate gtt_on_commit_delete_row +step s2_insert_d: insert into gtt_on_commit_delete_row (b) values('test1') +step s1_commit: commit + +starting permutation: s1_begin s2_begin s1_insert_p s2_insert_p s1_reindex_p s2_reindex_p s1_commit s2_commit s1_select_p s2_select_p +step s1_begin: begin +step s2_begin: begin +step s1_insert_p: insert into gtt_on_commit_preserve_row (b) values('test20') +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s1_reindex_p: reindex table gtt_on_commit_preserve_row +step s2_reindex_p: reindex table gtt_on_commit_preserve_row +step s1_commit: commit +step s2_commit: commit +step s1_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test20 +(1 row) + +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test10 +(1 row) + + +starting permutation: s1_begin s2_begin s1_insert_p s2_insert_p s1_reindex_i_p s2_reindex_i_p s1_commit s2_commit s1_select_p s2_select_p +step s1_begin: begin +step s2_begin: begin +step s1_insert_p: insert into gtt_on_commit_preserve_row (b) values('test20') +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s1_reindex_i_p: reindex index gtt_on_commit_preserve_row_pkey +step s2_reindex_i_p: reindex index gtt_on_commit_preserve_row_pkey +step s1_commit: commit +step s2_commit: commit +step s1_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test20 +(1 row) + +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test10 +(1 row) + + +starting permutation: s2_insert_c s3_create_c s3_insert_c s1_insert_c s1_analyze_c s2_analyze_c s3_analyze_c s1_select_c s2_select_c s3_select_c +step s2_insert_c: insert into gtt_test_createindex(a,b) values(generate_series(1,100000),'test create index') +step s3_create_c: create unique index idx_temp_table_a on gtt_test_createindex(a) +step s3_insert_c: insert into gtt_test_createindex(a,b) values(generate_series(1,100000),'test create index') +step s1_insert_c: insert into gtt_test_createindex(a,b) values(generate_series(1,100000),'test create index') +step s1_analyze_c: analyze gtt_test_createindex +step s2_analyze_c: analyze gtt_test_createindex +step s3_analyze_c: analyze gtt_test_createindex +step s1_select_c: explain (costs off) select * from gtt_test_createindex where a = 1 +QUERY PLAN +--------------------------------------------------------- +Index Scan using idx_temp_table_a on gtt_test_createindex + Index Cond: (a = 1) +(2 rows) + +step s2_select_c: explain (costs off) select * from gtt_test_createindex where a = 1 +QUERY PLAN +-------------------------------- +Seq Scan on gtt_test_createindex + Filter: (a = 1) +(2 rows) + +step s3_select_c: explain (costs off) select * from gtt_test_createindex where a = 1 +QUERY PLAN +--------------------------------------------------------- +Index Scan using idx_temp_table_a on gtt_test_createindex + Index Cond: (a = 1) +(2 rows) + + +starting permutation: s1_begin s2_begin s1_lock_p s2_lock_p s1_truncate_p s2_truncate_p s1_insert_p s2_insert_p s1_commit s2_commit s1_select_p s2_select_p +step s1_begin: begin +step s2_begin: begin +step s1_lock_p: LOCK TABLE gtt_on_commit_preserve_row in ACCESS EXCLUSIVE MODE +step s2_lock_p: LOCK TABLE gtt_on_commit_preserve_row in ACCESS EXCLUSIVE MODE +step s1_truncate_p: truncate gtt_on_commit_preserve_row +step s2_truncate_p: truncate gtt_on_commit_preserve_row +step s1_insert_p: insert into gtt_on_commit_preserve_row (b) values('test20') +step s2_insert_p: insert into gtt_on_commit_preserve_row (b) values('test10') +step s1_commit: commit +step s2_commit: commit +step s1_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test20 +(1 row) + +step s2_select_p: select a,b from gtt_on_commit_preserve_row order by a,b +a|b +-+------ +1|test10 +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 0dae483e827..77d4cff5fcb 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -98,3 +98,5 @@ test: plpgsql-toast test: truncate-conflict test: serializable-parallel test: serializable-parallel-2 +test: gtt-sequence +test: gtt-table diff --git a/src/test/isolation/isolationtester.c b/src/test/isolation/isolationtester.c index 12179f25146..7cf0b20e636 100644 --- a/src/test/isolation/isolationtester.c +++ b/src/test/isolation/isolationtester.c @@ -80,9 +80,30 @@ disconnect_atexit(void) { int i; - for (i = 0; i < nconns; i++) + for (i = 1; i < nconns; i++) if (conns[i].conn) PQfinish(conns[i].conn); + + if (parseresult.destroy) + { + PGresult *res; + + res = PQexec(conns[0].conn, parseresult.destroy); + if (PQresultStatus(res) == PGRES_TUPLES_OK) + { + printResultSet(res); + } + else if (PQresultStatus(res) != PGRES_COMMAND_OK) + { + fprintf(stderr, "destroy failed: %s", + PQerrorMessage(conns[0].conn)); + /* don't exit on teardown failure */ + } + PQclear(res); + } + + if (conns[0].conn) + PQfinish(conns[0].conn); } int @@ -238,6 +259,24 @@ main(int argc, char **argv) PQclear(res); termPQExpBuffer(&wait_query); + if (parseresult.initialize) + { + PGresult *res; + + res = PQexec(conns[0].conn, parseresult.initialize); + if (PQresultStatus(res) == PGRES_TUPLES_OK) + { + printResultSet(res); + } + else if (PQresultStatus(res) != PGRES_COMMAND_OK) + { + fprintf(stderr, "initialize failed: %s", + PQerrorMessage(conns[0].conn)); + /* don't exit on teardown failure */ + } + PQclear(res); + } + /* * Run the permutations specified in the spec, or all if none were * explicitly specified. diff --git a/src/test/isolation/isolationtester.h b/src/test/isolation/isolationtester.h index e00bc6b816b..e15d3c6d3ea 100644 --- a/src/test/isolation/isolationtester.h +++ b/src/test/isolation/isolationtester.h @@ -81,6 +81,8 @@ typedef struct int nsessions; Permutation **permutations; int npermutations; + char *initialize; + char *destroy; } TestSpec; extern TestSpec parseresult; diff --git a/src/test/isolation/specparse.y b/src/test/isolation/specparse.y index eb368184b8b..fb0107eccf2 100644 --- a/src/test/isolation/specparse.y +++ b/src/test/isolation/specparse.y @@ -39,7 +39,7 @@ TestSpec parseresult; /* result of parsing is left here */ } %type setup_list -%type opt_setup opt_teardown +%type opt_setup opt_teardown opt_initialize opt_destroy %type setup %type step_list session_list permutation_list opt_permutation_list %type permutation_step_list blocker_list @@ -51,23 +51,27 @@ TestSpec parseresult; /* result of parsing is left here */ %token sqlblock identifier %token INTEGER -%token NOTICES PERMUTATION SESSION SETUP STEP TEARDOWN TEST +%token NOTICES PERMUTATION SESSION SETUP STEP TEARDOWN TEST INITIALIZE DESTROY %% TestSpec: + opt_initialize setup_list opt_teardown + opt_destroy session_list opt_permutation_list { - parseresult.setupsqls = (char **) $1.elements; - parseresult.nsetupsqls = $1.nelements; - parseresult.teardownsql = $2; - parseresult.sessions = (Session **) $3.elements; - parseresult.nsessions = $3.nelements; - parseresult.permutations = (Permutation **) $4.elements; - parseresult.npermutations = $4.nelements; + parseresult.setupsqls = (char **) $2.elements; + parseresult.nsetupsqls = $2.nelements; + parseresult.teardownsql = $3; + parseresult.sessions = (Session **) $5.elements; + parseresult.nsessions = $5.nelements; + parseresult.permutations = (Permutation **) $6.elements; + parseresult.npermutations = $6.nelements; + parseresult.initialize = $1; + parseresult.destroy = $4; } ; @@ -100,6 +104,16 @@ opt_teardown: | TEARDOWN sqlblock { $$ = $2; } ; +opt_initialize: + /* EMPTY */ { $$ = NULL; } + | INITIALIZE sqlblock { $$ = $2; } + ; + +opt_destroy: + /* EMPTY */ { $$ = NULL; } + | DESTROY sqlblock { $$ = $2; } + ; + session_list: session_list session { diff --git a/src/test/isolation/specs/gtt-sequence.spec b/src/test/isolation/specs/gtt-sequence.spec new file mode 100644 index 00000000000..88eece45e29 --- /dev/null +++ b/src/test/isolation/specs/gtt-sequence.spec @@ -0,0 +1,39 @@ +# Tests for global temporary relations + +initialize +{ + CREATE GLOBAL TEMPORARY TABLE if not exists gtt_with_seq(c1 bigint, c2 bigserial) on commit PRESERVE rows; +} + +destroy +{ + /* wait other backend exit */ + select pg_sleep(1); + + DROP TABLE gtt_with_seq; +} + +# Session 1 +session "s1" +step "s1_seq_next" { select nextval('gtt_with_seq_c2_seq'); } +step "s1_seq_restart" { alter sequence gtt_with_seq_c2_seq RESTART; } +step "s1_insert" { insert into gtt_with_seq values(1); } +step "s1_select" { select * from gtt_with_seq order by c1,c2; } +teardown +{ + TRUNCATE gtt_with_seq; +} + +# Session 2 +session "s2" +step "s2_seq_next" { select nextval('gtt_with_seq_c2_seq'); } +step "s2_insert" { insert into gtt_with_seq values(10); } +step "s2_select" { select * from gtt_with_seq order by c1,c2; } +teardown +{ + TRUNCATE gtt_with_seq RESTART IDENTITY; +} + +permutation "s1_seq_next" "s2_seq_next" "s1_seq_next" +permutation "s1_select" "s2_select" "s1_insert" "s2_insert" "s1_select" "s2_select" + diff --git a/src/test/isolation/specs/gtt-table.spec b/src/test/isolation/specs/gtt-table.spec new file mode 100644 index 00000000000..e0396b21ef0 --- /dev/null +++ b/src/test/isolation/specs/gtt-table.spec @@ -0,0 +1,135 @@ +# Tests for global temporary relations + +initialize +{ + create global temp table gtt_on_commit_delete_row(a bigserial primary key, b text) on commit delete rows; + create global temp table gtt_on_commit_preserve_row(a bigserial primary key, b text) on commit preserve rows; + create global temp table gtt_test_createindex(a int, b char(1000)) on commit preserve rows; +} + +destroy +{ + /* wait other backend exit */ + select pg_sleep(1); + + DROP TABLE gtt_on_commit_delete_row; + DROP TABLE gtt_on_commit_preserve_row; + DROP TABLE gtt_test_createindex; +} + +# Session 1 +session "s1" +step "s1_begin" {begin} +step "s1_commit" {commit} +step "s1_rollback" {rollback} +step "s1_insert_d" {insert into gtt_on_commit_delete_row (b) values('test1')} +step "s1_select_d" {select a,b from gtt_on_commit_delete_row order by a,b} +step "s1_insert_p" {insert into gtt_on_commit_preserve_row (b) values('test20')} +step "s1_select_p" {select a,b from gtt_on_commit_preserve_row order by a,b} +step "s1_truncate_d" {truncate gtt_on_commit_delete_row} +step "s1_truncate_p" {truncate gtt_on_commit_preserve_row} +step "s1_lock_p" {LOCK TABLE gtt_on_commit_preserve_row in ACCESS EXCLUSIVE MODE} +step "s1_update_d" {update gtt_on_commit_delete_row set b = 'update'} +step "s1_save_1" {SAVEPOINT save1} +step "s1_save_2" {SAVEPOINT save2} +step "s1_save_3" {SAVEPOINT save3} +step "s1_rollback_to_save_2" {rollback to savepoint save2} +step "s1_reindex_p" {reindex table gtt_on_commit_preserve_row} +step "s1_reindex_i_p" {reindex index gtt_on_commit_preserve_row_pkey} +step "s1_insert_c" {insert into gtt_test_createindex(a,b) values(generate_series(1,100000),'test create index')} +step "s1_select_c" {explain (costs off) select * from gtt_test_createindex where a = 1} +step "s1_analyze_c" {analyze gtt_test_createindex} +teardown +{ + TRUNCATE gtt_on_commit_delete_row RESTART IDENTITY; + TRUNCATE gtt_on_commit_preserve_row RESTART IDENTITY; +} + +# Session 2 +session "s2" +step "s2_begin" {begin} +step "s2_commit" {commit} +step "s2_rollback" {rollback} +step "s2_insert_p" {insert into gtt_on_commit_preserve_row (b) values('test10')} +step "s2_select_p" {select a,b from gtt_on_commit_preserve_row order by a,b} +step "s2_insert_d" {insert into gtt_on_commit_delete_row (b) values('test1')} +step "s2_truncate_p" {truncate gtt_on_commit_preserve_row} +step "s2_update_p" {update gtt_on_commit_preserve_row set b = 'update'} +step "s2_lock_p" {LOCK TABLE gtt_on_commit_preserve_row in ACCESS EXCLUSIVE MODE} +step "s2_save_1" {SAVEPOINT save1} +step "s2_save_2" {SAVEPOINT save2} +step "s2_save_3" {SAVEPOINT save3} +step "s2_rollback_to_save_2" {rollback to savepoint save2} +step "s2_reindex_p" {reindex table gtt_on_commit_preserve_row} +step "s2_reindex_i_p" {reindex index gtt_on_commit_preserve_row_pkey} +step "s2_insert_c" {insert into gtt_test_createindex(a,b) values(generate_series(1,100000),'test create index')} +step "s2_select_c" {explain (costs off) select * from gtt_test_createindex where a = 1} +step "s2_analyze_c" {analyze gtt_test_createindex} +teardown +{ + TRUNCATE gtt_on_commit_delete_row RESTART IDENTITY; + TRUNCATE gtt_on_commit_preserve_row RESTART IDENTITY; +} + +session "s3" +step "s3_create_c" {create unique index idx_temp_table_a on gtt_test_createindex(a)} +step "s3_insert_c" {insert into gtt_test_createindex(a,b) values(generate_series(1,100000),'test create index')} +step "s3_select_c" {explain (costs off) select * from gtt_test_createindex where a = 1} +step "s3_analyze_c" {analyze gtt_test_createindex} + + +# +# test on commit delete temp table +# + +# test update empty temp table +permutation "s1_update_d" +# test insert into temp table +permutation "s1_select_d" "s1_insert_d" "s1_select_d" +# test temp table in transaction(commit) +permutation "s1_select_d" "s1_begin" "s1_insert_d" "s1_select_d" "s1_commit" "s1_select_d" +# test temp table in transaction(rollback) +permutation "s1_select_d" "s1_begin" "s1_insert_d" "s1_select_d" "s1_rollback" "s1_select_d" +# test truncate +permutation "s1_select_d" "s1_insert_d" "s1_select_d" "s1_truncate_d" "s1_select_d" +# test truncate in transaction block +permutation "s1_select_d" "s1_insert_d" "s1_begin" "s1_insert_d" "s1_select_d" "s1_truncate_d" "s1_select_d" "s1_insert_d" "s1_select_d" "s1_commit" "s1_select_d" +permutation "s1_select_d" "s1_insert_d" "s1_begin" "s1_insert_d" "s1_select_d" "s1_truncate_d" "s1_select_d" "s1_insert_d" "s1_select_d" "s1_rollback" "s1_select_d" +# test temp table with subtransaction or savepoint +permutation "s1_insert_d" "s1_select_d" "s1_begin" "s1_insert_d" "s1_select_d" "s1_save_1" "s1_truncate_d" "s1_insert_d" "s1_select_d" "s1_save_2" "s1_truncate_d" "s1_insert_d" "s1_select_d" "s1_save_3" "s1_rollback_to_save_2" "s1_select_d" "s1_insert_d" "s1_select_d" "s1_commit" "s1_select_d" +permutation "s1_insert_d" "s1_select_d" "s1_begin" "s1_insert_d" "s1_select_d" "s1_save_1" "s1_truncate_d" "s1_insert_d" "s1_select_d" "s1_save_2" "s1_truncate_d" "s1_insert_d" "s1_select_d" "s1_save_3" "s1_rollback_to_save_2" "s1_select_d" "s1_insert_d" "s1_select_d" "s1_rollback" "s1_select_d" + +# +# test on commit preserve table +# + +# same as test on commit delete temp table +permutation "s2_update_p" +permutation "s2_select_p" "s2_insert_p" "s2_select_p" +permutation "s2_select_p" "s2_begin" "s2_insert_p" "s2_select_p" "s2_commit" "s2_select_p" +permutation "s2_select_p" "s2_begin" "s2_insert_p" "s2_select_p" "s2_rollback" "s2_select_p" +permutation "s2_select_p" "s2_insert_p" "s2_select_p" "s2_truncate_p" "s2_select_p" +permutation "s2_select_p" "s2_insert_p" "s2_begin" "s2_insert_p" "s2_select_p" "s2_truncate_p" "s2_select_p" "s2_insert_p" "s2_select_p" "s2_commit" "s2_select_p" +permutation "s2_select_p" "s2_insert_p" "s2_begin" "s2_insert_p" "s2_select_p" "s2_truncate_p" "s2_select_p" "s2_insert_p" "s2_select_p" "s2_rollback" "s2_select_p" +permutation "s2_insert_p" "s2_select_p" "s2_begin" "s2_insert_p" "s2_select_p" "s2_save_1" "s2_truncate_p" "s2_insert_p" "s2_select_p" "s2_save_2" "s2_truncate_p" "s2_insert_p" "s2_select_p" "s2_save_3" "s2_rollback_to_save_2" "s2_select_p" "s2_insert_p" "s2_select_p" "s2_commit" "s2_select_p" +permutation "s2_insert_p" "s2_select_p" "s2_begin" "s2_insert_p" "s2_select_p" "s2_save_1" "s2_truncate_p" "s2_insert_p" "s2_select_p" "s2_save_2" "s2_truncate_p" "s2_insert_p" "s2_select_p" "s2_save_3" "s2_rollback_to_save_2" "s2_select_p" "s2_insert_p" "s2_select_p" "s2_rollback" "s2_select_p" + +# +# test concurrent operation on temp table +# + +# test concurrent read +permutation "s1_insert_p" "s2_insert_p" "s1_select_p" "s2_select_p" +# test concurrent truncate +permutation "s1_begin" "s2_begin" "s1_insert_p" "s2_insert_p" "s1_truncate_p" "s2_truncate_p" "s1_commit" "s2_commit" "s1_select_p" "s2_select_p" +permutation "s1_begin" "s1_insert_d" "s2_insert_d" "s1_truncate_d" "s2_insert_d" "s1_commit" +# test concurrent reindex table +permutation "s1_begin" "s2_begin" "s1_insert_p" "s2_insert_p" "s1_reindex_p" "s2_reindex_p" "s1_commit" "s2_commit" "s1_select_p" "s2_select_p" +# test concurrent reindex index +permutation "s1_begin" "s2_begin" "s1_insert_p" "s2_insert_p" "s1_reindex_i_p" "s2_reindex_i_p" "s1_commit" "s2_commit" "s1_select_p" "s2_select_p" + +# test create index +permutation "s2_insert_c" "s3_create_c" "s3_insert_c" "s1_insert_c" "s1_analyze_c" "s2_analyze_c" "s3_analyze_c" "s1_select_c" "s2_select_c" "s3_select_c" + +# test lock gtt +permutation "s1_begin" "s2_begin" "s1_lock_p" "s2_lock_p" "s1_truncate_p" "s2_truncate_p" "s1_insert_p" "s2_insert_p" "s1_commit" "s2_commit" "s1_select_p" "s2_select_p" diff --git a/src/test/isolation/specscanner.l b/src/test/isolation/specscanner.l index aa6e89268ef..f782b9b8fcc 100644 --- a/src/test/isolation/specscanner.l +++ b/src/test/isolation/specscanner.l @@ -67,6 +67,8 @@ session { return SESSION; } setup { return SETUP; } step { return STEP; } teardown { return TEARDOWN; } +initialize { return INITIALIZE; } +destroy { return DESTROY; } /* Whitespace and comments */ [\n] { yyline++; } diff --git a/src/test/regress/expected/global_temporary_table.out b/src/test/regress/expected/global_temporary_table.out new file mode 100644 index 00000000000..5b8203f28f5 --- /dev/null +++ b/src/test/regress/expected/global_temporary_table.out @@ -0,0 +1,577 @@ +-- +-- GLobal emparary table test case +-- +CREATE SCHEMA IF NOT EXISTS global_temporary_table; +set search_path=global_temporary_table,sys; +-- +-- test create global temp table basic syntax +-- +create global temp table gtt_on_commit_default(a int primary key, b text); +create global temp table gtt_on_commit_delete(a int primary key, b text) on commit delete rows; +create global temp table gtt_on_commit_delete2(n int) with (on_commit_delete_rows='true'); +create global temp table gtt_on_commit_preserve(a int primary key, b text) on commit PRESERVE rows; +create global temp table gtt_test_rename(a int primary key, b text); +create global temp table gtt_test_createindex(c0 tsvector,c1 varchar(100), c2 int); +create global temp table gtt_test_alter(b text) with(on_commit_delete_rows=true); +-- +-- test DML on global temp table +-- +-- update empty temp table +update gtt_on_commit_delete set b ='test'; +begin; +insert into gtt_on_commit_delete values (1); +update gtt_on_commit_delete set b ='test'; +-- should 1 row +select * from gtt_on_commit_delete; + a | b +---+------ + 1 | test +(1 row) + +commit; +-- data delete after transaction commit +-- should 0 row +select * from gtt_on_commit_delete; + a | b +---+--- +(0 rows) + +-- update empty temp table +update gtt_on_commit_preserve set b ='test'; +insert into gtt_on_commit_preserve values (2); +begin; +insert into gtt_on_commit_preserve values (3); +update gtt_on_commit_preserve set b ='test'; +-- should 2 row +select * from gtt_on_commit_preserve order by a; + a | b +---+------ + 2 | test + 3 | test +(2 rows) + +delete from gtt_on_commit_preserve where a=2; +commit; +-- should 1 row +select * from gtt_on_commit_preserve order by a; + a | b +---+------ + 3 | test +(1 row) + +begin; +insert into gtt_on_commit_preserve values (4); +-- temp table support truncate; +truncate gtt_on_commit_preserve; +select * from gtt_on_commit_preserve order by a; + a | b +---+--- +(0 rows) + +rollback; +-- should 1 row +select * from gtt_on_commit_preserve order by a; + a | b +---+------ + 3 | test +(1 row) + +-- +-- test unsupported global temp partition table +-- +-- should fail +CREATE global temp TABLE global_temp_partition_01 ( +id bigserial NOT NULL, +cre_time timestamp without time zone, +note varchar(30) +) PARTITION BY RANGE (cre_time) +on commit delete rows; +ERROR: global temporary relation can only be a regular table or sequence +CREATE TABLE regular_partition_01_2019 ( +id bigserial NOT NULL, +cre_time timestamp without time zone, +note varchar(30) +); +CREATE TABLE regular_partition01 ( +id bigserial NOT NULL, +cre_time timestamp without time zone, +note varchar(30) +) PARTITION BY RANGE (cre_time); +-- should fail +CREATE global temp TABLE temp_partition01_2018 +PARTITION OF regular_partition01 +FOR VALUES FROM ('2018-01-01 00:00:00') TO ('2019-01-01 00:00:00'); +ERROR: cannot create global temporary inherit table or global temporary partitioned table +CREATE global temp TABLE global_temp_partition_01_2021 ( +id bigserial NOT NULL, +cre_time timestamp without time zone, +note varchar(30) +)on commit delete rows; +-- should fail +ALTER TABLE regular_partition01 ATTACH PARTITION global_temp_partition_01_2021 FOR VALUES FROM ('2021-01-01 00:00:00') TO ('2022-01-01 00:00:00'); +ERROR: cannot attach a global temporary relation as partition of permanent relation "regular_partition01" +-- +-- test unsupported inherit table +-- +create table inherits_parent( +a int not null, +b varchar(32) not null default 'Got u', +c int check (c > 0), +d date not null +); +create global temp table inherits_parent_global_temp( +a int not null, +b varchar(32) not null default 'Got u', +c int check (c > 0), +d date not null +)on commit delete rows; +-- should fail +create global temp table temp_inherit() inherits (inherits_parent); +ERROR: cannot create global temporary inherit table or global temporary partitioned table +-- should fail +create global temp table temp_inherit() inherits (inherits_parent_global_temp) on commit delete rows; +ERROR: cannot create global temporary inherit table or global temporary partitioned table +-- +-- test DDL on global temp table +-- +create index idx_gtt_test_alter_b on gtt_test_alter (b); +insert into gtt_test_alter values('test'); +alter table gtt_test_alter alter b type varchar; +create index gtt_idx_1 on gtt_test_createindex using gin (c0); +create index gtt_idx_2 on gtt_test_createindex using gist (c0); +create index gtt_idx_3 on gtt_test_createindex using hash (c2); +alter table gtt_test_rename rename to gtt_test_new; +ALTER TABLE gtt_test_new ADD COLUMN address varchar(30); +create index CONCURRENTLY idx_b on gtt_on_commit_default (b); +cluster gtt_on_commit_default using gtt_on_commit_default_pkey; +insert into gtt_on_commit_default values(1,'test'); +create global temp table gtt_test_alter1 (a int primary key,b text); +alter table gtt_test_alter1 alter a type varchar; +-- should fail +alter table gtt_on_commit_default alter a type varchar; +ERROR: cannot rewrite global temporary table "gtt_on_commit_default" when it has data in this session +HINT: Please create a new connection and execute ALTER TABLE on the new connection. +-- should fail +cluster gtt_on_commit_default using gtt_on_commit_default_pkey; +ERROR: cannot cluster global temporary table +-- should fail +create table gtt_on_commit_default(a int primary key, b text) on commit delete rows; +ERROR: ON COMMIT can only be used on temporary tables +-- should fail +REINDEX (TABLESPACE pg_default) TABLE gtt_test_createindex; +ERROR: cannot change tablespace of global temporary table +-- should fail +REINDEX (TABLESPACE pg_default) INDEX gtt_idx_1; +ERROR: cannot change tablespace of global temporary table +-- should fail +alter table gtt_on_commit_default set ( on_commit_delete_rows='true'); +ERROR: cannot set "on_commit_delete_rows" for relation "gtt_on_commit_default" +-- should fail +create table gtt_on_commit_default(a int primary key, b text) with(on_commit_delete_rows=true); +ERROR: on_commit_delete_rows can only be used on global temporary table +-- should fail +create or replace global temp view gtt_v as select 5; +ERROR: views cannot be global temporary because they do not have storage +create table foo(); +-- should fail +alter table foo set (on_commit_delete_rows='true'); +ERROR: cannot set "on_commit_delete_rows" for relation "foo" +-- should fail +create global temp table gtt_on_commit_preserve(a int primary key, b text) on commit drop; +ERROR: specifying ON COMMIT DROP is not supported on a global temporary table +-- should fail +create global temp table gtt4(a int primary key, b text) with(on_commit_delete_rows=true) on commit delete rows; +ERROR: cannot specify both ON COMMIT clause and on_commit_delete_rows +-- should fail +CREATE MATERIALIZED VIEW mv_gtt_on_commit_default as select * from gtt_on_commit_default; +ERROR: materialized views must not use temporary tables or views +-- test create table as select +CREATE GLOBAL TEMPORARY TABLE test_create_table_as AS SELECT 1 AS a; +-- test copy stmt +create global temp table gtt_copytest ( + c1 int, + "col with , comma" text, + "col with "" quote" int); +copy gtt_copytest from stdin csv header; +select count(*) from gtt_copytest; + count +------- + 2 +(1 row) + +-- +-- test foreign key dependencies for global temp table +-- +CREATE global temp TABLE temp_products ( + product_no integer PRIMARY KEY, + name text, + price numeric +); +CREATE global temp TABLE products ( + product_no integer PRIMARY KEY, + name text, + price numeric +); +CREATE global temp TABLE temp_orders ( + order_id integer PRIMARY KEY, + product_no integer REFERENCES temp_products(product_no), + quantity integer +)on commit delete rows; +-- should fail +CREATE TABLE orders ( + order_id integer PRIMARY KEY, + product_no integer REFERENCES temp_products(product_no), + quantity integer +); +ERROR: constraints on permanent tables may reference only permanent tables +CREATE global temp TABLE temp_orders_2 ( + order_id integer PRIMARY KEY, + product_no integer REFERENCES products(product_no), + quantity integer +); +--should fail +insert into temp_orders values(1,1,1); +ERROR: insert or update on table "temp_orders" violates foreign key constraint "temp_orders_product_no_fkey" +DETAIL: Key (product_no)=(1) is not present in table "temp_products". +insert into temp_products values(1,'test',1.0); +begin; +insert into temp_orders values(1,1,1); +commit; +-- should 1 row +select count(*) from temp_products; + count +------- + 1 +(1 row) + +-- should 0 row +select count(*) from temp_orders; + count +------- + 0 +(1 row) + +-- +-- test sequence on global temp table +-- +create global temp table global_temp_with_serial (a SERIAL,b int); +begin; +set transaction_read_only = true; +-- support insert data to temp table in read only transaction +insert into global_temp_with_serial (b) values(1); +select * from global_temp_with_serial; + a | b +---+--- + 1 | 1 +(1 row) + +commit; +create sequence seq_1; +CREATE GLOBAL TEMPORARY TABLE temp_table_with_sequence_oncommit_delete(c1 int PRIMARY KEY) ON COMMIT DELETE ROWS; +CREATE GLOBAL TEMPORARY TABLE temp_table_with_sequence_oncommit_preserve(c1 int PRIMARY KEY) ON COMMIT PRESERVE ROWS; +alter table temp_table_with_sequence_oncommit_delete add c2 int default nextval('seq_1'); +alter table temp_table_with_sequence_oncommit_preserve add c2 int default nextval('seq_1'); +begin; +insert into temp_table_with_sequence_oncommit_delete (c1)values(1); +insert into temp_table_with_sequence_oncommit_preserve (c1)values(2); +insert into temp_table_with_sequence_oncommit_delete (c1)values(3); +insert into temp_table_with_sequence_oncommit_preserve (c1)values(4); +-- should 2 row +select * from temp_table_with_sequence_oncommit_delete order by c1; + c1 | c2 +----+---- + 1 | 1 + 3 | 3 +(2 rows) + +commit; +-- should 0 row +select * from temp_table_with_sequence_oncommit_delete order by c1; + c1 | c2 +----+---- +(0 rows) + +-- should 2 row +select * from temp_table_with_sequence_oncommit_preserve order by c1; + c1 | c2 +----+---- + 2 | 2 + 4 | 4 +(2 rows) + +-- +-- test statistics on temp table +-- +create global temp table temp_table_test_statistics(a int); +insert into temp_table_test_statistics values(generate_series(1,100000)); +create index idx_test_1 on temp_table_test_statistics (a); +create index idx_test_2 on temp_table_test_statistics((a*10)); +explain (costs off) select * from temp_table_test_statistics where a=200000; + QUERY PLAN +------------------------------------------------ + Bitmap Heap Scan on temp_table_test_statistics + Recheck Cond: (a = 200000) + -> Bitmap Index Scan on idx_test_1 + Index Cond: (a = 200000) +(4 rows) + +explain (costs off) select * from temp_table_test_statistics where a*10=3; + QUERY PLAN +------------------------------------------------ + Bitmap Heap Scan on temp_table_test_statistics + Recheck Cond: ((a * 10) = 3) + -> Bitmap Index Scan on idx_test_2 + Index Cond: ((a * 10) = 3) +(4 rows) + +-- test statistic for whole row +explain (costs off) select count(*) from temp_table_test_statistics group by temp_table_test_statistics; + QUERY PLAN +---------------------------------------------- + HashAggregate + Group Key: temp_table_test_statistics.* + -> Seq Scan on temp_table_test_statistics +(3 rows) + +-- test statistic for system column +explain (costs off) select count(*) from temp_table_test_statistics group by tableoid; + QUERY PLAN +---------------------------------------------- + HashAggregate + Group Key: tableoid + -> Seq Scan on temp_table_test_statistics +(3 rows) + +analyze temp_table_test_statistics; +-- indexscan by idx_test_1 +explain (costs off) select * from temp_table_test_statistics where a=200000; + QUERY PLAN +---------------------------------------------------------------- + Index Only Scan using idx_test_1 on temp_table_test_statistics + Index Cond: (a = 200000) +(2 rows) + +-- indexscan by idx_test_2 +explain (costs off) select * from temp_table_test_statistics where a*10=3; + QUERY PLAN +----------------------------------------------------------- + Index Scan using idx_test_2 on temp_table_test_statistics + Index Cond: ((a * 10) = 3) +(2 rows) + +explain (costs off) select count(*) from temp_table_test_statistics group by temp_table_test_statistics; + QUERY PLAN +---------------------------------------------- + HashAggregate + Group Key: temp_table_test_statistics.* + -> Seq Scan on temp_table_test_statistics +(3 rows) + +explain (costs off) select count(*) from temp_table_test_statistics group by tableoid; + QUERY PLAN +---------------------------------------------- + HashAggregate + Group Key: tableoid + -> Seq Scan on temp_table_test_statistics +(3 rows) + +-- +-- test temp table with toast table +-- +create global temp table gtt_t_kenyon(id int,vname varchar(48),remark text) on commit PRESERVE rows; +create index idx_gtt_t_kenyon_1 on gtt_t_kenyon(id); +create index idx_gtt_t_kenyon_2 on gtt_t_kenyon(remark); +insert into gtt_t_kenyon select generate_series(1,2000),repeat('kenyon here'||'^_^',2),repeat('^_^ Kenyon is not God',500); +select relname, pg_relation_size(oid),pg_relation_size(reltoastrelid),pg_table_size(oid),pg_indexes_size(oid),pg_total_relation_size(oid) from pg_class where relname like '%t_kenyon%' order by relname; + relname | pg_relation_size | pg_relation_size | pg_table_size | pg_indexes_size | pg_total_relation_size +--------------------+------------------+------------------+---------------+-----------------+------------------------ + gtt_t_kenyon | 450560 | 0 | 483328 | 98304 | 581632 + idx_gtt_t_kenyon_1 | 65536 | | 65536 | 0 | 65536 + idx_gtt_t_kenyon_2 | 32768 | | 32768 | 0 | 32768 +(3 rows) + +insert into gtt_t_kenyon select generate_series(5,6),repeat('kenyon here'||'^_^',2),repeat('^_^ Kenyon is not God,Remark here!!',5500); +select relname, pg_relation_size(oid),pg_relation_size(reltoastrelid),pg_table_size(oid),pg_indexes_size(oid),pg_total_relation_size(oid) from pg_class where relname like '%t_kenyon%' order by relname; + relname | pg_relation_size | pg_relation_size | pg_table_size | pg_indexes_size | pg_total_relation_size +--------------------+------------------+------------------+---------------+-----------------+------------------------ + gtt_t_kenyon | 450560 | 8192 | 499712 | 106496 | 606208 + idx_gtt_t_kenyon_1 | 65536 | | 65536 | 0 | 65536 + idx_gtt_t_kenyon_2 | 40960 | | 40960 | 0 | 40960 +(3 rows) + +begin; +truncate gtt_t_kenyon; +insert into gtt_t_kenyon select generate_series(1,10),repeat('kenyon here'||'^_^',2),repeat('^_^ Kenyon is not God',10); +select relname, pg_relation_size(oid),pg_relation_size(reltoastrelid),pg_table_size(oid),pg_indexes_size(oid),pg_total_relation_size(oid) from pg_class where relname like '%t_kenyon%' order by relname; + relname | pg_relation_size | pg_relation_size | pg_table_size | pg_indexes_size | pg_total_relation_size +--------------------+------------------+------------------+---------------+-----------------+------------------------ + gtt_t_kenyon | 8192 | 0 | 16384 | 32768 | 49152 + idx_gtt_t_kenyon_1 | 16384 | | 16384 | 0 | 16384 + idx_gtt_t_kenyon_2 | 16384 | | 16384 | 0 | 16384 +(3 rows) + +rollback; +select relname, pg_relation_size(oid),pg_relation_size(reltoastrelid),pg_table_size(oid),pg_indexes_size(oid),pg_total_relation_size(oid) from pg_class where relname like '%t_kenyon%' order by relname; + relname | pg_relation_size | pg_relation_size | pg_table_size | pg_indexes_size | pg_total_relation_size +--------------------+------------------+------------------+---------------+-----------------+------------------------ + gtt_t_kenyon | 450560 | 8192 | 499712 | 106496 | 606208 + idx_gtt_t_kenyon_1 | 65536 | | 65536 | 0 | 65536 + idx_gtt_t_kenyon_2 | 40960 | | 40960 | 0 | 40960 +(3 rows) + +-- test analyze/vacuum on global temp table +ANALYZE gtt_t_kenyon; +VACUUM gtt_t_kenyon; +-- +-- test global temp table system view +-- +create global temp table temp_table_test_systemview(a int primary key, b text) on commit PRESERVE rows; +-- should empty, storage not initialized +select tablename from pg_gtt_attached_pids where tablename = 'temp_table_test_systemview'; + tablename +----------- +(0 rows) + +-- should empty, storage not initialized +select count(*) from pg_list_gtt_relfrozenxids(); + count +------- + 1 +(1 row) + +insert into temp_table_test_systemview values(generate_series(1,10000),'test'); +select tablename from pg_gtt_attached_pids where tablename = 'temp_table_test_systemview'; + tablename +---------------------------- + temp_table_test_systemview +(1 row) + +select count(*) from pg_list_gtt_relfrozenxids(); + count +------- + 1 +(1 row) + +select schemaname, tablename, relpages, reltuples, relallvisible from pg_gtt_relstats where tablename in('temp_table_test_systemview','temp_table_test_systemview_pkey') order by tablename; + schemaname | tablename | relpages | reltuples | relallvisible +------------------------+---------------------------------+----------+-----------+--------------- + global_temporary_table | temp_table_test_systemview | 0 | 0 | 0 + global_temporary_table | temp_table_test_systemview_pkey | 1 | 0 | 0 +(2 rows) + +-- should empty +select * from pg_gtt_stats where tablename = 'temp_table_test_systemview' order by tablename; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram +------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+---------------------- +(0 rows) + +analyze temp_table_test_systemview; +select schemaname, tablename, relpages, reltuples, relallvisible from pg_gtt_relstats where tablename in('temp_table_test_systemview','temp_table_test_systemview_pkey') order by tablename; + schemaname | tablename | relpages | reltuples | relallvisible +------------------------+---------------------------------+----------+-----------+--------------- + global_temporary_table | temp_table_test_systemview | 55 | 10000 | 0 + global_temporary_table | temp_table_test_systemview_pkey | 30 | 10000 | 0 +(2 rows) + +-- get data after analyze; +select * from pg_gtt_stats where tablename = 'temp_table_test_systemview' order by tablename; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram +------------------------+----------------------------+---------+-----------+-----------+-----------+------------+------------------+-------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------+-------------------+------------------------+---------------------- + global_temporary_table | temp_table_test_systemview | a | f | 0 | 4 | -1 | | | {1,100,200,300,400,500,600,700,800,900,1000,1100,1200,1300,1400,1500,1600,1700,1800,1900,2000,2100,2200,2300,2400,2500,2600,2700,2800,2900,3000,3100,3200,3300,3400,3500,3600,3700,3800,3900,4000,4100,4200,4300,4400,4500,4600,4700,4800,4900,5000,5100,5200,5300,5400,5500,5600,5700,5800,5900,6000,6100,6200,6300,6400,6500,6600,6700,6800,6900,7000,7100,7200,7300,7400,7500,7600,7700,7800,7900,8000,8100,8200,8300,8400,8500,8600,8700,8800,8900,9000,9100,9200,9300,9400,9500,9600,9700,9800,9900,10000} | 1 | | | + global_temporary_table | temp_table_test_systemview | b | f | 0 | 5 | 1 | {test} | {1} | | 1 | | | +(2 rows) + +-- get all object info in current schema +select relname ,relkind, relpersistence, reloptions from pg_class c, pg_namespace n where c.relnamespace = n.oid and n.nspname = 'global_temporary_table' order by relkind,relpersistence,relname; + relname | relkind | relpersistence | reloptions +-------------------------------------------------+---------+----------------+------------------------------- + global_temp_partition_01_2021_id_seq | S | g | {on_commit_delete_rows=false} + global_temp_with_serial_a_seq | S | g | {on_commit_delete_rows=false} + regular_partition01_id_seq | S | p | + regular_partition_01_2019_id_seq | S | p | + seq_1 | S | p | + gtt_idx_1 | i | g | + gtt_idx_2 | i | g | + gtt_idx_3 | i | g | + gtt_on_commit_default_pkey | i | g | + gtt_on_commit_delete_pkey | i | g | + gtt_on_commit_preserve_pkey | i | g | + gtt_test_alter1_pkey | i | g | + gtt_test_rename_pkey | i | g | + idx_b | i | g | + idx_gtt_t_kenyon_1 | i | g | + idx_gtt_t_kenyon_2 | i | g | + idx_gtt_test_alter_b | i | g | + idx_test_1 | i | g | + idx_test_2 | i | g | + products_pkey | i | g | + temp_orders_2_pkey | i | g | + temp_orders_pkey | i | g | + temp_products_pkey | i | g | + temp_table_test_systemview_pkey | i | g | + temp_table_with_sequence_oncommit_delete_pkey | i | g | + temp_table_with_sequence_oncommit_preserve_pkey | i | g | + regular_partition01 | p | p | + global_temp_partition_01_2021 | r | g | {on_commit_delete_rows=true} + global_temp_with_serial | r | g | {on_commit_delete_rows=false} + gtt_copytest | r | g | {on_commit_delete_rows=false} + gtt_on_commit_default | r | g | {on_commit_delete_rows=false} + gtt_on_commit_delete | r | g | {on_commit_delete_rows=true} + gtt_on_commit_delete2 | r | g | {on_commit_delete_rows=true} + gtt_on_commit_preserve | r | g | {on_commit_delete_rows=false} + gtt_t_kenyon | r | g | {on_commit_delete_rows=false} + gtt_test_alter | r | g | {on_commit_delete_rows=true} + gtt_test_alter1 | r | g | {on_commit_delete_rows=false} + gtt_test_createindex | r | g | {on_commit_delete_rows=false} + gtt_test_new | r | g | {on_commit_delete_rows=false} + inherits_parent_global_temp | r | g | {on_commit_delete_rows=true} + products | r | g | {on_commit_delete_rows=false} + temp_orders | r | g | {on_commit_delete_rows=true} + temp_orders_2 | r | g | {on_commit_delete_rows=false} + temp_products | r | g | {on_commit_delete_rows=false} + temp_table_test_statistics | r | g | {on_commit_delete_rows=false} + temp_table_test_systemview | r | g | {on_commit_delete_rows=false} + temp_table_with_sequence_oncommit_delete | r | g | {on_commit_delete_rows=true} + temp_table_with_sequence_oncommit_preserve | r | g | {on_commit_delete_rows=false} + test_create_table_as | r | g | {on_commit_delete_rows=false} + foo | r | p | + inherits_parent | r | p | + regular_partition_01_2019 | r | p | +(52 rows) + +reset search_path; +drop schema global_temporary_table cascade; +NOTICE: drop cascades to 27 other objects +DETAIL: drop cascades to table global_temporary_table.gtt_on_commit_default +drop cascades to table global_temporary_table.gtt_on_commit_delete +drop cascades to table global_temporary_table.gtt_on_commit_delete2 +drop cascades to table global_temporary_table.gtt_on_commit_preserve +drop cascades to table global_temporary_table.gtt_test_new +drop cascades to table global_temporary_table.gtt_test_createindex +drop cascades to table global_temporary_table.gtt_test_alter +drop cascades to table global_temporary_table.regular_partition_01_2019 +drop cascades to table global_temporary_table.regular_partition01 +drop cascades to table global_temporary_table.global_temp_partition_01_2021 +drop cascades to table global_temporary_table.inherits_parent +drop cascades to table global_temporary_table.inherits_parent_global_temp +drop cascades to table global_temporary_table.gtt_test_alter1 +drop cascades to table global_temporary_table.foo +drop cascades to table global_temporary_table.test_create_table_as +drop cascades to table global_temporary_table.gtt_copytest +drop cascades to table global_temporary_table.temp_products +drop cascades to table global_temporary_table.products +drop cascades to table global_temporary_table.temp_orders +drop cascades to table global_temporary_table.temp_orders_2 +drop cascades to table global_temporary_table.global_temp_with_serial +drop cascades to sequence global_temporary_table.seq_1 +drop cascades to table global_temporary_table.temp_table_with_sequence_oncommit_delete +drop cascades to table global_temporary_table.temp_table_with_sequence_oncommit_preserve +drop cascades to table global_temporary_table.temp_table_test_statistics +drop cascades to table global_temporary_table.gtt_t_kenyon +drop cascades to table global_temporary_table.temp_table_test_systemview +-- should empty +select * from pg_list_gtt_relfrozenxids(); + pid | relfrozenxid +-----+-------------- +(0 rows) + diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 1420288d67b..faa70c947fa 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1337,6 +1337,94 @@ pg_group| SELECT pg_authid.rolname AS groname, WHERE (pg_auth_members.roleid = pg_authid.oid)) AS grolist FROM pg_authid WHERE (NOT pg_authid.rolcanlogin); +pg_gtt_attached_pids| SELECT n.nspname AS schemaname, + c.relname AS tablename, + s.relid, + s.pid + FROM (pg_class c + LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))), + LATERAL pg_gtt_attached_pid(c.oid) s(relid, pid) + WHERE ((c.relpersistence = 'g'::"char") AND (c.relkind = ANY (ARRAY['r'::"char", 'S'::"char"])) AND ((c.relrowsecurity = false) OR (NOT row_security_active(c.oid)))); +pg_gtt_relstats| SELECT n.nspname AS schemaname, + c.relname AS tablename, + s.relfilenode, + s.relpages, + s.reltuples, + s.relallvisible, + s.relfrozenxid, + s.relminmxid + FROM (pg_class c + LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))), + LATERAL pg_get_gtt_relstats(c.oid) s(relfilenode, relpages, reltuples, relallvisible, relfrozenxid, relminmxid) + WHERE ((c.relpersistence = 'g'::"char") AND (c.relkind = ANY (ARRAY['r'::"char", 'p'::"char", 'i'::"char", 't'::"char"])) AND ((c.relrowsecurity = false) OR (NOT row_security_active(c.oid)))); +pg_gtt_stats| SELECT n.nspname AS schemaname, + c.relname AS tablename, + a.attname, + s.stainherit AS inherited, + s.stanullfrac AS null_frac, + s.stawidth AS avg_width, + s.stadistinct AS n_distinct, + CASE + WHEN (s.stakind1 = 1) THEN s.stavalues1 + WHEN (s.stakind2 = 1) THEN s.stavalues2 + WHEN (s.stakind3 = 1) THEN s.stavalues3 + WHEN (s.stakind4 = 1) THEN s.stavalues4 + WHEN (s.stakind5 = 1) THEN s.stavalues5 + ELSE NULL::text[] + END AS most_common_vals, + CASE + WHEN (s.stakind1 = 1) THEN s.stanumbers1 + WHEN (s.stakind2 = 1) THEN s.stanumbers2 + WHEN (s.stakind3 = 1) THEN s.stanumbers3 + WHEN (s.stakind4 = 1) THEN s.stanumbers4 + WHEN (s.stakind5 = 1) THEN s.stanumbers5 + ELSE NULL::real[] + END AS most_common_freqs, + CASE + WHEN (s.stakind1 = 2) THEN s.stavalues1 + WHEN (s.stakind2 = 2) THEN s.stavalues2 + WHEN (s.stakind3 = 2) THEN s.stavalues3 + WHEN (s.stakind4 = 2) THEN s.stavalues4 + WHEN (s.stakind5 = 2) THEN s.stavalues5 + ELSE NULL::text[] + END AS histogram_bounds, + CASE + WHEN (s.stakind1 = 3) THEN s.stanumbers1[1] + WHEN (s.stakind2 = 3) THEN s.stanumbers2[1] + WHEN (s.stakind3 = 3) THEN s.stanumbers3[1] + WHEN (s.stakind4 = 3) THEN s.stanumbers4[1] + WHEN (s.stakind5 = 3) THEN s.stanumbers5[1] + ELSE NULL::real + END AS correlation, + CASE + WHEN (s.stakind1 = 4) THEN s.stavalues1 + WHEN (s.stakind2 = 4) THEN s.stavalues2 + WHEN (s.stakind3 = 4) THEN s.stavalues3 + WHEN (s.stakind4 = 4) THEN s.stavalues4 + WHEN (s.stakind5 = 4) THEN s.stavalues5 + ELSE NULL::text[] + END AS most_common_elems, + CASE + WHEN (s.stakind1 = 4) THEN s.stanumbers1 + WHEN (s.stakind2 = 4) THEN s.stanumbers2 + WHEN (s.stakind3 = 4) THEN s.stanumbers3 + WHEN (s.stakind4 = 4) THEN s.stanumbers4 + WHEN (s.stakind5 = 4) THEN s.stanumbers5 + ELSE NULL::real[] + END AS most_common_elem_freqs, + CASE + WHEN (s.stakind1 = 5) THEN s.stanumbers1 + WHEN (s.stakind2 = 5) THEN s.stanumbers2 + WHEN (s.stakind3 = 5) THEN s.stanumbers3 + WHEN (s.stakind4 = 5) THEN s.stanumbers4 + WHEN (s.stakind5 = 5) THEN s.stanumbers5 + ELSE NULL::real[] + END AS elem_count_histogram + FROM ((pg_class c + JOIN pg_attribute a ON ((c.oid = a.attrelid))) + LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))), + LATERAL pg_get_gtt_statistics(c.oid, (a.attnum)::integer, ''::text) s(starelid, staattnum, stainherit, stanullfrac, stawidth, stadistinct, stakind1, stakind2, stakind3, stakind4, stakind5, staop1, staop2, staop3, staop4, staop5, stacoll1, stacoll2, stacoll3, stacoll4, stacoll5, stanumbers1, stanumbers2, stanumbers3, stanumbers4, stanumbers5, stavalues1, stavalues2, stavalues3, stavalues4, stavalues5) + WHERE ((c.relpersistence = 'g'::"char") AND (c.relkind = ANY (ARRAY['r'::"char", 'p'::"char", 'i'::"char", 't'::"char"])) AND (NOT a.attisdropped) AND has_column_privilege(c.oid, a.attnum, 'select'::text) AND ((c.relrowsecurity = false) OR (NOT row_security_active(c.oid)))); pg_hba_file_rules| SELECT a.line_number, a.type, a.database, diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 6d8f524ae9e..7924bc02f59 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -135,3 +135,6 @@ test: fast_default # run stats by itself because its delay may be insufficient under heavy load test: stats + +# global temp table test +test: global_temporary_table diff --git a/src/test/regress/sql/global_temporary_table.sql b/src/test/regress/sql/global_temporary_table.sql new file mode 100644 index 00000000000..51cd9bbbc0c --- /dev/null +++ b/src/test/regress/sql/global_temporary_table.sql @@ -0,0 +1,315 @@ +-- +-- GLobal emparary table test case +-- + +CREATE SCHEMA IF NOT EXISTS global_temporary_table; +set search_path=global_temporary_table,sys; + +-- +-- test create global temp table basic syntax +-- +create global temp table gtt_on_commit_default(a int primary key, b text); +create global temp table gtt_on_commit_delete(a int primary key, b text) on commit delete rows; +create global temp table gtt_on_commit_delete2(n int) with (on_commit_delete_rows='true'); +create global temp table gtt_on_commit_preserve(a int primary key, b text) on commit PRESERVE rows; +create global temp table gtt_test_rename(a int primary key, b text); +create global temp table gtt_test_createindex(c0 tsvector,c1 varchar(100), c2 int); +create global temp table gtt_test_alter(b text) with(on_commit_delete_rows=true); +-- +-- test DML on global temp table +-- + +-- update empty temp table +update gtt_on_commit_delete set b ='test'; +begin; +insert into gtt_on_commit_delete values (1); +update gtt_on_commit_delete set b ='test'; +-- should 1 row +select * from gtt_on_commit_delete; +commit; +-- data delete after transaction commit +-- should 0 row +select * from gtt_on_commit_delete; + +-- update empty temp table +update gtt_on_commit_preserve set b ='test'; +insert into gtt_on_commit_preserve values (2); +begin; +insert into gtt_on_commit_preserve values (3); +update gtt_on_commit_preserve set b ='test'; +-- should 2 row +select * from gtt_on_commit_preserve order by a; +delete from gtt_on_commit_preserve where a=2; +commit; +-- should 1 row +select * from gtt_on_commit_preserve order by a; + +begin; +insert into gtt_on_commit_preserve values (4); +-- temp table support truncate; +truncate gtt_on_commit_preserve; +select * from gtt_on_commit_preserve order by a; +rollback; +-- should 1 row +select * from gtt_on_commit_preserve order by a; + +-- +-- test unsupported global temp partition table +-- + +-- should fail +CREATE global temp TABLE global_temp_partition_01 ( +id bigserial NOT NULL, +cre_time timestamp without time zone, +note varchar(30) +) PARTITION BY RANGE (cre_time) +on commit delete rows; + +CREATE TABLE regular_partition_01_2019 ( +id bigserial NOT NULL, +cre_time timestamp without time zone, +note varchar(30) +); + +CREATE TABLE regular_partition01 ( +id bigserial NOT NULL, +cre_time timestamp without time zone, +note varchar(30) +) PARTITION BY RANGE (cre_time); + +-- should fail +CREATE global temp TABLE temp_partition01_2018 +PARTITION OF regular_partition01 +FOR VALUES FROM ('2018-01-01 00:00:00') TO ('2019-01-01 00:00:00'); + +CREATE global temp TABLE global_temp_partition_01_2021 ( +id bigserial NOT NULL, +cre_time timestamp without time zone, +note varchar(30) +)on commit delete rows; + +-- should fail +ALTER TABLE regular_partition01 ATTACH PARTITION global_temp_partition_01_2021 FOR VALUES FROM ('2021-01-01 00:00:00') TO ('2022-01-01 00:00:00'); + +-- +-- test unsupported inherit table +-- +create table inherits_parent( +a int not null, +b varchar(32) not null default 'Got u', +c int check (c > 0), +d date not null +); + +create global temp table inherits_parent_global_temp( +a int not null, +b varchar(32) not null default 'Got u', +c int check (c > 0), +d date not null +)on commit delete rows; + +-- should fail +create global temp table temp_inherit() inherits (inherits_parent); +-- should fail +create global temp table temp_inherit() inherits (inherits_parent_global_temp) on commit delete rows; + +-- +-- test DDL on global temp table +-- +create index idx_gtt_test_alter_b on gtt_test_alter (b); +insert into gtt_test_alter values('test'); +alter table gtt_test_alter alter b type varchar; +create index gtt_idx_1 on gtt_test_createindex using gin (c0); +create index gtt_idx_2 on gtt_test_createindex using gist (c0); +create index gtt_idx_3 on gtt_test_createindex using hash (c2); +alter table gtt_test_rename rename to gtt_test_new; +ALTER TABLE gtt_test_new ADD COLUMN address varchar(30); +create index CONCURRENTLY idx_b on gtt_on_commit_default (b); +cluster gtt_on_commit_default using gtt_on_commit_default_pkey; +insert into gtt_on_commit_default values(1,'test'); +create global temp table gtt_test_alter1 (a int primary key,b text); +alter table gtt_test_alter1 alter a type varchar; +-- should fail +alter table gtt_on_commit_default alter a type varchar; +-- should fail +cluster gtt_on_commit_default using gtt_on_commit_default_pkey; +-- should fail +create table gtt_on_commit_default(a int primary key, b text) on commit delete rows; +-- should fail +REINDEX (TABLESPACE pg_default) TABLE gtt_test_createindex; +-- should fail +REINDEX (TABLESPACE pg_default) INDEX gtt_idx_1; +-- should fail +alter table gtt_on_commit_default set ( on_commit_delete_rows='true'); +-- should fail +create table gtt_on_commit_default(a int primary key, b text) with(on_commit_delete_rows=true); +-- should fail +create or replace global temp view gtt_v as select 5; +create table foo(); +-- should fail +alter table foo set (on_commit_delete_rows='true'); +-- should fail +create global temp table gtt_on_commit_preserve(a int primary key, b text) on commit drop; +-- should fail +create global temp table gtt4(a int primary key, b text) with(on_commit_delete_rows=true) on commit delete rows; +-- should fail +CREATE MATERIALIZED VIEW mv_gtt_on_commit_default as select * from gtt_on_commit_default; +-- test create table as select +CREATE GLOBAL TEMPORARY TABLE test_create_table_as AS SELECT 1 AS a; +-- test copy stmt +create global temp table gtt_copytest ( + c1 int, + "col with , comma" text, + "col with "" quote" int); + +copy gtt_copytest from stdin csv header; +this is just a line full of junk that would error out if parsed +1,a,1 +2,b,2 +\. +select count(*) from gtt_copytest; + +-- +-- test foreign key dependencies for global temp table +-- +CREATE global temp TABLE temp_products ( + product_no integer PRIMARY KEY, + name text, + price numeric +); + +CREATE global temp TABLE products ( + product_no integer PRIMARY KEY, + name text, + price numeric +); + +CREATE global temp TABLE temp_orders ( + order_id integer PRIMARY KEY, + product_no integer REFERENCES temp_products(product_no), + quantity integer +)on commit delete rows; + +-- should fail +CREATE TABLE orders ( + order_id integer PRIMARY KEY, + product_no integer REFERENCES temp_products(product_no), + quantity integer +); + +CREATE global temp TABLE temp_orders_2 ( + order_id integer PRIMARY KEY, + product_no integer REFERENCES products(product_no), + quantity integer +); + +--should fail +insert into temp_orders values(1,1,1); + +insert into temp_products values(1,'test',1.0); +begin; +insert into temp_orders values(1,1,1); +commit; +-- should 1 row +select count(*) from temp_products; +-- should 0 row +select count(*) from temp_orders; + +-- +-- test sequence on global temp table +-- +create global temp table global_temp_with_serial (a SERIAL,b int); +begin; +set transaction_read_only = true; +-- support insert data to temp table in read only transaction +insert into global_temp_with_serial (b) values(1); +select * from global_temp_with_serial; +commit; + +create sequence seq_1; +CREATE GLOBAL TEMPORARY TABLE temp_table_with_sequence_oncommit_delete(c1 int PRIMARY KEY) ON COMMIT DELETE ROWS; +CREATE GLOBAL TEMPORARY TABLE temp_table_with_sequence_oncommit_preserve(c1 int PRIMARY KEY) ON COMMIT PRESERVE ROWS; +alter table temp_table_with_sequence_oncommit_delete add c2 int default nextval('seq_1'); +alter table temp_table_with_sequence_oncommit_preserve add c2 int default nextval('seq_1'); +begin; +insert into temp_table_with_sequence_oncommit_delete (c1)values(1); +insert into temp_table_with_sequence_oncommit_preserve (c1)values(2); +insert into temp_table_with_sequence_oncommit_delete (c1)values(3); +insert into temp_table_with_sequence_oncommit_preserve (c1)values(4); +-- should 2 row +select * from temp_table_with_sequence_oncommit_delete order by c1; +commit; +-- should 0 row +select * from temp_table_with_sequence_oncommit_delete order by c1; +-- should 2 row +select * from temp_table_with_sequence_oncommit_preserve order by c1; + +-- +-- test statistics on temp table +-- +create global temp table temp_table_test_statistics(a int); +insert into temp_table_test_statistics values(generate_series(1,100000)); +create index idx_test_1 on temp_table_test_statistics (a); +create index idx_test_2 on temp_table_test_statistics((a*10)); +explain (costs off) select * from temp_table_test_statistics where a=200000; +explain (costs off) select * from temp_table_test_statistics where a*10=3; +-- test statistic for whole row +explain (costs off) select count(*) from temp_table_test_statistics group by temp_table_test_statistics; +-- test statistic for system column +explain (costs off) select count(*) from temp_table_test_statistics group by tableoid; +analyze temp_table_test_statistics; +-- indexscan by idx_test_1 +explain (costs off) select * from temp_table_test_statistics where a=200000; +-- indexscan by idx_test_2 +explain (costs off) select * from temp_table_test_statistics where a*10=3; +explain (costs off) select count(*) from temp_table_test_statistics group by temp_table_test_statistics; +explain (costs off) select count(*) from temp_table_test_statistics group by tableoid; + +-- +-- test temp table with toast table +-- +create global temp table gtt_t_kenyon(id int,vname varchar(48),remark text) on commit PRESERVE rows; +create index idx_gtt_t_kenyon_1 on gtt_t_kenyon(id); +create index idx_gtt_t_kenyon_2 on gtt_t_kenyon(remark); +insert into gtt_t_kenyon select generate_series(1,2000),repeat('kenyon here'||'^_^',2),repeat('^_^ Kenyon is not God',500); +select relname, pg_relation_size(oid),pg_relation_size(reltoastrelid),pg_table_size(oid),pg_indexes_size(oid),pg_total_relation_size(oid) from pg_class where relname like '%t_kenyon%' order by relname; +insert into gtt_t_kenyon select generate_series(5,6),repeat('kenyon here'||'^_^',2),repeat('^_^ Kenyon is not God,Remark here!!',5500); +select relname, pg_relation_size(oid),pg_relation_size(reltoastrelid),pg_table_size(oid),pg_indexes_size(oid),pg_total_relation_size(oid) from pg_class where relname like '%t_kenyon%' order by relname; +begin; +truncate gtt_t_kenyon; +insert into gtt_t_kenyon select generate_series(1,10),repeat('kenyon here'||'^_^',2),repeat('^_^ Kenyon is not God',10); +select relname, pg_relation_size(oid),pg_relation_size(reltoastrelid),pg_table_size(oid),pg_indexes_size(oid),pg_total_relation_size(oid) from pg_class where relname like '%t_kenyon%' order by relname; +rollback; +select relname, pg_relation_size(oid),pg_relation_size(reltoastrelid),pg_table_size(oid),pg_indexes_size(oid),pg_total_relation_size(oid) from pg_class where relname like '%t_kenyon%' order by relname; + +-- test analyze/vacuum on global temp table +ANALYZE gtt_t_kenyon; +VACUUM gtt_t_kenyon; + +-- +-- test global temp table system view +-- +create global temp table temp_table_test_systemview(a int primary key, b text) on commit PRESERVE rows; +-- should empty, storage not initialized +select tablename from pg_gtt_attached_pids where tablename = 'temp_table_test_systemview'; +-- should empty, storage not initialized +select count(*) from pg_list_gtt_relfrozenxids(); +insert into temp_table_test_systemview values(generate_series(1,10000),'test'); +select tablename from pg_gtt_attached_pids where tablename = 'temp_table_test_systemview'; +select count(*) from pg_list_gtt_relfrozenxids(); +select schemaname, tablename, relpages, reltuples, relallvisible from pg_gtt_relstats where tablename in('temp_table_test_systemview','temp_table_test_systemview_pkey') order by tablename; +-- should empty +select * from pg_gtt_stats where tablename = 'temp_table_test_systemview' order by tablename; +analyze temp_table_test_systemview; +select schemaname, tablename, relpages, reltuples, relallvisible from pg_gtt_relstats where tablename in('temp_table_test_systemview','temp_table_test_systemview_pkey') order by tablename; +-- get data after analyze; +select * from pg_gtt_stats where tablename = 'temp_table_test_systemview' order by tablename; + +-- get all object info in current schema +select relname ,relkind, relpersistence, reloptions from pg_class c, pg_namespace n where c.relnamespace = n.oid and n.nspname = 'global_temporary_table' order by relkind,relpersistence,relname; + +reset search_path; +drop schema global_temporary_table cascade; +-- should empty +select * from pg_list_gtt_relfrozenxids(); + -- 2.32.0 (Apple Git-132)