From: Dmitry Shulga Date: October 12 2011 3:36pm Subject: bzr push into mysql-trunk branch (Dmitry.Shulga:3466 to 3467) WL#6030 List-Archive: http://lists.mysql.com/commits/141406 Message-Id: <201110121536.p9CFaq1x009361@acsmt356.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3467 Dmitry Shulga 2011-10-12 Prerequisite patch for WL#6030. This patch minimizes a direct access to the data member Field::null_ptr. Direct access to null_ptr was replaced by call methods null_offset(), null_default_value_offset(), is_null_in_record(). Redundant static functions field_in_record_is_null() were removed from ha_federated.cc, ha_innodb.cc. @ sql/field.h The methods Field::null_offset() and Field::null_default_value_offset were added. Added overloaded method Field::new_key_field without arguments new_null_ptr, new_nullbit, is_nullable. This method is used when values for these missed arguments may be get from Field's instance. @ sql/item_func.cc Item_func_sp::init_result_field modified: pass pointer to null value as a last argument of sp_head::create_result_field instead of explicit use of attributes Field::null_ptr, Field::null_bit. @ sql/sp_head.cc sp_head::create_result_field() was midified: added pointer to byte that stores a null value as the last argument. Subsequently this pointer is passed to make_field() to initialize datamember Field::nul_ptr. @ sql/sp_head.h Added pointer to byte that stores a null value as a last argument of sp_head::create_result_field. @ sql/sql_select.cc Use Field::null_offset() when makes calculation of null byte offset for record. Call of Field::new_kye_field() was replaced by overloaded method that doesn't get arguments new_null_ptr, new_null_bit, is_nullable. @ sql/sql_update.cc Use Field::null_offset() when makes calculation of null byte offset for record. @ sql/table.cc Use Field::null_offset() and Field::null_default_value_offset() when makes calculation of null byte offset for record. @ storage/federated/ha_federated.cc Static function field_in_record_is_null() was removed since its implementation is a duplication of functional of Field::is_null_in_record(). @ storage/heap/ha_heap.cc Use Field::null_offset() when makes calculation of null byte offset for record. @ storage/innobase/handler/ha_innodb.cc Static function field_in_record_is_null() was removed since its implementation is a duplication of functional of Field::is_null_in_record(). Use Field::null_offset() when makes calculation of null byte offset for record. @ storage/myisam/ha_myisam.cc Use Field::null_offset() when makes calculation of null byte offset for record. modified: sql/field.cc sql/field.h sql/item_func.cc sql/sp.cc sql/sp_head.cc sql/sp_head.h sql/sql_select.cc sql/sql_update.cc sql/table.cc storage/federated/ha_federated.cc storage/heap/ha_heap.cc storage/innobase/handler/ha_innodb.cc storage/myisam/ha_myisam.cc 3466 Dmitry Shulga 2011-10-06 This patch is a prerequisite for WL#6030. This patch changes the way that Field's nullability is checked for. Instead of use null_ptr directly to check for nullability this patch takes into account the value of Field::flags attribute and the flag NOT_NULL_FLAG when makes decision about Field's nullability. Renamed maybe_null to is_nullable and real_maybe_null to real_is_nullable. @ sql/field.cc Filed's nullability now is checked using deicated value in flags attribute, null_ptr is no longer used to check for NOT NULL. Changed the Field constructors and constructors of derivated from Field classes to have nullability as an explicit parameter. Explicit nullability argument was added to the factory method new_key_field(). new_key_field implementation is changed - make update of flags for new created field object according to nullability condition. At some places tabs were removed. @ sql/field.h Filed's nullability now is checked using deicated value in flags attribute, null_ptr is no longer used to check for NOT NULL. Changed the Field constructors and constructors of derivated from Field classes to have nullability as an explicit parameter. Explicit nullability flag was added to the factory method new_key_field(). Some methods were renamed: maybe_null ==> is_nullable, real_maybe_null ==> real_is_nullable The method is_null_in_record_with_with_offset was removed since there is the method is_real_null that has the same functionality. At some places tabs were removed. @ sql/field_conv.cc References to Field::null_ptr were removed. Checking for nullability now is done using methods Field::real_is_nullable(), Field::is_nullable(). Since the methods Field::maybe_null(), Field::real_maybe_null() were renamed the references to these methods were also renamed. do_outer_field_to_null_str() were modified: checking for nullability is performed taking into account that is_nullable attribute may be true but from_null_ptr still may have NULL value. This is possible since currently we don't garantee that Fiedld::null_ptr is never equal to NULL. Such assertion will be true after a follow-up patch. do_copy_not_null() was modified: added check for NULL against value of Copy_field::from_null_ptr before makes dereference this pointer. At some places tabs were removed. @ sql/filesort.cc Since the method Field::maybe_null wase renamed the references to this method were also renamed. @ sql/item.cc Since the method Field::maybe_null was renamed the references to this method were also renamed. Item::tmp_table_field_from_field_type() and Item_type_holder::make_field_by_type() were modified: added passing of an explicit nullability flag to constructor of classes derived from Field. @ sql/item_subselect.cc References to Field::real_maybe_null() were replaced by Field::real_is_nullable() since the "rename" refactoring method was applied to Field class. @ sql/key.cc References to Field::is_null_in_record_with_offset () were replaced by Field::is_real_null() since the "rename" refactoring method was applied to Field class. @ sql/log_event.cc References to Field::maybe_null() were replaced by Field::is_nullable() since the "rename" refactoring method was applied to Field class. @ sql/log_event_old.cc References to Field::maybe_null() were replaced by Field::is_nullable() since the "rename" refactoring method was applied to Field class. @ sql/opt_range.cc References to Field::real_maybe_null() were replaced by Field::real_is_nullable() since the "rename" refactoring method was applied to Field class. @ sql/opt_sum.cc References to Field::real_maybe_null() were replaced by Field::real_is_nullable() since the "rename" refactoring method was applied to Field class. @ sql/rpl_record.cc References to Field::maybe_null() were replaced by Field::is_nullable() since the "rename" refactoring method was applied to Field class. @ sql/sql_join_cache.cc References to Field::maybe_null() were replaced by Field::is_nullable() since the "rename" refactoring method was applied to Field class. @ sql/sql_load.cc References to Field::maybe_null() were replaced by Field::is_nullable() since the "rename" refactoring method was applied to Field class. @ sql/sql_partition.cc References to Field::is_nullable() and Field::real_maybe_null() were replaced by Field::is_nullable() and Field::real_is_nullable() since the "rename" refactoring method was applied to Field class. @ sql/sql_select.cc References to Field::maybe_null() and Field::real_maybe_null() were replaced by Field::is_nullable() and Field::real_is_nullable() since the "rename" refactoring method was applied to Field class. @ sql/sql_select.h References to Field::maybe_nullable() were replaced by Field::is_nullable() since the "rename" refactoring method was applied to Field class. Added passing an explicit nullability flag when instantiating the class Field_varstring. @ sql/sql_show.cc References to Field::maybe_null() were replaced by Field::is_nullable() since the "rename" refactoring method was applied to Field class. Access to the Field::flags attribute were replaced by the call of Field::real_is_nullable(). @ sql/sql_table.cc References to Field::maybe_null() were replaced by Field::is_nullable() since the "rename" refactoring method was applied to Field class. Access to the Field::flags attribute were replaced by the call of Field::real_is_nullable(). @ sql/sql_update.cc References to Field::real_maybe_null() were replaced by Field::real_is_nullable() since the "rename" refactoring method was applied to Field class. @ sql/table.cc References to Field::real_maybe_null() were replaced by Field::real_is_nullable() since the "rename" refactoring method was applied to Field class. Access to the Field::null_ptr attribute were replaced by the call of Field::real_is_nullable(). @ sql/unireg.cc make_empty_rec() was modified: access to the Field::null_ptr attribute when set nullability for a field were replaced by the call of Field::set_null(). @ storage/csv/ha_tina.cc ha_tina::create() was modified: references to Field::maybe_null() was replaced by Field::is_nullable() since the "rename" refactoring method was applied to Field class. @ storage/federated/ha_federated.cc ha_federated::field_in_record_is_null() was modified: access to the Field::null_ptr attribute during a checking for nullability was replaced by the call of Field::real_is_nullable(). @ storage/heap/ha_heap.cc heap_prepare_hp_create_info() was modified: access to the Field::null_ptr attribute during a checking for nullability was replaced by the call of Field::real_is_nullable(). @ storage/innobase/handler/ha_innodb.cc The methods field_in_record_is_null(), build_template_field(), calc_row_difference(), create_table_def() were modified: access to the Field::null_ptr attribute during a checking for nullability were replaced by the call of Field::real_is_nullable(). @ storage/innobase/handler/handler0alter.cc Reference to Field::real_maybe_null() was replaced by Field::real_is_nullable() since the "rename" refactoring method was applied to Field class. @ storage/myisam/ha_myisam.cc table2myisam() was modified: access to the Field::null_ptr attribute during a checking for nullability was replaced by the call of Field::real_is_nullable(). modified: sql/field.cc sql/field.h sql/field_conv.cc sql/filesort.cc sql/item.cc sql/item_subselect.cc sql/key.cc sql/log_event.cc sql/log_event_old.cc sql/opt_range.cc sql/opt_sum.cc sql/rpl_record.cc sql/sql_join_cache.cc sql/sql_load.cc sql/sql_partition.cc sql/sql_select.cc sql/sql_select.h sql/sql_show.cc sql/sql_table.cc sql/sql_update.cc sql/table.cc sql/unireg.cc storage/csv/ha_tina.cc storage/federated/ha_federated.cc storage/heap/ha_heap.cc storage/innobase/handler/ha_innodb.cc storage/innobase/handler/handler0alter.cc storage/myisam/ha_myisam.cc === modified file 'sql/field.cc' --- a/sql/field.cc 2011-10-06 07:10:19 +0000 +++ b/sql/field.cc 2011-10-12 15:35:10 +0000 @@ -1333,7 +1333,7 @@ Field::do_last_null_byte() const { DBUG_ASSERT(null_ptr == NULL || null_ptr >= table->record[0]); if (null_ptr) - return (size_t) (null_ptr - table->record[0]) + 1; + return (size_t) null_offset() + 1; return LAST_NULL_BYTE_UNDEF; } === modified file 'sql/field.h' --- a/sql/field.h 2011-10-06 07:10:19 +0000 +++ b/sql/field.h 2011-10-12 15:35:10 +0000 @@ -288,7 +288,7 @@ public: { if (!real_is_nullable()) return FALSE; - return test(record[(uint) (null_ptr - table->record[0])] & + return test(record[(uint) null_offset()] & null_bit); } inline void set_null(my_ptrdiff_t row_offset= 0) @@ -306,6 +306,14 @@ public: LAST_NULL_BYTE_UNDEF= 0 }; + inline ptrdiff_t null_offset() const { + return null_ptr - table->record[0]; + } + + inline ptrdiff_t null_default_value_offset(const uchar* default_values) + { + return null_ptr - default_values; + } /* Find the position of the last null byte for the field. @@ -345,6 +353,13 @@ public: virtual Field *new_key_field(MEM_ROOT *root, TABLE *new_table, uchar *new_ptr, uchar *new_null_ptr, uint new_null_bit, bool is_nullable); + inline Field *new_key_field(MEM_ROOT *root, TABLE *new_table, + uchar *new_ptr) + { + return new_key_field(root, new_table, new_ptr, + null_ptr, null_bit, real_is_nullable()); + } + /** Makes a shallow copy of the Field object. === modified file 'sql/item_func.cc' --- a/sql/item_func.cc 2011-09-08 12:48:08 +0000 +++ b/sql/item_func.cc 2011-10-12 15:35:10 +0000 @@ -6259,7 +6259,7 @@ Item_func_sp::init_result_field(THD *thd share->table_name = empty_name; if (!(sp_result_field= m_sp->create_result_field(max_length, name, - dummy_table))) + dummy_table, (uchar *)&null_value))) { DBUG_RETURN(TRUE); } @@ -6274,8 +6274,6 @@ Item_func_sp::init_result_field(THD *thd else sp_result_field->move_field(result_buf); - sp_result_field->null_ptr= (uchar *) &null_value; - sp_result_field->null_bit= 1; DBUG_RETURN(FALSE); } === modified file 'sql/sp.cc' --- a/sql/sp.cc 2011-08-19 13:04:28 +0000 +++ b/sql/sp.cc 2011-10-12 15:35:10 +0000 @@ -923,7 +923,7 @@ sp_returns_type(THD *thd, String &result memset(&share, 0, sizeof(share)); table.in_use= thd; table.s = &share; - field= sp->create_result_field(0, 0, &table); + field= sp->create_result_field(0, 0, &table, (uchar*)""); field->sql_type(result); if (field->has_charset()) === modified file 'sql/sp_head.cc' --- a/sql/sp_head.cc 2011-09-21 11:01:41 +0000 +++ b/sql/sp_head.cc 2011-10-12 15:35:10 +0000 @@ -816,7 +816,7 @@ sp_head::~sp_head() Field * sp_head::create_result_field(uint field_max_length, const char *field_name, - TABLE *table) + TABLE *table, uchar *null_value) { uint field_length; Field *field; @@ -829,7 +829,7 @@ sp_head::create_result_field(uint field_ field= ::make_field(table->s, /* TABLE_SHARE ptr */ (uchar*) 0, /* field ptr */ field_length, /* field [max] length */ - (uchar*) "", /* null ptr */ + null_value, /* null ptr */ 0, /* null bit */ m_return_field_def.pack_flag, m_return_field_def.sql_type, === modified file 'sql/sp_head.h' --- a/sql/sp_head.h 2011-08-12 07:18:41 +0000 +++ b/sql/sp_head.h 2011-10-12 15:35:10 +0000 @@ -383,7 +383,7 @@ public: char *create_string(THD *thd, ulong *lenp); Field *create_result_field(uint field_max_length, const char *field_name, - TABLE *table); + TABLE *table, uchar *null_value); bool fill_field_definition(THD *thd, LEX *lex, enum enum_field_types field_type, === modified file 'sql/sql_select.cc' --- a/sql/sql_select.cc 2011-10-06 07:10:19 +0000 +++ b/sql/sql_select.cc 2011-10-12 15:35:10 +0000 @@ -17383,10 +17383,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARA cur_group->buff=(char*) group_buff; if (!(cur_group->field= field->new_key_field(thd->mem_root,table, group_buff + - test(maybe_null), - field->null_ptr, - field->null_bit, - field->real_is_nullable()))) + test(maybe_null)))) goto err; /* purecov: inspected */ if (maybe_null) { @@ -17783,10 +17780,7 @@ TABLE *create_duplicate_weedout_tmp_tabl if (!using_unique_constraint) { if (!(key_field= field->new_key_field(thd->mem_root, table, - group_buff, - field->null_ptr, - field->null_bit, - field->real_is_nullable()))) + group_buff))) goto err; key_part_info->key_part_flag|= HA_END_SPACE_ARE_EQUAL; //todo need this? } @@ -18079,7 +18073,7 @@ bool create_myisam_tmp_table(TABLE *tabl if (field->real_is_nullable()) { seg->null_bit= field->null_bit; - seg->null_pos= (uint) (field->null_ptr - (uchar*) table->record[0]); + seg->null_pos= (uint) field->null_offset(); /* We are using a GROUP BY on something that contains NULL In this case we have to tell MyISAM that two NULL should === modified file 'sql/sql_update.cc' --- a/sql/sql_update.cc 2011-10-06 07:10:19 +0000 +++ b/sql/sql_update.cc 2011-10-12 15:35:10 +0000 @@ -85,7 +85,7 @@ bool compare_records(const TABLE *table) { if (field->real_is_nullable()) { - uchar null_byte_index= field->null_ptr - table->record[0]; + uchar null_byte_index= field->null_offset(); if (((table->record[0][null_byte_index]) & field->null_bit) != ((table->record[1][null_byte_index]) & field->null_bit)) === modified file 'sql/table.cc' --- a/sql/table.cc 2011-10-06 07:10:19 +0000 +++ b/sql/table.cc 2011-10-12 15:35:10 +0000 @@ -799,7 +799,7 @@ void KEY_PART_INFO::init_from_field(Fiel field= fld; fieldnr= field->field_index + 1; null_bit= field->null_bit; - null_offset= (uint) (field->null_ptr - (uchar*) field->table->record[0]); + null_offset= (uint) field->null_offset(); offset= field->offset(field->table->record[0]); length= (uint16) field->key_length(); store_length= length; @@ -1658,8 +1658,8 @@ static int open_binary_frm(THD *thd, TAB key_part->type= field->key_type(); if (field->real_is_nullable()) { - key_part->null_offset=(uint) ((uchar*) field->null_ptr - - share->default_values); + key_part->null_offset= + (uint) field->null_default_value_offset(share->default_values); key_part->null_bit= field->null_bit; key_part->store_length+=HA_KEY_NULL_LENGTH; keyinfo->flags|=HA_NULL_PART_KEY; === modified file 'storage/federated/ha_federated.cc' --- a/storage/federated/ha_federated.cc 2011-10-06 07:10:19 +0000 +++ b/storage/federated/ha_federated.cc 2011-10-12 15:35:10 +0000 @@ -1681,43 +1681,6 @@ int ha_federated::close(void) DBUG_RETURN(free_share(share)); } -/* - - Checks if a field in a record is SQL NULL. - - SYNOPSIS - field_in_record_is_null() - table TABLE pointer, MySQL table object - field Field pointer, MySQL field object - record char pointer, contains record - - DESCRIPTION - This method uses the record format information in table to track - the null bit in record. - - RETURN VALUE - 1 if NULL - 0 otherwise -*/ - -static inline uint field_in_record_is_null(TABLE *table, - Field *field, - char *record) -{ - int null_offset; - DBUG_ENTER("ha_federated::field_in_record_is_null"); - - if (!field->real_is_nullable()) - DBUG_RETURN(0); - - null_offset= (uint) ((char*)field->null_ptr - (char*)table->record[0]); - - if (record[null_offset] & field->null_bit) - DBUG_RETURN(1); - - DBUG_RETURN(0); -} - /** @brief Construct the INSERT statement. @@ -2209,7 +2172,7 @@ int ha_federated::update_row(const uchar size_t field_name_length= strlen((*field)->field_name); append_ident(&where_string, (*field)->field_name, field_name_length, ident_quote_char); - if (field_in_record_is_null(table, *field, (char*) old_data)) + if ((*field)->is_null_in_record(old_data)) where_string.append(STRING_WITH_LEN(" IS NULL ")); else { @@ -2682,7 +2645,7 @@ int ha_federated::rnd_next_int(uchar *bu format SYNOPSIS - field_in_record_is_null() + ha_federated::read_next() buf byte pointer to record result mysql result set === modified file 'storage/heap/ha_heap.cc' --- a/storage/heap/ha_heap.cc 2011-10-06 07:10:19 +0000 +++ b/storage/heap/ha_heap.cc 2011-10-12 15:35:10 +0000 @@ -710,7 +710,7 @@ heap_prepare_hp_create_info(TABLE *table if (field->real_is_nullable()) { seg->null_bit= field->null_bit; - seg->null_pos= (uint) (field->null_ptr - (uchar*) table_arg->record[0]); + seg->null_pos= (uint) field->null_offset(); } else { === modified file 'storage/innobase/handler/ha_innodb.cc' --- a/storage/innobase/handler/ha_innodb.cc 2011-10-06 07:10:19 +0000 +++ b/storage/innobase/handler/ha_innodb.cc 2011-10-12 15:35:10 +0000 @@ -4352,35 +4352,6 @@ get_field_offset( return((uint) (field->ptr - table->record[0])); } -/**************************************************************//** -Checks if a field in a record is SQL NULL. Uses the record format -information in table to track the null bit in record. -@return 1 if NULL, 0 otherwise */ -static inline -uint -field_in_record_is_null( -/*====================*/ - TABLE* table, /*!< in: MySQL table object */ - Field* field, /*!< in: MySQL field object */ - char* record) /*!< in: a row in MySQL format */ -{ - int null_offset; - - if (!field->real_is_nullable()) { - - return(0); - } - - null_offset = (uint) ((char*) field->null_ptr - - (char*) table->record[0]); - - if (record[null_offset] & field->null_bit) { - - return(1); - } - - return(0); -} /*************************************************************//** InnoDB uses this function to compare two data fields for which the data type @@ -4994,10 +4965,7 @@ build_template_field( } if (field->real_is_nullable()) { - templ->mysql_null_byte_offset = - (ulint) ((char*) field->null_ptr - - (char*) table->record[0]); - + templ->mysql_null_byte_offset = (ulint)field->null_offset(); templ->mysql_null_bit_mask = (ulint) field->null_bit; } else { templ->mysql_null_bit_mask = 0; @@ -5761,13 +5729,11 @@ calc_row_difference( } if (field->real_is_nullable()) { - if (field_in_record_is_null(table, field, - (char*) old_row)) { + if (field->is_null_in_record(old_row)) { o_len = UNIV_SQL_NULL; } - if (field_in_record_is_null(table, field, - (char*) new_row)) { + if (field->is_null_in_record(new_row)) { n_len = UNIV_SQL_NULL; } } === modified file 'storage/myisam/ha_myisam.cc' --- a/storage/myisam/ha_myisam.cc 2011-10-06 07:10:19 +0000 +++ b/storage/myisam/ha_myisam.cc 2011-10-12 15:35:10 +0000 @@ -278,8 +278,7 @@ int table2myisam(TABLE *table_arg, MI_KE if (field->real_is_nullable()) { keydef[i].seg[j].null_bit= field->null_bit; - keydef[i].seg[j].null_pos= (uint) (field->null_ptr- - (uchar*) table_arg->record[0]); + keydef[i].seg[j].null_pos= (uint) field->null_offset(); } else { @@ -362,8 +361,7 @@ int table2myisam(TABLE *table_arg, MI_KE if (found->real_is_nullable()) { recinfo_pos->null_bit= found->null_bit; - recinfo_pos->null_pos= (uint) (found->null_ptr - - (uchar*) table_arg->record[0]); + recinfo_pos->null_pos= (uint) (found->null_offset()); } else { No bundle (reason: useless for push emails).