1 /* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 02110-1301 USA */
23
24
25 /*
26 In here, we rewrite queries (to obfuscate passwords etc.) that need it
27 before we log them.
28
29 Stored procedures may also rewrite their statements (to show the actual
30 values of their variables etc.). There is currently no scenario where
31 a statement can be eligible for both rewrites. (see sp_instr.cc)
32 Special consideration will need to be taken if this assertion is changed.
33
34 We also do not intersect with query cache at this time, as QC only
35 caches SELECTs (which we don't rewrite). If and when QC becomes more
36 general, it should probably cache the rewritten query along with the
37 user-submitted one. (see sql_parse.cc)
38 */
39
40
41 #include "sql_acl.h" // append_user
42 #include "sql_parse.h" // get_current_user
43 #include "sql_show.h" // append_identifier
44 #include "sp_head.h" // struct set_var_base
45 #include "rpl_slave.h" // SLAVE_SQL, SLAVE_IO
46
47
48 /**
49 Append a key/value pair to a string, with an optional preceeding comma.
50 For numeric values.
51
52 @param str The string to append to
53 @param comma Prepend a comma?
54 @param txt C-string, must end in a space
55 @param len strlen(txt)
56 @param val numeric value
57 @param cond only append if this evaluates to true
58
59 @retval false if any subsequent key/value pair would be the first
60 */
61
append_int(String * str,bool comma,const char * txt,size_t len,long val,int cond)62 bool append_int(String *str, bool comma, const char *txt, size_t len,
63 long val, int cond)
64 {
65 if (cond)
66 {
67 String numbuf(42);
68 if (comma)
69 str->append(STRING_WITH_LEN(", "));
70 str->append(txt,len);
71 numbuf.set((longlong)val,&my_charset_bin);
72 str->append(numbuf);
73 return true;
74 }
75 return comma;
76 }
77
78
79 /**
80 Append a key/value pair to a string if the value is non-NULL,
81 with an optional preceeding comma.
82
83 @param str The string to append to
84 @param comma Prepend a comma?
85 @param key C-string: the key, must be non-NULL
86 @param val C-string: the value
87
88 @retval false if any subsequent key/value pair would be the first
89 */
90
append_str(String * str,bool comma,const char * key,char * val)91 bool append_str(String *str, bool comma, const char *key, char *val)
92 {
93 if (val)
94 {
95 if (comma)
96 str->append(STRING_WITH_LEN(", "));
97 str->append(key);
98 str->append(STRING_WITH_LEN(" '"));
99 str->append(val);
100 str->append(STRING_WITH_LEN("'"));
101 return true;
102 }
103 return comma;
104 }
105
106
107 /**
108 Rewrite a GRANT statement.
109
110 @param thd The THD to rewrite for.
111 @param rlb An empty String object to put the rewritten query in.
112 */
113
mysql_rewrite_grant(THD * thd,String * rlb)114 static void mysql_rewrite_grant(THD *thd, String *rlb)
115 {
116 LEX *lex= thd->lex;
117 TABLE_LIST *first_table= (TABLE_LIST*) lex->select_lex.table_list.first;
118 bool comma= FALSE, comma_inner;
119 bool proxy_grant= lex->type == TYPE_ENUM_PROXY;
120 String cols(1024);
121 int c;
122
123 rlb->append(STRING_WITH_LEN("GRANT "));
124 if (proxy_grant)
125 rlb->append(STRING_WITH_LEN("PROXY"));
126 else if (lex->all_privileges)
127 rlb->append(STRING_WITH_LEN("ALL PRIVILEGES"));
128 else
129 {
130 ulong priv;
131
132 for (c= 0, priv= SELECT_ACL; priv <= GLOBAL_ACLS; c++, priv <<= 1)
133 {
134 if (priv == GRANT_ACL)
135 continue;
136
137 comma_inner= FALSE;
138
139 if (lex->columns.elements) // show columns, if any
140 {
141 class LEX_COLUMN *column;
142 List_iterator <LEX_COLUMN> column_iter(lex->columns);
143
144 cols.length(0);
145 cols.append(STRING_WITH_LEN(" ("));
146
147 /*
148 If the statement was GRANT SELECT(f2), INSERT(f3), UPDATE(f1,f3, f2),
149 our list cols will contain the order f2, f3, f1, and thus that's
150 the order we'll recreate the privilege: UPDATE (f2, f3, f1)
151 */
152
153 while ((column= column_iter++))
154 {
155 if (column->rights & priv)
156 {
157 if (comma_inner)
158 cols.append(STRING_WITH_LEN(", "));
159 else
160 comma_inner= TRUE;
161 cols.append(column->column.ptr(),column->column.length());
162 }
163 }
164 cols.append(STRING_WITH_LEN(")"));
165 }
166
167 if (comma_inner || (lex->grant & priv)) // show privilege name
168 {
169 if (comma)
170 rlb->append(STRING_WITH_LEN(", "));
171 else
172 comma= TRUE;
173 rlb->append(command_array[c],command_lengths[c]);
174 if (!(lex->grant & priv)) // general outranks specific
175 rlb->append(cols);
176 }
177 }
178 if (!comma) // no privs, default to USAGE
179 rlb->append(STRING_WITH_LEN("USAGE"));
180 }
181
182 rlb->append(STRING_WITH_LEN(" ON "));
183 switch(lex->type)
184 {
185 case TYPE_ENUM_PROCEDURE: rlb->append(STRING_WITH_LEN("PROCEDURE ")); break;
186 case TYPE_ENUM_FUNCTION: rlb->append(STRING_WITH_LEN("FUNCTION ")); break;
187 default: break;
188 }
189
190 LEX_USER *user_name, *tmp_user_name;
191 List_iterator <LEX_USER> user_list(lex->users_list);
192 comma= FALSE;
193
194 if (proxy_grant)
195 {
196 tmp_user_name= user_list++;
197 user_name= get_current_user(thd, tmp_user_name);
198 if (user_name)
199 append_user(thd, rlb, user_name, comma, true);
200 }
201 else if (first_table)
202 {
203 append_identifier(thd, rlb, first_table->db, strlen(first_table->db));
204 rlb->append(STRING_WITH_LEN("."));
205 append_identifier(thd, rlb, first_table->table_name,
206 strlen(first_table->table_name));
207 }
208 else
209 {
210 if (lex->current_select->db)
211 append_identifier(thd, rlb, lex->current_select->db,
212 strlen(lex->current_select->db));
213 else
214 rlb->append("*");
215 rlb->append(STRING_WITH_LEN(".*"));
216 }
217
218 rlb->append(STRING_WITH_LEN(" TO "));
219 {
220 while ((tmp_user_name= user_list++))
221 {
222 if ((user_name= get_current_user(thd, tmp_user_name)))
223 {
224 append_user(thd, rlb, user_name, comma, true);
225 comma= TRUE;
226 }
227 }
228 }
229
230 if (lex->ssl_type != SSL_TYPE_NOT_SPECIFIED)
231 {
232 rlb->append(STRING_WITH_LEN(" REQUIRE"));
233 switch (lex->ssl_type)
234 {
235 case SSL_TYPE_SPECIFIED:
236 if (lex->x509_subject)
237 {
238 rlb->append(STRING_WITH_LEN(" SUBJECT '"));
239 rlb->append(lex->x509_subject);
240 rlb->append(STRING_WITH_LEN("'"));
241 }
242 if (lex->x509_issuer)
243 {
244 rlb->append(STRING_WITH_LEN(" ISSUER '"));
245 rlb->append(lex->x509_issuer);
246 rlb->append(STRING_WITH_LEN("'"));
247 }
248 if (lex->ssl_cipher)
249 {
250 rlb->append(STRING_WITH_LEN(" CIPHER '"));
251 rlb->append(lex->ssl_cipher);
252 rlb->append(STRING_WITH_LEN("'"));
253 }
254 break;
255 case SSL_TYPE_X509:
256 rlb->append(STRING_WITH_LEN(" X509"));
257 break;
258 case SSL_TYPE_ANY:
259 rlb->append(STRING_WITH_LEN(" SSL"));
260 break;
261 case SSL_TYPE_NOT_SPECIFIED:
262 /* fall-thru */
263 case SSL_TYPE_NONE:
264 rlb->append(STRING_WITH_LEN(" NONE"));
265 break;
266 }
267 }
268
269 if (lex->mqh.specified_limits || (lex->grant & GRANT_ACL))
270 {
271 rlb->append(STRING_WITH_LEN(" WITH"));
272 if (lex->grant & GRANT_ACL)
273 rlb->append(STRING_WITH_LEN(" GRANT OPTION"));
274
275 append_int(rlb, false, STRING_WITH_LEN(" MAX_QUERIES_PER_HOUR "),
276 lex->mqh.questions,
277 lex->mqh.specified_limits & USER_RESOURCES::QUERIES_PER_HOUR);
278
279 append_int(rlb, false, STRING_WITH_LEN(" MAX_UPDATES_PER_HOUR "),
280 lex->mqh.updates,
281 lex->mqh.specified_limits & USER_RESOURCES::UPDATES_PER_HOUR);
282
283 append_int(rlb, false, STRING_WITH_LEN(" MAX_CONNECTIONS_PER_HOUR "),
284 lex->mqh.conn_per_hour,
285 lex->mqh.specified_limits & USER_RESOURCES::CONNECTIONS_PER_HOUR);
286
287 append_int(rlb, false, STRING_WITH_LEN(" MAX_USER_CONNECTIONS "),
288 lex->mqh.user_conn,
289 lex->mqh.specified_limits & USER_RESOURCES::USER_CONNECTIONS);
290 }
291 }
292
293
294 /**
295 Rewrite a SET statement.
296
297 @param thd The THD to rewrite for.
298 @param rlb An empty String object to put the rewritten query in.
299 */
300
mysql_rewrite_set(THD * thd,String * rlb)301 static void mysql_rewrite_set(THD *thd, String *rlb)
302 {
303 LEX *lex= thd->lex;
304 List_iterator_fast<set_var_base> it(lex->var_list);
305 set_var_base *var;
306 bool comma= FALSE;
307
308 rlb->append(STRING_WITH_LEN("SET "));
309
310 while ((var= it++))
311 {
312 if (comma)
313 rlb->append(STRING_WITH_LEN(","));
314 else
315 comma= TRUE;
316
317 var->print(thd, rlb);
318 }
319 }
320
321
322 /**
323 Rewrite CREATE USER statement.
324
325 @param thd The THD to rewrite for.
326 @param rlb An empty String object to put the rewritten query in.
327 */
328
mysql_rewrite_create_user(THD * thd,String * rlb)329 static void mysql_rewrite_create_user(THD *thd, String *rlb)
330 {
331 LEX *lex= thd->lex;
332 LEX_USER *user_name, *tmp_user_name;
333 List_iterator <LEX_USER> user_list(lex->users_list);
334 bool comma= FALSE;
335
336 rlb->append(STRING_WITH_LEN("CREATE USER "));
337 while ((tmp_user_name= user_list++))
338 {
339 if ((user_name= get_current_user(thd, tmp_user_name)))
340 {
341 append_user(thd, rlb, user_name, comma, TRUE);
342 comma= TRUE;
343 }
344 }
345 }
346
347
348 /**
349 Rewrite a CHANGE MASTER statement.
350
351 @param thd The THD to rewrite for.
352 @param rlb An empty String object to put the rewritten query in.
353 */
354
mysql_rewrite_change_master(THD * thd,String * rlb)355 static void mysql_rewrite_change_master(THD *thd, String *rlb)
356 {
357 LEX *lex= thd->lex;
358
359 rlb->append(STRING_WITH_LEN("CHANGE MASTER TO"));
360
361 if (lex->mi.host)
362 {
363 rlb->append(STRING_WITH_LEN(" MASTER_HOST = '"));
364 rlb->append(lex->mi.host);
365 rlb->append(STRING_WITH_LEN("'"));
366 }
367 if (lex->mi.user)
368 {
369 rlb->append(STRING_WITH_LEN(" MASTER_USER = '"));
370 rlb->append(lex->mi.user);
371 rlb->append(STRING_WITH_LEN("'"));
372 }
373 if (lex->mi.password)
374 {
375 rlb->append(STRING_WITH_LEN(" MASTER_PASSWORD = <secret>"));
376 }
377 if (lex->mi.port)
378 {
379 rlb->append(STRING_WITH_LEN(" MASTER_PORT = "));
380 rlb->append_ulonglong(lex->mi.port);
381 }
382 if (lex->mi.connect_retry)
383 {
384 rlb->append(STRING_WITH_LEN(" MASTER_CONNECT_RETRY = "));
385 rlb->append_ulonglong(lex->mi.connect_retry);
386 }
387 if (lex->mi.ssl)
388 {
389 rlb->append(STRING_WITH_LEN(" MASTER_SSL = "));
390 rlb->append(lex->mi.ssl == LEX_MASTER_INFO::LEX_MI_ENABLE ? "1" : "0");
391 }
392 if (lex->mi.ssl_ca)
393 {
394 rlb->append(STRING_WITH_LEN(" MASTER_SSL_CA = '"));
395 rlb->append(lex->mi.ssl_ca);
396 rlb->append(STRING_WITH_LEN("'"));
397 }
398 if (lex->mi.ssl_capath)
399 {
400 rlb->append(STRING_WITH_LEN(" MASTER_SSL_CAPATH = '"));
401 rlb->append(lex->mi.ssl_capath);
402 rlb->append(STRING_WITH_LEN("'"));
403 }
404 if (lex->mi.ssl_cert)
405 {
406 rlb->append(STRING_WITH_LEN(" MASTER_SSL_CERT = '"));
407 rlb->append(lex->mi.ssl_cert);
408 rlb->append(STRING_WITH_LEN("'"));
409 }
410 if (lex->mi.ssl_cipher)
411 {
412 rlb->append(STRING_WITH_LEN(" MASTER_SSL_CIPHER = '"));
413 rlb->append(lex->mi.ssl_cipher);
414 rlb->append(STRING_WITH_LEN("'"));
415 }
416 if (lex->mi.ssl_key)
417 {
418 rlb->append(STRING_WITH_LEN(" MASTER_SSL_KEY = '"));
419 rlb->append(lex->mi.ssl_key);
420 rlb->append(STRING_WITH_LEN("'"));
421 }
422 if (lex->mi.log_file_name)
423 {
424 rlb->append(STRING_WITH_LEN(" MASTER_LOG_FILE = '"));
425 rlb->append(lex->mi.log_file_name);
426 rlb->append(STRING_WITH_LEN("'"));
427 }
428 if (lex->mi.pos)
429 {
430 rlb->append(STRING_WITH_LEN(" MASTER_LOG_POS = "));
431 rlb->append_ulonglong(lex->mi.pos);
432 }
433 if (lex->mi.relay_log_name)
434 {
435 rlb->append(STRING_WITH_LEN(" RELAY_LOG_FILE = '"));
436 rlb->append(lex->mi.relay_log_name);
437 rlb->append(STRING_WITH_LEN("'"));
438 }
439 if (lex->mi.relay_log_pos)
440 {
441 rlb->append(STRING_WITH_LEN(" RELAY_LOG_POS = "));
442 rlb->append_ulonglong(lex->mi.relay_log_pos);
443 }
444
445 if (lex->mi.ssl_verify_server_cert)
446 {
447 rlb->append(STRING_WITH_LEN(" MASTER_SSL_VERIFY_SERVER_CERT = "));
448 rlb->append(lex->mi.ssl_verify_server_cert == LEX_MASTER_INFO::LEX_MI_ENABLE ? "1" : "0");
449 }
450 if (lex->mi.repl_ignore_server_ids_opt)
451 {
452 bool first= TRUE;
453 rlb->append(STRING_WITH_LEN(" IGNORE_SERVER_IDS = ( "));
454 for (uint i= 0; i < lex->mi.repl_ignore_server_ids.elements; i++)
455 {
456 ulong s_id;
457 get_dynamic(&lex->mi.repl_ignore_server_ids, (uchar*) &s_id, i);
458 if (first)
459 first= FALSE;
460 else
461 rlb->append(STRING_WITH_LEN(", "));
462 rlb->append_ulonglong(s_id);
463 }
464 rlb->append(STRING_WITH_LEN(" )"));
465 }
466 if (lex->mi.heartbeat_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
467 {
468 rlb->append(STRING_WITH_LEN(" MASTER_HEARTBEAT_PERIOD = "));
469 if (lex->mi.heartbeat_opt == LEX_MASTER_INFO::LEX_MI_DISABLE)
470 rlb->append(STRING_WITH_LEN("0"));
471 else
472 {
473 char buf[64];
474 snprintf(buf, 64, "%f", lex->mi.heartbeat_period);
475 rlb->append(buf);
476 }
477 }
478 }
479
480
481 /**
482 Rewrite a START SLAVE statement.
483
484 @param thd The THD to rewrite for.
485 @param rlb An empty String object to put the rewritten query in.
486 */
487
mysql_rewrite_start_slave(THD * thd,String * rlb)488 static void mysql_rewrite_start_slave(THD *thd, String *rlb)
489 {
490 LEX *lex= thd->lex;
491
492 if (!lex->slave_connection.password)
493 return;
494
495 rlb->append(STRING_WITH_LEN("START SLAVE"));
496
497 if (lex->slave_thd_opt & SLAVE_IO)
498 rlb->append(STRING_WITH_LEN(" IO_THREAD"));
499
500 /* we have printed the IO THREAD related options */
501 if (lex->slave_thd_opt & SLAVE_IO &&
502 lex->slave_thd_opt & SLAVE_SQL)
503 rlb->append(STRING_WITH_LEN(","));
504
505 if (lex->slave_thd_opt & SLAVE_SQL)
506 rlb->append(STRING_WITH_LEN(" SQL_THREAD"));
507
508 /* until options */
509 if (lex->mi.log_file_name || lex->mi.relay_log_name)
510 {
511 rlb->append(STRING_WITH_LEN(" UNTIL"));
512 if (lex->mi.log_file_name)
513 {
514 rlb->append(STRING_WITH_LEN(" MASTER_LOG_FILE = '"));
515 rlb->append(lex->mi.log_file_name);
516 rlb->append(STRING_WITH_LEN("', "));
517 rlb->append(STRING_WITH_LEN("MASTER_LOG_POS = "));
518 rlb->append_ulonglong(lex->mi.pos);
519 }
520
521 if (lex->mi.relay_log_name)
522 {
523 rlb->append(STRING_WITH_LEN(" RELAY_LOG_FILE = '"));
524 rlb->append(lex->mi.relay_log_name);
525 rlb->append(STRING_WITH_LEN("', "));
526 rlb->append(STRING_WITH_LEN("RELAY_LOG_POS = "));
527 rlb->append_ulonglong(lex->mi.relay_log_pos);
528 }
529 }
530
531 /* connection options */
532 if (lex->slave_connection.user)
533 {
534 rlb->append(STRING_WITH_LEN(" USER = '"));
535 rlb->append(lex->slave_connection.user);
536 rlb->append(STRING_WITH_LEN("'"));
537 }
538
539 if (lex->slave_connection.password)
540 rlb->append(STRING_WITH_LEN(" PASSWORD = '<secret>'"));
541
542 if (lex->slave_connection.plugin_auth)
543 {
544 rlb->append(STRING_WITH_LEN(" DEFAULT_AUTH = '"));
545 rlb->append(lex->slave_connection.plugin_auth);
546 rlb->append(STRING_WITH_LEN("'"));
547 }
548
549 if (lex->slave_connection.plugin_dir)
550 {
551 rlb->append(STRING_WITH_LEN(" PLUGIN_DIR = '"));
552 rlb->append(lex->slave_connection.plugin_dir);
553 rlb->append(STRING_WITH_LEN("'"));
554 }
555 }
556
557
558 /**
559 Rewrite a SERVER OPTIONS clause (for CREATE SERVER and ALTER SERVER).
560
561 @param thd The THD to rewrite for.
562 @param rlb An empty String object to put the rewritten query in.
563 */
564
mysql_rewrite_server_options(THD * thd,String * rlb)565 static void mysql_rewrite_server_options(THD *thd, String *rlb)
566 {
567 LEX *lex= thd->lex;
568
569 rlb->append(STRING_WITH_LEN(" OPTIONS ( "));
570
571 rlb->append(STRING_WITH_LEN("PASSWORD '<secret>'"));
572 append_str(rlb, true, "USER", lex->server_options.username);
573 append_str(rlb, true, "HOST", lex->server_options.host);
574 append_str(rlb, true, "DATABASE", lex->server_options.db);
575 append_str(rlb, true, "OWNER", lex->server_options.owner);
576 append_str(rlb, true, "SOCKET", lex->server_options.socket);
577 append_int(rlb, true, STRING_WITH_LEN("PORT "), lex->server_options.port,
578 lex->server_options.port > 0);
579
580 rlb->append(STRING_WITH_LEN(" )"));
581 }
582
583
584 /**
585 Rewrite a CREATE SERVER statement.
586
587 @param thd The THD to rewrite for.
588 @param rlb An empty String object to put the rewritten query in.
589 */
590
mysql_rewrite_create_server(THD * thd,String * rlb)591 static void mysql_rewrite_create_server(THD *thd, String *rlb)
592 {
593 LEX *lex= thd->lex;
594
595 if (!lex->server_options.password)
596 return;
597
598 rlb->append(STRING_WITH_LEN("CREATE SERVER "));
599
600 rlb->append(lex->server_options.server_name ?
601 lex->server_options.server_name : "");
602
603 rlb->append(STRING_WITH_LEN(" FOREIGN DATA WRAPPER '"));
604 rlb->append(lex->server_options.scheme ?
605 lex->server_options.scheme : "");
606 rlb->append(STRING_WITH_LEN("'"));
607
608 mysql_rewrite_server_options(thd, rlb);
609 }
610
611
612 /**
613 Rewrite a ALTER SERVER statement.
614
615 @param thd The THD to rewrite for.
616 @param rlb An empty String object to put the rewritten query in.
617 */
618
mysql_rewrite_alter_server(THD * thd,String * rlb)619 static void mysql_rewrite_alter_server(THD *thd, String *rlb)
620 {
621 LEX *lex= thd->lex;
622
623 if (!lex->server_options.password)
624 return;
625
626 rlb->append(STRING_WITH_LEN("ALTER SERVER "));
627
628 rlb->append(lex->server_options.server_name ?
629 lex->server_options.server_name : "");
630
631 mysql_rewrite_server_options(thd, rlb);
632 }
633
634
635
636
637 /**
638 Rewrite a PREPARE statement.
639
640 @param thd The THD to rewrite for.
641 @param rlb An empty String object to put the rewritten query in.
642 */
643
mysql_rewrite_prepare(THD * thd,String * rlb)644 static void mysql_rewrite_prepare(THD *thd, String *rlb)
645 {
646 LEX *lex= thd->lex;
647
648 if (lex->prepared_stmt_code_is_varref)
649 return;
650
651 rlb->append(STRING_WITH_LEN("PREPARE "));
652 rlb->append(lex->prepared_stmt_name.str,
653 lex->prepared_stmt_name.length);
654 rlb->append(STRING_WITH_LEN(" FROM ..."));
655 }
656
657
658
659
660 /**
661 Rewrite a query (to obfuscate passwords etc.)
662
663 Side-effects: thd->rewritten_query will contain a rewritten query,
664 or be cleared if no rewriting took place.
665
666 @param thd The THD to rewrite for.
667 */
668
mysql_rewrite_query(THD * thd)669 void mysql_rewrite_query(THD *thd)
670 {
671 String *rlb= &thd->rewritten_query;
672
673 rlb->free();
674
675 if (thd->lex->contains_plaintext_password)
676 {
677 switch(thd->lex->sql_command)
678 {
679 case SQLCOM_GRANT: mysql_rewrite_grant(thd, rlb); break;
680 case SQLCOM_SET_OPTION: mysql_rewrite_set(thd, rlb); break;
681 case SQLCOM_CREATE_USER: mysql_rewrite_create_user(thd, rlb); break;
682 case SQLCOM_CHANGE_MASTER: mysql_rewrite_change_master(thd, rlb); break;
683 case SQLCOM_SLAVE_START: mysql_rewrite_start_slave(thd, rlb); break;
684 case SQLCOM_CREATE_SERVER: mysql_rewrite_create_server(thd, rlb); break;
685 case SQLCOM_ALTER_SERVER: mysql_rewrite_alter_server(thd, rlb); break;
686
687 /*
688 PREPARE stmt FROM <string> is rewritten so that <string> is
689 not logged. The statement in <string> will in turn be logged
690 by the prepare and the execute functions in sql_prepare.cc.
691 They do call rewrite so they can safely log the statement,
692 but when they call us, it'll be with sql_command set to reflect
693 the statement in question, not SQLCOM_PREPARE or SQLCOM_EXECUTE.
694 Therefore, there is no SQLCOM_EXECUTE case here, and all
695 SQLCOM_PREPARE does is remove <string>; the "other half",
696 i.e. printing what string we prepare from happens when the
697 prepare function calls the logger (and comes by here with
698 sql_command set to the command being prepared).
699 */
700 case SQLCOM_PREPARE: mysql_rewrite_prepare(thd, rlb); break;
701 default: /* unhandled query types are legal. */ break;
702 }
703 }
704 }
705