From: Dmitry Shulga Date: October 2 2012 9:33am Subject: bzr push into mysql-trunk branch (Dmitry.Shulga:4219 to 4222) WL#6030 List-Archive: http://lists.mysql.com/commits/144925 Message-Id: <201210020932.q929W1W3019936@acsmt358.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 4222 Dmitry Shulga 2012-10-02 Follow-up patch for WL#6030. The test related to warnings count was changed in mysql_client_test.c Field::set_waring takes into account commands v and REPLACE_SELECT. During execution INSERT SELECT set thd->count_cuted_fields temporary to value CHECK_FIELD_WARN in order to outpyt warnings related to missed values for fields that doesn't have defautl values. modified: sql/field.cc sql/sql_insert.cc tests/mysql_client_test.c 4221 Dmitry Shulga 2012-10-02 Fixed failures in the tests INSERT SELECT and LOAD DATA INFILE related with NOT NULL columns. modified: mysql-test/r/wl6030.result sql/sql_insert.cc sql/sql_load.cc 4220 Dmitry Shulga 2012-10-01 Missed_fields_handler was removed. modified: sql/field.cc sql/field.h sql/sql_insert.cc sql/sql_insert.h sql/sql_load.cc sql/sql_trigger.cc 4219 Alexander Nozdrin 2012-09-28 Fixing wl6030.test/wl6030.result (the test does not pass now). modified: mysql-test/r/wl6030.result mysql-test/t/wl6030.test === modified file 'mysql-test/r/wl6030.result' --- a/mysql-test/r/wl6030.result 2012-09-28 07:55:02 +0000 +++ b/mysql-test/r/wl6030.result 2012-10-02 05:35:46 +0000 @@ -1116,9 +1116,9 @@ DELETE FROM t2; # - No column list (all columns) + NULL-value for NOT NULL column. INSERT INTO t2 SELECT * FROM t2_data; -ERROR 23000: Column 'd' cannot be null +ERROR 23000: Column 'b' cannot be null INSERT INTO v2 SELECT a * 10, b * 10, c * 10, d * 10 FROM t2_data; -ERROR 23000: Column 'd' cannot be null +ERROR 23000: Column 'b' cannot be null # The following SELECT output should have 4 rows. # t2's engine is MyISAM, so the transaction can not be fully rolled back. @@ -1152,9 +1152,9 @@ DELETE FROM t1; DELETE FROM t2; INSERT INTO t2(a, b, c, d) SELECT * FROM t2_data; -ERROR 23000: Column 'd' cannot be null +ERROR 23000: Column 'b' cannot be null INSERT INTO v2(a, b, c, d) SELECT a * 10, b * 10, c * 10, d * 10 FROM t2_data; -ERROR 23000: Column 'd' cannot be null +ERROR 23000: Column 'b' cannot be null # The following SELECT output should have 4 rows. # t2's engine is MyISAM, so the transaction can not be fully rolled back. === modified file 'sql/field.cc' --- a/sql/field.cc 2012-09-27 14:40:40 +0000 +++ b/sql/field.cc 2012-10-02 09:31:52 +0000 @@ -1360,7 +1360,7 @@ Field::Field(uchar *ptr_arg,uint32 lengt unireg_check(unireg_check_arg), field_length(length_arg), null_bit(null_bit_arg), is_created_from_null_item(FALSE), - field_warning_was_pushed(false) + field_warning_was_pushed(0) { flags=real_maybe_null() ? 0: NOT_NULL_FLAG; comment.str= (char*) ""; @@ -10578,6 +10578,15 @@ bool Field::set_warning(Sql_condition::enum_warning_level level, uint code, int cut_increment) { + return set_warning(level, code, cut_increment, NULL, NULL); +} + + +bool +Field::set_warning(Sql_condition::enum_warning_level level, uint code, + int cut_increment, const char *view_db, + const char *view_name) +{ /* If this field was created only for type conversion purposes it will have table == NULL. @@ -10587,16 +10596,39 @@ Field::set_warning(Sql_condition::enum_w { thd->cuted_fields+= cut_increment; if ((thd->lex->sql_command == SQLCOM_INSERT || - thd->lex->sql_command == SQLCOM_INSERT_SELECT) && - (code == ER_BAD_NULL_ERROR || - code == ER_WARN_NULL_TO_NOTNULL)) - { - if (!field_warning_was_pushed) + thd->lex->sql_command == SQLCOM_INSERT_SELECT || + thd->lex->sql_command == SQLCOM_REPLACE) || + thd->lex->sql_command == SQLCOM_REPLACE_SELECT) + { + unsigned bitmask; + if ((code == ER_BAD_NULL_ERROR && (bitmask= BAD_NULL_ERROR_PUSHED)) || + (code == ER_WARN_NULL_TO_NOTNULL && + (bitmask= WARN_NULL_TO_NOTNULL_PUSHED)) || + (code == ER_NO_DEFAULT_FOR_FIELD && + (bitmask= NO_DEFAULT_FOR_FIELD_PUSHED))) + { + if (!(field_warning_was_pushed & bitmask)) + { + push_warning_printf(thd, level, code, ER(code), field_name, + thd->get_stmt_da()->current_row_for_warning()); + field_warning_was_pushed|= bitmask; + } + } + else if (code == ER_NO_DEFAULT_FOR_VIEW_FIELD) { - field_warning_was_pushed= true; + if (!(field_warning_was_pushed & NO_DEFAULT_FOR_VIEW_FIELD_PUSHED)) + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_NO_DEFAULT_FOR_VIEW_FIELD, + ER(ER_NO_DEFAULT_FOR_VIEW_FIELD), + view_db, + view_name); + field_warning_was_pushed|= NO_DEFAULT_FOR_VIEW_FIELD_PUSHED; + } + } + else push_warning_printf(thd, level, code, ER(code), field_name, thd->get_stmt_da()->current_row_for_warning()); - } } else push_warning_printf(thd, level, code, ER(code), field_name, === modified file 'sql/field.h' --- a/sql/field.h 2012-09-27 14:40:40 +0000 +++ b/sql/field.h 2012-10-01 03:34:26 +0000 @@ -568,12 +568,16 @@ public: bool is_created_from_null_item; private: - bool field_warning_was_pushed; + unsigned field_warning_was_pushed; + enum pushed_warns_mask_e {BAD_NULL_ERROR_PUSHED= 1, + WARN_NULL_TO_NOTNULL_PUSHED= 2, + NO_DEFAULT_FOR_FIELD_PUSHED= 4, + NO_DEFAULT_FOR_VIEW_FIELD_PUSHED= 8}; public: void reset_warning_flag() { - field_warning_was_pushed= false; + field_warning_was_pushed= 0; } Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg, @@ -1250,6 +1254,10 @@ public: virtual void set_derivation(enum Derivation derivation_arg) { } bool set_warning(Sql_condition::enum_warning_level, unsigned int code, int cuted_increment); + bool set_warning(Sql_condition::enum_warning_level level, uint code, + int cut_increment, const char *view_db, + const char *view_name); + inline bool check_overflow(int op_result) { return (op_result == E_DEC_OVERFLOW); === modified file 'sql/sql_insert.cc' --- a/sql/sql_insert.cc 2012-09-27 14:40:40 +0000 +++ b/sql/sql_insert.cc 2012-10-02 09:31:52 +0000 @@ -609,79 +609,6 @@ create_insert_stmt_from_insert_delayed(T } -void Missed_fields_handler_impl::handle(bool is_view, Field* field, - TABLE_LIST* table_list) -{ - if (is_view) - add_field_idx_to_missed_set(field->field_index, - const_cast(field->field_name), - table_list->view_db.str, - table_list->view_name.str); - else - add_field_idx_to_missed_set(field->field_index, - const_cast(field->field_name)); -} - - -void Missed_fields_handler_impl::process_missed_fields() -{ - List_iterator_fast its(missed_fields_name_list); - const char *field_name= NULL; - - bool saved_abort_on_warning= thd->abort_on_warning; - thd->abort_on_warning= !ignore_errors && - thd->is_strict_mode(); - - for(unsigned i=0; iabort_on_warning= saved_abort_on_warning; -} - - -void Missed_fields_handler_impl::add_field_idx_to_missed_set(uint16 field_idx, - char* field_name) -{ - if (!bitmap_is_set(&fields_not_set_during_insert, field_idx)) - { - bitmap_set_bit(&fields_not_set_during_insert, field_idx); - ++number_of_missed_fields; - missed_fields_name_list.push_back(field_name); - } -} - - -void Missed_fields_handler_impl::add_field_idx_to_missed_set(uint16 field_idx, - char* field_name, - const char* v_db, - const char* v_nam) -{ - add_field_idx_to_missed_set(field_idx, field_name); - if (!is_view) - { - view_db= v_db; - view_name= v_nam; - is_view= true; - } -} - - /** Wrapper for invocation of function check_that_all_fields_are_given_value. @@ -698,14 +625,12 @@ void Missed_fields_handler_impl::add_fie static bool safely_check_that_all_fields_are_given_values(THD* thd, TABLE* table, TABLE_LIST* table_list, - bool abort_on_warning, - Missed_fields_handler *handler) + bool abort_on_warning) { bool saved_abort_on_warning= thd->abort_on_warning; thd->abort_on_warning= abort_on_warning; - bool res= check_that_all_fields_are_given_values(thd, table, table_list, - handler); + bool res= check_that_all_fields_are_given_values(thd, table, table_list); thd->abort_on_warning= saved_abort_on_warning; @@ -863,10 +788,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *t DBUG_RETURN(true); } - Missed_fields_handler_impl miss_flds_handler(thd, ignore, - table->s->column_bitmap_size, - table->s->fields); - context= &thd->lex->select_lex.context; /* These three asserts test the hypothesis that the resetting of the name @@ -1091,6 +1012,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *t table_list->prepare_check_option(thd)) error= 1; + for (Field** next_field= table->field; *next_field; ++next_field) + { + (*next_field)->reset_warning_flag(); + } + while ((values= its++)) { if (fields.elements || !value_count) @@ -1121,8 +1047,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t bool abort_on_warning= !ignore && thd->is_strict_mode(); res= safely_check_that_all_fields_are_given_values(thd, t, context->table_list, - abort_on_warning, - &miss_flds_handler); + abort_on_warning); if (res) { @@ -1202,9 +1127,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *t thd->get_stmt_da()->inc_current_row_for_warning(); } - if (miss_flds_handler.have_missed_fields()) - miss_flds_handler.process_missed_fields(); - error= thd->get_stmt_da()->is_error(); free_underlaid_joins(thd, &thd->lex->select_lex); joins_freed= TRUE; @@ -2049,8 +1971,7 @@ before_trg_err: ******************************************************************************/ int check_that_all_fields_are_given_values(THD *thd, TABLE *entry, - TABLE_LIST *table_list, - Missed_fields_handler *handler) + TABLE_LIST *table_list) { int err= 0; MY_BITMAP *write_set= entry->fields_set_during_insert; @@ -2067,7 +1988,14 @@ int check_that_all_fields_are_given_valu table_list= table_list->top_table(); view= test(table_list->view); } - handler->handle(view, *field, table_list); + if (view) + (*field)->set_warning(Sql_condition::WARN_LEVEL_WARN, + ER_NO_DEFAULT_FOR_VIEW_FIELD, 1, + table_list->view_db.str, + table_list->view_name.str); + else + (*field)->set_warning(Sql_condition::WARN_LEVEL_WARN, + ER_NO_DEFAULT_FOR_FIELD, 1); err= 1; } } @@ -3667,6 +3595,13 @@ select_insert::prepare(List &value { prepare_triggers_for_insert_stmt(table); } + + for (Field** next_field= table->field; *next_field; ++next_field) + { + (*next_field)->reset_warning_flag(); + (*next_field)->reset_tmp_null(); + } + DBUG_RETURN(res); } @@ -3801,14 +3736,7 @@ void select_insert::store_values(Listtriggers, TRG_EVENT_INSERT, table->s->fields); - check_that_all_fields_are_given_values(thd, table_list->table, table_list, - &missed_fields_handler); - - if (!info.get_ignore_errors() && thd->is_strict_mode() && - missed_fields_handler.have_missed_fields()) - { - missed_fields_handler.process_missed_fields(); - } + check_that_all_fields_are_given_values(thd, table_list->table, table_list); } void select_insert::send_error(uint errcode,const char *err) @@ -3883,11 +3811,6 @@ bool select_insert::send_eof() DBUG_RETURN(1); } - if (missed_fields_handler.have_missed_fields()) - { - missed_fields_handler.process_missed_fields(); - } - /* For the strict_mode call of push_warning above results to set error in Diagnostic_area. Therefore it is necessary to check whether @@ -4334,16 +4257,14 @@ select_create::prepare2() if (thd->locked_tables_mode <= LTM_LOCK_TABLES) table->file->ha_start_bulk_insert((ha_rows) 0); thd->abort_on_warning= (!ignore_errors && thd->is_strict_mode()); - Missed_fields_handler_impl miss_flds_handler(thd, ignore_errors, - table->s->column_bitmap_size, - table->s->fields); - if (check_that_all_fields_are_given_values(thd, table, table_list, - &miss_flds_handler)) + enum_check_fields save_coiunt_cuted_fields= thd->count_cuted_fields; + thd->count_cuted_fields= CHECK_FIELD_WARN; + + if (check_that_all_fields_are_given_values(thd, table, table_list)) DBUG_RETURN(1); - if (miss_flds_handler.have_missed_fields()) - miss_flds_handler.process_missed_fields(); + thd->count_cuted_fields= save_coiunt_cuted_fields; table->mark_columns_needed_for_insert(); table->file->extra(HA_EXTRA_WRITE_CACHE); === modified file 'sql/sql_insert.h' --- a/sql/sql_insert.h 2012-09-27 14:40:40 +0000 +++ b/sql/sql_insert.h 2012-10-01 03:34:26 +0000 @@ -37,75 +37,6 @@ void upgrade_lock_type_for_insert(THD *t bool is_multi_insert); -/** - Interface for handling table fields that isn't specified in INSERT statement - and doesn't have DEFAULT value in table definition. - - This interface is called for INSERT and INSERT SELECT - statements. -*/ -class Missed_fields_handler -{ -public: - virtual ~Missed_fields_handler() {} - - virtual void handle(bool is_view, Field* field, TABLE_LIST* table_list) = 0; -}; - - -/** - This class implements interface Missed_fields_handler. -*/ -class Missed_fields_handler_impl : public Missed_fields_handler -{ -public: - Missed_fields_handler_impl(THD* thd_val, bool ignore_errs, - uint column_bitmap_size, uint number_of_fields) - : thd(thd_val), number_of_missed_fields(0), - is_view(false), ignore_errors(ignore_errs) - { - if (column_bitmap_size) - { - uchar* bitmaps= (uchar*) alloc_root(thd->mem_root, - column_bitmap_size); - if (bitmaps) - { - bitmap_init(&fields_not_set_during_insert, - (my_bitmap_map*) (bitmaps), - number_of_fields, - false); - } - } - } - - virtual void handle(bool is_view, Field* field, TABLE_LIST* table_list); - - bool have_missed_fields() const - { - return number_of_missed_fields != 0; - } - - void process_missed_fields(); - -private: - void add_field_idx_to_missed_set(uint16 field_index, char* field_name); - - void add_field_idx_to_missed_set(uint16 field_index, char* field_name, - const char* v_db, const char* v_name); - - THD* thd; - - unsigned number_of_missed_fields; - bool is_view, ignore_errors; - - MY_BITMAP fields_not_set_during_insert; - List missed_fields_name_list; - - const char* view_db; - const char* view_name; -}; - - class select_insert :public select_result_interceptor { public: TABLE_LIST *table_list; @@ -118,8 +49,6 @@ private: */ List *fields; - Missed_fields_handler_impl missed_fields_handler; - public: ulonglong autoinc_value_of_last_inserted_row; // autogenerated or not COPY_INFO info; @@ -187,9 +116,6 @@ public: :table_list(table_list_par), table(table_par), fields(target_or_source_columns), - missed_fields_handler(thd, ignore, - (table ? table->s->column_bitmap_size : 0), - (table ? table->s->fields : 0)), autoinc_value_of_last_inserted_row(0), info(COPY_INFO::INSERT_OPERATION, target_columns, @@ -274,8 +200,7 @@ public: int check_that_all_fields_are_given_values(THD *thd, TABLE *entry, - TABLE_LIST *table_list, - Missed_fields_handler *handler); + TABLE_LIST *table_list); void prepare_triggers_for_insert_stmt(TABLE *table); int write_record(THD *thd, TABLE *table, COPY_INFO *info, COPY_INFO *update); === modified file 'sql/sql_load.cc' --- a/sql/sql_load.cc 2012-09-27 14:40:40 +0000 +++ b/sql/sql_load.cc 2012-10-02 05:35:46 +0000 @@ -292,17 +292,12 @@ int mysql_load(THD *thd,sql_exchange *ex } else { // Part field list - Missed_fields_handler_impl miss_flds_handler(thd, ignore, - table->s->column_bitmap_size, - table->s->fields); - /* TODO: use this conds for 'WITH CHECK OPTIONS' */ if (setup_fields(thd, Ref_ptr_array(), fields_vars, MARK_COLUMNS_WRITE, 0, 0) || setup_fields(thd, Ref_ptr_array(), set_fields, MARK_COLUMNS_WRITE, 0, 0) || - check_that_all_fields_are_given_values(thd, table, table_list, - &miss_flds_handler)) + check_that_all_fields_are_given_values(thd, table, table_list)) DBUG_RETURN(TRUE); /* Fix the expressions in SET clause */ if (setup_fields(thd, Ref_ptr_array(), set_values, MARK_COLUMNS_READ, 0, 0)) @@ -1144,6 +1139,9 @@ read_sep_field(THD *thd, COPY_INFO &info } } + if (thd->is_error()) + DBUG_RETURN(1); + switch (table_list->view_check_option(thd, ignore_check_option_errors)) { case VIEW_CHECK_SKIP: === modified file 'sql/sql_trigger.cc' --- a/sql/sql_trigger.cc 2012-09-27 14:40:40 +0000 +++ b/sql/sql_trigger.cc 2012-10-01 03:34:26 +0000 @@ -2255,7 +2255,6 @@ void Table_triggers_list::enable_fields_ if (thd->lex->sql_command != SQLCOM_LOAD) { (*next_field)->reset_tmp_null(); - (*next_field)->reset_warning_flag(); } (*next_field)->set_count_cuted_fields(thd->count_cuted_fields); } === modified file 'tests/mysql_client_test.c' --- a/tests/mysql_client_test.c 2012-07-26 18:46:34 +0000 +++ b/tests/mysql_client_test.c 2012-10-02 09:31:52 +0000 @@ -7847,7 +7847,7 @@ static void test_cuted_rows() count= mysql_warning_count(mysql); if (!opt_silent) fprintf(stdout, "\n total warnings: %d", count); - DIE_UNLESS(count == 2); + DIE_UNLESS(count == 1); rc= mysql_query(mysql, "SHOW WARNINGS"); myquery(rc); No bundle (reason: useless for push emails).