Merge lp:~jaypipes/drizzle/bug534806 into lp:~drizzle-trunk/drizzle/development

Proposed by Jay Pipes
Status: Merged
Merged at revision: not available
Proposed branch: lp:~jaypipes/drizzle/bug534806
Merge into: lp:~drizzle-trunk/drizzle/development
Diff against target: 195 lines (+132/-4)
4 files modified
drizzled/transaction_services.cc (+4/-1)
plugin/innobase/handler/ha_innodb.cc (+0/-3)
tests/r/savepoints.result (+46/-0)
tests/t/savepoints.test (+82/-0)
To merge this branch: bzr merge lp:~jaypipes/drizzle/bug534806
Reviewer Review Type Date Requested Status
Drizzle Developers Pending
Review via email: mp+21101@code.launchpad.net

Description of the change

Fixes bug #534806 (RANDGEN assert in InnobaseEngine::doSetSavepoint()

Manually issue a call to TransactionStorageEngine::startTransaction() inside
TransactionServices::registerResourceForTransaction(). An assert() in the InnoDB
handler was being hit because although startStatement() was properly being
called for an UPDATE ... LIMIT 0, startTransaction() was not called, and because
external_lock() bailed out without committing the transaction, an
assert(conc_state ! TRX_NOT_STARTED) was being hit when a SAVEPOINT A statement
expected the transaction to have been started...

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'drizzled/transaction_services.cc'
2--- drizzled/transaction_services.cc 2010-03-03 20:21:57 +0000
3+++ drizzled/transaction_services.cc 2010-03-11 00:00:46 +0000
4@@ -348,7 +348,6 @@
5
6 session->server_status|= SERVER_STATUS_IN_TRANS;
7
8-
9 trans->registerResource(resource_context);
10
11 assert(monitored->participatesInSqlTransaction());
12@@ -361,6 +360,8 @@
13 if (session->transaction.xid_state.xid.is_null())
14 session->transaction.xid_state.xid.set(session->getQueryId());
15
16+ engine->startTransaction(session, START_TRANS_NO_OPTIONS);
17+
18 /* Only true if user is executing a BEGIN WORK/START TRANSACTION */
19 if (! session->getResourceContext(monitored, 0)->isStarted())
20 registerResourceForStatement(session, monitored, engine);
21@@ -391,6 +392,8 @@
22 if (session->transaction.xid_state.xid.is_null())
23 session->transaction.xid_state.xid.set(session->getQueryId());
24
25+ engine->startTransaction(session, START_TRANS_NO_OPTIONS);
26+
27 /* Only true if user is executing a BEGIN WORK/START TRANSACTION */
28 if (! session->getResourceContext(monitored, 0)->isStarted())
29 registerResourceForStatement(session, monitored, engine, resource_manager);
30
31=== modified file 'plugin/innobase/handler/ha_innodb.cc'
32--- plugin/innobase/handler/ha_innodb.cc 2010-03-05 03:08:42 +0000
33+++ plugin/innobase/handler/ha_innodb.cc 2010-03-11 00:00:46 +0000
34@@ -2323,7 +2323,6 @@
35
36 innobase_release_stat_resources(trx);
37
38- /* TODO: use provided savepoint data area to store savepoint data */
39 error= (int)trx_rollback_to_savepoint_for_mysql(trx, named_savepoint.getName().c_str(),
40 &mysql_binlog_cache_pos);
41 return(convert_error_code_to_mysql(error, 0, NULL));
42@@ -2347,7 +2346,6 @@
43
44 trx = check_trx_exists(session);
45
46- /* TODO: use provided savepoint data area to store savepoint data */
47 error = (int) trx_release_savepoint_for_mysql(trx, named_savepoint.getName().c_str());
48
49 return(convert_error_code_to_mysql(error, 0, NULL));
50@@ -2384,7 +2382,6 @@
51 /* cannot happen outside of transaction */
52 assert(trx->conc_state != TRX_NOT_STARTED);
53
54- /* TODO: use provided savepoint data area to store savepoint data */
55 error = (int) trx_savepoint_for_mysql(trx, named_savepoint.getName().c_str(), (ib_int64_t)0);
56
57 return(convert_error_code_to_mysql(error, 0, NULL));
58
59=== added file 'tests/r/savepoints.result'
60--- tests/r/savepoints.result 1970-01-01 00:00:00 +0000
61+++ tests/r/savepoints.result 2010-03-11 00:00:46 +0000
62@@ -0,0 +1,46 @@
63+SET AUTOCOMMIT = 0;
64+CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY);
65+COMMIT;
66+UPDATE t1 SET id = 2 WHERE id != 2 LIMIT 0;
67+SAVEPOINT A;
68+DROP TABLE t1;
69+CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY);
70+START TRANSACTION;
71+INSERT INTO t1 VALUES (1);
72+SAVEPOINT A;
73+INSERT INTO t1 VALUES (2);
74+SAVEPOINT B;
75+INSERT INTO t1 VALUES (3);
76+COMMIT;
77+SELECT * FROM t1;
78+id
79+1
80+2
81+3
82+START TRANSACTION;
83+INSERT INTO t1 VALUES (4);
84+SAVEPOINT A;
85+INSERT INTO t1 VALUES (5);
86+SAVEPOINT B;
87+INSERT INTO t1 VALUES (6);
88+ROLLBACK;
89+SELECT * FROM t1;
90+id
91+1
92+2
93+3
94+START TRANSACTION;
95+INSERT INTO t1 VALUES (4);
96+SAVEPOINT A;
97+INSERT INTO t1 VALUES (5);
98+SAVEPOINT B;
99+INSERT INTO t1 VALUES (6);
100+ROLLBACK TO SAVEPOINT A;
101+COMMIT;
102+SELECT * FROM t1;
103+id
104+1
105+2
106+3
107+4
108+DROP TABLE t1;
109
110=== added file 'tests/t/savepoints.test'
111--- tests/t/savepoints.test 1970-01-01 00:00:00 +0000
112+++ tests/t/savepoints.test 2010-03-11 00:00:46 +0000
113@@ -0,0 +1,82 @@
114+# Tests of various SAVEPOINT functionality
115+
116+# Test for Bug #534806 - SAVEPOINT without active transaction
117+# triggers assert in InnoDB handler
118+
119+SET AUTOCOMMIT = 0;
120+CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY);
121+COMMIT;
122+UPDATE t1 SET id = 2 WHERE id != 2 LIMIT 0;
123+SAVEPOINT A;
124+
125+DROP TABLE t1;
126+
127+# Let's test the non-edge case for SAVEPOINTS:
128+#
129+# Typical usage pattern of starting a transaction, doing
130+# some work, savepointing, do more work, savepointing, etc
131+# and committing without any rollbacks or savepoint releases.
132+
133+CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY);
134+
135+START TRANSACTION;
136+
137+INSERT INTO t1 VALUES (1);
138+
139+SAVEPOINT A;
140+
141+INSERT INTO t1 VALUES (2);
142+
143+SAVEPOINT B;
144+
145+INSERT INTO t1 VALUES (3);
146+
147+COMMIT;
148+
149+# t1 should now have 1,2,3 in it.
150+SELECT * FROM t1;
151+
152+# We now test another typical usage pattern, similar to above,
153+# but we issue a ROLLBACK at the end instead of a COMMIT. All
154+# work done in all savepoints should be rolled back.
155+
156+START TRANSACTION;
157+
158+INSERT INTO t1 VALUES (4);
159+
160+SAVEPOINT A;
161+
162+INSERT INTO t1 VALUES (5);
163+
164+SAVEPOINT B;
165+
166+INSERT INTO t1 VALUES (6);
167+
168+ROLLBACK;
169+
170+# t1 should still have 1,2,3 in it.
171+SELECT * FROM t1;
172+
173+# We now test the final typical usage pattern, where we
174+# ROLLBACK work to a specific SAVEPOINT and then COMMIT.
175+
176+START TRANSACTION;
177+
178+INSERT INTO t1 VALUES (4);
179+
180+SAVEPOINT A;
181+
182+INSERT INTO t1 VALUES (5);
183+
184+SAVEPOINT B;
185+
186+INSERT INTO t1 VALUES (6);
187+
188+ROLLBACK TO SAVEPOINT A;
189+
190+COMMIT;
191+
192+# t1 should have 1,2,3,4 in it.
193+SELECT * FROM t1;
194+
195+DROP TABLE t1;