List:Commits« Previous MessageNext Message »
From:Alexander Nozdrin Date:June 14 2007 2:32pm
Subject:bk commit into 5.1 tree (anozdrin:1.2552) BUG#11986
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of alik. When alik does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-06-14 18:32:08+04:00, anozdrin@ibm. +9 -0
  This the 4-th patch in scope of CS patch (BUG#11986).
  
  The patch contains the following changes:
    - Introduce auxilary functions to convenient work with character sets:
      - resolve_charset();
      - resolve_collation();
      - get_default_db_collation();
    - Introduce set_lex_string();
    - Refactor Table_trigger_list::process_triggers() &
      sp_head::execute_trigger() to be consistent with other code;
    - Move reusable code from add_table_for_trigger() into
      build_trn_path() and load_table_name_for_trigger() to be used
      in the following patch.
    - Rename triggers_file_ext and trigname_file_ext into TRN_EXT and
      TRG_EXT respectively.

  include/my_sys.h@stripped, 2007-06-14 18:32:05+04:00, anozdrin@ibm. +8 -0
    Introduced auxilary functions (to be used in the following patch).

  mysys/charset.c@stripped, 2007-06-14 18:32:05+04:00, anozdrin@ibm. +64 -0
    Introduced auxilary functions (to be used in the following patch).

  sql/handler.cc@stripped, 2007-06-14 18:32:05+04:00, anozdrin@ibm. +2 -2
    Rename triggers_file_ext -> TRG_EXT;
    Rename trigname_file_ext -> TRN_EXT.

  sql/mysql_priv.h@stripped, 2007-06-14 18:32:05+04:00, anozdrin@ibm. +10 -3
    1. Fix typo;
    2. Introduce auxilary functions (set_lex_string() will  be used
       in the following patch);
    3. Rename triggers_file_ext -> TRG_EXT;
       Rename trigname_file_ext -> TRN_EXT.

  sql/sp_head.cc@stripped, 2007-06-14 18:32:05+04:00, anozdrin@ibm. +66 -20
    Make sp_head::execute_trigger() consistent with
    sp_head::execute_function() and sp_head::execute_procedure().

  sql/sp_head.h@stripped, 2007-06-14 18:32:05+04:00, anozdrin@ibm. +4 -2
    Make sp_head::execute_trigger() consistent with
    sp_head::execute_function() and sp_head::execute_procedure().

  sql/sql_db.cc@stripped, 2007-06-14 18:32:05+04:00, anozdrin@ibm. +36 -13
    1. Introduce auxilary function.
    2. Polishing.

  sql/sql_trigger.cc@stripped, 2007-06-14 18:32:05+04:00, anozdrin@ibm. +181 -129
    1. Move common code from add_table_for_trigger() into
       - build_trn_path();
       - check_trn_exists();
       - load_table_name_for_trigger();
    2. Polishing.

  sql/sql_trigger.h@stripped, 2007-06-14 18:32:05+04:00, anozdrin@ibm. +15 -4
    1. Move common code from add_table_for_trigger() into
       - build_trn_path();
       - check_trn_exists();
       - load_table_name_for_trigger();
    2. Polishing.

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	anozdrin
# Host:	ibm.
# Root:	/home/alik/Documents/MySQL/devel/5.1-rt-cs-4

--- 1.222/include/my_sys.h	2007-05-24 15:11:20 +04:00
+++ 1.223/include/my_sys.h	2007-06-14 18:32:05 +04:00
@@ -904,6 +904,14 @@
 extern CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags);
 extern CHARSET_INFO *get_charset_by_csname(const char *cs_name,
 					   uint cs_flags, myf my_flags);
+
+extern bool resolve_charset(CHARSET_INFO **cs,
+                            const char *cs_name,
+                            CHARSET_INFO *default_cs);
+extern bool resolve_collation(CHARSET_INFO **cl,
+                              const char *cl_name,
+                              CHARSET_INFO *default_cl);
+
 extern void free_charsets(void);
 extern char *get_charsets_dir(char *buf);
 extern my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2);

--- 1.151/mysys/charset.c	2007-05-10 13:59:25 +04:00
+++ 1.152/mysys/charset.c	2007-06-14 18:32:05 +04:00
@@ -573,6 +573,70 @@
 }
 
 
+/**
+  Resolve character set by the character set name (utf8, latin1, ...).
+
+  The function tries to resolve character set by the specified name. If
+  there is character set with the given name, it is assigned to the "cs"
+  parameter and FALSE is returned. If there is no such character set,
+  "default_cs" is assigned to the "cs" and TRUE is returned.
+
+  @param[out] cs        Variable to store character set.
+  @param[in] cs_name    Character set name.
+  @param[in] default_cs Default character set.
+
+  @return FALSE if character set was resolved successfully; TRUE if there
+  is no character set with given name.
+*/
+
+bool resolve_charset(CHARSET_INFO **cs,
+                     const char *cs_name,
+                     CHARSET_INFO *default_cs)
+{
+  *cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0));
+
+  if (*cs == NULL)
+  {
+    *cs= default_cs;
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+
+/**
+  Resolve collation by the collation name (utf8_general_ci, ...).
+
+  The function tries to resolve collation by the specified name. If there
+  is collation with the given name, it is assigned to the "cl" parameter
+  and FALSE is returned. If there is no such collation, "default_cl" is
+  assigned to the "cl" and TRUE is returned.
+
+  @param[out] cl        Variable to store collation.
+  @param[in] cl_name    Collation name.
+  @param[in] default_cl Default collation.
+
+  @return FALSE if collation was resolved successfully; TRUE if there is no
+  collation with given name.
+*/
+
+bool resolve_collation(CHARSET_INFO **cl,
+                       const char *cl_name,
+                       CHARSET_INFO *default_cl)
+{
+  *cl= get_charset_by_name(cl_name, MYF(0));
+
+  if (*cl == NULL)
+  {
+    *cl= default_cl;
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+
 /*
   Escape string with backslashes (\)
 

--- 1.310/sql/handler.cc	2007-06-01 11:43:51 +04:00
+++ 1.311/sql/handler.cc	2007-06-14 18:32:05 +04:00
@@ -3376,8 +3376,8 @@
     const char **ext, *old_ext;
 
     known_extensions_id= mysys_usage_id;
-    found_exts.push_back((char*) triggers_file_ext);
-    found_exts.push_back((char*) trigname_file_ext);
+    found_exts.push_back((char*) TRG_EXT);
+    found_exts.push_back((char*) TRN_EXT);
 
     plugin_foreach(NULL, exts_handlerton,
                    MYSQL_STORAGE_ENGINE_PLUGIN, &found_exts);

--- 1.518/sql/mysql_priv.h	2007-06-14 10:47:13 +04:00
+++ 1.519/sql/mysql_priv.h	2007-06-14 18:32:05 +04:00
@@ -101,7 +101,7 @@
                         ER_WARN_DEPRECATED_SYNTAX, ER(ER_WARN_DEPRECATED_SYNTAX),    \
                         (Old), (Ver), (New));                                        \
     else                                                                             \
-      sql_print_warning("The syntax %s is deprecated and will be removed "           \
+      sql_print_warning("The syntax '%s' is deprecated and will be removed "         \
                         "in MySQL %s. Please use %s instead.", (Old), (Ver), (New)); \
   } while(0)
 
@@ -1590,6 +1590,7 @@
 bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create);
 bool load_db_opt_by_name(THD *thd, const char *db_name,
                          HA_CREATE_INFO *db_create_info);
+CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name);
 bool my_dbopt_init(void);
 void my_dbopt_cleanup(void);
 extern int creating_database; // How many database locks are made
@@ -1610,8 +1611,8 @@
 extern const char **errmesg;			/* Error messages */
 extern const char *myisam_recover_options_str;
 extern const char *in_left_expr_name, *in_additional_cond, *in_having_cond;
-extern const char * const triggers_file_ext;
-extern const char * const trigname_file_ext;
+extern const char * const TRG_EXT;
+extern const char * const TRN_EXT;
 extern Eq_creator eq_creator;
 extern Ne_creator ne_creator;
 extern Gt_creator gt_creator;
@@ -2145,6 +2146,12 @@
 /* sql/item_create.cc */
 int item_create_init();
 void item_create_cleanup();
+
+inline void lex_string_set(LEX_STRING *lex_str, const char *c_str)
+{
+  lex_str->str= (char *) c_str;
+  lex_str->length= strlen(c_str);
+}
 
 #endif /* MYSQL_SERVER */
 #endif /* MYSQL_CLIENT */

--- 1.153/sql/sql_db.cc	2007-06-01 11:43:53 +04:00
+++ 1.154/sql/sql_db.cc	2007-06-14 18:32:05 +04:00
@@ -538,6 +538,37 @@
 }
 
 
+/**
+  Return default database collation.
+
+  @param thd     Thread context.
+  @param db_name Database name.
+
+  @return CHARSET_INFO object. The operation always return valid character
+    set, even if the database does not exist.
+*/
+
+CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name)
+{
+  HA_CREATE_INFO db_info;
+
+  if (thd->db != NULL && strcmp(db_name, thd->db) == 0)
+    return thd->db_charset;
+
+  load_db_opt_by_name(thd, db_name, &db_info);
+
+  /*
+    NOTE: even if load_db_opt_by_name() fails,
+    db_info.default_table_charset contains valid character set
+    (collation_server). We should not fail if load_db_opt_by_name() fails,
+    because it is valid case. If a database has been created just by
+    "mkdir", it does not contain db.opt file, but it is valid database.
+  */
+
+  return db_info.default_table_charset;
+}
+
+
 /*
   Create a database
 
@@ -751,10 +782,8 @@
   if ((error=write_db_opt(thd, path, create_info)))
     goto exit;
 
-  /*
-     Change options if current database is being altered
-     TODO: Delete this code
-  */
+  /* Change options if current database is being altered. */
+
   if (thd->db && !strcmp(thd->db,db))
   {
     thd->db_charset= create_info->default_table_charset ?
@@ -1358,6 +1387,7 @@
 
   Security_context *sctx= thd->security_ctx;
   ulong db_access= sctx->db_access;
+  CHARSET_INFO *db_default_cl;
 
   DBUG_ENTER("mysql_change_db");
   DBUG_PRINT("enter",("name: '%s'", new_db_name->str));
@@ -1487,16 +1517,9 @@
     attributes and will be freed in THD::~THD().
   */
 
-  {
-    HA_CREATE_INFO db_options;
+  db_default_cl= get_default_db_collation(thd, new_db_file_name.str);
 
-    load_db_opt_by_name(thd, new_db_name->str, &db_options);
-
-    mysql_change_db_impl(thd, &new_db_file_name, db_access,
-                         db_options.default_table_charset ?
-                         db_options.default_table_charset :
-                         thd->variables.collation_server);
-  }
+  mysql_change_db_impl(thd, &new_db_file_name, db_access, db_default_cl);
 
   DBUG_RETURN(FALSE);
 }

--- 1.96/sql/sql_trigger.cc	2007-06-14 10:47:13 +04:00
+++ 1.97/sql/sql_trigger.cc	2007-06-14 18:32:05 +04:00
@@ -23,7 +23,7 @@
 static const LEX_STRING triggers_file_type=
   { C_STRING_WITH_LEN("TRIGGERS") };
 
-const char * const triggers_file_ext= ".TRG";
+const char * const TRG_EXT= ".TRG";
 
 /*
   Table of .TRG file field descriptors.
@@ -79,7 +79,7 @@
 static const LEX_STRING trigname_file_type=
   { C_STRING_WITH_LEN("TRIGGERNAME") };
 
-const char * const trigname_file_ext= ".TRN";
+const char * const TRN_EXT= ".TRN";
 
 static File_option trigname_file_parameters[]=
 {
@@ -132,6 +132,7 @@
   LEX_STRING *trigger_table_value;
 };
 
+
 /*
   Create or drop trigger for table.
 
@@ -463,14 +464,14 @@
     sql_create_definition_file() files handles renaming and backup of older
     versions
   */
-  file.length= build_table_filename(file_buff, FN_REFLEN-1,
+  file.length= build_table_filename(file_buff, FN_REFLEN - 1,
                                     tables->db, tables->table_name,
-                                    triggers_file_ext, 0);
+                                    TRG_EXT, 0);
   file.str= file_buff;
   trigname_file.length= build_table_filename(trigname_buff, FN_REFLEN-1,
                                              tables->db,
                                              lex->spname->m_name.str,
-                                             trigname_file_ext, 0);
+                                             TRN_EXT, 0);
   trigname_file.str= trigname_buff;
 
   /* Use the filesystem to enforce trigger namespace constraints. */
@@ -604,7 +605,7 @@
 static bool rm_trigger_file(char *path, const char *db,
                             const char *table_name)
 {
-  build_table_filename(path, FN_REFLEN-1, db, table_name, triggers_file_ext, 0);
+  build_table_filename(path, FN_REFLEN-1, db, table_name, TRG_EXT, 0);
   return my_delete(path, MYF(MY_WME));
 }
 
@@ -627,8 +628,7 @@
 static bool rm_trigname_file(char *path, const char *db,
                              const char *trigger_name)
 {
-  build_table_filename(path, FN_REFLEN-1,
-                       db, trigger_name, trigname_file_ext, 0);
+  build_table_filename(path, FN_REFLEN - 1, db, trigger_name, TRN_EXT, 0);
   return my_delete(path, MYF(MY_WME));
 }
 
@@ -653,8 +653,8 @@
   char file_buff[FN_REFLEN];
   LEX_STRING file;
 
-  file.length= build_table_filename(file_buff, FN_REFLEN-1, db, table_name,
-                                    triggers_file_ext, 0);
+  file.length= build_table_filename(file_buff, FN_REFLEN - 1, db, table_name,
+                                    TRG_EXT, 0);
   file.str= file_buff;
   return sql_create_definition_file(NULL, &file, &triggers_file_type,
                                     (uchar*)triggers, triggers_file_parameters,
@@ -834,8 +834,8 @@
 
   DBUG_ENTER("Table_triggers_list::check_n_load");
 
-  path.length= build_table_filename(path_buff, FN_REFLEN-1,
-                                    db, table_name, triggers_file_ext, 0);
+  path.length= build_table_filename(path_buff, FN_REFLEN - 1,
+                                    db, table_name, TRG_EXT, 0);
   path.str= path_buff;
 
   // QQ: should we analyze errno somehow ?
@@ -1106,7 +1106,7 @@
       be merged into .FRM anyway.
     */
     my_error(ER_WRONG_OBJECT, MYF(0),
-             table_name, triggers_file_ext+1, "TRIGGER");
+             table_name, TRG_EXT + 1, "TRIGGER");
     DBUG_RETURN(1);
   }
 
@@ -1166,83 +1166,66 @@
 }
 
 
-/*
+/**
   Find trigger's table from trigger identifier and add it to
   the statement table list.
 
-  SYNOPSIS
-    mysql_table_for_trigger()
-      thd    - current thread context
-      trig   - identifier for trigger
-      if_exists - treat a not existing trigger as a warning if TRUE
-      table - pointer to TABLE_LIST object for the table trigger (output)
-
-  RETURN VALUE
-    0 Success
-    1 Error
-*/
-
-int
-add_table_for_trigger(THD *thd, sp_name *trig, bool if_exists,
-                      TABLE_LIST **table)
+  @param[in] thd       Thread context.
+  @param[in] trg_name  Trigger name.
+  @param[in] if_exists TRUE if SQL statement contains "IF EXISTS" clause.
+                       That means a warning instead of error should be
+                       thrown if trigger with given name does not exist.
+  @param[out] table    Pointer to TABLE_LIST object for the
+                       table trigger.
+
+  @return Operation status
+    @retval FALSE On success.
+    @retval TRUE  Otherwise.
+*/
+
+bool add_table_for_trigger(THD *thd,
+                           sp_name *trg_name,
+                           bool if_exists,
+                           TABLE_LIST **table)
 {
   LEX *lex= thd->lex;
-  char path_buff[FN_REFLEN];
-  LEX_STRING path;
-  File_parser *parser;
-  struct st_trigname trigname;
-  Handle_old_incorrect_trigger_table_hook trigger_table_hook(
-                                          path_buff, &trigname.trigger_table);
-  
+  char trn_path_buff[FN_REFLEN];
+  LEX_STRING trn_path= { trn_path_buff, 0 };
+  LEX_STRING tbl_name;
+
   DBUG_ENTER("add_table_for_trigger");
-  DBUG_ASSERT(table != NULL);
 
-  path.length= build_table_filename(path_buff, FN_REFLEN-1,
-                                    trig->m_db.str, trig->m_name.str,
-                                    trigname_file_ext, 0);
-  path.str= path_buff;
+  build_trn_path(thd, trg_name, &trn_path);
 
-  if (access(path_buff, F_OK))
+  if (check_trn_exists(&trn_path))
   {
     if (if_exists)
     {
       push_warning_printf(thd,
-                         MYSQL_ERROR::WARN_LEVEL_NOTE,
-                         ER_TRG_DOES_NOT_EXIST,
-                         ER(ER_TRG_DOES_NOT_EXIST));
+                          MYSQL_ERROR::WARN_LEVEL_NOTE,
+                          ER_TRG_DOES_NOT_EXIST,
+                          ER(ER_TRG_DOES_NOT_EXIST));
+
       *table= NULL;
-      DBUG_RETURN(0);
+
+      DBUG_RETURN(FALSE);
     }
 
     my_error(ER_TRG_DOES_NOT_EXIST, MYF(0));
-    DBUG_RETURN(1);
-  }
-
-  if (!(parser= sql_parse_prepare(&path, thd->mem_root, 1)))
-    DBUG_RETURN(1);
-
-  if (!is_equal(&trigname_file_type, parser->type()))
-  {
-    my_error(ER_WRONG_OBJECT, MYF(0), trig->m_name.str, trigname_file_ext+1,
-             "TRIGGERNAME");
-    DBUG_RETURN(1);
+    DBUG_RETURN(TRUE);
   }
 
-  if (parser->parse((uchar*)&trigname, thd->mem_root,
-                    trigname_file_parameters, 1,
-                    &trigger_table_hook))
-    DBUG_RETURN(1);
+  if (load_table_name_for_trigger(thd, trg_name, &trn_path, &tbl_name))
+    DBUG_RETURN(TRUE);
 
   /* We need to reset statement table list to be PS/SP friendly. */
   lex->query_tables= 0;
   lex->query_tables_last= &lex->query_tables;
-  *table= sp_add_to_query_tables(thd, lex, trig->m_db.str,
-                                 trigname.trigger_table.str, TL_IGNORE);
 
-  if (! *table)
-    DBUG_RETURN(1);
+  *table= sp_add_to_query_tables(thd, lex, trg_name->m_db.str,
+                                 tbl_name.str, TL_IGNORE);
 
-  DBUG_RETURN(0);
+  DBUG_RETURN(*table ? FALSE : TRUE);
 }
 
 
@@ -1426,7 +1409,7 @@
   {
     trigname_file.length= build_table_filename(trigname_buff, FN_REFLEN-1,
                                                db_name, trigger->str,
-                                               trigname_file_ext, 0);
+                                               TRN_EXT, 0);
     trigname_file.str= trigname_buff;
 
     trigname.trigger_table= *new_table_name;
@@ -1535,77 +1518,54 @@
 }
 
 
-bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event,
-                                           trg_action_time_type time_type,
-                                           bool old_row_is_record1)
-{
-  bool err_status= FALSE;
-  sp_head *sp_trigger= bodies[event][time_type];
+/**
+  Execute trigger for given (event, time) pair.
 
-  if (sp_trigger)
-  {
-    Sub_statement_state statement_state;
-
-    if (old_row_is_record1)
-    {
-      old_field= record1_field;
-      new_field= trigger_table->field;
-    }
-    else
-    {
-      new_field= record1_field;
-      old_field= trigger_table->field;
-    }
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
-    Security_context *sctx= &sp_trigger->m_security_ctx;
-    Security_context *save_ctx= NULL;
+  The operation executes trigger for the specified event (insert, update,
+  delete) and time (after, before) if it is set.
 
+  @param thd
+  @param event
+  @param time_type,
+  @param old_row_is_record1
 
-    if (sp_trigger->m_chistics->suid != SP_IS_NOT_SUID &&
-        sctx->change_security_context(thd,
-                                      &sp_trigger->m_definer_user,
-                                      &sp_trigger->m_definer_host,
-                                      &sp_trigger->m_db,
-                                      &save_ctx))
-      return TRUE;
-
-    /*
-      Fetch information about table-level privileges to GRANT_INFO structure for
-      subject table. Check of privileges that will use it and information about
-      column-level privileges will happen in Item_trigger_field::fix_fields().
-    */
+  @return Error status.
+    @retval FALSE on success.
+    @retval TRUE  on error.
+*/
 
-    fill_effective_table_privileges(thd,
-                                    &subject_table_grants[event][time_type],
-                                    trigger_table->s->db.str,
-                                    trigger_table->s->table_name.str);
+bool Table_triggers_list::process_triggers(THD *thd,
+                                           trg_event_type event,
+                                           trg_action_time_type time_type,
+                                           bool old_row_is_record1)
+{
+  bool err_status;
+  Sub_statement_state statement_state;
 
-    /* Check that the definer has TRIGGER privilege on the subject table. */
+  if (!bodies[event][time_type])
+    return FALSE;
 
-    if (!(subject_table_grants[event][time_type].privilege & TRIGGER_ACL))
-    {
-      char priv_desc[128];
-      get_privilege_desc(priv_desc, sizeof(priv_desc), TRIGGER_ACL);
-
-      my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), priv_desc,
-               thd->security_ctx->priv_user, thd->security_ctx->host_or_ip,
-               trigger_table->s->table_name.str);
+  if (old_row_is_record1)
+  {
+    old_field= record1_field;
+    new_field= trigger_table->field;
+  }
+  else
+  {
+    new_field= record1_field;
+    old_field= trigger_table->field;
+  }
 
-      sctx->restore_security_context(thd, save_ctx);
-      return TRUE;
-    }
-#endif // NO_EMBEDDED_ACCESS_CHECKS
+  thd->reset_sub_statement_state(&statement_state, SUB_STMT_TRIGGER);
 
-    thd->reset_sub_statement_state(&statement_state, SUB_STMT_TRIGGER);
-    err_status= sp_trigger->execute_trigger
-      (thd, trigger_table->s->db.str, trigger_table->s->table_name.str,
-       &subject_table_grants[event][time_type]);
-    thd->restore_sub_statement_state(&statement_state);
+  err_status=
+    bodies[event][time_type]->execute_trigger(
+      thd,
+      &trigger_table->s->db,
+      &trigger_table->s->table_name,
+      &subject_table_grants[event][time_type]);
 
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
-    sctx->restore_security_context(thd, save_ctx);
-#endif // NO_EMBEDDED_ACCESS_CHECKS
-  }
+  thd->restore_sub_statement_state(&statement_state);
 
   return err_status;
 }
@@ -1745,5 +1705,97 @@
     /* Set parsing pointer to the last symbol of string (\n). */
     unknown_key= ptr-1;
   }
+  DBUG_RETURN(FALSE);
+}
+
+
+/**
+  Contruct path to TRN-file.
+
+  @param thd[in]        Thread context.
+  @param trg_name[in]   Trigger name.
+  @param trn_path[out]  Variable to store constructed path
+*/
+
+void build_trn_path(THD *thd, const sp_name *trg_name, LEX_STRING *trn_path)
+{
+  /* Construct path to the TRN-file. */
+
+  trn_path->length= build_table_filename(trn_path->str,
+                                         FN_REFLEN - 1,
+                                         trg_name->m_db.str,
+                                         trg_name->m_name.str,
+                                         TRN_EXT,
+                                         0);
+}
+
+
+/**
+  Check if TRN-file exists.
+
+  @return
+    @retval TRUE  if TRN-file does not exist.
+    @retval FALSE if TRN-file exists.
+*/
+
+bool check_trn_exists(const LEX_STRING *trn_path)
+{
+  return access(trn_path->str, F_OK) != 0;
+}
+
+
+/**
+  Retrieve table name for given trigger.
+
+  @param thd[in]        Thread context.
+  @param trg_name[in]   Trigger name.
+  @param trn_path[in]   Path to the corresponding TRN-file.
+  @param tbl_name[out]  Variable to store retrieved table name.
+
+  @return Error status.
+    @retval FALSE on success.
+    @retval TRUE  if table name could not be retrieved.
+*/
+
+bool load_table_name_for_trigger(THD *thd,
+                                 const sp_name *trg_name,
+                                 const LEX_STRING *trn_path,
+                                 LEX_STRING *tbl_name)
+{
+  File_parser *parser;
+  struct st_trigname trn_data;
+
+  Handle_old_incorrect_trigger_table_hook trigger_table_hook(
+                                          trn_path->str,
+                                          &trn_data.trigger_table);
+
+  DBUG_ENTER("load_table_name_for_trigger");
+
+  /* Parse the TRN-file. */
+
+  if (!(parser= sql_parse_prepare(trn_path, thd->mem_root, TRUE)))
+    DBUG_RETURN(TRUE);
+
+  if (!is_equal(&trigname_file_type, parser->type()))
+  {
+    my_error(ER_WRONG_OBJECT, MYF(0),
+             trg_name->m_name.str,
+             TRN_EXT + 1,
+             "TRIGGERNAME");
+
+    DBUG_RETURN(TRUE);
+  }
+
+  if (parser->parse((uchar*) &trn_data, thd->mem_root,
+                    trigname_file_parameters, 1,
+                    &trigger_table_hook))
+    DBUG_RETURN(TRUE);
+
+  /* Copy trigger table name. */
+
+  *tbl_name= trn_data.trigger_table;
+
+  /* That's all. */
+
   DBUG_RETURN(FALSE);
 }

--- 1.30/sql/sql_trigger.h	2007-04-05 13:17:46 +04:00
+++ 1.31/sql/sql_trigger.h	2007-06-14 18:32:05 +04:00
@@ -17,7 +17,7 @@
 /*
   This class holds all information about triggers of table.
 
-  QQ: Will it be merged into TABLE in future ?
+  QQ: Will it be merged into TABLE in the future ?
 */
 
 class Table_triggers_list: public Sql_alloc
@@ -143,6 +143,17 @@
 extern const LEX_STRING trg_action_time_type_names[];
 extern const LEX_STRING trg_event_type_names[];
 
-int
-add_table_for_trigger(THD *thd, sp_name *trig, bool if_exists,
-                      TABLE_LIST **table);
+bool add_table_for_trigger(THD *thd,
+                           sp_name *trg_name,
+                           bool continue_if_not_exist,
+                           TABLE_LIST **table);
+
+void build_trn_path(THD *thd, const sp_name *trg_name, LEX_STRING *trn_path);
+
+bool check_trn_exists(const LEX_STRING *trn_path);
+
+bool load_table_name_for_trigger(THD *thd,
+                                 const sp_name *trg_name,
+                                 const LEX_STRING *trn_path,
+                                 LEX_STRING *tbl_name);
+

--- 1.277/sql/sp_head.cc	2007-06-12 21:04:18 +04:00
+++ 1.278/sql/sp_head.cc	2007-06-14 18:32:05 +04:00
@@ -1268,30 +1268,31 @@
 #endif // ! NO_EMBEDDED_ACCESS_CHECKS
 
 
-/*
+/**
+  Execute trigger stored program.
+
   Execute a trigger:
-   - changes security context for triggers
-   - switch to new memroot
-   - call sp_head::execute
-   - restore old memroot
-   - restores security context
-
-  SYNOPSIS
-    sp_head::execute_trigger()
-      thd               Thread handle
-      db                database name
-      table             table name
-      grant_info        GRANT_INFO structure to be filled with
-                        information about definer's privileges
-                        on subject table
-   
-  RETURN
-    FALSE  on success
-    TRUE   on error
+   - changes security context for triggers;
+   - switch to new memroot;
+   - call sp_head::execute;
+   - restore old memroot;
+   - restores security context.
+
+  @param thd        Thread context.
+  @param db_name    Database name.
+  @param table_name Table name.
+  @param grant_info GRANT_INFO structure to be filled with information
+                    about definer's privileges on subject table.
+
+  @return Error status.
+    @retval FALSE on success.
+    @retval TRUE  on error.
 */
 
 bool
-sp_head::execute_trigger(THD *thd, const char *db, const char *table,
+sp_head::execute_trigger(THD *thd,
+                         const LEX_STRING *db_name,
+                         const LEX_STRING *table_name,
                          GRANT_INFO *grant_info)
 {
   sp_rcontext *octx = thd->spcont;
@@ -1304,6 +1305,46 @@
   DBUG_ENTER("sp_head::execute_trigger");
   DBUG_PRINT("info", ("trigger %s", m_name.str));
 
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+  Security_context *save_ctx= NULL;
+
+
+  if (m_chistics->suid != SP_IS_NOT_SUID &&
+      m_security_ctx.change_security_context(thd,
+                                             &m_definer_user,
+                                             &m_definer_host,
+                                             &m_db,
+                                             &save_ctx))
+    DBUG_RETURN(TRUE);
+
+  /*
+    Fetch information about table-level privileges for subject table into
+    GRANT_INFO instance. The access check itself will happen in
+    Item_trigger_field, where this information will be used along with
+    information about column-level privileges.
+  */
+
+  fill_effective_table_privileges(thd,
+                                  grant_info,
+                                  db_name->str,
+                                  table_name->str);
+
+  /* Check that the definer has TRIGGER privilege on the subject table. */
+
+  if (!(grant_info->privilege & TRIGGER_ACL))
+  {
+    char priv_desc[128];
+    get_privilege_desc(priv_desc, sizeof(priv_desc), TRIGGER_ACL);
+
+    my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), priv_desc,
+             thd->security_ctx->priv_user, thd->security_ctx->host_or_ip,
+             table_name->str);
+
+    m_security_ctx.restore_security_context(thd, save_ctx);
+    DBUG_RETURN(TRUE);
+  }
+#endif // NO_EMBEDDED_ACCESS_CHECKS
+
   /*
     Prepare arena and memroot for objects which lifetime is whole
     duration of trigger call (sp_rcontext, it's tables and items,
@@ -1336,6 +1377,11 @@
 
 err_with_cleanup:
   thd->restore_active_arena(&call_arena, &backup_arena);
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+  m_security_ctx.restore_security_context(thd, save_ctx);
+#endif // NO_EMBEDDED_ACCESS_CHECKS
+
   delete nctx;
   call_arena.free_items();
   free_root(&call_mem_root, MYF(0));

--- 1.109/sql/sp_head.h	2007-06-10 14:43:54 +04:00
+++ 1.110/sql/sp_head.h	2007-06-14 18:32:05 +04:00
@@ -216,8 +216,10 @@
   destroy();
 
   bool
-  execute_trigger(THD *thd, const char *db, const char *table,
-                  GRANT_INFO *grant_onfo);
+  execute_trigger(THD *thd,
+                  const LEX_STRING *db_name,
+                  const LEX_STRING *table_name,
+                  GRANT_INFO *grant_info);
 
   bool
   execute_function(THD *thd, Item **args, uint argcount, Field *return_fld);
Thread
bk commit into 5.1 tree (anozdrin:1.2552) BUG#11986Alexander Nozdrin14 Jun
  • Re: bk commit into 5.1 tree (anozdrin:1.2552) BUG#11986Konstantin Osipov14 Jun