diff options
Diffstat (limited to 'sql/field.cc')
-rw-r--r-- | sql/field.cc | 130 |
1 files changed, 82 insertions, 48 deletions
diff --git a/sql/field.cc b/sql/field.cc index 80f138c53f6..03d78706f95 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +/* Copyright (c) 2000, 2010 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 @@ -1306,14 +1306,13 @@ String *Field::val_int_as_str(String *val_buffer, my_bool unsigned_val) Field::Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, const char *field_name_arg) - :ptr(ptr_arg), null_ptr(null_ptr_arg), - table(0), orig_table(0), table_name(0), - field_name(field_name_arg), - key_start(0), part_of_key(0), part_of_key_not_clustered(0), - part_of_sortkey(0), unireg_check(unireg_check_arg), - field_length(length_arg), null_bit(null_bit_arg), - is_created_from_null_item(FALSE), - vcol_info(0), stored_in_db(TRUE) + :ptr(ptr_arg), null_ptr(null_ptr_arg), table(0), orig_table(0), + table_name(0), field_name(field_name_arg), option_list(0), + option_struct(0), key_start(0), part_of_key(0), + part_of_key_not_clustered(0), part_of_sortkey(0), + unireg_check(unireg_check_arg), field_length(length_arg), + null_bit(null_bit_arg), is_created_from_null_item(FALSE), vcol_info(0), + stored_in_db(TRUE) { flags=null_ptr ? 0: NOT_NULL_FLAG; comment.str= (char*) ""; @@ -1375,12 +1374,14 @@ bool Field::send_binary(Protocol *protocol) to the size of this field (the slave or destination). @param field_metadata Encoded size in field metadata + @param mflags Flags from the table map event for the table. @retval 0 if this field's size is < the source field's size @retval 1 if this field's size is >= the source field's size */ int Field::compatible_field_size(uint field_metadata, - const Relay_log_info *rli_arg __attribute__((unused))) + const Relay_log_info *rli_arg __attribute__((unused)), + uint16 mflags __attribute__((unused))) { uint const source_size= pack_length_from_metadata(field_metadata); uint const destination_size= row_pack_length(); @@ -1707,7 +1708,7 @@ uint Field::fill_cache_field(CACHE_FIELD *copy) uint store_length; copy->str= ptr; copy->length= pack_length(); - copy->field= this; + copy->field= this; if (flags & BLOB_FLAG) { copy->type= CACHE_BLOB; @@ -1732,7 +1733,7 @@ uint Field::fill_cache_field(CACHE_FIELD *copy) copy->type= 0; store_length= 0; } - return copy->length+store_length; + return copy->length + store_length; } @@ -2887,7 +2888,8 @@ uint Field_new_decimal::pack_length_from_metadata(uint field_metadata) @retval 1 if this field's size is >= the source field's size */ int Field_new_decimal::compatible_field_size(uint field_metadata, - const Relay_log_info * __attribute__((unused))) + const Relay_log_info * __attribute__((unused)), + uint16 mflags __attribute__((unused))) { int compatible= 0; uint const source_precision= (field_metadata >> 8U) & 0x00ff; @@ -2952,16 +2954,16 @@ Field_new_decimal::unpack(uchar* to, a decimal and write that to the raw data buffer. */ decimal_digit_t dec_buf[DECIMAL_MAX_PRECISION]; - decimal_t dec; - dec.len= from_precision; - dec.buf= dec_buf; + decimal_t dec_val; + dec_val.len= from_precision; + dec_val.buf= dec_buf; /* Note: bin2decimal does not change the length of the field. So it is just the first step the resizing operation. The second step does the resizing using the precision and decimals from the slave. */ - bin2decimal((uchar *)from, &dec, from_precision, from_decimal); - decimal2bin(&dec, to, precision, decimals()); + bin2decimal((uchar *)from, &dec_val, from_precision, from_decimal); + decimal2bin(&dec_val, to, precision, decimals()); } else memcpy(to, from, len); // Sizes are the same, just copy the data. @@ -6340,7 +6342,7 @@ check_string_copy_error(Field_str *field, SYNOPSIS Field_longstr::report_if_important_data() - ptr - Truncated rest of string + pstr - Truncated rest of string end - End of truncated string count_spaces - Treat traling spaces as important data @@ -6356,12 +6358,12 @@ check_string_copy_error(Field_str *field, */ int -Field_longstr::report_if_important_data(const char *ptr, const char *end, +Field_longstr::report_if_important_data(const char *pstr, const char *end, bool count_spaces) { - if ((ptr < end) && table->in_use->count_cuted_fields) + if ((pstr < end) && table->in_use->count_cuted_fields) { - if (test_if_important_data(field_charset, ptr, end)) + if (test_if_important_data(field_charset, pstr, end)) { if (table->in_use->abort_on_warning) set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1); @@ -6667,7 +6669,8 @@ check_field_for_37426(const void *param_arg) #endif int Field_string::compatible_field_size(uint field_metadata, - const Relay_log_info *rli_arg) + const Relay_log_info *rli_arg, + uint16 mflags __attribute__((unused))) { #ifdef HAVE_REPLICATION const Check_field_param check_param = { this }; @@ -6675,7 +6678,7 @@ int Field_string::compatible_field_size(uint field_metadata, check_field_for_37426, &check_param)) return FALSE; // Not compatible field sizes #endif - return Field::compatible_field_size(field_metadata, rli_arg); + return Field::compatible_field_size(field_metadata, rli_arg, mflags); } @@ -7020,9 +7023,8 @@ const uint Field_varstring::MAX_SIZE= UINT_MAX16; */ int Field_varstring::do_save_field_metadata(uchar *metadata_ptr) { - char *ptr= (char *)metadata_ptr; DBUG_ASSERT(field_length <= 65535); - int2store(ptr, field_length); + int2store((char*)metadata_ptr, field_length); return 2; } @@ -8887,14 +8889,20 @@ bool Field_num::eq_def(Field *field) } +/** + Check whether two numeric fields can be considered 'equal' for table + alteration purposes. Fields are equal if they are of the same type + and retain the same pack length. +*/ + uint Field_num::is_equal(Create_field *new_field) { return ((new_field->sql_type == real_type()) && - ((new_field->flags & UNSIGNED_FLAG) == (uint) (flags & - UNSIGNED_FLAG)) && + ((new_field->flags & UNSIGNED_FLAG) == + (uint) (flags & UNSIGNED_FLAG)) && ((new_field->flags & AUTO_INCREMENT_FLAG) == (uint) (flags & AUTO_INCREMENT_FLAG)) && - (new_field->length <= max_display_length())); + (new_field->pack_length == pack_length())); } @@ -9227,8 +9235,13 @@ uint Field_bit::get_key_image(uchar *buff, uint length, imagetype type_arg) */ int Field_bit::do_save_field_metadata(uchar *metadata_ptr) { - *metadata_ptr= bit_len; - *(metadata_ptr + 1)= bytes_in_rec; + /* + Since this class and Field_bit_as_char have different ideas of + what should be stored here, we compute the values of the metadata + explicitly using the field_length. + */ + metadata_ptr[0]= field_length % 8; + metadata_ptr[1]= field_length / 8; return 2; } @@ -9268,20 +9281,26 @@ uint Field_bit::pack_length_from_metadata(uint field_metadata) @retval 1 if this field's size is >= the source field's size */ int Field_bit::compatible_field_size(uint field_metadata, - const Relay_log_info * __attribute__((unused))) + const Relay_log_info * __attribute__((unused)), + uint16 mflags) { - int compatible= 0; - uint const source_size= pack_length_from_metadata(field_metadata); - uint const destination_size= row_pack_length(); - uint const from_bit_len= field_metadata & 0x00ff; - uint const from_len= (field_metadata >> 8U) & 0x00ff; - if ((bit_len == 0) || (from_bit_len == 0)) - compatible= (source_size <= destination_size); - else if (from_bit_len > bit_len) - compatible= (from_len < bytes_in_rec); - else - compatible= ((from_bit_len <= bit_len) && (from_len <= bytes_in_rec)); - return (compatible); + uint from_bit_len= 8 * (field_metadata >> 8) + (field_metadata & 0xff); + uint to_bit_len= max_display_length(); + + /* + If the bit length exact flag is clear, we are dealing with an old + master, so we allow some less strict behaviour if replicating by + moving both bit lengths to an even multiple of 8. + + We do this by computing the number of bytes to store the field + instead, and then compare the result. + */ + if (!(mflags & Table_map_log_event::TM_BIT_LEN_EXACT_F)) { + from_bit_len= (from_bit_len + 7) / 8; + to_bit_len= (to_bit_len + 7) / 8; + } + + return from_bit_len <= to_bit_len; } @@ -9572,7 +9591,8 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, Item *fld_on_update_value, LEX_STRING *fld_comment, char *fld_change, List<String> *fld_interval_list, CHARSET_INFO *fld_charset, uint fld_geom_type, - Virtual_column_info *fld_vcol_info) + Virtual_column_info *fld_vcol_info, + engine_option_value *create_opt) { uint sign_len, allowed_type_modifier= 0; ulong max_field_charlength= MAX_FIELD_CHARLENGTH; @@ -9583,6 +9603,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, field_name= fld_name; def= fld_default_value; flags= fld_type_modifier; + option_list= create_opt; unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ? Field::NEXT_NUMBER : Field::NONE); decimals= fld_decimals ? (uint)atoi(fld_decimals) : 0; @@ -9603,13 +9624,13 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, interval_list.empty(); comment= *fld_comment; + vcol_info= fld_vcol_info; stored_in_db= TRUE; /* Initialize data for a computed field */ if ((uchar)fld_type == (uchar)MYSQL_TYPE_VIRTUAL) { DBUG_ASSERT(vcol_info && vcol_info->expr_item); - vcol_info= fld_vcol_info; stored_in_db= vcol_info->is_stored(); /* Walk through the Item tree checking if all items are valid @@ -9629,8 +9650,6 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, */ sql_type= fld_type= vcol_info->get_real_type(); } - else - vcol_info= NULL; /* Set NO_DEFAULT_VALUE_FLAG if this field doesn't have a default value and @@ -10224,6 +10243,8 @@ Create_field::Create_field(Field *old_field,Field *orig_field) decimals= old_field->decimals(); vcol_info= old_field->vcol_info; stored_in_db= old_field->stored_in_db; + option_list= old_field->option_list; + option_struct= old_field->option_struct; /* Fix if the original table had 4 byte pointer blobs */ if (flags & BLOB_FLAG) @@ -10298,6 +10319,19 @@ Create_field::Create_field(Field *old_field,Field *orig_field) /** + Makes a clone of this object for ALTER/CREATE TABLE + + @param mem_root MEM_ROOT where to clone the field +*/ + +Create_field *Create_field::clone(MEM_ROOT *mem_root) const +{ + Create_field *res= new (mem_root) Create_field(*this); + return res; +} + + +/** maximum possible display length for blob. @return |