00001 /* Copyright (C) 2004-2005 MySQL AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 00018 #define MYSQL_LEX 1 00019 #include "mysql_priv.h" 00020 #include "sp_head.h" 00021 #include "sql_trigger.h" 00022 #include "parse_file.h" 00023 00024 static const LEX_STRING triggers_file_type= 00025 { C_STRING_WITH_LEN("TRIGGERS") }; 00026 00027 const char * const triggers_file_ext= ".TRG"; 00028 00029 /* 00030 Table of .TRG file field descriptors. 00031 We have here only one field now because in nearest future .TRG 00032 files will be merged into .FRM files (so we don't need something 00033 like md5 or created fields). 00034 */ 00035 static File_option triggers_file_parameters[]= 00036 { 00037 { 00038 { C_STRING_WITH_LEN("triggers") }, 00039 offsetof(class Table_triggers_list, definitions_list), 00040 FILE_OPTIONS_STRLIST 00041 }, 00042 { 00043 { C_STRING_WITH_LEN("sql_modes") }, 00044 offsetof(class Table_triggers_list, definition_modes_list), 00045 FILE_OPTIONS_ULLLIST 00046 }, 00047 { 00048 { C_STRING_WITH_LEN("definers") }, 00049 offsetof(class Table_triggers_list, definers_list), 00050 FILE_OPTIONS_STRLIST 00051 }, 00052 { { 0, 0 }, 0, FILE_OPTIONS_STRING } 00053 }; 00054 00055 File_option sql_modes_parameters= 00056 { 00057 { C_STRING_WITH_LEN("sql_modes") }, 00058 offsetof(class Table_triggers_list, definition_modes_list), 00059 FILE_OPTIONS_ULLLIST 00060 }; 00061 00062 /* 00063 This must be kept up to date whenever a new option is added to the list 00064 above, as it specifies the number of required parameters of the trigger in 00065 .trg file. 00066 */ 00067 00068 static const int TRG_NUM_REQUIRED_PARAMETERS= 4; 00069 00070 /* 00071 Structure representing contents of .TRN file which are used to support 00072 database wide trigger namespace. 00073 */ 00074 00075 struct st_trigname 00076 { 00077 LEX_STRING trigger_table; 00078 }; 00079 00080 static const LEX_STRING trigname_file_type= 00081 { C_STRING_WITH_LEN("TRIGGERNAME") }; 00082 00083 const char * const trigname_file_ext= ".TRN"; 00084 00085 static File_option trigname_file_parameters[]= 00086 { 00087 { 00088 { C_STRING_WITH_LEN("trigger_table")}, 00089 offsetof(struct st_trigname, trigger_table), 00090 FILE_OPTIONS_ESTRING 00091 }, 00092 { { 0, 0 }, 0, FILE_OPTIONS_STRING } 00093 }; 00094 00095 00096 const LEX_STRING trg_action_time_type_names[]= 00097 { 00098 { C_STRING_WITH_LEN("BEFORE") }, 00099 { C_STRING_WITH_LEN("AFTER") } 00100 }; 00101 00102 const LEX_STRING trg_event_type_names[]= 00103 { 00104 { C_STRING_WITH_LEN("INSERT") }, 00105 { C_STRING_WITH_LEN("UPDATE") }, 00106 { C_STRING_WITH_LEN("DELETE") } 00107 }; 00108 00109 00110 static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig); 00111 00112 class Handle_old_incorrect_sql_modes_hook: public Unknown_key_hook 00113 { 00114 private: 00115 char *path; 00116 public: 00117 Handle_old_incorrect_sql_modes_hook(char *file_path) 00118 :path(file_path) 00119 {}; 00120 virtual bool process_unknown_string(char *&unknown_key, gptr base, 00121 MEM_ROOT *mem_root, char *end); 00122 }; 00123 00124 class Handle_old_incorrect_trigger_table_hook: public Unknown_key_hook 00125 { 00126 public: 00127 Handle_old_incorrect_trigger_table_hook(char *file_path, 00128 LEX_STRING *trigger_table_arg) 00129 :path(file_path), trigger_table_value(trigger_table_arg) 00130 {}; 00131 virtual bool process_unknown_string(char *&unknown_key, gptr base, 00132 MEM_ROOT *mem_root, char *end); 00133 private: 00134 char *path; 00135 LEX_STRING *trigger_table_value; 00136 }; 00137 00138 /* 00139 Create or drop trigger for table. 00140 00141 SYNOPSIS 00142 mysql_create_or_drop_trigger() 00143 thd - current thread context (including trigger definition in LEX) 00144 tables - table list containing one table for which trigger is created. 00145 create - whenever we create (TRUE) or drop (FALSE) trigger 00146 00147 NOTE 00148 This function is mainly responsible for opening and locking of table and 00149 invalidation of all its instances in table cache after trigger creation. 00150 Real work on trigger creation/dropping is done inside Table_triggers_list 00151 methods. 00152 00153 RETURN VALUE 00154 FALSE Success 00155 TRUE error 00156 */ 00157 bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) 00158 { 00159 TABLE *table; 00160 bool result= TRUE; 00161 LEX_STRING definer_user; 00162 LEX_STRING definer_host; 00163 00164 DBUG_ENTER("mysql_create_or_drop_trigger"); 00165 00166 /* 00167 QQ: This function could be merged in mysql_alter_table() function 00168 But do we want this ? 00169 */ 00170 00171 /* 00172 Note that once we will have check for TRIGGER privilege in place we won't 00173 need second part of condition below, since check_access() function also 00174 checks that db is specified. 00175 */ 00176 if (!thd->lex->spname->m_db.length || create && !tables->db_length) 00177 { 00178 my_error(ER_NO_DB_ERROR, MYF(0)); 00179 DBUG_RETURN(TRUE); 00180 } 00181 00182 if (!create && 00183 !(tables= add_table_for_trigger(thd, thd->lex->spname))) 00184 DBUG_RETURN(TRUE); 00185 00186 /* 00187 We don't allow creating triggers on tables in the 'mysql' schema 00188 */ 00189 if (create && !my_strcasecmp(system_charset_info, "mysql", tables->db)) 00190 { 00191 my_error(ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA, MYF(0)); 00192 DBUG_RETURN(TRUE); 00193 } 00194 00195 /* We should have only one table in table list. */ 00196 DBUG_ASSERT(tables->next_global == 0); 00197 00198 /* 00199 Check that the user has TRIGGER privilege on the subject table. 00200 */ 00201 { 00202 bool err_status; 00203 TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last; 00204 thd->lex->query_tables_own_last= 0; 00205 00206 err_status= check_table_access(thd, TRIGGER_ACL, tables, 0); 00207 00208 thd->lex->query_tables_own_last= save_query_tables_own_last; 00209 00210 if (err_status) 00211 DBUG_RETURN(TRUE); 00212 } 00213 00214 /* 00215 There is no DETERMINISTIC clause for triggers, so can't check it. 00216 But a trigger can in theory be used to do nasty things (if it supported 00217 DROP for example) so we do the check for privileges. Triggers have the 00218 same nature as functions regarding binlogging: their body is implicitely 00219 binlogged, so they share the same danger, so trust_function_creators 00220 applies to them too. 00221 */ 00222 if (!trust_function_creators && mysql_bin_log.is_open() && 00223 !(thd->security_ctx->master_access & SUPER_ACL)) 00224 { 00225 my_error(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER, MYF(0)); 00226 DBUG_RETURN(TRUE); 00227 } 00228 00229 /* We do not allow creation of triggers on temporary tables. */ 00230 if (create && find_temporary_table(thd, tables)) 00231 { 00232 my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias); 00233 DBUG_RETURN(TRUE); 00234 } 00235 00236 /* 00237 We don't want perform our operations while global read lock is held 00238 so we have to wait until its end and then prevent it from occuring 00239 again until we are done. (Acquiring LOCK_open is not enough because 00240 global read lock is held without helding LOCK_open). 00241 */ 00242 if (wait_if_global_read_lock(thd, 0, 1)) 00243 DBUG_RETURN(TRUE); 00244 00245 VOID(pthread_mutex_lock(&LOCK_open)); 00246 00247 if (lock_table_names(thd, tables)) 00248 goto end; 00249 00250 /* We also don't allow creation of triggers on views. */ 00251 tables->required_type= FRMTYPE_TABLE; 00252 00253 if (reopen_name_locked_table(thd, tables)) 00254 { 00255 unlock_table_name(thd, tables); 00256 goto end; 00257 } 00258 table= tables->table; 00259 00260 if (!table->triggers) 00261 { 00262 if (!create) 00263 { 00264 my_error(ER_TRG_DOES_NOT_EXIST, MYF(0)); 00265 goto end; 00266 } 00267 00268 if (!(table->triggers= new (&table->mem_root) Table_triggers_list(table))) 00269 goto end; 00270 } 00271 00272 result= (create ? 00273 table->triggers->create_trigger(thd, tables, &definer_user, &definer_host): 00274 table->triggers->drop_trigger(thd, tables)); 00275 00276 end: 00277 VOID(pthread_mutex_unlock(&LOCK_open)); 00278 start_waiting_global_read_lock(thd); 00279 00280 if (!result) 00281 { 00282 if (mysql_bin_log.is_open()) 00283 { 00284 thd->clear_error(); 00285 00286 String log_query(thd->query, thd->query_length, system_charset_info); 00287 00288 if (create) 00289 { 00290 log_query.set((char *) 0, 0, system_charset_info); /* reset log_query */ 00291 00292 log_query.append(STRING_WITH_LEN("CREATE ")); 00293 00294 if (definer_user.str && definer_host.str) 00295 { 00296 /* 00297 Append definer-clause if the trigger is SUID (a usual trigger in 00298 new MySQL versions). 00299 */ 00300 00301 append_definer(thd, &log_query, &definer_user, &definer_host); 00302 } 00303 00304 log_query.append(thd->lex->stmt_definition_begin, 00305 (char *)thd->lex->sphead->m_body_begin - 00306 thd->lex->stmt_definition_begin + 00307 thd->lex->sphead->m_body.length); 00308 } 00309 00310 /* Such a statement can always go directly to binlog, no trans cache. */ 00311 Query_log_event qinfo(thd, log_query.ptr(), log_query.length(), 0, FALSE); 00312 mysql_bin_log.write(&qinfo); 00313 } 00314 00315 send_ok(thd); 00316 } 00317 00318 DBUG_RETURN(result); 00319 } 00320 00321 00322 /* 00323 Create trigger for table. 00324 00325 SYNOPSIS 00326 create_trigger() 00327 thd - current thread context (including trigger definition in 00328 LEX) 00329 tables - table list containing one open table for which the 00330 trigger is created. 00331 definer_user - [out] after a call it points to 0-terminated string or 00332 contains the NULL-string: 00333 - 0-terminated is returned if the trigger is SUID. The 00334 string contains user name part of the actual trigger 00335 definer. 00336 - NULL-string is returned if the trigger is non-SUID. 00337 Anyway, the caller is responsible to provide memory for 00338 storing LEX_STRING object. 00339 definer_host - [out] after a call it points to 0-terminated string or 00340 contains the NULL-string: 00341 - 0-terminated string is returned if the trigger is 00342 SUID. The string contains host name part of the 00343 actual trigger definer. 00344 - NULL-string is returned if the trigger is non-SUID. 00345 Anyway, the caller is responsible to provide memory for 00346 storing LEX_STRING object. 00347 00348 NOTE 00349 - Assumes that trigger name is fully qualified. 00350 - NULL-string means the following LEX_STRING instance: 00351 { str = 0; length = 0 }. 00352 - In other words, definer_user and definer_host should contain 00353 simultaneously NULL-strings (non-SUID/old trigger) or valid strings 00354 (SUID/new trigger). 00355 00356 RETURN VALUE 00357 False - success 00358 True - error 00359 */ 00360 bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, 00361 LEX_STRING *definer_user, 00362 LEX_STRING *definer_host) 00363 { 00364 LEX *lex= thd->lex; 00365 TABLE *table= tables->table; 00366 char file_buff[FN_REFLEN], trigname_buff[FN_REFLEN]; 00367 LEX_STRING file, trigname_file; 00368 LEX_STRING *trg_def, *name; 00369 ulonglong *trg_sql_mode; 00370 char trg_definer_holder[USER_HOST_BUFF_SIZE]; 00371 LEX_STRING *trg_definer; 00372 Item_trigger_field *trg_field; 00373 struct st_trigname trigname; 00374 00375 00376 /* Trigger must be in the same schema as target table. */ 00377 if (my_strcasecmp(table_alias_charset, table->s->db.str, 00378 lex->spname->m_db.str)) 00379 { 00380 my_error(ER_TRG_IN_WRONG_SCHEMA, MYF(0)); 00381 return 1; 00382 } 00383 00384 /* We don't allow creation of several triggers of the same type yet */ 00385 if (bodies[lex->trg_chistics.event][lex->trg_chistics.action_time]) 00386 { 00387 my_error(ER_NOT_SUPPORTED_YET, MYF(0), 00388 "multiple triggers with the same action time" 00389 " and event for one table"); 00390 return 1; 00391 } 00392 00393 if (!lex->definer) 00394 { 00395 /* 00396 DEFINER-clause is missing. 00397 00398 If we are in slave thread, this means that we received CREATE TRIGGER 00399 from the master, that does not support definer in triggers. So, we 00400 should mark this trigger as non-SUID. Note that this does not happen 00401 when we parse triggers' definitions during opening .TRG file. 00402 LEX::definer is ignored in that case. 00403 00404 Otherwise, we should use CURRENT_USER() as definer. 00405 00406 NOTE: when CREATE TRIGGER statement is allowed to be executed in PS/SP, 00407 it will be required to create the definer below in persistent MEM_ROOT 00408 of PS/SP. 00409 */ 00410 00411 if (!thd->slave_thread) 00412 { 00413 if (!(lex->definer= create_default_definer(thd))) 00414 return 1; 00415 } 00416 } 00417 00418 /* 00419 If the specified definer differs from the current user, we should check 00420 that the current user has SUPER privilege (in order to create trigger 00421 under another user one must have SUPER privilege). 00422 */ 00423 00424 if (lex->definer && 00425 (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) || 00426 my_strcasecmp(system_charset_info, 00427 lex->definer->host.str, 00428 thd->security_ctx->priv_host))) 00429 { 00430 if (check_global_access(thd, SUPER_ACL)) 00431 { 00432 my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); 00433 return TRUE; 00434 } 00435 } 00436 00437 /* 00438 Let us check if all references to fields in old/new versions of row in 00439 this trigger are ok. 00440 00441 NOTE: We do it here more from ease of use standpoint. We still have to 00442 do some checks on each execution. E.g. we can catch privilege changes 00443 only during execution. Also in near future, when we will allow access 00444 to other tables from trigger we won't be able to catch changes in other 00445 tables... 00446 00447 Since we don't plan to access to contents of the fields it does not 00448 matter that we choose for both OLD and NEW values the same versions 00449 of Field objects here. 00450 */ 00451 old_field= new_field= table->field; 00452 00453 for (trg_field= (Item_trigger_field *)(lex->trg_table_fields.first); 00454 trg_field; trg_field= trg_field->next_trg_field) 00455 { 00456 /* 00457 NOTE: now we do not check privileges at CREATE TRIGGER time. This will 00458 be changed in the future. 00459 */ 00460 trg_field->setup_field(thd, table, NULL); 00461 00462 if (!trg_field->fixed && 00463 trg_field->fix_fields(thd, (Item **)0)) 00464 return 1; 00465 } 00466 00467 /* 00468 Here we are creating file with triggers and save all triggers in it. 00469 sql_create_definition_file() files handles renaming and backup of older 00470 versions 00471 */ 00472 file.length= build_table_filename(file_buff, FN_REFLEN-1, 00473 tables->db, tables->table_name, 00474 triggers_file_ext, 0); 00475 file.str= file_buff; 00476 trigname_file.length= build_table_filename(trigname_buff, FN_REFLEN-1, 00477 tables->db, 00478 lex->spname->m_name.str, 00479 trigname_file_ext, 0); 00480 trigname_file.str= trigname_buff; 00481 00482 /* Use the filesystem to enforce trigger namespace constraints. */ 00483 if (!access(trigname_buff, F_OK)) 00484 { 00485 my_error(ER_TRG_ALREADY_EXISTS, MYF(0)); 00486 return 1; 00487 } 00488 00489 trigname.trigger_table.str= tables->table_name; 00490 trigname.trigger_table.length= tables->table_name_length; 00491 00492 if (sql_create_definition_file(NULL, &trigname_file, &trigname_file_type, 00493 (gptr)&trigname, trigname_file_parameters, 0)) 00494 return 1; 00495 00496 /* 00497 Soon we will invalidate table object and thus Table_triggers_list object 00498 so don't care about place to which trg_def->ptr points and other 00499 invariants (e.g. we don't bother to update names_list) 00500 00501 QQ: Hmm... probably we should not care about setting up active thread 00502 mem_root too. 00503 */ 00504 if (!(trg_def= (LEX_STRING *)alloc_root(&table->mem_root, 00505 sizeof(LEX_STRING))) || 00506 definitions_list.push_back(trg_def, &table->mem_root) || 00507 !(trg_sql_mode= (ulonglong*)alloc_root(&table->mem_root, 00508 sizeof(ulonglong))) || 00509 definition_modes_list.push_back(trg_sql_mode, &table->mem_root) || 00510 !(trg_definer= (LEX_STRING*) alloc_root(&table->mem_root, 00511 sizeof(LEX_STRING))) || 00512 definers_list.push_back(trg_definer, &table->mem_root)) 00513 goto err_with_cleanup; 00514 00515 trg_def->str= thd->query; 00516 trg_def->length= thd->query_length; 00517 *trg_sql_mode= thd->variables.sql_mode; 00518 00519 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00520 if (lex->definer && !is_acl_user(lex->definer->host.str, 00521 lex->definer->user.str)) 00522 { 00523 push_warning_printf(thd, 00524 MYSQL_ERROR::WARN_LEVEL_NOTE, 00525 ER_NO_SUCH_USER, 00526 ER(ER_NO_SUCH_USER), 00527 lex->definer->user.str, 00528 lex->definer->host.str); 00529 } 00530 #endif /* NO_EMBEDDED_ACCESS_CHECKS */ 00531 00532 if (lex->definer) 00533 { 00534 /* SUID trigger. */ 00535 00536 *definer_user= lex->definer->user; 00537 *definer_host= lex->definer->host; 00538 00539 trg_definer->str= trg_definer_holder; 00540 trg_definer->length= strxmov(trg_definer->str, definer_user->str, "@", 00541 definer_host->str, NullS) - trg_definer->str; 00542 } 00543 else 00544 { 00545 /* non-SUID trigger. */ 00546 00547 definer_user->str= 0; 00548 definer_user->length= 0; 00549 00550 definer_host->str= 0; 00551 definer_host->length= 0; 00552 00553 trg_definer->str= (char*) ""; 00554 trg_definer->length= 0; 00555 } 00556 00557 if (!sql_create_definition_file(NULL, &file, &triggers_file_type, 00558 (gptr)this, triggers_file_parameters, 0)) 00559 return 0; 00560 00561 err_with_cleanup: 00562 my_delete(trigname_buff, MYF(MY_WME)); 00563 return 1; 00564 } 00565 00566 00567 /* 00568 Deletes the .TRG file for a table 00569 00570 SYNOPSIS 00571 rm_trigger_file() 00572 path - char buffer of size FN_REFLEN to be used 00573 for constructing path to .TRG file. 00574 db - table's database name 00575 table_name - table's name 00576 00577 RETURN VALUE 00578 False - success 00579 True - error 00580 */ 00581 00582 static bool rm_trigger_file(char *path, const char *db, 00583 const char *table_name) 00584 { 00585 build_table_filename(path, FN_REFLEN-1, db, table_name, triggers_file_ext, 0); 00586 return my_delete(path, MYF(MY_WME)); 00587 } 00588 00589 00590 /* 00591 Deletes the .TRN file for a trigger 00592 00593 SYNOPSIS 00594 rm_trigname_file() 00595 path - char buffer of size FN_REFLEN to be used 00596 for constructing path to .TRN file. 00597 db - trigger's database name 00598 table_name - trigger's name 00599 00600 RETURN VALUE 00601 False - success 00602 True - error 00603 */ 00604 00605 static bool rm_trigname_file(char *path, const char *db, 00606 const char *trigger_name) 00607 { 00608 build_table_filename(path, FN_REFLEN-1, 00609 db, trigger_name, trigname_file_ext, 0); 00610 return my_delete(path, MYF(MY_WME)); 00611 } 00612 00613 00614 /* 00615 Helper function that saves .TRG file for Table_triggers_list object. 00616 00617 SYNOPSIS 00618 save_trigger_file() 00619 triggers Table_triggers_list object for which file should be saved 00620 db Name of database for subject table 00621 table_name Name of subject table 00622 00623 RETURN VALUE 00624 FALSE Success 00625 TRUE Error 00626 */ 00627 00628 static bool save_trigger_file(Table_triggers_list *triggers, const char *db, 00629 const char *table_name) 00630 { 00631 char file_buff[FN_REFLEN]; 00632 LEX_STRING file; 00633 00634 file.length= build_table_filename(file_buff, FN_REFLEN-1, db, table_name, 00635 triggers_file_ext, 0); 00636 file.str= file_buff; 00637 return sql_create_definition_file(NULL, &file, &triggers_file_type, 00638 (gptr)triggers, triggers_file_parameters, 00639 0); 00640 } 00641 00642 00643 /* 00644 Drop trigger for table. 00645 00646 SYNOPSIS 00647 drop_trigger() 00648 thd - current thread context (including trigger definition in LEX) 00649 tables - table list containing one open table for which trigger is 00650 dropped. 00651 00652 RETURN VALUE 00653 False - success 00654 True - error 00655 */ 00656 bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables) 00657 { 00658 LEX *lex= thd->lex; 00659 LEX_STRING *name; 00660 List_iterator_fast<LEX_STRING> it_name(names_list); 00661 List_iterator<LEX_STRING> it_def(definitions_list); 00662 List_iterator<ulonglong> it_mod(definition_modes_list); 00663 List_iterator<LEX_STRING> it_definer(definers_list); 00664 char path[FN_REFLEN]; 00665 00666 while ((name= it_name++)) 00667 { 00668 it_def++; 00669 it_mod++; 00670 it_definer++; 00671 00672 if (my_strcasecmp(table_alias_charset, lex->spname->m_name.str, 00673 name->str) == 0) 00674 { 00675 /* 00676 Again we don't care much about other things required for 00677 clean trigger removing since table will be reopened anyway. 00678 */ 00679 it_def.remove(); 00680 it_mod.remove(); 00681 it_definer.remove(); 00682 00683 if (definitions_list.is_empty()) 00684 { 00685 /* 00686 TODO: Probably instead of removing .TRG file we should move 00687 to archive directory but this should be done as part of 00688 parse_file.cc functionality (because we will need it 00689 elsewhere). 00690 */ 00691 if (rm_trigger_file(path, tables->db, tables->table_name)) 00692 return 1; 00693 } 00694 else 00695 { 00696 if (save_trigger_file(this, tables->db, tables->table_name)) 00697 return 1; 00698 } 00699 00700 if (rm_trigname_file(path, tables->db, lex->spname->m_name.str)) 00701 return 1; 00702 return 0; 00703 } 00704 } 00705 00706 my_message(ER_TRG_DOES_NOT_EXIST, ER(ER_TRG_DOES_NOT_EXIST), MYF(0)); 00707 return 1; 00708 } 00709 00710 00711 Table_triggers_list::~Table_triggers_list() 00712 { 00713 for (int i= 0; i < (int)TRG_EVENT_MAX; i++) 00714 for (int j= 0; j < (int)TRG_ACTION_MAX; j++) 00715 delete bodies[i][j]; 00716 00717 if (record1_field) 00718 for (Field **fld_ptr= record1_field; *fld_ptr; fld_ptr++) 00719 delete *fld_ptr; 00720 } 00721 00722 00723 /* 00724 Prepare array of Field objects referencing to TABLE::record[1] instead 00725 of record[0] (they will represent OLD.* row values in ON UPDATE trigger 00726 and in ON DELETE trigger which will be called during REPLACE execution). 00727 00728 SYNOPSIS 00729 prepare_record1_accessors() 00730 table - pointer to TABLE object for which we are creating fields. 00731 00732 RETURN VALUE 00733 False - success 00734 True - error 00735 */ 00736 bool Table_triggers_list::prepare_record1_accessors(TABLE *table) 00737 { 00738 Field **fld, **old_fld; 00739 00740 if (!(record1_field= (Field **)alloc_root(&table->mem_root, 00741 (table->s->fields + 1) * 00742 sizeof(Field*)))) 00743 return 1; 00744 00745 for (fld= table->field, old_fld= record1_field; *fld; fld++, old_fld++) 00746 { 00747 /* 00748 QQ: it is supposed that it is ok to use this function for field 00749 cloning... 00750 */ 00751 if (!(*old_fld= (*fld)->new_field(&table->mem_root, table, 00752 table == (*fld)->table))) 00753 return 1; 00754 (*old_fld)->move_field_offset((my_ptrdiff_t)(table->record[1] - 00755 table->record[0])); 00756 } 00757 *old_fld= 0; 00758 00759 return 0; 00760 } 00761 00762 00763 /* 00764 Adjust Table_triggers_list with new TABLE pointer. 00765 00766 SYNOPSIS 00767 set_table() 00768 new_table - new pointer to TABLE instance 00769 */ 00770 00771 void Table_triggers_list::set_table(TABLE *new_table) 00772 { 00773 table= new_table; 00774 for (Field **field= table->triggers->record1_field ; *field ; field++) 00775 { 00776 (*field)->table= (*field)->orig_table= new_table; 00777 (*field)->table_name= &new_table->alias; 00778 } 00779 } 00780 00781 00782 /* 00783 Check whenever .TRG file for table exist and load all triggers it contains. 00784 00785 SYNOPSIS 00786 check_n_load() 00787 thd - current thread context 00788 db - table's database name 00789 table_name - table's name 00790 table - pointer to table object 00791 names_only - stop after loading trigger names 00792 00793 RETURN VALUE 00794 False - success 00795 True - error 00796 */ 00797 00798 bool Table_triggers_list::check_n_load(THD *thd, const char *db, 00799 const char *table_name, TABLE *table, 00800 bool names_only) 00801 { 00802 char path_buff[FN_REFLEN]; 00803 LEX_STRING path; 00804 File_parser *parser; 00805 LEX_STRING save_db; 00806 00807 DBUG_ENTER("Table_triggers_list::check_n_load"); 00808 00809 path.length= build_table_filename(path_buff, FN_REFLEN-1, 00810 db, table_name, triggers_file_ext, 0); 00811 path.str= path_buff; 00812 00813 // QQ: should we analyze errno somehow ? 00814 if (access(path_buff, F_OK)) 00815 DBUG_RETURN(0); 00816 00817 /* 00818 File exists so we got to load triggers. 00819 FIXME: A lot of things to do here e.g. how about other funcs and being 00820 more paranoical ? 00821 */ 00822 00823 if ((parser= sql_parse_prepare(&path, &table->mem_root, 1))) 00824 { 00825 if (is_equal(&triggers_file_type, parser->type())) 00826 { 00827 Table_triggers_list *triggers= 00828 new (&table->mem_root) Table_triggers_list(table); 00829 Handle_old_incorrect_sql_modes_hook sql_modes_hook(path.str); 00830 00831 if (!triggers) 00832 DBUG_RETURN(1); 00833 00834 /* 00835 We don't have the following attributes in old versions of .TRG file, so 00836 we should initialize the list for safety: 00837 - sql_modes; 00838 - definers; 00839 */ 00840 triggers->definition_modes_list.empty(); 00841 triggers->definers_list.empty(); 00842 00843 if (parser->parse((gptr)triggers, &table->mem_root, 00844 triggers_file_parameters, 00845 TRG_NUM_REQUIRED_PARAMETERS, 00846 &sql_modes_hook)) 00847 DBUG_RETURN(1); 00848 00849 List_iterator_fast<LEX_STRING> it(triggers->definitions_list); 00850 LEX_STRING *trg_create_str, *trg_name_str; 00851 ulonglong *trg_sql_mode; 00852 00853 if (triggers->definition_modes_list.is_empty() && 00854 !triggers->definitions_list.is_empty()) 00855 { 00856 /* 00857 It is old file format => we should fill list of sql_modes. 00858 00859 We use one mode (current) for all triggers, because we have not 00860 information about mode in old format. 00861 */ 00862 if (!(trg_sql_mode= (ulonglong*)alloc_root(&table->mem_root, 00863 sizeof(ulonglong)))) 00864 { 00865 DBUG_RETURN(1); // EOM 00866 } 00867 *trg_sql_mode= global_system_variables.sql_mode; 00868 while (it++) 00869 { 00870 if (triggers->definition_modes_list.push_back(trg_sql_mode, 00871 &table->mem_root)) 00872 { 00873 DBUG_RETURN(1); // EOM 00874 } 00875 } 00876 it.rewind(); 00877 } 00878 00879 if (triggers->definers_list.is_empty() && 00880 !triggers->definitions_list.is_empty()) 00881 { 00882 /* 00883 It is old file format => we should fill list of definers. 00884 00885 If there is no definer information, we should not switch context to 00886 definer when checking privileges. I.e. privileges for such triggers 00887 are checked for "invoker" rather than for "definer". 00888 */ 00889 00890 LEX_STRING *trg_definer; 00891 00892 if (! (trg_definer= (LEX_STRING*)alloc_root(&table->mem_root, 00893 sizeof(LEX_STRING)))) 00894 DBUG_RETURN(1); // EOM 00895 00896 trg_definer->str= (char*) ""; 00897 trg_definer->length= 0; 00898 00899 while (it++) 00900 { 00901 if (triggers->definers_list.push_back(trg_definer, 00902 &table->mem_root)) 00903 { 00904 DBUG_RETURN(1); // EOM 00905 } 00906 } 00907 00908 it.rewind(); 00909 } 00910 00911 DBUG_ASSERT(triggers->definition_modes_list.elements == 00912 triggers->definitions_list.elements); 00913 DBUG_ASSERT(triggers->definers_list.elements == 00914 triggers->definitions_list.elements); 00915 00916 table->triggers= triggers; 00917 00918 /* 00919 Construct key that will represent triggers for this table in the set 00920 of routines used by statement. 00921 */ 00922 triggers->sroutines_key.length= 1+strlen(db)+1+strlen(table_name)+1; 00923 if (!(triggers->sroutines_key.str= 00924 alloc_root(&table->mem_root, triggers->sroutines_key.length))) 00925 DBUG_RETURN(1); 00926 triggers->sroutines_key.str[0]= TYPE_ENUM_TRIGGER; 00927 strxmov(triggers->sroutines_key.str+1, db, ".", table_name, NullS); 00928 00929 /* 00930 TODO: This could be avoided if there is no triggers 00931 for UPDATE and DELETE. 00932 */ 00933 if (!names_only && triggers->prepare_record1_accessors(table)) 00934 DBUG_RETURN(1); 00935 00936 List_iterator_fast<ulonglong> itm(triggers->definition_modes_list); 00937 List_iterator_fast<LEX_STRING> it_definer(triggers->definers_list); 00938 LEX *old_lex= thd->lex, lex; 00939 sp_rcontext *save_spcont= thd->spcont; 00940 ulong save_sql_mode= thd->variables.sql_mode; 00941 LEX_STRING *on_table_name; 00942 00943 thd->lex= &lex; 00944 00945 save_db.str= thd->db; 00946 save_db.length= thd->db_length; 00947 thd->reset_db((char*) db, strlen(db)); 00948 while ((trg_create_str= it++)) 00949 { 00950 trg_sql_mode= itm++; 00951 LEX_STRING *trg_definer= it_definer++; 00952 00953 thd->variables.sql_mode= (ulong)*trg_sql_mode; 00954 lex_start(thd, (uchar*)trg_create_str->str, trg_create_str->length); 00955 00956 thd->spcont= 0; 00957 if (MYSQLparse((void *)thd) || thd->is_fatal_error) 00958 { 00959 /* 00960 Free lex associated resources. 00961 QQ: Do we really need all this stuff here ? 00962 */ 00963 delete lex.sphead; 00964 goto err_with_lex_cleanup; 00965 } 00966 00967 lex.sphead->set_info(0, 0, &lex.sp_chistics, *trg_sql_mode); 00968 00969 triggers->bodies[lex.trg_chistics.event] 00970 [lex.trg_chistics.action_time]= lex.sphead; 00971 00972 if (!trg_definer->length) 00973 { 00974 /* 00975 This trigger was created/imported from the previous version of 00976 MySQL, which does not support triggers definers. We should emit 00977 warning here. 00978 */ 00979 00980 push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 00981 ER_TRG_NO_DEFINER, ER(ER_TRG_NO_DEFINER), 00982 (const char*) db, 00983 (const char*) lex.sphead->m_name.str); 00984 00985 /* 00986 Set definer to the '' to correct displaying in the information 00987 schema. 00988 */ 00989 00990 lex.sphead->set_definer((char*) "", 0); 00991 00992 /* 00993 Triggers without definer information are executed under the 00994 authorization of the invoker. 00995 */ 00996 00997 lex.sphead->m_chistics->suid= SP_IS_NOT_SUID; 00998 } 00999 else 01000 lex.sphead->set_definer(trg_definer->str, trg_definer->length); 01001 01002 if (triggers->names_list.push_back(&lex.sphead->m_name, 01003 &table->mem_root)) 01004 goto err_with_lex_cleanup; 01005 01006 if (!(on_table_name= (LEX_STRING*) alloc_root(&table->mem_root, 01007 sizeof(LEX_STRING)))) 01008 goto err_with_lex_cleanup; 01009 *on_table_name= lex.ident; 01010 if (triggers->on_table_names_list.push_back(on_table_name, &table->mem_root)) 01011 goto err_with_lex_cleanup; 01012 01013 /* 01014 Let us check that we correctly update trigger definitions when we 01015 rename tables with triggers. 01016 */ 01017 DBUG_ASSERT(!my_strcasecmp(table_alias_charset, lex.query_tables->db, db) && 01018 !my_strcasecmp(table_alias_charset, lex.query_tables->table_name, 01019 table_name)); 01020 01021 if (names_only) 01022 { 01023 lex_end(&lex); 01024 continue; 01025 } 01026 01027 /* 01028 Gather all Item_trigger_field objects representing access to fields 01029 in old/new versions of row in trigger into lists containing all such 01030 objects for the triggers with same action and timing. 01031 */ 01032 triggers->trigger_fields[lex.trg_chistics.event] 01033 [lex.trg_chistics.action_time]= 01034 (Item_trigger_field *)(lex.trg_table_fields.first); 01035 /* 01036 Also let us bind these objects to Field objects in table being 01037 opened. 01038 01039 We ignore errors here, because if even something is wrong we still 01040 will be willing to open table to perform some operations (e.g. 01041 SELECT)... 01042 Anyway some things can be checked only during trigger execution. 01043 */ 01044 for (Item_trigger_field *trg_field= 01045 (Item_trigger_field *)(lex.trg_table_fields.first); 01046 trg_field; 01047 trg_field= trg_field->next_trg_field) 01048 { 01049 trg_field->setup_field(thd, table, 01050 &triggers->subject_table_grants[lex.trg_chistics.event] 01051 [lex.trg_chistics.action_time]); 01052 } 01053 01054 lex_end(&lex); 01055 } 01056 thd->reset_db(save_db.str, save_db.length); 01057 thd->lex= old_lex; 01058 thd->spcont= save_spcont; 01059 thd->variables.sql_mode= save_sql_mode; 01060 01061 DBUG_RETURN(0); 01062 01063 err_with_lex_cleanup: 01064 // QQ: anything else ? 01065 lex_end(&lex); 01066 thd->lex= old_lex; 01067 thd->spcont= save_spcont; 01068 thd->variables.sql_mode= save_sql_mode; 01069 thd->reset_db(save_db.str, save_db.length); 01070 DBUG_RETURN(1); 01071 } 01072 01073 /* 01074 We don't care about this error message much because .TRG files will 01075 be merged into .FRM anyway. 01076 */ 01077 my_error(ER_WRONG_OBJECT, MYF(0), 01078 table_name, triggers_file_ext+1, "TRIGGER"); 01079 DBUG_RETURN(1); 01080 } 01081 01082 DBUG_RETURN(1); 01083 } 01084 01085 01086 /* 01087 Obtains and returns trigger metadata 01088 01089 SYNOPSIS 01090 get_trigger_info() 01091 thd - current thread context 01092 event - trigger event type 01093 time_type - trigger action time 01094 name - returns name of trigger 01095 stmt - returns statement of trigger 01096 sql_mode - returns sql_mode of trigger 01097 definer_user - returns definer/creator of trigger. The caller is 01098 responsible to allocate enough space for storing definer 01099 information. 01100 01101 RETURN VALUE 01102 False - success 01103 True - error 01104 */ 01105 01106 bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event, 01107 trg_action_time_type time_type, 01108 LEX_STRING *trigger_name, 01109 LEX_STRING *trigger_stmt, 01110 ulong *sql_mode, 01111 LEX_STRING *definer) 01112 { 01113 sp_head *body; 01114 DBUG_ENTER("get_trigger_info"); 01115 if ((body= bodies[event][time_type])) 01116 { 01117 *trigger_name= body->m_name; 01118 *trigger_stmt= body->m_body; 01119 *sql_mode= body->m_sql_mode; 01120 01121 if (body->m_chistics->suid == SP_IS_NOT_SUID) 01122 { 01123 definer->str[0]= 0; 01124 definer->length= 0; 01125 } 01126 else 01127 { 01128 definer->length= strxmov(definer->str, body->m_definer_user.str, "@", 01129 body->m_definer_host.str, NullS) - definer->str; 01130 } 01131 01132 DBUG_RETURN(0); 01133 } 01134 DBUG_RETURN(1); 01135 } 01136 01137 01138 /* 01139 Find trigger's table from trigger identifier and add it to 01140 the statement table list. 01141 01142 SYNOPSIS 01143 mysql_table_for_trigger() 01144 thd - current thread context 01145 trig - identifier for trigger 01146 01147 RETURN VALUE 01148 0 - error 01149 # - pointer to TABLE_LIST object for the table 01150 */ 01151 01152 static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig) 01153 { 01154 LEX *lex= thd->lex; 01155 char path_buff[FN_REFLEN]; 01156 LEX_STRING path; 01157 File_parser *parser; 01158 struct st_trigname trigname; 01159 Handle_old_incorrect_trigger_table_hook trigger_table_hook( 01160 path_buff, &trigname.trigger_table); 01161 01162 DBUG_ENTER("add_table_for_trigger"); 01163 01164 path.length= build_table_filename(path_buff, FN_REFLEN-1, 01165 trig->m_db.str, trig->m_name.str, 01166 trigname_file_ext, 0); 01167 path.str= path_buff; 01168 01169 if (access(path_buff, F_OK)) 01170 { 01171 my_error(ER_TRG_DOES_NOT_EXIST, MYF(0)); 01172 DBUG_RETURN(0); 01173 } 01174 01175 if (!(parser= sql_parse_prepare(&path, thd->mem_root, 1))) 01176 DBUG_RETURN(0); 01177 01178 if (!is_equal(&trigname_file_type, parser->type())) 01179 { 01180 my_error(ER_WRONG_OBJECT, MYF(0), trig->m_name.str, trigname_file_ext+1, 01181 "TRIGGERNAME"); 01182 DBUG_RETURN(0); 01183 } 01184 01185 if (parser->parse((gptr)&trigname, thd->mem_root, 01186 trigname_file_parameters, 1, 01187 &trigger_table_hook)) 01188 DBUG_RETURN(0); 01189 01190 /* We need to reset statement table list to be PS/SP friendly. */ 01191 lex->query_tables= 0; 01192 lex->query_tables_last= &lex->query_tables; 01193 DBUG_RETURN(sp_add_to_query_tables(thd, lex, trig->m_db.str, 01194 trigname.trigger_table.str, TL_IGNORE)); 01195 } 01196 01197 01198 /* 01199 Drop all triggers for table. 01200 01201 SYNOPSIS 01202 drop_all_triggers() 01203 thd - current thread context 01204 db - schema for table 01205 name - name for table 01206 01207 NOTE 01208 The calling thread should hold the LOCK_open mutex; 01209 01210 RETURN VALUE 01211 False - success 01212 True - error 01213 */ 01214 01215 bool Table_triggers_list::drop_all_triggers(THD *thd, char *db, char *name) 01216 { 01217 TABLE table; 01218 char path[FN_REFLEN]; 01219 bool result= 0; 01220 DBUG_ENTER("drop_all_triggers"); 01221 01222 bzero(&table, sizeof(table)); 01223 init_alloc_root(&table.mem_root, 8192, 0); 01224 01225 safe_mutex_assert_owner(&LOCK_open); 01226 01227 if (Table_triggers_list::check_n_load(thd, db, name, &table, 1)) 01228 { 01229 result= 1; 01230 goto end; 01231 } 01232 if (table.triggers) 01233 { 01234 LEX_STRING *trigger; 01235 List_iterator_fast<LEX_STRING> it_name(table.triggers->names_list); 01236 01237 while ((trigger= it_name++)) 01238 { 01239 if (rm_trigname_file(path, db, trigger->str)) 01240 { 01241 /* 01242 Instead of immediately bailing out with error if we were unable 01243 to remove .TRN file we will try to drop other files. 01244 */ 01245 result= 1; 01246 continue; 01247 } 01248 } 01249 01250 if (rm_trigger_file(path, db, name)) 01251 { 01252 result= 1; 01253 goto end; 01254 } 01255 } 01256 end: 01257 if (table.triggers) 01258 delete table.triggers; 01259 free_root(&table.mem_root, MYF(0)); 01260 DBUG_RETURN(result); 01261 } 01262 01263 01264 /* 01265 Update .TRG file after renaming triggers' subject table 01266 (change name of table in triggers' definitions). 01267 01268 SYNOPSIS 01269 change_table_name_in_triggers() 01270 thd Thread context 01271 db_name Database of subject table 01272 old_table_name Old subject table's name 01273 new_table_name New subject table's name 01274 01275 RETURN VALUE 01276 FALSE Success 01277 TRUE Failure 01278 */ 01279 01280 bool 01281 Table_triggers_list::change_table_name_in_triggers(THD *thd, 01282 const char *db_name, 01283 LEX_STRING *old_table_name, 01284 LEX_STRING *new_table_name) 01285 { 01286 char path_buff[FN_REFLEN]; 01287 LEX_STRING *def, *on_table_name, new_def; 01288 ulonglong *sql_mode; 01289 ulong save_sql_mode= thd->variables.sql_mode; 01290 List_iterator_fast<LEX_STRING> it_def(definitions_list); 01291 List_iterator_fast<LEX_STRING> it_on_table_name(on_table_names_list); 01292 List_iterator_fast<ulonglong> it_mode(definition_modes_list); 01293 uint on_q_table_name_len, before_on_len; 01294 String buff; 01295 01296 DBUG_ASSERT(definitions_list.elements == on_table_names_list.elements && 01297 definitions_list.elements == definition_modes_list.elements); 01298 01299 while ((def= it_def++)) 01300 { 01301 on_table_name= it_on_table_name++; 01302 thd->variables.sql_mode= *(it_mode++); 01303 01304 /* Construct CREATE TRIGGER statement with new table name. */ 01305 buff.length(0); 01306 before_on_len= on_table_name->str - def->str; 01307 buff.append(def->str, before_on_len); 01308 buff.append(STRING_WITH_LEN("ON ")); 01309 append_identifier(thd, &buff, new_table_name->str, new_table_name->length); 01310 buff.append(STRING_WITH_LEN(" ")); 01311 on_q_table_name_len= buff.length() - before_on_len; 01312 buff.append(on_table_name->str + on_table_name->length, 01313 def->length - (before_on_len + on_table_name->length)); 01314 /* 01315 It is OK to allocate some memory on table's MEM_ROOT since this 01316 table instance will be thrown out at the end of rename anyway. 01317 */ 01318 new_def.str= memdup_root(&table->mem_root, buff.ptr(), buff.length()); 01319 new_def.length= buff.length(); 01320 on_table_name->str= new_def.str + before_on_len; 01321 on_table_name->length= on_q_table_name_len; 01322 *def= new_def; 01323 } 01324 01325 thd->variables.sql_mode= save_sql_mode; 01326 01327 if (thd->is_fatal_error) 01328 return TRUE; /* OOM */ 01329 01330 if (save_trigger_file(this, db_name, new_table_name->str)) 01331 return TRUE; 01332 if (rm_trigger_file(path_buff, db_name, old_table_name->str)) 01333 { 01334 (void) rm_trigger_file(path_buff, db_name, new_table_name->str); 01335 return TRUE; 01336 } 01337 return FALSE; 01338 } 01339 01340 01341 /* 01342 Iterate though Table_triggers_list::names_list list and update .TRN files 01343 after renaming triggers' subject table. 01344 01345 SYNOPSIS 01346 change_table_name_in_trignames() 01347 db_name Database of subject table 01348 new_table_name New subject table's name 01349 stopper Pointer to Table_triggers_list::names_list at 01350 which we should stop updating. 01351 01352 RETURN VALUE 01353 0 Success 01354 non-0 Failure, pointer to Table_triggers_list::names_list element 01355 for which update failed. 01356 */ 01357 01358 LEX_STRING* 01359 Table_triggers_list::change_table_name_in_trignames(const char *db_name, 01360 LEX_STRING *new_table_name, 01361 LEX_STRING *stopper) 01362 { 01363 char trigname_buff[FN_REFLEN]; 01364 struct st_trigname trigname; 01365 LEX_STRING trigname_file; 01366 LEX_STRING *trigger; 01367 List_iterator_fast<LEX_STRING> it_name(names_list); 01368 01369 while ((trigger= it_name++) != stopper) 01370 { 01371 trigname_file.length= build_table_filename(trigname_buff, FN_REFLEN-1, 01372 db_name, trigger->str, 01373 trigname_file_ext, 0); 01374 trigname_file.str= trigname_buff; 01375 01376 trigname.trigger_table= *new_table_name; 01377 01378 if (sql_create_definition_file(NULL, &trigname_file, &trigname_file_type, 01379 (gptr)&trigname, trigname_file_parameters, 01380 0)) 01381 return trigger; 01382 } 01383 01384 return 0; 01385 } 01386 01387 01388 /* 01389 Update .TRG and .TRN files after renaming triggers' subject table. 01390 01391 SYNOPSIS 01392 change_table_name() 01393 thd Thread context 01394 db Old database of subject table 01395 old_table Old name of subject table 01396 new_db New database for subject table 01397 new_table New name of subject table 01398 01399 NOTE 01400 This method tries to leave trigger related files in consistent state, 01401 i.e. it either will complete successfully, or will fail leaving files 01402 in their initial state. 01403 Also this method assumes that subject table is not renamed to itself. 01404 01405 RETURN VALUE 01406 FALSE Success 01407 TRUE Error 01408 */ 01409 01410 bool Table_triggers_list::change_table_name(THD *thd, const char *db, 01411 const char *old_table, 01412 const char *new_db, 01413 const char *new_table) 01414 { 01415 TABLE table; 01416 bool result= 0; 01417 LEX_STRING *err_trigname; 01418 DBUG_ENTER("change_table_name"); 01419 01420 bzero(&table, sizeof(table)); 01421 init_alloc_root(&table.mem_root, 8192, 0); 01422 01423 safe_mutex_assert_owner(&LOCK_open); 01424 01425 DBUG_ASSERT(my_strcasecmp(table_alias_charset, db, new_db) || 01426 my_strcasecmp(table_alias_charset, old_table, new_table)); 01427 01428 if (Table_triggers_list::check_n_load(thd, db, old_table, &table, TRUE)) 01429 { 01430 result= 1; 01431 goto end; 01432 } 01433 if (table.triggers) 01434 { 01435 LEX_STRING old_table_name= { (char *) old_table, strlen(old_table) }; 01436 LEX_STRING new_table_name= { (char *) new_table, strlen(new_table) }; 01437 /* 01438 Since triggers should be in the same schema as their subject tables 01439 moving table with them between two schemas raises too many questions. 01440 (E.g. what should happen if in new schema we already have trigger 01441 with same name ?). 01442 */ 01443 if (my_strcasecmp(table_alias_charset, db, new_db)) 01444 { 01445 my_error(ER_TRG_IN_WRONG_SCHEMA, MYF(0)); 01446 result= 1; 01447 goto end; 01448 } 01449 if (table.triggers->change_table_name_in_triggers(thd, db, 01450 &old_table_name, 01451 &new_table_name)) 01452 { 01453 result= 1; 01454 goto end; 01455 } 01456 if ((err_trigname= table.triggers->change_table_name_in_trignames( 01457 db, &new_table_name, 0))) 01458 { 01459 /* 01460 If we were unable to update one of .TRN files properly we will 01461 revert all changes that we have done and report about error. 01462 We assume that we will be able to undo our changes without errors 01463 (we can't do much if there will be an error anyway). 01464 */ 01465 (void) table.triggers->change_table_name_in_trignames(db, 01466 &old_table_name, 01467 err_trigname); 01468 (void) table.triggers->change_table_name_in_triggers(thd, db, 01469 &new_table_name, 01470 &old_table_name); 01471 result= 1; 01472 goto end; 01473 } 01474 } 01475 end: 01476 delete table.triggers; 01477 free_root(&table.mem_root, MYF(0)); 01478 DBUG_RETURN(result); 01479 } 01480 01481 01482 bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event, 01483 trg_action_time_type time_type, 01484 bool old_row_is_record1) 01485 { 01486 bool err_status= FALSE; 01487 sp_head *sp_trigger= bodies[event][time_type]; 01488 01489 if (sp_trigger) 01490 { 01491 Sub_statement_state statement_state; 01492 01493 if (old_row_is_record1) 01494 { 01495 old_field= record1_field; 01496 new_field= table->field; 01497 } 01498 else 01499 { 01500 new_field= record1_field; 01501 old_field= table->field; 01502 } 01503 #ifndef NO_EMBEDDED_ACCESS_CHECKS 01504 Security_context *save_ctx; 01505 01506 if (sp_change_security_context(thd, sp_trigger, &save_ctx)) 01507 return TRUE; 01508 01509 /* 01510 Fetch information about table-level privileges to GRANT_INFO structure for 01511 subject table. Check of privileges that will use it and information about 01512 column-level privileges will happen in Item_trigger_field::fix_fields(). 01513 */ 01514 01515 fill_effective_table_privileges(thd, 01516 &subject_table_grants[event][time_type], 01517 table->s->db.str, table->s->table_name.str); 01518 01519 /* Check that the definer has TRIGGER privilege on the subject table. */ 01520 01521 if (!(subject_table_grants[event][time_type].privilege & TRIGGER_ACL)) 01522 { 01523 char priv_desc[128]; 01524 get_privilege_desc(priv_desc, sizeof(priv_desc), TRIGGER_ACL); 01525 01526 my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), priv_desc, 01527 thd->security_ctx->priv_user, thd->security_ctx->host_or_ip, 01528 table->s->table_name.str); 01529 01530 sp_restore_security_context(thd, save_ctx); 01531 return TRUE; 01532 } 01533 #endif // NO_EMBEDDED_ACCESS_CHECKS 01534 01535 thd->reset_sub_statement_state(&statement_state, SUB_STMT_TRIGGER); 01536 err_status= sp_trigger->execute_trigger 01537 (thd, table->s->db.str, table->s->table_name.str, 01538 &subject_table_grants[event][time_type]); 01539 thd->restore_sub_statement_state(&statement_state); 01540 01541 #ifndef NO_EMBEDDED_ACCESS_CHECKS 01542 sp_restore_security_context(thd, save_ctx); 01543 #endif // NO_EMBEDDED_ACCESS_CHECKS 01544 } 01545 01546 return err_status; 01547 } 01548 01549 01550 /* 01551 Mark fields of subject table which we read/set in its triggers as such. 01552 01553 SYNOPSIS 01554 mark_fields_used() 01555 thd Current thread context 01556 event Type of event triggers for which we are going to inspect 01557 01558 DESCRIPTION 01559 This method marks fields of subject table which are read/set in its 01560 triggers as such (by properly updating TABLE::read_set/write_set) 01561 and thus informs handler that values for these fields should be 01562 retrieved/stored during execution of statement. 01563 */ 01564 01565 void Table_triggers_list::mark_fields_used(trg_event_type event) 01566 { 01567 int action_time; 01568 Item_trigger_field *trg_field; 01569 01570 for (action_time= 0; action_time < (int)TRG_ACTION_MAX; action_time++) 01571 { 01572 for (trg_field= trigger_fields[event][action_time]; trg_field; 01573 trg_field= trg_field->next_trg_field) 01574 { 01575 /* We cannot mark fields which does not present in table. */ 01576 if (trg_field->field_idx != (uint)-1) 01577 { 01578 bitmap_set_bit(table->read_set, trg_field->field_idx); 01579 if (trg_field->get_settable_routine_parameter()) 01580 bitmap_set_bit(table->write_set, trg_field->field_idx); 01581 } 01582 } 01583 } 01584 table->file->column_bitmaps_signal(); 01585 } 01586 01587 01588 /* 01589 Trigger BUG#14090 compatibility hook 01590 01591 SYNOPSIS 01592 Handle_old_incorrect_sql_modes_hook::process_unknown_string() 01593 unknown_key [in/out] reference on the line with unknown 01594 parameter and the parsing point 01595 base [in] base address for parameter writing (structure 01596 like TABLE) 01597 mem_root [in] MEM_ROOT for parameters allocation 01598 end [in] the end of the configuration 01599 01600 NOTE: this hook process back compatibility for incorrectly written 01601 sql_modes parameter (see BUG#14090). 01602 01603 RETURN 01604 FALSE OK 01605 TRUE Error 01606 */ 01607 01608 #define INVALID_SQL_MODES_LENGTH 13 01609 01610 bool 01611 Handle_old_incorrect_sql_modes_hook::process_unknown_string(char *&unknown_key, 01612 gptr base, 01613 MEM_ROOT *mem_root, 01614 char *end) 01615 { 01616 DBUG_ENTER("Handle_old_incorrect_sql_modes_hook::process_unknown_string"); 01617 DBUG_PRINT("info", ("unknown key:%60s", unknown_key)); 01618 01619 if (unknown_key + INVALID_SQL_MODES_LENGTH + 1 < end && 01620 unknown_key[INVALID_SQL_MODES_LENGTH] == '=' && 01621 !memcmp(unknown_key, STRING_WITH_LEN("sql_modes"))) 01622 { 01623 char *ptr= unknown_key + INVALID_SQL_MODES_LENGTH + 1; 01624 01625 DBUG_PRINT("info", ("sql_modes affected by BUG#14090 detected")); 01626 push_warning_printf(current_thd, 01627 MYSQL_ERROR::WARN_LEVEL_NOTE, 01628 ER_OLD_FILE_FORMAT, 01629 ER(ER_OLD_FILE_FORMAT), 01630 (char *)path, "TRIGGER"); 01631 if (get_file_options_ulllist(ptr, end, unknown_key, base, 01632 &sql_modes_parameters, mem_root)) 01633 { 01634 DBUG_RETURN(TRUE); 01635 } 01636 /* 01637 Set parsing pointer to the last symbol of string (\n) 01638 1) to avoid problem with \0 in the junk after sql_modes 01639 2) to speed up skipping this line by parser. 01640 */ 01641 unknown_key= ptr-1; 01642 } 01643 DBUG_RETURN(FALSE); 01644 } 01645 01646 /* 01647 Trigger BUG#15921 compatibility hook. For details see 01648 Handle_old_incorrect_sql_modes_hook::process_unknown_string(). 01649 */ 01650 01651 #define INVALID_TRIGGER_TABLE_LENGTH 15 01652 01653 bool 01654 Handle_old_incorrect_trigger_table_hook:: 01655 process_unknown_string(char *&unknown_key, gptr base, MEM_ROOT *mem_root, 01656 char *end) 01657 { 01658 DBUG_ENTER("Handle_old_incorrect_trigger_table_hook::process_unknown_string"); 01659 DBUG_PRINT("info", ("unknown key:%60s", unknown_key)); 01660 01661 if (unknown_key + INVALID_TRIGGER_TABLE_LENGTH + 1 < end && 01662 unknown_key[INVALID_TRIGGER_TABLE_LENGTH] == '=' && 01663 !memcmp(unknown_key, STRING_WITH_LEN("trigger_table"))) 01664 { 01665 char *ptr= unknown_key + INVALID_TRIGGER_TABLE_LENGTH + 1; 01666 01667 DBUG_PRINT("info", ("trigger_table affected by BUG#15921 detected")); 01668 push_warning_printf(current_thd, 01669 MYSQL_ERROR::WARN_LEVEL_NOTE, 01670 ER_OLD_FILE_FORMAT, 01671 ER(ER_OLD_FILE_FORMAT), 01672 (char *)path, "TRIGGER"); 01673 01674 if (!(ptr= parse_escaped_string(ptr, end, mem_root, trigger_table_value))) 01675 { 01676 my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0), "trigger_table", 01677 unknown_key); 01678 DBUG_RETURN(TRUE); 01679 } 01680 01681 /* Set parsing pointer to the last symbol of string (\n). */ 01682 unknown_key= ptr-1; 01683 } 01684 DBUG_RETURN(FALSE); 01685 }
1.4.7

