List:Commits« Previous MessageNext Message »
From:Marc Alff Date:May 9 2012 7:32am
Subject:bzr push into mysql-trunk-pfs-tuning branch (marc.alff:3505 to 3506)
View as plain text  
 3506 Marc Alff	2012-05-09 [merge]
      Merge mysql-trunk --> mysql-trunk-pfs-tuning

    added:
      unittest/gunit/field_date-t.cc
      unittest/gunit/field_datetime-t.cc
      unittest/gunit/field_long-t.cc
      unittest/gunit/field_newdecimal-t.cc
      unittest/gunit/field_temporal_utils.h
      unittest/gunit/gunit_test_main_server.cc
    modified:
      client/mysqldump.c
      mysql-test/extra/rpl_tests/rpl_extra_col_master.test
      mysql-test/extra/rpl_tests/rpl_mts_crash_safe.inc
      mysql-test/include/index_merge2.inc
      mysql-test/include/wait_condition.inc
      mysql-test/r/ctype_ucs.result
      mysql-test/r/index_merge_myisam.result
      mysql-test/r/mysqldump.result
      mysql-test/r/type_bit.result
      mysql-test/r/variables-big.result
      mysql-test/suite/rpl/r/rpl_extra_col_master_innodb.result
      mysql-test/suite/rpl/r/rpl_extra_col_master_myisam.result
      mysql-test/suite/rpl/r/rpl_gtid_sql_until_before_after.result
      mysql-test/suite/rpl/t/rpl_gtid_sql_until_before_after.test
      mysql-test/suite/rpl/t/rpl_stm_mts_crash_safe.test
      mysql-test/t/ctype_ucs.test
      mysql-test/t/events_time_zone.test
      mysql-test/t/mysqldump.test
      mysql-test/t/type_bit.test
      mysql-test/t/variables-big.test
      sql-common/my_time.c
      sql/field.cc
      sql/field.h
      sql/field_conv.cc
      sql/item.cc
      sql/item.h
      sql/item_cmpfunc.cc
      sql/item_func.cc
      sql/item_func.h
      sql/item_strfunc.h
      sql/item_timefunc.cc
      sql/item_timefunc.h
      sql/opt_range.cc
      sql/rpl_slave.cc
      sql/sql_base.cc
      sql/sql_lex.cc
      sql/sql_lex.h
      sql/sql_select.h
      sql/sql_yacc.yy
      sql/unireg.cc
      storage/innobase/include/ut0counter.h
      unittest/gunit/CMakeLists.txt
      unittest/gunit/copy_info-t.cc
      unittest/gunit/create_field-t.cc
      unittest/gunit/decimal-t.cc
      unittest/gunit/fake_table.h
      unittest/gunit/field-t.cc
      unittest/gunit/field_timestamp-t.cc
      unittest/gunit/get_diagnostics-t.cc
      unittest/gunit/item-t.cc
      unittest/gunit/item_func_now_local-t.cc
      unittest/gunit/join_tab_sort-t.cc
      unittest/gunit/my_decimal-t.cc
      unittest/gunit/opt_range-t.cc
      unittest/gunit/segfault-t.cc
      unittest/gunit/sql_table-t.cc
      unittest/gunit/test_utils.cc
      unittest/gunit/test_utils.h
      unittest/unit.pl
 3505 Marc Alff	2012-05-07
      Windows build break (perf tests)

    modified:
      storage/perfschema/unittest/pfs_benchmark_helper.cc
=== modified file 'client/mysqldump.c'
--- a/client/mysqldump.c	2012-04-16 09:14:37 +0000
+++ b/client/mysqldump.c	2012-05-08 09:59:59 +0000
@@ -85,6 +85,15 @@
 #define IGNORE_DATA 0x01 /* don't dump data for this table */
 #define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */
 
+/* general_log or slow_log tables under mysql database */
+static inline my_bool general_log_or_slow_log_tables(const char *db, 
+                                                     const char *table)
+{
+  return (strcmp(db, "mysql") == 0) &&
+         ((strcmp(table, "general_log") == 0) ||
+          (strcmp(table, "slow_log") == 0));
+}
+
 static void add_load_option(DYNAMIC_STRING *str, const char *option,
                              const char *option_value);
 static ulong find_set(TYPELIB *lib, const char *x, uint length,
@@ -2467,6 +2476,7 @@ static uint get_table_structure(char *ta
                                 "TABLE_SCHEMA = '%s' AND TABLE_NAME = '%s'";
   FILE       *sql_file= md_result_file;
   int        len;
+  my_bool    is_log_table;
   MYSQL_RES  *result;
   MYSQL_ROW  row;
   DBUG_ENTER("get_table_structure");
@@ -2551,9 +2561,12 @@ static uint get_table_structure(char *ta
       /*
         Even if the "table" is a view, we do a DROP TABLE here.  The
         view-specific code below fills in the DROP VIEW.
+        We will skip the DROP TABLE for general_log and slow_log, since
+        those stmts will fail, in case we apply dump by enabling logging.
        */
-        fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",
-                opt_quoted_table);
+        if (!general_log_or_slow_log_tables(db, table))
+          fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",
+                  opt_quoted_table);
         check_io(sql_file);
       }
 
@@ -2665,12 +2678,25 @@ static uint get_table_structure(char *ta
 
       row= mysql_fetch_row(result);
 
-      fprintf(sql_file, (opt_compatible_mode & 3) ? "%s;\n" :
-              "/*!40101 SET @saved_cs_client     = @@character_set_client */;\n"
-              "/*!40101 SET character_set_client = utf8 */;\n"
-              "%s;\n"
-              "/*!40101 SET character_set_client = @saved_cs_client */;\n",
-              row[1]);
+      is_log_table= general_log_or_slow_log_tables(db, table);
+      if (is_log_table)
+        row[1]+= 13; /* strlen("CREATE TABLE ")= 13 */
+      if (opt_compatible_mode & 3)
+      {
+        fprintf(sql_file,
+                is_log_table ? "CREATE TABLE IF NOT EXISTS %s;\n" : "%s;\n",
+                row[1]);
+      }
+      else
+      {
+        fprintf(sql_file,
+                "/*!40101 SET @saved_cs_client     = @@character_set_client */;\n"
+                "/*!40101 SET character_set_client = utf8 */;\n"
+                "%s%s;\n"
+                "/*!40101 SET character_set_client = @saved_cs_client */;\n",
+                is_log_table ? "CREATE TABLE IF NOT EXISTS " : "",
+                row[1]);
+      }
 
       check_io(sql_file);
       mysql_free_result(result);
@@ -4339,6 +4365,22 @@ static int dump_all_tables_in_db(char *d
   if (opt_xml)
     print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NullS);
 
+  if (strcmp(database, "mysql") == 0)
+  {
+    char table_type[NAME_LEN];
+    char ignore_flag;
+    uint num_fields;
+    num_fields= get_table_structure((char *) "general_log", 
+                                    database, table_type, &ignore_flag);
+    if (num_fields == 0)
+      verbose_msg("-- Warning: get_table_structure() failed with some internal "
+                  "error for 'general_log' table\n");
+    num_fields= get_table_structure((char *) "slow_log", 
+                                    database, table_type, &ignore_flag);
+    if (num_fields == 0)
+      verbose_msg("-- Warning: get_table_structure() failed with some internal "
+                  "error for 'slow_log' table\n");
+  }
   if (lock_tables)
   {
     DYNAMIC_STRING query;

=== modified file 'mysql-test/extra/rpl_tests/rpl_extra_col_master.test'
--- a/mysql-test/extra/rpl_tests/rpl_extra_col_master.test	2012-03-06 14:29:42 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_extra_col_master.test	2012-05-07 08:29:18 +0000
@@ -156,7 +156,7 @@ connection master;
                        f6 ENUM('a', 'b', 'c') default 'a',
 		       f7 DECIMAL(17,9) default '1000.00',
 		       f8 MEDIUMBLOB,
-		       f9 NUMERIC(6,4) default '2000.00',
+		       f9 NUMERIC(6,2) default '2000.00',
 		       f10 VARCHAR(1024),
 		       f11 BINARY(20) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
 		       f12 SET('a', 'b', 'c') default 'b')
@@ -179,7 +179,7 @@ connection master;
                        f5 DOUBLE DEFAULT '2.00', 
 		       f6 DECIMAL(17,9) default '1000.00',
 		       f7 MEDIUMBLOB,
-		       f8 NUMERIC(6,4) default '2000.00',
+		       f8 NUMERIC(6,2) default '2000.00',
 		       f9 VARCHAR(1024),
 		       f10 BINARY(20) not null default '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
 		       f11 CHAR(255))

=== modified file 'mysql-test/extra/rpl_tests/rpl_mts_crash_safe.inc'
--- a/mysql-test/extra/rpl_tests/rpl_mts_crash_safe.inc	2012-04-11 16:52:28 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_mts_crash_safe.inc	2012-05-07 19:15:48 +0000
@@ -94,6 +94,7 @@ if ($commands == recovery)
   SET GLOBAL debug="d,rotate_slave_debug_group";
   --source include/start_slave_io.inc
   let $wait_condition=SELECT Master_log_pos = $m_before_master_pos AND Master_log_name = "$m_before_master_file" FROM mysql.slave_master_info;
+  let $slave_failure_printout= 1;
   --source include/wait_condition.inc
 
   #### Crashing server after assigning and processing jobs ######

=== modified file 'mysql-test/include/index_merge2.inc'
--- a/mysql-test/include/index_merge2.inc	2011-11-03 07:01:49 +0000
+++ b/mysql-test/include/index_merge2.inc	2012-05-08 06:07:50 +0000
@@ -463,3 +463,34 @@ DROP TABLE t1, t2;
 #a	b
 #1	b
 #DROP TABLE t1, t2;
+
+--echo #
+--echo # BUG#13970015: ASSERT `MIN_ENDP || MAX_ENDP' FAILED IN
+--echo #               HANDLER::MULTI_RANGE_READ_INFO_CONST
+--echo #
+
+CREATE TABLE t1 (
+  pk INT NOT NULL,
+  col_int_key INT NOT NULL,
+  col_varchar_key VARCHAR(1) NOT NULL,
+  PRIMARY KEY (pk),
+  KEY col_int_key (col_int_key),
+  KEY col_varchar_key (col_varchar_key,col_int_key)
+);
+
+INSERT INTO t1 VALUES (1,1,'a'), (2,2,'b');
+
+EXPLAIN
+SELECT col_int_key
+FROM t1
+WHERE col_varchar_key >= 'l' OR 
+      (((pk BETWEEN 141 AND 141) OR col_varchar_key <> 'l') 
+         AND ((pk BETWEEN 141 AND 141) OR (col_int_key > 141)));
+
+SELECT col_int_key
+FROM t1
+WHERE col_varchar_key >= 'l' OR 
+      (((pk BETWEEN 141 AND 141) OR col_varchar_key <> 'l') 
+         AND ((pk BETWEEN 141 AND 141) OR (col_int_key > 141)));
+
+DROP TABLE t1;

=== modified file 'mysql-test/include/wait_condition.inc'
--- a/mysql-test/include/wait_condition.inc	2012-02-08 20:01:18 +0000
+++ b/mysql-test/include/wait_condition.inc	2012-05-07 19:15:48 +0000
@@ -13,12 +13,14 @@
 #
 #   OR
 #
+#    let $slave_failure_printout= 1; # to force post-failure printout
 #    let $wait_timeout= 60; # Override default 30 seconds with 60.
 #    let $wait_condition=
 #      SELECT c = 3 FROM t;
 #    --source include/wait_condition.inc
 #    --echo Executed the test condition $wait_condition_reps times
 #
+# 
 # EXAMPLE
 #    events_bugs.test, events_time_zone.test
 #
@@ -51,5 +53,16 @@ while ($wait_counter)
 }
 if (!$success)
 {
+  if ($slave_failure_printout)
+  {
+     --connection slave
+     --echo
+     --echo *** Slave server status: ***
+     --echo
+     --query_vertical show slave status
+     --query_vertical show processlist
+     --query_vertical select * from mysql.slave_relay_log_info
+     --query_vertical select * from mysql.slave_master_info
+  }
   die Timeout in wait_condition.inc for $wait_condition;
 }

=== modified file 'mysql-test/r/ctype_ucs.result'
--- a/mysql-test/r/ctype_ucs.result	2012-03-20 05:51:52 +0000
+++ b/mysql-test/r/ctype_ucs.result	2012-05-07 08:29:18 +0000
@@ -4721,5 +4721,17 @@ DO CAST(CONVERT('' USING ucs2) AS UNSIGN
 Warnings:
 Warning	1292	Truncated incorrect INTEGER value: ''
 #
+# Test error message for conversion using different charset
+# 
+CREATE TABLE t1 (a DECIMAL(2,0));
+SET sql_mode='strict_all_tables';
+INSERT INTO t1 VALUES (CONVERT('9e99999999' USING ucs2));
+ERROR HY000: Incorrect decimal value: '9e99999999' for column 'a' at row 1
+SET sql_mode=DEFAULT;
+INSERT INTO t1 VALUES (CONVERT('aaa' USING ucs2));
+Warnings:
+Warning	1366	Incorrect decimal value: 'aaa' for column 'a' at row 1
+DROP TABLE t1;
+#
 # End of 5.6 tests
 #

=== modified file 'mysql-test/r/index_merge_myisam.result'
--- a/mysql-test/r/index_merge_myisam.result	2012-02-29 11:17:52 +0000
+++ b/mysql-test/r/index_merge_myisam.result	2012-05-08 06:07:50 +0000
@@ -1241,6 +1241,34 @@ SELECT * FROM t2;
 a	b
 1	b
 DROP TABLE t1, t2;
+#
+# BUG#13970015: ASSERT `MIN_ENDP || MAX_ENDP' FAILED IN
+#               HANDLER::MULTI_RANGE_READ_INFO_CONST
+#
+CREATE TABLE t1 (
+pk INT NOT NULL,
+col_int_key INT NOT NULL,
+col_varchar_key VARCHAR(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+);
+INSERT INTO t1 VALUES (1,1,'a'), (2,2,'b');
+EXPLAIN
+SELECT col_int_key
+FROM t1
+WHERE col_varchar_key >= 'l' OR 
+(((pk BETWEEN 141 AND 141) OR col_varchar_key <> 'l') 
+AND ((pk BETWEEN 141 AND 141) OR (col_int_key > 141)));
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	PRIMARY,col_int_key,col_varchar_key	NULL	NULL	NULL	2	Using where
+SELECT col_int_key
+FROM t1
+WHERE col_varchar_key >= 'l' OR 
+(((pk BETWEEN 141 AND 141) OR col_varchar_key <> 'l') 
+AND ((pk BETWEEN 141 AND 141) OR (col_int_key > 141)));
+col_int_key
+DROP TABLE t1;
 #---------------- 2-sweeps read Index merge test 2 -------------------------------
 SET SESSION DEFAULT_STORAGE_ENGINE = MyISAM;
 drop table if exists t1;

=== modified file 'mysql-test/r/mysqldump.result'
--- a/mysql-test/r/mysqldump.result	2012-03-06 14:29:42 +0000
+++ b/mysql-test/r/mysqldump.result	2012-05-08 09:59:59 +0000
@@ -5352,5 +5352,49 @@ Warning: Using a password on the command
 /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
 
 DROP DATABASE b12688860_db;
-
-End of tests
+#
+# Bug#45740 MYSQLDUMP DOESN'T DUMP GENERAL_LOG AND SLOW_QUERY CAUSES RESTORE PROBLEM
+#
+SET @old_log_output_state=       @@global.log_output;
+SET @old_general_log_state=      @@global.general_log;
+SET @old_slow_query_log_state=   @@global.slow_query_log;
+call mtr.add_suppression("Failed to write to mysql.general_log");
+SET @@global.log_output="TABLE";
+SET @@global.general_log='OFF';
+SET @@global.slow_query_log='OFF';
+DROP DATABASE mysql;
+Warnings:
+Error	1146	Table 'mysql.proc' doesn't exist
+Error	1146	Table 'mysql.event' doesn't exist
+SHOW CREATE TABLE mysql.general_log;
+Table	Create Table
+general_log	CREATE TABLE `general_log` (
+  `event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `user_host` mediumtext NOT NULL,
+  `thread_id` int(11) NOT NULL,
+  `server_id` int(10) unsigned NOT NULL,
+  `command_type` varchar(64) NOT NULL,
+  `argument` mediumtext NOT NULL
+) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'
+SHOW CREATE TABLE mysql.slow_log;
+Table	Create Table
+slow_log	CREATE TABLE `slow_log` (
+  `start_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `user_host` mediumtext NOT NULL,
+  `query_time` time NOT NULL,
+  `lock_time` time NOT NULL,
+  `rows_sent` int(11) NOT NULL,
+  `rows_examined` int(11) NOT NULL,
+  `db` varchar(512) NOT NULL,
+  `last_insert_id` int(11) NOT NULL,
+  `insert_id` int(11) NOT NULL,
+  `server_id` int(10) unsigned NOT NULL,
+  `sql_text` mediumtext NOT NULL,
+  `thread_id` int(11) NOT NULL
+) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'
+SET @@global.log_output=       @old_log_output_state;
+SET @@global.slow_query_log=   @old_slow_query_log_state;
+SET @@global.general_log=      @old_general_log_state;
+#
+# End of 5.1 tests
+#

=== modified file 'mysql-test/r/type_bit.result'
--- a/mysql-test/r/type_bit.result	2010-02-21 21:33:11 +0000
+++ b/mysql-test/r/type_bit.result	2012-05-07 08:29:18 +0000
@@ -718,6 +718,12 @@ t1	CREATE TABLE `t1` (
   `f1` bit(2) NOT NULL DEFAULT b'10',
   `f2` bit(14) NOT NULL DEFAULT b'11110000111100'
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci
+INSERT INTO t1 (f1) VALUES (DEFAULT);
+INSERT INTO t1 VALUES (b'', b'');
+SELECT HEX(f1), HEX(f2) FROM t1;
+HEX(f1)	HEX(f2)
+2	3C3C
+0	0
 DROP TABLE t1;
 CREATE TABLE IF NOT EXISTS t1 (
 f1 bit(2) NOT NULL default b''
@@ -801,3 +807,14 @@ SUM(a)
 NULL
 DROP TABLE t1;
 End of 5.1 tests
+#
+# Test insert of no bits. Should be treated as 0.
+#
+CREATE TABLE IF NOT EXISTS t1 (
+f1 bit(2) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
+INSERT INTO t1 VALUES (b'');
+SELECT bin(f1) FROM t1;
+bin(f1)
+0
+DROP TABLE t1;

=== modified file 'mysql-test/r/variables-big.result'
--- a/mysql-test/r/variables-big.result	2011-05-24 12:05:57 +0000
+++ b/mysql-test/r/variables-big.result	2012-05-07 16:11:47 +0000
@@ -2,21 +2,21 @@ SET @def_var= @@session.transaction_prea
 SET SESSION transaction_prealloc_size=1024*1024*1024*1;
 SHOW PROCESSLIST;
 Id	User	Host	db	Command	Time	State	Info
-<Id>	root	<Host>	test	Query	<Time>	init	SHOW PROCESSLIST
+<Id>	root	<Host>	test	Query	<Time>	<State>	SHOW PROCESSLIST
 SET SESSION transaction_prealloc_size=1024*1024*1024*2;
 SHOW PROCESSLIST;
 Id	User	Host	db	Command	Time	State	Info
-<Id>	root	<Host>	test	Query	<Time>	init	SHOW PROCESSLIST
+<Id>	root	<Host>	test	Query	<Time>	<State>	SHOW PROCESSLIST
 SET SESSION transaction_prealloc_size=1024*1024*1024*3;
 SHOW PROCESSLIST;
 Id	User	Host	db	Command	Time	State	Info
-<Id>	root	<Host>	test	Query	<Time>	init	SHOW PROCESSLIST
+<Id>	root	<Host>	test	Query	<Time>	<State>	SHOW PROCESSLIST
 SET SESSION transaction_prealloc_size=1024*1024*1024*4;
 SHOW PROCESSLIST;
 Id	User	Host	db	Command	Time	State	Info
-<Id>	root	<Host>	test	Query	<Time>	init	SHOW PROCESSLIST
+<Id>	root	<Host>	test	Query	<Time>	<State>	SHOW PROCESSLIST
 SET SESSION transaction_prealloc_size=1024*1024*1024*5;
 SHOW PROCESSLIST;
 Id	User	Host	db	Command	Time	State	Info
-<Id>	root	<Host>	test	Query	<Time>	init	SHOW PROCESSLIST
+<Id>	root	<Host>	test	Query	<Time>	<State>	SHOW PROCESSLIST
 SET @@session.transaction_prealloc_size= @def_var;

=== modified file 'mysql-test/suite/rpl/r/rpl_extra_col_master_innodb.result'
--- a/mysql-test/suite/rpl/r/rpl_extra_col_master_innodb.result	2012-03-23 20:11:19 +0000
+++ b/mysql-test/suite/rpl/r/rpl_extra_col_master_innodb.result	2012-05-07 08:29:18 +0000
@@ -99,13 +99,11 @@ f5 DOUBLE DEFAULT '2.00',
 f6 ENUM('a', 'b', 'c') default 'a',
 f7 DECIMAL(17,9) default '1000.00',
 f8 MEDIUMBLOB,
-f9 NUMERIC(6,4) default '2000.00',
+f9 NUMERIC(6,2) default '2000.00',
 f10 VARCHAR(1024),
 f11 BINARY(20) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
 f12 SET('a', 'b', 'c') default 'b')
 ENGINE='InnoDB';
-Warnings:
-Warning	1264	Out of range value for column 'f9' at row 1
 
 CREATE TABLE t3 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20),
 /* extra */
@@ -122,13 +120,11 @@ CREATE TABLE t4 (f1 INT, f2 INT, f3 INT
 f5 DOUBLE DEFAULT '2.00', 
 f6 DECIMAL(17,9) default '1000.00',
 f7 MEDIUMBLOB,
-f8 NUMERIC(6,4) default '2000.00',
+f8 NUMERIC(6,2) default '2000.00',
 f9 VARCHAR(1024),
 f10 BINARY(20) not null default '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
 f11 CHAR(255))
 ENGINE='InnoDB';
-Warnings:
-Warning	1264	Out of range value for column 'f8' at row 1
 
 CREATE TABLE t31 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20),
 /* extra */
@@ -187,9 +183,6 @@ INSERT into t2 values (2, 2, 2, 'second'
 (3, 3, 3, 'third',
 3.0, 'b', 3000.0003, 'f8: medium size blob', 3000, 'f10: some var char',
 '01234567', 'c');
-Warnings:
-Warning	1264	Out of range value for column 'f9' at row 1
-Warning	1264	Out of range value for column 'f9' at row 2
 INSERT into t3 set f1=1, f2=1, f3=1, f4='first', f10='f10: some var char';
 INSERT into t4 set f1=1, f2=1, f3=1, f4='first', f7='f7: medium size blob', f10='f10:
 binary data';

=== modified file 'mysql-test/suite/rpl/r/rpl_extra_col_master_myisam.result'
--- a/mysql-test/suite/rpl/r/rpl_extra_col_master_myisam.result	2012-03-23 20:11:19 +0000
+++ b/mysql-test/suite/rpl/r/rpl_extra_col_master_myisam.result	2012-05-07 08:29:18 +0000
@@ -99,13 +99,11 @@ f5 DOUBLE DEFAULT '2.00',
 f6 ENUM('a', 'b', 'c') default 'a',
 f7 DECIMAL(17,9) default '1000.00',
 f8 MEDIUMBLOB,
-f9 NUMERIC(6,4) default '2000.00',
+f9 NUMERIC(6,2) default '2000.00',
 f10 VARCHAR(1024),
 f11 BINARY(20) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
 f12 SET('a', 'b', 'c') default 'b')
 ENGINE='MyISAM';
-Warnings:
-Warning	1264	Out of range value for column 'f9' at row 1
 
 CREATE TABLE t3 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20),
 /* extra */
@@ -122,13 +120,11 @@ CREATE TABLE t4 (f1 INT, f2 INT, f3 INT
 f5 DOUBLE DEFAULT '2.00', 
 f6 DECIMAL(17,9) default '1000.00',
 f7 MEDIUMBLOB,
-f8 NUMERIC(6,4) default '2000.00',
+f8 NUMERIC(6,2) default '2000.00',
 f9 VARCHAR(1024),
 f10 BINARY(20) not null default '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
 f11 CHAR(255))
 ENGINE='MyISAM';
-Warnings:
-Warning	1264	Out of range value for column 'f8' at row 1
 
 CREATE TABLE t31 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20),
 /* extra */
@@ -187,9 +183,6 @@ INSERT into t2 values (2, 2, 2, 'second'
 (3, 3, 3, 'third',
 3.0, 'b', 3000.0003, 'f8: medium size blob', 3000, 'f10: some var char',
 '01234567', 'c');
-Warnings:
-Warning	1264	Out of range value for column 'f9' at row 1
-Warning	1264	Out of range value for column 'f9' at row 2
 INSERT into t3 set f1=1, f2=1, f3=1, f4='first', f10='f10: some var char';
 INSERT into t4 set f1=1, f2=1, f3=1, f4='first', f7='f7: medium size blob', f10='f10:
 binary data';

=== modified file 'mysql-test/suite/rpl/r/rpl_gtid_sql_until_before_after.result'
--- a/mysql-test/suite/rpl/r/rpl_gtid_sql_until_before_after.result	2012-03-29 17:53:11 +0000
+++ b/mysql-test/suite/rpl/r/rpl_gtid_sql_until_before_after.result	2012-05-08 17:11:38 +0000
@@ -18,15 +18,30 @@ INSERT INTO t1 VALUES(8);
 INSERT INTO t1 VALUES(9);
 INSERT INTO t1 VALUES(10);
 [connection slave]
+START SLAVE UNTIL SQL_BEFORE_GTIDS= "MASTER_UUID:4-5", MASTER_LOG_FILE= 'foo.bin', MASTER_LOG_POS= 100;
+ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL
+START SLAVE SQL_THREAD UNTIL SQL_BEFORE_GTIDS= "MASTER_UUID:4-5", MASTER_LOG_FILE= 'foo.bin', MASTER_LOG_POS= 100;
+ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL
+START SLAVE IO_THREAD UNTIL SQL_BEFORE_GTIDS= "MASTER_UUID:4-5", MASTER_LOG_FILE= 'foo.bin', MASTER_LOG_POS= 100;
+ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL
+START SLAVE FOO UNTIL SQL_BEFORE_GTIDS= "MASTER_UUID:4-5";
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FOO UNTIL SQL_BEFORE_GTIDS= "MASTER_UUID:4-5"' at line 1
+Check that START SLAVE IO_THREAD UNTIL ... maintains old behaviour, condition is ignored.
+START SLAVE IO_THREAD UNTIL SQL_BEFORE_GTIDS= "MASTER_UUID:4-5";
+Warnings:
+Note	1279	SQL thread is not to be started so UNTIL options are ignored
+Wait until IO Thread reads all master binlog and stop slave.
+include/wait_for_slave_param.inc [Retrieved_Gtid_Set]
+include/stop_slave_io.inc
 SQL thread must stop *before* INSERT 4
-START SLAVE UNTIL SQL_BEFORE_GTIDS= "MASTER_UUID:4-5";
+START SLAVE SQL_THREAD UNTIL SQL_BEFORE_GTIDS= "MASTER_UUID:4-5";
 include/wait_for_slave_sql_to_stop.inc
 SELECT * FROM t1;
 c1
 2
 3
 SQL thread must stop *after* INSERT 5
-START SLAVE UNTIL SQL_AFTER_GTIDS= "MASTER_UUID:4-5";
+START SLAVE SQL_THREAD UNTIL SQL_AFTER_GTIDS= "MASTER_UUID:4-5";
 include/wait_for_slave_sql_to_stop.inc
 SELECT * FROM t1;
 c1
@@ -35,7 +50,7 @@ c1
 4
 5
 SQL thread must stop *before* INSERT 6
-START SLAVE UNTIL SQL_BEFORE_GTIDS= "MASTER_UUID:2-7";
+START SLAVE SQL_THREAD, IO_THREAD UNTIL SQL_BEFORE_GTIDS= "MASTER_UUID:2-7";
 include/wait_for_slave_sql_to_stop.inc
 SELECT * FROM t1;
 c1
@@ -45,7 +60,7 @@ c1
 5
 SQL thread must stop *after* INSERT 5
 1-5 are already applied so it will stop immediately
-START SLAVE UNTIL SQL_AFTER_GTIDS= "MASTER_UUID:1-5";
+START SLAVE SQL_THREAD, IO_THREAD UNTIL SQL_AFTER_GTIDS= "MASTER_UUID:1-5";
 include/wait_for_slave_sql_to_stop.inc
 SELECT * FROM t1;
 c1
@@ -95,7 +110,7 @@ c1
 8
 9
 Sync slave with master
-include/start_slave_sql.inc
+include/start_slave.inc
 SELECT SQL_THREAD_WAIT_AFTER_GTIDS('MASTER_UUID:10', 300);
 SELECT * FROM t1;
 c1

=== modified file 'mysql-test/suite/rpl/t/rpl_gtid_sql_until_before_after.test'
--- a/mysql-test/suite/rpl/t/rpl_gtid_sql_until_before_after.test	2012-03-27 08:43:25 +0000
+++ b/mysql-test/suite/rpl/t/rpl_gtid_sql_until_before_after.test	2012-05-08 17:11:38 +0000
@@ -32,11 +32,53 @@ while ($i != 11)
 
 --connection slave
 --echo [connection slave]
+
+# Incorrect START SLAVE UNTIL SQL_BEFORE_GTIDS
+--disable_query_log
+--replace_result $master_uuid MASTER_UUID
+--enable_query_log
+--error ER_BAD_SLAVE_UNTIL_COND
+--eval START SLAVE UNTIL SQL_BEFORE_GTIDS= "$master_uuid:4-5", MASTER_LOG_FILE= 'foo.bin', MASTER_LOG_POS= 100
+
+# Incorrect START SLAVE UNTIL SQL_BEFORE_GTIDS
+--disable_query_log
+--replace_result $master_uuid MASTER_UUID
+--enable_query_log
+--error ER_BAD_SLAVE_UNTIL_COND
+--eval START SLAVE SQL_THREAD UNTIL SQL_BEFORE_GTIDS= "$master_uuid:4-5", MASTER_LOG_FILE= 'foo.bin', MASTER_LOG_POS= 100
+
+# Incorrect START SLAVE UNTIL SQL_BEFORE_GTIDS
+--disable_query_log
+--replace_result $master_uuid MASTER_UUID
+--enable_query_log
+--error ER_BAD_SLAVE_UNTIL_COND
+--eval START SLAVE IO_THREAD UNTIL SQL_BEFORE_GTIDS= "$master_uuid:4-5", MASTER_LOG_FILE= 'foo.bin', MASTER_LOG_POS= 100
+
+# Incorrect START SLAVE UNTIL SQL_BEFORE_GTIDS
+--disable_query_log
+--replace_result $master_uuid MASTER_UUID
+--enable_query_log
+--error ER_PARSE_ERROR
+--eval START SLAVE FOO UNTIL SQL_BEFORE_GTIDS= "$master_uuid:4-5"
+
+# UNTIL GTID
+--echo Check that START SLAVE IO_THREAD UNTIL ... maintains old behaviour, condition is ignored.
+--disable_query_log
+--replace_result $master_uuid MASTER_UUID
+--enable_query_log
+--eval START SLAVE IO_THREAD UNTIL SQL_BEFORE_GTIDS= "$master_uuid:4-5"
+
+--echo Wait until IO Thread reads all master binlog and stop slave.
+--let $slave_param= Retrieved_Gtid_Set
+--let $slave_param_value= $master_uuid:1-10
+--source include/wait_for_slave_param.inc
+--source include/stop_slave_io.inc
+
 --echo SQL thread must stop *before* INSERT 4
 --disable_query_log
 --replace_result $master_uuid MASTER_UUID
 --enable_query_log
---eval START SLAVE UNTIL SQL_BEFORE_GTIDS= "$master_uuid:4-5"
+--eval START SLAVE SQL_THREAD UNTIL SQL_BEFORE_GTIDS= "$master_uuid:4-5"
 --source include/wait_for_slave_sql_to_stop.inc
 SELECT * FROM t1;
 
@@ -44,7 +86,7 @@ SELECT * FROM t1;
 --disable_query_log
 --replace_result $master_uuid MASTER_UUID
 --enable_query_log
---eval START SLAVE UNTIL SQL_AFTER_GTIDS= "$master_uuid:4-5"
+--eval START SLAVE SQL_THREAD UNTIL SQL_AFTER_GTIDS= "$master_uuid:4-5"
 --source include/wait_for_slave_sql_to_stop.inc
 SELECT * FROM t1;
 
@@ -52,7 +94,7 @@ SELECT * FROM t1;
 --disable_query_log
 --replace_result $master_uuid MASTER_UUID
 --enable_query_log
---eval START SLAVE UNTIL SQL_BEFORE_GTIDS= "$master_uuid:2-7"
+--eval START SLAVE SQL_THREAD, IO_THREAD UNTIL SQL_BEFORE_GTIDS= "$master_uuid:2-7"
 --source include/wait_for_slave_sql_to_stop.inc
 SELECT * FROM t1;
 
@@ -61,7 +103,7 @@ SELECT * FROM t1;
 --disable_query_log
 --replace_result $master_uuid MASTER_UUID
 --enable_query_log
---eval START SLAVE UNTIL SQL_AFTER_GTIDS= "$master_uuid:1-5"
+--eval START SLAVE SQL_THREAD, IO_THREAD UNTIL SQL_AFTER_GTIDS= "$master_uuid:1-5"
 --source include/wait_for_slave_sql_to_stop.inc
 SELECT * FROM t1;
 
@@ -92,7 +134,7 @@ SELECT * FROM t1;
 SELECT * FROM t1;
 
 --echo Sync slave with master
---source include/start_slave_sql.inc
+--source include/start_slave.inc
 --disable_query_log
 --replace_result $master_uuid MASTER_UUID
 --enable_query_log

=== modified file 'mysql-test/suite/rpl/t/rpl_stm_mts_crash_safe.test'
--- a/mysql-test/suite/rpl/t/rpl_stm_mts_crash_safe.test	2012-03-23 11:48:18 +0000
+++ b/mysql-test/suite/rpl/t/rpl_stm_mts_crash_safe.test	2012-05-08 19:53:29 +0000
@@ -1,6 +1,11 @@
---source include/big_test.inc
+#
+# Temprorarily made as regular to catch a failure
+# visible on weekly runs.
+# todo: restore
+#--source include/big_test.inc
+#
 --source include/master-slave.inc
---source include/have_binlog_format_statement.inc
+--source include/have_binlog_format_mixed_or_statement.inc
 --source include/have_innodb.inc
 --source include/have_debug.inc
 --source include/not_valgrind.inc

=== modified file 'mysql-test/t/ctype_ucs.test'
--- a/mysql-test/t/ctype_ucs.test	2012-03-20 05:51:52 +0000
+++ b/mysql-test/t/ctype_ucs.test	2012-05-07 08:29:18 +0000
@@ -788,5 +788,20 @@ DO IFNULL(CHAR(NULL USING ucs2), '');
 DO CAST(CONVERT('' USING ucs2) AS UNSIGNED);
 
 --echo #
+--echo # Test error message for conversion using different charset
+--echo # 
+
+CREATE TABLE t1 (a DECIMAL(2,0));
+
+SET sql_mode='strict_all_tables';
+--error ER_TRUNCATED_WRONG_VALUE_FOR_FIELD
+INSERT INTO t1 VALUES (CONVERT('9e99999999' USING ucs2));
+SET sql_mode=DEFAULT;
+
+INSERT INTO t1 VALUES (CONVERT('aaa' USING ucs2)); 
+
+DROP TABLE t1;
+
+--echo #
 --echo # End of 5.6 tests
 --echo #

=== modified file 'mysql-test/t/events_time_zone.test'
--- a/mysql-test/t/events_time_zone.test	2008-11-14 16:18:20 +0000
+++ b/mysql-test/t/events_time_zone.test	2012-05-07 10:07:20 +0000
@@ -37,7 +37,9 @@ let $N = 5;
 #
 
 --source include/big_test.inc
-
+#Event scheduler is not available at all when the embedded server is used
+#So this test has to include "not_embedded.inc", like all other tests for the event scheduler
+--source include/not_embedded.inc
 
 --disable_warnings
 DROP DATABASE IF EXISTS mysqltest_db1;

=== modified file 'mysql-test/t/mysqldump.test'
--- a/mysql-test/t/mysqldump.test	2012-03-06 14:29:42 +0000
+++ b/mysql-test/t/mysqldump.test	2012-05-08 09:59:59 +0000
@@ -2426,5 +2426,29 @@ DROP DATABASE b12688860_db;
 # Wait till we reached the initial number of concurrent sessions
 --source include/wait_until_count_sessions.inc
 
---echo
---echo End of tests
+--echo #
+--echo # Bug#45740 MYSQLDUMP DOESN'T DUMP GENERAL_LOG AND SLOW_QUERY CAUSES RESTORE PROBLEM
+--echo #
+SET @old_log_output_state=       @@global.log_output;
+SET @old_general_log_state=      @@global.general_log;
+SET @old_slow_query_log_state=   @@global.slow_query_log;
+
+call mtr.add_suppression("Failed to write to mysql.general_log");
+--exec $MYSQL_DUMP -uroot --all-databases > $MYSQLTEST_VARDIR/tmp/bug45740.sql
+# Make log_output as table and disabling general_log and slow_log
+SET @@global.log_output="TABLE";
+SET @@global.general_log='OFF';
+SET @@global.slow_query_log='OFF';
+DROP DATABASE mysql; 
+--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug45740.sql
+SHOW CREATE TABLE mysql.general_log;
+SHOW CREATE TABLE mysql.slow_log;
+--remove_file $MYSQLTEST_VARDIR/tmp/bug45740.sql
+
+SET @@global.log_output=       @old_log_output_state;
+SET @@global.slow_query_log=   @old_slow_query_log_state;
+SET @@global.general_log=      @old_general_log_state;
+ 
+--echo #
+--echo # End of 5.1 tests
+--echo #

=== modified file 'mysql-test/t/type_bit.test'
--- a/mysql-test/t/type_bit.test	2010-02-16 09:13:49 +0000
+++ b/mysql-test/t/type_bit.test	2012-05-07 08:29:18 +0000
@@ -360,6 +360,14 @@ f1 bit(2) NOT NULL default b'10',
 f2 bit(14) NOT NULL default b'11110000111100'
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
 SHOW CREATE TABLE t1;
+
+# Should store the defaults
+INSERT INTO t1 (f1) VALUES (DEFAULT);
+# Should store 0's, not the default
+INSERT INTO t1 VALUES (b'', b''); 
+
+SELECT HEX(f1), HEX(f2) FROM t1;
+
 DROP TABLE t1;
 
 --error ER_INVALID_DEFAULT
@@ -439,3 +447,15 @@ SELECT SUM(a) FROM t1 GROUP BY c, b, a;
 DROP TABLE t1;
 
 --echo End of 5.1 tests
+
+--echo #
+--echo # Test insert of no bits. Should be treated as 0.
+--echo #
+
+CREATE TABLE IF NOT EXISTS t1 (
+f1 bit(2) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
+INSERT INTO t1 VALUES (b'');
+SELECT bin(f1) FROM t1;
+DROP TABLE t1;
+

=== modified file 'mysql-test/t/variables-big.test'
--- a/mysql-test/t/variables-big.test	2011-05-24 12:05:57 +0000
+++ b/mysql-test/t/variables-big.test	2012-05-07 16:11:47 +0000
@@ -38,19 +38,19 @@ SET @def_var= @@session.transaction_prea
 
 --disable_warnings
 SET SESSION transaction_prealloc_size=1024*1024*1024*1;
---replace_column 1 <Id> 3 <Host> 6 <Time>
+--replace_column 1 <Id> 3 <Host> 6 <Time> 7 <State>
 SHOW PROCESSLIST;
 SET SESSION transaction_prealloc_size=1024*1024*1024*2;
---replace_column 1 <Id> 3 <Host> 6 <Time>
+--replace_column 1 <Id> 3 <Host> 6 <Time> 7 <State>
 SHOW PROCESSLIST;
 SET SESSION transaction_prealloc_size=1024*1024*1024*3;
---replace_column 1 <Id> 3 <Host> 6 <Time>
+--replace_column 1 <Id> 3 <Host> 6 <Time> 7 <State>
 SHOW PROCESSLIST;
 SET SESSION transaction_prealloc_size=1024*1024*1024*4;
---replace_column 1 <Id> 3 <Host> 6 <Time>
+--replace_column 1 <Id> 3 <Host> 6 <Time> 7 <State>
 SHOW PROCESSLIST;
 SET SESSION transaction_prealloc_size=1024*1024*1024*5;
---replace_column 1 <Id> 3 <Host> 6 <Time>
+--replace_column 1 <Id> 3 <Host> 6 <Time> 7 <State>
 SHOW PROCESSLIST;
 --enable_warnings
 

=== modified file 'sql-common/my_time.c'
--- a/sql-common/my_time.c	2012-04-30 12:42:56 +0000
+++ b/sql-common/my_time.c	2012-05-07 08:29:18 +0000
@@ -824,11 +824,14 @@ fractional:
 }
 
 
-/*
-  Convert numer to TIME
+/**
+  Convert number to TIME
   @param nr            Number to convert.
   @param OUT ltime     Variable to convert to.
   @param OUT warnings  Warning vector.
+
+  @retval false OK
+  @retval true No. is out of range
 */
 my_bool
 number_to_time(longlong nr, MYSQL_TIME *ltime, int *warnings)
@@ -1385,6 +1388,12 @@ int my_timeval_to_str(const struct timev
     -1              Timestamp with wrong values
     anything else   DATETIME as integer in YYYYMMDDHHMMSS format
     Datetime value in YYYYMMDDHHMMSS format.
+
+    was_cut         if return value -1: one of
+                      - MYSQL_TIME_WARN_OUT_OF_RANGE
+                      - MYSQL_TIME_WARN_ZERO_DATE
+                      - MYSQL_TIME_WARN_TRUNCATED
+                    otherwise 0.
 */
 
 longlong number_to_datetime(longlong nr, MYSQL_TIME *time_res,
@@ -1466,7 +1475,7 @@ longlong number_to_datetime(longlong nr,
     return LL(-1);
 
  err:
-  *was_cut= 1;
+  *was_cut= MYSQL_TIME_WARN_TRUNCATED;
   return LL(-1);
 }
 

=== modified file 'sql/field.cc'
--- a/sql/field.cc	2012-04-27 11:57:38 +0000
+++ b/sql/field.cc	2012-05-07 08:29:18 +0000
@@ -1,5 +1,5 @@
 /*
-   Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+   Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -1072,6 +1072,46 @@ static void push_numerical_conversion_wa
 
 
 /**
+  Emits a warning for the decimal conversion error. May modify
+  dec_value if there was conversion overflow or bad number.
+
+
+  @param dec_error         decimal library return code
+                           (E_DEC_* see include/decimal.h)
+  @param dec_value[in,out] Decimal value returned by convertion function.
+  @param from              Value converted from
+  @param length            Length of 'from'
+  @param charset_arg       Charset of 'from'
+*/
+static void set_decimal_warning(Field_new_decimal *field,
+                                int dec_error,
+                                my_decimal *dec_value,
+                                const char *from,
+                                uint length,
+                                const CHARSET_INFO *charset_arg)
+{
+  switch (dec_error) {
+  case E_DEC_TRUNCATED:
+    field->set_warning(Sql_condition::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
+    break;
+  case E_DEC_OVERFLOW:
+    field->set_warning(Sql_condition::WARN_LEVEL_WARN,
+                       ER_WARN_DATA_OUT_OF_RANGE, 1);
+    field->set_value_on_overflow(dec_value, dec_value->sign());
+    break;
+  case E_DEC_BAD_NUM:
+    ErrConvString errmsg(from, length, charset_arg);
+    const Diagnostics_area *da= field->table->in_use->get_stmt_da();
+    push_warning_printf(field->table->in_use, Sql_condition::WARN_LEVEL_WARN,
+                        ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
+                        ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
+                        "decimal", errmsg.ptr(), field->field_name,
+                        static_cast<ulong>(da->current_row_for_warning()));
+    my_decimal_set_zero(dec_value);
+  }
+}
+
+/**
   Check whether a field type can be partially indexed by a key.
 
   This is a static method, rather than a virtual function, because we need
@@ -1149,16 +1189,12 @@ void Field_num::prepend_zeros(String *va
   @note
     This is called after one has called strntoull10rnd() function.
 
-  @retval
-    0	OK
-  @retval
-    1	error: empty string or wrong integer.
-  @retval
-    2   error: garbage at the end of string.
+  @return TYPE_OK, TYPE_ERR_BAD_VALUE or TYPE_WARN_TRUNCATED
 */
 
-int Field_num::check_int(const CHARSET_INFO *cs, const char *str, int length, 
-                         const char *int_end, int error)
+type_conversion_status
+Field_num::check_int(const CHARSET_INFO *cs, const char *str, int length,
+                     const char *int_end, int error)
 {
   /* Test if we get an empty string or wrong integer */
   if (str == int_end || error == MY_ERRNO_EDOM)
@@ -1170,15 +1206,15 @@ int Field_num::check_int(const CHARSET_I
                         "integer", err.ptr(), field_name,
                         (ulong) table->in_use->get_stmt_da()->
                         current_row_for_warning());
-    return 1;
+    return TYPE_ERR_BAD_VALUE;
   }
   /* Test if we have garbage at the end of the given string. */
   if (test_if_important_data(cs, int_end, str + length))
   {
     set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
-    return 2;
+    return TYPE_WARN_TRUNCATED;
   }
-  return 0;
+  return TYPE_OK;
 }
 
 
@@ -1200,29 +1236,27 @@ int Field_num::check_int(const CHARSET_I
     check bounds and errors returned. In case of any error a warning
     is raised.
 
-  RETURN
-    0   ok
-    1   error
+  @return TYPE_OK, TYPE_WARN_OUT_OF_RANGE, TYPE_ERR_BAD_VALUE or 
+          TYPE_WARN_TRUNCATED
 */
 
-bool Field_num::get_int(const CHARSET_INFO *cs, const char *from, uint len,
-                        longlong *rnd, ulonglong unsigned_max, 
-                        longlong signed_min, longlong signed_max)
+type_conversion_status
+Field_num::get_int(const CHARSET_INFO *cs, const char *from, uint len,
+                   longlong *rnd, ulonglong unsigned_max,
+                   longlong signed_min, longlong signed_max)
 {
   char *end;
   int error;
-  
+
   *rnd= (longlong) cs->cset->strntoull10rnd(cs, from, len,
                                             unsigned_flag, &end,
                                             &error);
   if (unsigned_flag)
   {
-
-    if ((((ulonglong) *rnd > unsigned_max) && (*rnd= (longlong) unsigned_max)) ||
+    if ((((ulonglong) *rnd > unsigned_max) &&
+         (*rnd= (longlong) unsigned_max)) ||
         error == MY_ERRNO_ERANGE)
-    {
       goto out_of_range;
-    }
   }
   else
   {
@@ -1237,14 +1271,14 @@ bool Field_num::get_int(const CHARSET_IN
       goto out_of_range;
     }
   }
-  if (table->in_use->count_cuted_fields &&
-      check_int(cs, from, len, end, error))
-    return 1;
-  return 0;
+  if (table->in_use->count_cuted_fields != 0)
+    return check_int(cs, from, len, end, error);
+
+  return TYPE_OK;
 
 out_of_range:
   set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-  return 1;
+  return TYPE_WARN_OUT_OF_RANGE;
 }
 
 
@@ -1256,7 +1290,7 @@ out_of_range:
   Field_real (common parent for Field_decimal, Field_float, Field_double),
   Field_new_decimal, Field_year.
 */
-int
+type_conversion_status
 Field_num::store_time(MYSQL_TIME *ltime,
                       uint8 dec_arg __attribute__((unused)))
 {
@@ -1271,25 +1305,23 @@ Field_num::store_time(MYSQL_TIME *ltime,
 
   @param op_result  decimal library return code (E_DEC_* see include/decimal.h)
 
-  @retval
-    1  there was overflow
-  @retval
-    0  no error or some other errors except overflow
+  @retval 0 No error or some other errors except overflow
+  @retval 1 There was overflow
 */
 
-int Field::warn_if_overflow(int op_result)
+bool Field::warn_if_overflow(int op_result)
 {
   if (op_result == E_DEC_OVERFLOW)
   {
     set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-    return 1;
+    return true;
   }
   if (op_result == E_DEC_TRUNCATED)
   {
     set_warning(Sql_condition::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
     /* We return 0 here as this is not a critical issue */
   }
-  return 0;
+  return false;
 }
 
 
@@ -1427,13 +1459,13 @@ bool Field::compatible_field_size(uint f
 }
 
 
-int Field::store(const char *to, uint length, const CHARSET_INFO *cs,
-                 enum_check_fields check_level)
+type_conversion_status
+Field::store(const char *to, uint length, const CHARSET_INFO *cs,
+             enum_check_fields check_level)
 {
-  int res;
   enum_check_fields old_check_level= table->in_use->count_cuted_fields;
   table->in_use->count_cuted_fields= check_level;
-  res= store(to, length, cs);
+  const type_conversion_status res= store(to, length, cs);
   table->in_use->count_cuted_fields= old_check_level;
   return res;
 }
@@ -1591,44 +1623,43 @@ void Field::make_field(Send_field *field
 
 
 /**
-  Conversion from decimal to longlong with checking overflow and
-  setting correct value (min/max) in case of overflow.
+  Conversion from decimal to longlong. Checks overflow and returns
+  correct value (min/max) in case of overflow.
 
-  @param val             value which have to be converted
-  @param unsigned_flag   type of integer in which we convert val
-  @param err             variable to pass error code
+  @param val             value to be converted
+  @param unsigned_flag   type of integer to which we convert val
+  @param has_overflow    true if there is overflow
 
   @return
     value converted from val
 */
 longlong Field::convert_decimal2longlong(const my_decimal *val,
-                                         bool unsigned_flag, int *err)
+                                         bool unsigned_flag,
+                                         bool *has_overflow)
 {
-  longlong i;
-  if (unsigned_flag)
+  if (unsigned_flag && val->sign())
   {
-    if (val->sign())
-    {
-      set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      i= 0;
-      *err= 1;
-    }
-    else if (warn_if_overflow(my_decimal2int(E_DEC_ERROR &
-                                           ~E_DEC_OVERFLOW & ~E_DEC_TRUNCATED,
-                                           val, TRUE, &i)))
-    {
-      i= ~(longlong) 0;
-      *err= 1;
-    }
+    // Converting a signed decimal to unsigned int
+    set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+    *has_overflow= true;
+    return 0;
   }
-  else if (warn_if_overflow(my_decimal2int(E_DEC_ERROR &
-                                         ~E_DEC_OVERFLOW & ~E_DEC_TRUNCATED,
-                                         val, FALSE, &i)))
+
+  longlong val_ll;
+  int conversion_error= my_decimal2int(E_DEC_ERROR & ~E_DEC_OVERFLOW
+                                                   & ~E_DEC_TRUNCATED,
+                                       val, unsigned_flag, &val_ll);
+
+  if (warn_if_overflow(conversion_error))
   {
-    i= (val->sign() ? LONGLONG_MIN : LONGLONG_MAX);
-    *err= 1;
+    *has_overflow= true;
+    if (unsigned_flag)
+      return ULONGLONG_MAX;
+
+    return (val->sign() ? LONGLONG_MIN : LONGLONG_MAX);
   }
-  return i;
+
+  return val_ll;
 }
 
 
@@ -1640,18 +1671,17 @@ longlong Field::convert_decimal2longlong
   @note
     This method is used by all integer fields, real/decimal redefine it
 
-  @retval
-    0     OK
-  @retval
-    !=0  error
+  @retval TYPE_OK   Storage of value went fine without warnings or errors
+  @retval !TYPE_OK  Warning/error as indicated by type_conversion_status enum
+                    value
 */
-
-int Field_num::store_decimal(const my_decimal *val)
+type_conversion_status Field_num::store_decimal(const my_decimal *val)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int err= 0;
-  longlong i= convert_decimal2longlong(val, unsigned_flag, &err);
-  return test(err | store(i, unsigned_flag));
+  bool has_overflow= false;
+  longlong i= convert_decimal2longlong(val, unsigned_flag, &has_overflow);
+  const type_conversion_status res= store(i, unsigned_flag);
+  return has_overflow ? TYPE_WARN_OUT_OF_RANGE : res;
 }
 
 
@@ -1733,14 +1763,16 @@ void Field_str::make_field(Send_field *f
     !=0  error
 */
 
-int Field_str::store_decimal(const my_decimal *d)
+type_conversion_status Field_str::store_decimal(const my_decimal *d)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   double val;
   /* TODO: use decimal2string? */
-  int err= warn_if_overflow(my_decimal2double(E_DEC_FATAL_ERROR &
-                                            ~E_DEC_OVERFLOW, d, &val));
-  return err | store(val);
+  int err= my_decimal2double(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, d, &val);
+  warn_if_overflow(err);
+  const type_conversion_status res= store(val);
+
+  return (err != E_DEC_OK) ? decimal_err_to_type_conv_status(err) : res;
 }
 
 
@@ -1811,7 +1843,7 @@ bool Field::get_timestamp(struct timeval
     Needs to be changed if/when we want to support different time formats.
 */
 
-int Field::store_time(MYSQL_TIME *ltime, uint8 dec_arg)
+type_conversion_status Field::store_time(MYSQL_TIME *ltime, uint8 dec_arg)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   char buff[MAX_DATE_STRING_REP_LENGTH];
@@ -1897,11 +1929,10 @@ void Field_null::sql_type(String &res) c
   This is an number stored as a pre-space (or pre-zero) string
 ****************************************************************************/
 
-int
-Field_decimal::reset(void)
+type_conversion_status Field_decimal::reset(void)
 {
   Field_decimal::store(STRING_WITH_LEN("0"),&my_charset_bin);
-  return 0;
+  return TYPE_OK;
 }
 
 void Field_decimal::overflow(bool negative)
@@ -1943,8 +1974,8 @@ void Field_decimal::overflow(bool negati
 }
 
 
-int Field_decimal::store(const char *from_arg, uint len,
-                         const CHARSET_INFO *cs)
+type_conversion_status Field_decimal::store(const char *from_arg, uint len,
+                                            const CHARSET_INFO *cs)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   char buff[STRING_BUFFER_USUAL_SIZE];
@@ -2034,7 +2065,7 @@ int Field_decimal::store(const char *fro
       if (sign_char=='-')
       {
         Field_decimal::overflow(1);
-        return 1;
+        return TYPE_WARN_OUT_OF_RANGE;
       }
       /* 
 	 Defining this will not store "+" for unsigned decimal type even if
@@ -2179,7 +2210,7 @@ int Field_decimal::store(const char *fro
   {
     // too big number, change to max or min number
     Field_decimal::overflow(sign_char == '-');
-    return 1;
+    return TYPE_WARN_OUT_OF_RANGE;
   }
  
   /*
@@ -2260,7 +2291,7 @@ int Field_decimal::store(const char *fro
       {
         if (table->in_use->count_cuted_fields && !is_cuted_fields_incr) 
           break; // Go on below to see if we lose non zero digits
-        return 0;
+        return TYPE_OK;
       }
       *pos++='0';
     }
@@ -2274,7 +2305,7 @@ int Field_decimal::store(const char *fro
           if (!is_cuted_fields_incr)
             set_warning(Sql_condition::WARN_LEVEL_WARN, 
                         WARN_DATA_TRUNCATED, 1);
-          return 0;
+          return TYPE_OK;
         }
         continue;
       }
@@ -2297,7 +2328,7 @@ int Field_decimal::store(const char *fro
           */
 	  set_warning(Sql_condition::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
         }
-        return 0;
+        return TYPE_OK;
       }
       continue;
     }
@@ -2306,23 +2337,23 @@ int Field_decimal::store(const char *fro
       
   while (pos != right_wall)
    *pos++='0';			// Fill with zeros at right of '.'
-  return 0;
+  return TYPE_OK;
 }
 
 
-int Field_decimal::store(double nr)
+type_conversion_status Field_decimal::store(double nr)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   if (unsigned_flag && nr < 0)
   {
     overflow(1);
-    return 1;
+    return TYPE_WARN_OUT_OF_RANGE;
   }
   
   if (!isfinite(nr)) // Handle infinity as special case
   {
     overflow(nr < 0.0);
-    return 1;
+    return TYPE_WARN_OUT_OF_RANGE;
   }
 
   reg4 uint i;
@@ -2336,7 +2367,7 @@ int Field_decimal::store(double nr)
   if (length > field_length)
   {
     overflow(nr < 0.0);
-    return 1;
+    return TYPE_WARN_OUT_OF_RANGE;
   }
   else
   {
@@ -2344,12 +2375,12 @@ int Field_decimal::store(double nr)
     for (i=field_length-length ; i-- > 0 ;)
       *to++ = fyllchar;
     memcpy(to,buff,length);
-    return 0;
+    return TYPE_OK;
   }
 }
 
 
-int Field_decimal::store(longlong nr, bool unsigned_val)
+type_conversion_status Field_decimal::store(longlong nr, bool unsigned_val)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   char buff[22];
@@ -2360,7 +2391,7 @@ int Field_decimal::store(longlong nr, bo
   if (nr < 0 && unsigned_flag && !unsigned_val)
   {
     overflow(1);
-    return 1;
+    return TYPE_WARN_OUT_OF_RANGE;
   }
   length= (uint) (longlong10_to_str(nr,buff,unsigned_val ? 10 : -10) - buff);
   int_part= field_length- (dec  ? dec+1 : 0);
@@ -2368,7 +2399,7 @@ int Field_decimal::store(longlong nr, bo
   if (length > int_part)
   {
     overflow(!unsigned_val && nr < 0L);		/* purecov: inspected */
-    return 1;
+    return TYPE_WARN_OUT_OF_RANGE;
   }
 
   fyllchar = zerofill ? (char) '0' : (char) ' ';
@@ -2381,7 +2412,7 @@ int Field_decimal::store(longlong nr, bo
     to[length]='.';
     memset(to + length + 1, '0', dec);
   }
-  return 0;
+  return TYPE_OK;
 }
 
 
@@ -2584,10 +2615,10 @@ Field *Field_new_decimal::create_from_it
 }
 
 
-int Field_new_decimal::reset(void)
+type_conversion_status Field_new_decimal::reset(void)
 {
   store_value(&decimal_zero);
-  return 0;
+  return TYPE_OK;
 }
 
 
@@ -2628,11 +2659,11 @@ void Field_new_decimal::set_value_on_ove
   @retval
     1 error
 */
-
-bool Field_new_decimal::store_value(const my_decimal *decimal_value)
+type_conversion_status
+Field_new_decimal::store_value(const my_decimal *decimal_value)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int error= 0;
+  type_conversion_status error= TYPE_OK;
   DBUG_ENTER("Field_new_decimal::store_value");
 #ifndef DBUG_OFF
   {
@@ -2646,7 +2677,7 @@ bool Field_new_decimal::store_value(cons
   {
     DBUG_PRINT("info", ("unsigned overflow"));
     set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-    error= 1;
+    error= TYPE_WARN_OUT_OF_RANGE;
     decimal_value= &decimal_zero;
   }
 #ifndef DBUG_OFF
@@ -2658,138 +2689,125 @@ bool Field_new_decimal::store_value(cons
   }
 #endif
 
-  if (warn_if_overflow(my_decimal2binary(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
-                                         decimal_value, ptr, precision, dec)))
+  int err= my_decimal2binary(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
+                             decimal_value, ptr, precision, dec);
+  if (warn_if_overflow(err))
   {
     my_decimal buff;
     DBUG_PRINT("info", ("overflow"));
     set_value_on_overflow(&buff, decimal_value->sign());
     my_decimal2binary(E_DEC_FATAL_ERROR, &buff, ptr, precision, dec);
-    error= 1;
   }
   DBUG_EXECUTE("info", print_decimal_buff(decimal_value, (uchar *) ptr,
                                           bin_size););
-  DBUG_RETURN(error);
+  DBUG_RETURN((err != E_DEC_OK) ? decimal_err_to_type_conv_status(err)
+                                : error);
 }
 
 
-int Field_new_decimal::store(const char *from, uint length,
-                             const CHARSET_INFO *charset_arg)
+type_conversion_status
+Field_new_decimal::store(const char *from, uint length,
+                         const CHARSET_INFO *charset_arg)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int err;
   my_decimal decimal_value;
   DBUG_ENTER("Field_new_decimal::store(char*)");
 
-  if ((err= str2my_decimal(E_DEC_FATAL_ERROR &
-                           ~(E_DEC_OVERFLOW | E_DEC_BAD_NUM),
-                           from, length, charset_arg,
-                           &decimal_value)) &&
-      table->in_use->abort_on_warning)
+  int err= str2my_decimal(E_DEC_FATAL_ERROR &
+                          ~(E_DEC_OVERFLOW | E_DEC_BAD_NUM),
+                          from, length, charset_arg,
+                          &decimal_value);
+
+  if (err != 0 && table->in_use->abort_on_warning)
   {
-    ErrConvString errmsg(from, length, &my_charset_bin);
+    ErrConvString errmsg(from, length, charset_arg);
+    const Diagnostics_area *da= table->in_use->get_stmt_da();
     push_warning_printf(table->in_use, Sql_condition::WARN_LEVEL_WARN,
                         ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
                         ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
                         "decimal", errmsg.ptr(), field_name,
-                        (ulong) table->in_use->get_stmt_da()->
-                        current_row_for_warning());
-
-    DBUG_RETURN(err);
+                        static_cast<ulong>(da->current_row_for_warning()));
+    DBUG_RETURN(decimal_err_to_type_conv_status(err));
   }
 
-  switch (err) {
-  case E_DEC_TRUNCATED:
-    set_warning(Sql_condition::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
-    break;
-  case E_DEC_OVERFLOW:
-    set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-    set_value_on_overflow(&decimal_value, decimal_value.sign());
-    break;
-  case E_DEC_BAD_NUM:
-    {
-      ErrConvString errmsg(from, length, &my_charset_bin);
-      push_warning_printf(table->in_use, Sql_condition::WARN_LEVEL_WARN,
-                          ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
-                          ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
-                          "decimal", errmsg.ptr(), field_name,
-                          (ulong) table->in_use->get_stmt_da()->
-                          current_row_for_warning());
-      my_decimal_set_zero(&decimal_value);
-      break;
-    }
-  }
+  if (err != 0)
+    set_decimal_warning(this, err, &decimal_value, from, length, charset_arg);
 
 #ifndef DBUG_OFF
   char dbug_buff[DECIMAL_MAX_STR_LENGTH+2];
   DBUG_PRINT("enter", ("value: %s",
                        dbug_decimal_as_string(dbug_buff, &decimal_value)));
 #endif
-  store_value(&decimal_value);
-  DBUG_RETURN(err);
+
+  type_conversion_status store_stat= store_value(&decimal_value);
+  DBUG_RETURN(err != 0 ? decimal_err_to_type_conv_status(err) : store_stat);
 }
 
 
+type_conversion_status
+store_internal_with_error_check(Field_new_decimal *field,
+                                int err, my_decimal *value)
+{
+  type_conversion_status stat= TYPE_OK;
+  if (err != 0)
+  {
+    if (field->check_overflow(err))
+    {
+      field->set_value_on_overflow(value, value->sign());
+      stat= TYPE_WARN_OUT_OF_RANGE;
+    }
+    else if (field->check_truncated(err))
+      stat= TYPE_NOTE_TRUNCATED;
+    /* Only issue a warning if store_value doesn't issue an warning */
+    field->table->in_use->got_warning= 0;
+  }
+  type_conversion_status store_stat= field->store_value(value);
+  if (store_stat != TYPE_OK)
+    return store_stat;
+  else if (err != 0 && !field->table->in_use->got_warning)
+    field->warn_if_overflow(err);
+  return stat;
+}
+
 /**
   @todo
   Fix following when double2my_decimal when double2decimal
   will return E_DEC_TRUNCATED always correctly
 */
 
-int Field_new_decimal::store(double nr)
+type_conversion_status Field_new_decimal::store(double nr)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  my_decimal decimal_value;
-  int err;
   DBUG_ENTER("Field_new_decimal::store(double)");
+  my_decimal decimal_value;
 
-  err= double2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, nr,
-                         &decimal_value);
-  if (err)
-  {
-    if (check_overflow(err))
-      set_value_on_overflow(&decimal_value, decimal_value.sign());
-    /* Only issue a warning if store_value doesn't issue an warning */
-    table->in_use->got_warning= 0;
-  }
-  if (store_value(&decimal_value))
-    err= 1;
-  else if (err && !table->in_use->got_warning)
-    err= warn_if_overflow(err);
-  DBUG_RETURN(err);
+  int conv_err= double2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, nr,
+                                  &decimal_value);
+  DBUG_RETURN(store_internal_with_error_check(this, conv_err, &decimal_value));
 }
 
-
-int Field_new_decimal::store(longlong nr, bool unsigned_val)
+type_conversion_status
+Field_new_decimal::store(longlong nr, bool unsigned_val)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
+  DBUG_ENTER("Field_new_decimal::store(double, unsigned_val)");
   my_decimal decimal_value;
-  int err;
-
-  if ((err= int2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
-                           nr, unsigned_val, &decimal_value)))
-  {
-    if (check_overflow(err))
-      set_value_on_overflow(&decimal_value, decimal_value.sign());
-    /* Only issue a warning if store_value doesn't issue an warning */
-    table->in_use->got_warning= 0;
-  }
-  if (store_value(&decimal_value))
-    err= 1;
-  else if (err && !table->in_use->got_warning)
-    err= warn_if_overflow(err);
-  return err;
+  int conv_err= int2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
+                               nr, unsigned_val, &decimal_value);
+  DBUG_RETURN(store_internal_with_error_check(this, conv_err, &decimal_value));
 }
 
 
-int Field_new_decimal::store_decimal(const my_decimal *decimal_value)
+type_conversion_status
+Field_new_decimal::store_decimal(const my_decimal *decimal_value)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   return store_value(decimal_value);
 }
 
 
-int Field_new_decimal::store_time(MYSQL_TIME *ltime,
+type_conversion_status
+Field_new_decimal::store_time(MYSQL_TIME *ltime,
                                   uint8 dec_arg __attribute__((unused)))
 {
   my_decimal decimal_value;
@@ -3026,22 +3044,23 @@ Field_new_decimal::unpack(uchar* to,
 ** tiny int
 ****************************************************************************/
 
-int Field_tiny::store(const char *from,uint len, const CHARSET_INFO *cs)
+type_conversion_status
+Field_tiny::store(const char *from,uint len, const CHARSET_INFO *cs)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int error;
   longlong rnd;
   
-  error= get_int(cs, from, len, &rnd, 255, -128, 127);
+  const type_conversion_status error= get_int(cs, from, len, &rnd,
+                                           255, -128, 127);
   ptr[0]= unsigned_flag ? (char) (ulonglong) rnd : (char) rnd;
   return error;
 }
 
 
-int Field_tiny::store(double nr)
+type_conversion_status Field_tiny::store(double nr)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int error= 0;
+  type_conversion_status error= TYPE_OK;
   nr=rint(nr);
   if (unsigned_flag)
   {
@@ -3049,13 +3068,13 @@ int Field_tiny::store(double nr)
     {
       *ptr=0;
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else if (nr > 255.0)
     {
       *ptr=(char) 255;
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else
       *ptr=(char) nr;
@@ -3066,13 +3085,13 @@ int Field_tiny::store(double nr)
     {
       *ptr= (char) -128;
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else if (nr > 127.0)
     {
       *ptr=127;
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else
       *ptr=(char) (int) nr;
@@ -3081,10 +3100,10 @@ int Field_tiny::store(double nr)
 }
 
 
-int Field_tiny::store(longlong nr, bool unsigned_val)
+type_conversion_status Field_tiny::store(longlong nr, bool unsigned_val)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int error= 0;
+  type_conversion_status error= TYPE_OK;
 
   if (unsigned_flag)
   {
@@ -3092,13 +3111,13 @@ int Field_tiny::store(longlong nr, bool
     {
       *ptr= 0;
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else if ((ulonglong) nr > (ulonglong) 255)
     {
       *ptr= (char) 255;
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else
       *ptr=(char) nr;
@@ -3111,13 +3130,13 @@ int Field_tiny::store(longlong nr, bool
     {
       *ptr= (char) -128;
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else if (nr > 127)
     {
       *ptr=127;
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else
       *ptr=(char) nr;
@@ -3202,14 +3221,15 @@ void Field_tiny::sql_type(String &res) c
  Field type short int (2 byte)
 ****************************************************************************/
 
-int Field_short::store(const char *from,uint len, const CHARSET_INFO *cs)
+type_conversion_status
+Field_short::store(const char *from,uint len, const CHARSET_INFO *cs)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   int store_tmp;
-  int error;
   longlong rnd;
   
-  error= get_int(cs, from, len, &rnd, UINT_MAX16, INT_MIN16, INT_MAX16);
+  const type_conversion_status error=
+    get_int(cs, from, len, &rnd, UINT_MAX16, INT_MIN16, INT_MAX16);
   store_tmp= unsigned_flag ? (int) (ulonglong) rnd : (int) rnd;
 #ifdef WORDS_BIGENDIAN
   if (table->s->db_low_byte_first)
@@ -3223,10 +3243,10 @@ int Field_short::store(const char *from,
 }
 
 
-int Field_short::store(double nr)
+type_conversion_status Field_short::store(double nr)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int error= 0;
+  type_conversion_status error= TYPE_OK;
   int16 res;
   nr=rint(nr);
   if (unsigned_flag)
@@ -3235,13 +3255,13 @@ int Field_short::store(double nr)
     {
       res=0;
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else if (nr > (double) UINT_MAX16)
     {
       res=(int16) UINT_MAX16;
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else
       res=(int16) (uint16) nr;
@@ -3252,13 +3272,13 @@ int Field_short::store(double nr)
     {
       res=INT_MIN16;
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else if (nr > (double) INT_MAX16)
     {
       res=INT_MAX16;
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else
       res=(int16) (int) nr;
@@ -3275,10 +3295,10 @@ int Field_short::store(double nr)
 }
 
 
-int Field_short::store(longlong nr, bool unsigned_val)
+type_conversion_status Field_short::store(longlong nr, bool unsigned_val)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int error= 0;
+  type_conversion_status error= TYPE_OK;
   int16 res;
 
   if (unsigned_flag)
@@ -3287,13 +3307,13 @@ int Field_short::store(longlong nr, bool
     {
       res=0;
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else if ((ulonglong) nr > (ulonglong) UINT_MAX16)
     {
       res=(int16) UINT_MAX16;
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else
       res=(int16) (uint16) nr;
@@ -3307,13 +3327,13 @@ int Field_short::store(longlong nr, bool
     {
       res=INT_MIN16;
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else if (nr > (longlong) INT_MAX16)
     {
       res=INT_MAX16;
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else
       res=(int16) nr;
@@ -3450,24 +3470,25 @@ void Field_short::sql_type(String &res)
   Field type medium int (3 byte)
 ****************************************************************************/
 
-int Field_medium::store(const char *from,uint len, const CHARSET_INFO *cs)
+type_conversion_status Field_medium::store(const char *from,uint len,
+                                           const CHARSET_INFO *cs)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   int store_tmp;
-  int error;
   longlong rnd;
   
-  error= get_int(cs, from, len, &rnd, UINT_MAX24, INT_MIN24, INT_MAX24);
+  const type_conversion_status error=
+    get_int(cs, from, len, &rnd, UINT_MAX24, INT_MIN24, INT_MAX24);
   store_tmp= unsigned_flag ? (int) (ulonglong) rnd : (int) rnd;
   int3store(ptr, store_tmp);
   return error;
 }
 
 
-int Field_medium::store(double nr)
+type_conversion_status Field_medium::store(double nr)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int error= 0;
+  type_conversion_status error= TYPE_OK;
   nr=rint(nr);
   if (unsigned_flag)
   {
@@ -3475,14 +3496,14 @@ int Field_medium::store(double nr)
     {
       int3store(ptr,0);
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else if (nr >= (double) (long) (1L << 24))
     {
       uint32 tmp=(uint32) (1L << 24)-1L;
       int3store(ptr,tmp);
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else
       int3store(ptr,(uint32) nr);
@@ -3494,14 +3515,14 @@ int Field_medium::store(double nr)
       long tmp=(long) INT_MIN24;
       int3store(ptr,tmp);
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else if (nr > (double) INT_MAX24)
     {
       long tmp=(long) INT_MAX24;
       int3store(ptr,tmp);
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else
       int3store(ptr,(long) nr);
@@ -3510,10 +3531,10 @@ int Field_medium::store(double nr)
 }
 
 
-int Field_medium::store(longlong nr, bool unsigned_val)
+type_conversion_status Field_medium::store(longlong nr, bool unsigned_val)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int error= 0;
+  type_conversion_status error= TYPE_OK;
 
   if (unsigned_flag)
   {
@@ -3521,14 +3542,14 @@ int Field_medium::store(longlong nr, boo
     {
       int3store(ptr,0);
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else if ((ulonglong) nr >= (ulonglong) (long) (1L << 24))
     {
       long tmp= (long) (1L << 24)-1L;
       int3store(ptr,tmp);
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else
       int3store(ptr,(uint32) nr);
@@ -3543,14 +3564,14 @@ int Field_medium::store(longlong nr, boo
       long tmp= (long) INT_MIN24;
       int3store(ptr,tmp);
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else if (nr > (longlong) INT_MAX24)
     {
       long tmp=(long) INT_MAX24;
       int3store(ptr,tmp);
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else
       int3store(ptr,(long) nr);
@@ -3641,14 +3662,15 @@ void Field_medium::sql_type(String &res)
 ** long int
 ****************************************************************************/
 
-int Field_long::store(const char *from,uint len, const CHARSET_INFO *cs)
+type_conversion_status Field_long::store(const char *from,uint len,
+                                         const CHARSET_INFO *cs)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   long store_tmp;
-  int error;
   longlong rnd;
   
-  error= get_int(cs, from, len, &rnd, UINT_MAX32, INT_MIN32, INT_MAX32);
+  const type_conversion_status error=
+    get_int(cs, from, len, &rnd, UINT_MAX32, INT_MIN32, INT_MAX32);
   store_tmp= unsigned_flag ? (long) (ulonglong) rnd : (long) rnd;
 #ifdef WORDS_BIGENDIAN
   if (table->s->db_low_byte_first)
@@ -3662,10 +3684,10 @@ int Field_long::store(const char *from,u
 }
 
 
-int Field_long::store(double nr)
+type_conversion_status Field_long::store(double nr)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int error= 0;
+  type_conversion_status error= TYPE_OK;
   int32 res;
   nr=rint(nr);
   if (unsigned_flag)
@@ -3673,13 +3695,13 @@ int Field_long::store(double nr)
     if (nr < 0)
     {
       res=0;
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else if (nr > (double) UINT_MAX32)
     {
       res= UINT_MAX32;
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else
       res=(int32) (ulong) nr;
@@ -3689,12 +3711,12 @@ int Field_long::store(double nr)
     if (nr < (double) INT_MIN32)
     {
       res=(int32) INT_MIN32;
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else if (nr > (double) INT_MAX32)
     {
       res=(int32) INT_MAX32;
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else
       res=(int32) (longlong) nr;
@@ -3714,10 +3736,19 @@ int Field_long::store(double nr)
 }
 
 
-int Field_long::store(longlong nr, bool unsigned_val)
+/**
+  Store a longlong in the field
+
+  @param nr            the value to store
+  @param unsigned_val  whether or not 'nr' should be interpreted as 
+                       signed or unsigned. E.g., if 'nr' has all bits
+                       set it is interpreted as -1 if unsigned_val is 
+                       false and ULONGLONG_MAX if unsigned_val is true.
+*/
+type_conversion_status Field_long::store(longlong nr, bool unsigned_val)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int error= 0;
+  type_conversion_status error= TYPE_OK;
   int32 res;
 
   if (unsigned_flag)
@@ -3725,12 +3756,12 @@ int Field_long::store(longlong nr, bool
     if (nr < 0 && !unsigned_val)
     {
       res=0;
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else if ((ulonglong) nr >= (LL(1) << 32))
     {
       res=(int32) (uint32) ~0L;
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else
       res=(int32) (uint32) nr;
@@ -3738,16 +3769,19 @@ int Field_long::store(longlong nr, bool
   else
   {
     if (nr < 0 && unsigned_val)
+    {
       nr= ((longlong) INT_MAX32) + 1;           // Generate overflow
+      error= TYPE_WARN_OUT_OF_RANGE;
+    }
     if (nr < (longlong) INT_MIN32) 
     {
       res=(int32) INT_MIN32;
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else if (nr > (longlong) INT_MAX32)
     {
       res=(int32) INT_MAX32;
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else
       res=(int32) nr;
@@ -3889,24 +3923,27 @@ void Field_long::sql_type(String &res) c
  Field type longlong int (8 bytes)
 ****************************************************************************/
 
-int Field_longlong::store(const char *from,uint len, const CHARSET_INFO *cs)
+type_conversion_status
+Field_longlong::store(const char *from,uint len, const CHARSET_INFO *cs)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int error= 0;
+  int conv_err= 0;
+  type_conversion_status error= TYPE_OK;
   char *end;
   ulonglong tmp;
 
-  tmp= cs->cset->strntoull10rnd(cs,from,len,unsigned_flag,&end,&error);
-  if (error == MY_ERRNO_ERANGE)
+  tmp= cs->cset->strntoull10rnd(cs,from,len,unsigned_flag,&end,&conv_err);
+  if (conv_err == MY_ERRNO_ERANGE)
   {
     set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-    error= 1;
+    error= TYPE_WARN_OUT_OF_RANGE;
   }
   else if (table->in_use->count_cuted_fields && 
-           check_int(cs, from, len, end, error))
-    error= 1;
+           check_int(cs, from, len, end, conv_err))
+    error= TYPE_WARN_OUT_OF_RANGE;
   else
-    error= 0;
+    error= TYPE_OK;
+
 #ifdef WORDS_BIGENDIAN
   if (table->s->db_low_byte_first)
   {
@@ -3919,10 +3956,10 @@ int Field_longlong::store(const char *fr
 }
 
 
-int Field_longlong::store(double nr)
+type_conversion_status Field_longlong::store(double nr)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int error= 0;
+  type_conversion_status error= TYPE_OK;
   longlong res;
 
   nr= rint(nr);
@@ -3931,12 +3968,12 @@ int Field_longlong::store(double nr)
     if (nr < 0)
     {
       res=0;
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else if (nr >= (double) ULONGLONG_MAX)
     {
       res= ~(longlong) 0;
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
     else
       res=(longlong) double2ulonglong(nr);
@@ -3946,12 +3983,14 @@ int Field_longlong::store(double nr)
     if (nr <= (double) LONGLONG_MIN)
     {
       res= LONGLONG_MIN;
-      error= (nr < (double) LONGLONG_MIN);
+      if (nr < (double) LONGLONG_MIN)
+        error= TYPE_WARN_OUT_OF_RANGE;
     }
     else if (nr >= (double) (ulonglong) LONGLONG_MAX)
     {
       res= LONGLONG_MAX;
-      error= (nr > (double) LONGLONG_MAX);
+      if (nr > (double) LONGLONG_MAX)
+        error= TYPE_WARN_OUT_OF_RANGE;
     }
     else
       res=(longlong) nr;
@@ -3971,10 +4010,10 @@ int Field_longlong::store(double nr)
 }
 
 
-int Field_longlong::store(longlong nr, bool unsigned_val)
+type_conversion_status Field_longlong::store(longlong nr, bool unsigned_val)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int error= 0;
+  type_conversion_status error= TYPE_OK;
 
   if (nr < 0)                                   // Only possible error
   {
@@ -3986,7 +4025,7 @@ int Field_longlong::store(longlong nr, b
     {
       nr= unsigned_flag ? (ulonglong) 0 : (ulonglong) LONGLONG_MAX;
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-      error= 1;
+      error= TYPE_WARN_OUT_OF_RANGE;
     }
   }
 
@@ -4178,7 +4217,7 @@ Field_real::unpack(uchar *to, const ucha
 }
 
 
-int
+type_conversion_status
 Field_real::store_time(MYSQL_TIME *ltime,
                        uint8 dec_arg __attribute__((unused)))
 {
@@ -4191,27 +4230,33 @@ Field_real::store_time(MYSQL_TIME *ltime
   single precision float
 ****************************************************************************/
 
-int Field_float::store(const char *from,uint len, const CHARSET_INFO *cs)
+type_conversion_status
+Field_float::store(const char *from,uint len, const CHARSET_INFO *cs)
 {
-  int error;
+  int conv_error;
+  type_conversion_status err= TYPE_OK;
   char *end;
-  double nr= my_strntod(cs,(char*) from,len,&end,&error);
-  if (error || (!len || ((uint) (end-from) != len &&
-                table->in_use->count_cuted_fields)))
+  double nr= my_strntod(cs,(char*) from,len,&end,&conv_error);
+  if (conv_error || (!len || ((uint) (end-from) != len &&
+                              table->in_use->count_cuted_fields)))
   {
     set_warning(Sql_condition::WARN_LEVEL_WARN,
-                (error ? ER_WARN_DATA_OUT_OF_RANGE : WARN_DATA_TRUNCATED), 1);
-    error= error ? 1 : 2;
+                (conv_error ? ER_WARN_DATA_OUT_OF_RANGE
+                            : WARN_DATA_TRUNCATED),
+                1);
+    err= conv_error ? TYPE_WARN_OUT_OF_RANGE : TYPE_WARN_TRUNCATED;
   }
   Field_float::store(nr);
-  return error;
+  return err;
 }
 
 
-int Field_float::store(double nr)
+type_conversion_status Field_float::store(double nr)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int error= truncate(&nr, FLT_MAX);
+  const type_conversion_status error=
+    truncate(&nr, FLT_MAX) ? TYPE_WARN_OUT_OF_RANGE : TYPE_OK;
+
   float j= (float)nr;
 
 #ifdef WORDS_BIGENDIAN
@@ -4226,7 +4271,7 @@ int Field_float::store(double nr)
 }
 
 
-int Field_float::store(longlong nr, bool unsigned_val)
+type_conversion_status Field_float::store(longlong nr, bool unsigned_val)
 {
   return Field_float::store(unsigned_val ? ulonglong2double((ulonglong) nr) :
                             (double) nr);
@@ -4413,27 +4458,32 @@ void Field_float::sql_type(String &res)
   double precision floating point numbers
 ****************************************************************************/
 
-int Field_double::store(const char *from,uint len, const CHARSET_INFO *cs)
+type_conversion_status
+Field_double::store(const char *from,uint len, const CHARSET_INFO *cs)
 {
-  int error;
+  int conv_error;
+  type_conversion_status error= TYPE_OK;
   char *end;
-  double nr= my_strntod(cs,(char*) from, len, &end, &error);
-  if (error || (!len || ((uint) (end-from) != len &&
-                table->in_use->count_cuted_fields)))
+  double nr= my_strntod(cs,(char*) from, len, &end, &conv_error);
+  if ((conv_error != 0) || (!len || ((uint) (end-from) != len &&
+                                     table->in_use->count_cuted_fields)))
   {
     set_warning(Sql_condition::WARN_LEVEL_WARN,
-                (error ? ER_WARN_DATA_OUT_OF_RANGE : WARN_DATA_TRUNCATED), 1);
-    error= error ? 1 : 2;
+                (conv_error ? ER_WARN_DATA_OUT_OF_RANGE
+                            : WARN_DATA_TRUNCATED),
+                1);
+    error= conv_error ? TYPE_WARN_OUT_OF_RANGE : TYPE_WARN_TRUNCATED;
   }
   Field_double::store(nr);
   return error;
 }
 
 
-int Field_double::store(double nr)
+type_conversion_status Field_double::store(double nr)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int error= truncate(&nr, DBL_MAX);
+  const type_conversion_status error=
+    truncate(&nr, DBL_MAX) ? TYPE_WARN_OUT_OF_RANGE : TYPE_OK;
 
 #ifdef WORDS_BIGENDIAN
   if (table->s->db_low_byte_first)
@@ -4447,7 +4497,7 @@ int Field_double::store(double nr)
 }
 
 
-int Field_double::store(longlong nr, bool unsigned_val)
+type_conversion_status Field_double::store(longlong nr, bool unsigned_val)
 {
   return Field_double::store(unsigned_val ? ulonglong2double((ulonglong) nr) :
                              (double) nr);
@@ -4459,23 +4509,20 @@ int Field_double::store(longlong nr, boo
   Also ensure that the argument is within [-max_value; max_value] range.
 */
 
-int Field_real::truncate(double *nr, double max_value)
+bool Field_real::truncate(double *nr, double max_value)
 {
-  int error= 1;
-  double res= *nr;
-  
-  if (isnan(res))
+  if (isnan(*nr))
   {
-    res= 0;
+    *nr= 0;
     set_null();
     set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-    goto end;
+    return true;
   }
-  else if (unsigned_flag && res < 0)
+  else if (unsigned_flag && *nr < 0)
   {
-    res= 0;
+    *nr= 0;
     set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-    goto end;
+    return true;
   }
 
   if (!not_fixed)
@@ -4489,33 +4536,31 @@ int Field_real::truncate(double *nr, dou
     max_value-= 1.0 / log_10[dec];
 
     /* Check for infinity so we don't get NaN in calculations */
-    if (!my_isinf(res))
+    if (!my_isinf(*nr))
     {
-      double tmp= rint((res - floor(res)) * log_10[dec]) / log_10[dec];
-      res= floor(res) + tmp;
+      double tmp= rint((*nr - floor(*nr)) * log_10[dec]) / log_10[dec];
+      *nr= floor(*nr) + tmp;
     }
   }
   
-  if (res < -max_value)
+  if (*nr < -max_value)
   {
-   res= -max_value;
-   set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+    *nr= -max_value;
+    set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+    return true;
   }
-  else if (res > max_value)
+  else if (*nr > max_value)
   {
-    res= max_value;
+    *nr= max_value;
     set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+    return true;
   }
-  else
-    error= 0;
 
-end:
-  *nr= res;
-  return error;
+  return false;
 }
 
 
-int Field_real::store_decimal(const my_decimal *dm)
+type_conversion_status Field_real::store_decimal(const my_decimal *dm)
 {
   double dbl;
   my_decimal2double(E_DEC_FATAL_ERROR, dm, &dbl);
@@ -4774,19 +4819,23 @@ Field_temporal::set_warnings(ErrConvStri
 }
 
 
-int Field_temporal::store(longlong nr, bool unsigned_val)
+type_conversion_status Field_temporal::store(longlong nr, bool unsigned_val)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int warnings= 0, error;
+  int warnings= 0;
   MYSQL_TIME ltime;
-  if (!(error= convert_number_to_TIME(nr, unsigned_val, 0, &ltime, &warnings)))
+  type_conversion_status error= convert_number_to_TIME(nr, unsigned_val, 0,
+                                                       &ltime, &warnings);
+  if (error == TYPE_OK || error == TYPE_NOTE_TRUNCATED)
     error= store_internal(&ltime, &warnings);
   else
   {
     DBUG_ASSERT(warnings != 0); // Must be set by convert_number_to_TIME
 
-    if (warnings & (MYSQL_TIME_WARN_ZERO_DATE | MYSQL_TIME_WARN_ZERO_IN_DATE))
-      error= current_thd->is_strict_mode() ? 1 : 3;
+    if (warnings & (MYSQL_TIME_WARN_ZERO_DATE |
+                    MYSQL_TIME_WARN_ZERO_IN_DATE) &&
+        !current_thd->is_strict_mode())
+      error= TYPE_NOTE_TIME_TRUNCATED;
   }
   if (warnings)
     set_warnings(ErrConvString(nr, unsigned_val), warnings);
@@ -4794,46 +4843,49 @@ int Field_temporal::store(longlong nr, b
 }
 
 
-int Field_temporal::store_lldiv_t(const lldiv_t *lld, int *warnings)
+type_conversion_status
+Field_temporal::store_lldiv_t(const lldiv_t *lld, int *warnings)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int error;
+  type_conversion_status error;
   MYSQL_TIME ltime;
-  if (!(error= convert_number_to_TIME(lld->quot, 0, lld->rem, &ltime, warnings)))
+  error= convert_number_to_TIME(lld->quot, 0, lld->rem, &ltime, warnings);
+  if (error == TYPE_OK || error == TYPE_NOTE_TRUNCATED)
     error= store_internal_with_round(&ltime, warnings);
   else if (!*warnings)
   {
     DBUG_ASSERT(warnings != 0); // Must be set by convert_number_to_TIME
+    if (((*warnings & MYSQL_TIME_WARN_ZERO_DATE) != 0 ||
+         (*warnings & MYSQL_TIME_WARN_ZERO_IN_DATE) != 0) &&
+        !current_thd->is_strict_mode())
+      error= TYPE_NOTE_TIME_TRUNCATED;
   }
 
-  if (*warnings & (MYSQL_TIME_WARN_ZERO_DATE | MYSQL_TIME_WARN_ZERO_IN_DATE))
-    error= current_thd->is_strict_mode() ? 1 : 3;
-
   return error;
 }
 
 
-int Field_temporal::store_decimal(const my_decimal *decimal)
+type_conversion_status Field_temporal::store_decimal(const my_decimal *decimal)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   lldiv_t lld;
   int warnings= 0;
   /* Pass 0 in the first argument, not to produce warnings automatically */
   my_decimal2lldiv_t(0, decimal, &lld);
-  int error= store_lldiv_t(&lld, &warnings);
+  const type_conversion_status error= store_lldiv_t(&lld, &warnings);
   if (warnings)
     set_warnings(ErrConvString(decimal), warnings);
   return error;
 }
 
 
-int Field_temporal::store(double nr)
+type_conversion_status Field_temporal::store(double nr)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   int warnings= 0;
   lldiv_t lld;
   double2lldiv_t(nr, &lld);
-  int error= store_lldiv_t(&lld, &warnings);
+  const type_conversion_status error= store_lldiv_t(&lld, &warnings);
   if (warnings)
     set_warnings(ErrConvString(nr), warnings);
    return error;
@@ -4847,36 +4899,41 @@ int Field_temporal::store(double nr)
   @param  len     Length of the string
   @param  cs      Character set of the string
 
-  @retval  0  ok
-  @retval  1  Value was cut during conversion
-  @retval  2  Wrong date/time string
-  @retval  3  Date/time value that was cut (warning level NOTE)
-              This is used by opt_range.cc:get_mm_leaf().
-
-              Only Field_newdate can return 3.
+  @retval TYPE_OK   Storage of value went fine without warnings or errors
+  @retval !TYPE_OK  Warning/error as indicated by type_conversion_status enum
+                    value
 */
-int
+type_conversion_status
 Field_temporal::store(const char *str, uint len, const CHARSET_INFO *cs)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int error;
+  type_conversion_status error= TYPE_OK;
   MYSQL_TIME ltime;
   MYSQL_TIME_STATUS status;
   if (convert_str_to_TIME(str, len, cs, &ltime, &status))
   {
+    /*
+      When convert_str_to_TIME() returns error, ltime has been set to
+      0 so there's nothing to store in the field.
+    */
     reset();
     if (status.warnings & (MYSQL_TIME_WARN_ZERO_DATE |
-                           MYSQL_TIME_WARN_ZERO_IN_DATE))
-      error= current_thd->is_strict_mode() ? 1 : 3;
+                           MYSQL_TIME_WARN_ZERO_IN_DATE) &&
+        !current_thd->is_strict_mode())
+      error= TYPE_NOTE_TIME_TRUNCATED;
     else
-      error= 2;
+      error= TYPE_ERR_BAD_VALUE;
   }
   else
   {
-    error= test(status.warnings); // Test convert_str_to_TIME warnings
-    const int error2= store_internal_with_round(&ltime, &status.warnings);
-    if (!error)
-      error= error2; 
+    error= time_warning_to_type_conversion_status(status.warnings);
+
+    const type_conversion_status tmp_error= store_internal_with_round(&ltime,
+                                                           &status.warnings);
+
+    // Return the most serious error of the two, see type_conversion_status
+    if (tmp_error > error)
+      error= tmp_error;
   }
   if (status.warnings)
     set_warnings(ErrConvString(str, len, cs), status.warnings);
@@ -4884,6 +4941,10 @@ Field_temporal::store(const char *str, u
 }
 
 
+/**
+  @retval -1              Timestamp with wrong values
+  @retval anything else   DATETIME as integer in YYYYMMDDHHMMSS format
+*/
 longlong
 Field_temporal::convert_number_to_datetime(longlong nr, bool unsigned_val,
                                            MYSQL_TIME *ltime, int *warnings)
@@ -5005,7 +5066,7 @@ String *Field_temporal_with_date::val_st
 }
 
 
-int
+type_conversion_status
 Field_temporal_with_date::convert_number_to_TIME(longlong nr,
                                                  bool unsigned_val,
                                                  int nanoseconds,
@@ -5016,34 +5077,35 @@ Field_temporal_with_date::convert_number
   {
     reset();
     *warnings|= MYSQL_TIME_WARN_OUT_OF_RANGE;
-    return 1;
+    return TYPE_WARN_OUT_OF_RANGE;
   }
 
   if (convert_number_to_datetime(nr, unsigned_val, ltime, warnings) == LL(-1))
-    return 2;
+    return TYPE_ERR_BAD_VALUE;
 
   if (ltime->time_type == MYSQL_TIMESTAMP_DATE && nanoseconds)
   {
     *warnings|= MYSQL_TIME_WARN_TRUNCATED;
-    return 0;
+    return TYPE_NOTE_TRUNCATED;
   }
 
   ltime->second_part= 0;
   if (datetime_add_nanoseconds_with_round(ltime, nanoseconds, warnings))
   {
     reset();
-    return 1;
+    return TYPE_WARN_OUT_OF_RANGE;
   }
-  return 0;
+  return TYPE_OK;
 }
 
 
-int
+type_conversion_status
 Field_temporal_with_date::store_time(MYSQL_TIME *ltime,
                                      uint8 dec_arg __attribute__((unused)))
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int error, warnings= 0;
+  type_conversion_status error;
+  int warnings= 0;
 
   switch (ltime->time_type) // TS-TODO: split into separate methods?
   {
@@ -5051,8 +5113,13 @@ Field_temporal_with_date::store_time(MYS
   case MYSQL_TIMESTAMP_DATE:
     if (check_date(ltime, non_zero_date(ltime), date_flags(), &warnings))
     {
+      DBUG_ASSERT(warnings &
+                  (MYSQL_TIME_WARN_OUT_OF_RANGE |
+                   MYSQL_TIME_WARN_ZERO_DATE |
+                   MYSQL_TIME_WARN_ZERO_IN_DATE));
+
+      error= time_warning_to_type_conversion_status(warnings);
       reset();
-      error= 1;
     }
     else
       error= store_internal_with_round(ltime, &warnings);
@@ -5071,7 +5138,7 @@ Field_temporal_with_date::store_time(MYS
   default:
     warnings|= MYSQL_TIME_WARN_TRUNCATED;
     reset();
-    error= 1;
+    error= TYPE_WARN_TRUNCATED;
   }
 
   if (warnings)
@@ -5103,15 +5170,17 @@ bool Field_temporal_with_date::send_bina
 }
 
 
-int Field_temporal_with_date::store_internal_with_round(MYSQL_TIME *ltime,
-                                                        int *warnings)
+type_conversion_status
+Field_temporal_with_date::store_internal_with_round(MYSQL_TIME *ltime,
+                                                    int *warnings)
 {
   if (my_datetime_round(ltime, dec, warnings))
   {
     reset();
-    return 1;
+    return time_warning_to_type_conversion_status(*warnings);
   }
-  return store_internal(ltime, warnings);
+  else
+    return store_internal(ltime, warnings);
 }
 
 
@@ -5277,11 +5346,14 @@ ulonglong Field_timestamp::date_flags(co
 }
 
 
-int Field_timestamp::store_internal(const MYSQL_TIME *ltime, int *warnings)
+type_conversion_status
+Field_timestamp::store_internal(const MYSQL_TIME *ltime, int *warnings)
 {
   THD *thd= table ? table->in_use : current_thd;
   struct timeval tm;
-  int error= convert_TIME_to_timestamp(thd, ltime, &tm, warnings) ?  1 : 0;
+  convert_TIME_to_timestamp(thd, ltime, &tm, warnings);
+  const type_conversion_status error=
+    time_warning_to_type_conversion_status(*warnings);
   store_timestamp_internal(&tm);
   return error;
 }
@@ -5345,7 +5417,7 @@ void Field_timestamp::store_timestamp_in
 }
 
 
-int Field_timestamp::store_packed(longlong nr)
+type_conversion_status Field_timestamp::store_packed(longlong nr)
 {
   /* Make sure the stored value was previously properly rounded or truncated */
   DBUG_ASSERT((MY_PACKED_TIME_GET_FRAC_PART(nr) % 
@@ -5455,10 +5527,10 @@ ulonglong Field_timestampf::date_flags(c
 }
 
 
-int Field_timestampf::reset()
+type_conversion_status Field_timestampf::reset()
 {
   memset(ptr, 0, pack_length());
-  return 0;
+  return TYPE_OK;
 }
 
 
@@ -5468,17 +5540,20 @@ void Field_timestampf::store_timestamp_i
 }
 
 
-int Field_timestampf::store_internal(const MYSQL_TIME *ltime, int *warnings)
+type_conversion_status
+Field_timestampf::store_internal(const MYSQL_TIME *ltime, int *warnings)
 {
   THD *thd= table ? table->in_use : current_thd;
   struct timeval tm;
-  int error= convert_TIME_to_timestamp(thd, ltime, &tm, warnings) ? 1 : 0;
+  convert_TIME_to_timestamp(thd, ltime, &tm, warnings);
+  const type_conversion_status error=
+    time_warning_to_type_conversion_status(*warnings);
   store_timestamp_internal(&tm);
   return error;
 }
 
 
-int Field_timestampf::store_packed(longlong nr)
+type_conversion_status Field_timestampf::store_packed(longlong nr)
 {
   MYSQL_TIME ltime;
   TIME_from_longlong_datetime_packed(&ltime, nr);
@@ -5544,7 +5619,7 @@ Field_time_common::convert_str_to_TIME(c
 }
 
 
-int
+type_conversion_status
 Field_time_common::convert_number_to_TIME(longlong nr, bool unsigned_val,
                                           int nanoseconds,
                                           MYSQL_TIME *ltime, int *warnings)
@@ -5554,12 +5629,12 @@ Field_time_common::convert_number_to_TIM
     *warnings|= MYSQL_TIME_WARN_OUT_OF_RANGE;
     set_max_time(ltime, 0);
     store_internal(ltime, warnings);
-    return 1;
+    return TYPE_WARN_OUT_OF_RANGE;
   }
   if (number_to_time(nr, ltime, warnings))
   {
     store_internal(ltime, warnings);
-    return 1;
+    return TYPE_WARN_OUT_OF_RANGE;
   }
   /*
     Both number_to_time() call and negative nanoseconds value
@@ -5568,12 +5643,17 @@ Field_time_common::convert_number_to_TIM
   if ((ltime->neg|= (nanoseconds < 0)))
     nanoseconds= -nanoseconds;
   ltime->second_part= 0;
-  return time_add_nanoseconds_with_round(ltime, nanoseconds, warnings);
+  bool round_error= time_add_nanoseconds_with_round(ltime, nanoseconds,
+                                                    warnings);
+
+  return round_error ? time_warning_to_type_conversion_status(*warnings)
+                     : TYPE_OK;
 }
 
 
-int Field_time_common::store_time(MYSQL_TIME *ltime,
-                                  uint8 dec_arg __attribute__((unused)))
+type_conversion_status
+Field_time_common::store_time(MYSQL_TIME *ltime,
+                              uint8 dec_arg __attribute__((unused)))
 {
   /* Check if seconds or minutes are out of range */
   if (ltime->second >= 60 || ltime->minute >= 60)
@@ -5581,18 +5661,19 @@ int Field_time_common::store_time(MYSQL_
     set_warnings(ErrConvString(ltime, decimals()),
                  MYSQL_TIME_WARN_OUT_OF_RANGE);
     reset();
-    return 1;
+    return TYPE_WARN_OUT_OF_RANGE;
   }
   int warnings= 0;
   return store_internal_with_round(ltime, &warnings);
 }
 
 
-int Field_time_common::store_internal_with_round(MYSQL_TIME *ltime,
-                                                 int *warnings)
+type_conversion_status
+Field_time_common::store_internal_with_round(MYSQL_TIME *ltime, int *warnings)
 {
   if (my_time_round(ltime, dec))
-    return 1;
+    return TYPE_WARN_OUT_OF_RANGE;
+
   return store_internal(ltime, warnings);
 }
 
@@ -5669,18 +5750,19 @@ bool Field_time_common::send_binary(Prot
 ** Stored as a 3 byte unsigned int
 ****************************************************************************/
 
-int Field_time::store_internal(const MYSQL_TIME *ltime, int *warnings)
+type_conversion_status
+Field_time::store_internal(const MYSQL_TIME *ltime, int *warnings)
 {
   long tmp= ((ltime->month ? 0 : ltime->day * 24L) + ltime->hour) * 10000L +
             (ltime->minute * 100 + ltime->second);
   if (ltime->neg)
     tmp= -tmp;
   int3store(ptr, tmp);
-  return 0;
+  return TYPE_OK;
 }
 
 
-int Field_time::store_packed(longlong nr)
+type_conversion_status Field_time::store_packed(longlong nr)
 {
   MYSQL_TIME ltime;
   TIME_from_longlong_time_packed(&ltime, nr);
@@ -5800,16 +5882,16 @@ void Field_timef::sql_type(String &res)
 }
 
 
-int Field_timef::reset()
+type_conversion_status Field_timef::reset()
 {
   return store_packed(0);
 }
 
 
-int Field_timef::store_packed(longlong nr)
+type_conversion_status Field_timef::store_packed(longlong nr)
 {
   my_time_packed_to_binary(nr, ptr, dec);
-  return 0;
+  return TYPE_OK;
 }
 
 
@@ -5820,17 +5902,19 @@ longlong Field_timef::val_time_temporal(
 }
 
 
-int Field_timef::store_internal(const MYSQL_TIME *ltime, int *warnings)
+type_conversion_status
+Field_timef::store_internal(const MYSQL_TIME *ltime, int *warnings)
 {
-  int rc= store_packed(TIME_to_longlong_time_packed(ltime));
-  if (rc == 0 && non_zero_date(ltime))
+  type_conversion_status rc= store_packed(TIME_to_longlong_time_packed(ltime));
+  if (rc == TYPE_OK && non_zero_date(ltime))
   {
     /*
       The DATE part got lost; we warn, like in Field_newdate::store_internal,
-      and trigger some code in get_mm_leaf() (see err==3 there).
+      and trigger some code in get_mm_leaf()
+      (see err==TYPE_NOTE_TIME_TRUNCATED there).
     */
     *warnings|= MYSQL_TIME_NOTE_TRUNCATED;
-    rc= 3;
+    rc= TYPE_NOTE_TIME_TRUNCATED;
   }
   return rc;
 }
@@ -5850,29 +5934,37 @@ bool Field_timef::get_time(MYSQL_TIME *l
 ** Can handle 2 byte or 4 byte years!
 ****************************************************************************/
 
-int Field_year::store(const char *from, uint len,const CHARSET_INFO *cs)
+type_conversion_status
+Field_year::store(const char *from, uint len,const CHARSET_INFO *cs)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   char *end;
-  int error;
-  longlong nr= cs->cset->strntoull10rnd(cs, from, len, 0, &end, &error);
+  int conv_error;
+  type_conversion_status ret= TYPE_OK;
+  longlong nr= cs->cset->strntoull10rnd(cs, from, len, 0, &end, &conv_error);
 
   if (nr < 0 || (nr >= 100 && nr <= 1900) || nr > 2155 ||
-      error == MY_ERRNO_ERANGE)
+      conv_error == MY_ERRNO_ERANGE)
   {
     *ptr=0;
     set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-    return 1;
+    return TYPE_WARN_OUT_OF_RANGE;
   }
-  if (table->in_use->count_cuted_fields && 
-      (error= check_int(cs, from, len, end, error)))
+  else if (conv_error)
+    ret= TYPE_ERR_BAD_VALUE;
+
+  if (table->in_use->count_cuted_fields)
   {
-    if (error == 1)  /* empty or incorrect string */
+    ret= check_int(cs, from, len, end, conv_error);
+    if (ret != TYPE_OK)
     {
-      *ptr= 0;
-      return 1;
+      if (ret == TYPE_ERR_BAD_VALUE)  /* empty or incorrect string */
+      {
+        *ptr= 0;
+        return TYPE_WARN_OUT_OF_RANGE;
+      }
+      ret= TYPE_WARN_OUT_OF_RANGE;
     }
-    error= 1;
   }
 
   if (nr != 0 || len != 4)
@@ -5883,22 +5975,22 @@ int Field_year::store(const char *from,
       nr-= 1900;
   }
   *ptr= (char) (uchar) nr;
-  return error;
+  return ret;
 }
 
 
-int Field_year::store(double nr)
+type_conversion_status Field_year::store(double nr)
 {
   if (nr < 0.0 || nr >= 2155.0)
   {
     (void) Field_year::store((longlong) -1, FALSE);
-    return 1;
+    return TYPE_WARN_OUT_OF_RANGE;
   }
   return Field_year::store((longlong) nr, FALSE);
 }
 
 
-int
+type_conversion_status
 Field_year::store_time(MYSQL_TIME *ltime,
                        uint8 dec_arg __attribute__((unused)))
 {
@@ -5915,14 +6007,14 @@ Field_year::store_time(MYSQL_TIME *ltime
 }
 
 
-int Field_year::store(longlong nr, bool unsigned_val)
+type_conversion_status Field_year::store(longlong nr, bool unsigned_val)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   if (nr < 0 || (nr >= 100 && nr <= 1900) || nr > 2155)
   {
     *ptr= 0;
     set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-    return 1;
+    return TYPE_WARN_OUT_OF_RANGE;
   }
   if (nr != 0 || field_length != 4)		// 0000 -> 0; 00 -> 2000
   {
@@ -5932,7 +6024,7 @@ int Field_year::store(longlong nr, bool
       nr-= 1900;
   }
   *ptr= (char) (uchar) nr;
-  return 0;
+  return TYPE_OK;
 }
 
 
@@ -5996,16 +6088,17 @@ ulonglong Field_newdate::date_flags(cons
 }
 
 
-int Field_newdate::store_internal(const MYSQL_TIME *ltime, int *warnings)
+type_conversion_status
+Field_newdate::store_internal(const MYSQL_TIME *ltime, int *warnings)
 {
   long tmp= ltime->day + ltime->month * 32 + ltime->year * 16 * 32;
   int3store(ptr, tmp);
   if (non_zero_time(ltime))
   {
     *warnings|= MYSQL_TIME_NOTE_TRUNCATED;
-    return 3;
+    return TYPE_NOTE_TIME_TRUNCATED;
   }
-  return 0;
+  return TYPE_OK;
 }
 
 
@@ -6021,7 +6114,7 @@ bool Field_newdate::get_date_internal(MY
 }
 
 
-int Field_newdate::store_packed(longlong nr)
+type_conversion_status Field_newdate::store_packed(longlong nr)
 {
   int warnings= 0;
   MYSQL_TIME ltime;
@@ -6154,7 +6247,7 @@ void Field_datetime::store_timestamp_int
   @param tmp    The number, in YYYYMMDDhhmmss format
   @param ptr    Where to store to
 */
-static inline int
+static inline type_conversion_status
 datetime_store_internal(TABLE *table, ulonglong tmp, uchar *ptr)
 {
 #ifdef WORDS_BIGENDIAN
@@ -6165,7 +6258,7 @@ datetime_store_internal(TABLE *table, ul
   else
 #endif
     longlongstore(ptr, tmp);
-  return 0;
+  return TYPE_OK;
 }
 
 
@@ -6202,27 +6295,27 @@ bool Field_datetime::get_date_internal(M
 }
 
 
-int Field_datetime::store_internal(const MYSQL_TIME *ltime, int *warnings)
+type_conversion_status
+Field_datetime::store_internal(const MYSQL_TIME *ltime, int *warnings)
 {
   ulonglong tmp= TIME_to_ulonglong_datetime(ltime);
   return datetime_store_internal(table, tmp, ptr);
 }
 
 
-int Field_datetime::store(longlong nr, bool unsigned_val)
+type_conversion_status Field_datetime::store(longlong nr, bool unsigned_val)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   MYSQL_TIME ltime;
-  int error, warnings;
-  longlong tmp;
-  if ((tmp= convert_number_to_datetime(nr, unsigned_val, &ltime, &warnings)) ==
-                                       LL(-1))
-  {
-    error= 2;
-  }
+  int warnings;
+  type_conversion_status error= TYPE_OK;
+  longlong tmp= convert_number_to_datetime(nr, unsigned_val,
+                                           &ltime, &warnings);
+  if (tmp == LL(-1))
+    error= TYPE_ERR_BAD_VALUE;
   else
   {
-    error= warnings;
+    error= time_warning_to_type_conversion_status(warnings);
     datetime_store_internal(table, tmp, ptr);
   }
   if (warnings)
@@ -6231,7 +6324,7 @@ int Field_datetime::store(longlong nr, b
 }
 
 
-int Field_datetime::store_packed(longlong nr)
+type_conversion_status Field_datetime::store_packed(longlong nr)
 {
   MYSQL_TIME ltime;
   TIME_from_longlong_datetime_packed(&ltime, nr);
@@ -6345,8 +6438,8 @@ void Field_datetimef::store_timestamp_in
   THD *thd= current_thd;
   thd->variables.time_zone->gmt_sec_to_TIME(&mysql_time, *tm);
   thd->time_zone_used= true;
-  int error= 0;
-  store_internal(&mysql_time, &error);
+  int warnings= 0;
+  store_internal(&mysql_time, &warnings);
 }
 
 
@@ -6378,17 +6471,18 @@ bool Field_datetimef::get_date_internal(
 }
 
 
-int Field_datetimef::store_internal(const MYSQL_TIME *ltime, int *warnings)
+type_conversion_status
+Field_datetimef::store_internal(const MYSQL_TIME *ltime, int *warnings)
 {
   store_packed(TIME_to_longlong_datetime_packed(ltime));
-  return 0;
+  return TYPE_OK;
 }
 
 
-int Field_datetimef::reset()
+type_conversion_status Field_datetimef::reset()
 {
   store_packed(0);
-  return 0;
+  return TYPE_OK;
 }
 
 
@@ -6398,10 +6492,10 @@ longlong Field_datetimef::val_date_tempo
 }
 
 
-int Field_datetimef::store_packed(longlong nr)
+type_conversion_status Field_datetimef::store_packed(longlong nr)
 {
   my_datetime_packed_to_binary(nr, ptr, dec);
-  return 0;
+  return TYPE_OK;
 }
 
 
@@ -6411,46 +6505,47 @@ int Field_datetimef::store_packed(longlo
 ** A string may be varchar or binary
 ****************************************************************************/
 
-/*
+/**
   Report "not well formed" or "cannot convert" error
   after storing a character string info a field.
 
-  SYNOPSIS
-    check_string_copy_error()
-    field                    - Field
-    well_formed_error_pos    - where not well formed data was first met
-    cannot_convert_error_pos - where a not-convertable character was first met
-    end                      - end of the string
-    cs                       - character set of the string
+  As of version 5.0 both cases return the same error:
 
-  NOTES
-    As of version 5.0 both cases return the same error:
-  
       "Invalid string value: 'xxx' for column 't' at row 1"
-  
+
   Future versions will possibly introduce a new error message:
 
       "Cannot convert character string: 'xxx' for column 't' at row 1"
 
-  RETURN
-    FALSE - If errors didn't happen
-    TRUE  - If an error happened
+  @param  well_formed_error_pos      position of the first non-wellformed
+                                     character in the source string
+  @param  cannot_convert_error_pos   position of the first non-convertable
+                                     character in the source string
+  @param  from_end_pos               position where conversion stopped in
+                                     the source string
+  @param  end                        end of the source string
+  @param  count_spaces               treat trailing spaces as important data
+  @param  cs                         character set of the string
+
+  @return TYPE_OK, TYPE_NOTE_TRUNCATED, TYPE_WARN_TRUNCATED
+
 */
 
-static bool
-check_string_copy_error(Field_str *field,
-                        const char *well_formed_error_pos,
-                        const char *cannot_convert_error_pos,
-                        const char *end,
-                        const CHARSET_INFO *cs)
+type_conversion_status
+Field_longstr::check_string_copy_error(const char *well_formed_error_pos,
+                                       const char *cannot_convert_error_pos,
+                                       const char *from_end_pos,
+                                       const char *end,
+                                       bool count_spaces,
+                                       const CHARSET_INFO *cs) const
 {
   const char *pos;
   char tmp[32];
-  THD *thd= field->table->in_use;
+  THD *thd= table->in_use;
 
   if (!(pos= well_formed_error_pos) &&
       !(pos= cannot_convert_error_pos))
-    return FALSE;
+    return report_if_important_data(from_end_pos, end, count_spaces);
 
   convert_to_printable(tmp, sizeof(tmp), pos, (end - pos), cs, 6);
 
@@ -6458,9 +6553,9 @@ check_string_copy_error(Field_str *field
                       Sql_condition::WARN_LEVEL_WARN,
                       ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
                       ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
-                      "string", tmp, field->field_name,
+                      "string", tmp, field_name,
                       thd->get_stmt_da()->current_row_for_warning());
-  return TRUE;
+  return TYPE_WARN_TRUNCATED;
 }
 
 
@@ -6474,8 +6569,8 @@ check_string_copy_error(Field_str *field
     count_spaces             - Treat traling spaces as important data
 
   RETURN VALUES
-    0   - None was truncated (or we don't count cut fields)
-    2   - Some bytes was truncated
+    false  - None was truncated (or we don't count cut fields)
+    true   - Some bytes were truncated
 
   NOTE
     Check if we lost any important data (anything in a binary string,
@@ -6484,9 +6579,9 @@ check_string_copy_error(Field_str *field
     Silently ignore traling spaces if the count_space parameter is FALSE.
 */
 
-int
+type_conversion_status
 Field_longstr::report_if_important_data(const char *pstr, const char *end,
-                                        bool count_spaces)
+                                        bool count_spaces) const
 {
   if ((pstr < end) && table->in_use->count_cuted_fields)
   {
@@ -6496,21 +6591,22 @@ Field_longstr::report_if_important_data(
         set_warning(Sql_condition::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1);
       else
         set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
-      return 2;
+      return TYPE_WARN_TRUNCATED;
     }
     else if (count_spaces)
     { /* If we lost only spaces then produce a NOTE, not a WARNING */
       set_warning(Sql_condition::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
-      return 2;
+      return TYPE_NOTE_TRUNCATED;
     }
   }
-  return 0;
+  return TYPE_OK;
 }
 
 
 	/* Copy a string and fill with space */
 
-int Field_string::store(const char *from,uint length,const CHARSET_INFO *cs)
+type_conversion_status
+Field_string::store(const char *from,uint length,const CHARSET_INFO *cs)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   uint copy_length;
@@ -6535,11 +6631,9 @@ int Field_string::store(const char *from
                               field_length-copy_length,
                               field_charset->pad_char);
 
-  if (check_string_copy_error(this, well_formed_error_pos,
-                              cannot_convert_error_pos, from + length, cs))
-    return 2;
-
-  return report_if_important_data(from_end_pos, from + length, FALSE);
+  return check_string_copy_error(well_formed_error_pos,
+                                 cannot_convert_error_pos, from_end_pos,
+                                 from + length, false, cs);
 }
 
 
@@ -6551,7 +6645,7 @@ int Field_string::store(const char *from
   @param nr            number
 */
 
-int Field_str::store(double nr)
+type_conversion_status Field_str::store(double nr)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
@@ -6591,7 +6685,7 @@ uint Field_str::is_equal(Create_field *n
 }
 
 
-int Field_string::store(longlong nr, bool unsigned_val)
+type_conversion_status Field_string::store(longlong nr, bool unsigned_val)
 {
   char buff[64];
   int  l;
@@ -6602,7 +6696,7 @@ int Field_string::store(longlong nr, boo
 }
 
 
-int Field_longstr::store_decimal(const my_decimal *d)
+type_conversion_status Field_longstr::store_decimal(const my_decimal *d)
 {
   char buff[DECIMAL_MAX_STR_LENGTH+1];
   String str(buff, sizeof(buff), &my_charset_numeric);
@@ -7018,8 +7112,8 @@ int Field_varstring::do_save_field_metad
   return 2;
 }
 
-int Field_varstring::store(const char *from,uint length,
-                           const CHARSET_INFO *cs)
+type_conversion_status Field_varstring::store(const char *from,uint length,
+                                              const CHARSET_INFO *cs)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   uint copy_length;
@@ -7041,15 +7135,13 @@ int Field_varstring::store(const char *f
   else
     int2store(ptr, copy_length);
 
-  if (check_string_copy_error(this, well_formed_error_pos,
-                              cannot_convert_error_pos, from + length, cs))
-    return 2;
-
-  return report_if_important_data(from_end_pos, from + length, TRUE);
+  return check_string_copy_error(well_formed_error_pos,
+                                 cannot_convert_error_pos, from_end_pos,
+                                 from + length, true, cs);
 }
 
 
-int Field_varstring::store(longlong nr, bool unsigned_val)
+type_conversion_status Field_varstring::store(longlong nr, bool unsigned_val)
 {
   char buff[64];
   uint  length;
@@ -7581,7 +7673,8 @@ void Field_blob::put_length(uchar *pos,
 }
 
 
-int Field_blob::store(const char *from,uint length,const CHARSET_INFO *cs)
+type_conversion_status
+Field_blob::store(const char *from,uint length,const CHARSET_INFO *cs)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   uint copy_length, new_length;
@@ -7594,7 +7687,7 @@ int Field_blob::store(const char *from,u
   if (!length)
   {
     memset(ptr, 0, Field_blob::pack_length());
-    return 0;
+    return TYPE_OK;
   }
 
   /*
@@ -7614,7 +7707,7 @@ int Field_blob::store(const char *from,u
     {
       Field_blob::store_length(length);
       bmove(ptr+packlength,(char*) &from,sizeof(char*));
-      return 0;
+      return TYPE_OK;
     }
     if (tmpstr.copy(from, length, cs))
       goto oom_error;
@@ -7634,7 +7727,7 @@ int Field_blob::store(const char *from,u
     Field_blob::store_length(copy_length);
     tmp= value.ptr();
     bmove(ptr + packlength, (uchar*) &tmp, sizeof(char*));
-    return 0;
+    return TYPE_OK;
   }
   /*
     "length" is OK as "nchars" argument to well_formed_copy_nchars as this
@@ -7653,20 +7746,18 @@ int Field_blob::store(const char *from,u
   tmp= value.ptr();
   bmove(ptr+packlength,(uchar*) &tmp,sizeof(char*));
 
-  if (check_string_copy_error(this, well_formed_error_pos,
-                              cannot_convert_error_pos, from + length, cs))
-    return 2;
-
-  return report_if_important_data(from_end_pos, from + length, TRUE);
+  return check_string_copy_error(well_formed_error_pos,
+                                 cannot_convert_error_pos, from_end_pos,
+                                 from + length, true, cs);
 
 oom_error:
   /* Fatal OOM error */
   memset(ptr, 0, Field_blob::pack_length());
-  return -1; 
+  return TYPE_ERR_OOM;
 }
 
 
-int Field_blob::store(double nr)
+type_conversion_status Field_blob::store(double nr)
 {
   const CHARSET_INFO *cs=charset();
   value.set_real(nr, NOT_FIXED_DEC, cs);
@@ -7674,7 +7765,7 @@ int Field_blob::store(double nr)
 }
 
 
-int Field_blob::store(longlong nr, bool unsigned_val)
+type_conversion_status Field_blob::store(longlong nr, bool unsigned_val)
 {
   const CHARSET_INFO *cs=charset();
   value.set_int(nr, unsigned_val, cs);
@@ -8092,31 +8183,32 @@ void Field_geom::sql_type(String &res) c
 }
 
 
-int Field_geom::store(double nr)
+type_conversion_status Field_geom::store(double nr)
 {
   my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
              ER(ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
-  return -1;
+  return TYPE_ERR_BAD_VALUE;
 }
 
 
-int Field_geom::store(longlong nr, bool unsigned_val)
+type_conversion_status Field_geom::store(longlong nr, bool unsigned_val)
 {
   my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
              ER(ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
-  return -1;
+  return TYPE_ERR_BAD_VALUE;
 }
 
 
-int Field_geom::store_decimal(const my_decimal *)
+type_conversion_status Field_geom::store_decimal(const my_decimal *)
 {
   my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
              ER(ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
-  return -1;
+  return TYPE_ERR_BAD_VALUE;
 }
 
 
-int Field_geom::store(const char *from, uint length, const CHARSET_INFO *cs)
+type_conversion_status
+Field_geom::store(const char *from, uint length, const CHARSET_INFO *cs)
 {
   if (!length)
     memset(ptr, 0, Field_blob::pack_length());
@@ -8140,13 +8232,13 @@ int Field_geom::store(const char *from,
     }
     bmove(ptr + packlength, (char*) &from, sizeof(char*));
   }
-  return 0;
+  return TYPE_OK;
 
 err:
   memset(ptr, 0, Field_blob::pack_length());  
   my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
              ER(ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
-  return -1;
+  return TYPE_ERR_BAD_VALUE;
 }
 
 #endif /*HAVE_SPATIAL*/
@@ -8212,10 +8304,12 @@ void Field_enum::store_type(ulonglong va
     (if there isn't a empty value in the enum)
 */
 
-int Field_enum::store(const char *from,uint length,const CHARSET_INFO *cs)
+type_conversion_status
+Field_enum::store(const char *from,uint length,const CHARSET_INFO *cs)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   int err= 0;
+  type_conversion_status ret= TYPE_OK;
   uint32 not_used;
   char buff[STRING_BUFFER_USUAL_SIZE];
   String tmpstr(buff,sizeof(buff), &my_charset_bin);
@@ -8243,35 +8337,36 @@ int Field_enum::store(const char *from,u
       {
 	tmp=0;
 	set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
+        ret= TYPE_WARN_TRUNCATED;
       }
       if (!table->in_use->count_cuted_fields)
-        err= 0;
+        ret= TYPE_OK;
     }
     else
       set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
   }
   store_type((ulonglong) tmp);
-  return err;
+  return ret;
 }
 
 
-int Field_enum::store(double nr)
+type_conversion_status Field_enum::store(double nr)
 {
   return Field_enum::store((longlong) nr, FALSE);
 }
 
 
-int Field_enum::store(longlong nr, bool unsigned_val)
+type_conversion_status Field_enum::store(longlong nr, bool unsigned_val)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int error= 0;
+  type_conversion_status error= TYPE_OK;
   if ((ulonglong) nr > typelib->count || nr == 0)
   {
     set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
     if (nr != 0 || table->in_use->count_cuted_fields)
     {
       nr= 0;
-      error= 1;
+      error= TYPE_WARN_TRUNCATED;
     }
   }
   store_type((ulonglong) (uint) nr);
@@ -8438,11 +8533,13 @@ Field *Field_enum::new_field(MEM_ROOT *r
 */
 
 
-int Field_set::store(const char *from,uint length,const CHARSET_INFO *cs)
+type_conversion_status
+Field_set::store(const char *from,uint length,const CHARSET_INFO *cs)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   bool got_warning= 0;
   int err= 0;
+  type_conversion_status ret= TYPE_OK;
   char *not_used;
   uint not_used2;
   uint32 not_used_offset;
@@ -8469,19 +8566,20 @@ int Field_set::store(const char *from,ui
     {
       tmp=0;      
       set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
+      ret= TYPE_WARN_TRUNCATED;
     }
   }
   else if (got_warning)
     set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
   store_type(tmp);
-  return err;
+  return ret;
 }
 
 
-int Field_set::store(longlong nr, bool unsigned_val)
+type_conversion_status Field_set::store(longlong nr, bool unsigned_val)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
-  int error= 0;
+  type_conversion_status error= TYPE_OK;
   ulonglong max_nr;
 
   if (sizeof(ulonglong)*8 <= typelib->count)
@@ -8493,7 +8591,7 @@ int Field_set::store(longlong nr, bool u
   {
     nr&= max_nr;
     set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
-    error=1;
+    error= TYPE_WARN_TRUNCATED;
   }
   store_type((ulonglong) nr);
   return error;
@@ -8861,7 +8959,8 @@ uint Field_bit::is_equal(Create_field *n
 }
 
                        
-int Field_bit::store(const char *from, uint length, const CHARSET_INFO *cs)
+type_conversion_status
+Field_bit::store(const char *from, uint length, const CHARSET_INFO *cs)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   int delta;
@@ -8869,6 +8968,9 @@ int Field_bit::store(const char *from, u
   for (; length && !*from; from++, length--) ;         // skip left 0's
   delta= bytes_in_rec - length;
 
+  /*
+    *from should probably be treated like uint here see BUG#13727586
+  */
   if (delta < -1 ||
       (delta == -1 && (uchar) *from > ((1 << bit_len) - 1)) ||
       (!bit_len && delta < 0))
@@ -8879,7 +8981,7 @@ int Field_bit::store(const char *from, u
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1);
     else
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-    return 1;
+    return TYPE_WARN_OUT_OF_RANGE;
   }
   /* delta is >= -1 here */
   if (delta > 0)
@@ -8904,17 +9006,17 @@ int Field_bit::store(const char *from, u
     }
     memcpy(ptr, from, bytes_in_rec);
   }
-  return 0;
+  return TYPE_OK;
 }
 
 
-int Field_bit::store(double nr)
+type_conversion_status Field_bit::store(double nr)
 {
   return Field_bit::store((longlong) nr, FALSE);
 }
 
 
-int Field_bit::store(longlong nr, bool unsigned_val)
+type_conversion_status Field_bit::store(longlong nr, bool unsigned_val)
 {
   char buf[8];
 
@@ -8923,11 +9025,12 @@ int Field_bit::store(longlong nr, bool u
 }
 
 
-int Field_bit::store_decimal(const my_decimal *val)
+type_conversion_status Field_bit::store_decimal(const my_decimal *val)
 {
-  int err= 0;
-  longlong i= convert_decimal2longlong(val, 1, &err);
-  return test(err | store(i, TRUE));
+  bool has_overflow= false;
+  longlong i= convert_decimal2longlong(val, 1, &has_overflow);
+  type_conversion_status res= store(i, TRUE);
+  return has_overflow ? TYPE_WARN_OUT_OF_RANGE : res;
 }
 
 
@@ -9299,8 +9402,8 @@ Field_bit_as_char::Field_bit_as_char(uch
 }
 
 
-int Field_bit_as_char::store(const char *from, uint length,
-                             const CHARSET_INFO *cs)
+type_conversion_status Field_bit_as_char::store(const char *from, uint length,
+                                                const CHARSET_INFO *cs)
 {
   ASSERT_COLUMN_MARKED_FOR_WRITE;
   int delta;
@@ -9319,11 +9422,11 @@ int Field_bit_as_char::store(const char
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1);
     else
       set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
-    return 1;
+    return TYPE_WARN_OUT_OF_RANGE;
   }
   memset(ptr, 0, delta);
   memcpy(ptr + delta, from, length);
-  return 0;
+  return TYPE_OK;
 }
 
 
@@ -10346,7 +10449,7 @@ uint32 Field_blob::max_display_length()
 
 bool 
 Field::set_warning(Sql_condition::enum_warning_level level, uint code,
-                   int cut_increment)
+                   int cut_increment) const
 {
   /*
     If this field was created only for type conversion purposes it

=== modified file 'sql/field.h'
--- a/sql/field.h	2012-04-19 09:09:01 +0000
+++ b/sql/field.h	2012-05-07 08:29:18 +0000
@@ -1,7 +1,7 @@
 #ifndef FIELD_INCLUDED
 #define FIELD_INCLUDED
 
-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -99,6 +99,57 @@ enum Derivation
   DERIVATION_EXPLICIT= 0
 };
 
+/**
+  Status when storing a value in a field or converting from one
+  datatype to another. The values should be listed in order of
+  increasing seriousness so that if two type_conversion_status
+  variables are compared, the bigger one is most serious.
+*/
+enum type_conversion_status
+{
+  /// Storage/conversion went fine.
+  TYPE_OK= 0,
+  /**
+    A minor problem when converting between temporal values, e.g.
+    if datetime is converted to date the time information is lost.
+  */
+  TYPE_NOTE_TIME_TRUNCATED,
+  /**
+    Value outside min/max limit of datatype. The min/max value is
+    stored by Field::store() instead (if applicable)
+  */
+  TYPE_WARN_OUT_OF_RANGE,
+  /**
+    Value was stored, but something was cut. What was cut is
+    considered insignificant enough to only issue a note. Example:
+    trying to store a number with 5 decimal places into a field that
+    can only store 3 decimals. The number rounded to 3 decimal places
+    should be stored. Another example: storing the string "foo " into
+    a VARCHAR(3). The string "foo" is stored in this case, so only
+    whitespace is cut.
+  */
+  TYPE_NOTE_TRUNCATED,
+  /**
+    Value was stored, but something was cut. What was cut is
+    considered significant enough to issue a warning. Example: storing
+    the string "foo" into a VARCHAR(2). The string "fo" is stored in
+    this case. Another example: storing the string "2010-01-01foo"
+    into a DATE. The garbage in the end of the string is cut in this
+    case.
+  */
+  TYPE_WARN_TRUNCATED,
+  /// Trying to store NULL in a NOT NULL field.
+  TYPE_ERR_NULL_CONSTRAINT_VIOLATION,
+  /**
+    Store/convert incompatible values, like converting "foo" to a
+    date.
+  */
+  TYPE_ERR_BAD_VALUE,
+  /// Out of memory
+  TYPE_ERR_OOM
+};
+
+
 #define STORAGE_TYPE_MASK 7
 #define COLUMN_FORMAT_MASK 7
 #define COLUMN_FORMAT_SHIFT 3
@@ -107,7 +158,7 @@ enum Derivation
 #define MY_REPERTOIRE_NUMERIC   MY_REPERTOIRE_ASCII
 
 struct st_cache_field;
-int field_conv(Field *to,Field *from);
+type_conversion_status field_conv(Field *to,Field *from);
 
 inline uint get_enum_pack_length(int elements)
 {
@@ -120,6 +171,56 @@ inline uint get_set_pack_length(int elem
   return len > 4 ? 8 : len;
 }
 
+inline type_conversion_status
+decimal_err_to_type_conv_status(int dec_error)
+{
+  if (dec_error & E_DEC_OOM)
+    return TYPE_ERR_OOM;
+
+  if (dec_error & (E_DEC_DIV_ZERO | E_DEC_BAD_NUM))
+    return TYPE_ERR_BAD_VALUE;
+
+  if (dec_error & E_DEC_TRUNCATED)
+    return TYPE_NOTE_TRUNCATED;
+
+  if (dec_error & E_DEC_OVERFLOW)
+    return TYPE_WARN_OUT_OF_RANGE;
+
+  if (dec_error == E_DEC_OK)
+    return TYPE_OK;
+
+  // impossible
+  DBUG_ASSERT(false);
+  return TYPE_ERR_BAD_VALUE;
+}
+
+/**
+  Convert warnings returned from str_to_time() and str_to_datetime()
+  to their corresponding type_conversion_status codes.
+*/
+inline type_conversion_status
+time_warning_to_type_conversion_status(const int warn)
+{
+  if (warn & MYSQL_TIME_NOTE_TRUNCATED)
+    return TYPE_NOTE_TIME_TRUNCATED;
+
+  if (warn & MYSQL_TIME_WARN_OUT_OF_RANGE)
+    return TYPE_WARN_OUT_OF_RANGE;
+
+  if (warn & MYSQL_TIME_WARN_TRUNCATED)
+    return TYPE_NOTE_TRUNCATED;
+
+  if (warn & (MYSQL_TIME_WARN_ZERO_DATE | MYSQL_TIME_WARN_ZERO_IN_DATE))
+    return TYPE_ERR_BAD_VALUE;
+
+  if (warn & MYSQL_TIME_WARN_INVALID_TIMESTAMP)
+    // date was fine but pointed to daylight saving time switch gap
+    return TYPE_OK;
+
+  DBUG_ASSERT(!warn);
+  return TYPE_OK;
+}
+
 #define ASSERT_COLUMN_MARKED_FOR_READ \
 DBUG_ASSERT(!table || (!table->read_set || \
                        bitmap_is_set(table->read_set, field_index)))
@@ -394,11 +495,12 @@ public:
         uchar null_bit_arg, utype unireg_check_arg,
         const char *field_name_arg);
   virtual ~Field() {}
+
   /* Store functions returns 1 on overflow and -1 on fatal error */
-  virtual int  store(const char *to, uint length,
-                     const CHARSET_INFO *cs)=0;
-  virtual int  store(double nr)=0;
-  virtual int  store(longlong nr, bool unsigned_val)=0;
+  virtual type_conversion_status store(const char *to, uint length,
+                                       const CHARSET_INFO *cs)=0;
+  virtual type_conversion_status store(double nr)=0;
+  virtual type_conversion_status store(longlong nr, bool unsigned_val)=0;
   /**
     Store a temporal value in packed longlong format into a field.
     The packed value is compatible with TIME_to_longlong_time_packed(),
@@ -410,8 +512,11 @@ public:
     @retval false on success
     @retval true  on error
   */
-  virtual int  store_packed(longlong nr) { return store(nr, 0); }
-  virtual int  store_decimal(const my_decimal *d)=0;
+  virtual type_conversion_status store_packed(longlong nr)
+  {
+    return store(nr, 0);
+  }
+  virtual type_conversion_status store_decimal(const my_decimal *d)=0;
   /**
     Store MYSQL_TIME value with the given amount of decimal digits
     into a field.
@@ -427,7 +532,7 @@ public:
     @retval false  on success
     @retval true   on error
   */
-  virtual int store_time(MYSQL_TIME *ltime, uint8 dec);
+  virtual type_conversion_status store_time(MYSQL_TIME *ltime, uint8 dec);
   /**
     Store MYSQL_TYPE value into a field when the number of fractional
     digits is not important or is not know.
@@ -436,12 +541,13 @@ public:
     @retval false   on success
     @retval true   on error
   */
-  int store_time(MYSQL_TIME *ltime)
+  type_conversion_status store_time(MYSQL_TIME *ltime)
   {
     return store_time(ltime, 0);
   }
-  int store(const char *to, uint length, const CHARSET_INFO *cs,
-            enum_check_fields check_level);
+  type_conversion_status store(const char *to, uint length,
+                               const CHARSET_INFO *cs,
+                               enum_check_fields check_level);
   virtual double val_real(void)=0;
   virtual longlong val_int(void)=0;
   /**
@@ -564,7 +670,11 @@ public:
     return pack_length();
   };
 
-  virtual int reset(void) { memset(ptr, 0, pack_length()); return 0; }
+  virtual type_conversion_status reset(void)
+  {
+    memset(ptr, 0, pack_length());
+    return TYPE_OK;
+  }
   virtual void reset_fields() {}
   /**
     Returns timestamp value in "struct timeval" format.
@@ -962,12 +1072,16 @@ public:
   virtual uint repertoire(void) const { return MY_REPERTOIRE_UNICODE30; }
   virtual void set_derivation(enum Derivation derivation_arg) { }
   bool set_warning(Sql_condition::enum_warning_level, unsigned int code,
-                   int cuted_increment);
+                   int cuted_increment) const;
   inline bool check_overflow(int op_result)
   {
     return (op_result == E_DEC_OVERFLOW);
   }
-  int warn_if_overflow(int op_result);
+  inline bool check_truncated(int op_result)
+  {
+    return (op_result == E_DEC_TRUNCATED);
+  }
+  bool warn_if_overflow(int op_result);
   void init(TABLE *table_arg)
   {
     orig_table= table= table_arg;
@@ -987,7 +1101,7 @@ public:
   virtual uint is_equal(Create_field *new_field);
   /* convert decimal to longlong with overflow check */
   longlong convert_decimal2longlong(const my_decimal *val, bool unsigned_flag,
-                                    int *err);
+                                    bool *has_overflow);
   /* The max. number of characters */
   virtual uint32 char_length()
   {
@@ -1250,8 +1364,8 @@ public:
   friend class Create_field;
   uint decimals() const { return (uint) dec; }
   bool eq_def(Field *field);
-  int store_decimal(const my_decimal *);
-  int store_time(MYSQL_TIME *ltime, uint8 dec);
+  type_conversion_status store_decimal(const my_decimal *);
+  type_conversion_status store_time(MYSQL_TIME *ltime, uint8 dec);
   my_decimal *val_decimal(my_decimal *);
   bool get_date(MYSQL_TIME *ltime, uint fuzzydate);
   bool get_time(MYSQL_TIME *ltime);
@@ -1263,11 +1377,13 @@ public:
                           field_metadata, length));
     return length;
   }
-  int check_int(const CHARSET_INFO *cs, const char *str, int length,
-                const char *int_end, int error);
-  bool get_int(const CHARSET_INFO *cs, const char *from, uint len, 
-               longlong *rnd, ulonglong unsigned_max, 
-               longlong signed_min, longlong signed_max);
+  type_conversion_status check_int(const CHARSET_INFO *cs,
+                                   const char *str, int length,
+                                   const char *int_end, int error);
+  type_conversion_status get_int(const CHARSET_INFO *cs,
+                                 const char *from, uint len,
+                                 longlong *rnd, ulonglong unsigned_max,
+                                 longlong signed_min, longlong signed_max);
 };
 
 
@@ -1286,10 +1402,11 @@ public:
   }
   uint decimals() const { return NOT_FIXED_DEC; }
   void make_field(Send_field *field);
-  int  store(double nr);
-  int  store(longlong nr, bool unsigned_val)=0;
-  int  store_decimal(const my_decimal *);
-  int  store(const char *to,uint length, const CHARSET_INFO *cs)=0;
+  type_conversion_status store(double nr);
+  type_conversion_status store(longlong nr, bool unsigned_val)=0;
+  type_conversion_status store_decimal(const my_decimal *);
+  type_conversion_status store(const char *to, uint length,
+                               const CHARSET_INFO *cs)=0;
   uint repertoire(void) const
   {
     return my_charset_repertoire(field_charset);
@@ -1313,8 +1430,16 @@ public:
 class Field_longstr :public Field_str
 {
 protected:
-  int report_if_important_data(const char *ptr, const char *end,
-                               bool count_spaces);
+  type_conversion_status report_if_important_data(const char *ptr,
+                                                  const char *end,
+                                                  bool count_spaces) const;
+  type_conversion_status
+    check_string_copy_error(const char *well_formed_error_pos,
+                            const char *cannot_convert_error_pos,
+                            const char *from_end_pos,
+                            const char *end,
+                            bool count_spaces,
+                            const CHARSET_INFO *cs) const;
 public:
   Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
                 uchar null_bit_arg, utype unireg_check_arg,
@@ -1323,7 +1448,7 @@ public:
                field_name_arg, charset_arg)
     {}
 
-  int store_decimal(const my_decimal *d);
+  type_conversion_status store_decimal(const my_decimal *d);
   uint32 max_data_length() const;
 };
 
@@ -1340,12 +1465,12 @@ public:
                field_name_arg, dec_arg, zero_arg, unsigned_arg),
     not_fixed(dec_arg >= NOT_FIXED_DEC)
     {}
-  int store_decimal(const my_decimal *);
-  int store_time(MYSQL_TIME *ltime, uint8 dec);
+  type_conversion_status store_decimal(const my_decimal *);
+  type_conversion_status store_time(MYSQL_TIME *ltime, uint8 dec);
   my_decimal *val_decimal(my_decimal *);
   bool get_date(MYSQL_TIME *ltime, uint fuzzydate);
   bool get_time(MYSQL_TIME *ltime);
-  int truncate(double *nr, double max_length);
+  bool truncate(double *nr, double max_length);
   uint32 max_display_length() { return field_length; }
   virtual const uchar *unpack(uchar* to, const uchar *from,
                               uint param_data, bool low_byte_first);
@@ -1367,10 +1492,11 @@ public:
   enum_field_types type() const { return MYSQL_TYPE_DECIMAL;}
   enum ha_base_keytype key_type() const
   { return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; }
-  int reset(void);
-  int store(const char *to,uint length, const CHARSET_INFO *charset);
-  int store(double nr);
-  int store(longlong nr, bool unsigned_val);
+  type_conversion_status reset(void);
+  type_conversion_status store(const char *to, uint length,
+                               const CHARSET_INFO *charset);
+  type_conversion_status store(double nr);
+  type_conversion_status store(longlong nr, bool unsigned_val);
   double val_real(void);
   longlong val_int(void);
   String *val_str(String*,String *);
@@ -1405,6 +1531,7 @@ class Field_new_decimal :public Field_nu
 private:
   int do_save_field_metadata(uchar *first_byte);
 public:
+
   /* The maximum number of decimal digits can be stored */
   uint precision;
   uint bin_size;
@@ -1424,14 +1551,15 @@ public:
   enum_field_types type() const { return MYSQL_TYPE_NEWDECIMAL;}
   enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
   Item_result result_type () const { return DECIMAL_RESULT; }
-  int  reset(void);
-  bool store_value(const my_decimal *decimal_value);
+  type_conversion_status reset(void);
+  type_conversion_status store_value(const my_decimal *decimal_value);
   void set_value_on_overflow(my_decimal *decimal_value, bool sign);
-  int  store(const char *to, uint length, const CHARSET_INFO *charset);
-  int  store(double nr);
-  int  store(longlong nr, bool unsigned_val);
-  int store_time(MYSQL_TIME *ltime, uint8 dec);
-  int  store_decimal(const my_decimal *);
+  type_conversion_status store(const char *to, uint length,
+                               const CHARSET_INFO *charset);
+  type_conversion_status store(double nr);
+  type_conversion_status store(longlong nr, bool unsigned_val);
+  type_conversion_status store_time(MYSQL_TIME *ltime, uint8 dec);
+  type_conversion_status store_decimal(const my_decimal *);
   double val_real(void);
   longlong val_int(void);
   my_decimal *val_decimal(my_decimal *);
@@ -1477,10 +1605,11 @@ public:
   enum_field_types type() const { return MYSQL_TYPE_TINY;}
   enum ha_base_keytype key_type() const
     { return unsigned_flag ? HA_KEYTYPE_BINARY : HA_KEYTYPE_INT8; }
-  int store(const char *to,uint length, const CHARSET_INFO *charset);
-  int store(double nr);
-  int store(longlong nr, bool unsigned_val);
-  int reset(void) { ptr[0]=0; return 0; }
+  type_conversion_status store(const char *to, uint length,
+                               const CHARSET_INFO *charset);
+  type_conversion_status store(double nr);
+  type_conversion_status store(longlong nr, bool unsigned_val);
+  type_conversion_status reset(void) { ptr[0]=0; return TYPE_OK; }
   double val_real(void);
   longlong val_int(void);
   String *val_str(String*,String *);
@@ -1533,10 +1662,11 @@ public:
   enum_field_types type() const { return MYSQL_TYPE_SHORT;}
   enum ha_base_keytype key_type() const
     { return unsigned_flag ? HA_KEYTYPE_USHORT_INT : HA_KEYTYPE_SHORT_INT;}
-  int store(const char *to,uint length, const CHARSET_INFO *charset);
-  int store(double nr);
-  int store(longlong nr, bool unsigned_val);
-  int reset(void) { ptr[0]=ptr[1]=0; return 0; }
+  type_conversion_status store(const char *to, uint length,
+                               const CHARSET_INFO *charset);
+  type_conversion_status store(double nr);
+  type_conversion_status store(longlong nr, bool unsigned_val);
+  type_conversion_status reset(void) { ptr[0]=ptr[1]=0; return TYPE_OK; }
   double val_real(void);
   longlong val_int(void);
   String *val_str(String*,String *);
@@ -1581,10 +1711,15 @@ public:
   enum_field_types type() const { return MYSQL_TYPE_INT24;}
   enum ha_base_keytype key_type() const
     { return unsigned_flag ? HA_KEYTYPE_UINT24 : HA_KEYTYPE_INT24; }
-  int store(const char *to,uint length, const CHARSET_INFO *charset);
-  int store(double nr);
-  int store(longlong nr, bool unsigned_val);
-  int reset(void) { ptr[0]=ptr[1]=ptr[2]=0; return 0; }
+  type_conversion_status store(const char *to, uint length,
+                               const CHARSET_INFO *charset);
+  type_conversion_status store(double nr);
+  type_conversion_status store(longlong nr, bool unsigned_val);
+  type_conversion_status reset(void)
+  {
+    ptr[0]=ptr[1]=ptr[2]=0;
+    return TYPE_OK;
+  }
   double val_real(void);
   longlong val_int(void);
   String *val_str(String*,String *);
@@ -1618,6 +1753,9 @@ public:
 
 class Field_long :public Field_num {
 public:
+
+  static const int PACK_LENGTH= 4;
+
   Field_long(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
 	     uchar null_bit_arg,
 	     enum utype unireg_check_arg, const char *field_name_arg,
@@ -1635,17 +1773,22 @@ public:
   enum_field_types type() const { return MYSQL_TYPE_LONG;}
   enum ha_base_keytype key_type() const
     { return unsigned_flag ? HA_KEYTYPE_ULONG_INT : HA_KEYTYPE_LONG_INT; }
-  int store(const char *to,uint length, const CHARSET_INFO *charset);
-  int store(double nr);
-  int store(longlong nr, bool unsigned_val);
-  int reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; }
+  type_conversion_status store(const char *to, uint length,
+                               const CHARSET_INFO *charset);
+  type_conversion_status store(double nr);
+  type_conversion_status store(longlong nr, bool unsigned_val);
+  type_conversion_status reset(void)
+  {
+    ptr[0]=ptr[1]=ptr[2]=ptr[3]=0;
+    return TYPE_OK;
+  }
   double val_real(void);
   longlong val_int(void);
   bool send_binary(Protocol *protocol);
   String *val_str(String*,String *);
   int cmp(const uchar *,const uchar *);
   void sort_string(uchar *buff,uint length);
-  uint32 pack_length() const { return 4; }
+  uint32 pack_length() const { return PACK_LENGTH; }
   void sql_type(String &str) const;
   uint32 max_display_length() { return MY_INT32_NUM_DECIMAL_DIGITS; }
   Field_long *clone(MEM_ROOT *mem_root) const {
@@ -1692,13 +1835,14 @@ public:
   enum_field_types type() const { return MYSQL_TYPE_LONGLONG;}
   enum ha_base_keytype key_type() const
     { return unsigned_flag ? HA_KEYTYPE_ULONGLONG : HA_KEYTYPE_LONGLONG; }
-  int store(const char *to,uint length, const CHARSET_INFO *charset);
-  int store(double nr);
-  int store(longlong nr, bool unsigned_val);
-  int reset(void)
+  type_conversion_status store(const char *to, uint length,
+                               const CHARSET_INFO *charset);
+  type_conversion_status store(double nr);
+  type_conversion_status store(longlong nr, bool unsigned_val);
+  type_conversion_status reset(void)
   {
     ptr[0]=ptr[1]=ptr[2]=ptr[3]=ptr[4]=ptr[5]=ptr[6]=ptr[7]=0;
-    return 0;
+    return TYPE_OK;
   }
   double val_real(void);
   longlong val_int(void);
@@ -1751,10 +1895,15 @@ public:
     {}
   enum_field_types type() const { return MYSQL_TYPE_FLOAT;}
   enum ha_base_keytype key_type() const { return HA_KEYTYPE_FLOAT; }
-  int store(const char *to,uint length, const CHARSET_INFO *charset);
-  int store(double nr);
-  int store(longlong nr, bool unsigned_val);
-  int reset(void) { memset(ptr, 0, sizeof(float)); return 0; }
+  type_conversion_status store(const char *to, uint length,
+                               const CHARSET_INFO *charset);
+  type_conversion_status store(double nr);
+  type_conversion_status store(longlong nr, bool unsigned_val);
+  type_conversion_status reset(void)
+  {
+    memset(ptr, 0, sizeof(float));
+    return TYPE_OK;
+  }
   double val_real(void);
   longlong val_int(void);
   String *val_str(String*,String *);
@@ -1799,10 +1948,15 @@ public:
     {not_fixed= not_fixed_arg; }
   enum_field_types type() const { return MYSQL_TYPE_DOUBLE;}
   enum ha_base_keytype key_type() const { return HA_KEYTYPE_DOUBLE; }
-  int  store(const char *to,uint length, const CHARSET_INFO *charset);
-  int  store(double nr);
-  int  store(longlong nr, bool unsigned_val);
-  int reset(void) { memset(ptr, 0, sizeof(double)); return 0; }
+  type_conversion_status store(const char *to, uint length,
+                               const CHARSET_INFO *charset);
+  type_conversion_status store(double nr);
+  type_conversion_status store(longlong nr, bool unsigned_val);
+  type_conversion_status reset(void)
+  {
+    memset(ptr, 0, sizeof(double));
+    return TYPE_OK;
+  }
   double val_real(void);
   longlong val_int(void);
   String *val_str(String*,String *);
@@ -1837,12 +1991,24 @@ public:
 	       unireg_check_arg, field_name_arg, cs)
     {}
   enum_field_types type() const { return MYSQL_TYPE_NULL;}
-  int  store(const char *to, uint length, const CHARSET_INFO *cs)
-  { null[0]=1; return 0; }
-  int store(double nr)   { null[0]=1; return 0; }
-  int store(longlong nr, bool unsigned_val) { null[0]=1; return 0; }
-  int store_decimal(const my_decimal *d)  { null[0]=1; return 0; }
-  int reset(void)	  { return 0; }
+  type_conversion_status store(const char *to, uint length,
+                               const CHARSET_INFO *cs)
+  {
+    null[0]= 1;
+    return TYPE_OK;
+  }
+  type_conversion_status store(double nr)   { null[0]=1; return TYPE_OK; }
+  type_conversion_status store(longlong nr, bool unsigned_val)
+  {
+    null[0]=1;
+    return TYPE_OK;
+  }
+  type_conversion_status store_decimal(const my_decimal *d)
+  {
+    null[0]=1;
+    return TYPE_OK;
+  }
+  type_conversion_status reset(void)       { return TYPE_OK; }
   double val_real(void)		{ return 0.0;}
   longlong val_int(void)	{ return 0;}
   my_decimal *val_decimal(my_decimal *) { return 0; }
@@ -1888,7 +2054,8 @@ protected:
     @retval     false   In case of success.
     @retval     true    In case of error.
   */
-  virtual int store_internal(const MYSQL_TIME *ltime, int *error)= 0;
+  virtual type_conversion_status store_internal(const MYSQL_TIME *ltime,
+                                                int *error)= 0;
 
   /**
     Low level routine to store a MYSQL_TIME value into a field
@@ -1899,7 +2066,8 @@ protected:
     @retval     false   In case of success.
     @retval     true    In case of error.    
   */
-  virtual int store_internal_with_round(MYSQL_TIME *ltime, int *warnings)= 0;
+  virtual type_conversion_status store_internal_with_round(MYSQL_TIME *ltime,
+                                                           int *warnings)= 0;
 
   /**
     Store a temporal value in lldiv_t into a field,
@@ -1910,7 +2078,7 @@ protected:
     @retval     false   In case of success.
     @retval     true    In case of error.    
   */
-  int store_lldiv_t(const lldiv_t *lld, int *warning);
+  type_conversion_status store_lldiv_t(const lldiv_t *lld, int *warning);
 
   /**
     Convert a string to MYSQL_TIME, according to the field type.
@@ -1920,8 +2088,8 @@ protected:
     @param IN   cs      String character set
     @param OUT  ltime   The value is stored here
     @param OUT  status  Conversion status
-    @retval     false   On success
-    @retval     true    On error
+    @retval     false   Conversion went fine, ltime contains a valid time
+    @retval     true    Conversion failed, ltime was reset and contains nothing
   */
   virtual bool convert_str_to_TIME(const char *str, uint len,
                                    const CHARSET_INFO *cs,
@@ -1940,9 +2108,11 @@ protected:
     @retval     false         On success
     @retval     true          On error
   */
-  virtual int convert_number_to_TIME(longlong nr, bool unsigned_val,
-                                     int nanoseconds,
-                                     MYSQL_TIME *ltime, int *warning)= 0;
+  virtual type_conversion_status convert_number_to_TIME(longlong nr,
+                                                        bool unsigned_val,
+                                                        int nanoseconds,
+                                                        MYSQL_TIME *ltime,
+                                                        int *warning)= 0;
 
   /**
     Convert an integer number into MYSQL_TIME, according to the field type.
@@ -2054,10 +2224,11 @@ public:
   const CHARSET_INFO *charset() const { return &my_charset_numeric; }
   bool can_be_compared_as_longlong() const { return true; }
   bool binary() const { return true; }
-  int store(const char *str, uint len, const CHARSET_INFO *cs);
-  int store_decimal(const my_decimal *decimal);
-  int store(longlong nr, bool unsigned_val);
-  int store(double nr);
+  type_conversion_status store(const char *str, uint len,
+                               const CHARSET_INFO *cs);
+  type_conversion_status store_decimal(const my_decimal *decimal);
+  type_conversion_status store(longlong nr, bool unsigned_val);
+  type_conversion_status store(double nr);
   double val_real() // FSP-enable types redefine it.
   {
     return (double) val_int();
@@ -2086,11 +2257,14 @@ protected:
   */
   bool get_internal_check_zero(MYSQL_TIME *ltime, uint fuzzydate);
   
-  int convert_number_to_TIME(longlong nr, bool unsigned_val, int nanoseconds,
-                             MYSQL_TIME *ltime, int *warning);
+  type_conversion_status convert_number_to_TIME(longlong nr, bool unsigned_val,
+                                                int nanoseconds,
+                                                MYSQL_TIME *ltime,
+                                                int *warning);
   bool convert_str_to_TIME(const char *str, uint len, const CHARSET_INFO *cs,
                            MYSQL_TIME *ltime, MYSQL_TIME_STATUS *status);
-  int store_internal_with_round(MYSQL_TIME *ltime, int *warnings);
+  type_conversion_status store_internal_with_round(MYSQL_TIME *ltime,
+                                                   int *warnings);
 public:
   /**
     Constructor for Field_temporal
@@ -2124,7 +2298,7 @@ public:
                     NONE, field_name_arg, int_length_arg, dec_arg)
     { }
   bool send_binary(Protocol *protocol);
-  int store_time(MYSQL_TIME *ltime, uint8 dec);
+  type_conversion_status store_time(MYSQL_TIME *ltime, uint8 dec);
   String *val_str(String *, String *);
   longlong val_time_temporal();
   longlong val_date_temporal();
@@ -2261,7 +2435,7 @@ public:
 class Field_timestamp :public Field_temporal_with_date_and_time {
 protected:
   ulonglong date_flags(const THD *thd);
-  int store_internal(const MYSQL_TIME *ltime, int *error);
+  type_conversion_status store_internal(const MYSQL_TIME *ltime, int *error);
   bool get_date_internal(MYSQL_TIME *ltime);
   void store_timestamp_internal(const struct timeval *tm);
 public:
@@ -2272,8 +2446,12 @@ public:
   Field_timestamp(bool maybe_null_arg, const char *field_name_arg);
   enum_field_types type() const { return MYSQL_TYPE_TIMESTAMP;}
   enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
-  int store_packed(longlong nr);
-  int  reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; }
+  type_conversion_status store_packed(longlong nr);
+  type_conversion_status reset(void)
+  {
+    ptr[0]=ptr[1]=ptr[2]=ptr[3]=0;
+    return TYPE_OK;
+  }
   longlong val_int(void);
   int cmp(const uchar *,const uchar *);
   void sort_string(uchar *buff,uint length);
@@ -2312,7 +2490,7 @@ public:
 class Field_timestampf :public Field_temporal_with_date_and_timef {
 protected:
   bool get_date_internal(MYSQL_TIME *ltime);
-  int store_internal(const MYSQL_TIME *ltime, int *error);
+  type_conversion_status store_internal(const MYSQL_TIME *ltime, int *error);
   ulonglong date_flags(const THD *thd);
   void store_timestamp_internal(const struct timeval *tm);
 public:
@@ -2365,8 +2543,8 @@ public:
     DBUG_RETURN(tmp);
   }
 
-  int  reset();
-  int  store_packed(longlong nr);
+  type_conversion_status reset();
+  type_conversion_status store_packed(longlong nr);
   bool get_date(MYSQL_TIME *ltime, uint fuzzydate);
   void sql_type(String &str) const;
 
@@ -2383,10 +2561,11 @@ public:
 		unireg_check_arg, field_name_arg, 1, 1)
     {}
   enum_field_types type() const { return MYSQL_TYPE_YEAR;}
-  int  store(const char *to,uint length, const CHARSET_INFO *charset);
-  int  store(double nr);
-  int  store(longlong nr, bool unsigned_val);
-  int store_time(MYSQL_TIME *ltime, uint8 dec);
+  type_conversion_status store(const char *to,uint length,
+                               const CHARSET_INFO *charset);
+  type_conversion_status store(double nr);
+  type_conversion_status store(longlong nr, bool unsigned_val);
+  type_conversion_status store_time(MYSQL_TIME *ltime, uint8 dec);
   double val_real(void);
   longlong val_int(void);
   String *val_str(String*,String *);
@@ -2406,9 +2585,10 @@ public:
 
 class Field_newdate :public Field_temporal_with_date {
 protected:
+  static const int PACK_LENGTH= 3;
   ulonglong date_flags(const THD *thd);
   bool get_date_internal(MYSQL_TIME *ltime);
-  int store_internal(const MYSQL_TIME *ltime, int *error);
+  type_conversion_status store_internal(const MYSQL_TIME *ltime, int *error);
 
 public:
   Field_newdate(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
@@ -2424,8 +2604,12 @@ public:
   enum_field_types type() const { return MYSQL_TYPE_DATE;}
   enum_field_types real_type() const { return MYSQL_TYPE_NEWDATE; }
   enum ha_base_keytype key_type() const { return HA_KEYTYPE_UINT24; }
-  int reset(void) { ptr[0]=ptr[1]=ptr[2]=0; return 0; }
-  int store_packed(longlong nr);
+  type_conversion_status reset(void)
+  {
+    ptr[0]=ptr[1]=ptr[2]=0;
+    return TYPE_OK;
+  }
+  type_conversion_status store_packed(longlong nr);
   longlong val_int(void);
   longlong val_time_temporal();
   longlong val_date_temporal();
@@ -2433,7 +2617,7 @@ public:
   bool send_binary(Protocol *protocol);
   int cmp(const uchar *,const uchar *);
   void sort_string(uchar *buff,uint length);
-  uint32 pack_length() const { return 3; }
+  uint32 pack_length() const { return PACK_LENGTH; }
   void sql_type(String &str) const;
   bool zero_pack() const { return 1; }
   bool get_date(MYSQL_TIME *ltime,uint fuzzydate);
@@ -2459,18 +2643,27 @@ class Field_time_common :public Field_te
 protected:
   bool convert_str_to_TIME(const char *str, uint len, const CHARSET_INFO *cs,
                            MYSQL_TIME *ltime, MYSQL_TIME_STATUS *status);
-  int convert_number_to_TIME(longlong nr, bool unsigned_val, int nanoseconds,
-                             MYSQL_TIME *ltime, int *warning);
+  /**
+    @todo: convert_number_to_TIME returns conversion status through
+    two different interfaces: return value and warning. It should be
+    refactored to only use return value.
+   */
+  type_conversion_status convert_number_to_TIME(longlong nr, bool unsigned_val,
+                                                int nanoseconds,
+                                                MYSQL_TIME *ltime,
+                                                int *warning);
   /**
     Low-level function to store MYSQL_TIME value.
     The value must be rounded or truncated according to decimals().
   */
-  virtual int store_internal(const MYSQL_TIME *ltime, int *error)= 0;
+  virtual type_conversion_status store_internal(const MYSQL_TIME *ltime,
+                                                int *error)= 0;
   /**
     Function to store time value.
     The value is rounded according to decimals().
   */
-  virtual int store_internal_with_round(MYSQL_TIME *ltime, int *warnings);
+  virtual type_conversion_status store_internal_with_round(MYSQL_TIME *ltime,
+                                                           int *warnings);
 public:
   /**
     Constructor for Field_time_common
@@ -2499,7 +2692,7 @@ public:
     :Field_temporal((uchar *) 0, maybe_null_arg ? (uchar *) "" : 0, 0,
                     NONE, field_name_arg, MAX_TIME_WIDTH, dec_arg)
     { }
-  int store_time(MYSQL_TIME *ltime, uint8 dec);
+  type_conversion_status store_time(MYSQL_TIME *ltime, uint8 dec);
   String *val_str(String*, String *);
   bool get_date(MYSQL_TIME *ltime, uint fuzzydate);
   longlong val_date_temporal();
@@ -2513,7 +2706,7 @@ public:
 */
 class Field_time :public Field_time_common {
 protected:
-  int store_internal(const MYSQL_TIME *ltime, int *error);
+  type_conversion_status store_internal(const MYSQL_TIME *ltime, int *error);
 public:
   Field_time(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
 	     enum utype unireg_check_arg, const char *field_name_arg)
@@ -2526,8 +2719,12 @@ public:
     { }
   enum_field_types type() const { return MYSQL_TYPE_TIME;}
   enum ha_base_keytype key_type() const { return HA_KEYTYPE_INT24; }
-  int store_packed(longlong nr);
-  int reset(void) { ptr[0]=ptr[1]=ptr[2]=0; return 0; }
+  type_conversion_status store_packed(longlong nr);
+  type_conversion_status reset(void)
+  {
+    ptr[0]=ptr[1]=ptr[2]=0;
+    return TYPE_OK;
+  }
   longlong val_int(void);
   longlong val_time_temporal();
   bool get_time(MYSQL_TIME *ltime);
@@ -2558,7 +2755,7 @@ private:
     return 1;
   }
 protected:
-  int store_internal(const MYSQL_TIME *ltime, int *error);
+  type_conversion_status store_internal(const MYSQL_TIME *ltime, int *error);
 public:
   /**
     Constructor for Field_timef
@@ -2599,8 +2796,8 @@ public:
   enum_field_types type() const { return MYSQL_TYPE_TIME;}
   enum_field_types real_type() const { return MYSQL_TYPE_TIME2; }
   enum_field_types binlog_type() const { return MYSQL_TYPE_TIME2; }
-  int store_packed(longlong nr);
-  int reset();
+  type_conversion_status store_packed(longlong nr);
+  type_conversion_status reset();
   double val_real();
   longlong val_int();
   longlong val_time_temporal();
@@ -2638,7 +2835,7 @@ public:
 */
 class Field_datetime :public Field_temporal_with_date_and_time {
 protected:
-  int store_internal(const MYSQL_TIME *ltime, int *error);
+  type_conversion_status store_internal(const MYSQL_TIME *ltime, int *error);
   bool get_date_internal(MYSQL_TIME *ltime);
   ulonglong date_flags(const THD *thd);
   void store_timestamp_internal(const struct timeval *tm);
@@ -2686,12 +2883,12 @@ public:
   enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONGLONG; }
 #endif
   using Field_temporal_with_date_and_time::store; // Make -Woverloaded-virtual
-  int  store(longlong nr, bool unsigned_val);
-  int  store_packed(longlong nr);
-  int reset(void)
+  type_conversion_status store(longlong nr, bool unsigned_val);
+  type_conversion_status store_packed(longlong nr);
+  type_conversion_status reset(void)
   {
     ptr[0]=ptr[1]=ptr[2]=ptr[3]=ptr[4]=ptr[5]=ptr[6]=ptr[7]=0;
-    return 0;
+    return TYPE_OK;
   }
   longlong val_int(void);
   String *val_str(String*,String *);
@@ -2731,7 +2928,7 @@ public:
 class Field_datetimef :public Field_temporal_with_date_and_timef {
 protected:
   bool get_date_internal(MYSQL_TIME *ltime);
-  int store_internal(const MYSQL_TIME *ltime, int *error);
+  type_conversion_status store_internal(const MYSQL_TIME *ltime, int *error);
   ulonglong date_flags(const THD *thd);
   void store_timestamp_internal(const struct timeval *tm);
 
@@ -2791,8 +2988,8 @@ public:
   }
   bool zero_pack() const { return 1; }
 
-  int store_packed(longlong nr);
-  int reset();
+  type_conversion_status store_packed(longlong nr);
+  type_conversion_status reset();
   longlong val_date_temporal();
   bool get_date(MYSQL_TIME *ltime, uint fuzzydate);
   void sql_type(String &str) const;
@@ -2827,15 +3024,17 @@ public:
   enum ha_base_keytype key_type() const
     { return binary() ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; }
   bool zero_pack() const { return 0; }
-  int reset(void)
+  type_conversion_status reset(void)
   {
     charset()->cset->fill(charset(),(char*) ptr, field_length,
                           (has_charset() ? ' ' : 0));
-    return 0;
+    return TYPE_OK;
   }
-  int store(const char *to,uint length, const CHARSET_INFO *charset);
-  int store(longlong nr, bool unsigned_val);
-  int store(double nr) { return Field_str::store(nr); } /* QQ: To be deleted */
+  type_conversion_status store(const char *to,uint length,
+                               const CHARSET_INFO *charset);
+  type_conversion_status store(longlong nr, bool unsigned_val);
+  /* QQ: To be deleted */
+  type_conversion_status store(double nr) { return Field_str::store(nr); }
   double val_real(void);
   longlong val_int(void);
   String *val_str(String*,String *);
@@ -2915,7 +3114,11 @@ public:
   enum ha_base_keytype key_type() const;
   uint row_pack_length() const { return field_length; }
   bool zero_pack() const { return 0; }
-  int  reset(void) { memset(ptr, 0, field_length+length_bytes); return 0; }
+  type_conversion_status reset(void)
+  {
+    memset(ptr, 0, field_length+length_bytes);
+    return TYPE_OK;
+  }
   uint32 pack_length() const { return (uint32) field_length+length_bytes; }
   uint32 key_length() const { return (uint32) field_length; }
   uint32 sort_length() const
@@ -2923,9 +3126,11 @@ public:
     return (uint32) field_length + (field_charset == &my_charset_bin ?
                                     length_bytes : 0);
   }
-  int  store(const char *to,uint length, const CHARSET_INFO *charset);
-  int  store(longlong nr, bool unsigned_val);
-  int  store(double nr) { return Field_str::store(nr); } /* QQ: To be deleted */
+  type_conversion_status store(const char *to,uint length,
+                               const CHARSET_INFO *charset);
+  type_conversion_status store(longlong nr, bool unsigned_val);
+  /* QQ: To be deleted */
+  type_conversion_status store(double nr) { return Field_str::store(nr); }
   double val_real(void);
   longlong val_int(void);
   String *val_str(String*,String *);
@@ -3020,9 +3225,10 @@ public:
   bool match_collation_to_optimize_range() const { return true; }
   enum ha_base_keytype key_type() const
     { return binary() ? HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2; }
-  int  store(const char *to,uint length, const CHARSET_INFO *charset);
-  int  store(double nr);
-  int  store(longlong nr, bool unsigned_val);
+  type_conversion_status store(const char *to, uint length,
+                               const CHARSET_INFO *charset);
+  type_conversion_status store(double nr);
+  type_conversion_status store(longlong nr, bool unsigned_val);
   double val_real(void);
   longlong val_int(void);
   String *val_str(String*,String *);
@@ -3055,7 +3261,11 @@ public:
   {
     return (uint32) (((ulonglong) 1 << (packlength*8)) -1);
   }
-  int reset(void) { memset(ptr, 0, packlength+sizeof(uchar*)); return 0; }
+  type_conversion_status reset(void)
+  {
+    memset(ptr, 0, packlength+sizeof(uchar*));
+    return TYPE_OK;
+  }
   void reset_fields() { memset(&value, 0, sizeof(value)); }
   uint32 get_field_buffer_size(void) { return value.alloced_length(); }
 #ifndef WORDS_BIGENDIAN
@@ -3143,7 +3353,7 @@ public:
   uint max_packed_col_length(uint max_length);
   void free() { value.free(); }
   inline void clear_temporary() { memset(&value, 0, sizeof(value)); }
-  friend int field_conv(Field *to,Field *from);
+  friend type_conversion_status field_conv(Field *to,Field *from);
   bool has_charset(void) const
   { return charset() == &my_charset_bin ? FALSE : TRUE; }
   uint32 max_display_length();
@@ -3176,16 +3386,23 @@ public:
   enum_field_types type() const { return MYSQL_TYPE_GEOMETRY; }
   bool match_collation_to_optimize_range() const { return false; }
   void sql_type(String &str) const;
-  int  store(const char *to, uint length, const CHARSET_INFO *charset);
-  int  store(double nr);
-  int  store(longlong nr, bool unsigned_val);
-  int  store_decimal(const my_decimal *);
+  type_conversion_status store(const char *to, uint length,
+                               const CHARSET_INFO *charset);
+  type_conversion_status store(double nr);
+  type_conversion_status store(longlong nr, bool unsigned_val);
+  type_conversion_status store_decimal(const my_decimal *);
 
   /**
     Non-nullable GEOMETRY types cannot have defaults,
     but the underlying blob must still be reset.
    */
-  int reset(void) { return Field_blob::reset() || !maybe_null(); }
+  type_conversion_status reset(void)
+  {
+    type_conversion_status res= Field_blob::reset();
+    if (res != TYPE_OK)
+      return res;
+    return maybe_null() ? TYPE_OK : TYPE_ERR_NULL_CONSTRAINT_VIOLATION;
+  }
 
   geometry_type get_geometry_type() { return geom_type; };
   Field_geom *clone(MEM_ROOT *mem_root) const {
@@ -3223,9 +3440,10 @@ public:
   enum Item_result cmp_type () const { return INT_RESULT; }
   enum Item_result cast_to_int_type () const { return INT_RESULT; }
   enum ha_base_keytype key_type() const;
-  int  store(const char *to,uint length, const CHARSET_INFO *charset);
-  int  store(double nr);
-  int  store(longlong nr, bool unsigned_val);
+  type_conversion_status store(const char *to,uint length,
+                               const CHARSET_INFO *charset);
+  type_conversion_status store(double nr);
+  type_conversion_status store(longlong nr, bool unsigned_val);
   double val_real(void);
   my_decimal *val_decimal(my_decimal *decimal_value);
   longlong val_int(void);
@@ -3279,9 +3497,13 @@ public:
     {
       flags= (flags & ~ENUM_FLAG) | SET_FLAG;
     }
-  int  store(const char *to,uint length, const CHARSET_INFO *charset);
-  int  store(double nr) { return Field_set::store((longlong) nr, FALSE); }
-  int  store(longlong nr, bool unsigned_val);
+  type_conversion_status store(const char *to, uint length,
+                               const CHARSET_INFO *charset);
+  type_conversion_status store(double nr)
+  {
+    return Field_set::store((longlong) nr, FALSE);
+  }
+  type_conversion_status store(longlong nr, bool unsigned_val);
   virtual bool zero_pack() const { return 1; }
   String *val_str(String*,String *);
   void sql_type(String &str) const;
@@ -3329,16 +3551,18 @@ public:
   uint32 max_data_length() const { return (field_length + 7) / 8; }
   uint32 max_display_length() { return field_length; }
   Item_result result_type () const { return INT_RESULT; }
-  int reset(void) { 
-    memset(ptr, 0, bytes_in_rec); 
+  type_conversion_status reset(void)
+  {
+    memset(ptr, 0, bytes_in_rec);
     if (bit_ptr && (bit_len > 0))  // reset odd bits among null bits
       clr_rec_bits(bit_ptr, bit_ofs, bit_len);
-    return 0; 
+    return TYPE_OK;
   }
-  int store(const char *to, uint length, const CHARSET_INFO *charset);
-  int store(double nr);
-  int store(longlong nr, bool unsigned_val);
-  int store_decimal(const my_decimal *);
+  type_conversion_status store(const char *to, uint length,
+                               const CHARSET_INFO *charset);
+  type_conversion_status store(double nr);
+  type_conversion_status store(longlong nr, bool unsigned_val);
+  type_conversion_status store_decimal(const my_decimal *);
   double val_real(void);
   longlong val_int(void);
   String *val_str(String*, String *);
@@ -3430,9 +3654,10 @@ public:
                     uchar null_bit_arg,
                     enum utype unireg_check_arg, const char *field_name_arg);
   enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
-  int store(const char *to, uint length, const CHARSET_INFO *charset);
-  int store(double nr) { return Field_bit::store(nr); }
-  int store(longlong nr, bool unsigned_val)
+  type_conversion_status store(const char *to, uint length,
+                               const CHARSET_INFO *charset);
+  type_conversion_status store(double nr) { return Field_bit::store(nr); }
+  type_conversion_status store(longlong nr, bool unsigned_val)
   { return Field_bit::store(nr, unsigned_val); }
   void sql_type(String &str) const;
   Field_bit_as_char *clone(MEM_ROOT *mem_root) const { 
@@ -3596,8 +3821,9 @@ Field *make_field(TABLE_SHARE *share, uc
 uint pack_length_to_packflag(uint type);
 enum_field_types get_blob_type_from_length(ulong length);
 uint32 calc_pack_length(enum_field_types type,uint32 length);
-int set_field_to_null(Field *field);
-int set_field_to_null_with_conversions(Field *field, bool no_conversions);
+type_conversion_status set_field_to_null(Field *field);
+type_conversion_status set_field_to_null_with_conversions(Field *field,
+                                                          bool no_conversions);
 
 /*
   The following are for the interface with the .frm file

=== modified file 'sql/field_conv.cc'
--- a/sql/field_conv.cc	2012-04-12 14:29:14 +0000
+++ b/sql/field_conv.cc	2012-05-07 08:29:18 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -98,14 +98,13 @@ static void do_field_to_null_str(Copy_fi
 }
 
 
-int
-set_field_to_null(Field *field)
+type_conversion_status set_field_to_null(Field *field)
 {
   if (field->real_maybe_null())
   {
     field->set_null();
     field->reset();
-    return 0;
+    return TYPE_OK;
   }
   field->reset();
   switch (field->table->in_use->count_cuted_fields) {
@@ -113,14 +112,14 @@ set_field_to_null(Field *field)
     field->set_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
     /* fall through */
   case CHECK_FIELD_IGNORE:
-    return 0;
+    return TYPE_OK;
   case CHECK_FIELD_ERROR_FOR_NULL:
     if (!field->table->in_use->no_errors)
       my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name);
-    return -1;
+    return TYPE_ERR_NULL_CONSTRAINT_VIOLATION;
   }
-  DBUG_ASSERT(0); // impossible
-  return -1;
+  DBUG_ASSERT(false); // impossible
+  return TYPE_ERR_NULL_CONSTRAINT_VIOLATION;
 }
 
 
@@ -141,17 +140,17 @@ set_field_to_null(Field *field)
     If no_conversion was not set, an error message is printed
 */
 
-int
+type_conversion_status
 set_field_to_null_with_conversions(Field *field, bool no_conversions)
 {
   if (field->real_maybe_null())
   {
     field->set_null();
     field->reset();
-    return 0;
+    return TYPE_OK;
   }
   if (no_conversions)
-    return -1;
+    return TYPE_ERR_NULL_CONSTRAINT_VIOLATION;
 
   /*
     Check if this is a special type, which will get a special walue
@@ -165,7 +164,7 @@ set_field_to_null_with_conversions(Field
   if (field->type() == MYSQL_TYPE_TIMESTAMP)
   {
     Item_func_now_local::store_in(field);
-    return 0;					// Ok to set time to NULL
+    return TYPE_OK;			// Ok to set time to NULL
   }
   
   // Note: we ignore any potential failure of reset() here.
@@ -174,21 +173,21 @@ set_field_to_null_with_conversions(Field
   if (field == field->table->next_number_field)
   {
     field->table->auto_increment_field_not_null= FALSE;
-    return 0;				  // field is set in fill_record()
+    return TYPE_OK;		        // field is set in fill_record()
   }
   switch (field->table->in_use->count_cuted_fields) {
   case CHECK_FIELD_WARN:
     field->set_warning(Sql_condition::WARN_LEVEL_WARN, ER_BAD_NULL_ERROR, 1);
     /* fall through */
   case CHECK_FIELD_IGNORE:
-    return 0;
+    return TYPE_OK;
   case CHECK_FIELD_ERROR_FOR_NULL:
     if (!field->table->in_use->no_errors)
       my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name);
-    return -1;
+    return TYPE_ERR_NULL_CONSTRAINT_VIOLATION;
   }
-  DBUG_ASSERT(0); // impossible
-  return -1;
+  DBUG_ASSERT(false); // impossible
+  return TYPE_ERR_NULL_CONSTRAINT_VIOLATION;
 }
 
 
@@ -344,7 +343,7 @@ static void do_field_decimal(Copy_field
 }
 
 
-inline int copy_time_to_time(Field *from, Field *to)
+inline type_conversion_status copy_time_to_time(Field *from, Field *to)
 {
   MYSQL_TIME ltime;
   from->get_time(&ltime);
@@ -780,7 +779,7 @@ Copy_field::get_copy_func(Field *to,Fiel
 
 /** Simple quick field convert that is called on insert. */
 
-int field_conv(Field *to,Field *from)
+type_conversion_status field_conv(Field *to,Field *from)
 {
   if (to->real_type() == from->real_type() &&
       !(to->type() == MYSQL_TYPE_BLOB && to->table->copy_blobs) &&
@@ -794,7 +793,7 @@ int field_conv(Field *to,Field *from)
       if (to_vc->length_bytes == from_vc->length_bytes)
       {
         copy_field_varstring(to_vc, from_vc);
-        return 0;
+        return TYPE_OK;
       }
     }
     if (to->pack_length() == from->pack_length() &&
@@ -816,7 +815,7 @@ int field_conv(Field *to,Field *from)
     {						// Identical fields
       // to->ptr==from->ptr may happen if one does 'UPDATE ... SET x=x'
       memmove(to->ptr, from->ptr, to->pack_length());
-      return 0;
+      return TYPE_OK;
     }
   }
   if (to->type() == MYSQL_TYPE_BLOB)
@@ -839,7 +838,7 @@ int field_conv(Field *to,Field *from)
       from->val_int() == 0)
   {
     ((Field_enum *)(to))->store_type(0);
-    return 0;
+    return TYPE_OK;
   }
   else if (from->is_temporal() && to->result_type() == INT_RESULT)
   {

=== modified file 'sql/item.cc'
--- a/sql/item.cc	2012-04-20 06:48:15 +0000
+++ b/sql/item.cc	2012-05-07 08:29:18 +0000
@@ -1,5 +1,5 @@
 /*
-   Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+   Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -495,7 +495,7 @@ longlong Item::val_int_from_datetime()
 }
 
 
-int Item::save_time_in_field(Field *field)
+type_conversion_status Item::save_time_in_field(Field *field)
 {
   MYSQL_TIME ltime;
   if (get_time(&ltime))
@@ -505,7 +505,7 @@ int Item::save_time_in_field(Field *fiel
 }
 
 
-int Item::save_date_in_field(Field *field)
+type_conversion_status Item::save_date_in_field(Field *field)
 {
   MYSQL_TIME ltime;
   if (get_date(&ltime, TIME_FUZZY_DATE))
@@ -536,13 +536,14 @@ int Item::save_date_in_field(Field *fiel
     Nonzero value if error
 */
 
-int Item::save_str_value_in_field(Field *field, String *result)
+type_conversion_status
+Item::save_str_value_in_field(Field *field, String *result)
 {
   if (null_value)
     return set_field_to_null(field);
+
   field->set_notnull();
-  return field->store(result->ptr(), result->length(),
-		      collation.collation);
+  return field->store(result->ptr(), result->length(), collation.collation);
 }
 
 
@@ -1473,10 +1474,10 @@ const CHARSET_INFO *Item::default_charse
    for example in opt_range to adjust the key value to fit the column.
 */
 
-int Item::save_in_field_no_warnings(Field *field, bool no_conversions)
+type_conversion_status
+Item::save_in_field_no_warnings(Field *field, bool no_conversions)
 {
   DBUG_ENTER("Item::save_in_field_no_warnings");
-  int res;
   TABLE *table= field->table;
   THD *thd= table->in_use;
   enum_check_fields tmp= thd->count_cuted_fields;
@@ -1485,7 +1486,7 @@ int Item::save_in_field_no_warnings(Fiel
   thd->variables.sql_mode&= ~(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE);
   thd->count_cuted_fields= CHECK_FIELD_IGNORE;
 
-  res= save_in_field(field, no_conversions);
+  const type_conversion_status res= save_in_field(field, no_conversions);
 
   thd->count_cuted_fields= tmp;
   dbug_tmp_restore_column_map(table->write_set, old_map);
@@ -3681,7 +3682,8 @@ void Item_param::reset()
 }
 
 
-int Item_param::save_in_field(Field *field, bool no_conversions)
+type_conversion_status
+Item_param::save_in_field(Field *field, bool no_conversions)
 {
   field->set_notnull();
 
@@ -3694,7 +3696,7 @@ int Item_param::save_in_field(Field *fie
     return field->store_decimal(&decimal_value);
   case TIME_VALUE:
     field->store_time(&value.time);
-    return 0;
+    return TYPE_OK;
   case STRING_VALUE:
   case LONG_DATA_VALUE:
     return field->store(str_value.ptr(), str_value.length(),
@@ -3705,7 +3707,7 @@ int Item_param::save_in_field(Field *fie
   default:
     DBUG_ASSERT(0);
   }
-  return 1;
+  return TYPE_ERR_BAD_VALUE;
 }
 
 
@@ -4291,7 +4293,8 @@ longlong Item_copy_string::val_int()
 }
 
 
-int Item_copy_string::save_in_field(Field *field, bool no_conversions)
+type_conversion_status
+Item_copy_string::save_in_field(Field *field, bool no_conversions)
 {
   return save_str_value_in_field(field, &str_value);
 }
@@ -4345,12 +4348,14 @@ void Item_copy_int::copy()
   null_value=item->null_value;
 }
 
-static int save_int_value_in_field (Field *field, longlong nr, 
-                                    bool null_value, bool unsigned_flag);
+static type_conversion_status
+save_int_value_in_field (Field *field, longlong nr,
+                         bool null_value, bool unsigned_flag);
 
-int Item_copy_int::save_in_field(Field *field, bool no_conversions)
+type_conversion_status
+Item_copy_int::save_in_field(Field *field, bool no_conversions)
 {
-  return save_int_value_in_field(field, cached_value, 
+  return save_int_value_in_field(field, cached_value,
                                  null_value, unsigned_flag);
 }
 
@@ -4419,10 +4424,13 @@ my_decimal *Item_copy_float::val_decimal
 }
 
 
-int Item_copy_float::save_in_field(Field *field, bool no_conversions)
+type_conversion_status
+Item_copy_float::save_in_field(Field *field, bool no_conversions)
 {
+  // TODO: call set_field_to_null_with_conversions below
   if (null_value)
     return set_field_to_null(field);
+
   field->set_notnull();
   return field->store(cached_value);
 }
@@ -4432,8 +4440,10 @@ int Item_copy_float::save_in_field(Field
   Item_copy_decimal
 ****************************************************************************/
 
-int Item_copy_decimal::save_in_field(Field *field, bool no_conversions)
+type_conversion_status
+Item_copy_decimal::save_in_field(Field *field, bool no_conversions)
 {
+  // TODO: call set_field_to_null_with_conversions below
   if (null_value)
     return set_field_to_null(field);
   field->set_notnull();
@@ -6024,7 +6034,7 @@ void Item_field::save_org_in_field(Field
   if (field->is_null())
   {
     null_value=1;
-    set_field_to_null_with_conversions(to, 1);
+    set_field_to_null_with_conversions(to, true);
   }
   else
   {
@@ -6034,9 +6044,10 @@ void Item_field::save_org_in_field(Field
   }
 }
 
-int Item_field::save_in_field(Field *to, bool no_conversions)
+type_conversion_status
+Item_field::save_in_field(Field *to, bool no_conversions)
 {
-  int res;
+  type_conversion_status res;
   DBUG_ENTER("Item_field::save_in_field");
   if (result_field->is_null())
   {
@@ -6052,7 +6063,7 @@ int Item_field::save_in_field(Field *to,
   if (to == result_field)
   {
     null_value=0;
-    DBUG_RETURN(0);
+    DBUG_RETURN(TYPE_OK);
   }
 
   res= field_conv(to,result_field);
@@ -6075,7 +6086,8 @@ int Item_field::save_in_field(Field *to,
     1   Field doesn't support NULL values and can't handle 'field = NULL'
 */
 
-int Item_null::save_in_field(Field *field, bool no_conversions)
+type_conversion_status
+Item_null::save_in_field(Field *field, bool no_conversions)
 {
   return set_field_to_null_with_conversions(field, no_conversions);
 }
@@ -6092,7 +6104,7 @@ int Item_null::save_in_field(Field *fiel
     1	 Field doesn't support NULL values
 */
 
-int Item_null::save_safe_in_field(Field *field)
+type_conversion_status Item_null::save_safe_in_field(Field *field)
 {
   return set_field_to_null(field);
 }
@@ -6107,9 +6119,10 @@ int Item_null::save_safe_in_field(Field
   str != str_value. For example, see fix for bug #44743.
 */
 
-int Item::save_in_field(Field *field, bool no_conversions)
+type_conversion_status
+Item::save_in_field(Field *field, bool no_conversions)
 {
-  int error;
+  type_conversion_status error;
   if (result_type() == STRING_RESULT)
   {
     String *result;
@@ -6163,11 +6176,13 @@ int Item::save_in_field(Field *field, bo
     field->set_notnull();
     error=field->store(nr, unsigned_flag);
   }
-  return error ? error : (field->table->in_use->is_error() ? 1 : 0);
+  return error ? error : (field->table->in_use->is_error() ?
+                          TYPE_ERR_BAD_VALUE : TYPE_OK);
 }
 
 
-int Item_string::save_in_field(Field *field, bool no_conversions)
+type_conversion_status
+Item_string::save_in_field(Field *field, bool no_conversions)
 {
   String *result;
   result=val_str(&str_value);
@@ -6175,15 +6190,30 @@ int Item_string::save_in_field(Field *fi
 }
 
 
-int Item_uint::save_in_field(Field *field, bool no_conversions)
+type_conversion_status
+Item_uint::save_in_field(Field *field, bool no_conversions)
 {
   /* Item_int::save_in_field handles both signed and unsigned. */
   return Item_int::save_in_field(field, no_conversions);
 }
 
-static int save_int_value_in_field (Field *field, longlong nr, 
-                                    bool null_value, bool unsigned_flag)
+/**
+  Store an int in a field
+
+  @param field           The field where the int value is to be stored
+  @param nr              The value to store in field
+  @param null_value      True if the value to store is NULL, false otherwise
+  @param unsigned_flag   Whether or not the int value is signed or unsigned
+
+  @retval TYPE_OK   Storing of value went fine without warnings or errors
+  @retval !TYPE_OK  Warning/error as indicated by type_conversion_status enum
+                    value
+*/
+static type_conversion_status
+save_int_value_in_field (Field *field, longlong nr,
+                         bool null_value, bool unsigned_flag)
 {
+  // TODO: call set_field_to_null_with_conversions below
   if (null_value)
     return set_field_to_null(field);
   field->set_notnull();
@@ -6191,17 +6221,38 @@ static int save_int_value_in_field (Fiel
 }
 
 
-int Item_int::save_in_field(Field *field, bool no_conversions)
+/**
+  Store this item's int-value in a field
+
+  @param field           The field where the int value is to be stored
+  @param no_conversions  Only applies if the value to store is NULL
+                         (null_value is true) and NULL is not allowed
+                         in field. In that case: if no_coversion is
+                         true, do nothing and return with error
+                         TYPE_ERR_NULL_CONSTRAINT_VIOLATION. If
+                         no_coversion is false, the field's default
+                         value is stored if one exists. Otherwise an
+                         error is returned.
+
+  @retval TYPE_OK   Storing of value went fine without warnings or errors
+  @retval !TYPE_OK  Warning/error as indicated by type_conversion_status enum
+                    value
+*/
+type_conversion_status
+Item_int::save_in_field(Field *field, bool no_conversions)
 {
-  return save_int_value_in_field (field, val_int(), null_value, unsigned_flag);
+  return save_int_value_in_field (field, val_int(), null_value,
+                                  unsigned_flag);
 }
 
 
-int Item_temporal::save_in_field(Field *field, bool no_conversions)
+type_conversion_status
+Item_temporal::save_in_field(Field *field, bool no_conversions)
 {
   longlong nr= field->is_temporal_with_time() ?
                val_temporal_with_round(field->type(), field->decimals()) :
                val_date_temporal();
+  // TODO: call set_field_to_null_with_conversions below
   if (null_value)
     return set_field_to_null(field);
   field->set_notnull();
@@ -6209,7 +6260,8 @@ int Item_temporal::save_in_field(Field *
 }
 
 
-int Item_decimal::save_in_field(Field *field, bool no_conversions)
+type_conversion_status
+Item_decimal::save_in_field(Field *field, bool no_conversions)
 {
   field->set_notnull();
   return field->store_decimal(&decimal_value);
@@ -6359,9 +6411,11 @@ Item_float::Item_float(const char *str_a
 }
 
 
-int Item_float::save_in_field(Field *field, bool no_conversions)
+type_conversion_status
+Item_float::save_in_field(Field *field, bool no_conversions)
 {
   double nr= val_real();
+  // TODO: call set_field_to_null_with_conversions below
   if (null_value)
     return set_field_to_null(field);
   field->set_notnull();
@@ -6469,7 +6523,8 @@ my_decimal *Item_hex_string::val_decimal
 }
 
 
-int Item_hex_string::save_in_field(Field *field, bool no_conversions)
+type_conversion_status
+Item_hex_string::save_in_field(Field *field, bool no_conversions)
 {
   field->set_notnull();
   if (field->result_type() == STRING_RESULT)
@@ -6479,8 +6534,10 @@ int Item_hex_string::save_in_field(Field
   ulonglong nr;
   uint32 length= str_value.length();
   if (!length)
-    return 1;
-
+  {
+    field->reset();
+    return TYPE_WARN_OUT_OF_RANGE;
+  }
   if (length > 8)
   {
     nr= field->flags & UNSIGNED_FLAG ? ULONGLONG_MAX : LONGLONG_MAX;
@@ -6495,10 +6552,11 @@ int Item_hex_string::save_in_field(Field
   return field->store((longlong) nr, TRUE);  // Assume hex numbers are unsigned
 
 warn:
-  if (!field->store((longlong) nr, TRUE))
-    field->set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE,
-                       1);
-  return 1;
+  const type_conversion_status res= field->store((longlong) nr, TRUE);
+  if (res == TYPE_OK)
+    field->set_warning(Sql_condition::WARN_LEVEL_WARN,
+                       ER_WARN_DATA_OUT_OF_RANGE, 1);
+  return res;
 }
 
 
@@ -7516,9 +7574,10 @@ my_decimal *Item_ref::val_decimal(my_dec
   return val;
 }
 
-int Item_ref::save_in_field(Field *to, bool no_conversions)
+type_conversion_status
+Item_ref::save_in_field(Field *to, bool no_conversions)
 {
-  int res;
+  type_conversion_status res;
   if (result_field)
   {
     if (result_field->is_null())
@@ -7846,7 +7905,8 @@ void Item_default_value::print(String *s
 }
 
 
-int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
+type_conversion_status
+Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
 {
   if (!arg)
   {
@@ -7857,7 +7917,7 @@ int Item_default_value::save_in_field(Fi
       {
         my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
                    ER(ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
-        return -1;
+        return TYPE_ERR_BAD_VALUE;
       }
 
       if (context->error_processor == &view_error_processor)
@@ -7878,10 +7938,10 @@ int Item_default_value::save_in_field(Fi
                             ER(ER_NO_DEFAULT_FOR_FIELD),
                             field_arg->field_name);
       }
-      return 1;
+      return TYPE_ERR_BAD_VALUE;
     }
     field_arg->set_default();
-    return 0;
+    return TYPE_OK;
   }
   return Item_field::save_in_field(field_arg, no_conversions);
 }
@@ -8864,13 +8924,18 @@ my_decimal *Item_cache_str::val_decimal(
 }
 
 
-int Item_cache_str::save_in_field(Field *field, bool no_conversions)
+type_conversion_status
+Item_cache_str::save_in_field(Field *field, bool no_conversions)
 {
   if (!value_cached && !cache_value())
-    return -1;                      // Fatal: couldn't cache the value
-  int res= Item_cache::save_in_field(field, no_conversions);
-  return (is_varbinary && field->type() == MYSQL_TYPE_STRING &&
-          value->length() < field->field_length) ? 1 : res;
+    return TYPE_ERR_BAD_VALUE;               // Fatal: couldn't cache the value
+  const type_conversion_status res= Item_cache::save_in_field(field,
+                                                              no_conversions);
+  if (is_varbinary && field->type() == MYSQL_TYPE_STRING &&
+      value->length() < field->field_length)
+    return TYPE_WARN_OUT_OF_RANGE;
+  return res;
+
 }
 
 

=== modified file 'sql/item.h'
--- a/sql/item.h	2012-04-24 08:04:39 +0000
+++ b/sql/item.h	2012-05-07 08:29:18 +0000
@@ -1,7 +1,7 @@
 #ifndef ITEM_INCLUDED
 #define ITEM_INCLUDED
 
-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -768,7 +768,8 @@ public:
   */
   inline void quick_fix_field() { fixed= 1; }
   /* Function returns 1 on overflow and -1 on fatal errors */
-  int save_in_field_no_warnings(Field *field, bool no_conversions);
+  type_conversion_status save_in_field_no_warnings(Field *field,
+                                                   bool no_conversions);
   /**
     Save a temporal value in packed longlong format into a Field.
     Used in optimizer.
@@ -776,10 +777,11 @@ public:
     @retval 0         On success.
     @retval >0        In error.
   */
-  virtual int save_in_field(Field *field, bool no_conversions);
+  virtual type_conversion_status save_in_field(Field *field,
+                                               bool no_conversions);
   virtual void save_org_in_field(Field *field)
   { (void) save_in_field(field, 1); }
-  virtual int save_safe_in_field(Field *field)
+  virtual type_conversion_status save_safe_in_field(Field *field)
   { return save_in_field(field, 1); }
   virtual bool send(Protocol *protocol, String *str);
   virtual bool eq(const Item *, bool binary_cmp) const;
@@ -1132,9 +1134,9 @@ protected:
 
 public:
 
-  int save_time_in_field(Field *field);
-  int save_date_in_field(Field *field);
-  int save_str_value_in_field(Field *field, String *result);
+  type_conversion_status save_time_in_field(Field *field);
+  type_conversion_status save_date_in_field(Field *field);
+  type_conversion_status save_str_value_in_field(Field *field, String *result);
 
   virtual Field *get_tmp_table_field() { return 0; }
   /* This is also used to create fields in CREATE ... SELECT: */
@@ -1738,7 +1740,8 @@ public:
 
 public:
   inline void make_field(Send_field *field);  
-  inline int save_in_field(Field *field, bool no_conversions);
+  inline type_conversion_status save_in_field(Field *field,
+                                              bool no_conversions);
   inline bool send(Protocol *protocol, String *str);
 }; 
 
@@ -1753,7 +1756,8 @@ inline void Item_sp_variable::make_field
   it->make_field(field);
 }
 
-inline int Item_sp_variable::save_in_field(Field *field, bool no_conversions)
+inline type_conversion_status
+Item_sp_variable::save_in_field(Field *field, bool no_conversions)
 {
   return this_item()->save_in_field(field, no_conversions);
 }
@@ -1937,7 +1941,7 @@ public:
     return value_item->result_type();
   }
 
-  int save_in_field(Field *field, bool no_conversions)
+  type_conversion_status save_in_field(Field *field, bool no_conversions)
   {
     return  value_item->save_in_field(field, no_conversions);
   }
@@ -2145,7 +2149,7 @@ public:
   void reset_field(Field *f);
   bool fix_fields(THD *, Item **);
   void make_field(Send_field *tmp_field);
-  int save_in_field(Field *field,bool no_conversions);
+  type_conversion_status save_in_field(Field *field,bool no_conversions);
   void save_org_in_field(Field *field);
   table_map used_tables() const;
   virtual table_map resolved_used_tables() const;
@@ -2282,8 +2286,8 @@ public:
   {
     return true;
   }
-  int save_in_field(Field *field, bool no_conversions);
-  int save_safe_in_field(Field *field);
+  type_conversion_status save_in_field(Field *field, bool no_conversions);
+  type_conversion_status save_safe_in_field(Field *field);
   bool send(Protocol *protocol, String *str);
   enum Item_result result_type () const { return STRING_RESULT; }
   enum_field_types field_type() const   { return MYSQL_TYPE_NULL; }
@@ -2398,7 +2402,7 @@ public:
   String *val_str(String*);
   bool get_time(MYSQL_TIME *tm);
   bool get_date(MYSQL_TIME *tm, uint fuzzydate);
-  int  save_in_field(Field *field, bool no_conversions);
+  type_conversion_status save_in_field(Field *field, bool no_conversions);
 
   void set_null();
   void set_int(longlong i, uint32 max_length_arg);
@@ -2518,7 +2522,7 @@ public:
   {
     return get_time_from_int(ltime);
   }
-  int save_in_field(Field *field, bool no_conversions);
+  type_conversion_status save_in_field(Field *field, bool no_conversions);
   bool basic_const_item() const { return 1; }
   Item *clone_item() { return new Item_int(this); }
   virtual void print(String *str, enum_query_type query_type);
@@ -2569,7 +2573,7 @@ public:
     fixed= 1;
   }
   Item *clone_item() { return new Item_temporal(field_type(), value); }
-  int save_in_field(Field *field, bool no_conversions);
+  type_conversion_status save_in_field(Field *field, bool no_conversions);
   longlong val_time_temporal() { return val_int(); }
   longlong val_date_temporal() { return val_int(); }
   bool get_date(MYSQL_TIME *ltime, uint fuzzydate)
@@ -2600,8 +2604,9 @@ public:
   double val_real()
     { DBUG_ASSERT(fixed == 1); return ulonglong2double((ulonglong)value); }
   String *val_str(String*);
+
   Item *clone_item() { return new Item_uint(item_name, value, max_length); }
-  int save_in_field(Field *field, bool no_conversions);
+  type_conversion_status save_in_field(Field *field, bool no_conversions);
   virtual void print(String *str, enum_query_type query_type);
   Item_num *neg ();
   uint decimal_precision() const { return max_length; }
@@ -2638,7 +2643,7 @@ public:
   {
     return get_time_from_decimal(ltime);
   }
-  int save_in_field(Field *field, bool no_conversions);
+  type_conversion_status save_in_field(Field *field, bool no_conversions);
   bool basic_const_item() const { return 1; }
   Item *clone_item()
   {
@@ -2680,7 +2685,7 @@ public:
     decimals= (uint8) decimal_par;
     fixed= 1;
   }
-  int save_in_field(Field *field, bool no_conversions);
+  type_conversion_status save_in_field(Field *field, bool no_conversions);
   enum Type type() const { return REAL_ITEM; }
   enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
   double val_real() { DBUG_ASSERT(fixed == 1); return value; }
@@ -2814,7 +2819,7 @@ public:
   {
     return get_time_from_string(ltime);
   }
-  int save_in_field(Field *field, bool no_conversions);
+  type_conversion_status save_in_field(Field *field, bool no_conversions);
   enum Item_result result_type () const { return STRING_RESULT; }
   enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
   bool basic_const_item() const { return 1; }
@@ -3001,7 +3006,7 @@ public:
   {
     return get_time_from_string(ltime);
   }
-  int save_in_field(Field *field, bool no_conversions);
+  type_conversion_status save_in_field(Field *field, bool no_conversions);
   enum Item_result result_type () const { return STRING_RESULT; }
   enum Item_result cast_to_int_type() const { return INT_RESULT; }
   enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
@@ -3121,7 +3126,7 @@ public:
   bool fix_fields(THD *, Item **);
   void fix_after_pullout(st_select_lex *parent_select,
                          st_select_lex *removed_select, Item **ref);
-  int save_in_field(Field *field, bool no_conversions);
+  type_conversion_status save_in_field(Field *field, bool no_conversions);
   void save_org_in_field(Field *field);
   enum Item_result result_type () const { return (*ref)->result_type(); }
   enum_field_types field_type() const   { return (*ref)->field_type(); }
@@ -3423,7 +3428,7 @@ public:
   {
     unsigned_flag= unsigned_arg;
   }
-  int save_in_field(Field *field, bool no_conversions)
+  type_conversion_status save_in_field(Field *field, bool no_conversions)
   {
     return ref->save_in_field(field, no_conversions);
   }
@@ -3641,7 +3646,8 @@ public:
   virtual longlong val_int() = 0;
   virtual bool get_date(MYSQL_TIME *ltime, uint fuzzydate)= 0;
   virtual bool get_time(MYSQL_TIME *ltime)= 0;
-  virtual int save_in_field(Field *field, bool no_conversions) = 0;
+  virtual type_conversion_status save_in_field(Field *field,
+                                               bool no_conversions) = 0;
 };
 
 /**
@@ -3661,7 +3667,7 @@ public:
   bool get_date(MYSQL_TIME *ltime, uint fuzzydate);
   bool get_time(MYSQL_TIME *ltime);
   void copy();
-  int save_in_field(Field *field, bool no_conversions);
+  type_conversion_status save_in_field(Field *field, bool no_conversions);
 };
 
 
@@ -3671,7 +3677,7 @@ protected:
   longlong cached_value; 
 public:
   Item_copy_int (Item *i) : Item_copy(i) {}
-  int save_in_field(Field *field, bool no_conversions);
+  type_conversion_status save_in_field(Field *field, bool no_conversions);
 
   virtual String *val_str(String*);
   virtual my_decimal *val_decimal(my_decimal *);
@@ -3717,7 +3723,7 @@ protected:
   double cached_value; 
 public:
   Item_copy_float (Item *i) : Item_copy(i) {}
-  int save_in_field(Field *field, bool no_conversions);
+  type_conversion_status save_in_field(Field *field, bool no_conversions);
 
   String *val_str(String*);
   my_decimal *val_decimal(my_decimal *);
@@ -3751,7 +3757,7 @@ protected:
   my_decimal cached_value;
 public:
   Item_copy_decimal (Item *i) : Item_copy(i) {}
-  int save_in_field(Field *field, bool no_conversions);
+  type_conversion_status save_in_field(Field *field, bool no_conversions);
 
   String *val_str(String*);
   my_decimal *val_decimal(my_decimal *) 
@@ -3876,7 +3882,7 @@ public:
   bool eq(const Item *item, bool binary_cmp) const;
   bool fix_fields(THD *, Item **);
   virtual void print(String *str, enum_query_type query_type);
-  int save_in_field(Field *field_arg, bool no_conversions);
+  type_conversion_status save_in_field(Field *field_arg, bool no_conversions);
   table_map used_tables() const { return (table_map)0L; }
 
   bool walk(Item_processor processor, bool walk_subquery, uchar *args)
@@ -3909,7 +3915,7 @@ public:
   bool eq(const Item *item, bool binary_cmp) const;
   bool fix_fields(THD *, Item **);
   virtual void print(String *str, enum_query_type query_type);
-  int save_in_field(Field *field_arg, bool no_conversions)
+  type_conversion_status save_in_field(Field *field_arg, bool no_conversions)
   {
     return Item_field::save_in_field(field_arg, no_conversions);
   }
@@ -4219,7 +4225,7 @@ public:
   }
   enum Item_result result_type() const { return STRING_RESULT; }
   const CHARSET_INFO *charset() const { return value->charset(); };
-  int save_in_field(Field *field, bool no_conversions);
+  type_conversion_status save_in_field(Field *field, bool no_conversions);
   bool cache_value();
 };
 

=== modified file 'sql/item_cmpfunc.cc'
--- a/sql/item_cmpfunc.cc	2012-05-02 19:59:24 +0000
+++ b/sql/item_cmpfunc.cc	2012-05-07 08:29:18 +0000
@@ -451,7 +451,8 @@ static bool convert_constant_item(THD *t
       orig_field_val= field->val_int();
     int rc;
     if (!(*item)->is_null() &&
-        (((rc= (*item)->save_in_field(field, 1)) == 0) || rc == 3)) // TS-TODO
+        (((rc= (*item)->save_in_field(field, 1)) == TYPE_OK) ||
+         rc == TYPE_NOTE_TIME_TRUNCATED)) // TS-TODO
     {
       int field_cmp= 0;
       /*

=== modified file 'sql/item_func.cc'
--- a/sql/item_func.cc	2012-04-20 06:48:15 +0000
+++ b/sql/item_func.cc	2012-05-07 08:29:18 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -5239,12 +5239,13 @@ void Item_func_set_user_var::make_field(
     TRUE        Error
 */
 
-int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
-                                          bool can_use_result_field)
+type_conversion_status
+Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
+                                      bool can_use_result_field)
 {
   bool use_result_field= (!can_use_result_field ? 0 :
                           (result_field && result_field != field));
-  int error;
+  type_conversion_status error;
 
   /* Update the value of the user variable */
   check(use_result_field);

=== modified file 'sql/item_func.h'
--- a/sql/item_func.h	2012-04-24 08:04:39 +0000
+++ b/sql/item_func.h	2012-05-07 08:29:18 +0000
@@ -1,7 +1,7 @@
 #ifndef ITEM_FUNC_INCLUDED
 #define ITEM_FUNC_INCLUDED
 
-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -1673,9 +1673,9 @@ public:
   virtual void print(String *str, enum_query_type query_type);
   void print_assignment(String *str, enum_query_type query_type);
   const char *func_name() const { return "set_user_var"; }
-  int save_in_field(Field *field, bool no_conversions,
-                    bool can_use_result_field);
-  int save_in_field(Field *field, bool no_conversions)
+  type_conversion_status save_in_field(Field *field, bool no_conversions,
+                                       bool can_use_result_field);
+  type_conversion_status save_in_field(Field *field, bool no_conversions)
   {
     return save_in_field(field, no_conversions, 1);
   }

=== modified file 'sql/item_strfunc.h'
--- a/sql/item_strfunc.h	2012-04-17 14:37:50 +0000
+++ b/sql/item_strfunc.h	2012-05-07 08:29:18 +0000
@@ -1,7 +1,7 @@
 #ifndef ITEM_STRFUNC_INCLUDED
 #define ITEM_STRFUNC_INCLUDED
 
-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -508,7 +508,7 @@ public:
   const char *func_name() const { return "user"; }
   const NameString fully_qualified_func_name() const
   { return NAME_STRING("user()"); }
-  int save_in_field(Field *field, bool no_conversions)
+  type_conversion_status save_in_field(Field *field, bool no_conversions)
   {
     return save_str_value_in_field(field, &str_value);
   }

=== modified file 'sql/item_timefunc.cc'
--- a/sql/item_timefunc.cc	2012-04-27 11:57:38 +0000
+++ b/sql/item_timefunc.cc	2012-05-07 08:29:18 +0000
@@ -1,5 +1,5 @@
 /*
-   Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+   Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -812,7 +812,8 @@ bool Item_temporal_func::check_precision
 }
 
 
-int Item_temporal_hybrid_func::save_in_field(Field *field, bool no_conversions)
+type_conversion_status
+Item_temporal_hybrid_func::save_in_field(Field *field, bool no_conversions)
 {
   if (cached_field_type == MYSQL_TYPE_TIME)
     return save_time_in_field(field);
@@ -1868,7 +1869,8 @@ Time_zone *Item_func_now_utc::time_zone(
 }
 
 
-int Item_func_now::save_in_field(Field *to, bool no_conversions)
+type_conversion_status
+Item_func_now::save_in_field(Field *to, bool no_conversions)
 {
   to->set_notnull();
   return to->store_time(cached_time.get_TIME_ptr(), decimals);

=== modified file 'sql/item_timefunc.h'
--- a/sql/item_timefunc.h	2012-04-12 15:31:01 +0000
+++ b/sql/item_timefunc.h	2012-05-07 08:29:18 +0000
@@ -1,7 +1,7 @@
 #ifndef ITEM_TIMEFUNC_INCLUDED
 #define ITEM_TIMEFUNC_INCLUDED
 
-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -560,7 +560,7 @@ public:
   longlong val_int() { return val_int_from_decimal(); }
   double val_real() { return val_real_from_decimal(); }
   my_decimal *val_decimal(my_decimal *decimal_value);
-  int save_in_field(Field *field, bool no_conversions);
+  type_conversion_status save_in_field(Field *field, bool no_conversions);
   /**
     Return string value in ASCII character set.
   */
@@ -618,7 +618,7 @@ public:
     DBUG_ASSERT(fixed == 1);
     return  val_decimal_from_date(decimal_value);
   }
-  int save_in_field(Field *field, bool no_conversions)
+  type_conversion_status save_in_field(Field *field, bool no_conversions)
   {
     return save_date_in_field(field);
   }
@@ -659,7 +659,7 @@ public:
     DBUG_ASSERT(fixed == 1);
     return  val_decimal_from_date(decimal_value);
   }
-  int save_in_field(Field *field, bool no_conversions)
+  type_conversion_status save_in_field(Field *field, bool no_conversions)
   {
     return save_date_in_field(field);
   }
@@ -691,7 +691,7 @@ public:
     DBUG_ASSERT(fixed == 1);
     return  val_decimal_from_time(decimal_value);
   }
-  int save_in_field(Field *field, bool no_conversions)
+  type_conversion_status save_in_field(Field *field, bool no_conversions)
   {
     return save_time_in_field(field);
   }
@@ -1135,7 +1135,7 @@ public:
   */
   Item_func_now(uint8 dec_arg) :Item_datetime_func() { decimals= dec_arg; }
   void fix_length_and_dec();
-  int save_in_field(Field *to, bool no_conversions);
+  type_conversion_status save_in_field(Field *to, bool no_conversions);
   longlong val_date_temporal()
   {
     DBUG_ASSERT(fixed == 1);

=== modified file 'sql/opt_range.cc'
--- a/sql/opt_range.cc	2012-04-26 10:33:24 +0000
+++ b/sql/opt_range.cc	2012-05-08 06:07:50 +0000
@@ -394,7 +394,17 @@ public:
   */
   SEL_ARG *next_key_part; 
   enum leaf_color { BLACK,RED } color;
-  enum Type { IMPOSSIBLE, MAYBE, MAYBE_KEY, KEY_RANGE } type;
+
+  /**
+    Starting an effort to document this field:
+
+    IMPOSSIBLE: if the range predicate for this index is always false.
+
+    ALWAYS: if the range predicate for this index is always true.
+
+    KEY_RANGE: if there is a range predicate that can be used on this index.
+  */
+  enum Type { IMPOSSIBLE, ALWAYS, MAYBE, MAYBE_KEY, KEY_RANGE } type;
 
   enum { MAX_SEL_ARGS = 16000 };
 
@@ -699,10 +709,28 @@ class SEL_IMERGE;
 class SEL_TREE :public Sql_alloc
 {
 public:
-  /*
+  /**
     Starting an effort to document this field:
-    (for some i, keys[i]->type == SEL_ARG::IMPOSSIBLE) => 
-       (type == SEL_TREE::IMPOSSIBLE)
+
+    IMPOSSIBLE: if keys[i]->type == SEL_ARG::IMPOSSIBLE for some i,
+      then type == SEL_TREE::IMPOSSIBLE. Rationale: if the predicate for
+      one of the indexes is always false, then the full predicate is also
+      always false.
+
+    ALWAYS: if either (keys[i]->type == SEL_ARG::ALWAYS) or 
+      (keys[i] == NULL) for all i, then type == SEL_TREE::ALWAYS. 
+      Rationale: the range access method will not be able to filter
+      out any rows when there are no range predicates that can be used
+      to filter on any index.
+
+    KEY: There are range predicates that can be used on at least one
+      index.
+      
+    KEY_SMALLER: There are range predicates that can be used on at
+      least one index. In addition, there are predicates that cannot
+      be directly utilized by range access on key parts in the same
+      index. These unused predicates makes it probable that the row
+      estimate for range access on this index is too pessimistic.
   */
   enum Type { IMPOSSIBLE, ALWAYS, MAYBE, KEY, KEY_SMALLER } type;
   SEL_TREE(enum Type type_arg) :type(type_arg) {}
@@ -6354,7 +6382,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, Item
   MEM_ROOT *alloc= param->mem_root;
   uchar *str;
   sql_mode_t orig_sql_mode;
-  int err;
+  type_conversion_status err;
   const char* impossible_cond_cause= NULL;
   DBUG_ENTER("get_mm_leaf");
 
@@ -6588,7 +6616,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, Item
   // Note that value may be a stored function call, executed here.
   err= value->save_in_field_no_warnings(field, 1);
 
-  if (err > 0)
+  if (err != TYPE_OK && err != TYPE_ERR_NULL_CONSTRAINT_VIOLATION)
   {
     if (field->cmp_type() != value->result_type())
     {
@@ -6609,7 +6637,8 @@ get_mm_leaf(RANGE_OPT_PARAM *param, Item
           for the cases like int_field > 999999999999999999999999 as well.
         */
         tree= 0;
-        if (err == 3 && field->type() == FIELD_TYPE_DATE &&
+        if (err == TYPE_NOTE_TIME_TRUNCATED &&
+            field->type() == FIELD_TYPE_DATE &&
             (type == Item_func::GT_FUNC || type == Item_func::GE_FUNC ||
              type == Item_func::LT_FUNC || type == Item_func::LE_FUNC) )
         {
@@ -6645,7 +6674,8 @@ get_mm_leaf(RANGE_OPT_PARAM *param, Item
       If an integer got bounded (e.g. to within 0..255 / -128..127)
       for < or >, set flags as for <= or >= (no NEAR_MAX / NEAR_MIN)
     */
-    else if (err == 1 && field->result_type() == INT_RESULT)
+    else if (err == TYPE_WARN_OUT_OF_RANGE && 
+             field->result_type() == INT_RESULT)
     {
       if (type == Item_func::LT_FUNC && (value->val_int() > 0))
         type = Item_func::LE_FUNC;
@@ -6657,7 +6687,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, Item
         type = Item_func::GE_FUNC;
     }
   }
-  else if (err < 0)
+  else if (err == TYPE_ERR_NULL_CONSTRAINT_VIOLATION)
   {
     impossible_cond_cause= "null_field_in_non_null_column";
     field->table->in_use->variables.sql_mode= orig_sql_mode;
@@ -7536,6 +7566,8 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *
           // cur_key2 is full range: [-inf <= cur_key2 <= +inf]
           key1->free_tree();
           key2->free_tree();
+          key1->type= SEL_ARG::ALWAYS;
+          key2->type= SEL_ARG::ALWAYS;
           if (key1->maybe_flag)
             return new SEL_ARG(SEL_ARG::MAYBE_KEY);
           return 0;
@@ -7744,6 +7776,8 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *
         if (full_range)
         {                                       // Full range
           key1->free_tree();
+          key1->type= SEL_ARG::ALWAYS;
+          key2->type= SEL_ARG::ALWAYS;
           for (; cur_key2 ; cur_key2= cur_key2->next)
             cur_key2->increment_use_count(-1);  // Free not used tree
           if (key1->maybe_flag)

=== modified file 'sql/rpl_slave.cc'
--- a/sql/rpl_slave.cc	2012-05-03 08:11:43 +0000
+++ b/sql/rpl_slave.cc	2012-05-08 17:11:38 +0000
@@ -7614,7 +7614,7 @@ int start_slave(THD* thd , Master_info*
                               "not retry the transaction and will stop.");
         }
       }
-      else if (thd->lex->mi.pos || thd->lex->mi.relay_log_pos)
+      else if (thd->lex->mi.pos || thd->lex->mi.relay_log_pos || thd->lex->mi.gtid)
         push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, ER_UNTIL_COND_IGNORED,
                      ER(ER_UNTIL_COND_IGNORED));
 

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2012-05-02 08:36:41 +0000
+++ b/sql/sql_base.cc	2012-05-09 07:31:29 +0000
@@ -9060,7 +9060,7 @@ fill_record(THD *thd, Field **ptr, List<
     table= field->table;
     if (field == table->next_number_field)
       table->auto_increment_field_not_null= TRUE;
-    if (value->save_in_field(field, 0) < 0)
+    if (value->save_in_field(field, 0) == TYPE_ERR_NULL_CONSTRAINT_VIOLATION)
       goto err;
   }
   DBUG_RETURN(thd->is_error());

=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc	2012-04-21 12:11:15 +0000
+++ b/sql/sql_lex.cc	2012-05-08 17:11:38 +0000
@@ -173,6 +173,16 @@ st_parsing_options::reset()
   allows_derived= TRUE;
 }
 
+/**
+ Cleans slave connection info.
+*/
+void struct_slave_connection::reset()
+{
+  user= 0;
+  password= 0;
+  plugin_auth= 0;
+  plugin_dir= 0;
+}
 
 /**
   Perform initialization of Lex_input_stream instance.

=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	2012-04-21 12:14:15 +0000
+++ b/sql/sql_lex.h	2012-05-08 17:11:38 +0000
@@ -986,6 +986,8 @@ typedef struct struct_slave_connection
   char *password;
   char *plugin_auth;
   char *plugin_dir;
+
+  void reset();
 } LEX_SLAVE_CONNECTION;
 
 struct st_sp_chistics

=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h	2012-03-22 08:17:51 +0000
+++ b/sql/sql_select.h	2012-05-07 08:29:18 +0000
@@ -1014,6 +1014,29 @@ public:
 };
 
 
+static store_key::store_key_result
+type_conversion_status_to_store_key (type_conversion_status ts)
+{
+  switch (ts)
+  {
+  case TYPE_OK:
+    return store_key::STORE_KEY_OK;
+  case TYPE_NOTE_TIME_TRUNCATED:
+    return store_key::STORE_KEY_CONV;
+  case TYPE_WARN_OUT_OF_RANGE:
+  case TYPE_NOTE_TRUNCATED:
+  case TYPE_WARN_TRUNCATED:
+  case TYPE_ERR_NULL_CONSTRAINT_VIOLATION:
+  case TYPE_ERR_BAD_VALUE:
+  case TYPE_ERR_OOM:
+    return store_key::STORE_KEY_FATAL;
+  default:
+    DBUG_ASSERT(false); // not possible
+  }
+
+  return store_key::STORE_KEY_FATAL;
+}
+
 class store_key_field: public store_key
 {
   Copy_field copy_field;
@@ -1066,17 +1089,19 @@ public:
     TABLE *table= to_field->table;
     my_bitmap_map *old_map= dbug_tmp_use_all_columns(table,
                                                      table->write_set);
-    int res= item->save_in_field(to_field, 1);
+    type_conversion_status save_res= item->save_in_field(to_field, true);
+    store_key_result res;
     /*
      Item::save_in_field() may call Item::val_xxx(). And if this is a subquery
      we need to check for errors executing it and react accordingly
     */
-    if (!res && table->in_use->is_error())
-      res= 1; /* STORE_KEY_FATAL */
+    if (save_res != TYPE_OK && table->in_use->is_error())
+      res= STORE_KEY_FATAL;
+    else
+      res= type_conversion_status_to_store_key(save_res);
     dbug_tmp_restore_column_map(table->write_set, old_map);
     null_key= to_field->is_null() || item->null_value;
-    return ((err != 0 || res < 0 || res > 2) ? STORE_KEY_FATAL : 
-            (store_key_result) res);
+    return (err != 0) ? STORE_KEY_FATAL : res;
   }
 };
 
@@ -1100,7 +1125,7 @@ protected:
     if (!inited)
     {
       inited=1;
-      int res= store_key_item::copy_inner();
+      store_key_result res= store_key_item::copy_inner();
       if (res && !err)
         err= res;
     }

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2012-04-30 07:13:31 +0000
+++ b/sql/sql_yacc.yy	2012-05-08 17:11:38 +0000
@@ -7580,6 +7580,8 @@ slave:
           START_SYM SLAVE opt_slave_thread_option_list
           {
             LEX *lex=Lex;
+            /* Clean previous slave connection values */
+            lex->slave_connection.reset();
             lex->sql_command = SQLCOM_SLAVE_START;
             lex->type = 0;
             /* We'll use mi structure for UNTIL options */
@@ -7673,7 +7675,7 @@ slave_connection_opts:
 
 slave_user_name_opt:
           {
-            Lex->slave_connection.user= 0;
+            /* empty */
           }
         | USER EQ TEXT_STRING_sys
           {
@@ -7683,7 +7685,7 @@ slave_user_name_opt:
 
 slave_user_pass_opt:
           {
-            Lex->slave_connection.password= 0;
+            /* empty */
           }
         | PASSWORD EQ TEXT_STRING_sys
           {
@@ -7692,7 +7694,7 @@ slave_user_pass_opt:
 
 slave_plugin_auth_opt:
           {
-            Lex->slave_connection.plugin_auth= 0;
+            /* empty */
           }
         | DEFAULT_AUTH_SYM EQ TEXT_STRING_sys
           {
@@ -7702,7 +7704,7 @@ slave_plugin_auth_opt:
 
 slave_plugin_dir_opt:
           {
-            Lex->slave_connection.plugin_dir= 0;
+            /* empty */
           }
         | PLUGIN_DIR_SYM EQ TEXT_STRING_sys
           {
@@ -7749,7 +7751,8 @@ slave_until:
           {
             LEX *lex=Lex;
             if (((lex->mi.log_file_name || lex->mi.pos) &&
-                (lex->mi.relay_log_name || lex->mi.relay_log_pos) &&
+                lex->mi.gtid) ||
+               ((lex->mi.relay_log_name || lex->mi.relay_log_pos) &&
                 lex->mi.gtid) ||
                 !((lex->mi.log_file_name && lex->mi.pos) ||
                   (lex->mi.relay_log_name && lex->mi.relay_log_pos) ||

=== modified file 'sql/unireg.cc'
--- a/sql/unireg.cc	2012-04-10 12:20:05 +0000
+++ b/sql/unireg.cc	2012-05-07 08:29:18 +0000
@@ -1133,9 +1133,9 @@ static bool make_empty_rec(THD *thd, Fil
         be constant.
       */
       DBUG_ASSERT(field->def->type() != Item::FUNC_ITEM);
-      int res= field->def->save_in_field(regfield, 1);
-      /* If not ok or warning of level 'note' */
-      if (res != 0 && res != 3)
+      type_conversion_status res= field->def->save_in_field(regfield, 1);
+      if (res != TYPE_OK && res != TYPE_NOTE_TIME_TRUNCATED &&
+          res != TYPE_NOTE_TRUNCATED)
       {
         /*
           clear current error and report INVALID DEFAULT value error message

=== modified file 'storage/innobase/include/ut0counter.h'
--- a/storage/innobase/include/ut0counter.h	2012-05-04 00:07:22 +0000
+++ b/storage/innobase/include/ut0counter.h	2012-05-08 21:47:01 +0000
@@ -28,6 +28,7 @@ Created 2012/04/12 by Sunny Bains
 #define UT0COUNTER_H
 
 #include "univ.i"
+#include <string.h>
 #include "os0thread.h"
 
 /** CPU cache line size */

=== modified file 'unittest/gunit/CMakeLists.txt'
--- a/unittest/gunit/CMakeLists.txt	2012-05-03 10:59:36 +0000
+++ b/unittest/gunit/CMakeLists.txt	2012-05-07 12:05:48 +0000
@@ -1,4 +1,4 @@
-# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
 # 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -195,9 +195,14 @@ INCLUDE_DIRECTORIES(
 )
 
 # main-wrapper library (with tap-compatible option).
-ADD_LIBRARY(gunit STATIC
+ADD_LIBRARY(gunit_small STATIC
   gunit_test_main.cc tap_event_listener.cc thread_utils.cc)
-TARGET_LINK_LIBRARIES(gunit mysys mytap dbug strings ${GTEST_LIBRARIES})
+ADD_LIBRARY(gunit_large STATIC
+  gunit_test_main_server.cc test_utils.cc tap_event_listener.cc thread_utils.cc)
+ADD_DEPENDENCIES(gunit_small GenError)
+ADD_DEPENDENCIES(gunit_large GenError)
+TARGET_LINK_LIBRARIES(gunit_small mysys mytap dbug strings ${GTEST_LIBRARIES})
+TARGET_LINK_LIBRARIES(gunit_large mysys mytap dbug strings ${GTEST_LIBRARIES})
 MESSAGE(STATUS "GTEST_LIBRARIES:${GTEST_LIBRARIES}")
 
 # Add some defines.
@@ -252,21 +257,20 @@ SET(SERVER_TESTS
   create_field
   delayable_insert_operation
   field
-  field_timestamp
+  get_diagnostics
   item
   item_func_now_local
+  join_tab_sort
   my_decimal
   opt_range
   opt_trace
-  sql_table
-  get_diagnostics
   segfault
-  join_tab_sort
+  sql_table
 )
 
 FOREACH(test ${TESTS})
   ADD_EXECUTABLE(${test}-t ${test}-t.cc)
-  TARGET_LINK_LIBRARIES(${test}-t gunit sqlgunitlib strings dbug regex)
+  TARGET_LINK_LIBRARIES(${test}-t gunit_small sqlgunitlib strings dbug regex)
   IF(APPLE AND GTEST_DYLIB_LOCATION)
     ADD_CUSTOM_COMMAND(TARGET ${test}-t POST_BUILD
       COMMAND install_name_tool -change
@@ -278,12 +282,13 @@ ENDFOREACH()
 
 FOREACH(test ${SERVER_TESTS})
   IF(WIN32)
-    ADD_EXECUTABLE(${test}-t ${test}-t.cc test_utils.cc ../../sql/nt_servc.cc)
+    ADD_EXECUTABLE(${test}-t ${test}-t.cc ../../sql/nt_servc.cc)
   ELSE()
-    ADD_EXECUTABLE(${test}-t ${test}-t.cc test_utils.cc)
+    ADD_EXECUTABLE(${test}-t ${test}-t.cc)
   ENDIF()
   TARGET_LINK_LIBRARIES(${test}-t sql binlog rpl master slave sql)
-  TARGET_LINK_LIBRARIES(${test}-t gunit sqlgunitlib strings dbug regex mysys)
+  TARGET_LINK_LIBRARIES(${test}-t gunit_large strings dbug regex mysys)
+  TARGET_LINK_LIBRARIES(${test}-t sql binlog rpl master slave sql)
   IF(APPLE AND GTEST_DYLIB_LOCATION)
     ADD_CUSTOM_COMMAND(TARGET ${test}-t POST_BUILD
       COMMAND install_name_tool -change

=== modified file 'unittest/gunit/copy_info-t.cc'
--- a/unittest/gunit/copy_info-t.cc	2012-01-31 15:16:16 +0000
+++ b/unittest/gunit/copy_info-t.cc	2012-05-07 12:05:48 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -38,12 +38,7 @@ using my_testing::Mock_error_handler;
 class CopyInfoTest : public ::testing::Test
 {
 protected:
-  static void SetUpTestCase() { Server_initializer::SetUpTestCase(); }
-
-  static void TearDownTestCase() { Server_initializer::TearDownTestCase(); }
-
   virtual void SetUp() { initializer.SetUp(); }
-
   virtual void TearDown() { initializer.TearDown(); }
 
   Server_initializer initializer;

=== modified file 'unittest/gunit/create_field-t.cc'
--- a/unittest/gunit/create_field-t.cc	2012-01-31 15:16:16 +0000
+++ b/unittest/gunit/create_field-t.cc	2012-05-07 12:05:48 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -30,12 +30,7 @@ using my_testing::Mock_error_handler;
 class CreateFieldTest : public ::testing::Test
 {
 protected:
-  static void SetUpTestCase() { Server_initializer::SetUpTestCase(); }
-
-  static void TearDownTestCase() { Server_initializer::TearDownTestCase(); }
-
   virtual void SetUp() { initializer.SetUp(); }
-
   virtual void TearDown() { initializer.TearDown(); }
 
   Server_initializer initializer;

=== modified file 'unittest/gunit/decimal-t.cc'
--- a/unittest/gunit/decimal-t.cc	2012-04-27 11:57:38 +0000
+++ b/unittest/gunit/decimal-t.cc	2012-05-07 12:05:48 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by

=== modified file 'unittest/gunit/fake_table.h'
--- a/unittest/gunit/fake_table.h	2012-05-02 08:30:33 +0000
+++ b/unittest/gunit/fake_table.h	2012-05-07 08:29:18 +0000
@@ -52,6 +52,7 @@ class Fake_TABLE: public TABLE
     null_row= '\0';
     write_set= &write_set_struct;
     read_set= NULL;
+    next_number_field= NULL; // No autoinc column
 
     EXPECT_EQ(0, bitmap_init(write_set, &write_set_buf, s->fields, false));
 

=== modified file 'unittest/gunit/field-t.cc'
--- a/unittest/gunit/field-t.cc	2012-04-12 14:29:14 +0000
+++ b/unittest/gunit/field-t.cc	2012-05-07 12:05:48 +0000
@@ -22,6 +22,7 @@
 
 #include "field.h"
 #include "sql_time.h"
+#include <my_decimal.h>
 
 namespace {
 
@@ -31,9 +32,6 @@ using my_testing::Mock_error_handler;
 class FieldTest : public ::testing::Test
 {
 protected:
-  static void SetUpTestCase() { Server_initializer::SetUpTestCase(); }
-  static void TearDownTestCase() { Server_initializer::TearDownTestCase(); }
-
   virtual void SetUp() { initializer.SetUp(); }
   virtual void TearDown() { initializer.TearDown(); }
 
@@ -222,31 +220,31 @@ TEST_F(FieldTest, FieldTimef)
   
   // Not testing make_field, it also needs a mock TABLE object
   
-  EXPECT_EQ(0, field->store("12:23:12.123456", 15, &my_charset_numeric));
+  EXPECT_EQ(TYPE_OK, field->store("12:23:12.123456", 15, &my_charset_numeric));
   EXPECT_DOUBLE_EQ(122312.1235, field->val_real());
 
-  EXPECT_EQ(0, field->store_decimal(dec));
+  EXPECT_EQ(TYPE_OK, field->store_decimal(dec));
   EXPECT_DOUBLE_EQ(122312.1234, field->val_real());
 
-  EXPECT_EQ(0, field->store(-234545, false));
+  EXPECT_EQ(TYPE_OK, field->store(-234545, false));
   EXPECT_DOUBLE_EQ(-234545.0, field->val_real());
   
   {
     // Test that store() with a to big number gives right error
     Mock_error_handler error_handler(thd(), ER_TRUNCATED_WRONG_VALUE);
-    EXPECT_EQ(1, field->store(0x80000000, true));
+    EXPECT_EQ(TYPE_WARN_OUT_OF_RANGE, field->store(0x80000000, true));
     // Test that error handler was actually called
     EXPECT_EQ(1, error_handler.handle_called());
     // Test that field contains expecte max time value
     EXPECT_DOUBLE_EQ(8385959, field->val_real());  // Max time value
   }
 
-  EXPECT_EQ(0, field->store(1234545.555555));
+  EXPECT_EQ(TYPE_OK, field->store(1234545.555555));
   EXPECT_DOUBLE_EQ(1234545.5556, field->val_real());
 
   // Some of the functions inherited from Field
   Field *f= field;
-  EXPECT_EQ(0, f->store_time(&time, MYSQL_TIMESTAMP_TIME)); 
+  EXPECT_EQ(TYPE_OK, f->store_time(&time, MYSQL_TIMESTAMP_TIME));
   EXPECT_DOUBLE_EQ(122312.1234, f->val_real());  // Why decimals  here?
   EXPECT_STREQ("12:23:12.1234", f->val_str(&timeStr)->c_ptr());
   EXPECT_STREQ("122312", f->val_int_as_str(&timeStr, false)->c_ptr());
@@ -408,3 +406,9 @@ TEST_F(FieldTest, CopyFieldSet)
 
 
 }
+
+#include "field_date-t.cc"
+#include "field_datetime-t.cc"
+#include "field_long-t.cc"
+#include "field_newdecimal-t.cc"
+#include "field_timestamp-t.cc"

=== added file 'unittest/gunit/field_date-t.cc'
--- a/unittest/gunit/field_date-t.cc	1970-01-01 00:00:00 +0000
+++ b/unittest/gunit/field_date-t.cc	2012-05-07 12:05:48 +0000
@@ -0,0 +1,341 @@
+/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+// First include (the generated) my_config.h, to get correct platform defines.
+#include "my_config.h"
+#include <gtest/gtest.h>
+
+#include "field_temporal_utils.h"
+#include "test_utils.h"
+#include "fake_table.h"
+
+#include "field.h"
+
+namespace {
+
+using my_testing::Server_initializer;
+using my_testing::Mock_error_handler;
+
+class FieldDateTest : public ::testing::Test
+{
+protected:
+  virtual void SetUp() { initializer.SetUp(); }
+  virtual void TearDown() { initializer.TearDown(); }
+
+  THD *thd() { return initializer.thd(); }
+
+  Server_initializer initializer;
+
+  Field_set *create_field_set(TYPELIB *tl);
+
+  // Store zero date using different combinations of SQL modes
+  static const int no_modes= 4;
+  static const sql_mode_t strict_modes[no_modes];
+
+  static const type_conversion_status nozero_expected_status[];
+};
+
+const sql_mode_t FieldDateTest::strict_modes[no_modes]=
+{
+  0,
+  MODE_STRICT_TRANS_TABLES,
+  MODE_STRICT_ALL_TABLES,
+  MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES
+};
+
+const type_conversion_status FieldDateTest::nozero_expected_status[]=
+{
+  TYPE_NOTE_TIME_TRUNCATED,
+  TYPE_ERR_BAD_VALUE,
+  TYPE_ERR_BAD_VALUE,
+  TYPE_ERR_BAD_VALUE
+};
+
+
+class Mock_field_date : public Field_newdate
+{
+private:
+  uchar buffer[PACK_LENGTH];
+  uchar null_byte;
+
+  void initialize()
+  {
+    ptr= buffer;
+    null_ptr= &null_byte;
+    memset(buffer, 0, PACK_LENGTH);
+    null_byte= '\0';
+  }
+public:
+
+  Mock_field_date()
+    : Field_newdate(0,                          // ptr_arg
+                    NULL,                       // null_ptr_arg
+                    1,                          // null_bit_arg
+                    Field::NONE,                // unireg_check_arg
+                    "field_name")               // field_name_arg
+  {
+    initialize();
+  }
+
+  void make_writable() { bitmap_set_bit(table->write_set, field_index); }
+};
+
+
+TEST_F(FieldDateTest, StoreLegalStringValues)
+{
+  Mock_field_date field_date;
+  Fake_TABLE table(&field_date);
+  table.in_use= thd();
+  field_date.make_writable();
+
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_date, STRING_WITH_LEN("2001-01-01"),
+                      "2001-01-01", 0, TYPE_OK);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_date, STRING_WITH_LEN("0000-00-00"),
+                      "0000-00-00", 0, TYPE_OK);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_date, STRING_WITH_LEN("0001-00-00"),
+                      "0001-00-00", 0, TYPE_OK);
+  }
+}
+
+TEST_F(FieldDateTest, StoreIllegalStringValues)
+{
+  Mock_field_date field_date;
+  Fake_TABLE table(&field_date);
+  table.in_use= thd();
+  field_date.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+  // Truncates time
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_date, STRING_WITH_LEN("2001-01-01 00:00:01"),
+                      "2001-01-01",
+                      WARN_DATA_TRUNCATED, TYPE_NOTE_TIME_TRUNCATED);
+  }
+
+  // Bad year
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_date, STRING_WITH_LEN("99999-01-01"),
+                      "0000-00-00",
+                      WARN_DATA_TRUNCATED, TYPE_ERR_BAD_VALUE);
+  }
+
+  // Bad month
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_date, STRING_WITH_LEN("2001-13-01"), "0000-00-00",
+                      WARN_DATA_TRUNCATED, TYPE_ERR_BAD_VALUE);
+  }
+
+  // Bad day
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_date, STRING_WITH_LEN("2001-01-32"), "0000-00-00",
+                      WARN_DATA_TRUNCATED, TYPE_ERR_BAD_VALUE);
+  }
+
+  // Not a date
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_date, STRING_WITH_LEN("foo"), "0000-00-00",
+                      WARN_DATA_TRUNCATED, TYPE_ERR_BAD_VALUE);
+  }
+}
+
+
+
+/**
+  Strictness mode test 1:
+
+  Try storing dates with zeroes when no zero-restrictions apply
+  (neither NO_ZERO_DATE or NO_ZERO_IN_DATE are set). There should be
+  no errors, warnings or notes.
+*/
+TEST_F(FieldDateTest, StoreZeroDateSqlModeNoZeroRestrictions)
+{
+  Mock_field_date field_date;
+  Fake_TABLE table(&field_date);
+  table.in_use= thd();
+  field_date.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_date, STRING_WITH_LEN("0000-00-00"),
+                           "0000-00-00", TYPE_OK, strict_modes[i], 0);
+  }
+
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_date, STRING_WITH_LEN("0000-01-01"),
+                           "0000-01-01", TYPE_OK, strict_modes[i], 0);
+
+  }
+
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_date, STRING_WITH_LEN("2001-00-01"),
+                           "2001-00-01", TYPE_OK, strict_modes[i], 0);
+
+  }
+
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_date, STRING_WITH_LEN("2001-01-00"),
+                           "2001-01-00", TYPE_OK, strict_modes[i], 0);
+  }
+}
+
+
+/**
+  Strictness mode test 2:
+
+  Try storing dates with zeroes when NO_ZERO_DATE flag is set. There
+  should be no errors, warnings or notes unless the entire date is
+  zero: "0000-00-00"
+*/
+TEST_F(FieldDateTest, StoreZeroDateSqlModeNoZeroDate)
+{
+  Mock_field_date field_date;
+  Fake_TABLE table(&field_date);
+  table.in_use= thd();
+  field_date.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+  // With "MODE_NO_ZERO_DATE" set - Errors if date is all null
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_date,
+                           STRING_WITH_LEN("0000-00-00"),
+                           "0000-00-00",
+                           nozero_expected_status[i],
+                           MODE_NO_ZERO_DATE | strict_modes[i],
+                           ER_WARN_DATA_OUT_OF_RANGE);
+  }
+
+  // Zero year, month or day is fine
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_date,
+                           STRING_WITH_LEN("0000-01-01"),
+                           "0000-01-01",
+                           TYPE_OK,
+                           MODE_NO_ZERO_DATE | strict_modes[i],
+                           0);
+  }
+
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_date,
+                           STRING_WITH_LEN("2001-00-01"),
+                           "2001-00-01",
+                           TYPE_OK,
+                           MODE_NO_ZERO_DATE | strict_modes[i],
+                           0);
+  }
+
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_date,
+                           STRING_WITH_LEN("2001-01-00"),
+                           "2001-01-00",
+                           TYPE_OK,
+                           MODE_NO_ZERO_DATE | strict_modes[i],
+                           0);
+  }
+}
+
+/**
+  Strictness mode test 3:
+
+  Try storing dates with zeroes when NO_ZERO_IN_DATE flag is set. There
+  should be no errors unless either month or day is zero.
+*/
+TEST_F(FieldDateTest, StoreZeroDateSqlModeNoZeroInDate)
+{
+  Mock_field_date field_date;
+  Fake_TABLE table(&field_date);
+  table.in_use= thd();
+  field_date.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+  // With "MODE_NO_ZERO_IN_DATE" set - Entire date zero is ok
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_date,
+                           STRING_WITH_LEN("0000-00-00"),
+                           "0000-00-00",
+                           TYPE_OK,
+                           MODE_NO_ZERO_IN_DATE | strict_modes[i],
+                           0);
+  }
+
+  // Year 0 is valid in strict mode too
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_date,
+                           STRING_WITH_LEN("0000-01-01"),
+                           "0000-01-01",
+                           TYPE_OK,
+                           MODE_NO_ZERO_IN_DATE | strict_modes[i],
+                           0);
+  }
+
+  // Month 0 is NOT valid in strict mode, stores all-zero date
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_date,
+                           STRING_WITH_LEN("2001-00-01"),
+                           "0000-00-00",
+                           nozero_expected_status[i],
+                           MODE_NO_ZERO_IN_DATE | strict_modes[i],
+                           ER_WARN_DATA_OUT_OF_RANGE);
+  }
+
+  // Day 0 is NOT valid in strict mode, stores all-zero date
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_date,
+                           STRING_WITH_LEN("2001-01-00"),
+                           "0000-00-00",
+                           nozero_expected_status[i],
+                           MODE_NO_ZERO_IN_DATE | strict_modes[i],
+                           ER_WARN_DATA_OUT_OF_RANGE);
+  }
+}
+
+
+}

=== added file 'unittest/gunit/field_datetime-t.cc'
--- a/unittest/gunit/field_datetime-t.cc	1970-01-01 00:00:00 +0000
+++ b/unittest/gunit/field_datetime-t.cc	2012-05-07 12:05:48 +0000
@@ -0,0 +1,368 @@
+/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+// First include (the generated) my_config.h, to get correct platform defines.
+#include "my_config.h"
+#include <gtest/gtest.h>
+
+#include "field_temporal_utils.h"
+#include "test_utils.h"
+#include "fake_table.h"
+
+#include "field.h"
+
+namespace {
+
+using my_testing::Server_initializer;
+using my_testing::Mock_error_handler;
+
+class FieldDatetimeTest : public ::testing::Test
+{
+protected:
+  virtual void SetUp() { initializer.SetUp(); }
+  virtual void TearDown() { initializer.TearDown(); }
+
+  THD *thd() { return initializer.thd(); }
+
+  Server_initializer initializer;
+
+  Field_set *create_field_set(TYPELIB *tl);
+};
+
+
+class Mock_field_datetime : public Field_datetime
+{
+private:
+  uchar buffer[PACK_LENGTH];
+  uchar null_byte;
+
+  void initialize()
+  {
+    ptr= buffer;
+    null_ptr= &null_byte;
+    memset(buffer, 0, PACK_LENGTH);
+    null_byte= '\0';
+  }
+
+public:
+
+  Mock_field_datetime()
+    : Field_datetime(0,                         // ptr_arg
+                     NULL,                      // null_ptr_arg
+                     1,                         // null_bit_arg
+                     Field::NONE,               // unireg_check_arg
+                     "field_name")              // field_name_arg
+  {
+    initialize();
+  }
+
+  void make_writable() { bitmap_set_bit(table->write_set, field_index); }
+};
+
+
+TEST_F(FieldDatetimeTest, StoreLegalStringValues)
+{
+  char buff[MAX_FIELD_WIDTH];
+  String str(buff, sizeof(buff), &my_charset_bin);
+  String unused;
+
+  Mock_field_datetime field_dt;
+  Fake_TABLE table(&field_dt);
+  table.in_use= thd();
+  field_dt.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_dt, STRING_WITH_LEN("2001-01-01 00:00:01"),
+                      "2001-01-01 00:00:01", 0, TYPE_OK);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_dt, STRING_WITH_LEN("0000-00-00 00:00:00"),
+                      "0000-00-00 00:00:00", 0, TYPE_OK);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_dt, STRING_WITH_LEN("0001-00-00 00:00:00"),
+                      "0001-00-00 00:00:00", 0, TYPE_OK);
+  }
+}
+
+
+TEST_F(FieldDatetimeTest, StoreIllegalStringValues)
+{
+  Mock_field_datetime field_dt;
+  Fake_TABLE table(&field_dt);
+  table.in_use= thd();
+  field_dt.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+  // Bad year
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_dt, STRING_WITH_LEN("99999-01-01 00:00:01"),
+                      "0000-00-00 00:00:00",
+                      WARN_DATA_TRUNCATED, TYPE_ERR_BAD_VALUE);
+  }
+
+  // Bad month
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_dt, STRING_WITH_LEN("2001-13-01 00:00:01"),
+                      "0000-00-00 00:00:00",
+                      WARN_DATA_TRUNCATED, TYPE_ERR_BAD_VALUE);
+  }
+
+  // Bad day
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_dt, STRING_WITH_LEN("2001-01-32 00:00:01"),
+                      "0000-00-00 00:00:00",
+                      WARN_DATA_TRUNCATED, TYPE_ERR_BAD_VALUE);
+  }
+
+  // Bad hour
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_dt, STRING_WITH_LEN("2001-01-01 72:00:01"),
+                      "0000-00-00 00:00:00",
+                      WARN_DATA_TRUNCATED, TYPE_ERR_BAD_VALUE);
+  }
+
+  // Bad minute
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_dt, STRING_WITH_LEN("2001-01-01 00:72:01"),
+                      "0000-00-00 00:00:00",
+                      WARN_DATA_TRUNCATED, TYPE_ERR_BAD_VALUE);
+  }
+
+  // Bad second
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_dt, STRING_WITH_LEN("2001-01-01 00:00:72"),
+                      "0000-00-00 00:00:00",
+                      WARN_DATA_TRUNCATED, TYPE_ERR_BAD_VALUE);
+  }
+
+  // Not a day
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_dt, STRING_WITH_LEN("foo"), "0000-00-00 00:00:00",
+                      WARN_DATA_TRUNCATED, TYPE_ERR_BAD_VALUE);
+  }
+}
+
+
+// Store zero date using different combinations of SQL modes
+static const int no_modes= 4;
+static const sql_mode_t strict_modes[no_modes]=
+ {
+   0,
+   MODE_STRICT_TRANS_TABLES,
+   MODE_STRICT_ALL_TABLES,
+   MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES
+ };
+
+
+/**
+  Strictness mode test 1:
+
+  Try storing dates with zeroes when no zero-restrictions apply
+  (neither NO_ZERO_DATE or NO_ZERO_IN_DATE are set). There should be
+  no errors, warnings or notes.
+*/
+TEST_F(FieldDatetimeTest, StoreZeroDateSqlModeNoZeroRestrictions)
+{
+  Mock_field_datetime field_dt;
+  Fake_TABLE table(&field_dt);
+  table.in_use= thd();
+  field_dt.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_dt,
+                           STRING_WITH_LEN("0000-00-00 00:00:00"),
+                           "0000-00-00 00:00:00",
+                           TYPE_OK, strict_modes[i], 0);
+  }
+
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_dt,
+                           STRING_WITH_LEN("0000-01-01 00:00:00"),
+                           "0000-01-01 00:00:00",
+                           TYPE_OK, strict_modes[i], 0);
+  }
+
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_dt,
+                           STRING_WITH_LEN("2001-00-01 00:00:00"),
+                           "2001-00-01 00:00:00",
+                           TYPE_OK, strict_modes[i], 0);
+  }
+
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_dt,
+                           STRING_WITH_LEN("2001-01-00 00:00:00"),
+                           "2001-01-00 00:00:00",
+                           TYPE_OK, strict_modes[i], 0);
+  }
+}
+
+
+static const type_conversion_status nozero_expected_status[]=
+  {
+    TYPE_NOTE_TIME_TRUNCATED,
+    TYPE_ERR_BAD_VALUE,
+    TYPE_ERR_BAD_VALUE,
+    TYPE_ERR_BAD_VALUE
+  };
+
+/**
+  Strictness mode test 2:
+
+  Try storing dates with zeroes when NO_ZERO_DATE flag is set. There
+  should be no errors, warnings or notes unless the entire date is
+  zero: "0000-00-00"
+*/
+TEST_F(FieldDatetimeTest, StoreZeroDateSqlModeNoZeroDate)
+{
+  Mock_field_datetime field_dt;
+  Fake_TABLE table(&field_dt);
+  table.in_use= thd();
+  field_dt.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+  // With "MODE_NO_ZERO_DATE" set - Errors if date is all null
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_dt,
+                           STRING_WITH_LEN("0000-00-00 00:00:00"),
+                           "0000-00-00 00:00:00",
+                           nozero_expected_status[i],
+                           MODE_NO_ZERO_DATE | strict_modes[i],
+                           ER_WARN_DATA_OUT_OF_RANGE);
+  }
+
+  // Zero year, month or day is fine
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_dt,
+                           STRING_WITH_LEN("0000-01-01 00:00:00"),
+                           "0000-01-01 00:00:00",
+                           TYPE_OK,
+                           MODE_NO_ZERO_DATE | strict_modes[i],
+                           0);
+  }
+
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_dt,
+                           STRING_WITH_LEN("2001-00-01 00:00:00"),
+                           "2001-00-01 00:00:00",
+                           TYPE_OK,
+                           MODE_NO_ZERO_DATE | strict_modes[i],
+                           0);
+  }
+
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_dt,
+                           STRING_WITH_LEN("2001-01-00 00:00:00"),
+                           "2001-01-00 00:00:00",
+                           TYPE_OK,
+                           MODE_NO_ZERO_DATE | strict_modes[i],
+                           0);
+  }
+}
+
+/**
+  Strictness mode test 3:
+
+  Try storing dates with zeroes when NO_ZERO_IN_DATE flag is set. There
+  should be no errors unless either month or day is zero.
+*/
+TEST_F(FieldDatetimeTest, StoreZeroDateSqlModeNoZeroInDate)
+{
+  Mock_field_datetime field_dt;
+  Fake_TABLE table(&field_dt);
+  table.in_use= thd();
+  field_dt.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+  // With "MODE_NO_ZERO_IN_DATE" set - Entire date zero is ok
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_dt,
+                           STRING_WITH_LEN("0000-00-00 00:00:00"),
+                           "0000-00-00 00:00:00",
+                           TYPE_OK,
+                           MODE_NO_ZERO_IN_DATE | strict_modes[i],
+                           0);
+  }
+
+  // Year 0 is valid in strict mode too
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_dt,
+                           STRING_WITH_LEN("0000-01-01 00:00:00"),
+                           "0000-01-01 00:00:00",
+                           TYPE_OK,
+                           MODE_NO_ZERO_IN_DATE | strict_modes[i],
+                           0);
+  }
+
+  // Month 0 is NOT valid in strict mode, stores all-zero date
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_dt,
+                           STRING_WITH_LEN("2001-00-01 00:00:00"),
+                           "0000-00-00 00:00:00",
+                           nozero_expected_status[i],
+                           MODE_NO_ZERO_IN_DATE | strict_modes[i],
+                           ER_WARN_DATA_OUT_OF_RANGE);
+  }
+
+  // Day 0 is NOT valid in strict mode, stores all-zero date
+  for (int i= 0; i < no_modes; i++)
+  {
+    SCOPED_TRACE("");
+    store_zero_in_sql_mode(&field_dt,
+                           STRING_WITH_LEN("2001-01-00 00:00:00"),
+                           "0000-00-00 00:00:00",
+                           nozero_expected_status[i],
+                           MODE_NO_ZERO_IN_DATE | strict_modes[i],
+                           ER_WARN_DATA_OUT_OF_RANGE);
+  }
+}
+
+
+}

=== added file 'unittest/gunit/field_long-t.cc'
--- a/unittest/gunit/field_long-t.cc	1970-01-01 00:00:00 +0000
+++ b/unittest/gunit/field_long-t.cc	2012-05-07 12:05:48 +0000
@@ -0,0 +1,383 @@
+/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+// First include (the generated) my_config.h, to get correct platform defines.
+#include "my_config.h"
+#include <gtest/gtest.h>
+
+#include "test_utils.h"
+#include "fake_table.h"
+
+#include "field.h"
+
+namespace {
+
+using my_testing::Server_initializer;
+using my_testing::Mock_error_handler;
+
+class FieldLongTest : public ::testing::Test
+{
+protected:
+  virtual void SetUp() { initializer.SetUp(); }
+  virtual void TearDown() { initializer.TearDown(); }
+
+  THD *thd() { return initializer.thd(); }
+
+  Server_initializer initializer;
+
+  Field_set *create_field_set(TYPELIB *tl);
+};
+
+class Mock_field_long : public Field_long
+{
+  uchar buffer[PACK_LENGTH];
+  uchar null_byte;
+  void initialize()
+  {
+    ptr= buffer;
+    null_ptr= &null_byte;
+    memset(buffer, 0, PACK_LENGTH);
+    null_byte= '\0';
+  }
+public:
+  Mock_field_long()
+    : Field_long(0,                             // ptr_arg
+                 8,                             // len_arg
+                 NULL,                          // null_ptr_arg
+                 1,                             // null_bit_arg
+                 Field::NONE,                   // unireg_check_arg
+                 "field_name",                  // field_name_arg
+                 false,                         // zero_arg
+                 false)                         // unsigned_arg
+  {
+    initialize();
+  }
+
+  void make_writable() { bitmap_set_bit(table->write_set, field_index); }
+
+};
+
+void test_store_long(Field_long *field,
+                     const longlong store_value,
+                     const longlong expected_result,
+                     const int expected_error_no,
+                     const type_conversion_status expected_status)
+{
+  Mock_error_handler error_handler(field->table->in_use, expected_error_no);
+  type_conversion_status err= field->store(store_value, false); // signed
+  EXPECT_EQ(expected_result, field->val_int());
+  EXPECT_FALSE(field->is_null());
+  EXPECT_EQ(expected_status, err);
+  EXPECT_EQ((expected_error_no == 0 ? 0 : 1), error_handler.handle_called());
+}
+
+void test_store_string(Field_long *field,
+                       const char *store_value, const int length,
+                       const longlong expected_result,
+                       const int expected_error_no,
+                       const type_conversion_status expected_status)
+{
+  Mock_error_handler error_handler(field->table->in_use, expected_error_no);
+  type_conversion_status err= field->store(store_value, length,
+                                           &my_charset_latin1);
+  EXPECT_EQ(expected_result, field->val_int());
+  EXPECT_FALSE(field->is_null());
+  EXPECT_EQ(expected_status, err);
+  EXPECT_EQ((expected_error_no == 0 ? 0 : 1), error_handler.handle_called());
+}
+
+
+TEST_F(FieldLongTest, StoreLegalIntValues)
+{
+  Mock_field_long field_long;
+  Fake_TABLE table(&field_long);
+  table.in_use= thd();
+  field_long.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+  SCOPED_TRACE(""); test_store_long(&field_long, 0,   0, 0, TYPE_OK);
+  SCOPED_TRACE(""); test_store_long(&field_long, 5,   5, 0, TYPE_OK);
+  SCOPED_TRACE(""); test_store_long(&field_long, -1, -1, 0, TYPE_OK);
+
+  {
+    SCOPED_TRACE("");
+    test_store_long(&field_long, INT_MIN32, INT_MIN32, 0, TYPE_OK);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_long(&field_long, INT_MAX32, INT_MAX32, 0, TYPE_OK);
+  }
+
+  {
+    Mock_error_handler error_handler(thd(), 0);
+    type_conversion_status err;
+    err= set_field_to_null(&field_long);
+
+    EXPECT_EQ(0, field_long.val_int());
+    EXPECT_TRUE(field_long.is_null());
+    EXPECT_EQ(TYPE_OK, err);
+
+    field_long.set_notnull();
+    EXPECT_EQ(0, field_long.val_int());
+    EXPECT_FALSE(field_long.is_null());
+
+    // None of the above should generate warnings
+    EXPECT_EQ(0, error_handler.handle_called());
+  }
+}
+
+// Values higher and lower than valid range for the Field_long
+TEST_F(FieldLongTest, StoreOutOfRangeIntValues)
+{
+  Mock_field_long field_long;
+  Fake_TABLE table(&field_long);
+  table.in_use= thd();
+  field_long.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+
+  // Field_long is signed
+  {
+    SCOPED_TRACE("");
+    test_store_long(&field_long, INT_MAX32 + 1LL, INT_MAX32,
+                    ER_WARN_DATA_OUT_OF_RANGE,
+                    TYPE_WARN_OUT_OF_RANGE);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_long(&field_long, INT_MIN32 - 1LL, INT_MIN32,
+                    ER_WARN_DATA_OUT_OF_RANGE,
+                    TYPE_WARN_OUT_OF_RANGE);
+  }
+
+  // Field_long is unsigned
+  {
+    SCOPED_TRACE("");
+    field_long.unsigned_flag= true;
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_long(&field_long, -1LL, 0, ER_WARN_DATA_OUT_OF_RANGE,
+                    TYPE_WARN_OUT_OF_RANGE);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_long(&field_long, INT_MIN32, 0, ER_WARN_DATA_OUT_OF_RANGE,
+                    TYPE_WARN_OUT_OF_RANGE);
+  }
+
+}
+
+
+TEST_F(FieldLongTest, StoreLegalStringValues)
+{
+  Mock_field_long field_long;
+
+  Fake_TABLE table(&field_long);
+  table.in_use= thd();
+  field_long.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+  const char min_int[]= "-2147483648";
+  const char max_int[]= "2147483647";
+  const char max_int_plus1[]= "2147483648";
+  const char max_uint[]= "4294967295";
+
+  // Field_long is signed
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_long, STRING_WITH_LEN("0"),   0, 0, TYPE_OK);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_long, STRING_WITH_LEN("1"),   1, 0, TYPE_OK);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_long, STRING_WITH_LEN("-1"), -1, 0, TYPE_OK);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_long, STRING_WITH_LEN(max_int), INT_MAX32,
+                      0, TYPE_OK);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_long, STRING_WITH_LEN(min_int), INT_MIN32,
+                      0, TYPE_OK);
+  }
+
+  // Field_long is unsigned
+  field_long.unsigned_flag= true;
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_long, STRING_WITH_LEN(max_int_plus1),
+                      INT_MAX32 + 1LL,
+                      0, TYPE_OK);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_long, STRING_WITH_LEN(max_uint), UINT_MAX32,
+                      0, TYPE_OK);
+  }
+}
+
+
+TEST_F(FieldLongTest, StoreIllegalStringValues)
+{
+  Mock_field_long field_long;
+
+  Fake_TABLE table(&field_long);
+  table.in_use= thd();
+  field_long.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+  const char max_int_plus1[]=  "2147483648";
+  const char min_int_minus1[]= "-2147483649";
+  const char very_high[]=      "999999999999999";
+  const char very_low[]=       "-999999999999999";
+
+  // Field_long is signed - Stored value is INT_MIN32/INT_MAX32
+  //                        depending on sign of string to store
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_long, STRING_WITH_LEN(max_int_plus1), INT_MAX32,
+                      ER_WARN_DATA_OUT_OF_RANGE,
+                      TYPE_WARN_OUT_OF_RANGE);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_long, STRING_WITH_LEN(very_high), INT_MAX32,
+                      ER_WARN_DATA_OUT_OF_RANGE,
+                      TYPE_WARN_OUT_OF_RANGE);
+
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_long, STRING_WITH_LEN(min_int_minus1), INT_MIN32,
+                      ER_WARN_DATA_OUT_OF_RANGE,
+                      TYPE_WARN_OUT_OF_RANGE);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_long, STRING_WITH_LEN(very_low), INT_MIN32,
+                      ER_WARN_DATA_OUT_OF_RANGE,
+                      TYPE_WARN_OUT_OF_RANGE);
+  }
+
+  // Field_long is unsigned - Stored value is 0/UINT_MAX32
+  //                          depending on sign of string to store
+  const char min_int[]=        "-2147483648";
+  const char max_uint_plus1[]= "4294967296";
+  field_long.unsigned_flag= true;
+
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_long, STRING_WITH_LEN(max_uint_plus1), UINT_MAX32,
+                      ER_WARN_DATA_OUT_OF_RANGE,
+                      TYPE_WARN_OUT_OF_RANGE);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_long, STRING_WITH_LEN(very_high), UINT_MAX32,
+                      ER_WARN_DATA_OUT_OF_RANGE,
+                      TYPE_WARN_OUT_OF_RANGE);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_long, STRING_WITH_LEN("-1"), 0,
+                      ER_WARN_DATA_OUT_OF_RANGE,
+                      TYPE_WARN_OUT_OF_RANGE);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_long, STRING_WITH_LEN(min_int), 0,
+                      ER_WARN_DATA_OUT_OF_RANGE,
+                      TYPE_WARN_OUT_OF_RANGE);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_long, STRING_WITH_LEN(very_low), 0,
+                      ER_WARN_DATA_OUT_OF_RANGE,
+                      TYPE_WARN_OUT_OF_RANGE);
+  }
+
+  // Invalid value
+  {
+    SCOPED_TRACE("");
+    test_store_string(&field_long, STRING_WITH_LEN("foo"), 0,
+                      ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
+                      TYPE_ERR_BAD_VALUE);
+  }
+}
+
+TEST_F(FieldLongTest, StoreNullValue)
+{
+  Mock_field_long field_long;
+
+  Fake_TABLE table(&field_long);
+  table.in_use= thd();
+  field_long.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+  type_conversion_status err;
+
+  // Save NULL value in a field that can have NULL value
+  {
+    Mock_error_handler error_handler(thd(), 0);
+    err= set_field_to_null(&field_long);
+    EXPECT_EQ(0, field_long.val_int());
+    EXPECT_EQ(TYPE_OK, err);
+
+    err= set_field_to_null_with_conversions(&field_long, true);
+    EXPECT_EQ(0, field_long.val_int());
+    EXPECT_EQ(TYPE_OK, err);
+
+    err= set_field_to_null_with_conversions(&field_long, false);
+    EXPECT_EQ(0, field_long.val_int());
+    EXPECT_EQ(TYPE_OK, err);
+
+    EXPECT_EQ(0, error_handler.handle_called());
+  }
+
+  // Save NULL value in a field that can NOT have NULL value
+  field_long.null_ptr= NULL;
+  {
+    Mock_error_handler error_handler(thd(), WARN_DATA_TRUNCATED);
+    err= set_field_to_null(&field_long);
+    EXPECT_EQ(0, field_long.val_int());
+    EXPECT_EQ(TYPE_OK, err);
+    EXPECT_EQ(1, error_handler.handle_called());
+  }
+
+  {
+    Mock_error_handler error_handler(thd(), 0);
+    err= set_field_to_null_with_conversions(&field_long, true);
+    EXPECT_EQ(0, field_long.val_int());
+    EXPECT_EQ(TYPE_ERR_NULL_CONSTRAINT_VIOLATION, err);
+    EXPECT_EQ(0, error_handler.handle_called());
+  }
+
+  {
+    Mock_error_handler error_handler(thd(), ER_BAD_NULL_ERROR);
+    err= set_field_to_null_with_conversions(&field_long, false);
+    EXPECT_EQ(0, field_long.val_int());
+    EXPECT_EQ(TYPE_OK, err);
+    EXPECT_EQ(1, error_handler.handle_called());
+  }
+}
+
+
+}

=== added file 'unittest/gunit/field_newdecimal-t.cc'
--- a/unittest/gunit/field_newdecimal-t.cc	1970-01-01 00:00:00 +0000
+++ b/unittest/gunit/field_newdecimal-t.cc	2012-05-07 12:05:48 +0000
@@ -0,0 +1,456 @@
+/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+// First include (the generated) my_config.h, to get correct platform defines.
+#include "my_config.h"
+#include <gtest/gtest.h>
+
+#include "test_utils.h"
+#include "fake_table.h"
+
+#include "field.h"
+
+type_conversion_status
+store_internal_with_error_check(Field_new_decimal *field,
+                                int conversion_err, my_decimal *value);
+namespace {
+
+using my_testing::Server_initializer;
+using my_testing::Mock_error_handler;
+
+class FieldNewDecimalTest : public ::testing::Test
+{
+protected:
+  virtual void SetUp() { initializer.SetUp(); }
+  virtual void TearDown() { initializer.TearDown(); }
+
+  THD *thd() { return initializer.thd(); }
+
+  Server_initializer initializer;
+
+  Field_set *create_field_set(TYPELIB *tl);
+};
+
+
+class Mock_field_new_decimal : public Field_new_decimal
+{
+  uchar buffer[MAX_FIELD_WIDTH];
+  uchar null_byte;
+  void initialize()
+  {
+    ptr= buffer;
+    null_ptr= &null_byte;
+    memset(buffer, 0, MAX_FIELD_WIDTH);
+    null_byte= '\0';
+  }
+
+public:
+  Mock_field_new_decimal(int decimals)
+    : Field_new_decimal(0,                      // ptr_arg
+                        8,                      // len_arg
+                        NULL,                   // null_ptr_arg
+                        1,                      // null_bit_arg
+                        Field::NONE,            // unireg_check_arg
+                        "field_name",           // field_name_arg
+                        decimals,               // dec_arg
+                        false,                  // zero_arg
+                        false)                  // unsigned_arg
+  {
+    initialize();
+  }
+
+  void make_writable() { bitmap_set_bit(table->write_set, field_index); }
+
+  void test_store_string(const char *store_value, const int length,
+                         const char *expected_string_result,
+                         const longlong expected_int_result,
+                         const double expected_real_result,
+                         const int expected_error_no,
+                         const type_conversion_status expected_status)
+  {
+    char buff[MAX_FIELD_WIDTH];
+    String str(buff, sizeof(buff), &my_charset_bin);
+    String unused;
+
+    Mock_error_handler error_handler(table->in_use, expected_error_no);
+    type_conversion_status err= store(store_value, length, &my_charset_latin1);
+    val_str(&str, &unused);
+    EXPECT_STREQ(expected_string_result, str.ptr());
+    EXPECT_EQ(expected_int_result, val_int());
+    EXPECT_EQ(expected_real_result, val_real());
+
+    EXPECT_FALSE(is_null());
+    EXPECT_EQ(expected_status, err);
+    EXPECT_EQ((expected_error_no == 0 ? 0 : 1), error_handler.handle_called());
+  }
+
+};
+
+
+TEST_F(FieldNewDecimalTest, StoreLegalStringValues)
+{
+  // Alows storing this range [-999.999, 999.999]
+  Mock_field_new_decimal field_dec(3);
+  Fake_TABLE table(&field_dec);
+  table.in_use= thd();
+  field_dec.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+  {
+    SCOPED_TRACE("");
+    field_dec.test_store_string(STRING_WITH_LEN("10.01"), "10.010", 10, 10.01,
+                                0, TYPE_OK);
+  }
+  {
+    SCOPED_TRACE("");
+    field_dec.test_store_string(STRING_WITH_LEN("0"), "0.000", 0, 0,
+                                0, TYPE_OK);
+  }
+}
+
+
+TEST_F(FieldNewDecimalTest, StoreIllegalStringValues)
+{
+  // Alows storing this range [-999.999, 999.999]
+  Mock_field_new_decimal field_dec(3);
+  Fake_TABLE table(&field_dec);
+  table.in_use= thd();
+  field_dec.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+  // Truncated (precision beyond 3 decimals is lost)
+  {
+    SCOPED_TRACE("");
+    field_dec.test_store_string(STRING_WITH_LEN("10.0101"), "10.010",
+                                10, 10.01,
+                                WARN_DATA_TRUNCATED, TYPE_NOTE_TRUNCATED);
+  }
+  {
+    SCOPED_TRACE("");
+    field_dec.test_store_string(STRING_WITH_LEN("10.0109"), "10.011",
+                                10, 10.011,
+                                WARN_DATA_TRUNCATED, TYPE_NOTE_TRUNCATED);
+  }
+  // Values higher and lower than valid range for the decimal
+  {
+    SCOPED_TRACE("");
+    field_dec.test_store_string(STRING_WITH_LEN("10000"), "999.999",
+                                1000, 999.999,
+                                ER_WARN_DATA_OUT_OF_RANGE,
+                                TYPE_WARN_OUT_OF_RANGE);
+  }
+
+  // Values higher and lower than valid range for the decimal
+  {
+    SCOPED_TRACE("");
+    field_dec.test_store_string(STRING_WITH_LEN("-10000"), "-999.999",
+                                -1000, -999.999,
+                                ER_WARN_DATA_OUT_OF_RANGE,
+                                TYPE_WARN_OUT_OF_RANGE);
+  }
+}
+
+
+static int chars_2_decimal(const char *chars, my_decimal *to)
+{
+  char *end= strend(chars);
+  return string2decimal(chars, to, &end);
+}
+
+static void test_store_internal(Field_new_decimal *field,
+                                my_decimal *value,
+                                const char *expected_string_result,
+                                const longlong expected_int_result,
+                                const double expected_real_result,
+                                const int conversion_error,
+                                const int expected_error_no,
+                                const type_conversion_status expected_status)
+{
+  char buff[MAX_FIELD_WIDTH];
+  String str(buff, sizeof(buff), &my_charset_bin);
+  String unused;
+
+  Mock_error_handler error_handler(field->table->in_use, expected_error_no);
+  type_conversion_status err=
+    store_internal_with_error_check(field, conversion_error, value);
+  field->val_str(&str, &unused);
+  EXPECT_STREQ(expected_string_result, str.ptr());
+  EXPECT_EQ(expected_int_result, field->val_int());
+  EXPECT_EQ(expected_real_result, field->val_real());
+
+  EXPECT_EQ(expected_status, err);
+}
+
+
+/**
+  Test store_internal_with_error_check(). This is an internal store
+  function for Field_new_decimal. The function does not modify the
+  NULL value of the field so we don't test field.is_null()
+*/
+TEST_F(FieldNewDecimalTest, storeInternalWithErrorCheckLegalValues)
+{
+  // Alows storing this range [-99.9999, 99.9999]
+  Mock_field_new_decimal field_dec(4);
+  Fake_TABLE table(&field_dec);
+  table.in_use= thd();
+  field_dec.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+  my_decimal d10_01;
+  my_decimal dMin10_01;
+  my_decimal d10_01001;
+  my_decimal d10_01009;
+  my_decimal dInsignificant;
+
+  EXPECT_EQ(0, chars_2_decimal("10.01", &d10_01));
+  EXPECT_EQ(0, chars_2_decimal("-10.01", &dMin10_01));
+  EXPECT_EQ(0, chars_2_decimal("10.01001", &d10_01001));
+  EXPECT_EQ(0, chars_2_decimal("10.01009", &d10_01009));
+  EXPECT_EQ(0, chars_2_decimal("0.00000000001", &dInsignificant));
+
+  // Legal values
+  {
+    SCOPED_TRACE("");
+    test_store_internal(&field_dec, &d10_01, "10.0100", 10, 10.01,
+                        E_DEC_OK, 0, TYPE_OK);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_internal(&field_dec, &dMin10_01, "-10.0100", -10, -10.01,
+                        E_DEC_OK, 0, TYPE_OK);
+  }
+
+  // Legal values, but rounded
+  {
+    SCOPED_TRACE("");
+    test_store_internal(&field_dec, &d10_01001, "10.0100", 10, 10.01,
+                        E_DEC_OK, WARN_DATA_TRUNCATED, TYPE_NOTE_TRUNCATED);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_internal(&field_dec, &d10_01009, "10.0101", 10, 10.0101,
+                        E_DEC_OK, WARN_DATA_TRUNCATED, TYPE_NOTE_TRUNCATED);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_internal(&field_dec, &dInsignificant, "0.0000", 0, 0, E_DEC_OK,
+                        WARN_DATA_TRUNCATED, TYPE_NOTE_TRUNCATED);
+  }
+}
+
+
+/**
+  Test store_internal_with_error_check() - out of range valuse
+*/
+TEST_F(FieldNewDecimalTest, storeInternalWithErrorCheckOutOfRange)
+{
+  // Alows storing this range [-99.9999, 99.9999]
+  Mock_field_new_decimal field_dec(4);
+  Fake_TABLE table(&field_dec);
+  table.in_use= thd();
+  field_dec.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+  my_decimal dTooHigh;
+  my_decimal dTooLow;
+
+  EXPECT_EQ(0, chars_2_decimal("1000", &dTooHigh));
+  EXPECT_EQ(0, chars_2_decimal("-1000", &dTooLow));
+
+  {
+    SCOPED_TRACE("");
+    test_store_internal(&field_dec, &dTooHigh, "99.9999", 100, 99.9999,
+                        E_DEC_OK, ER_WARN_DATA_OUT_OF_RANGE,
+                        TYPE_WARN_OUT_OF_RANGE);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_internal(&field_dec, &dTooLow, "-99.9999", -100, -99.9999,
+                        E_DEC_OK, ER_WARN_DATA_OUT_OF_RANGE,
+                        TYPE_WARN_OUT_OF_RANGE);
+  }
+
+}
+
+
+/**
+  Test store_internal_with_error_check() - Test first parameter: the error.
+
+  When E_DEC_OVERFLOW is specified, the min/max value (depends on
+  the sign of the input value) of the field is used to overwrite the
+  input decimal value because E_DEC_OVERFLOW indicates that the decimal
+  conversion got a number that was too high/low.
+*/
+TEST_F(FieldNewDecimalTest, storeInternalWithErrorCheckEDecOverflow)
+{
+  // Alows storing this range [-99.9999, 99.9999]
+  Mock_field_new_decimal field_dec(4);
+  Fake_TABLE table(&field_dec);
+  table.in_use= thd();
+  field_dec.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+  my_decimal d10_01;
+  my_decimal dMin10_01;
+  my_decimal dInsignificant;
+  my_decimal dTooHigh;
+  my_decimal dTooLow;
+
+  EXPECT_EQ(0, chars_2_decimal("10.01", &d10_01));
+  EXPECT_EQ(0, chars_2_decimal("-10.01", &dMin10_01));
+  EXPECT_EQ(0, chars_2_decimal("0.00000000001", &dInsignificant));
+  EXPECT_EQ(0, chars_2_decimal("1000", &dTooHigh));
+  EXPECT_EQ(0, chars_2_decimal("-1000", &dTooLow));
+
+  // Positive number - the field's MAX value is used
+  {
+    SCOPED_TRACE("");
+    test_store_internal(&field_dec, &d10_01, "99.9999", 100, 99.9999,
+                        E_DEC_OVERFLOW, ER_WARN_DATA_OUT_OF_RANGE,
+                        TYPE_WARN_OUT_OF_RANGE);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_internal(&field_dec, &dInsignificant, "99.9999", 100, 99.9999,
+                        E_DEC_OVERFLOW, ER_WARN_DATA_OUT_OF_RANGE,
+                        TYPE_WARN_OUT_OF_RANGE);
+
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_internal(&field_dec, &dTooHigh, "99.9999", 100, 99.9999,
+                        E_DEC_OVERFLOW, ER_WARN_DATA_OUT_OF_RANGE,
+                        TYPE_WARN_OUT_OF_RANGE);
+  }
+
+  // Negative number - the field's MIN value is used
+  {
+    SCOPED_TRACE("");
+    test_store_internal(&field_dec, &dMin10_01, "-99.9999", -100, -99.9999,
+                        E_DEC_OVERFLOW, ER_WARN_DATA_OUT_OF_RANGE,
+                        TYPE_WARN_OUT_OF_RANGE);
+
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_internal(&field_dec, &dTooLow, "-99.9999", -100, -99.9999,
+                        E_DEC_OVERFLOW, ER_WARN_DATA_OUT_OF_RANGE,
+                        TYPE_WARN_OUT_OF_RANGE);
+  }
+}
+
+
+/**
+  Test store_internal_with_error_check() - Test first parameter: the error.
+
+  When E_DEC_TRUNCATED is specified, a truncation warning will
+  appear iff Field_new_decimal::store_value() would otherwise not
+  issue a warning. The rationale is that E_DEC_TRUNCATED indicates
+  that the value to store has already been truncated, something that
+  will not be noticed by store_value(). However, the value is not
+  automatically changed like in the E_DEC_OVERFLOW case tested
+  above.
+*/
+TEST_F(FieldNewDecimalTest, storeInternalWithErrorCheckEDecTrunkated)
+{
+  // Alows storing this range [-99.9999, 99.9999]
+  Mock_field_new_decimal field_dec(4);
+  Fake_TABLE table(&field_dec);
+  table.in_use= thd();
+  field_dec.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+  my_decimal d10_01;
+  my_decimal dMin10_01;
+  my_decimal dInsignificant;
+  my_decimal dTooHigh;
+  my_decimal dTooLow;
+
+  EXPECT_EQ(0, chars_2_decimal("10.01", &d10_01));
+  EXPECT_EQ(0, chars_2_decimal("-10.01", &dMin10_01));
+  EXPECT_EQ(0, chars_2_decimal("0.00000000001", &dInsignificant));
+  EXPECT_EQ(0, chars_2_decimal("1000", &dTooHigh));
+  EXPECT_EQ(0, chars_2_decimal("-1000", &dTooLow));
+
+
+  // Conversion went fine
+  {
+    SCOPED_TRACE("");
+    test_store_internal(&field_dec, &d10_01, "10.0100", 10, 10.01,
+                        E_DEC_TRUNCATED, WARN_DATA_TRUNCATED,
+                        TYPE_NOTE_TRUNCATED);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_internal(&field_dec, &dMin10_01, "-10.0100", -10, -10.01,
+                        E_DEC_TRUNCATED, WARN_DATA_TRUNCATED,
+                        TYPE_NOTE_TRUNCATED);
+  }
+
+  {
+    SCOPED_TRACE("");
+    test_store_internal(&field_dec, &dInsignificant, "0.0000", 0, 0,
+                        E_DEC_TRUNCATED, WARN_DATA_TRUNCATED,
+                        TYPE_NOTE_TRUNCATED);
+  }
+
+  /*
+    In what follows, the values are out of range causing warning
+    ER_WARN_DATA_OUT_OF_RANGE instead of WARN_DATA_TRUNCATED.
+  */
+  {
+    SCOPED_TRACE("");
+    test_store_internal(&field_dec, &dTooHigh, "99.9999", 100, 99.9999,
+                        E_DEC_TRUNCATED, ER_WARN_DATA_OUT_OF_RANGE,
+                        TYPE_WARN_OUT_OF_RANGE);
+  }
+  {
+    SCOPED_TRACE("");
+    test_store_internal(&field_dec, &dTooLow, "-99.9999", -100, -99.9999,
+                        E_DEC_TRUNCATED, ER_WARN_DATA_OUT_OF_RANGE,
+                        TYPE_WARN_OUT_OF_RANGE);
+  }
+}
+
+
+/**
+  Test store_internal_with_error_check() - Test first parameter: the error.
+
+  Any E_DEC_* value other than E_DEC_OK, E_DEC_TRUNCATED and
+  E_DEC_OVERFLOW will be ignored.
+*/
+TEST_F(FieldNewDecimalTest, storeInternalWithErrorCheckRestOfParams)
+{
+  // Alows storing this range [-99.9999, 99.9999]
+  Mock_field_new_decimal field_dec(4);
+  Fake_TABLE table(&field_dec);
+  table.in_use= thd();
+  field_dec.make_writable();
+  thd()->count_cuted_fields= CHECK_FIELD_WARN;
+
+  my_decimal d10_01;
+  EXPECT_EQ(0, chars_2_decimal("10.01", &d10_01));
+
+  test_store_internal(&field_dec, &d10_01, "10.0100", 10, 10.01,
+                      E_DEC_DIV_ZERO, 0, TYPE_OK);
+
+  test_store_internal(&field_dec, &d10_01, "10.0100", 10, 10.01,
+                      E_DEC_BAD_NUM, 0, TYPE_OK);
+
+  test_store_internal(&field_dec, &d10_01, "10.0100", 10, 10.01,
+                      E_DEC_OOM, 0, TYPE_OK);
+}
+
+}

=== added file 'unittest/gunit/field_temporal_utils.h'
--- a/unittest/gunit/field_temporal_utils.h	1970-01-01 00:00:00 +0000
+++ b/unittest/gunit/field_temporal_utils.h	2012-05-07 12:05:48 +0000
@@ -0,0 +1,79 @@
+/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef FIELD_TEMPORAL_UTILS_INCLUDED
+#define FIELD_TEMPORAL_UTILS_INCLUDED
+
+#include "field.h"
+#include <gtest/gtest.h>
+#include "test_utils.h"
+
+namespace {
+
+using my_testing::Mock_error_handler;
+
+void store_zero_in_sql_mode(Field_temporal *field,
+                            const char *store_value, const int length,
+                            const char *expected_result,
+                            const type_conversion_status expect_status,
+                            const sql_mode_t test_mode,
+                            const uint expected_error_code)
+{
+  THD *thd= field->table->in_use;
+  sql_mode_t save_mode= thd->variables.sql_mode;
+  thd->variables.sql_mode= test_mode;
+
+  Mock_error_handler error_handler(thd, expected_error_code);
+  type_conversion_status err=
+    field->store(store_value, length, &my_charset_latin1);
+
+  String unused;
+  String str;
+  field->val_str(&str, &unused);
+
+  EXPECT_EQ(expect_status, err);
+  EXPECT_STREQ(expected_result, str.ptr());
+  EXPECT_EQ((expected_error_code == 0 ? 0 : 1),
+            error_handler.handle_called());
+
+  thd->variables.sql_mode= save_mode;
+}
+
+void test_store_string(Field_temporal *field,
+                       const char *store_value, const int length,
+                       const char *expected_result,
+                       const int expected_error_no,
+                       const type_conversion_status expected_status)
+{
+  char buff[MAX_FIELD_WIDTH];
+  String str(buff, sizeof(buff), &my_charset_bin);
+  String unused;
+  
+  Mock_error_handler error_handler(field->table->in_use, expected_error_no);
+  type_conversion_status err= field->store(store_value, length,
+                                           &my_charset_latin1);
+  field->val_str(&str, &unused);
+  EXPECT_STREQ(expected_result, str.ptr());
+
+  EXPECT_FALSE(field->is_null());
+  EXPECT_EQ(expected_status, err);
+  EXPECT_EQ((expected_error_no == 0 ? 0 : 1), error_handler.handle_called());
+}
+
+
+};
+
+
+#endif  // FIELD_TEMPORAL_UTILS_INCLUDED

=== modified file 'unittest/gunit/field_timestamp-t.cc'
--- a/unittest/gunit/field_timestamp-t.cc	2012-04-12 14:29:14 +0000
+++ b/unittest/gunit/field_timestamp-t.cc	2012-05-07 12:05:48 +0000
@@ -34,12 +34,7 @@ using my_testing::Mock_error_handler;
 class FieldTimestampTest : public ::testing::Test
 {
 protected:
-  static void SetUpTestCase() { Server_initializer::SetUpTestCase(); }
-
-  static void TearDownTestCase() { Server_initializer::TearDownTestCase(); }
-
   virtual void SetUp() { initializer.SetUp(); }
-
   virtual void TearDown() { initializer.TearDown(); }
 
   THD *get_thd() { return initializer.thd(); }

=== modified file 'unittest/gunit/get_diagnostics-t.cc'
--- a/unittest/gunit/get_diagnostics-t.cc	2011-12-20 09:51:05 +0000
+++ b/unittest/gunit/get_diagnostics-t.cc	2012-05-07 12:05:48 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -30,25 +30,8 @@ using my_testing::Mock_error_handler;
 class GetDiagnosticsTest : public ::testing::Test
 {
 protected:
-  static void SetUpTestCase()
-  {
-    Server_initializer::SetUpTestCase();
-  }
-
-  static void TearDownTestCase()
-  {
-    Server_initializer::TearDownTestCase();
-  }
-
-  virtual void SetUp()
-  {
-    initializer.SetUp();
-  }
-
-  virtual void TearDown()
-  {
-    initializer.TearDown();
-  }
+  virtual void SetUp() { initializer.SetUp(); }
+  virtual void TearDown() { initializer.TearDown(); }
 
   THD *thd() { return initializer.thd(); }
 

=== added file 'unittest/gunit/gunit_test_main_server.cc'
--- a/unittest/gunit/gunit_test_main_server.cc	1970-01-01 00:00:00 +0000
+++ b/unittest/gunit/gunit_test_main_server.cc	2012-05-07 12:05:48 +0000
@@ -0,0 +1,73 @@
+/* Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
+
+// First include (the generated) my_config.h, to get correct platform defines.
+#include "my_config.h"
+#include <gtest/gtest.h>
+
+#include "my_getopt.h"
+#include "test_utils.h"
+#include <stdlib.h>
+
+namespace {
+
+my_bool opt_use_tap= true;
+my_bool opt_help= false;
+
+struct my_option unittest_options[] =
+{
+  { "tap-output", 1, "TAP (default) or gunit output.",
+    &opt_use_tap, &opt_use_tap, NULL,
+    GET_BOOL, OPT_ARG,
+    opt_use_tap, 0, 1, 0,
+    0, NULL
+  },
+  { "help", 2, "Help.",
+    &opt_help, &opt_help, NULL,
+    GET_BOOL, NO_ARG,
+    opt_help, 0, 1, 0,
+    0, NULL
+  },
+  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+
+
+extern "C" my_bool get_one_option(int, const struct my_option *, char *)
+{
+  return FALSE;
+}
+
+}  // namespace
+
+
+extern void install_tap_listener();
+
+int main(int argc, char **argv)
+{
+  ::testing::InitGoogleTest(&argc, argv);
+  MY_INIT(argv[0]);
+
+  if (handle_options(&argc, &argv, unittest_options, get_one_option))
+    return EXIT_FAILURE;
+  if (opt_use_tap)
+    install_tap_listener();
+  if (opt_help)
+    printf("\n\nTest options: [--[disable-]tap-output]\n");
+
+  my_testing::setup_server_for_unit_tests();
+  int ret= RUN_ALL_TESTS();
+  my_testing::teardown_server_for_unit_tests();
+  return ret;
+}

=== modified file 'unittest/gunit/item-t.cc'
--- a/unittest/gunit/item-t.cc	2012-02-27 09:09:31 +0000
+++ b/unittest/gunit/item-t.cc	2012-05-07 12:05:48 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 
+/* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. 
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -33,25 +33,8 @@ using my_testing::Mock_error_handler;
 class ItemTest : public ::testing::Test
 {
 protected:
-  static void SetUpTestCase()
-  {
-    Server_initializer::SetUpTestCase();
-  }
-
-  static void TearDownTestCase()
-  {
-    Server_initializer::TearDownTestCase();
-  }
-
-  virtual void SetUp()
-  {
-    initializer.SetUp();
-  }
-
-  virtual void TearDown()
-  {
-    initializer.TearDown();
-  }
+  virtual void SetUp() { initializer.SetUp(); }
+  virtual void TearDown() { initializer.TearDown(); }
 
   THD *thd() { return initializer.thd(); }
 
@@ -92,12 +75,12 @@ public:
     This is the only member function we need to override.
     We expect it to be called with specific arguments.
    */
-  virtual int store(longlong nr, bool unsigned_val)
+  virtual type_conversion_status store(longlong nr, bool unsigned_val)
   {
     EXPECT_EQ(m_expected_value, nr);
     EXPECT_FALSE(unsigned_val);
     ++m_store_called;
-    return 0;
+    return TYPE_OK;
   }
 
 private:

=== modified file 'unittest/gunit/item_func_now_local-t.cc'
--- a/unittest/gunit/item_func_now_local-t.cc	2012-01-31 15:16:16 +0000
+++ b/unittest/gunit/item_func_now_local-t.cc	2012-05-07 12:05:48 +0000
@@ -1,10 +1,4 @@
-// I suggest putting these tests in item-t.cc
-// why? simply to save 50M of disk space.
-
-// TODO(didrik) create a dynamic version of libsql,
-// and link that into all SERVER_TESTS
-
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -19,8 +13,7 @@
    along with this program; if not, write to the Free Software Foundation,
    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
 
-// First include (the generated) my_config.h, to get correct platform defines,
-// then gtest.h (before any other MySQL headers), to avoid min() macros etc ...
+// First include (the generated) my_config.h, to get correct platform defines.
 #include "my_config.h"
 #include <gtest/gtest.h>
 
@@ -47,11 +40,8 @@ const int CURRENT_TIMESTAMP_FRACTIONAL_S
 class ItemFuncNowLocalTest : public ::testing::Test
 {
 protected:
-  static void SetUpTestCase() { Server_initializer::SetUpTestCase(); }
-
-  static void TearDownTestCase() { Server_initializer::TearDownTestCase(); }
-
-  virtual void SetUp() {
+  virtual void SetUp()
+  {
     initializer.SetUp();
     timeval now=
     {

=== modified file 'unittest/gunit/join_tab_sort-t.cc'
--- a/unittest/gunit/join_tab_sort-t.cc	2012-02-23 13:54:03 +0000
+++ b/unittest/gunit/join_tab_sort-t.cc	2012-05-07 12:05:48 +0000
@@ -32,25 +32,8 @@ using my_testing::Mock_error_handler;
 class JTSortTest : public ::testing::Test
 {
 protected:
-  static void SetUpTestCase()
-  {
-    Server_initializer::SetUpTestCase();
-  }
-
-  static void TearDownTestCase()
-  {
-    Server_initializer::TearDownTestCase();
-  }
-
-  virtual void SetUp()
-  {
-    initializer.SetUp();
-  }
-
-  virtual void TearDown()
-  {
-    initializer.TearDown();
-  }
+  virtual void SetUp() { initializer.SetUp(); }
+  virtual void TearDown() { initializer.TearDown(); }
 
   Server_initializer initializer;
 };

=== modified file 'unittest/gunit/my_decimal-t.cc'
--- a/unittest/gunit/my_decimal-t.cc	2011-10-14 09:40:10 +0000
+++ b/unittest/gunit/my_decimal-t.cc	2012-05-07 12:05:48 +0000
@@ -28,25 +28,8 @@ using my_testing::Mock_error_handler;
 class DecimalTest : public ::testing::Test
 {
 protected:
-  static void SetUpTestCase()
-  {
-    Server_initializer::SetUpTestCase();
-  }
-
-  static void TearDownTestCase()
-  {
-    Server_initializer::TearDownTestCase();
-  }
-
-  virtual void SetUp()
-  {
-    initializer.SetUp();
-  }
-
-  virtual void TearDown()
-  {
-    initializer.TearDown();
-  }
+  virtual void SetUp() { initializer.SetUp(); }
+  virtual void TearDown() { initializer.TearDown(); }
 
   THD *thd() { return initializer.thd(); }
 

=== modified file 'unittest/gunit/opt_range-t.cc'
--- a/unittest/gunit/opt_range-t.cc	2012-03-19 14:40:35 +0000
+++ b/unittest/gunit/opt_range-t.cc	2012-05-09 07:31:29 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -28,16 +28,6 @@ using my_testing::Server_initializer;
 class SelArgTest : public ::testing::Test
 {
 protected:
-  static void SetUpTestCase()
-  {
-    Server_initializer::SetUpTestCase();
-  }
-
-  static void TearDownTestCase()
-  {
-    Server_initializer::TearDownTestCase();
-  }
-
   SelArgTest()
   {
     memset(&m_opt_param, 0, sizeof(m_opt_param));

=== modified file 'unittest/gunit/segfault-t.cc'
--- a/unittest/gunit/segfault-t.cc	2011-12-05 12:37:08 +0000
+++ b/unittest/gunit/segfault-t.cc	2012-05-07 12:05:48 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -29,20 +29,12 @@ using my_testing::Mock_error_handler;
 class FatalSignalDeathTest : public ::testing::Test
 {
 protected:
-  static void SetUpTestCase()
-  { Server_initializer::SetUpTestCase(); }
-
-  static void TearDownTestCase()
-  { Server_initializer::TearDownTestCase(); }
-
   virtual void SetUp()
   {
     ::testing::FLAGS_gtest_death_test_style = "threadsafe";
     initializer.SetUp();
   }
-
-  virtual void TearDown()
-  { initializer.TearDown(); }
+  virtual void TearDown() { initializer.TearDown(); }
 
   Server_initializer initializer;
 };

=== modified file 'unittest/gunit/sql_table-t.cc'
--- a/unittest/gunit/sql_table-t.cc	2012-01-31 15:16:16 +0000
+++ b/unittest/gunit/sql_table-t.cc	2012-05-07 12:05:48 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -37,12 +37,7 @@ using my_testing::Mock_error_handler;
 class SqlTableTest : public ::testing::Test
 {
 protected:
-  static void SetUpTestCase() { Server_initializer::SetUpTestCase(); }
-
-  static void TearDownTestCase() { Server_initializer::TearDownTestCase(); }
-
   virtual void SetUp() { initializer.SetUp(); }
-
   virtual void TearDown() { initializer.TearDown(); }
 
   THD *get_thd() { return initializer.thd(); }

=== modified file 'unittest/gunit/test_utils.cc'
--- a/unittest/gunit/test_utils.cc	2011-12-20 09:51:05 +0000
+++ b/unittest/gunit/test_utils.cc	2012-05-07 12:05:48 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -31,12 +31,7 @@ extern "C" void test_error_handler_hook(
   EXPECT_EQ(expected_error, err) << str;
 }
 
-void Server_initializer::set_expected_error(uint val)
-{
-  expected_error= val;
-}
-
-void Server_initializer::SetUpTestCase()
+void setup_server_for_unit_tests()
 {
   static char *my_name= strdup(my_progname);
   char *argv[] = { my_name, 0 };
@@ -49,12 +44,17 @@ void Server_initializer::SetUpTestCase()
   error_handler_hook= test_error_handler_hook;
 }
 
-void Server_initializer::TearDownTestCase()
+void teardown_server_for_unit_tests()
 {
   delegates_destroy();
   xid_cache_free();
 }
 
+void Server_initializer::set_expected_error(uint val)
+{
+  expected_error= val;
+}
+
 void Server_initializer::SetUp()
 {
   expected_error= 0;

=== modified file 'unittest/gunit/test_utils.h'
--- a/unittest/gunit/test_utils.h	2011-07-28 10:54:44 +0000
+++ b/unittest/gunit/test_utils.h	2012-05-07 12:05:48 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -22,6 +22,9 @@
 
 namespace my_testing {
 
+void setup_server_for_unit_tests();
+void teardown_server_for_unit_tests();
+
 /*
   A class which wraps the necessary setup/teardown logic for
   unit tests which depend on a working THD environment.
@@ -32,8 +35,6 @@ public:
   Server_initializer() : m_thd(NULL) {}
 
   // Invoke these from corresponding functions in test fixture classes.
-  static void SetUpTestCase();
-  static void TearDownTestCase();
   void SetUp();
   void TearDown();
 

=== modified file 'unittest/unit.pl'
--- a/unittest/unit.pl	2011-09-07 10:08:09 +0000
+++ b/unittest/unit.pl	2012-05-07 21:01:12 +0000
@@ -121,7 +121,9 @@ sub run_cmd (@) {
         {
           my %args = ( exec => [ ], verbosity => $opt_verbose );
           my $harness = TAP::Harness->new( \%args );
-          $harness->runtests(@files);
+	  my $aggreg= $harness->runtests(@files);
+	  # Signal failure to calling scripts
+	  exit(1) if $aggreg->get_status() ne 'PASS';
         }
         else
         {

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk-pfs-tuning branch (marc.alff:3505 to 3506) Marc Alff9 May