summaryrefslogtreecommitdiff
path: root/sql/field.cc
diff options
context:
space:
mode:
authorAlexey Kopytov <Alexey.Kopytov@Sun.com>2010-03-20 23:23:42 +0300
committerAlexey Kopytov <Alexey.Kopytov@Sun.com>2010-03-20 23:23:42 +0300
commitacc2b9e3662cd868f5108b1b4ee7257d95582f02 (patch)
tree772f4ae43ad7ce905f024b77bebdd1897d813391 /sql/field.cc
parent41f23283e54d311155959faf58ae7edf81803ca3 (diff)
parent84917914e01415cbbc2a128cabc344c127e76db1 (diff)
downloadmariadb-git-acc2b9e3662cd868f5108b1b4ee7257d95582f02.tar.gz
Manual merge of mysql-5.1-bugteam to mysql-trunk-merge.
Conflicts: Text conflict in mysql-test/r/partition_innodb.result Text conflict in sql/field.h Text conflict in sql/item.h Text conflict in sql/item_cmpfunc.h Text conflict in sql/item_sum.h Text conflict in sql/log_event_old.cc Text conflict in sql/protocol.cc Text conflict in sql/sql_select.cc Text conflict in sql/sql_yacc.yy
Diffstat (limited to 'sql/field.cc')
-rw-r--r--sql/field.cc76
1 files changed, 45 insertions, 31 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 5fe031a38b9..ad6b14d4b0a 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
@@ -1401,12 +1401,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();
@@ -2906,7 +2908,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;
@@ -2971,16 +2974,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.
@@ -6361,7 +6364,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
@@ -6377,12 +6380,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_WARN, ER_DATA_TOO_LONG, 1);
@@ -6675,7 +6678,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 };
@@ -6683,7 +6687,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);
}
@@ -7027,9 +7031,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;
}
@@ -9265,8 +9268,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;
}
@@ -9306,20 +9314,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;
}