mirror of
https://github.com/postgres/postgres.git
synced 2025-06-11 20:28:21 +03:00
Detect unused steps in isolation specs and do some cleanup
This is useful for developers to find out if an isolation spec is over-engineered or if it needs more work by warning at the end of a test run if a step is not used, generating a failure with extra diffs. While on it, clean up all the specs which include steps not used in any permutations to simplify them. This is a backpatch of989d23b
and06fdc4e
, as it is becoming useful to make all the branches consistent for an upcoming patch that will improve the output generated by isolationtester. Author: Michael Paquier Reviewed-by: Asim Praveen, Melanie Plageman Discussion: https://postgr.es/m/20190819080820.GG18166@paquier.xyz Discussion: https://postgr.es/m/794820.1623872009@sss.pgh.pa.us Backpatch-through: 9.6
This commit is contained in:
@ -19,7 +19,6 @@ setup { SET synchronous_commit=on; }
|
|||||||
step "s1_init" { SELECT 'init' FROM pg_create_logical_replication_slot('isolation_slot', 'test_decoding'); }
|
step "s1_init" { SELECT 'init' FROM pg_create_logical_replication_slot('isolation_slot', 'test_decoding'); }
|
||||||
step "s1_begin" { BEGIN; }
|
step "s1_begin" { BEGIN; }
|
||||||
step "s1_insert_tbl1" { INSERT INTO tbl1 (val1, val2) VALUES (1, 1); }
|
step "s1_insert_tbl1" { INSERT INTO tbl1 (val1, val2) VALUES (1, 1); }
|
||||||
step "s1_insert_tbl1_3col" { INSERT INTO tbl1 (val1, val2, val3) VALUES (1, 1, 1); }
|
|
||||||
step "s1_insert_tbl2" { INSERT INTO tbl2 (val1, val2) VALUES (1, 1); }
|
step "s1_insert_tbl2" { INSERT INTO tbl2 (val1, val2) VALUES (1, 1); }
|
||||||
step "s1_insert_tbl2_3col" { INSERT INTO tbl2 (val1, val2, val3) VALUES (1, 1, 1); }
|
step "s1_insert_tbl2_3col" { INSERT INTO tbl2 (val1, val2, val3) VALUES (1, 1, 1); }
|
||||||
step "s1_commit" { COMMIT; }
|
step "s1_commit" { COMMIT; }
|
||||||
@ -29,15 +28,8 @@ setup { SET synchronous_commit=on; }
|
|||||||
|
|
||||||
step "s2_alter_tbl1_float" { ALTER TABLE tbl1 ALTER COLUMN val2 TYPE float; }
|
step "s2_alter_tbl1_float" { ALTER TABLE tbl1 ALTER COLUMN val2 TYPE float; }
|
||||||
step "s2_alter_tbl1_char" { ALTER TABLE tbl1 ALTER COLUMN val2 TYPE character varying; }
|
step "s2_alter_tbl1_char" { ALTER TABLE tbl1 ALTER COLUMN val2 TYPE character varying; }
|
||||||
step "s2_alter_tbl1_text" { ALTER TABLE tbl1 ALTER COLUMN val2 TYPE text; }
|
|
||||||
step "s2_alter_tbl1_boolean" { ALTER TABLE tbl1 ALTER COLUMN val2 TYPE boolean; }
|
step "s2_alter_tbl1_boolean" { ALTER TABLE tbl1 ALTER COLUMN val2 TYPE boolean; }
|
||||||
|
|
||||||
step "s2_alter_tbl1_add_int" { ALTER TABLE tbl1 ADD COLUMN val3 INTEGER; }
|
|
||||||
step "s2_alter_tbl1_add_float" { ALTER TABLE tbl1 ADD COLUMN val3 FLOAT; }
|
|
||||||
step "s2_alter_tbl1_add_char" { ALTER TABLE tbl1 ADD COLUMN val3 character varying; }
|
|
||||||
step "s2_alter_tbl1_add_boolean" { ALTER TABLE tbl1 ADD COLUMN val3 BOOLEAN; }
|
|
||||||
step "s2_alter_tbl1_add_text" { ALTER TABLE tbl1 ADD COLUMN val3 TEXT; }
|
|
||||||
|
|
||||||
step "s2_alter_tbl2_float" { ALTER TABLE tbl2 ALTER COLUMN val2 TYPE float; }
|
step "s2_alter_tbl2_float" { ALTER TABLE tbl2 ALTER COLUMN val2 TYPE float; }
|
||||||
step "s2_alter_tbl2_char" { ALTER TABLE tbl2 ALTER COLUMN val2 TYPE character varying; }
|
step "s2_alter_tbl2_char" { ALTER TABLE tbl2 ALTER COLUMN val2 TYPE character varying; }
|
||||||
step "s2_alter_tbl2_text" { ALTER TABLE tbl2 ALTER COLUMN val2 TYPE text; }
|
step "s2_alter_tbl2_text" { ALTER TABLE tbl2 ALTER COLUMN val2 TYPE text; }
|
||||||
@ -46,7 +38,6 @@ step "s2_alter_tbl2_boolean" { ALTER TABLE tbl2 ALTER COLUMN val2 TYPE boolean;
|
|||||||
step "s2_alter_tbl2_add_int" { ALTER TABLE tbl2 ADD COLUMN val3 INTEGER; }
|
step "s2_alter_tbl2_add_int" { ALTER TABLE tbl2 ADD COLUMN val3 INTEGER; }
|
||||||
step "s2_alter_tbl2_add_float" { ALTER TABLE tbl2 ADD COLUMN val3 FLOAT; }
|
step "s2_alter_tbl2_add_float" { ALTER TABLE tbl2 ADD COLUMN val3 FLOAT; }
|
||||||
step "s2_alter_tbl2_add_char" { ALTER TABLE tbl2 ADD COLUMN val3 character varying; }
|
step "s2_alter_tbl2_add_char" { ALTER TABLE tbl2 ADD COLUMN val3 character varying; }
|
||||||
step "s2_alter_tbl2_add_boolean" { ALTER TABLE tbl2 ADD COLUMN val3 BOOLEAN; }
|
|
||||||
step "s2_alter_tbl2_add_text" { ALTER TABLE tbl2 ADD COLUMN val3 TEXT; }
|
step "s2_alter_tbl2_add_text" { ALTER TABLE tbl2 ADD COLUMN val3 TEXT; }
|
||||||
step "s2_alter_tbl2_drop_3rd_col" { ALTER TABLE tbl2 DROP COLUMN val3; }
|
step "s2_alter_tbl2_drop_3rd_col" { ALTER TABLE tbl2 DROP COLUMN val3; }
|
||||||
step "s2_alter_tbl2_3rd_char" { ALTER TABLE tbl2 ALTER COLUMN val3 TYPE character varying; }
|
step "s2_alter_tbl2_3rd_char" { ALTER TABLE tbl2 ALTER COLUMN val3 TYPE character varying; }
|
||||||
|
@ -25,7 +25,6 @@ step "s0_sub_get_base_snap" { INSERT INTO dummy VALUES (0); }
|
|||||||
step "s0_insert" { INSERT INTO harvest VALUES (1, 2, 3); }
|
step "s0_insert" { INSERT INTO harvest VALUES (1, 2, 3); }
|
||||||
step "s0_end_sub0" { RELEASE SAVEPOINT s0; }
|
step "s0_end_sub0" { RELEASE SAVEPOINT s0; }
|
||||||
step "s0_end_sub1" { RELEASE SAVEPOINT s1; }
|
step "s0_end_sub1" { RELEASE SAVEPOINT s1; }
|
||||||
step "s0_insert2" { INSERT INTO harvest VALUES (1, 2, 3, 4); }
|
|
||||||
step "s0_commit" { COMMIT; }
|
step "s0_commit" { COMMIT; }
|
||||||
step "s0_get_changes" { SELECT data FROM pg_logical_slot_get_changes('isolation_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1'); }
|
step "s0_get_changes" { SELECT data FROM pg_logical_slot_get_changes('isolation_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1'); }
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Parsed test spec with 4 sessions
|
Parsed test spec with 3 sessions
|
||||||
|
|
||||||
starting permutation: s1_trig_rep_b_u s1_trig_rep_a_u s1_ins_a s1_ins_b s1_b_rc s2_b_rc s1_upd_a_data s1_c s2_upd_a_data s2_c s0_rep
|
starting permutation: s1_trig_rep_b_u s1_trig_rep_a_u s1_ins_a s1_ins_b s1_b_rc s2_b_rc s1_upd_a_data s1_c s2_upd_a_data s2_c s0_rep
|
||||||
step s1_trig_rep_b_u: CREATE TRIGGER rep_b_u BEFORE UPDATE ON trigtest FOR EACH ROW EXECUTE PROCEDURE trig_report();
|
step s1_trig_rep_b_u: CREATE TRIGGER rep_b_u BEFORE UPDATE ON trigtest FOR EACH ROW EXECUTE PROCEDURE trig_report();
|
||||||
|
@ -88,7 +88,7 @@ main(int argc, char **argv)
|
|||||||
puts("isolationtester (PostgreSQL) " PG_VERSION);
|
puts("isolationtester (PostgreSQL) " PG_VERSION);
|
||||||
exit(0);
|
exit(0);
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Usage: isolationtester [-n] [CONNINFO]\n");
|
fprintf(stderr, "Usage: isolationtester [CONNINFO]\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -252,10 +252,23 @@ static int *piles;
|
|||||||
static void
|
static void
|
||||||
run_testspec(TestSpec *testspec)
|
run_testspec(TestSpec *testspec)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
if (testspec->permutations)
|
if (testspec->permutations)
|
||||||
run_named_permutations(testspec);
|
run_named_permutations(testspec);
|
||||||
else
|
else
|
||||||
run_all_permutations(testspec);
|
run_all_permutations(testspec);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify that all steps have been used, complaining about anything
|
||||||
|
* defined but not used.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < testspec->nallsteps; i++)
|
||||||
|
{
|
||||||
|
if (!testspec->allsteps[i]->used)
|
||||||
|
fprintf(stderr, "unused step name: %s\n",
|
||||||
|
testspec->allsteps[i]->name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -455,7 +468,11 @@ run_permutation(TestSpec *testspec, int nsteps, Step **steps)
|
|||||||
|
|
||||||
printf("\nstarting permutation:");
|
printf("\nstarting permutation:");
|
||||||
for (i = 0; i < nsteps; i++)
|
for (i = 0; i < nsteps; i++)
|
||||||
|
{
|
||||||
|
/* Track the permutation as in-use */
|
||||||
|
steps[i]->used = true;
|
||||||
printf(" %s", steps[i]->name);
|
printf(" %s", steps[i]->name);
|
||||||
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
/* Perform setup */
|
/* Perform setup */
|
||||||
|
@ -29,6 +29,7 @@ struct Session
|
|||||||
struct Step
|
struct Step
|
||||||
{
|
{
|
||||||
int session;
|
int session;
|
||||||
|
bool used;
|
||||||
char *name;
|
char *name;
|
||||||
char *sql;
|
char *sql;
|
||||||
char *errormsg;
|
char *errormsg;
|
||||||
|
@ -145,6 +145,7 @@ step:
|
|||||||
$$ = pg_malloc(sizeof(Step));
|
$$ = pg_malloc(sizeof(Step));
|
||||||
$$->name = $2;
|
$$->name = $2;
|
||||||
$$->sql = $3;
|
$$->sql = $3;
|
||||||
|
$$->used = false;
|
||||||
$$->errormsg = NULL;
|
$$->errormsg = NULL;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
@ -113,7 +113,7 @@ session "s2"
|
|||||||
step "s2_b_rc" { BEGIN ISOLATION LEVEL READ COMMITTED; SELECT 1; }
|
step "s2_b_rc" { BEGIN ISOLATION LEVEL READ COMMITTED; SELECT 1; }
|
||||||
step "s2_b_rr" { BEGIN ISOLATION LEVEL REPEATABLE READ; SELECT 1; }
|
step "s2_b_rr" { BEGIN ISOLATION LEVEL REPEATABLE READ; SELECT 1; }
|
||||||
step "s2_c" { COMMIT; }
|
step "s2_c" { COMMIT; }
|
||||||
step "s2_r" { ROLLBACK; }
|
#step "s2_r" { ROLLBACK; }
|
||||||
step "s2_ins_a" { INSERT INTO trigtest VALUES ('key-a', 'val-a-s2') RETURNING *; }
|
step "s2_ins_a" { INSERT INTO trigtest VALUES ('key-a', 'val-a-s2') RETURNING *; }
|
||||||
step "s2_del_a" {
|
step "s2_del_a" {
|
||||||
DELETE FROM trigtest
|
DELETE FROM trigtest
|
||||||
@ -153,25 +153,25 @@ step "s2_upsert_a_data" {
|
|||||||
RETURNING *;
|
RETURNING *;
|
||||||
}
|
}
|
||||||
|
|
||||||
session "s3"
|
#session "s3"
|
||||||
#setup { }
|
#setup { }
|
||||||
step "s3_b_rc" { BEGIN ISOLATION LEVEL READ COMMITTED; SELECT 1; }
|
#step "s3_b_rc" { BEGIN ISOLATION LEVEL READ COMMITTED; SELECT 1; }
|
||||||
step "s3_c" { COMMIT; }
|
#step "s3_c" { COMMIT; }
|
||||||
step "s3_r" { ROLLBACK; }
|
#step "s3_r" { ROLLBACK; }
|
||||||
step "s3_del_a" {
|
#step "s3_del_a" {
|
||||||
DELETE FROM trigtest
|
# DELETE FROM trigtest
|
||||||
WHERE
|
# WHERE
|
||||||
noisy_oper('upd', key, '=', 'key-a') AND
|
# noisy_oper('upd', key, '=', 'key-a') AND
|
||||||
noisy_oper('upk', data, '<>', 'mismatch')
|
# noisy_oper('upk', data, '<>', 'mismatch')
|
||||||
RETURNING *
|
# RETURNING *
|
||||||
}
|
#}
|
||||||
step "s3_upd_a_data" {
|
#step "s3_upd_a_data" {
|
||||||
UPDATE trigtest SET data = data || '-ups3'
|
# UPDATE trigtest SET data = data || '-ups3'
|
||||||
WHERE
|
# WHERE
|
||||||
noisy_oper('upd', key, '=', 'key-a') AND
|
# noisy_oper('upd', key, '=', 'key-a') AND
|
||||||
noisy_oper('upk', data, '<>', 'mismatch')
|
# noisy_oper('upk', data, '<>', 'mismatch')
|
||||||
RETURNING *;
|
# RETURNING *;
|
||||||
}
|
#}
|
||||||
|
|
||||||
### base case verifying that triggers see performed modifications
|
### base case verifying that triggers see performed modifications
|
||||||
# s1 updates, s1 commits, s2 updates
|
# s1 updates, s1 commits, s2 updates
|
||||||
|
@ -19,7 +19,6 @@ session "s1"
|
|||||||
step "s1_begin" { BEGIN; }
|
step "s1_begin" { BEGIN; }
|
||||||
step "s1_update" { UPDATE tab_freeze SET x = x + 1 WHERE id = 3; }
|
step "s1_update" { UPDATE tab_freeze SET x = x + 1 WHERE id = 3; }
|
||||||
step "s1_commit" { COMMIT; }
|
step "s1_commit" { COMMIT; }
|
||||||
step "s1_vacuum" { VACUUM FREEZE tab_freeze; }
|
|
||||||
step "s1_selectone" {
|
step "s1_selectone" {
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SET LOCAL enable_seqscan = false;
|
SET LOCAL enable_seqscan = false;
|
||||||
@ -28,7 +27,6 @@ step "s1_selectone" {
|
|||||||
COMMIT;
|
COMMIT;
|
||||||
}
|
}
|
||||||
step "s1_selectall" { SELECT * FROM tab_freeze ORDER BY name, id; }
|
step "s1_selectall" { SELECT * FROM tab_freeze ORDER BY name, id; }
|
||||||
step "s1_reindex" { REINDEX TABLE tab_freeze; }
|
|
||||||
|
|
||||||
session "s2"
|
session "s2"
|
||||||
step "s2_begin" { BEGIN; }
|
step "s2_begin" { BEGIN; }
|
||||||
@ -40,7 +38,6 @@ session "s3"
|
|||||||
step "s3_begin" { BEGIN; }
|
step "s3_begin" { BEGIN; }
|
||||||
step "s3_key_share" { SELECT id FROM tab_freeze WHERE id = 3 FOR KEY SHARE; }
|
step "s3_key_share" { SELECT id FROM tab_freeze WHERE id = 3 FOR KEY SHARE; }
|
||||||
step "s3_commit" { COMMIT; }
|
step "s3_commit" { COMMIT; }
|
||||||
step "s3_vacuum" { VACUUM FREEZE tab_freeze; }
|
|
||||||
|
|
||||||
# This permutation verfies that a previous bug
|
# This permutation verfies that a previous bug
|
||||||
# https://postgr.es/m/E5711E62-8FDF-4DCA-A888-C200BF6B5742@amazon.com
|
# https://postgr.es/m/E5711E62-8FDF-4DCA-A888-C200BF6B5742@amazon.com
|
||||||
|
@ -33,7 +33,6 @@ setup
|
|||||||
step "donothing2" { INSERT INTO ints(key, val) VALUES(1, 'donothing2') ON CONFLICT DO NOTHING; }
|
step "donothing2" { INSERT INTO ints(key, val) VALUES(1, 'donothing2') ON CONFLICT DO NOTHING; }
|
||||||
step "select2" { SELECT * FROM ints; }
|
step "select2" { SELECT * FROM ints; }
|
||||||
step "c2" { COMMIT; }
|
step "c2" { COMMIT; }
|
||||||
step "a2" { ABORT; }
|
|
||||||
|
|
||||||
# Regular case where one session block-waits on another to determine if it
|
# Regular case where one session block-waits on another to determine if it
|
||||||
# should proceed with an insert or do nothing.
|
# should proceed with an insert or do nothing.
|
||||||
|
@ -32,7 +32,6 @@ setup
|
|||||||
step "insert2" { INSERT INTO upsert(key, payload) VALUES('FOOFOO', 'insert2') ON CONFLICT (lower(key)) DO UPDATE set key = EXCLUDED.key, payload = upsert.payload || ' updated by insert2'; }
|
step "insert2" { INSERT INTO upsert(key, payload) VALUES('FOOFOO', 'insert2') ON CONFLICT (lower(key)) DO UPDATE set key = EXCLUDED.key, payload = upsert.payload || ' updated by insert2'; }
|
||||||
step "select2" { SELECT * FROM upsert; }
|
step "select2" { SELECT * FROM upsert; }
|
||||||
step "c2" { COMMIT; }
|
step "c2" { COMMIT; }
|
||||||
step "a2" { ABORT; }
|
|
||||||
|
|
||||||
# One session (session 2) block-waits on another (session 1) to determine if it
|
# One session (session 2) block-waits on another (session 1) to determine if it
|
||||||
# should proceed with an insert or update. The user can still usefully UPDATE
|
# should proceed with an insert or update. The user can still usefully UPDATE
|
||||||
|
@ -30,7 +30,6 @@ setup
|
|||||||
step "insert2" { INSERT INTO upsert(key, val) VALUES(1, 'insert2') ON CONFLICT (key) DO UPDATE set val = upsert.val || ' updated by insert2'; }
|
step "insert2" { INSERT INTO upsert(key, val) VALUES(1, 'insert2') ON CONFLICT (key) DO UPDATE set val = upsert.val || ' updated by insert2'; }
|
||||||
step "select2" { SELECT * FROM upsert; }
|
step "select2" { SELECT * FROM upsert; }
|
||||||
step "c2" { COMMIT; }
|
step "c2" { COMMIT; }
|
||||||
step "a2" { ABORT; }
|
|
||||||
|
|
||||||
# One session (session 2) block-waits on another (session 1) to determine if it
|
# One session (session 2) block-waits on another (session 1) to determine if it
|
||||||
# should proceed with an insert or update. Notably, this entails updating a
|
# should proceed with an insert or update. Notably, this entails updating a
|
||||||
|
@ -57,7 +57,6 @@ step "s1r" { ROLLBACK; }
|
|||||||
|
|
||||||
session "s2"
|
session "s2"
|
||||||
step "s2b" { BEGIN ISOLATION LEVEL READ COMMITTED; }
|
step "s2b" { BEGIN ISOLATION LEVEL READ COMMITTED; }
|
||||||
step "s2u" { UPDATE foo SET b='EFG' WHERE a=1; }
|
|
||||||
step "s2u2" { UPDATE footrg SET b='XYZ' WHERE a=1; }
|
step "s2u2" { UPDATE footrg SET b='XYZ' WHERE a=1; }
|
||||||
step "s2i" { INSERT INTO bar VALUES(7); }
|
step "s2i" { INSERT INTO bar VALUES(7); }
|
||||||
step "s2d" { DELETE FROM foo WHERE a=1; }
|
step "s2d" { DELETE FROM foo WHERE a=1; }
|
||||||
|
@ -15,7 +15,6 @@ setup { BEGIN; }
|
|||||||
step "s1alter" { ALTER SEQUENCE seq1 MAXVALUE 10; }
|
step "s1alter" { ALTER SEQUENCE seq1 MAXVALUE 10; }
|
||||||
step "s1alter2" { ALTER SEQUENCE seq1 MAXVALUE 20; }
|
step "s1alter2" { ALTER SEQUENCE seq1 MAXVALUE 20; }
|
||||||
step "s1restart" { ALTER SEQUENCE seq1 RESTART WITH 5; }
|
step "s1restart" { ALTER SEQUENCE seq1 RESTART WITH 5; }
|
||||||
step "s1setval" { SELECT setval('seq1', 5); }
|
|
||||||
step "s1commit" { COMMIT; }
|
step "s1commit" { COMMIT; }
|
||||||
|
|
||||||
session "s2"
|
session "s2"
|
||||||
|
@ -19,7 +19,6 @@ teardown
|
|||||||
session "s0"
|
session "s0"
|
||||||
step "s0_begin" { begin; }
|
step "s0_begin" { begin; }
|
||||||
step "s0_keyshare" { select id from tlu_job where id = 1 for key share;}
|
step "s0_keyshare" { select id from tlu_job where id = 1 for key share;}
|
||||||
step "s0_share" { select id from tlu_job where id = 1 for share;}
|
|
||||||
step "s0_rollback" { rollback; }
|
step "s0_rollback" { rollback; }
|
||||||
|
|
||||||
session "s1"
|
session "s1"
|
||||||
@ -28,7 +27,6 @@ step "s1_keyshare" { select id from tlu_job where id = 1 for key share;}
|
|||||||
step "s1_share" { select id from tlu_job where id = 1 for share; }
|
step "s1_share" { select id from tlu_job where id = 1 for share; }
|
||||||
step "s1_fornokeyupd" { select id from tlu_job where id = 1 for no key update; }
|
step "s1_fornokeyupd" { select id from tlu_job where id = 1 for no key update; }
|
||||||
step "s1_update" { update tlu_job set name = 'b' where id = 1; }
|
step "s1_update" { update tlu_job set name = 'b' where id = 1; }
|
||||||
step "s1_delete" { delete from tlu_job where id = 1; }
|
|
||||||
step "s1_savept_e" { savepoint s1_e; }
|
step "s1_savept_e" { savepoint s1_e; }
|
||||||
step "s1_savept_f" { savepoint s1_f; }
|
step "s1_savept_f" { savepoint s1_f; }
|
||||||
step "s1_rollback_e" { rollback to s1_e; }
|
step "s1_rollback_e" { rollback to s1_e; }
|
||||||
@ -44,7 +42,6 @@ step "s2_for_update" { select id from tlu_job where id = 1 for update; }
|
|||||||
step "s2_update" { update tlu_job set name = 'b' where id = 1; }
|
step "s2_update" { update tlu_job set name = 'b' where id = 1; }
|
||||||
step "s2_delete" { delete from tlu_job where id = 1; }
|
step "s2_delete" { delete from tlu_job where id = 1; }
|
||||||
step "s2_rollback" { rollback; }
|
step "s2_rollback" { rollback; }
|
||||||
step "s2_commit" { commit; }
|
|
||||||
|
|
||||||
session "s3"
|
session "s3"
|
||||||
setup { begin; }
|
setup { begin; }
|
||||||
|
Reference in New Issue
Block a user