Merge lp:~tsarev/percona-server/5.1-18205_02_wl36.patch into lp:percona-server/5.1
- 5.1-18205_02_wl36.patch
- Merge into 5.1
Proposed by
Oleg Tsarev
Status: | Superseded |
---|---|
Proposed branch: | lp:~tsarev/percona-server/5.1-18205_02_wl36.patch |
Merge into: | lp:percona-server/5.1 |
Diff against target: |
1037 lines (+572/-29) 24 files modified
Percona-Server/client/Makefile.am (+3/-1) Percona-Server/client/client_priv.h (+1/-0) Percona-Server/client/mysqlbinlog.cc (+159/-9) Percona-Server/client/sql_string.cc (+0/-9) Percona-Server/client/sql_string.h (+5/-0) Percona-Server/mysql-test/include/wl36.inc (+51/-0) Percona-Server/mysql-test/r/mysqlbinlog.result (+2/-6) Percona-Server/mysql-test/r/wl36-mixed.result (+48/-0) Percona-Server/mysql-test/r/wl36-row.result (+48/-0) Percona-Server/mysql-test/r/wl36-statement.result (+48/-0) Percona-Server/mysql-test/t/wl36-mixed.test (+3/-0) Percona-Server/mysql-test/t/wl36-row.test (+3/-0) Percona-Server/mysql-test/t/wl36-statement.test (+3/-0) Percona-Server/sql/log_event.cc (+106/-1) Percona-Server/sql/log_event.h (+16/-2) Percona-Server/sql/mysql_priv.h (+4/-0) Percona-Server/sql/mysqld.cc (+1/-0) Percona-Server/sql/rpl_filter.cc (+9/-0) Percona-Server/sql/rpl_filter.h (+4/-1) Percona-Server/sql/sql_string.cc (+3/-0) Percona-Server/sql/sql_string.h (+9/-0) Percona-Server/sql/thr_malloc.cc (+2/-0) doc/source/flexibility/mysqlbinlog_change_db.rst (+43/-0) doc/source/index.rst (+1/-0) |
To merge this branch: | bzr merge lp:~tsarev/percona-server/5.1-18205_02_wl36.patch |
Related bugs: | |
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Laurynas Biveinis (community) | Needs Information | ||
Review via email: mp+91985@code.launchpad.net |
This proposal has been superseded by a proposal from 2012-02-09.
Commit message
Description of the change
http://
merge wl36.patch from lp:percona-server/rnt-5.1
Feature WL #36 description: http://
To post a comment you must log in.
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote : | # |
review:
Needs Information
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'Percona-Server/client/Makefile.am' |
2 | --- Percona-Server/client/Makefile.am 2011-07-03 15:47:37 +0000 |
3 | +++ Percona-Server/client/Makefile.am 2012-02-09 15:07:20 +0000 |
4 | @@ -24,6 +24,7 @@ |
5 | INCLUDES = -I$(top_builddir)/include \ |
6 | -I$(top_srcdir)/include \ |
7 | -I$(top_srcdir)/regex \ |
8 | + -I$(top_srcdir)/sql \ |
9 | $(openssl_includes) |
10 | |
11 | LIBS = @CLIENT_LIBS@ |
12 | @@ -107,7 +108,8 @@ |
13 | rpl_utility.h rpl_tblmap.h rpl_tblmap.cc \ |
14 | log_event.cc my_decimal.h my_decimal.cc \ |
15 | log_event_old.h log_event_old.cc \ |
16 | - rpl_record_old.h rpl_record_old.cc |
17 | + rpl_record_old.h rpl_record_old.cc \ |
18 | + sql_list.h rpl_filter.h sql_list.cc rpl_filter.cc |
19 | strings_src=decimal.c |
20 | |
21 | link_sources: |
22 | |
23 | === modified file 'Percona-Server/client/client_priv.h' |
24 | --- Percona-Server/client/client_priv.h 2011-11-24 02:01:33 +0000 |
25 | +++ Percona-Server/client/client_priv.h 2012-02-09 15:07:20 +0000 |
26 | @@ -97,6 +97,7 @@ |
27 | OPT_SYSLOG, |
28 | #endif |
29 | OPT_FIRST_SLAVE, |
30 | + OPT_REWRITE_DB, |
31 | OPT_ALL, |
32 | OPT_NO_REMOVE_EOL_CARRET, |
33 | OPT_INNODB_OPTIMIZE_KEYS, |
34 | |
35 | === modified file 'Percona-Server/client/mysqlbinlog.cc' |
36 | --- Percona-Server/client/mysqlbinlog.cc 2011-07-11 16:13:27 +0000 |
37 | +++ Percona-Server/client/mysqlbinlog.cc 2012-02-09 15:07:20 +0000 |
38 | @@ -38,6 +38,15 @@ |
39 | #include "sql_common.h" |
40 | #include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE |
41 | |
42 | +/* Needed for Rpl_filter */ |
43 | +CHARSET_INFO* system_charset_info= &my_charset_utf8_general_ci; |
44 | + |
45 | +#include "sql_string.h" // needed for Rpl_filter |
46 | +#include "sql_list.h" // needed for Rpl_filter |
47 | +#include "rpl_filter.h" |
48 | + |
49 | +Rpl_filter *binlog_filter; |
50 | + |
51 | #define BIN_LOG_HEADER_SIZE 4 |
52 | #define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4) |
53 | |
54 | @@ -623,6 +632,49 @@ |
55 | |
56 | |
57 | /** |
58 | + Print "use <db>" statement when current db is to be changed. |
59 | + |
60 | + We have to control emiting USE statements according to rewrite-db options. |
61 | + We have to do it here (see process_event() below) and to suppress |
62 | + producing USE statements by corresponding log event print-functions. |
63 | +*/ |
64 | +void print_use_stmt(PRINT_EVENT_INFO* pinfo, const char* db, size_t db_len) |
65 | +{ |
66 | + /* |
67 | + pinfo->db is the current db. |
68 | + If current db is the same as required db, do nothing. |
69 | + */ |
70 | + if (!db || !memcmp(pinfo->db, db, db_len + 1)) |
71 | + return; |
72 | + |
73 | + /* |
74 | + Current db and required db are different. |
75 | + Check for rewrite rule for required db. (Note that in a rewrite rule |
76 | + neither db_from nor db_to part can be empty) |
77 | + */ |
78 | + size_t len_to= 0; |
79 | + const char* db_to= binlog_filter->get_rewrite_db(db, &len_to); |
80 | + |
81 | + /* |
82 | + If there is no rewrite rule for db (in this case len_to is left = 0), |
83 | + printing of the corresponding USE statement is left for log event |
84 | + print-function. |
85 | + */ |
86 | + if (!len_to) |
87 | + return; |
88 | + |
89 | + // In case of rewrite rule print USE statement for db_to |
90 | + fprintf(result_file, "use %s%s\n", db_to, pinfo->delimiter); |
91 | + |
92 | + /* |
93 | + Copy the *original* db to pinfo to suppress emiting |
94 | + of USE stmts by log_event print-functions. |
95 | + */ |
96 | + memcpy(pinfo->db, db, db_len + 1); |
97 | +} |
98 | + |
99 | + |
100 | +/** |
101 | Prints the given event in base64 format. |
102 | |
103 | The header is printed to the head cache and the body is printed to |
104 | @@ -741,9 +793,22 @@ |
105 | |
106 | switch (ev_type) { |
107 | case QUERY_EVENT: |
108 | - if (!((Query_log_event*)ev)->is_trans_keyword() && |
109 | - shall_skip_database(((Query_log_event*)ev)->db)) |
110 | - goto end; |
111 | + { |
112 | + Query_log_event *qe= (Query_log_event*)ev; |
113 | + if (!qe->is_trans_keyword()) |
114 | + { |
115 | + if (shall_skip_database(qe->db)) |
116 | + goto end; |
117 | + } |
118 | + else |
119 | + { |
120 | + /* |
121 | + In case the event for one of these statements is obtained |
122 | + from 5.0 binary log, make it compatible with 5.1. |
123 | + */ |
124 | + ev->flags|= LOG_EVENT_SUPPRESS_USE_F; |
125 | + } |
126 | + print_use_stmt(print_event_info, qe->db, qe->db_len); |
127 | if (opt_base64_output_mode == BASE64_OUTPUT_ALWAYS) |
128 | { |
129 | if ((retval= write_event_header_and_base64(ev, result_file, |
130 | @@ -754,6 +819,7 @@ |
131 | else |
132 | ev->print(result_file, print_event_info); |
133 | break; |
134 | + } |
135 | |
136 | case CREATE_FILE_EVENT: |
137 | { |
138 | @@ -875,6 +941,7 @@ |
139 | |
140 | if (!shall_skip_database(exlq->db)) |
141 | { |
142 | + print_use_stmt(print_event_info, exlq->db, exlq->db_len); |
143 | if (fname) |
144 | { |
145 | convert_path_to_forward_slashes(fname); |
146 | @@ -898,6 +965,14 @@ |
147 | destroy_evt= FALSE; |
148 | goto end; |
149 | } |
150 | + size_t len_to= 0; |
151 | + const char* db_to= binlog_filter->get_rewrite_db(map->get_db_name(), |
152 | + &len_to); |
153 | + if (len_to && map->rewrite_db(db_to, len_to, glob_description_event)) |
154 | + { |
155 | + error("Could not rewrite database name"); |
156 | + goto err; |
157 | + } |
158 | } |
159 | case WRITE_ROWS_EVENT: |
160 | case DELETE_ROWS_EVENT: |
161 | @@ -983,15 +1058,19 @@ |
162 | retval= ERROR_STOP; |
163 | end: |
164 | rec_count++; |
165 | + |
166 | + |
167 | /* |
168 | - Destroy the log_event object. If reading from a remote host, |
169 | - set the temp_buf to NULL so that memory isn't freed twice. |
170 | + Destroy the log_event object. |
171 | + MariaDB MWL#36: mainline does this: |
172 | + If reading from a remote host, |
173 | + set the temp_buf to NULL so that memory isn't freed twice. |
174 | + We no longer do that, we use Rpl_filter::event_owns_temp_buf instead. |
175 | */ |
176 | if (ev) |
177 | { |
178 | - if (remote_opt) |
179 | - ev->temp_buf= 0; |
180 | - if (destroy_evt) /* destroy it later if not set (ignored table map) */ |
181 | + /* destroy it later if not set (ignored table map) */ |
182 | + if (destroy_evt) |
183 | delete ev; |
184 | } |
185 | DBUG_RETURN(retval); |
186 | @@ -1156,6 +1235,10 @@ |
187 | "Used to reserve file descriptors for use by this program.", |
188 | &open_files_limit, &open_files_limit, 0, GET_ULONG, |
189 | REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0}, |
190 | + {"rewrite-db", OPT_REWRITE_DB, |
191 | + "Updates to a database with a different name than the original. \ |
192 | +Example: rewrite-db='from->to'.", |
193 | + 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, |
194 | {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} |
195 | }; |
196 | |
197 | @@ -1347,6 +1430,53 @@ |
198 | (find_type_or_exit(argument, &base64_output_mode_typelib, opt->name)-1); |
199 | } |
200 | break; |
201 | + case OPT_REWRITE_DB: // db_from->db_to |
202 | + { |
203 | + /* See also handling of OPT_REPLICATE_REWRITE_DB in sql/mysqld.cc */ |
204 | + char* ptr; |
205 | + char* key= argument; // db-from |
206 | + char* val; // db-to |
207 | + |
208 | + // Where key begins |
209 | + while (*key && my_isspace(&my_charset_latin1, *key)) |
210 | + key++; |
211 | + |
212 | + // Where val begins |
213 | + if (!(ptr= strstr(argument, "->"))) |
214 | + { |
215 | + sql_print_error("Bad syntax in rewrite-db: missing '->'!\n"); |
216 | + return 1; |
217 | + } |
218 | + val= ptr + 2; |
219 | + while (*val && my_isspace(&my_charset_latin1, *val)) |
220 | + val++; |
221 | + |
222 | + // Write \0 and skip blanks at the end of key |
223 | + *ptr-- = 0; |
224 | + while (my_isspace(&my_charset_latin1, *ptr) && ptr > argument) |
225 | + *ptr-- = 0; |
226 | + |
227 | + if (!*key) |
228 | + { |
229 | + sql_print_error("Bad syntax in rewrite-db: empty db-from!\n"); |
230 | + return 1; |
231 | + } |
232 | + |
233 | + // Skip blanks at the end of val |
234 | + ptr= val; |
235 | + while (*ptr && !my_isspace(&my_charset_latin1, *ptr)) |
236 | + ptr++; |
237 | + *ptr= 0; |
238 | + |
239 | + if (!*val) |
240 | + { |
241 | + sql_print_error("Bad syntax in rewrite-db: empty db-to!\n"); |
242 | + return 1; |
243 | + } |
244 | + |
245 | + binlog_filter->add_db_rewrite(key, val); |
246 | + break; |
247 | + } |
248 | case 'v': |
249 | if (argument == disabled_my_option) |
250 | verbose= 0; |
251 | @@ -1616,7 +1746,7 @@ |
252 | If reading from a remote host, ensure the temp_buf for the |
253 | Log_event class is pointing to the incoming stream. |
254 | */ |
255 | - ev->register_temp_buf((char *) net->read_pos + 1); |
256 | + ev->register_temp_buf((char *) net->read_pos + 1, FALSE); |
257 | |
258 | Log_event_type type= ev->get_type_code(); |
259 | if (glob_description_event->binlog_version >= 3 || |
260 | @@ -2016,6 +2146,8 @@ |
261 | return retval; |
262 | } |
263 | |
264 | +/* Used in sql_alloc(). Inited and freed in main() */ |
265 | +MEM_ROOT s_mem_root; |
266 | |
267 | int main(int argc, char** argv) |
268 | { |
269 | @@ -2028,6 +2160,13 @@ |
270 | |
271 | my_init_time(); // for time functions |
272 | |
273 | + init_alloc_root(&s_mem_root, 16384, 0); |
274 | + if (!(binlog_filter= new Rpl_filter)) |
275 | + { |
276 | + error("Failed to create Rpl_filter"); |
277 | + exit(1); |
278 | + } |
279 | + |
280 | if (load_defaults("my", load_default_groups, &argc, &argv)) |
281 | exit(1); |
282 | defaults_argv= argv; |
283 | @@ -2116,6 +2255,8 @@ |
284 | if (result_file != stdout) |
285 | my_fclose(result_file, MYF(0)); |
286 | cleanup(); |
287 | + delete binlog_filter; |
288 | + free_root(&s_mem_root, MYF(0)); |
289 | free_defaults(defaults_argv); |
290 | my_free_open_file_info(); |
291 | load_processor.destroy(); |
292 | @@ -2127,6 +2268,12 @@ |
293 | DBUG_RETURN(retval == ERROR_STOP ? 1 : 0); |
294 | } |
295 | |
296 | + |
297 | +void *sql_alloc(size_t size) |
298 | +{ |
299 | + return alloc_root(&s_mem_root, size); |
300 | +} |
301 | + |
302 | /* |
303 | We must include this here as it's compiled with different options for |
304 | the server |
305 | @@ -2137,4 +2284,7 @@ |
306 | #include "my_decimal.cc" |
307 | #include "log_event.cc" |
308 | #include "log_event_old.cc" |
309 | +#include "sql_string.cc" |
310 | +#include "sql_list.cc" |
311 | +#include "rpl_filter.cc" |
312 | |
313 | |
314 | === modified file 'Percona-Server/client/sql_string.cc' |
315 | --- Percona-Server/client/sql_string.cc 2011-11-01 06:50:54 +0000 |
316 | +++ Percona-Server/client/sql_string.cc 2012-02-09 15:07:20 +0000 |
317 | @@ -28,15 +28,6 @@ |
318 | #ifdef HAVE_FCONVERT |
319 | #include <floatingpoint.h> |
320 | #endif |
321 | - |
322 | -/* |
323 | - The following extern declarations are ok as these are interface functions |
324 | - required by the string function |
325 | -*/ |
326 | - |
327 | -extern void sql_alloc(size_t size); |
328 | -extern void sql_element_free(void *ptr); |
329 | - |
330 | #include "sql_string.h" |
331 | |
332 | /***************************************************************************** |
333 | |
334 | === modified file 'Percona-Server/client/sql_string.h' |
335 | --- Percona-Server/client/sql_string.h 2011-06-30 15:37:13 +0000 |
336 | +++ Percona-Server/client/sql_string.h 2012-02-09 15:07:20 +0000 |
337 | @@ -17,6 +17,9 @@ |
338 | |
339 | /* This file is originally from the mysql distribution. Coded by monty */ |
340 | |
341 | +#ifndef CLIENT_SQL_STRING_H |
342 | +#define CLIENT_SQL_STRING_H |
343 | + |
344 | #ifdef USE_PRAGMA_INTERFACE |
345 | #pragma interface /* gcc class implementation */ |
346 | #endif |
347 | @@ -359,3 +362,5 @@ |
348 | return (s->alloced && Ptr >= s->Ptr && Ptr < s->Ptr + s->str_length); |
349 | } |
350 | }; |
351 | + |
352 | +#endif |
353 | |
354 | === added file 'Percona-Server/mysql-test/include/wl36.inc' |
355 | --- Percona-Server/mysql-test/include/wl36.inc 1970-01-01 00:00:00 +0000 |
356 | +++ Percona-Server/mysql-test/include/wl36.inc 2012-02-09 15:07:20 +0000 |
357 | @@ -0,0 +1,51 @@ |
358 | +# |
359 | +# WL #36: http://askmonty.org/worklog/Server-Sprint/?tid=36 |
360 | +# This is basic test for --rewrite-db option. |
361 | +# mysqlbinlog --rewrite-db="from->to" should rewrite database |
362 | +# |
363 | + |
364 | +CREATE DATABASE a; USE a; CREATE TABLE t1(a INT); |
365 | +CREATE DATABASE b; USE b; CREATE TABLE t1(b INT); |
366 | +CREATE DATABASE c; USE c; CREATE TABLE t1(c INT); |
367 | + |
368 | +RESET MASTER; |
369 | +--let MYSQLD_DATA_DIR=`select @@datadir` |
370 | +--let BIN_LOG_FILE_NAME=query_get_value(show master status, File, 1) |
371 | +--let BIN_LOG_START_POSITION=query_get_value(show master status, Position, 1) |
372 | +USE a; INSERT INTO t1 VALUES(0); |
373 | +USE b; INSERT INTO t1 VALUES(1); |
374 | +--let BIN_LOG_STOP_POSITION=query_get_value(show master status, Position, 1) |
375 | +FLUSH LOGS; |
376 | + |
377 | +--let BIN_LOG_FULL_PATH=`SELECT CONCAT("$MYSQLD_DATA_DIR", "$BIN_LOG_FILE_NAME")` |
378 | + |
379 | +--let i=3 |
380 | +# i=3: rewrite nothing |
381 | +# i=2: rewrite a->c |
382 | +# i=0: rewrite a->b |
383 | +--disable_query_log |
384 | +while ($i) |
385 | +{ |
386 | +--let REWRITE=`SELECT CASE $i WHEN 3 THEN '' WHEN 2 THEN '--rewrite-db="a->c"' WHEN 1 THEN '--rewrite-db="a->b"' END` |
387 | + |
388 | +USE a; DELETE FROM t1; |
389 | +USE b; DELETE FROM t1; |
390 | +USE c; DELETE FROM t1; |
391 | + |
392 | +--echo # |
393 | +--echo # Apply log with '$REWRITE' |
394 | +--echo # |
395 | + |
396 | +--exec $MYSQL_BINLOG $REWRITE --start-position=$BIN_LOG_START_POSITION --stop-position=$BIN_LOG_STOP_POSITION $BIN_LOG_FULL_PATH | $MYSQL |
397 | + |
398 | +USE a; SELECT * FROM t1; |
399 | +USE b; SELECT * FROM t1; |
400 | +USE c; SELECT * FROM t1; |
401 | + |
402 | +dec $i; |
403 | +} |
404 | +--enable_query_log |
405 | + |
406 | +USE a; DROP TABLE t1; DROP DATABASE a; |
407 | +USE b; DROP TABLE t1; DROP DATABASE b; |
408 | +USE c; DROP TABLE t1; DROP DATABASE c; |
409 | |
410 | === modified file 'Percona-Server/mysql-test/r/mysqlbinlog.result' |
411 | --- Percona-Server/mysql-test/r/mysqlbinlog.result 2011-03-25 14:16:13 +0000 |
412 | +++ Percona-Server/mysql-test/r/mysqlbinlog.result 2012-02-09 15:07:20 +0000 |
413 | @@ -220,7 +220,6 @@ |
414 | /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; |
415 | DELIMITER /*!*/; |
416 | ROLLBACK/*!*/; |
417 | -use test/*!*/; |
418 | SET TIMESTAMP=1108844556/*!*/; |
419 | SET @@session.pseudo_thread_id=999999999/*!*/; |
420 | SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; |
421 | @@ -228,6 +227,7 @@ |
422 | SET @@session.collation_database=DEFAULT/*!*/; |
423 | BEGIN |
424 | /*!*/; |
425 | +use test/*!*/; |
426 | SET TIMESTAMP=1108844555/*!*/; |
427 | insert t1 values (1) |
428 | /*!*/; |
429 | @@ -239,7 +239,6 @@ |
430 | /*!40019 SET @@session.max_insert_delayed_threads=0*/; |
431 | /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; |
432 | DELIMITER /*!*/; |
433 | -use test/*!*/; |
434 | SET TIMESTAMP=1108844556/*!*/; |
435 | SET @@session.pseudo_thread_id=999999999/*!*/; |
436 | SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; |
437 | @@ -247,6 +246,7 @@ |
438 | SET @@session.collation_database=DEFAULT/*!*/; |
439 | BEGIN |
440 | /*!*/; |
441 | +use test/*!*/; |
442 | SET TIMESTAMP=1108844555/*!*/; |
443 | insert t1 values (1) |
444 | /*!*/; |
445 | @@ -581,7 +581,6 @@ |
446 | SET @@session.collation_database=DEFAULT/*!*/; |
447 | BEGIN |
448 | /*!*/; |
449 | -use test/*!*/; |
450 | SET TIMESTAMP=1266652094/*!*/; |
451 | SavePoint mixed_cases |
452 | /*!*/; |
453 | @@ -592,11 +591,9 @@ |
454 | SET TIMESTAMP=1266652094/*!*/; |
455 | INSERT INTO db1.t1 VALUES(40) |
456 | /*!*/; |
457 | -use test/*!*/; |
458 | SET TIMESTAMP=1266652094/*!*/; |
459 | ROLLBACK TO mixed_cases |
460 | /*!*/; |
461 | -use db1/*!*/; |
462 | SET TIMESTAMP=1266652094/*!*/; |
463 | INSERT INTO db1.t2 VALUES("after rollback to") |
464 | /*!*/; |
465 | @@ -624,7 +621,6 @@ |
466 | SET @@session.collation_database=DEFAULT/*!*/; |
467 | BEGIN |
468 | /*!*/; |
469 | -use test/*!*/; |
470 | SET TIMESTAMP=1266652094/*!*/; |
471 | SavePoint mixed_cases |
472 | /*!*/; |
473 | |
474 | === added file 'Percona-Server/mysql-test/r/wl36-mixed.result' |
475 | --- Percona-Server/mysql-test/r/wl36-mixed.result 1970-01-01 00:00:00 +0000 |
476 | +++ Percona-Server/mysql-test/r/wl36-mixed.result 2012-02-09 15:07:20 +0000 |
477 | @@ -0,0 +1,48 @@ |
478 | +CREATE DATABASE a; |
479 | +USE a; |
480 | +CREATE TABLE t1(a INT); |
481 | +CREATE DATABASE b; |
482 | +USE b; |
483 | +CREATE TABLE t1(b INT); |
484 | +CREATE DATABASE c; |
485 | +USE c; |
486 | +CREATE TABLE t1(c INT); |
487 | +RESET MASTER; |
488 | +USE a; |
489 | +INSERT INTO t1 VALUES(0); |
490 | +USE b; |
491 | +INSERT INTO t1 VALUES(1); |
492 | +FLUSH LOGS; |
493 | +# |
494 | +# Apply log with '' |
495 | +# |
496 | +a |
497 | +0 |
498 | +b |
499 | +1 |
500 | +c |
501 | +# |
502 | +# Apply log with '--rewrite-db="a->c"' |
503 | +# |
504 | +a |
505 | +b |
506 | +1 |
507 | +c |
508 | +0 |
509 | +# |
510 | +# Apply log with '--rewrite-db="a->b"' |
511 | +# |
512 | +a |
513 | +b |
514 | +0 |
515 | +1 |
516 | +c |
517 | +USE a; |
518 | +DROP TABLE t1; |
519 | +DROP DATABASE a; |
520 | +USE b; |
521 | +DROP TABLE t1; |
522 | +DROP DATABASE b; |
523 | +USE c; |
524 | +DROP TABLE t1; |
525 | +DROP DATABASE c; |
526 | |
527 | === added file 'Percona-Server/mysql-test/r/wl36-row.result' |
528 | --- Percona-Server/mysql-test/r/wl36-row.result 1970-01-01 00:00:00 +0000 |
529 | +++ Percona-Server/mysql-test/r/wl36-row.result 2012-02-09 15:07:20 +0000 |
530 | @@ -0,0 +1,48 @@ |
531 | +CREATE DATABASE a; |
532 | +USE a; |
533 | +CREATE TABLE t1(a INT); |
534 | +CREATE DATABASE b; |
535 | +USE b; |
536 | +CREATE TABLE t1(b INT); |
537 | +CREATE DATABASE c; |
538 | +USE c; |
539 | +CREATE TABLE t1(c INT); |
540 | +RESET MASTER; |
541 | +USE a; |
542 | +INSERT INTO t1 VALUES(0); |
543 | +USE b; |
544 | +INSERT INTO t1 VALUES(1); |
545 | +FLUSH LOGS; |
546 | +# |
547 | +# Apply log with '' |
548 | +# |
549 | +a |
550 | +0 |
551 | +b |
552 | +1 |
553 | +c |
554 | +# |
555 | +# Apply log with '--rewrite-db="a->c"' |
556 | +# |
557 | +a |
558 | +b |
559 | +1 |
560 | +c |
561 | +0 |
562 | +# |
563 | +# Apply log with '--rewrite-db="a->b"' |
564 | +# |
565 | +a |
566 | +b |
567 | +0 |
568 | +1 |
569 | +c |
570 | +USE a; |
571 | +DROP TABLE t1; |
572 | +DROP DATABASE a; |
573 | +USE b; |
574 | +DROP TABLE t1; |
575 | +DROP DATABASE b; |
576 | +USE c; |
577 | +DROP TABLE t1; |
578 | +DROP DATABASE c; |
579 | |
580 | === added file 'Percona-Server/mysql-test/r/wl36-statement.result' |
581 | --- Percona-Server/mysql-test/r/wl36-statement.result 1970-01-01 00:00:00 +0000 |
582 | +++ Percona-Server/mysql-test/r/wl36-statement.result 2012-02-09 15:07:20 +0000 |
583 | @@ -0,0 +1,48 @@ |
584 | +CREATE DATABASE a; |
585 | +USE a; |
586 | +CREATE TABLE t1(a INT); |
587 | +CREATE DATABASE b; |
588 | +USE b; |
589 | +CREATE TABLE t1(b INT); |
590 | +CREATE DATABASE c; |
591 | +USE c; |
592 | +CREATE TABLE t1(c INT); |
593 | +RESET MASTER; |
594 | +USE a; |
595 | +INSERT INTO t1 VALUES(0); |
596 | +USE b; |
597 | +INSERT INTO t1 VALUES(1); |
598 | +FLUSH LOGS; |
599 | +# |
600 | +# Apply log with '' |
601 | +# |
602 | +a |
603 | +0 |
604 | +b |
605 | +1 |
606 | +c |
607 | +# |
608 | +# Apply log with '--rewrite-db="a->c"' |
609 | +# |
610 | +a |
611 | +b |
612 | +1 |
613 | +c |
614 | +0 |
615 | +# |
616 | +# Apply log with '--rewrite-db="a->b"' |
617 | +# |
618 | +a |
619 | +b |
620 | +0 |
621 | +1 |
622 | +c |
623 | +USE a; |
624 | +DROP TABLE t1; |
625 | +DROP DATABASE a; |
626 | +USE b; |
627 | +DROP TABLE t1; |
628 | +DROP DATABASE b; |
629 | +USE c; |
630 | +DROP TABLE t1; |
631 | +DROP DATABASE c; |
632 | |
633 | === added file 'Percona-Server/mysql-test/t/wl36-mixed.test' |
634 | --- Percona-Server/mysql-test/t/wl36-mixed.test 1970-01-01 00:00:00 +0000 |
635 | +++ Percona-Server/mysql-test/t/wl36-mixed.test 2012-02-09 15:07:20 +0000 |
636 | @@ -0,0 +1,3 @@ |
637 | +--source include/have_log_bin.inc |
638 | +--source include/have_binlog_format_mixed.inc |
639 | +--source include/wl36.inc |
640 | |
641 | === added file 'Percona-Server/mysql-test/t/wl36-row.test' |
642 | --- Percona-Server/mysql-test/t/wl36-row.test 1970-01-01 00:00:00 +0000 |
643 | +++ Percona-Server/mysql-test/t/wl36-row.test 2012-02-09 15:07:20 +0000 |
644 | @@ -0,0 +1,3 @@ |
645 | +--source include/have_log_bin.inc |
646 | +--source include/have_binlog_format_row.inc |
647 | +--source include/wl36.inc |
648 | |
649 | === added file 'Percona-Server/mysql-test/t/wl36-statement.test' |
650 | --- Percona-Server/mysql-test/t/wl36-statement.test 1970-01-01 00:00:00 +0000 |
651 | +++ Percona-Server/mysql-test/t/wl36-statement.test 2012-02-09 15:07:20 +0000 |
652 | @@ -0,0 +1,3 @@ |
653 | +--source include/have_log_bin.inc |
654 | +--source include/have_binlog_format_statement.inc |
655 | +--source include/wl36.inc |
656 | |
657 | === modified file 'Percona-Server/sql/log_event.cc' |
658 | --- Percona-Server/sql/log_event.cc 2012-01-30 04:30:33 +0000 |
659 | +++ Percona-Server/sql/log_event.cc 2012-02-09 15:07:20 +0000 |
660 | @@ -1134,7 +1134,7 @@ |
661 | goto err; |
662 | } |
663 | if ((res= read_log_event(buf, data_len, &error, description_event))) |
664 | - res->register_temp_buf(buf); |
665 | + res->register_temp_buf(buf, TRUE); |
666 | |
667 | err: |
668 | UNLOCK_MUTEX; |
669 | @@ -8271,6 +8271,111 @@ |
670 | my_free(m_memory, MYF(MY_ALLOW_ZERO_PTR)); |
671 | } |
672 | |
673 | + |
674 | +#ifdef MYSQL_CLIENT |
675 | + |
676 | +/* |
677 | + Rewrite database name for the event to name specified by new_db |
678 | + SYNOPSIS |
679 | + new_db Database name to change to |
680 | + new_len Length |
681 | + desc Event describing binlog that we're writing to. |
682 | + |
683 | + DESCRIPTION |
684 | + Reset db name. This function assumes that temp_buf member contains event |
685 | + representation taken from a binary log. It resets m_dbnam and m_dblen and |
686 | + rewrites temp_buf with new db name. |
687 | + |
688 | + RETURN |
689 | + 0 - Success |
690 | + other - Error |
691 | +*/ |
692 | + |
693 | +int Table_map_log_event::rewrite_db(const char* new_db, size_t new_len, |
694 | + const Format_description_log_event* desc) |
695 | +{ |
696 | + DBUG_ENTER("Table_map_log_event::rewrite_db"); |
697 | + DBUG_ASSERT(temp_buf); |
698 | + |
699 | + uint header_len= min(desc->common_header_len, |
700 | + LOG_EVENT_MINIMAL_HEADER_LEN) + TABLE_MAP_HEADER_LEN; |
701 | + int len_diff; |
702 | + |
703 | + if (!(len_diff= new_len - m_dblen)) |
704 | + { |
705 | + memcpy((void*) (temp_buf + header_len + 1), new_db, m_dblen + 1); |
706 | + memcpy((void*) m_dbnam, new_db, m_dblen + 1); |
707 | + DBUG_RETURN(0); |
708 | + } |
709 | + |
710 | + // Create new temp_buf |
711 | + ulong event_cur_len= uint4korr(temp_buf + EVENT_LEN_OFFSET); |
712 | + ulong event_new_len= event_cur_len + len_diff; |
713 | + char* new_temp_buf= (char*) my_malloc(event_new_len, MYF(MY_WME)); |
714 | + |
715 | + if (!new_temp_buf) |
716 | + { |
717 | + sql_print_error("Table_map_log_event::rewrite_db: " |
718 | + "failed to allocate new temp_buf (%d bytes required)", |
719 | + event_new_len); |
720 | + DBUG_RETURN(-1); |
721 | + } |
722 | + |
723 | + // Rewrite temp_buf |
724 | + char* ptr= new_temp_buf; |
725 | + ulong cnt= 0; |
726 | + |
727 | + // Copy header and change event length |
728 | + memcpy(ptr, temp_buf, header_len); |
729 | + int4store(ptr + EVENT_LEN_OFFSET, event_new_len); |
730 | + ptr += header_len; |
731 | + cnt += header_len; |
732 | + |
733 | + // Write new db name length and new name |
734 | + *ptr++ = new_len; |
735 | + memcpy(ptr, new_db, new_len + 1); |
736 | + ptr += new_len + 1; |
737 | + cnt += m_dblen + 2; |
738 | + |
739 | + // Copy rest part |
740 | + memcpy(ptr, temp_buf + cnt, event_cur_len - cnt); |
741 | + |
742 | + // Reregister temp buf |
743 | + free_temp_buf(); |
744 | + register_temp_buf(new_temp_buf, TRUE); |
745 | + |
746 | + // Reset m_dbnam and m_dblen members |
747 | + m_dblen= new_len; |
748 | + |
749 | + // m_dbnam resides in m_memory together with m_tblnam and m_coltype |
750 | + uchar* memory= m_memory; |
751 | + char const* tblnam= m_tblnam; |
752 | + uchar* coltype= m_coltype; |
753 | + |
754 | + m_memory= (uchar*) my_multi_malloc(MYF(MY_WME), |
755 | + &m_dbnam, (uint) m_dblen + 1, |
756 | + &m_tblnam, (uint) m_tbllen + 1, |
757 | + &m_coltype, (uint) m_colcnt, |
758 | + NullS); |
759 | + |
760 | + if (!m_memory) |
761 | + { |
762 | + sql_print_error("Table_map_log_event::rewrite_db: " |
763 | + "failed to allocate new m_memory (%d + %d + %d bytes required)", |
764 | + m_dblen + 1, m_tbllen + 1, m_colcnt); |
765 | + DBUG_RETURN(-1); |
766 | + } |
767 | + |
768 | + memcpy((void*)m_dbnam, new_db, m_dblen + 1); |
769 | + memcpy((void*)m_tblnam, tblnam, m_tbllen + 1); |
770 | + memcpy(m_coltype, coltype, m_colcnt); |
771 | + |
772 | + my_free(memory, MYF(MY_WME)); |
773 | + DBUG_RETURN(0); |
774 | +} |
775 | +#endif /* MYSQL_CLIENT */ |
776 | + |
777 | + |
778 | /* |
779 | Return value is an error code, one of: |
780 | |
781 | |
782 | === modified file 'Percona-Server/sql/log_event.h' |
783 | --- Percona-Server/sql/log_event.h 2012-01-30 04:30:33 +0000 |
784 | +++ Percona-Server/sql/log_event.h 2012-02-09 15:07:20 +0000 |
785 | @@ -889,6 +889,13 @@ |
786 | event's type, and its content is distributed in the event-specific fields. |
787 | */ |
788 | char *temp_buf; |
789 | + |
790 | + /* |
791 | + TRUE <=> this event 'owns' temp_buf and should call my_free() when done |
792 | + with it |
793 | + */ |
794 | + bool event_owns_temp_buf; |
795 | + |
796 | /* |
797 | Timestamp on the master(for debugging and replication of |
798 | NOW()/TIMESTAMP). It is important for queries and LOAD DATA |
799 | @@ -1030,12 +1037,17 @@ |
800 | Log_event(const char* buf, const Format_description_log_event |
801 | *description_event); |
802 | virtual ~Log_event() { free_temp_buf();} |
803 | - void register_temp_buf(char* buf) { temp_buf = buf; } |
804 | + void register_temp_buf(char* buf, bool must_free) |
805 | + { |
806 | + temp_buf= buf; |
807 | + event_owns_temp_buf= must_free; |
808 | + } |
809 | void free_temp_buf() |
810 | { |
811 | if (temp_buf) |
812 | { |
813 | - my_free(temp_buf, MYF(0)); |
814 | + if (event_owns_temp_buf) |
815 | + my_free(temp_buf, MYF(0)); |
816 | temp_buf = 0; |
817 | } |
818 | } |
819 | @@ -3360,6 +3372,8 @@ |
820 | ulong get_table_id() const { return m_table_id; } |
821 | const char *get_table_name() const { return m_tblnam; } |
822 | const char *get_db_name() const { return m_dbnam; } |
823 | + int rewrite_db(const char* new_name, size_t new_name_len, |
824 | + const Format_description_log_event*); |
825 | #endif |
826 | |
827 | virtual Log_event_type get_type_code() { return TABLE_MAP_EVENT; } |
828 | |
829 | === modified file 'Percona-Server/sql/mysql_priv.h' |
830 | --- Percona-Server/sql/mysql_priv.h 2011-11-24 02:01:21 +0000 |
831 | +++ Percona-Server/sql/mysql_priv.h 2012-02-09 15:07:20 +0000 |
832 | @@ -93,12 +93,16 @@ |
833 | #include "unireg.h" |
834 | |
835 | void init_sql_alloc(MEM_ROOT *root, uint block_size, uint pre_alloc_size); |
836 | +#endif // MYSQL_CLIENT |
837 | + |
838 | void *sql_alloc(size_t); |
839 | void *sql_calloc(size_t); |
840 | char *sql_strdup(const char *str); |
841 | char *sql_strmake(const char *str, size_t len); |
842 | void *sql_memdup(const void * ptr, size_t size); |
843 | void sql_element_free(void *ptr); |
844 | + |
845 | +#ifndef MYSQL_CLIENT |
846 | char *sql_strmake_with_convert(const char *str, size_t arg_length, |
847 | CHARSET_INFO *from_cs, |
848 | size_t max_res_length, |
849 | |
850 | === modified file 'Percona-Server/sql/mysqld.cc' |
851 | --- Percona-Server/sql/mysqld.cc 2012-02-07 03:25:46 +0000 |
852 | +++ Percona-Server/sql/mysqld.cc 2012-02-09 15:07:20 +0000 |
853 | @@ -8469,6 +8469,7 @@ |
854 | } |
855 | case (int)OPT_REPLICATE_REWRITE_DB: |
856 | { |
857 | + /* See also OPT_REWRITE_DB handling in client/mysqlbinlog.cc */ |
858 | char* key = argument,*p, *val; |
859 | |
860 | if (!(p= strstr(argument, "->"))) |
861 | |
862 | === modified file 'Percona-Server/sql/rpl_filter.cc' |
863 | --- Percona-Server/sql/rpl_filter.cc 2011-06-30 15:37:13 +0000 |
864 | +++ Percona-Server/sql/rpl_filter.cc 2012-02-09 15:07:20 +0000 |
865 | @@ -48,6 +48,7 @@ |
866 | } |
867 | |
868 | |
869 | +#ifndef MYSQL_CLIENT |
870 | /* |
871 | Returns true if table should be logged/replicated |
872 | |
873 | @@ -132,6 +133,7 @@ |
874 | !do_table_inited && !wild_do_table_inited); |
875 | } |
876 | |
877 | +#endif |
878 | |
879 | /* |
880 | Checks whether a db matches some do_db and ignore_db rules |
881 | @@ -517,6 +519,13 @@ |
882 | } |
883 | |
884 | |
885 | +bool |
886 | +Rpl_filter::rewrite_db_is_empty() |
887 | +{ |
888 | + return rewrite_db.is_empty(); |
889 | +} |
890 | + |
891 | + |
892 | const char* |
893 | Rpl_filter::get_rewrite_db(const char* db, size_t *new_len) |
894 | { |
895 | |
896 | === modified file 'Percona-Server/sql/rpl_filter.h' |
897 | --- Percona-Server/sql/rpl_filter.h 2007-05-10 09:59:39 +0000 |
898 | +++ Percona-Server/sql/rpl_filter.h 2012-02-09 15:07:20 +0000 |
899 | @@ -42,7 +42,9 @@ |
900 | |
901 | /* Checks - returns true if ok to replicate/log */ |
902 | |
903 | - bool tables_ok(const char* db, TABLE_LIST* tables); |
904 | +#ifndef MYSQL_CLIENT |
905 | + bool tables_ok(const char* db, TABLE_LIST *tables); |
906 | +#endif |
907 | bool db_ok(const char* db); |
908 | bool db_ok_with_wild_table(const char *db); |
909 | |
910 | @@ -69,6 +71,7 @@ |
911 | void get_wild_do_table(String* str); |
912 | void get_wild_ignore_table(String* str); |
913 | |
914 | + bool rewrite_db_is_empty(); |
915 | const char* get_rewrite_db(const char* db, size_t *new_len); |
916 | |
917 | I_List<i_string>* get_do_db(); |
918 | |
919 | === modified file 'Percona-Server/sql/sql_string.cc' |
920 | --- Percona-Server/sql/sql_string.cc 2011-10-31 09:10:04 +0000 |
921 | +++ Percona-Server/sql/sql_string.cc 2012-02-09 15:07:20 +0000 |
922 | @@ -39,6 +39,9 @@ |
923 | |
924 | #include "sql_string.h" |
925 | |
926 | +#ifdef MYSQL_CLIENT |
927 | +#error Attempt to use server-side sql_string on client. Use client/sql_string.cc |
928 | +#endif |
929 | /***************************************************************************** |
930 | ** String functions |
931 | *****************************************************************************/ |
932 | |
933 | === modified file 'Percona-Server/sql/sql_string.h' |
934 | --- Percona-Server/sql/sql_string.h 2011-07-03 15:47:37 +0000 |
935 | +++ Percona-Server/sql/sql_string.h 2012-02-09 15:07:20 +0000 |
936 | @@ -1,3 +1,6 @@ |
937 | +#ifndef MYSQL_SQL_STRING_H_INCLUDED |
938 | +#define MYSQL_SQL_STRING_H_INCLUDED |
939 | + |
940 | /* |
941 | Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. |
942 | |
943 | @@ -25,6 +28,10 @@ |
944 | #define NOT_FIXED_DEC 31 |
945 | #endif |
946 | |
947 | +#ifdef MYSQL_CLIENT |
948 | +#error Attempt to use server-side sql_string on client. Use client/sql_string.h |
949 | +#endif |
950 | + |
951 | class String; |
952 | int sortcmp(const String *a,const String *b, CHARSET_INFO *cs); |
953 | String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); |
954 | @@ -408,3 +415,5 @@ |
955 | { |
956 | return str+ cs->cset->scan(cs, str, end, MY_SEQ_SPACES) == end; |
957 | } |
958 | + |
959 | +#endif // MYSQL_SQL_STRING_H_INCLUDED |
960 | |
961 | === modified file 'Percona-Server/sql/thr_malloc.cc' |
962 | --- Percona-Server/sql/thr_malloc.cc 2011-06-30 15:37:13 +0000 |
963 | +++ Percona-Server/sql/thr_malloc.cc 2012-02-09 15:07:20 +0000 |
964 | @@ -65,11 +65,13 @@ |
965 | } |
966 | |
967 | |
968 | +#ifndef MYSQL_CLIENT |
969 | void *sql_alloc(size_t Size) |
970 | { |
971 | MEM_ROOT *root= *my_pthread_getspecific_ptr(MEM_ROOT**,THR_MALLOC); |
972 | return alloc_root(root,Size); |
973 | } |
974 | +#endif |
975 | |
976 | |
977 | void *sql_calloc(size_t size) |
978 | |
979 | === added file 'doc/source/flexibility/mysqlbinlog_change_db.rst' |
980 | --- doc/source/flexibility/mysqlbinlog_change_db.rst 1970-01-01 00:00:00 +0000 |
981 | +++ doc/source/flexibility/mysqlbinlog_change_db.rst 2012-02-09 15:07:20 +0000 |
982 | @@ -0,0 +1,43 @@ |
983 | +.. _mysqlbinlog_change_db: |
984 | + |
985 | +========================= |
986 | +Ability to change database for mysqlbinlog |
987 | +========================= |
988 | + |
989 | +Sometimes there is a need to take a binary log and apply it to a database with |
990 | +a different name than the original name of the database on binlog producer. |
991 | + |
992 | +If one is using statement-based replication, he can achieve this by grepping |
993 | +out "USE dbname" statements out of the output of mysqlbinlog(*). With |
994 | +row-based replication this is no longer possible, as database name is encoded |
995 | +within the the BINLOG '....' statement. |
996 | + |
997 | +This task is about adding an option to mysqlbinlog that would allow to change |
998 | +the names of used databases in both RBR and SBR events. |
999 | + |
1000 | +Varible :variable:`rewrite-db` of **mysqlbinlog** utility allows to setup rewriting rule "from->"to". |
1001 | + |
1002 | +Version Specific Information |
1003 | +============================ |
1004 | + |
1005 | + * 5.1.62-12.1 |
1006 | + Full functionality. |
1007 | + |
1008 | +Client Command Line Parameter |
1009 | +============================= |
1010 | + |
1011 | +.. variable:: rewrite-db |
1012 | + |
1013 | + :cli: Yes |
1014 | + :conf: Yes |
1015 | + :scope: Global |
1016 | + :dyn: No |
1017 | + :vartype: String |
1018 | + :default: Off |
1019 | + |
1020 | + |
1021 | +Related Reading |
1022 | +=============== |
1023 | + |
1024 | + * `WL #36 <http://askmonty.org/worklog/Server-Sprint/?tid=36>`_ |
1025 | + |
1026 | |
1027 | === modified file 'doc/source/index.rst' |
1028 | --- doc/source/index.rst 2012-01-31 10:35:01 +0000 |
1029 | +++ doc/source/index.rst 2012-02-09 15:07:20 +0000 |
1030 | @@ -88,6 +88,7 @@ |
1031 | flexibility/innodb_files_extend |
1032 | flexibility/log_warnings_suppress |
1033 | flexibility/mysql_remove_eol_carret |
1034 | + flexibility/mysqlbinlog_change_db |
1035 | flexibility/replication_skip_single_statement |
1036 | flexibility/buff_read_ahead_area |
1037 | flexibility/innodb_fast_shutdown |
For the feature branch to go in, it needs an associated blueprint on Launchpad.