Merge lp:~percona-dev/percona-server/release-5.1.50-12-rename_index into lp:percona-server/release-5.1.50-12
- release-5.1.50-12-rename_index
- Merge into release-5.1.50-12
Proposed by
Yasufumi Kinoshita
Status: | Rejected |
---|---|
Rejected by: | Vadim Tkachenko |
Proposed branch: | lp:~percona-dev/percona-server/release-5.1.50-12-rename_index |
Merge into: | lp:percona-server/release-5.1.50-12 |
Diff against target: |
1214 lines (+1179/-0) 6 files modified
mysql-test/percona_rename_index.result (+39/-0) mysql-test/percona_rename_index.test (+25/-0) rename_field.patch (+501/-0) rename_index.patch (+570/-0) series (+2/-0) series_tmp_ported (+42/-0) |
To merge this branch: | bzr merge lp:~percona-dev/percona-server/release-5.1.50-12-rename_index |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Fred Linhoss (community) | documentation | Approve | |
Percona | Pending | ||
Review via email: mp+34652@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Percona (percona-team) wrote : | # |
Revision history for this message
Percona (percona-team) wrote : | # |
Fred,
I added you for merge review.
Please approve merge when you have documentation for this feature ready.
- 110. By kinoyasu <kinoyasu@gauntlet4>
-
add percona_
rename_ index test script
Revision history for this message
Yasufumi Kinoshita (yasufumi-kinoshita) wrote : | # |
Vadim?,
I have added the test script.
- 111. By kinoyasu <kinoyasu@gauntlet4>
-
add rename_field.patch; add series_tmp_ported to test current enable patches; clean rename_index.patch
Revision history for this message
Yasufumi Kinoshita (yasufumi-kinoshita) wrote : | # |
Vadim,
Currently, the branch is used as the temporary branch for RN.
Please use the difference to be merged to branch for RN.
Revision history for this message
Fred Linhoss (fred-linhoss) wrote : | # |
New wiki page http://
review:
Approve
(documentation)
Revision history for this message
Vadim Tkachenko (vadim-tk) wrote : | # |
pushed into special tree
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file 'mysql-test/percona_rename_index.result' |
2 | --- mysql-test/percona_rename_index.result 1970-01-01 00:00:00 +0000 |
3 | +++ mysql-test/percona_rename_index.result 2010-09-10 02:31:43 +0000 |
4 | @@ -0,0 +1,39 @@ |
5 | +drop table if exists t; |
6 | +create table t(a INT PRIMARY KEY, b INT, KEY index0 (b)) engine=MyISAM; |
7 | +alter table t rename index index0 to index1; |
8 | +show create table t; |
9 | +Table Create Table |
10 | +t CREATE TABLE `t` ( |
11 | + `a` int(11) NOT NULL, |
12 | + `b` int(11) DEFAULT NULL, |
13 | + PRIMARY KEY (`a`), |
14 | + KEY `index1` (`b`) |
15 | +) ENGINE=MyISAM DEFAULT CHARSET=latin1 |
16 | +alter table t drop index index1; |
17 | +drop table t; |
18 | +create table t(a INT PRIMARY KEY, b INT, KEY index0 (b)) engine=InnoDB; |
19 | +alter table t rename index index0 to index1; |
20 | +show create table t; |
21 | +Table Create Table |
22 | +t CREATE TABLE `t` ( |
23 | + `a` int(11) NOT NULL, |
24 | + `b` int(11) DEFAULT NULL, |
25 | + PRIMARY KEY (`a`), |
26 | + KEY `index1` (`b`) |
27 | +) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
28 | +alter table t drop index index1; |
29 | +drop table t; |
30 | +create table t(a INT PRIMARY KEY, b INT, KEY index0 (b)) engine=InnoDB PARTITION BY HASH(a) PARTITIONS 4; |
31 | +alter table t rename index index0 to index1; |
32 | +ERROR HY000: Incorrect usage of RENAME INDEX and PARTITIONED TABLE |
33 | +show create table t; |
34 | +Table Create Table |
35 | +t CREATE TABLE `t` ( |
36 | + `a` int(11) NOT NULL, |
37 | + `b` int(11) DEFAULT NULL, |
38 | + PRIMARY KEY (`a`), |
39 | + KEY `index0` (`b`) |
40 | +) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
41 | +/*!50100 PARTITION BY HASH (a) |
42 | +PARTITIONS 4 */ |
43 | +drop table t; |
44 | |
45 | === added file 'mysql-test/percona_rename_index.test' |
46 | --- mysql-test/percona_rename_index.test 1970-01-01 00:00:00 +0000 |
47 | +++ mysql-test/percona_rename_index.test 2010-09-10 02:31:43 +0000 |
48 | @@ -0,0 +1,25 @@ |
49 | +--source include/have_innodb.inc |
50 | +--source include/have_partition.inc |
51 | + |
52 | +--disable_warnings |
53 | +drop table if exists t; |
54 | +--enable_warnings |
55 | + |
56 | +create table t(a INT PRIMARY KEY, b INT, KEY index0 (b)) engine=MyISAM; |
57 | +alter table t rename index index0 to index1; |
58 | +show create table t; |
59 | +alter table t drop index index1; |
60 | +drop table t; |
61 | + |
62 | +create table t(a INT PRIMARY KEY, b INT, KEY index0 (b)) engine=InnoDB; |
63 | +alter table t rename index index0 to index1; |
64 | +show create table t; |
65 | +alter table t drop index index1; |
66 | +drop table t; |
67 | + |
68 | +#not supported yet |
69 | +create table t(a INT PRIMARY KEY, b INT, KEY index0 (b)) engine=InnoDB PARTITION BY HASH(a) PARTITIONS 4; |
70 | +--error 1221 |
71 | +alter table t rename index index0 to index1; |
72 | +show create table t; |
73 | +drop table t; |
74 | |
75 | === added file 'rename_field.patch' |
76 | --- rename_field.patch 1970-01-01 00:00:00 +0000 |
77 | +++ rename_field.patch 2010-09-10 02:31:43 +0000 |
78 | @@ -0,0 +1,501 @@ |
79 | +# name : rename_field.patch |
80 | +# introduced : 12 |
81 | +# maintainer : Yasufumi |
82 | +# |
83 | +#!!! notice !!! |
84 | +# Any small change to this file in the main branch |
85 | +# should be done or reviewed by the maintainer! |
86 | +diff -ruN a/patch_info/rename_field.info b/patch_info/rename_field.info |
87 | +--- /dev/null 1970-01-01 09:00:00.000000000 +0900 |
88 | ++++ b/patch_info/rename_field.info 2010-09-10 11:22:27.351954038 +0900 |
89 | +@@ -0,0 +1,15 @@ |
90 | ++File=rename_field.patch |
91 | ++Name=allow to rename field in storage engine dicrtionary |
92 | ++Version=1.0 |
93 | ++Author=Percona <info@percona.com> |
94 | ++License=GPL |
95 | ++Comment=ALTER TABLE which are only consisted by renaming field |
96 | ++can call renaming field internal of InnoDB and avoid recreation |
97 | ++of table if possible. |
98 | ++Current limitations: |
99 | ++1. The feature is disabled for XtraDB by default. |
100 | ++ (innodb_internal_rename_field = true|false (default: false)) |
101 | ++2. PARTITIONed XtraDB is not allowed |
102 | ++3. if the command ends by error, it should cause inconsistency |
103 | ++ of the index name between mysqld and InnoDB. |
104 | ++ (Don't use reserved names! "DB_ROW_ID", "DB_TRX_ID", "DB_ROLL_PTR") |
105 | +diff -ruN a/sql/handler.h b/sql/handler.h |
106 | +--- a/sql/handler.h 2010-09-10 10:54:15.464960210 +0900 |
107 | ++++ b/sql/handler.h 2010-09-10 11:12:15.235922418 +0900 |
108 | +@@ -1633,6 +1633,10 @@ |
109 | + virtual int rename_index(TABLE *table_arg, const char *from, const char *to) |
110 | + { return (HA_ERR_WRONG_COMMAND); } |
111 | + |
112 | ++ virtual bool can_rename_field() { return 0; } |
113 | ++ virtual int rename_field(TABLE *table_arg, uint position, const char *old_name, const char *new_name) |
114 | ++ { return (HA_ERR_WRONG_COMMAND); } |
115 | ++ |
116 | + uint max_record_length() const |
117 | + { return min(HA_MAX_REC_LENGTH, max_supported_record_length()); } |
118 | + uint max_keys() const |
119 | +diff -ruN a/sql/sql_table.cc b/sql/sql_table.cc |
120 | +--- a/sql/sql_table.cc 2010-09-10 10:54:15.485922029 +0900 |
121 | ++++ b/sql/sql_table.cc 2010-09-10 11:12:15.241891549 +0900 |
122 | +@@ -7332,6 +7332,33 @@ |
123 | + copy data for MERGE tables. Only the children have data. |
124 | + */ |
125 | + } |
126 | ++ else if (table->file->can_rename_field()) |
127 | ++ { |
128 | ++ /* ALTER_TABLE_METADATA_ONLY && need rename */ |
129 | ++ /* check renaming of the fields */ |
130 | ++ uint k; |
131 | ++ Field *field; |
132 | ++ Create_field *sql_field; |
133 | ++ List_iterator<Create_field> it(alter_info->create_list); |
134 | ++ |
135 | ++ for (k = 0; k < table->s->fields; k++) |
136 | ++ { |
137 | ++ field= table->field[k]; |
138 | ++ sql_field= it++; |
139 | ++ |
140 | ++ if (field->flags & FIELD_IS_RENAMED |
141 | ++ && sql_field |
142 | ++ && !my_strcasecmp(system_charset_info, field->field_name, sql_field->change)) |
143 | ++ { |
144 | ++ if ((error= table->file->rename_field(table, k, |
145 | ++ field->field_name, sql_field->field_name))) |
146 | ++ { |
147 | ++ table->file->print_error(error, MYF(0)); |
148 | ++ goto err1; |
149 | ++ } |
150 | ++ } |
151 | ++ } |
152 | ++ } |
153 | + |
154 | + /* Copy the data if necessary. */ |
155 | + thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields |
156 | +diff -ruN a/storage/innodb_plugin/dict/dict0mem.c b/storage/innodb_plugin/dict/dict0mem.c |
157 | +--- a/storage/innodb_plugin/dict/dict0mem.c 2010-09-10 10:54:15.082919251 +0900 |
158 | ++++ b/storage/innodb_plugin/dict/dict0mem.c 2010-09-10 11:12:15.246960627 +0900 |
159 | +@@ -199,6 +199,17 @@ |
160 | + |
161 | + table->col_names = dict_add_col_name(table->col_names, |
162 | + i, name, heap); |
163 | ++ |
164 | ++ if (UNIV_UNLIKELY(table->n_def == table->n_cols)) { |
165 | ++ const char* s = table->col_names; |
166 | ++ ulint j; |
167 | ++ |
168 | ++ for (j = 0; j < table->n_def; j++) { |
169 | ++ s += strlen(s) + 1; |
170 | ++ } |
171 | ++ |
172 | ++ table->col_names_maxlen = s - table->col_names; |
173 | ++ } |
174 | + } |
175 | + |
176 | + col = dict_table_get_nth_col(table, i); |
177 | +diff -ruN a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc |
178 | +--- a/storage/innodb_plugin/handler/ha_innodb.cc 2010-09-10 10:54:15.536916334 +0900 |
179 | ++++ b/storage/innodb_plugin/handler/ha_innodb.cc 2010-09-10 11:12:15.254960837 +0900 |
180 | +@@ -198,6 +198,8 @@ |
181 | + static my_bool innobase_stats_on_metadata = TRUE; |
182 | + static my_bool innobase_use_sys_stats_table = FALSE; |
183 | + |
184 | ++static my_bool innobase_internal_rename_field = FALSE; |
185 | ++ |
186 | + static char* internal_innobase_data_file_path = NULL; |
187 | + |
188 | + static char* innodb_version_str = (char*) INNODB_VERSION_STR; |
189 | +@@ -10577,7 +10579,7 @@ |
190 | + system metadata change. To avoid system metadata inconsistency, |
191 | + currently we can just request a table rebuild/copy by returning |
192 | + COMPATIBLE_DATA_NO */ |
193 | +- if (check_column_being_renamed(table, NULL)) { |
194 | ++ if ((table->part_info || !innobase_rename_field()) && check_column_being_renamed(table, NULL)) { |
195 | + return COMPATIBLE_DATA_NO; |
196 | + } |
197 | + |
198 | +@@ -11091,6 +11093,15 @@ |
199 | + return(false); |
200 | + } |
201 | + |
202 | ++/*********************************************************************//** |
203 | ++*/ |
204 | ++extern "C" UNIV_INTERN |
205 | ++bool |
206 | ++innobase_rename_field() |
207 | ++{ |
208 | ++ return((bool)innobase_internal_rename_field); |
209 | ++} |
210 | ++ |
211 | + static SHOW_VAR innodb_status_variables_export[]= { |
212 | + {"Innodb", (char*) &show_innodb_vars, SHOW_FUNC}, |
213 | + {NullS, NullS, SHOW_LONG} |
214 | +@@ -11597,6 +11608,13 @@ |
215 | + "except for the deletion.", |
216 | + NULL, NULL, 0, 0, 1, 0); |
217 | + |
218 | ++static MYSQL_SYSVAR_BOOL(internal_rename_field, innobase_internal_rename_field, |
219 | ++ PLUGIN_VAR_OPCMDARG, |
220 | ++ "To avoid recreation of the table at ALTER TABLE, " |
221 | ++ "directly update field names if the ALTER TABLE contains only rename fields. " |
222 | ++ "(disabled by default)", |
223 | ++ NULL, NULL, FALSE); |
224 | ++ |
225 | + static struct st_mysql_sys_var* innobase_system_variables[]= { |
226 | + MYSQL_SYSVAR(page_size), |
227 | + MYSQL_SYSVAR(additional_mem_pool_size), |
228 | +@@ -11682,6 +11700,7 @@ |
229 | + MYSQL_SYSVAR(io_capacity), |
230 | + MYSQL_SYSVAR(use_purge_thread), |
231 | + MYSQL_SYSVAR(pass_corrupt_table), |
232 | ++ MYSQL_SYSVAR(internal_rename_field), |
233 | + NULL |
234 | + }; |
235 | + |
236 | +diff -ruN a/storage/innodb_plugin/handler/ha_innodb.h b/storage/innodb_plugin/handler/ha_innodb.h |
237 | +--- a/storage/innodb_plugin/handler/ha_innodb.h 2010-09-10 10:54:15.513918159 +0900 |
238 | ++++ b/storage/innodb_plugin/handler/ha_innodb.h 2010-09-10 11:12:15.260959990 +0900 |
239 | +@@ -224,6 +224,8 @@ |
240 | + |
241 | + bool can_rename_index(); |
242 | + int rename_index(TABLE *table_arg, const char *from, const char *to); |
243 | ++ bool can_rename_field(); |
244 | ++ int rename_field(TABLE *table_arg, uint position, const char *old_name, const char *new_name); |
245 | + }; |
246 | + |
247 | + /* Some accessor functions which the InnoDB plugin needs, but which |
248 | +@@ -333,3 +335,10 @@ |
249 | + ulint num_of_keys); /* in: Number of indexes to |
250 | + be created. */ |
251 | + |
252 | ++/*********************************************************************//** |
253 | ++*/ |
254 | ++extern "C" |
255 | ++bool |
256 | ++innobase_rename_field(); |
257 | ++/*===================*/ |
258 | ++ |
259 | +diff -ruN a/storage/innodb_plugin/handler/handler0alter.cc b/storage/innodb_plugin/handler/handler0alter.cc |
260 | +--- a/storage/innodb_plugin/handler/handler0alter.cc 2010-09-10 10:54:15.514916344 +0900 |
261 | ++++ b/storage/innodb_plugin/handler/handler0alter.cc 2010-09-10 11:12:15.262959956 +0900 |
262 | +@@ -1379,3 +1379,124 @@ |
263 | + |
264 | + DBUG_RETURN(error); |
265 | + } |
266 | ++ |
267 | ++/* additional methods for rename field internally feature */ |
268 | ++UNIV_INTERN |
269 | ++bool |
270 | ++ha_innobase::can_rename_field() |
271 | ++{ |
272 | ++ return(innobase_rename_field()); |
273 | ++} |
274 | ++ |
275 | ++UNIV_INTERN |
276 | ++int |
277 | ++ha_innobase::rename_field( |
278 | ++ TABLE* table, |
279 | ++ uint position, |
280 | ++ const char* old_name, |
281 | ++ const char* new_name) |
282 | ++{ |
283 | ++ dict_table_t* innodb_table; |
284 | ++ trx_t* trx; |
285 | ++ ibool dict_locked = FALSE; |
286 | ++ int error = 0; |
287 | ++ |
288 | ++ DBUG_ENTER("ha_innobase::rename_field"); |
289 | ++ ut_a(table); |
290 | ++ ut_a(old_name); |
291 | ++ ut_a(new_name); |
292 | ++ |
293 | ++ if (srv_created_new_raw || srv_force_recovery) { |
294 | ++ DBUG_RETURN(HA_ERR_WRONG_COMMAND); |
295 | ++ } |
296 | ++ |
297 | ++ update_thd(); |
298 | ++ |
299 | ++ trx_search_latch_release_if_reserved(prebuilt->trx); |
300 | ++ trx_start_if_not_started(prebuilt->trx); |
301 | ++ |
302 | ++ trx = innobase_trx_allocate(user_thd); |
303 | ++ trx_start_if_not_started(trx); |
304 | ++ |
305 | ++ innodb_table = dict_table_get(prebuilt->table->name, FALSE); |
306 | ++ |
307 | ++ if (UNIV_UNLIKELY(!innodb_table)) { |
308 | ++ error = HA_ERR_NO_SUCH_TABLE; |
309 | ++ goto err_exit; |
310 | ++ } |
311 | ++ |
312 | ++ if (dict_col_name_is_reserved(new_name)) { |
313 | ++ push_warning_printf((THD*) trx->mysql_thd, |
314 | ++ MYSQL_ERROR::WARN_LEVEL_WARN, |
315 | ++ ER_WRONG_COLUMN_NAME, |
316 | ++ "Cannot Create Field with name " |
317 | ++ "'%s'. The name is reserved " |
318 | ++ "for the system fields in index.", |
319 | ++ new_name); |
320 | ++ |
321 | ++ my_error(ER_WRONG_COLUMN_NAME, MYF(0), |
322 | ++ new_name); |
323 | ++ error = -1; |
324 | ++ } |
325 | ++ |
326 | ++ /* TODO: other checks are omitted. currently believe mysqld. */ |
327 | ++ |
328 | ++ if (UNIV_UNLIKELY(error)) { |
329 | ++err_exit: |
330 | ++ trx_general_rollback_for_mysql(trx, NULL); |
331 | ++ trx_free_for_mysql(trx); |
332 | ++ trx_commit_for_mysql(prebuilt->trx); |
333 | ++ DBUG_RETURN(error); |
334 | ++ } |
335 | ++ |
336 | ++ trx_set_dict_operation(trx, TRX_DICT_OP_INDEX); |
337 | ++ |
338 | ++ error = row_merge_lock_table(prebuilt->trx, innodb_table, LOCK_X); |
339 | ++ |
340 | ++ if (UNIV_UNLIKELY(error != DB_SUCCESS)) { |
341 | ++ goto error_handling; |
342 | ++ } |
343 | ++ |
344 | ++ row_mysql_lock_data_dictionary(trx); |
345 | ++ dict_locked = TRUE; |
346 | ++ |
347 | ++ /*======================================*/ |
348 | ++ |
349 | ++ error = row_rename_field_for_mysql(innodb_table, position, old_name, new_name, trx); |
350 | ++ |
351 | ++error_handling: |
352 | ++ switch (error) { |
353 | ++ case DB_SUCCESS: |
354 | ++ goto convert_error; |
355 | ++ case DB_TOO_BIG_RECORD: |
356 | ++ my_error(HA_ERR_TO_BIG_ROW, MYF(0)); |
357 | ++ goto error; |
358 | ++ case DB_PRIMARY_KEY_IS_NULL: |
359 | ++ my_error(ER_PRIMARY_CANT_HAVE_NULL, MYF(0)); |
360 | ++ case DB_DUPLICATE_KEY: |
361 | ++error: |
362 | ++ prebuilt->trx->error_info = NULL; |
363 | ++ default: |
364 | ++ trx->error_state = DB_SUCCESS; |
365 | ++convert_error: |
366 | ++ error = convert_error_code_to_mysql(error, |
367 | ++ innodb_table->flags, |
368 | ++ user_thd); |
369 | ++ } |
370 | ++ |
371 | ++ trx_commit_for_mysql(trx); |
372 | ++ if (prebuilt->trx) { |
373 | ++ trx_commit_for_mysql(prebuilt->trx); |
374 | ++ } |
375 | ++ |
376 | ++ if (dict_locked) { |
377 | ++ row_mysql_unlock_data_dictionary(trx); |
378 | ++ } |
379 | ++ |
380 | ++ trx_free_for_mysql(trx); |
381 | ++ |
382 | ++ srv_active_wake_master_thread(); |
383 | ++ |
384 | ++ DBUG_RETURN(error); |
385 | ++} |
386 | ++ |
387 | +diff -ruN a/storage/innodb_plugin/include/dict0mem.h b/storage/innodb_plugin/include/dict0mem.h |
388 | +--- a/storage/innodb_plugin/include/dict0mem.h 2010-09-10 10:54:15.127879538 +0900 |
389 | ++++ b/storage/innodb_plugin/include/dict0mem.h 2010-09-10 11:12:15.264960559 +0900 |
390 | +@@ -414,6 +414,7 @@ |
391 | + the string contains n_cols, it will be |
392 | + allocated from a temporary heap. The final |
393 | + string will be allocated from table->heap. */ |
394 | ++ ulint col_names_maxlen; |
395 | + #ifndef UNIV_HOTBACKUP |
396 | + hash_node_t name_hash; /*!< hash chain node */ |
397 | + hash_node_t id_hash; /*!< hash chain node */ |
398 | +diff -ruN a/storage/innodb_plugin/include/row0mysql.h b/storage/innodb_plugin/include/row0mysql.h |
399 | +--- a/storage/innodb_plugin/include/row0mysql.h 2010-09-10 10:54:15.516960655 +0900 |
400 | ++++ b/storage/innodb_plugin/include/row0mysql.h 2010-09-10 11:12:15.265963598 +0900 |
401 | +@@ -534,6 +534,18 @@ |
402 | + const char* to, |
403 | + trx_t* trx); |
404 | + |
405 | ++/*********************************************************************//** |
406 | ++*/ |
407 | ++UNIV_INTERN |
408 | ++int |
409 | ++row_rename_field_for_mysql( |
410 | ++/*=======================*/ |
411 | ++ dict_table_t* innodb_table, |
412 | ++ uint pos, |
413 | ++ const char* from, |
414 | ++ const char* to, |
415 | ++ trx_t* trx); |
416 | ++ |
417 | + /* A struct describing a place for an individual column in the MySQL |
418 | + row format which is presented to the table handler in ha_innobase. |
419 | + This template struct is used to speed up row transformations between |
420 | +diff -ruN a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c |
421 | +--- a/storage/innodb_plugin/row/row0mysql.c 2010-09-10 10:54:15.519880499 +0900 |
422 | ++++ b/storage/innodb_plugin/row/row0mysql.c 2010-09-10 11:12:15.270960787 +0900 |
423 | +@@ -4250,3 +4250,156 @@ |
424 | + |
425 | + return(err); |
426 | + } |
427 | ++ |
428 | ++/*********************************************************************//** |
429 | ++*/ |
430 | ++UNIV_INTERN |
431 | ++int |
432 | ++row_rename_field_for_mysql( |
433 | ++/*=======================*/ |
434 | ++ dict_table_t* innodb_table, |
435 | ++ uint position, |
436 | ++ const char* from, |
437 | ++ const char* to, |
438 | ++ trx_t* trx) |
439 | ++{ |
440 | ++ ulint err; |
441 | ++ dict_index_t* index; |
442 | ++ pars_info_t* info; |
443 | ++ ulint len_from = strlen(from) + 1; |
444 | ++ ulint len_to = strlen(to) + 1; |
445 | ++ ulint col_names_len; |
446 | ++ ulint pre_len = 0; |
447 | ++ ulint after_len = 0; |
448 | ++ |
449 | ++ |
450 | ++ /* assumed that the field is not related to foreign key */ |
451 | ++ static const char rename_column[] = |
452 | ++ "PROCEDURE RENAME_COLUMN_PROC () IS\n" |
453 | ++ "BEGIN\n" |
454 | ++ "UPDATE SYS_COLUMNS SET NAME=:to_name \n" |
455 | ++ "WHERE TABLE_ID = :tableid AND NAME=:from_name;\n" |
456 | ++ "END;\n"; |
457 | ++ |
458 | ++ static const char rename_field[] = |
459 | ++ "PROCEDURE RENAME_FIELD_PROC () IS\n" |
460 | ++ "BEGIN\n" |
461 | ++ "UPDATE SYS_FIELDS SET COL_NAME=:to_name \n" |
462 | ++ "WHERE INDEX_ID = :indexid AND COL_NAME=:from_name;\n" |
463 | ++ "END;\n"; |
464 | ++ |
465 | ++ ut_a(trx->dict_operation_lock_mode == RW_X_LATCH); |
466 | ++ |
467 | ++ trx->op_info = "renaming field"; |
468 | ++ |
469 | ++ /* update dict_mem */ |
470 | ++ /* innodb_table->col_names */ |
471 | ++ { |
472 | ++ const char* s = innodb_table->col_names; |
473 | ++ const char* t = NULL; |
474 | ++ ulint i; |
475 | ++ |
476 | ++ for (i = 0; i < innodb_table->n_def; i++) { |
477 | ++ if (i == position) { |
478 | ++ pre_len = s - innodb_table->col_names; |
479 | ++ } else if (i == position + 1) { |
480 | ++ t = s; |
481 | ++ } |
482 | ++ |
483 | ++ s += strlen(s) + 1; |
484 | ++ } |
485 | ++ |
486 | ++ col_names_len = s - innodb_table->col_names; |
487 | ++ |
488 | ++ if (t) { |
489 | ++ after_len = s - t; |
490 | ++ } else { |
491 | ++ after_len = 0; |
492 | ++ } |
493 | ++ } |
494 | ++ |
495 | ++ ut_a(col_names_len == pre_len + len_from + after_len); |
496 | ++ |
497 | ++ if (col_names_len + len_from - len_to > innodb_table->col_names_maxlen ) { |
498 | ++ char* new_col_names; |
499 | ++ ulint margin = 32; |
500 | ++ /* need larger area */ |
501 | ++ |
502 | ++ innodb_table->col_names_maxlen = col_names_len + len_from - len_to + margin; |
503 | ++ new_col_names = mem_heap_alloc(innodb_table->heap, innodb_table->col_names_maxlen); |
504 | ++ |
505 | ++ if (pre_len) { |
506 | ++ memcpy(new_col_names, innodb_table->col_names, pre_len); |
507 | ++ } |
508 | ++ |
509 | ++ memcpy(new_col_names + pre_len, to, len_to); |
510 | ++ |
511 | ++ if (after_len) { |
512 | ++ memcpy(new_col_names + pre_len + len_to, |
513 | ++ innodb_table->col_names + pre_len + len_from, |
514 | ++ after_len); |
515 | ++ } |
516 | ++ |
517 | ++ innodb_table->col_names = new_col_names; |
518 | ++ } else { |
519 | ++ /* reuse */ |
520 | ++ if (len_to != len_from && after_len) { |
521 | ++ memmove((char*)innodb_table->col_names + pre_len + len_to, |
522 | ++ innodb_table->col_names + pre_len + len_from, |
523 | ++ after_len); |
524 | ++ } |
525 | ++ |
526 | ++ memcpy((char*)innodb_table->col_names + pre_len, to, len_to); |
527 | ++ } |
528 | ++ |
529 | ++ |
530 | ++ /* re-link field->name */ |
531 | ++ if (len_to != len_from) { |
532 | ++ index = dict_table_get_first_index(innodb_table); |
533 | ++ while (index) { |
534 | ++ ulint i; |
535 | ++ |
536 | ++ for (i = 0; i < index->n_def; i++) { |
537 | ++ dict_field_t* field = &index->fields[i]; |
538 | ++ |
539 | ++ field->name = dict_table_get_col_name(innodb_table, field->col->ind); |
540 | ++ } |
541 | ++ |
542 | ++ index = dict_table_get_next_index(index); |
543 | ++ } |
544 | ++ } |
545 | ++ |
546 | ++ |
547 | ++ /* update SYS_FIELDS, SYS_COLUMNS */ |
548 | ++ info = pars_info_create(); |
549 | ++ |
550 | ++ pars_info_add_dulint_literal(info, "tableid", innodb_table->id); |
551 | ++ pars_info_add_str_literal(info, "from_name", from); |
552 | ++ pars_info_add_str_literal(info, "to_name", to); |
553 | ++ |
554 | ++ err = que_eval_sql(info, rename_column, FALSE, trx); |
555 | ++ |
556 | ++ if (err != DB_SUCCESS) |
557 | ++ return(err); |
558 | ++ |
559 | ++ index = dict_table_get_first_index(innodb_table); |
560 | ++ while (index) { |
561 | ++ info = pars_info_create(); |
562 | ++ |
563 | ++ pars_info_add_dulint_literal(info, "indexid", index->id); |
564 | ++ pars_info_add_str_literal(info, "from_name", from); |
565 | ++ pars_info_add_str_literal(info, "to_name", to); |
566 | ++ |
567 | ++ err = que_eval_sql(info, rename_field, FALSE, trx); |
568 | ++ |
569 | ++ if (err != DB_SUCCESS) |
570 | ++ return(err); |
571 | ++ |
572 | ++ index = dict_table_get_next_index(index); |
573 | ++ } |
574 | ++ |
575 | ++ trx->op_info = ""; |
576 | ++ |
577 | ++ return(err); |
578 | ++} |
579 | ++ |
580 | |
581 | === added file 'rename_index.patch' |
582 | --- rename_index.patch 1970-01-01 00:00:00 +0000 |
583 | +++ rename_index.patch 2010-09-10 02:31:43 +0000 |
584 | @@ -0,0 +1,570 @@ |
585 | +# name : rename_index.patch |
586 | +# introduced : 12 |
587 | +# maintainer : Yasufumi |
588 | +# |
589 | +#!!! notice !!! |
590 | +# Any small change to this file in the main branch |
591 | +# should be done or reviewed by the maintainer! |
592 | +diff -ruN a/patch_info/rename_index.info b/patch_info/rename_index.info |
593 | +--- /dev/null 1970-01-01 09:00:00.000000000 +0900 |
594 | ++++ b/patch_info/rename_index.info 2010-09-03 17:18:34.280135668 +0900 |
595 | +@@ -0,0 +1,11 @@ |
596 | ++File=rename_index.patch |
597 | ++Name=RENAME INDEX clause for ALTER TABLE |
598 | ++Version=1.0 |
599 | ++Author=Percona <info@percona.com> |
600 | ++License=GPL |
601 | ++Comment=<RENAME INDEX/KEY xxx TO yyy> clause is added to ALTER TABLE. |
602 | ++Current limitations: |
603 | ++1. should be used without another type of clauses. |
604 | ++2. for MyISAM or InnoDB (Plugin) only. PARTITION is not allowed |
605 | ++3. if the command ends by error, it should cause inconsistency |
606 | ++ of the index name between mysqld and InnoDB. (InnoDB only) |
607 | +diff -ruN a/sql/handler.h b/sql/handler.h |
608 | +--- a/sql/handler.h 2010-09-03 17:10:01.236168680 +0900 |
609 | ++++ b/sql/handler.h 2010-09-03 17:10:21.629543000 +0900 |
610 | +@@ -1629,6 +1629,10 @@ |
611 | + virtual int final_drop_index(TABLE *table_arg) |
612 | + { return (HA_ERR_WRONG_COMMAND); } |
613 | + |
614 | ++ virtual bool can_rename_index() { return 0; } |
615 | ++ virtual int rename_index(TABLE *table_arg, const char *from, const char *to) |
616 | ++ { return (HA_ERR_WRONG_COMMAND); } |
617 | ++ |
618 | + uint max_record_length() const |
619 | + { return min(HA_MAX_REC_LENGTH, max_supported_record_length()); } |
620 | + uint max_keys() const |
621 | +diff -ruN a/sql/sql_class.cc b/sql/sql_class.cc |
622 | +--- a/sql/sql_class.cc 2010-09-03 17:10:00.082166558 +0900 |
623 | ++++ b/sql/sql_class.cc 2010-09-03 17:10:21.632246778 +0900 |
624 | +@@ -68,6 +68,8 @@ |
625 | + template class List_iterator<Alter_drop>; |
626 | + template class List<Alter_column>; |
627 | + template class List_iterator<Alter_column>; |
628 | ++template class List<Rename_key>; |
629 | ++template class List_iterator<Rename_key>; |
630 | + #endif |
631 | + |
632 | + /**************************************************************************** |
633 | +diff -ruN a/sql/sql_class.h b/sql/sql_class.h |
634 | +--- a/sql/sql_class.h 2010-09-03 17:10:01.258166856 +0900 |
635 | ++++ b/sql/sql_class.h 2010-09-03 17:10:21.637251953 +0900 |
636 | +@@ -165,6 +165,17 @@ |
637 | + }; |
638 | + |
639 | + |
640 | ++class Rename_key :public Sql_alloc { |
641 | ++public: |
642 | ++ const char *from_name; |
643 | ++ const char *to_name; |
644 | ++ Rename_key(const char *par_from_name, const char *par_to_name) |
645 | ++ :from_name(par_from_name), to_name(par_to_name) {} |
646 | ++ Rename_key *clone(MEM_ROOT *mem_root) const |
647 | ++ { return new (mem_root) Rename_key(*this); } |
648 | ++}; |
649 | ++ |
650 | ++ |
651 | + class Alter_drop :public Sql_alloc { |
652 | + public: |
653 | + enum drop_type {KEY, COLUMN }; |
654 | +diff -ruN a/sql/sql_lex.cc b/sql/sql_lex.cc |
655 | +--- a/sql/sql_lex.cc 2010-08-04 02:24:19.000000000 +0900 |
656 | ++++ b/sql/sql_lex.cc 2010-09-03 17:10:21.640242292 +0900 |
657 | +@@ -1493,6 +1493,7 @@ |
658 | + alter_list(rhs.alter_list, mem_root), |
659 | + key_list(rhs.key_list, mem_root), |
660 | + create_list(rhs.create_list, mem_root), |
661 | ++ rename_key_list(rhs.rename_key_list, mem_root), |
662 | + flags(rhs.flags), |
663 | + keys_onoff(rhs.keys_onoff), |
664 | + tablespace_op(rhs.tablespace_op), |
665 | +@@ -1515,6 +1516,7 @@ |
666 | + list_copy_and_replace_each_value(alter_list, mem_root); |
667 | + list_copy_and_replace_each_value(key_list, mem_root); |
668 | + list_copy_and_replace_each_value(create_list, mem_root); |
669 | ++ list_copy_and_replace_each_value(rename_key_list, mem_root); |
670 | + /* partition_names are not deeply copied currently */ |
671 | + } |
672 | + |
673 | +diff -ruN a/sql/sql_lex.h b/sql/sql_lex.h |
674 | +--- a/sql/sql_lex.h 2010-09-03 17:10:00.016135765 +0900 |
675 | ++++ b/sql/sql_lex.h 2010-09-03 17:10:21.643204100 +0900 |
676 | +@@ -873,6 +873,7 @@ |
677 | + #define ALTER_ALL_PARTITION (1L << 21) |
678 | + #define ALTER_REMOVE_PARTITIONING (1L << 22) |
679 | + #define ALTER_FOREIGN_KEY (1L << 23) |
680 | ++#define ALTER_RENAME_INDEX (1L << 24) |
681 | + |
682 | + enum enum_alter_table_change_level |
683 | + { |
684 | +@@ -895,6 +896,7 @@ |
685 | + List<Alter_column> alter_list; |
686 | + List<Key> key_list; |
687 | + List<Create_field> create_list; |
688 | ++ List<Rename_key> rename_key_list; |
689 | + uint flags; |
690 | + enum enum_enable_or_disable keys_onoff; |
691 | + enum tablespace_op_type tablespace_op; |
692 | +@@ -921,6 +923,7 @@ |
693 | + alter_list.empty(); |
694 | + key_list.empty(); |
695 | + create_list.empty(); |
696 | ++ rename_key_list.empty(); |
697 | + flags= 0; |
698 | + keys_onoff= LEAVE_AS_IS; |
699 | + tablespace_op= NO_TABLESPACE_OP; |
700 | +diff -ruN a/sql/sql_table.cc b/sql/sql_table.cc |
701 | +--- a/sql/sql_table.cc 2010-09-03 17:10:01.272166375 +0900 |
702 | ++++ b/sql/sql_table.cc 2010-09-03 17:10:21.650203965 +0900 |
703 | +@@ -49,7 +49,7 @@ |
704 | + bool tmp_table, |
705 | + uint *db_options, |
706 | + handler *file, KEY **key_info_buffer, |
707 | +- uint *key_count, int select_field_count); |
708 | ++ uint *key_count, int select_field_count, bool rename_keys); |
709 | + static bool |
710 | + mysql_prepare_alter_table(THD *thd, TABLE *table, |
711 | + HA_CREATE_INFO *create_info, |
712 | +@@ -1623,7 +1623,7 @@ |
713 | + lpt->table->file, |
714 | + &lpt->key_info_buffer, |
715 | + &lpt->key_count, |
716 | +- /*select_field_count*/ 0)) |
717 | ++ /*select_field_count*/ 0, FALSE)) |
718 | + { |
719 | + DBUG_RETURN(TRUE); |
720 | + } |
721 | +@@ -2577,7 +2577,7 @@ |
722 | + bool tmp_table, |
723 | + uint *db_options, |
724 | + handler *file, KEY **key_info_buffer, |
725 | +- uint *key_count, int select_field_count) |
726 | ++ uint *key_count, int select_field_count, bool rename_keys) |
727 | + { |
728 | + const char *key_name; |
729 | + Create_field *sql_field,*dup_field; |
730 | +@@ -2916,9 +2916,11 @@ |
731 | + |
732 | + List_iterator<Key> key_iterator(alter_info->key_list); |
733 | + List_iterator<Key> key_iterator2(alter_info->key_list); |
734 | ++ List_iterator<Rename_key> rename_key_iterator(alter_info->rename_key_list); |
735 | + uint key_parts=0, fk_key_count=0; |
736 | + bool primary_key=0,unique_key=0; |
737 | + Key *key, *key2; |
738 | ++ Rename_key *rename_key; |
739 | + uint tmp, key_number; |
740 | + /* special marker for keys to be ignored */ |
741 | + static char ignore_key[1]; |
742 | +@@ -3357,7 +3359,22 @@ |
743 | + key_name=primary_key_name; |
744 | + primary_key=1; |
745 | + } |
746 | +- else if (!(key_name = key->name)) |
747 | ++ else |
748 | ++ { |
749 | ++ key_name = key->name; |
750 | ++ if (rename_keys) |
751 | ++ { |
752 | ++ rename_key_iterator.rewind(); |
753 | ++ while ((rename_key=rename_key_iterator++)) |
754 | ++ { |
755 | ++ if (!my_strcasecmp(system_charset_info, key_name, rename_key->from_name)) |
756 | ++ { |
757 | ++ key_name = rename_key->to_name; |
758 | ++ } |
759 | ++ } |
760 | ++ } |
761 | ++ } |
762 | ++ if (!key_name) |
763 | + key_name=make_unique_key_name(sql_field->field_name, |
764 | + *key_info_buffer, key_info); |
765 | + if (check_if_keyname_exists(key_name, *key_info_buffer, key_info)) |
766 | +@@ -3845,7 +3862,7 @@ |
767 | + internal_tmp_table, |
768 | + &db_options, file, |
769 | + &key_info_buffer, &key_count, |
770 | +- select_field_count)) |
771 | ++ select_field_count, TRUE)) |
772 | + goto err; |
773 | + |
774 | + /* Check if table exists */ |
775 | +@@ -5225,7 +5242,7 @@ |
776 | + if (mysql_prepare_create_table(thd, &local_create_info, &alter_info, |
777 | + tmp_table, &db_options, |
778 | + schema_table->table->file, |
779 | +- &schema_table->table->s->key_info, &keys, 0)) |
780 | ++ &schema_table->table->s->key_info, &keys, 0, FALSE)) |
781 | + DBUG_RETURN(1); |
782 | + local_create_info.max_rows= 0; |
783 | + if (mysql_create_frm(thd, dst_path, NullS, NullS, |
784 | +@@ -5737,7 +5754,7 @@ |
785 | + (table->s->tmp_table != NO_TMP_TABLE), |
786 | + &db_options, |
787 | + table->file, key_info_buffer, |
788 | +- &key_count, 0)) |
789 | ++ &key_count, 0, FALSE)) |
790 | + DBUG_RETURN(1); |
791 | + /* Allocate result buffers. */ |
792 | + if (! (*index_drop_buffer= |
793 | +@@ -6568,6 +6585,16 @@ |
794 | + |
795 | + mysql_ha_rm_tables(thd, table_list, FALSE); |
796 | + |
797 | ++ /* RENAME INDEX should be isolated from anothers */ |
798 | ++ if (alter_info->flags & ALTER_RENAME_INDEX) |
799 | ++ { |
800 | ++ if (alter_info->flags != ALTER_RENAME_INDEX) |
801 | ++ { |
802 | ++ my_error(ER_WRONG_USAGE, MYF(0), "RENAME INDEX", "other type operations"); |
803 | ++ DBUG_RETURN(TRUE); |
804 | ++ } |
805 | ++ } |
806 | ++ |
807 | + /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */ |
808 | + if (alter_info->tablespace_op != NO_TABLESPACE_OP) |
809 | + /* Conditionally writes to binlog. */ |
810 | +@@ -6730,6 +6757,48 @@ |
811 | + new_name= table_name; |
812 | + } |
813 | + |
814 | ++ /* check names for RENAME INDEX */ |
815 | ++ if (alter_info->flags & ALTER_RENAME_INDEX) |
816 | ++ { |
817 | ++ List_iterator<Rename_key> rename_key_iterator(alter_info->rename_key_list); |
818 | ++ Rename_key *rename_key; |
819 | ++ |
820 | ++ if (!table->file->can_rename_index()) |
821 | ++ { |
822 | ++ my_error(ER_WRONG_USAGE, MYF(0), "RENAME INDEX", |
823 | ++ (table->part_info ? "PARTITIONED TABLE" : table->file->table_type())); |
824 | ++ DBUG_RETURN(TRUE); |
825 | ++ } |
826 | ++ |
827 | ++ rename_key_iterator.rewind(); |
828 | ++ while ((rename_key=rename_key_iterator++)) |
829 | ++ { |
830 | ++ KEY *key_info=table->key_info; |
831 | ++ bool find_from = FALSE; |
832 | ++ bool find_to = FALSE; |
833 | ++ |
834 | ++ for (uint i=0 ; i < table->s->keys ; i++,key_info++) |
835 | ++ { |
836 | ++ if (!my_strcasecmp(system_charset_info, key_info->name, rename_key->from_name)) |
837 | ++ find_from = TRUE; |
838 | ++ if (!my_strcasecmp(system_charset_info, key_info->name, rename_key->to_name)) |
839 | ++ find_to = TRUE; |
840 | ++ } |
841 | ++ |
842 | ++ if (!find_from) |
843 | ++ { |
844 | ++ my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), rename_key->from_name, table_name); |
845 | ++ DBUG_RETURN(TRUE); |
846 | ++ } |
847 | ++ |
848 | ++ if (find_to) |
849 | ++ { |
850 | ++ my_error(ER_DUP_KEYNAME, MYF(0), rename_key->to_name); |
851 | ++ DBUG_RETURN(TRUE); |
852 | ++ } |
853 | ++ } |
854 | ++ } |
855 | ++ |
856 | + old_db_type= table->s->db_type(); |
857 | + if (!create_info->db_type) |
858 | + { |
859 | +@@ -7386,6 +7455,26 @@ |
860 | + } |
861 | + /*end of if (! new_table) for add/drop index*/ |
862 | + |
863 | ++ /* rename index also internal of the storage engine */ |
864 | ++ if (alter_info->flags & ALTER_RENAME_INDEX) |
865 | ++ { |
866 | ++ List_iterator<Rename_key> rename_key_iterator(alter_info->rename_key_list); |
867 | ++ Rename_key *rename_key; |
868 | ++ |
869 | ++ rename_key_iterator.rewind(); |
870 | ++ while ((rename_key=rename_key_iterator++)) |
871 | ++ { |
872 | ++ if ((error= table->file->rename_index(table, |
873 | ++ rename_key->from_name, rename_key->to_name))) |
874 | ++ { |
875 | ++ table->file->print_error(error, MYF(0)); |
876 | ++ goto err1; |
877 | ++ } |
878 | ++ } |
879 | ++ |
880 | ++ /* need commit or something? */ |
881 | ++ } |
882 | ++ |
883 | + if (table->s->tmp_table != NO_TMP_TABLE) |
884 | + { |
885 | + /* We changed a temporary table */ |
886 | +diff -ruN a/sql/sql_yacc.yy b/sql/sql_yacc.yy |
887 | +--- a/sql/sql_yacc.yy 2010-09-03 17:10:00.048138226 +0900 |
888 | ++++ b/sql/sql_yacc.yy 2010-09-03 17:10:21.679137536 +0900 |
889 | +@@ -6180,6 +6180,15 @@ |
890 | + LEX *lex=Lex; |
891 | + lex->alter_info.flags|= ALTER_ORDER; |
892 | + } |
893 | ++ | RENAME key_or_index field_ident TO_SYM field_ident |
894 | ++ { |
895 | ++ LEX *lex=Lex; |
896 | ++ Rename_key *rk= new Rename_key($3.str, $5.str); |
897 | ++ if (rk == NULL) |
898 | ++ MYSQL_YYABORT; |
899 | ++ lex->alter_info.rename_key_list.push_back(rk); |
900 | ++ lex->alter_info.flags|= ALTER_RENAME_INDEX; |
901 | ++ } |
902 | + ; |
903 | + |
904 | + opt_column: |
905 | +diff -ruN a/storage/innodb_plugin/handler/ha_innodb.h b/storage/innodb_plugin/handler/ha_innodb.h |
906 | +--- a/storage/innodb_plugin/handler/ha_innodb.h 2010-09-03 17:10:00.914204836 +0900 |
907 | ++++ b/storage/innodb_plugin/handler/ha_innodb.h 2010-09-03 17:10:21.694845461 +0900 |
908 | +@@ -221,6 +221,9 @@ |
909 | + /** @} */ |
910 | + bool check_if_incompatible_data(HA_CREATE_INFO *info, |
911 | + uint table_changes); |
912 | ++ |
913 | ++ bool can_rename_index(); |
914 | ++ int rename_index(TABLE *table_arg, const char *from, const char *to); |
915 | + }; |
916 | + |
917 | + /* Some accessor functions which the InnoDB plugin needs, but which |
918 | +diff -ruN a/storage/innodb_plugin/handler/handler0alter.cc b/storage/innodb_plugin/handler/handler0alter.cc |
919 | +--- a/storage/innodb_plugin/handler/handler0alter.cc 2010-08-04 02:24:19.000000000 +0900 |
920 | ++++ b/storage/innodb_plugin/handler/handler0alter.cc 2010-09-03 17:10:21.697204244 +0900 |
921 | +@@ -1241,3 +1241,141 @@ |
922 | + |
923 | + DBUG_RETURN(err); |
924 | + } |
925 | ++ |
926 | ++/* additional methods for rename index feature */ |
927 | ++UNIV_INTERN |
928 | ++bool |
929 | ++ha_innobase::can_rename_index() |
930 | ++{ |
931 | ++ return(true); |
932 | ++} |
933 | ++ |
934 | ++static const char innobase_index_reserve_name[]= "GEN_CLUST_INDEX"; |
935 | ++ |
936 | ++UNIV_INTERN |
937 | ++int |
938 | ++ha_innobase::rename_index( |
939 | ++/*======================*/ |
940 | ++ TABLE* table, |
941 | ++ const char* from, |
942 | ++ const char* to) |
943 | ++{ |
944 | ++ dict_table_t* innodb_table; |
945 | ++ trx_t* trx; |
946 | ++ ibool dict_locked = FALSE; |
947 | ++ int error = 0; |
948 | ++ |
949 | ++ DBUG_ENTER("ha_innobase::rename_index"); |
950 | ++ ut_a(table); |
951 | ++ ut_a(from); |
952 | ++ ut_a(to); |
953 | ++ |
954 | ++ if (srv_created_new_raw || srv_force_recovery) { |
955 | ++ DBUG_RETURN(HA_ERR_WRONG_COMMAND); |
956 | ++ } |
957 | ++ |
958 | ++ update_thd(); |
959 | ++ |
960 | ++ trx_search_latch_release_if_reserved(prebuilt->trx); |
961 | ++ trx_start_if_not_started(prebuilt->trx); |
962 | ++ |
963 | ++ trx = innobase_trx_allocate(user_thd); |
964 | ++ trx_start_if_not_started(trx); |
965 | ++ |
966 | ++ innodb_table = dict_table_get(prebuilt->table->name, FALSE); |
967 | ++ |
968 | ++ if (UNIV_UNLIKELY(!innodb_table)) { |
969 | ++ error = HA_ERR_NO_SUCH_TABLE; |
970 | ++ goto err_exit; |
971 | ++ } |
972 | ++ |
973 | ++ if (innobase_strcasecmp(from, innobase_index_reserve_name) == 0 |
974 | ++ || innobase_strcasecmp(to, innobase_index_reserve_name) == 0) { |
975 | ++ push_warning_printf((THD*) trx->mysql_thd, |
976 | ++ MYSQL_ERROR::WARN_LEVEL_WARN, |
977 | ++ ER_WRONG_NAME_FOR_INDEX, |
978 | ++ "Cannot Create Index with name " |
979 | ++ "'%s'. The name is reserved " |
980 | ++ "for the system default primary " |
981 | ++ "index.", |
982 | ++ innobase_index_reserve_name); |
983 | ++ |
984 | ++ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), |
985 | ++ innobase_index_reserve_name); |
986 | ++ |
987 | ++ error = -1; |
988 | ++ } else { |
989 | ++ for (const dict_index_t* index |
990 | ++ = dict_table_get_first_index(innodb_table); |
991 | ++ index; index = dict_table_get_next_index(index)) { |
992 | ++ if (0 == strcmp(to, index->name)) { |
993 | ++ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), |
994 | ++ to); |
995 | ++ error = ER_WRONG_NAME_FOR_INDEX; |
996 | ++ break; |
997 | ++ } |
998 | ++ } |
999 | ++ } |
1000 | ++ |
1001 | ++ if (UNIV_UNLIKELY(error)) { |
1002 | ++err_exit: |
1003 | ++ trx_general_rollback_for_mysql(trx, NULL); |
1004 | ++ trx_free_for_mysql(trx); |
1005 | ++ trx_commit_for_mysql(prebuilt->trx); |
1006 | ++ DBUG_RETURN(error); |
1007 | ++ } |
1008 | ++ |
1009 | ++ trx_set_dict_operation(trx, TRX_DICT_OP_INDEX); |
1010 | ++ |
1011 | ++ error = row_merge_lock_table(prebuilt->trx, innodb_table, LOCK_X); |
1012 | ++ |
1013 | ++ if (UNIV_UNLIKELY(error != DB_SUCCESS)) { |
1014 | ++ goto error_handling; |
1015 | ++ } |
1016 | ++ |
1017 | ++ row_mysql_lock_data_dictionary(trx); |
1018 | ++ dict_locked = TRUE; |
1019 | ++ |
1020 | ++ /*======================================*/ |
1021 | ++ |
1022 | ++ error = row_rename_index_for_mysql(innodb_table, from, to, trx); |
1023 | ++ |
1024 | ++ /* need to rebuild index translation table? */ |
1025 | ++ //share->idx_trans_tbl.index_count = 0; |
1026 | ++ |
1027 | ++error_handling: |
1028 | ++ switch (error) { |
1029 | ++ case DB_SUCCESS: |
1030 | ++ goto convert_error; |
1031 | ++ case DB_TOO_BIG_RECORD: |
1032 | ++ my_error(HA_ERR_TO_BIG_ROW, MYF(0)); |
1033 | ++ goto error; |
1034 | ++ case DB_PRIMARY_KEY_IS_NULL: |
1035 | ++ my_error(ER_PRIMARY_CANT_HAVE_NULL, MYF(0)); |
1036 | ++ case DB_DUPLICATE_KEY: |
1037 | ++error: |
1038 | ++ prebuilt->trx->error_info = NULL; |
1039 | ++ default: |
1040 | ++ trx->error_state = DB_SUCCESS; |
1041 | ++ |
1042 | ++convert_error: |
1043 | ++ error = convert_error_code_to_mysql(error, |
1044 | ++ innodb_table->flags, |
1045 | ++ user_thd); |
1046 | ++ } |
1047 | ++ |
1048 | ++ trx_commit_for_mysql(trx); |
1049 | ++ if (prebuilt->trx) { |
1050 | ++ trx_commit_for_mysql(prebuilt->trx); |
1051 | ++ } |
1052 | ++ |
1053 | ++ if (dict_locked) { |
1054 | ++ row_mysql_unlock_data_dictionary(trx); |
1055 | ++ } |
1056 | ++ |
1057 | ++ trx_free_for_mysql(trx); |
1058 | ++ |
1059 | ++ srv_active_wake_master_thread(); |
1060 | ++ |
1061 | ++ DBUG_RETURN(error); |
1062 | ++} |
1063 | +diff -ruN a/storage/innodb_plugin/include/row0mysql.h b/storage/innodb_plugin/include/row0mysql.h |
1064 | +--- a/storage/innodb_plugin/include/row0mysql.h 2010-09-03 17:10:00.591203928 +0900 |
1065 | ++++ b/storage/innodb_plugin/include/row0mysql.h 2010-09-03 17:10:21.699166081 +0900 |
1066 | +@@ -523,6 +523,17 @@ |
1067 | + const char* table_name); /*!< in: name of the table, in the |
1068 | + form database/table_name */ |
1069 | + |
1070 | ++/*********************************************************************//** |
1071 | ++*/ |
1072 | ++UNIV_INTERN |
1073 | ++int |
1074 | ++row_rename_index_for_mysql( |
1075 | ++/*=======================*/ |
1076 | ++ dict_table_t* innodb_table, |
1077 | ++ const char* from, |
1078 | ++ const char* to, |
1079 | ++ trx_t* trx); |
1080 | ++ |
1081 | + /* A struct describing a place for an individual column in the MySQL |
1082 | + row format which is presented to the table handler in ha_innobase. |
1083 | + This template struct is used to speed up row transformations between |
1084 | +diff -ruN a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c |
1085 | +--- a/storage/innodb_plugin/row/row0mysql.c 2010-09-03 17:10:01.164135774 +0900 |
1086 | ++++ b/storage/innodb_plugin/row/row0mysql.c 2010-09-03 17:10:21.702166315 +0900 |
1087 | +@@ -4200,3 +4200,53 @@ |
1088 | + |
1089 | + return(FALSE); |
1090 | + } |
1091 | ++ |
1092 | ++/*********************************************************************//** |
1093 | ++*/ |
1094 | ++UNIV_INTERN |
1095 | ++int |
1096 | ++row_rename_index_for_mysql( |
1097 | ++/*=======================*/ |
1098 | ++ dict_table_t* innodb_table, |
1099 | ++ const char* from, |
1100 | ++ const char* to, |
1101 | ++ trx_t* trx) |
1102 | ++{ |
1103 | ++ ulint err; |
1104 | ++ dict_index_t* index; |
1105 | ++ pars_info_t* info = pars_info_create(); |
1106 | ++ static const char rename_index[] = |
1107 | ++ "PROCEDURE RENAME_INDEX_PROC () IS\n" |
1108 | ++ "BEGIN\n" |
1109 | ++ "UPDATE SYS_INDEXES SET NAME=:to_name \n" |
1110 | ++ "WHERE TABLE_ID = :tableid AND NAME=:from_name;\n" |
1111 | ++ "END;\n"; |
1112 | ++ |
1113 | ++ ut_a(trx->dict_operation_lock_mode == RW_X_LATCH); |
1114 | ++ |
1115 | ++ trx->op_info = "renaming index"; |
1116 | ++ |
1117 | ++ /* update dict_mem */ |
1118 | ++ for (index = dict_table_get_first_index(innodb_table); |
1119 | ++ index; index = dict_table_get_next_index(index)) { |
1120 | ++ if (0 == strcmp(from, index->name)) { |
1121 | ++ if (strlen(to) > strlen(index->name)) { |
1122 | ++ index->name = mem_heap_strdup(index->heap, to); |
1123 | ++ } else { |
1124 | ++ memcpy((char*)index->name, to, strlen(to) + 1); |
1125 | ++ } |
1126 | ++ break; |
1127 | ++ } |
1128 | ++ } |
1129 | ++ |
1130 | ++ /* update SYS_INDEXES */ |
1131 | ++ pars_info_add_str_literal(info, "from_name", from); |
1132 | ++ pars_info_add_dulint_literal(info, "tableid", innodb_table->id); |
1133 | ++ pars_info_add_str_literal(info, "to_name", to); |
1134 | ++ |
1135 | ++ err = que_eval_sql(info, rename_index, FALSE, trx); |
1136 | ++ |
1137 | ++ trx->op_info = ""; |
1138 | ++ |
1139 | ++ return(err); |
1140 | ++} |
1141 | +diff -ruN a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h |
1142 | +--- a/storage/myisam/ha_myisam.h 2010-08-04 02:24:27.000000000 +0900 |
1143 | ++++ b/storage/myisam/ha_myisam.h 2010-09-03 17:10:21.704163306 +0900 |
1144 | +@@ -60,6 +60,10 @@ |
1145 | + uint max_supported_key_part_length() const { return MI_MAX_KEY_LENGTH; } |
1146 | + uint checksum() const; |
1147 | + |
1148 | ++ bool can_rename_index() { return 1; } |
1149 | ++ int rename_index(TABLE *table_arg, const char *from, const char *to) |
1150 | ++ { return (0); } /* MyISAM doesn't have index name in other than .frm file */ |
1151 | ++ |
1152 | + int open(const char *name, int mode, uint test_if_locked); |
1153 | + int close(void); |
1154 | + int write_row(uchar * buf); |
1155 | |
1156 | === modified file 'series' |
1157 | --- series 2010-09-03 01:56:58 +0000 |
1158 | +++ series 2010-09-10 02:31:43 +0000 |
1159 | @@ -41,6 +41,8 @@ |
1160 | bugfix48929.patch |
1161 | query_cache_with_comments.patch |
1162 | control_online_alter_index.patch |
1163 | +rename_index.patch |
1164 | +rename_field.patch |
1165 | log_connection_error.patch |
1166 | query_cache_totally_disable.patch |
1167 | mysql-syslog.patch |
1168 | |
1169 | === added file 'series_tmp_ported' |
1170 | --- series_tmp_ported 1970-01-01 00:00:00 +0000 |
1171 | +++ series_tmp_ported 2010-09-10 02:31:43 +0000 |
1172 | @@ -0,0 +1,42 @@ |
1173 | +innodb_swap_builtin_plugin.patch |
1174 | +show_patches.patch |
1175 | +slow_extended.patch |
1176 | +profiling_slow.patch |
1177 | +microsec_process.patch |
1178 | +userstat.patch |
1179 | +optimizer_fix.patch |
1180 | +mysql_dump_ignore_ct.patch |
1181 | +show_temp_51.patch |
1182 | +suppress_log_warning_1592.patch |
1183 | +innodb_show_enhancements.patch |
1184 | +innodb_show_status.patch |
1185 | +innodb_io_patches.patch |
1186 | +innodb_opt_lru_count.patch |
1187 | +i_s_innodb_buffer_pool_pages.patch |
1188 | +innodb_expand_undo_slots.patch |
1189 | +innodb_extra_rseg.patch |
1190 | +innodb_overwrite_relay_log_info.patch |
1191 | +innodb_thread_concurrency_timer_based.patch |
1192 | +innodb_dict_size_limit.patch |
1193 | +innodb_split_buf_pool_mutex.patch |
1194 | +innodb_expand_import.patch |
1195 | +innodb_stats.patch |
1196 | +innodb_recovery_patches.patch |
1197 | +innodb_purge_thread.patch |
1198 | +innodb_admin_command_base.patch |
1199 | +innodb_show_lock_name.patch |
1200 | +innodb_extend_slow.patch |
1201 | +innodb_lru_dump_restore.patch |
1202 | +innodb_separate_doublewrite.patch |
1203 | +innodb_pass_corrupt_table.patch |
1204 | +innodb_fast_checksum.patch |
1205 | +innodb_files_extend.patch |
1206 | +innodb_show_sys_tables.patch |
1207 | +innodb_fix_misc.patch |
1208 | +innodb_adjust_defaults.patch |
1209 | +mysql-test.diff |
1210 | +percona-support.patch |
1211 | +control_online_alter_index.patch |
1212 | +rename_index.patch |
1213 | +rename_field.patch |
1214 | +innodb_buffer_pool_shm.patch |
Yasufumi,
Please provide at least minimal mysql-test on new ALTER TABLE ... RENAME INDEX command.