4216 Dmitry Shulga 2012-09-25
Fixed bug related to duplicate warnings about NOT_NULL column value.
modified:
mysql-test/r/wl6030.result
sql/field.cc
sql/field.h
sql/sql_base.cc
sql/sql_base.h
sql/sql_insert.cc
sql/sql_insert.h
sql/sql_load.cc
sql/sql_update.cc
4215 Alexander Nozdrin 2012-09-25
Fix various failures.
modified:
mysql-test/r/wl6030.result
sql/field.cc
sql/field.h
sql/sql_base.cc
sql/sql_trigger.cc
=== modified file 'mysql-test/r/wl6030.result'
--- a/mysql-test/r/wl6030.result 2012-09-25 12:34:49 +0000
+++ b/mysql-test/r/wl6030.result 2012-09-25 13:00:18 +0000
@@ -556,6 +556,7 @@ END IF;
END|
INSERT INTO t1(a) VALUES (1), (2), (3), (4), (5), (6);
Warnings:
+Warning 1048 Column 'b' cannot be null
Warning 1364 Field 'b' doesn't have a default value
SELECT * FROM t1;
a b
=== modified file 'sql/field.cc'
--- a/sql/field.cc 2012-09-25 12:34:49 +0000
+++ b/sql/field.cc 2012-09-25 13:00:18 +0000
@@ -1377,7 +1377,7 @@ Field::Field(uchar *ptr_arg,uint32 lengt
@return TYPE_OK if the value is Ok, or corresponding error code from
the type_conversion_status enum.
*/
-type_conversion_status Field::check_constraints(int warning_no) const
+type_conversion_status Field::check_constraints(bool *got_warning) const
{
/*
Ensure that Field::check_constraints() is called only when temporary
@@ -1386,6 +1386,7 @@ type_conversion_status Field::check_cons
DBUG_ASSERT(!is_tmp_nullable());
+ *got_warning= false;
if (real_maybe_null())
return TYPE_OK; // If the field is nullable, we're Ok.
@@ -1412,7 +1413,7 @@ type_conversion_status Field::check_cons
switch (m_count_cuted_fields_saved) {
case CHECK_FIELD_WARN:
- set_warning(Sql_condition::WARN_LEVEL_WARN, warning_no, 1);
+ *got_warning= true;
/* fall through */
case CHECK_FIELD_IGNORE:
return TYPE_OK;
=== modified file 'sql/field.h'
--- a/sql/field.h 2012-09-25 12:34:49 +0000
+++ b/sql/field.h 2012-09-25 13:00:18 +0000
@@ -985,7 +985,7 @@ public:
void set_notnull(my_ptrdiff_t row_offset= 0);
- type_conversion_status check_constraints(int warning_no) const;
+ type_conversion_status check_constraints(bool *got_warning) const;
/**
Remember the value of THD::count_cuted_fields to handle possible
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2012-09-25 12:34:49 +0000
+++ b/sql/sql_base.cc 2012-09-25 13:00:18 +0000
@@ -8894,6 +8894,18 @@ err:
}
+void Not_Null_Warning_Handler::report_field_warning(const Field *field,
+ int warning_no)
+{
+ if (!bitmap_is_set(&fields_keeper, field->field_index))
+ {
+ bitmap_set_bit(&fields_keeper, field->field_index);
+ field->set_warning(Sql_condition::WARN_LEVEL_WARN,
+ warning_no, 1);
+ }
+}
+
+
/**
Check the NOT NULL constraint on all the fields of the current record.
@@ -8903,7 +8915,8 @@ err:
@return Error status.
*/
-static bool check_record(THD *thd, List<Item> &fields, bool ignore_errors)
+static bool check_record(THD *thd, List<Item> &fields, bool ignore_errors,
+ Not_Null_Warning_Handler *not_null_warning_handler)
{
List_iterator_fast<Item> f(fields);
Item *fld;
@@ -8912,12 +8925,28 @@ static bool check_record(THD *thd, List<
while ((fld= f++))
{
field= fld->field_for_view_update();
- if (field &&
- field->field->check_constraints(ER_BAD_NULL_ERROR) != TYPE_OK &&
- !ignore_errors)
+ if (field)
{
- my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
- return true;
+ if (not_null_warning_handler &&
+ not_null_warning_handler->have_been_reported_field_warning(field->field))
+ continue;
+
+ bool got_warning;
+ if (field->field->check_constraints(&got_warning) != TYPE_OK &&
+ !ignore_errors)
+ {
+ my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
+ return true;
+ }
+ if (got_warning)
+ {
+ if (not_null_warning_handler)
+ not_null_warning_handler->report_field_warning(field->field,
+ ER_BAD_NULL_ERROR);
+ else
+ field->field->set_warning(Sql_condition::WARN_LEVEL_WARN,
+ ER_BAD_NULL_ERROR, 1);
+ }
}
}
return thd->is_error();
@@ -8932,13 +8961,25 @@ static bool check_record(THD *thd, List<
@return Error status.
*/
-static bool check_record(THD *thd, Field **ptr)
+static bool check_record(THD *thd, Field **ptr,
+ Not_Null_Warning_Handler *not_null_warning_handler)
{
Field *field;
while ((field = *ptr++) && !thd->is_error())
{
- if (field->check_constraints(ER_BAD_NULL_ERROR) != TYPE_OK)
+ if (not_null_warning_handler &&
+ not_null_warning_handler->have_been_reported_field_warning(field))
+ continue;
+ bool got_warning;
+ if (field->check_constraints(&got_warning) != TYPE_OK)
return true;
+ if (got_warning)
+ {
+ if (not_null_warning_handler)
+ not_null_warning_handler->report_field_warning(field, ER_BAD_NULL_ERROR);
+ else
+ field->set_warning(Sql_condition::WARN_LEVEL_WARN, ER_BAD_NULL_ERROR, 1);
+ }
}
return thd->is_error();
}
@@ -8970,7 +9011,8 @@ fill_record_n_invoke_before_triggers(THD
List<Item> &values, bool ignore_errors,
Table_triggers_list *triggers,
enum trg_event_type event,
- uint bitmap_size)
+ uint bitmap_size,
+ Not_Null_Warning_Handler *null_warn_hndl)
{
if (triggers)
triggers->enable_fields_temporary_nullability(thd);
@@ -9033,8 +9075,8 @@ fill_record_n_invoke_before_triggers(THD
return true;
return triggers ?
- check_record(thd, triggers->trigger_table->field) :
- check_record(thd, fields, ignore_errors);
+ check_record(thd, triggers->trigger_table->field, null_warn_hndl) :
+ check_record(thd, fields, ignore_errors, null_warn_hndl);
}
@@ -9137,7 +9179,8 @@ fill_record_n_invoke_before_triggers(THD
List<Item> &values, bool ignore_errors,
Table_triggers_list *triggers,
enum trg_event_type event,
- uint bitmap_size)
+ uint bitmap_size,
+ Not_Null_Warning_Handler *null_warn_hndl)
{
if (triggers)
triggers->enable_fields_temporary_nullability(thd);
@@ -9201,7 +9244,7 @@ fill_record_n_invoke_before_triggers(THD
if (rc)
return true;
- return check_record(thd, ptr);
+ return check_record(thd, ptr, null_warn_hndl);
}
=== modified file 'sql/sql_base.h'
--- a/sql/sql_base.h 2012-09-24 14:54:55 +0000
+++ b/sql/sql_base.h 2012-09-25 13:00:18 +0000
@@ -165,18 +165,45 @@ TABLE *find_temporary_table(THD *thd, co
TABLE *find_temporary_table(THD *thd, const char *table_key,
uint table_key_length);
void close_thread_tables(THD *thd);
+
+class Not_Null_Warning_Handler
+{
+public:
+ explicit Not_Null_Warning_Handler(uint number_of_fields)
+ {
+ // number_of_fields is equal to 0 when select_create class is executed
+ if (number_of_fields)
+ bitmap_init(&fields_keeper,
+ NULL,
+ number_of_fields,
+ false);
+ }
+
+ bool have_been_reported_field_warning(const Field *field)
+ {
+ return bitmap_is_set(&fields_keeper, field->field_index);
+ }
+
+ void report_field_warning(const Field *field, int warning_no);
+
+private:
+ MY_BITMAP fields_keeper;
+};
+
bool fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
List<Item> &values,
bool ignore_errors,
Table_triggers_list *triggers,
enum trg_event_type event,
- uint bitmap_size);
+ uint bitmap_size,
+ Not_Null_Warning_Handler *handler);
bool fill_record_n_invoke_before_triggers(THD *thd, Field **field,
List<Item> &values,
bool ignore_errors,
Table_triggers_list *triggers,
enum trg_event_type event,
- uint bitmap_size);
+ uint bitmap_size,
+ Not_Null_Warning_Handler *handler);
bool insert_fields(THD *thd, Name_resolution_context *context,
const char *db_name, const char *table_name,
List_iterator<Item> *it, bool any_privileges);
=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc 2012-09-24 14:54:55 +0000
+++ b/sql/sql_insert.cc 2012-09-25 13:00:18 +0000
@@ -1092,6 +1092,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
table_list->prepare_check_option(thd))
error= 1;
+ Not_Null_Warning_Handler not_null_warn_handler(table->s->fields);
while ((values= its++))
{
if (fields.elements || !value_count)
@@ -1100,7 +1101,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
if (fill_record_n_invoke_before_triggers(thd, fields, *values, 0,
table->triggers,
TRG_EVENT_INSERT,
- table->s->fields))
+ table->s->fields,
+ ¬_null_warn_handler))
{
if (values_list.elements != 1 && ! thd->is_error())
{
@@ -1163,7 +1165,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
if (fill_record_n_invoke_before_triggers(thd, table->field, *values, 0,
table->triggers,
TRG_EVENT_INSERT,
- table->s->fields))
+ table->s->fields,
+ ¬_null_warn_handler))
{
if (values_list.elements != 1 && ! thd->is_error())
{
@@ -1197,7 +1200,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
}
else
#endif
- error= write_record(thd, table, &info, &update);
+ error= write_record(thd, table, &info, &update, ¬_null_warn_handler);
if (error)
break;
thd->get_stmt_da()->inc_current_row_for_warning();
@@ -1754,7 +1757,8 @@ static int last_uniq_key(TABLE *table,ui
non-0 - error
*/
-int write_record(THD *thd, TABLE *table, COPY_INFO *info, COPY_INFO *update)
+int write_record(THD *thd, TABLE *table, COPY_INFO *info, COPY_INFO *update,
+ Not_Null_Warning_Handler *not_null_warn_handler)
{
int error, trg_error= 0;
char *key=0;
@@ -1869,7 +1873,8 @@ int write_record(THD *thd, TABLE *table,
*update->update_values,
ignore_errors,
table->triggers,
- TRG_EVENT_UPDATE, 0))
+ TRG_EVENT_UPDATE, 0,
+ not_null_warn_handler))
goto before_trg_err;
/* CHECK OPTION for VIEW ... ON DUPLICATE KEY UPDATE ... */
@@ -3329,7 +3334,7 @@ bool Delayed_insert::handle_inserts(void
if (duplicate_handling == DUP_UPDATE)
table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE);
thd.clear_error(); // reset error for binlog
- if (write_record(&thd, table, &d_info, NULL))
+ if (write_record(&thd, table, &d_info, NULL, NULL))
{
d_info.stats.error_count++; // Ignore errors
thread_safe_increment(delayed_insert_errors,&LOCK_delayed_status);
@@ -3754,7 +3759,7 @@ bool select_insert::send_data(List<Item>
// Release latches in case bulk insert takes a long time
ha_release_temporary_latches(thd);
- error= write_record(thd, table, &info, &update);
+ error= write_record(thd, table, &info, &update, ¬_null_warn_handler);
table->auto_increment_field_not_null= FALSE;
if (!error)
@@ -3796,11 +3801,13 @@ void select_insert::store_values(List<It
if (fields->elements)
fill_record_n_invoke_before_triggers(thd, *fields, values, ignore_err,
table->triggers, TRG_EVENT_INSERT,
- table->s->fields);
+ table->s->fields,
+ ¬_null_warn_handler);
else
fill_record_n_invoke_before_triggers(thd, table->field, values, ignore_err,
table->triggers, TRG_EVENT_INSERT,
- table->s->fields);
+ table->s->fields,
+ ¬_null_warn_handler);
check_that_all_fields_are_given_values(thd, table_list->table, table_list,
&missed_fields_handler);
@@ -4405,7 +4412,8 @@ void select_create::store_values(List<It
const bool ignore_err= true;
fill_record_n_invoke_before_triggers(thd, field, values, ignore_err,
table->triggers, TRG_EVENT_INSERT,
- table->s->fields);
+ table->s->fields,
+ NULL);
}
=== modified file 'sql/sql_insert.h'
--- a/sql/sql_insert.h 2012-09-17 15:26:51 +0000
+++ b/sql/sql_insert.h 2012-09-25 13:00:18 +0000
@@ -18,6 +18,7 @@
#include "sql_class.h" /* enum_duplicates */
#include "sql_list.h"
+#include "sql_base.h"
/* Instead of including sql_lex.h we add this typedef here */
typedef List<Item> List_item;
@@ -120,6 +121,9 @@ private:
Missed_fields_handler_impl missed_fields_handler;
+protected:
+ Not_Null_Warning_Handler not_null_warn_handler;
+
public:
ulonglong autoinc_value_of_last_inserted_row; // autogenerated or not
COPY_INFO info;
@@ -190,6 +194,7 @@ public:
missed_fields_handler(thd, ignore,
(table ? table->s->column_bitmap_size : 0),
(table ? table->s->fields : 0)),
+ not_null_warn_handler(table ? table->s->fields : 0), // TODO: fix possible bug for select_create
autoinc_value_of_last_inserted_row(0),
info(COPY_INFO::INSERT_OPERATION,
target_columns,
@@ -301,7 +306,8 @@ int check_that_all_fields_are_given_valu
Missed_fields_handler *handler);
void prepare_triggers_for_insert_stmt(TABLE *table);
int write_record(THD *thd, TABLE *table,
- COPY_INFO *info, COPY_INFO *update);
+ COPY_INFO *info, COPY_INFO *update,
+ Not_Null_Warning_Handler *not_null_warn_handler);
void kill_delayed_threads(void);
#ifdef EMBEDDED_LIBRARY
=== modified file 'sql/sql_load.cc'
--- a/sql/sql_load.cc 2012-09-24 14:54:55 +0000
+++ b/sql/sql_load.cc 2012-09-25 13:00:18 +0000
@@ -887,7 +887,8 @@ read_fixed_length(THD *thd, COPY_INFO &i
ignore_check_option_errors,
table->triggers,
TRG_EVENT_INSERT,
- table->s->fields))
+ table->s->fields,
+ NULL))
DBUG_RETURN(1);
switch (table_list->view_check_option(thd,
@@ -899,7 +900,7 @@ read_fixed_length(THD *thd, COPY_INFO &i
DBUG_RETURN(-1);
}
- err= write_record(thd, table, &info, NULL);
+ err= write_record(thd, table, &info, NULL, NULL);
table->auto_increment_field_not_null= FALSE;
if (err)
DBUG_RETURN(1);
@@ -1119,7 +1120,8 @@ read_sep_field(THD *thd, COPY_INFO &info
ignore_check_option_errors,
table->triggers,
TRG_EVENT_INSERT,
- table->s->fields))
+ table->s->fields,
+ NULL))
DBUG_RETURN(1);
if (!table->triggers)
@@ -1133,8 +1135,12 @@ read_sep_field(THD *thd, COPY_INFO &info
while ((item= it++))
{
real_item= item->real_item();
+ bool got_warning;
if (real_item->type() == Item::FIELD_ITEM)
- ((Item_field *) real_item)->field->check_constraints(ER_WARN_NULL_TO_NOTNULL);
+ ((Item_field *) real_item)->field->check_constraints(&got_warning);
+ if (got_warning)
+ ((Item_field *) real_item)->field->set_warning(Sql_condition::WARN_LEVEL_WARN,
+ ER_WARN_NULL_TO_NOTNULL, 1);
}
}
@@ -1147,7 +1153,7 @@ read_sep_field(THD *thd, COPY_INFO &info
DBUG_RETURN(-1);
}
- err= write_record(thd, table, &info, NULL);
+ err= write_record(thd, table, &info, NULL, NULL);
table->auto_increment_field_not_null= FALSE;
if (err)
DBUG_RETURN(1);
@@ -1310,7 +1316,8 @@ read_xml_field(THD *thd, COPY_INFO &info
ignore_check_option_errors,
table->triggers,
TRG_EVENT_INSERT,
- table->s->fields))
+ table->s->fields,
+ NULL))
DBUG_RETURN(1);
switch (table_list->view_check_option(thd,
@@ -1322,7 +1329,7 @@ read_xml_field(THD *thd, COPY_INFO &info
DBUG_RETURN(-1);
}
- if (write_record(thd, table, &info, NULL))
+ if (write_record(thd, table, &info, NULL, NULL))
DBUG_RETURN(1);
/*
=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc 2012-09-24 14:54:55 +0000
+++ b/sql/sql_update.cc 2012-09-25 13:00:18 +0000
@@ -809,7 +809,8 @@ int mysql_update(THD *thd,
store_record(table,record[1]);
if (fill_record_n_invoke_before_triggers(thd, fields, values, 0,
table->triggers,
- TRG_EVENT_UPDATE, 0))
+ TRG_EVENT_UPDATE, 0,
+ NULL))
break; /* purecov: inspected */
found++;
@@ -2086,7 +2087,7 @@ bool multi_update::send_data(List<Item>
*values_for_table[offset],
false, // ignore_errors
table->triggers,
- TRG_EVENT_UPDATE, 0))
+ TRG_EVENT_UPDATE, 0, NULL))
DBUG_RETURN(1);
/*
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-trunk branch (Dmitry.Shulga:4215 to 4216) | Dmitry Shulga | 26 Sep |