List:Internals« Previous MessageNext Message »
From:sanja Date:July 28 2005 9:39pm
Subject:bk commit into 5.0 tree (bell:1.1883) BUG#5891
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of bell. When bell 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
  1.1883 05/07/28 22:39:11 bell@stripped +14 -0
  store/restore sql_mode which was in force during ctrigger creation (BUG#5891)
  other sql_mode fixes

  sql/sql_view.cc
    1.54 05/07/28 22:39:07 bell@stripped +4 -4
    fixed sql_mode

  sql/sql_trigger.h
    1.11 05/07/28 22:39:07 bell@stripped +6 -1
    store/restore sql_mode which was in force during ctrigger creation

  sql/sql_trigger.cc
    1.23 05/07/28 22:39:07 bell@stripped +76 -15
    store/restore sql_mode which was in force during ctrigger creation

  sql/sql_show.cc
    1.258 05/07/28 22:39:07 bell@stripped +18 -4
    added sql_mode field

  sql/sp_head.h
    1.63 05/07/28 22:39:07 bell@stripped +1 -1
    comment fixed according this changes

  sql/sp_head.cc
    1.160 05/07/28 22:39:07 bell@stripped +15 -29
    added sql_mode storing/restoring during SP execution
    optimised sql_mode printing

  sql/set_var.h
    1.69 05/07/28 22:39:07 bell@stripped +2 -0
    mode output made as static method

  sql/set_var.cc
    1.126 05/07/28 22:39:07 bell@stripped +23 -6
    mode output made as static method

  sql/parse_file.h
    1.8 05/07/28 22:39:07 bell@stripped +3 -1
    new type of list (ulonglong)

  sql/parse_file.cc
    1.14 05/07/28 22:39:07 bell@stripped +64 -4
    new type of list (ulonglong)

  sql/mysqld.cc
    1.486 05/07/28 22:39:07 bell@stripped +41 -4
    add length of mode names

  mysql-test/t/trigger.test
    1.19 05/07/28 22:39:06 bell@stripped +36 -0
    storing and restoring parsing modes for triggers

  mysql-test/r/trigger.result
    1.14 05/07/28 22:39:06 bell@stripped +47 -0
    storing and restoring sql modes for triggers

  mysql-test/r/information_schema.result
    1.65 05/07/28 22:39:06 bell@stripped +9 -8
    changes in information schema

# 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:	bell
# Host:	sanja.is.com.ua
# Root:	/home/bell/mysql/bk/work-trigger-5.0

--- 1.485/sql/mysqld.cc	2005-07-20 02:33:19 +03:00
+++ 1.486/sql/mysqld.cc	2005-07-28 22:39:07 +03:00
@@ -220,21 +220,58 @@
 /* Constants */
 
 const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
-static const char *sql_mode_names[] =
+static const char *sql_mode_names[]=
 {
   "REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
   "?", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
   "NO_DIR_IN_CREATE",
   "POSTGRESQL", "ORACLE", "MSSQL", "DB2", "MAXDB", "NO_KEY_OPTIONS",
   "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI",
-  "NO_AUTO_VALUE_ON_ZERO", "NO_BACKSLASH_ESCAPES", "STRICT_TRANS_TABLES",
"STRICT_ALL_TABLES",
-  "NO_ZERO_IN_DATE", "NO_ZERO_DATE", "ALLOW_INVALID_DATES", "ERROR_FOR_DIVISION_BY_ZERO",
+  "NO_AUTO_VALUE_ON_ZERO", "NO_BACKSLASH_ESCAPES", "STRICT_TRANS_TABLES",
+  "STRICT_ALL_TABLES",
+  "NO_ZERO_IN_DATE", "NO_ZERO_DATE", "ALLOW_INVALID_DATES",
+  "ERROR_FOR_DIVISION_BY_ZERO",
   "TRADITIONAL", "NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE",
   "NO_ENGINE_SUBSTITUTION",
   NullS
 };
+static const unsigned int sql_mode_names_len[]=
+{
+  /*REAL_AS_FLOAT*/               13,
+  /*PIPES_AS_CONCAT*/             15,
+  /*ANSI_QUOTES*/                 11,
+  /*IGNORE_SPACE*/                12,
+  /*?*/                           1,
+  /*ONLY_FULL_GROUP_BY*/          18,
+  /*NO_UNSIGNED_SUBTRACTION*/     23,
+  /*NO_DIR_IN_CREATE*/            16,
+  /*POSTGRESQL*/                  10,
+  /*ORACLE*/                      6,
+  /*MSSQL*/                       5,
+  /*DB2*/                         3,
+  /*MAXDB*/                       5,
+  /*NO_KEY_OPTIONS*/              14,
+  /*NO_TABLE_OPTIONS*/            16,
+  /*NO_FIELD_OPTIONS*/            16,
+  /*MYSQL323*/                    8,
+  /*MYSQL40*/                     7,
+  /*ANSI*/                        4,
+  /*NO_AUTO_VALUE_ON_ZERO*/       21,
+  /*NO_BACKSLASH_ESCAPES*/        20,
+  /*STRICT_TRANS_TABLES*/         19,
+  /*STRICT_ALL_TABLES*/           17,
+  /*NO_ZERO_IN_DATE*/             15,
+  /*NO_ZERO_DATE*/                12,
+  /*ALLOW_INVALID_DATES*/         19,
+  /*ERROR_FOR_DIVISION_BY_ZERO*/  26,
+  /*TRADITIONAL*/                 11,
+  /*NO_AUTO_CREATE_USER*/         19,
+  /*HIGH_NOT_PRECEDENCE*/         19,
+  /*NO_ENGINE_SUBSTITUTION*/      22
+};
 TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"",
-			    sql_mode_names, NULL };
+			    sql_mode_names,
+                            (unsigned int *)sql_mode_names_len };
 static const char *tc_heuristic_recover_names[]=
 {
   "COMMIT", "ROLLBACK", NullS

--- 1.257/sql/sql_show.cc	2005-07-20 02:33:19 +03:00
+++ 1.258/sql/sql_show.cc	2005-07-28 22:39:07 +03:00
@@ -2983,9 +2983,13 @@
                           const char *tname, LEX_STRING *trigger_name,
                           enum trg_event_type event,
                           enum trg_action_time_type timing,
-                          LEX_STRING *trigger_stmt)
+                          LEX_STRING *trigger_stmt,
+                          ulong sql_mode)
 {
   CHARSET_INFO *cs= system_charset_info;
+  byte *sql_mode_str;
+  ulong sql_mode_len;
+
   restore_record(table, s->default_values);
   table->field[1]->store(db, strlen(db), cs);
   table->field[2]->store(trigger_name->str, trigger_name->length, cs);
@@ -2999,6 +3003,12 @@
                           trg_action_time_type_names[timing].length, cs);
   table->field[14]->store("OLD", 3, cs);
   table->field[15]->store("NEW", 3, cs);
+
+  sql_mode_str=
+    sys_var_thd_sql_mode::symbolic_mode_representation(thd,
+                                                       sql_mode,
+                                                       &sql_mode_len);
+  table->field[17]->store(sql_mode_str, sql_mode_len, cs);
   return schema_table_store_record(thd, table);
 }
 
@@ -3031,13 +3041,16 @@
       {
         LEX_STRING trigger_name;
         LEX_STRING trigger_stmt;
+        ulong sql_mode;
         if (triggers->get_trigger_info(thd, (enum trg_event_type) event,
                                        (enum trg_action_time_type)timing,
-                                       &trigger_name, &trigger_stmt))
+                                       &trigger_name, &trigger_stmt,
+                                       &sql_mode))
           continue;
         if (store_trigger(thd, table, base_name, file_name, &trigger_name,
                          (enum trg_event_type) event,
-                         (enum trg_action_time_type) timing, &trigger_stmt))
+                         (enum trg_action_time_type) timing, &trigger_stmt,
+                         sql_mode))
           DBUG_RETURN(1);
       }
     }
@@ -3949,6 +3962,7 @@
   {"ACTION_REFERENCE_OLD_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0},
   {"ACTION_REFERENCE_NEW_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0},
   {"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Created"},
+  {"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, "sql_mode"},
   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
 };
 
@@ -4003,7 +4017,7 @@
    fill_open_tables, make_old_format, 0, -1, -1, 1},
   {"STATUS", variables_fields_info, create_schema_table, fill_status, 
    make_old_format, 0, -1, -1, 1},
-  {"TRIGGERS", triggers_fields_info, create_schema_table, 
+  {"TRIGGERS", triggers_fields_info, create_schema_table,
    get_all_tables, make_old_format, get_schema_triggers_record, 5, 6, 0},
   {"VARIABLES", variables_fields_info, create_schema_table, fill_variables,
    make_old_format, 0, -1, -1, 1},

--- 1.13/sql/parse_file.cc	2005-07-18 15:31:59 +03:00
+++ 1.14/sql/parse_file.cc	2005-07-28 22:39:07 +03:00
@@ -166,6 +166,25 @@
     }
     break;
   }
+  case FILE_OPTIONS_ULLLIST:
+  {
+    List_iterator_fast<ulonglong> it(*((List<ulonglong>*)
+                                       (base + parameter->offset)));
+    bool first= 1;
+    ulonglong *val;
+    while ((val= it++))
+    {
+      num.set(*val, &my_charset_bin);
+      // We need ' ' after string to detect list continuation
+      if ((!first && my_b_append(file, (const byte *)" ", 1)) ||
+          my_b_append(file, (const byte *)num.ptr(), num.length()))
+      {
+        DBUG_RETURN(TRUE);
+      }
+      first= 0;
+    }
+    break;
+  }
   default:
     DBUG_ASSERT(0); // never should happened
   }
@@ -615,6 +634,8 @@
   char *eol;
   LEX_STRING *str;
   List<LEX_STRING> *list;
+  ulonglong *num;
+  List<ulonglong> *nlist;
   DBUG_ENTER("File_parser::parse");
 
   while (ptr < end && found < required)
@@ -719,7 +740,7 @@
 	case FILE_OPTIONS_STRLIST:
 	{
           list= (List<LEX_STRING>*)(base + parameter->offset);
-	    
+
 	  list->empty();
 	  // list parsing
 	  while (ptr < end)
@@ -741,17 +762,56 @@
 	      goto list_err_w_message;
 	    }
 	  }
-      end_of_list:
+
+end_of_list:
 	  if (*(ptr++) != '\n')
 	    goto list_err;
 	  break;
 
-      list_err_w_message:
+list_err_w_message:
 	  my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
                    parameter->name.str, line);
-      list_err:
+list_err:
 	  DBUG_RETURN(TRUE);
 	}
+        case FILE_OPTIONS_ULLLIST:
+        {
+          nlist= (List<ulonglong>*)(base + parameter->offset);
+          nlist->empty();
+          // list parsing
+          while (ptr < end)
+          {
+            int not_used;
+            char *num_end= end;
+            if (!(num= (ulonglong*)alloc_root(mem_root, sizeof(ulonglong))) ||
+                nlist->push_back(num, mem_root))
+              goto nlist_err;
+            *num= my_strtoll10(ptr, &num_end, &not_used);
+            ptr= num_end;
+            switch (*ptr) {
+            case '\n':
+              goto end_of_nlist;
+            case ' ':
+              // we cant go over buffer bounds, because we have \0 at the end
+              ptr++;
+              break;
+            default:
+              goto nlist_err_w_message;
+            }
+          }
+
+end_of_nlist:
+          if (*(ptr++) != '\n')
+            goto nlist_err;
+          break;
+
+nlist_err_w_message:
+          my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
+                   parameter->name.str, line);
+nlist_err:
+          DBUG_RETURN(TRUE);
+
+        }
 	default:
 	  DBUG_ASSERT(0); // never should happened
 	}

--- 1.7/sql/parse_file.h	2004-10-07 01:44:11 +03:00
+++ 1.8/sql/parse_file.h	2005-07-28 22:39:07 +03:00
@@ -27,8 +27,10 @@
   FILE_OPTIONS_REV,		/* Revision version number (ulonglong) */
   FILE_OPTIONS_TIMESTAMP,	/* timestamp (LEX_STRING have to be
 				   allocated with length 20 (19+1) */
-  FILE_OPTIONS_STRLIST          /* list of escaped strings
+  FILE_OPTIONS_STRLIST,         /* list of escaped strings
                                    (List<LEX_STRING>) */
+  FILE_OPTIONS_ULLLIST          /* list of ulonglong values
+                                   (List<ulonglong>) */
 };
 
 struct File_option

--- 1.53/sql/sql_view.cc	2005-07-12 18:33:56 +03:00
+++ 1.54/sql/sql_view.cc	2005-07-28 22:39:07 +03:00
@@ -691,7 +691,7 @@
   view_select= &lex->select_lex;
   view_select->select_number= ++thd->select_number;
   {
-    ulong options= thd->options;
+    ulong save_mode= thd->variables.sql_mode;
     /* switch off modes which can prevent normal parsing of VIEW
       - MODE_REAL_AS_FLOAT            affect only CREATE TABLE parsing
       + MODE_PIPES_AS_CONCAT          affect expression parsing
@@ -716,13 +716,13 @@
       ? MODE_NO_AUTO_VALUE_ON_ZERO    affect UPDATEs
       + MODE_NO_BACKSLASH_ESCAPES     affect expression parsing
     */
-    thd->options&= ~(MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
-                     MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES);
+    thd->variables.sql_mode&= ~(MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
+                                MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES);
     CHARSET_INFO *save_cs= thd->variables.character_set_client;
     thd->variables.character_set_client= system_charset_info;
     res= yyparse((void *)thd);
     thd->variables.character_set_client= save_cs;
-    thd->options= options;
+    thd->variables.sql_mode= save_mode;
   }
   if (!res && !thd->is_fatal_error)
   {

--- 1.13/mysql-test/r/trigger.result	2005-07-19 19:06:42 +03:00
+++ 1.14/mysql-test/r/trigger.result	2005-07-28 22:39:06 +03:00
@@ -595,3 +595,50 @@
 ERROR 42000: FUNCTION test.bug5893 does not exist
 drop trigger t1_bu;
 drop table t1;
+set sql_mode='ansi';
+create table t1 ("t1 column" int);
+create trigger t1_bi before insert on t1 for each row set new."t1 column" = 5;
+set sql_mode=default;
+insert into t1 values (0);
+create trigger t1_af after insert on t1 for each row set @a=10;
+insert into t1 values (0);
+select * from t1;
+t1 column
+5
+5
+select @a;
+@a
+10
+show triggers;
+Trigger	Event	Table	Statement	Timing	Created	sql_mode
+t1_bi	INSERT	t1	set new."t1 column" =
5	BEFORE	#	REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI
+t1_af	INSERT	t1	 set @a=10	AFTER	#	
+select * from information_schema.triggers;
+TRIGGER_CATALOG	TRIGGER_SCHEMA	TRIGGER_NAME	EVENT_MANIPULATION	EVENT_OBJECT_CATALOG	EVENT_OBJECT_SCHEMA	EVENT_OBJECT_TABLE	ACTION_ORDER	ACTION_CONDITION	ACTION_STATEMENT	ACTION_ORIENTATION	ACTION_TIMING	ACTION_REFERENCE_OLD_TABLE	ACTION_REFERENCE_NEW_TABLE	ACTION_REFERENCE_OLD_ROW	ACTION_REFERENCE_NEW_ROW	CREATED	SQL_MODE
+NULL	test	t1_bi	INSERT	NULL	test	t1	0	NULL	set new."t1 column" =
5	ROW	BEFORE	NULL	NULL	OLD	NEW	#	REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI
+NULL	test	t1_af	INSERT	NULL	test	t1	0	NULL	 set @a=10	ROW	AFTER	NULL	NULL	OLD	NEW	#	
+drop table t1;
+set sql_mode="traditional";
+create table t1 (a date);
+insert into t1 values ('2004-01-00');
+ERROR 22007: Incorrect date value: '2004-01-00' for column 'a' at row 1
+set sql_mode="";
+create trigger t1_bi before insert on t1 for each row set new.a = '2004-01-00';
+set sql_mode="traditional";
+insert into t1 values ('2004-01-01');
+select * from t1;
+a
+2004-01-00
+set sql_mode=default;
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` date default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+show triggers;
+Trigger	Event	Table	Statement	Timing	Created	sql_mode
+t1_bi	INSERT	t1	 set new.a = '2004-01-00'	BEFORE	#	
+select * from information_schema.triggers;
+TRIGGER_CATALOG	TRIGGER_SCHEMA	TRIGGER_NAME	EVENT_MANIPULATION	EVENT_OBJECT_CATALOG	EVENT_OBJECT_SCHEMA	EVENT_OBJECT_TABLE	ACTION_ORDER	ACTION_CONDITION	ACTION_STATEMENT	ACTION_ORIENTATION	ACTION_TIMING	ACTION_REFERENCE_OLD_TABLE	ACTION_REFERENCE_NEW_TABLE	ACTION_REFERENCE_OLD_ROW	ACTION_REFERENCE_NEW_ROW	CREATED	SQL_MODE
+NULL	test	t1_bi	INSERT	NULL	test	t1	0	NULL	 set new.a =
'2004-01-00'	ROW	BEFORE	NULL	NULL	OLD	NEW	#	
+drop table t1;

--- 1.18/mysql-test/t/trigger.test	2005-07-19 20:38:06 +03:00
+++ 1.19/mysql-test/t/trigger.test	2005-07-28 22:39:06 +03:00
@@ -610,3 +610,39 @@
 # This should not crash server too.
 drop trigger t1_bu;
 drop table t1;
+
+#
+# storing and restoring parsing modes for triggers (BUG#5891)
+#
+set sql_mode='ansi';
+create table t1 ("t1 column" int);
+create trigger t1_bi before insert on t1 for each row set new."t1 column" = 5;
+set sql_mode=default;
+insert into t1 values (0);
+# create trigger with different sql_mode
+create trigger t1_af after insert on t1 for each row set @a=10;
+insert into t1 values (0);
+select * from t1;
+select @a;
+--replace_column 6 #
+show triggers;
+--replace_column 17 #
+select * from information_schema.triggers;
+drop table t1;
+# check that rigger preserve sql_mode during execution
+set sql_mode="traditional";
+create table t1 (a date);
+-- error 1292
+insert into t1 values ('2004-01-00');
+set sql_mode="";
+create trigger t1_bi before insert on t1 for each row set new.a = '2004-01-00';
+set sql_mode="traditional";
+insert into t1 values ('2004-01-01');
+select * from t1;
+set sql_mode=default;
+show create table t1;
+--replace_column 6 #
+show triggers;
+--replace_column 17 #
+select * from information_schema.triggers;
+drop table t1;

--- 1.22/sql/sql_trigger.cc	2005-07-19 19:06:43 +03:00
+++ 1.23/sql/sql_trigger.cc	2005-07-28 22:39:07 +03:00
@@ -32,8 +32,12 @@
 */
 static File_option triggers_file_parameters[]=
 {
-  {{(char*)"triggers", 8}, offsetof(class Table_triggers_list, definitions_list),
-   FILE_OPTIONS_STRLIST},
+  {{(char*)"triggers", 8},
+    offsetof(class Table_triggers_list, definitions_list),
+    FILE_OPTIONS_STRLIST},
+  {{(char*)"sql_modes", 13},
+    offsetof(class Table_triggers_list, definition_modes_list),
+    FILE_OPTIONS_ULLLIST},
   {{0, 0}, 0, FILE_OPTIONS_STRING}
 };
 
@@ -127,12 +131,13 @@
     DBUG_RETURN(TRUE);
 
   /*
-    We do not allow creation of triggers on views or temporary tables.
-    We have to do this check here and not in
-    Table_triggers_list::create_trigger() because we want to avoid messing
-    with table cash for views and temporary tables.
+    We do not allow creation of triggers on temporary tables. We also don't
+    allow creation of triggers on views but fulfilment of this restriction
+    is guaranteed by open_ltable(). It is better to have this check here
+    than do it in Table_triggers_list::create_trigger() and mess with table
+    cache.
   */
-  if (tables->view || table->s->tmp_table != NO_TMP_TABLE)
+  if (table->s->tmp_table != NO_TMP_TABLE)
   {
     my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias);
     DBUG_RETURN(TRUE);
@@ -221,6 +226,7 @@
        trigname_path[FN_REFLEN];
   LEX_STRING dir, file, trigname_file;
   LEX_STRING *trg_def, *name;
+  ulonglong *trg_sql_mode;
   Item_trigger_field *trg_field;
   struct st_trigname trigname;
 
@@ -307,11 +313,15 @@
   */
   if (!(trg_def= (LEX_STRING *)alloc_root(&table->mem_root,
                                           sizeof(LEX_STRING))) ||
-      definitions_list.push_back(trg_def, &table->mem_root))
+      definitions_list.push_back(trg_def, &table->mem_root) ||
+      !(trg_sql_mode= (ulonglong*)alloc_root(&table->mem_root,
+                                             sizeof(ulonglong))) ||
+      definition_modes_list.push_back(trg_sql_mode, &table->mem_root))
     goto err_with_cleanup;
 
   trg_def->str= thd->query;
   trg_def->length= thd->query_length;
+  *trg_sql_mode= thd->variables.sql_mode;
 
   if (!sql_create_definition_file(&dir, &file, &triggers_file_type,
                                   (gptr)this, triggers_file_parameters, 3))
@@ -390,11 +400,13 @@
   LEX_STRING *name;
   List_iterator_fast<LEX_STRING> it_name(names_list);
   List_iterator<LEX_STRING>      it_def(definitions_list);
+  List_iterator<ulonglong>       it_mod(definition_modes_list);
   char path[FN_REFLEN];
 
   while ((name= it_name++))
   {
     it_def++;
+    it_mod++;
 
     if (my_strcasecmp(system_charset_info, lex->spname->m_name.str,
                       name->str) == 0)
@@ -404,6 +416,7 @@
         clean trigger removing since table will be reopened anyway.
       */
       it_def.remove();
+      it_mod.remove();
 
       if (definitions_list.is_empty())
       {
@@ -549,10 +562,48 @@
       if (!triggers)
         DBUG_RETURN(1);
 
+      /*
+        We don't have sql_modes in old versions of .TRG file, so we should
+        initialize list for safety.
+      */
+      triggers->definition_modes_list.empty();
+
       if (parser->parse((gptr)triggers, &table->mem_root,
-                        triggers_file_parameters, 1))
+                        triggers_file_parameters, 2))
         DBUG_RETURN(1);
 
+      List_iterator_fast<LEX_STRING> it(triggers->definitions_list);
+      LEX_STRING *trg_create_str, *trg_name_str;
+      ulonglong *trg_sql_mode;
+
+      if (triggers->definition_modes_list.is_empty() &&
+          !triggers->definitions_list.is_empty())
+      {
+        /*
+          It is old file format => we should fill list of sql_modes.
+
+          We use one mode (current) for all triggers, because we have not
+          information about mode in old format.
+        */
+        if (!(trg_sql_mode= (ulonglong*)alloc_root(&table->mem_root,
+                                                   sizeof(ulonglong))))
+        {
+          DBUG_RETURN(1); // EOM
+        }
+        *trg_sql_mode= global_system_variables.sql_mode;
+        while ((trg_create_str= it++))
+        {
+          if (triggers->definition_modes_list.push_back(trg_sql_mode,
+                                                        &table->mem_root))
+          {
+            DBUG_RETURN(1); // EOM
+          }
+        }
+        it.rewind();
+      }
+
+      DBUG_ASSERT(triggers->definition_modes_list.elements ==
+                  triggers->definitions_list.elements);
       table->triggers= triggers;
 
       /*
@@ -574,15 +625,17 @@
       if (!names_only && triggers->prepare_record1_accessors(table))
         DBUG_RETURN(1);
 
-      List_iterator_fast<LEX_STRING> it(triggers->definitions_list);
-      LEX_STRING *trg_create_str, *trg_name_str;
       char *trg_name_buff;
+      List_iterator_fast<ulonglong> itm(triggers->definition_modes_list);
       LEX *old_lex= thd->lex, lex;
+      ulong save_sql_mode= thd->variables.sql_mode;
 
       thd->lex= &lex;
 
       while ((trg_create_str= it++))
       {
+        trg_sql_mode= itm++;
+        thd->variables.sql_mode= (ulong)*trg_sql_mode;
         lex_start(thd, (uchar*)trg_create_str->str, trg_create_str->length);
 
         if (yyparse((void *)thd) || thd->is_fatal_error)
@@ -595,9 +648,11 @@
           goto err_with_lex_cleanup;
         }
 
+        lex.sphead->m_sql_mode= *trg_sql_mode;
         triggers->bodies[lex.trg_chistics.event]
                              [lex.trg_chistics.action_time]= lex.sphead;
-        if (triggers->names_list.push_back(&lex.sphead->m_name,
&table->mem_root))
+        if (triggers->names_list.push_back(&lex.sphead->m_name,
+                                           &table->mem_root))
             goto err_with_lex_cleanup;
 
         if (names_only)
@@ -611,8 +666,9 @@
           in old/new versions of row in trigger to Field objects in table being
           opened.
 
-          We ignore errors here, because if even something is wrong we still will
-          be willing to open table to perform some operations (e.g. SELECT)...
+          We ignore errors here, because if even something is wrong we still
+          will be willing to open table to perform some operations (e.g.
+          SELECT)...
           Anyway some things can be checked only during trigger execution.
         */
         for (Item_trigger_field *trg_field=
@@ -624,6 +680,7 @@
         lex_end(&lex);
       }
       thd->lex= old_lex;
+      thd->variables.sql_mode= save_sql_mode;
 
       DBUG_RETURN(0);
 
@@ -631,6 +688,7 @@
       // QQ: anything else ?
       lex_end(&lex);
       thd->lex= old_lex;
+      thd->variables.sql_mode= save_sql_mode;
       DBUG_RETURN(1);
     }
 
@@ -657,6 +715,7 @@
       time_type - trigger action time
       name      - returns name of trigger
       stmt      - returns statement of trigger
+      sql_mode  - returns sql_mode of trigger
 
   RETURN VALUE
     False - success
@@ -666,7 +725,8 @@
 bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event,
                                            trg_action_time_type time_type,
                                            LEX_STRING *trigger_name,
-                                           LEX_STRING *trigger_stmt)
+                                           LEX_STRING *trigger_stmt,
+                                           ulong *sql_mode)
 {
   sp_head *body;
   DBUG_ENTER("get_trigger_info");
@@ -674,6 +734,7 @@
   {
     *trigger_name= body->m_name;
     *trigger_stmt= body->m_body;
+    *sql_mode= body->m_sql_mode;
     DBUG_RETURN(0);
   }
   DBUG_RETURN(1);

--- 1.10/sql/sql_trigger.h	2005-07-19 19:06:43 +03:00
+++ 1.11/sql/sql_trigger.h	2005-07-28 22:39:07 +03:00
@@ -60,6 +60,10 @@
     It have to be public because we are using it directly from parser.
   */
   List<LEX_STRING>  definitions_list;
+  /*
+    List of sql modes for triggers
+  */
+  List<ulonglong> definition_modes_list;
 
   Table_triggers_list(TABLE *table_arg):
     record1_field(0), table(table_arg)
@@ -123,7 +127,8 @@
   }
   bool get_trigger_info(THD *thd, trg_event_type event,
                         trg_action_time_type time_type,
-                        LEX_STRING *trigger_name, LEX_STRING *trigger_stmt);
+                        LEX_STRING *trigger_name, LEX_STRING *trigger_stmt,
+                        ulong *sql_mode);
 
   static bool check_n_load(THD *thd, const char *db, const char *table_name,
                            TABLE *table, bool names_only);

--- 1.64/mysql-test/r/information_schema.result	2005-07-21 16:43:50 +03:00
+++ 1.65/mysql-test/r/information_schema.result	2005-07-28 22:39:06 +03:00
@@ -713,6 +713,7 @@
 information_schema	VIEWS	VIEW_DEFINITION
 information_schema	TRIGGERS	ACTION_CONDITION
 information_schema	TRIGGERS	ACTION_STATEMENT
+information_schema	TRIGGERS	SQL_MODE
 select table_name, column_name, data_type from information_schema.columns
 where data_type = 'datetime';
 table_name	column_name	data_type
@@ -790,45 +791,45 @@
 end if;
 end|
 show triggers;
-Trigger	Event	Table	Statement	Timing	Created
+Trigger	Event	Table	Statement	Timing	Created	sql_mode
 trg1	INSERT	t1	
 begin
 if new.j > 10 then
 set new.j := 10;
 end if;
-end	BEFORE	NULL
+end	BEFORE	NULL	
 trg2	UPDATE	t1	
 begin
 if old.i % 2 = 0 then
 set new.j := -1;
 end if;
-end	BEFORE	NULL
+end	BEFORE	NULL	
 trg3	UPDATE	t1	
 begin
 if new.j = -1 then
 set @fired:= "Yes";
 end if;
-end	AFTER	NULL
+end	AFTER	NULL	
 select * from information_schema.triggers;
-TRIGGER_CATALOG	TRIGGER_SCHEMA	TRIGGER_NAME	EVENT_MANIPULATION	EVENT_OBJECT_CATALOG	EVENT_OBJECT_SCHEMA	EVENT_OBJECT_TABLE	ACTION_ORDER	ACTION_CONDITION	ACTION_STATEMENT	ACTION_ORIENTATION	ACTION_TIMING	ACTION_REFERENCE_OLD_TABLE	ACTION_REFERENCE_NEW_TABLE	ACTION_REFERENCE_OLD_ROW	ACTION_REFERENCE_NEW_ROW	CREATED
+TRIGGER_CATALOG	TRIGGER_SCHEMA	TRIGGER_NAME	EVENT_MANIPULATION	EVENT_OBJECT_CATALOG	EVENT_OBJECT_SCHEMA	EVENT_OBJECT_TABLE	ACTION_ORDER	ACTION_CONDITION	ACTION_STATEMENT	ACTION_ORIENTATION	ACTION_TIMING	ACTION_REFERENCE_OLD_TABLE	ACTION_REFERENCE_NEW_TABLE	ACTION_REFERENCE_OLD_ROW	ACTION_REFERENCE_NEW_ROW	CREATED	SQL_MODE
 NULL	test	trg1	INSERT	NULL	test	t1	0	NULL	
 begin
 if new.j > 10 then
 set new.j := 10;
 end if;
-end	ROW	BEFORE	NULL	NULL	OLD	NEW	NULL
+end	ROW	BEFORE	NULL	NULL	OLD	NEW	NULL	
 NULL	test	trg2	UPDATE	NULL	test	t1	0	NULL	
 begin
 if old.i % 2 = 0 then
 set new.j := -1;
 end if;
-end	ROW	BEFORE	NULL	NULL	OLD	NEW	NULL
+end	ROW	BEFORE	NULL	NULL	OLD	NEW	NULL	
 NULL	test	trg3	UPDATE	NULL	test	t1	0	NULL	
 begin
 if new.j = -1 then
 set @fired:= "Yes";
 end if;
-end	ROW	AFTER	NULL	NULL	OLD	NEW	NULL
+end	ROW	AFTER	NULL	NULL	OLD	NEW	NULL	
 drop trigger trg1;
 drop trigger trg2;
 drop trigger trg3;

--- 1.125/sql/set_var.cc	2005-07-19 21:21:02 +03:00
+++ 1.126/sql/set_var.cc	2005-07-28 22:39:07 +03:00
@@ -3196,27 +3196,44 @@
  Functions to handle sql_mode
 ****************************************************************************/
 
-byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type,
-				      LEX_STRING *base)
+/*
+  Make string representation of mode
+
+  SINOPSYS
+    thd       thread handler
+    val       sql_mode value
+    len       pointer on length of string
+*/
+
+byte *sys_var_thd_sql_mode::symbolic_mode_representation(THD *thd, ulong val,
+                                                         ulong *len)
 {
-  ulong val;
   char buff[256];
   String tmp(buff, sizeof(buff), &my_charset_latin1);
 
   tmp.length(0);
-  val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
-        thd->variables.*offset);
   for (uint i= 0; val; val>>= 1, i++)
   {
     if (val & 1)
     {
-      tmp.append(enum_names->type_names[i]);
+      tmp.append(sql_mode_typelib.type_names[i],
+                 sql_mode_typelib.type_lengths[i]);
       tmp.append(',');
     }
   }
   if (tmp.length())
     tmp.length(tmp.length() - 1);
+  *len= tmp.length();
   return (byte*) thd->strmake(tmp.ptr(), tmp.length());
+}
+
+byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type,
+				      LEX_STRING *base)
+{
+  ulong val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
+              thd->variables.*offset);
+  ulong length_unused;
+  return symbolic_mode_representation(thd, val, &length_unused);
 }
 
 

--- 1.68/sql/set_var.h	2005-07-16 12:45:23 +03:00
+++ 1.69/sql/set_var.h	2005-07-28 22:39:07 +03:00
@@ -361,6 +361,8 @@
   }
   void set_default(THD *thd, enum_var_type type);
   byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
+  static byte *symbolic_mode_representation(THD *thd, ulong sql_mode,
+                                            ulong *length);
 };
 
 

--- 1.159/sql/sp_head.cc	2005-07-15 18:24:13 +03:00
+++ 1.160/sql/sp_head.cc	2005-07-28 22:39:07 +03:00
@@ -574,6 +574,7 @@
   sp_rcontext *ctx;
   int ret= 0;
   uint ip= 0;
+  ulong save_sql_mode;
   Query_arena *old_arena;
   query_id_t old_query_id;
   TABLE *old_derived_tables;
@@ -626,6 +627,8 @@
   old_query_id= thd->query_id;
   old_derived_tables= thd->derived_tables;
   thd->derived_tables= 0;
+  save_sql_mode= thd->variables.sql_mode;
+  thd->variables.sql_mode= m_sql_mode;
   /*
     It is also more efficient to save/restore current thd->lex once when
     do it in each instruction
@@ -715,6 +718,7 @@
   thd->query_id= old_query_id;
   DBUG_ASSERT(!thd->derived_tables);
   thd->derived_tables= old_derived_tables;
+  thd->variables.sql_mode= save_sql_mode;
 
   thd->current_arena= old_arena;
   state= EXECUTED;
@@ -1245,8 +1249,6 @@
   String buffer(buff, sizeof(buff), system_charset_info);
   int res;
   List<Item> field_list;
-  ulong old_sql_mode;
-  sys_var *sql_mode_var;
   byte *sql_mode_str;
   ulong sql_mode_len;
   bool full_access;
@@ -1258,19 +1260,13 @@
 
   if (check_show_routine_access(thd, this, &full_access))
     return 1;
-  
-  old_sql_mode= thd->variables.sql_mode;
-  thd->variables.sql_mode= m_sql_mode;
-  sql_mode_var= find_sys_var("SQL_MODE", 8);
-  if (sql_mode_var)
-  {
-    sql_mode_str= sql_mode_var->value_ptr(thd, OPT_SESSION, 0);
-    sql_mode_len= strlen((char*) sql_mode_str);
-  }
 
+  sql_mode_str=
+    sys_var_thd_sql_mode::symbolic_mode_representation(thd,
+                                                       m_sql_mode,
+                                                       &sql_mode_len);
   field_list.push_back(new Item_empty_string("Procedure", NAME_LEN));
-  if (sql_mode_var)
-    field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len));
+  field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len));
   // 1024 is for not to confuse old clients
   field_list.push_back(new Item_empty_string("Create Procedure",
 					     max(buffer.length(), 1024)));
@@ -1282,15 +1278,13 @@
   }
   protocol->prepare_for_resend();
   protocol->store(m_name.str, m_name.length, system_charset_info);
-  if (sql_mode_var)
-    protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
+  protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
   if (full_access)
     protocol->store(m_defstr.str, m_defstr.length, system_charset_info);
   res= protocol->write();
   send_eof(thd);
 
  done:
-  thd->variables.sql_mode= old_sql_mode;
   DBUG_RETURN(res);
 }
 
@@ -1326,7 +1320,6 @@
   String buffer(buff, sizeof(buff), system_charset_info);
   int res;
   List<Item> field_list;
-  ulong old_sql_mode;
   sys_var *sql_mode_var;
   byte *sql_mode_str;
   ulong sql_mode_len;
@@ -1339,15 +1332,10 @@
   if (check_show_routine_access(thd, this, &full_access))
     return 1;
 
-  old_sql_mode= thd->variables.sql_mode;
-  thd->variables.sql_mode= m_sql_mode;
-  sql_mode_var= find_sys_var("SQL_MODE", 8);
-  if (sql_mode_var)
-  {
-    sql_mode_str= sql_mode_var->value_ptr(thd, OPT_SESSION, 0);
-    sql_mode_len= strlen((char*) sql_mode_str);
-  }
-
+  sql_mode_str=
+    sys_var_thd_sql_mode::symbolic_mode_representation(thd,
+                                                       m_sql_mode,
+                                                       &sql_mode_len);
   field_list.push_back(new Item_empty_string("Function",NAME_LEN));
   if (sql_mode_var)
     field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len));
@@ -1361,15 +1349,13 @@
   }
   protocol->prepare_for_resend();
   protocol->store(m_name.str, m_name.length, system_charset_info);
-  if (sql_mode_var)
-    protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
+  protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
   if (full_access)
     protocol->store(m_defstr.str, m_defstr.length, system_charset_info);
   res= protocol->write();
   send_eof(thd);
 
  done:
-  thd->variables.sql_mode= old_sql_mode;
   DBUG_RETURN(res);
 }
 

--- 1.62/sql/sp_head.h	2005-07-09 20:55:09 +03:00
+++ 1.63/sql/sp_head.h	2005-07-28 22:39:07 +03:00
@@ -121,7 +121,7 @@
   uchar *m_tmp_query;		// Temporary pointer to sub query string
   uint m_old_cmq;		// Old CLIENT_MULTI_QUERIES value
   st_sp_chistics *m_chistics;
-  ulong m_sql_mode;		// For SHOW CREATE
+  ulong m_sql_mode;		// For SHOW CREATE and execution
   LEX_STRING m_qname;		// db.name
   LEX_STRING m_db;
   LEX_STRING m_name;
Thread
bk commit into 5.0 tree (bell:1.1883) BUG#5891sanja28 Jul