Merge lp:~stewart/drizzle/embedded-innodb-select-for-update into lp:~drizzle-trunk/drizzle/development

Proposed by Stewart Smith
Status: Merged
Approved by: Brian Aker
Approved revision: 1515
Merged at revision: 1711
Proposed branch: lp:~stewart/drizzle/embedded-innodb-select-for-update
Merge into: lp:~drizzle-trunk/drizzle/development
Prerequisite: lp:~stewart/drizzle/embedded-innodb-sec-index-prev
Diff against target: 331 lines (+207/-4)
8 files modified
plugin/embedded_innodb/embedded_innodb_engine.cc (+115/-4)
plugin/embedded_innodb/embedded_innodb_engine.h (+2/-0)
plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/r/basic_select_for_update.result (+17/-0)
plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/r/basic_select_for_update_pk_index.result (+17/-0)
plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/t/basic_select_for_update-master.opt (+1/-0)
plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/t/basic_select_for_update.test (+27/-0)
plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/t/basic_select_for_update_pk_index-master.opt (+1/-0)
plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/t/basic_select_for_update_pk_index.test (+27/-0)
To merge this branch: bzr merge lp:~stewart/drizzle/embedded-innodb-select-for-update
Reviewer Review Type Date Requested Status
Drizzle Developers Pending
Brian Aker Pending
Review via email: mp+32425@code.launchpad.net

Description of the change

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 'plugin/embedded_innodb/embedded_innodb_engine.cc'
2--- plugin/embedded_innodb/embedded_innodb_engine.cc 2010-08-12 06:37:45 +0000
3+++ plugin/embedded_innodb/embedded_innodb_engine.cc 2010-08-12 06:37:46 +0000
4@@ -231,6 +231,90 @@
5 return (ib_trx_t*) session->getEngineData(embedded_innodb_engine);
6 }
7
8+/* This is a superset of the map from innobase plugin.
9+ Unlike innobase plugin we don't act on errors here, we just
10+ map error codes. */
11+static int ib_err_t_to_drizzle_error(ib_err_t err)
12+{
13+ switch (err)
14+ {
15+ case DB_SUCCESS:
16+ return 0;
17+
18+ case DB_ERROR:
19+ default:
20+ return -1;
21+
22+ case DB_INTERRUPTED:
23+ return ER_QUERY_INTERRUPTED; // FIXME: is this correct?
24+
25+ case DB_OUT_OF_MEMORY:
26+ return HA_ERR_OUT_OF_MEM;
27+
28+ case DB_DUPLICATE_KEY:
29+ return HA_ERR_FOUND_DUPP_KEY;
30+
31+ case DB_FOREIGN_DUPLICATE_KEY:
32+ return HA_ERR_FOREIGN_DUPLICATE_KEY;
33+
34+ case DB_MISSING_HISTORY:
35+ return HA_ERR_TABLE_DEF_CHANGED;
36+
37+ case DB_RECORD_NOT_FOUND:
38+ return HA_ERR_NO_ACTIVE_RECORD;
39+
40+ case DB_DEADLOCK:
41+ return HA_ERR_LOCK_DEADLOCK;
42+
43+ case DB_LOCK_WAIT_TIMEOUT:
44+ return HA_ERR_LOCK_WAIT_TIMEOUT;
45+
46+ case DB_NO_REFERENCED_ROW:
47+ return HA_ERR_NO_REFERENCED_ROW;
48+
49+ case DB_ROW_IS_REFERENCED:
50+ return HA_ERR_ROW_IS_REFERENCED;
51+
52+ case DB_CANNOT_ADD_CONSTRAINT:
53+ return HA_ERR_CANNOT_ADD_FOREIGN;
54+
55+ case DB_CANNOT_DROP_CONSTRAINT:
56+ return HA_ERR_ROW_IS_REFERENCED; /* misleading. should have new err code */
57+
58+ case DB_COL_APPEARS_TWICE_IN_INDEX:
59+ case DB_CORRUPTION:
60+ return HA_ERR_CRASHED;
61+
62+ case DB_MUST_GET_MORE_FILE_SPACE:
63+ case DB_OUT_OF_FILE_SPACE:
64+ return HA_ERR_RECORD_FILE_FULL;
65+
66+ case DB_TABLE_IS_BEING_USED:
67+ return HA_ERR_WRONG_COMMAND;
68+
69+ case DB_TABLE_NOT_FOUND:
70+ return HA_ERR_NO_SUCH_TABLE;
71+
72+ case DB_TOO_BIG_RECORD:
73+ return HA_ERR_TO_BIG_ROW;
74+
75+ case DB_NO_SAVEPOINT:
76+ return HA_ERR_NO_SAVEPOINT;
77+
78+ case DB_LOCK_TABLE_FULL:
79+ return HA_ERR_LOCK_TABLE_FULL;
80+
81+ case DB_PRIMARY_KEY_IS_NULL:
82+ return ER_PRIMARY_CANT_HAVE_NULL;
83+
84+ case DB_TOO_MANY_CONCURRENT_TRXS:
85+ return HA_ERR_RECORD_FILE_FULL; /* need better error code */
86+
87+ case DB_UNSUPPORTED:
88+ return HA_ERR_UNSUPPORTED;
89+ }
90+}
91+
92 static ib_trx_level_t tx_isolation_to_ib_trx_level(enum_tx_isolation level)
93 {
94 switch(level)
95@@ -630,6 +714,7 @@
96 EmbeddedInnoDBCursor::EmbeddedInnoDBCursor(drizzled::plugin::StorageEngine &engine_arg,
97 TableShare &table_arg)
98 :Cursor(engine_arg, table_arg),
99+ ib_lock_mode(IB_LOCK_NONE),
100 write_can_replace(false),
101 blobroot(NULL)
102 { }
103@@ -684,7 +769,14 @@
104 ib_cursor_stmt_begin(cursor);
105
106 (void)session;
107- (void)lock_type;
108+
109+ if (lock_type == F_WRLCK)
110+ {
111+ /* SELECT ... FOR UPDATE or UPDATE TABLE */
112+ ib_lock_mode= IB_LOCK_X;
113+ }
114+ else
115+ ib_lock_mode= IB_LOCK_NONE;
116
117 return 0;
118 }
119@@ -1881,6 +1973,7 @@
120
121 int EmbeddedInnoDBCursor::doStartTableScan(bool)
122 {
123+ ib_err_t err;
124 ib_trx_t transaction;
125
126 if (in_table_scan)
127@@ -1893,14 +1986,21 @@
128
129 ib_cursor_attach_trx(cursor, transaction);
130
131+ err= ib_cursor_set_lock_mode(cursor, ib_lock_mode);
132+ assert(err == DB_SUCCESS); // FIXME
133+
134 tuple= ib_clust_read_tuple_create(cursor);
135
136- ib_err_t err= ib_cursor_first(cursor);
137+ err= ib_cursor_first(cursor);
138 if (err != DB_SUCCESS && err != DB_END_OF_INDEX)
139- return -1; // FIXME
140+ {
141+ previous_error= ib_err_t_to_drizzle_error(err);
142+ return previous_error;
143+ }
144
145 advance_cursor= false;
146
147+ previous_error= 0;
148 return(0);
149 }
150
151@@ -1991,6 +2091,9 @@
152 ib_err_t err;
153 int ret;
154
155+ if (previous_error)
156+ return previous_error;
157+
158 if (advance_cursor)
159 err= ib_cursor_next(cursor);
160
161@@ -2011,6 +2114,7 @@
162 err= ib_cursor_reset(cursor);
163 assert(err == DB_SUCCESS);
164 in_table_scan= false;
165+ previous_error= 0;
166 return 0;
167 }
168
169@@ -2156,6 +2260,7 @@
170 return -1;
171
172 err= ib_cursor_close(cursor);
173+ assert(err == DB_SUCCESS);
174 err= ib_cursor_open_index_using_id(index_id, transaction, &cursor);
175
176 if (err != DB_SUCCESS)
177@@ -2165,6 +2270,9 @@
178 ib_cursor_set_cluster_access(cursor);
179 }
180
181+ ib_err_t err= ib_cursor_set_lock_mode(cursor, ib_lock_mode);
182+ assert(err == DB_SUCCESS);
183+
184 advance_cursor= false;
185 return 0;
186 }
187@@ -2305,7 +2413,10 @@
188 return HA_ERR_KEY_NOT_FOUND;
189 }
190
191- assert(err==DB_SUCCESS);
192+ if (err != DB_SUCCESS)
193+ {
194+ return ib_err_t_to_drizzle_error(err);
195+ }
196
197 tuple= ib_tuple_clear(tuple);
198 ret= read_row_from_innodb(buf, cursor, tuple, table,
199
200=== modified file 'plugin/embedded_innodb/embedded_innodb_engine.h'
201--- plugin/embedded_innodb/embedded_innodb_engine.h 2010-05-31 06:30:16 +0000
202+++ plugin/embedded_innodb/embedded_innodb_engine.h 2010-08-12 06:37:46 +0000
203@@ -120,6 +120,8 @@
204 ib_crsr_t cursor;
205 ib_tpl_t tuple;
206 bool advance_cursor;
207+ ib_lck_mode_t ib_lock_mode;
208+ int previous_error;
209
210 bool write_can_replace;
211 uint64_t hidden_autoinc_pkey_position;
212
213=== added file 'plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/r/basic_select_for_update.result'
214--- plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/r/basic_select_for_update.result 1970-01-01 00:00:00 +0000
215+++ plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/r/basic_select_for_update.result 2010-08-12 06:37:46 +0000
216@@ -0,0 +1,17 @@
217+create table t1 (a int);
218+insert into t1 values (1);
219+begin;
220+select a from t1 where a=1 for update;
221+a
222+1
223+update t1 set a=2 where a=1;
224+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
225+commit;
226+select * from t1;
227+a
228+1
229+update t1 set a=2 where a=1;
230+select * from t1;
231+a
232+2
233+DROP TABLE t1;
234
235=== added file 'plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/r/basic_select_for_update_pk_index.result'
236--- plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/r/basic_select_for_update_pk_index.result 1970-01-01 00:00:00 +0000
237+++ plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/r/basic_select_for_update_pk_index.result 2010-08-12 06:37:46 +0000
238@@ -0,0 +1,17 @@
239+create table t1 (a int primary key);
240+insert into t1 values (1);
241+begin;
242+select a from t1 where a=1 for update;
243+a
244+1
245+update t1 set a=2 where a=1;
246+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
247+commit;
248+select * from t1;
249+a
250+1
251+update t1 set a=2 where a=1;
252+select * from t1;
253+a
254+2
255+DROP TABLE t1;
256
257=== added file 'plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/t/basic_select_for_update-master.opt'
258--- plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/t/basic_select_for_update-master.opt 1970-01-01 00:00:00 +0000
259+++ plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/t/basic_select_for_update-master.opt 2010-08-12 06:37:46 +0000
260@@ -0,0 +1,1 @@
261+--plugin_add=embedded_innodb --plugin_remove=innobase --innodb_lock_wait_timeout=1
262
263=== added file 'plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/t/basic_select_for_update.test'
264--- plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/t/basic_select_for_update.test 1970-01-01 00:00:00 +0000
265+++ plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/t/basic_select_for_update.test 2010-08-12 06:37:46 +0000
266@@ -0,0 +1,27 @@
267+connect (a,localhost,root,,);
268+connect (b,localhost,root,,);
269+
270+connection a;
271+create table t1 (a int);
272+insert into t1 values (1);
273+begin;
274+select a from t1 where a=1 for update;
275+
276+connection b;
277+--error ER_LOCK_WAIT_TIMEOUT
278+update t1 set a=2 where a=1;
279+
280+connection a;
281+commit;
282+
283+connection b;
284+select * from t1;
285+update t1 set a=2 where a=1;
286+select * from t1;
287+
288+disconnect a;
289+disconnect b;
290+
291+connection default;
292+
293+DROP TABLE t1;
294
295=== added file 'plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/t/basic_select_for_update_pk_index-master.opt'
296--- plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/t/basic_select_for_update_pk_index-master.opt 1970-01-01 00:00:00 +0000
297+++ plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/t/basic_select_for_update_pk_index-master.opt 2010-08-12 06:37:46 +0000
298@@ -0,0 +1,1 @@
299+--plugin_add=embedded_innodb --plugin_remove=innobase --innodb_lock_wait_timeout=1
300
301=== added file 'plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/t/basic_select_for_update_pk_index.test'
302--- plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/t/basic_select_for_update_pk_index.test 1970-01-01 00:00:00 +0000
303+++ plugin/embedded_innodb/test-suite-dir/embedded_innodb/tests/t/basic_select_for_update_pk_index.test 2010-08-12 06:37:46 +0000
304@@ -0,0 +1,27 @@
305+connect (a,localhost,root,,);
306+connect (b,localhost,root,,);
307+
308+connection a;
309+create table t1 (a int primary key);
310+insert into t1 values (1);
311+begin;
312+select a from t1 where a=1 for update;
313+
314+connection b;
315+--error ER_LOCK_WAIT_TIMEOUT
316+update t1 set a=2 where a=1;
317+
318+connection a;
319+commit;
320+
321+connection b;
322+select * from t1;
323+update t1 set a=2 where a=1;
324+select * from t1;
325+
326+disconnect a;
327+disconnect b;
328+
329+connection default;
330+
331+DROP TABLE t1;