From: Dmitry Shulga Date: September 25 2012 1:01pm Subject: bzr push into mysql-trunk branch (Dmitry.Shulga:4215 to 4216) List-Archive: http://lists.mysql.com/commits/144879 Message-Id: <201209251300.q8PD02i1001013@acsmt358.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 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 &fields, bool ignore_errors) +static bool check_record(THD *thd, List &fields, bool ignore_errors, + Not_Null_Warning_Handler *not_null_warning_handler) { List_iterator_fast 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 &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 &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 &fields, List &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 &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 *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 // 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(Listelements) 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(Listtriggers, 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 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 *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).