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
=== modified file 'drizzled/transaction_services.cc'
--- drizzled/transaction_services.cc 2010-03-03 20:21:57 +0000
+++ drizzled/transaction_services.cc 2010-03-11 00:00:46 +0000
@@ -348,7 +348,6 @@
348348
349 session->server_status|= SERVER_STATUS_IN_TRANS;349 session->server_status|= SERVER_STATUS_IN_TRANS;
350350
351
352 trans->registerResource(resource_context);351 trans->registerResource(resource_context);
353352
354 assert(monitored->participatesInSqlTransaction());353 assert(monitored->participatesInSqlTransaction());
@@ -361,6 +360,8 @@
361 if (session->transaction.xid_state.xid.is_null())360 if (session->transaction.xid_state.xid.is_null())
362 session->transaction.xid_state.xid.set(session->getQueryId());361 session->transaction.xid_state.xid.set(session->getQueryId());
363362
363 engine->startTransaction(session, START_TRANS_NO_OPTIONS);
364
364 /* Only true if user is executing a BEGIN WORK/START TRANSACTION */365 /* Only true if user is executing a BEGIN WORK/START TRANSACTION */
365 if (! session->getResourceContext(monitored, 0)->isStarted())366 if (! session->getResourceContext(monitored, 0)->isStarted())
366 registerResourceForStatement(session, monitored, engine);367 registerResourceForStatement(session, monitored, engine);
@@ -391,6 +392,8 @@
391 if (session->transaction.xid_state.xid.is_null())392 if (session->transaction.xid_state.xid.is_null())
392 session->transaction.xid_state.xid.set(session->getQueryId());393 session->transaction.xid_state.xid.set(session->getQueryId());
393394
395 engine->startTransaction(session, START_TRANS_NO_OPTIONS);
396
394 /* Only true if user is executing a BEGIN WORK/START TRANSACTION */397 /* Only true if user is executing a BEGIN WORK/START TRANSACTION */
395 if (! session->getResourceContext(monitored, 0)->isStarted())398 if (! session->getResourceContext(monitored, 0)->isStarted())
396 registerResourceForStatement(session, monitored, engine, resource_manager);399 registerResourceForStatement(session, monitored, engine, resource_manager);
397400
=== modified file 'plugin/innobase/handler/ha_innodb.cc'
--- plugin/innobase/handler/ha_innodb.cc 2010-03-05 03:08:42 +0000
+++ plugin/innobase/handler/ha_innodb.cc 2010-03-11 00:00:46 +0000
@@ -2323,7 +2323,6 @@
23232323
2324 innobase_release_stat_resources(trx);2324 innobase_release_stat_resources(trx);
23252325
2326 /* TODO: use provided savepoint data area to store savepoint data */
2327 error= (int)trx_rollback_to_savepoint_for_mysql(trx, named_savepoint.getName().c_str(),2326 error= (int)trx_rollback_to_savepoint_for_mysql(trx, named_savepoint.getName().c_str(),
2328 &mysql_binlog_cache_pos);2327 &mysql_binlog_cache_pos);
2329 return(convert_error_code_to_mysql(error, 0, NULL));2328 return(convert_error_code_to_mysql(error, 0, NULL));
@@ -2347,7 +2346,6 @@
23472346
2348 trx = check_trx_exists(session);2347 trx = check_trx_exists(session);
23492348
2350 /* TODO: use provided savepoint data area to store savepoint data */
2351 error = (int) trx_release_savepoint_for_mysql(trx, named_savepoint.getName().c_str());2349 error = (int) trx_release_savepoint_for_mysql(trx, named_savepoint.getName().c_str());
23522350
2353 return(convert_error_code_to_mysql(error, 0, NULL));2351 return(convert_error_code_to_mysql(error, 0, NULL));
@@ -2384,7 +2382,6 @@
2384 /* cannot happen outside of transaction */2382 /* cannot happen outside of transaction */
2385 assert(trx->conc_state != TRX_NOT_STARTED);2383 assert(trx->conc_state != TRX_NOT_STARTED);
23862384
2387 /* TODO: use provided savepoint data area to store savepoint data */
2388 error = (int) trx_savepoint_for_mysql(trx, named_savepoint.getName().c_str(), (ib_int64_t)0);2385 error = (int) trx_savepoint_for_mysql(trx, named_savepoint.getName().c_str(), (ib_int64_t)0);
23892386
2390 return(convert_error_code_to_mysql(error, 0, NULL));2387 return(convert_error_code_to_mysql(error, 0, NULL));
23912388
=== added file 'tests/r/savepoints.result'
--- tests/r/savepoints.result 1970-01-01 00:00:00 +0000
+++ tests/r/savepoints.result 2010-03-11 00:00:46 +0000
@@ -0,0 +1,46 @@
1SET AUTOCOMMIT = 0;
2CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY);
3COMMIT;
4UPDATE t1 SET id = 2 WHERE id != 2 LIMIT 0;
5SAVEPOINT A;
6DROP TABLE t1;
7CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY);
8START TRANSACTION;
9INSERT INTO t1 VALUES (1);
10SAVEPOINT A;
11INSERT INTO t1 VALUES (2);
12SAVEPOINT B;
13INSERT INTO t1 VALUES (3);
14COMMIT;
15SELECT * FROM t1;
16id
171
182
193
20START TRANSACTION;
21INSERT INTO t1 VALUES (4);
22SAVEPOINT A;
23INSERT INTO t1 VALUES (5);
24SAVEPOINT B;
25INSERT INTO t1 VALUES (6);
26ROLLBACK;
27SELECT * FROM t1;
28id
291
302
313
32START TRANSACTION;
33INSERT INTO t1 VALUES (4);
34SAVEPOINT A;
35INSERT INTO t1 VALUES (5);
36SAVEPOINT B;
37INSERT INTO t1 VALUES (6);
38ROLLBACK TO SAVEPOINT A;
39COMMIT;
40SELECT * FROM t1;
41id
421
432
443
454
46DROP TABLE t1;
047
=== added file 'tests/t/savepoints.test'
--- tests/t/savepoints.test 1970-01-01 00:00:00 +0000
+++ tests/t/savepoints.test 2010-03-11 00:00:46 +0000
@@ -0,0 +1,82 @@
1# Tests of various SAVEPOINT functionality
2
3# Test for Bug #534806 - SAVEPOINT without active transaction
4# triggers assert in InnoDB handler
5
6SET AUTOCOMMIT = 0;
7CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY);
8COMMIT;
9UPDATE t1 SET id = 2 WHERE id != 2 LIMIT 0;
10SAVEPOINT A;
11
12DROP TABLE t1;
13
14# Let's test the non-edge case for SAVEPOINTS:
15#
16# Typical usage pattern of starting a transaction, doing
17# some work, savepointing, do more work, savepointing, etc
18# and committing without any rollbacks or savepoint releases.
19
20CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY);
21
22START TRANSACTION;
23
24INSERT INTO t1 VALUES (1);
25
26SAVEPOINT A;
27
28INSERT INTO t1 VALUES (2);
29
30SAVEPOINT B;
31
32INSERT INTO t1 VALUES (3);
33
34COMMIT;
35
36# t1 should now have 1,2,3 in it.
37SELECT * FROM t1;
38
39# We now test another typical usage pattern, similar to above,
40# but we issue a ROLLBACK at the end instead of a COMMIT. All
41# work done in all savepoints should be rolled back.
42
43START TRANSACTION;
44
45INSERT INTO t1 VALUES (4);
46
47SAVEPOINT A;
48
49INSERT INTO t1 VALUES (5);
50
51SAVEPOINT B;
52
53INSERT INTO t1 VALUES (6);
54
55ROLLBACK;
56
57# t1 should still have 1,2,3 in it.
58SELECT * FROM t1;
59
60# We now test the final typical usage pattern, where we
61# ROLLBACK work to a specific SAVEPOINT and then COMMIT.
62
63START TRANSACTION;
64
65INSERT INTO t1 VALUES (4);
66
67SAVEPOINT A;
68
69INSERT INTO t1 VALUES (5);
70
71SAVEPOINT B;
72
73INSERT INTO t1 VALUES (6);
74
75ROLLBACK TO SAVEPOINT A;
76
77COMMIT;
78
79# t1 should have 1,2,3,4 in it.
80SELECT * FROM t1;
81
82DROP TABLE t1;