From 7dc693229fc90dbd9c7744435483cbe1a0767c56 Mon Sep 17 00:00:00 2001 From: Martin Hansson Date: Tue, 16 Mar 2010 15:51:00 +0100 Subject: Bug#47762: Incorrect result from MIN() when WHERE tests NOT NULL column for NULL The optimization to read MIN() and MAX() values from an index did not properly handle comparisons with NULL values. Fixed by giving up the particular optimization step if there are non-NULL safe comparisons with NULL values, as the result is NULL anyway. Also, Oracle copyright notice was added to all files. --- sql/field.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'sql/field.h') diff --git a/sql/field.h b/sql/field.h index 55604193687..5bfcc9f21a6 100644 --- a/sql/field.h +++ b/sql/field.h @@ -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 @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* Because of the function new_field() all field classes that have static @@ -55,7 +55,11 @@ public: static void operator delete(void *ptr_arg, size_t size) { TRASH(ptr_arg, size); } uchar *ptr; // Position to field in record - uchar *null_ptr; // Byte where null_bit is + /** + Byte where the @c NULL bit is stored inside a record. If this Field is a + @c NOT @c NULL field, this member is @c NULL. + */ + uchar *null_ptr; /* Note that you can use table->in_use as replacement for current_thd member only inside of val_*() and store() members (e.g. you can't use it in cons) @@ -261,6 +265,9 @@ public: inline void set_notnull(my_ptrdiff_t row_offset= 0) { if (null_ptr) null_ptr[row_offset]&= (uchar) ~null_bit; } inline bool maybe_null(void) { return null_ptr != 0 || table->maybe_null; } + /** + Signals that this field is NULL-able. + */ inline bool real_maybe_null(void) { return null_ptr != 0; } enum { -- cgit v1.2.1 From 2c5f439d651f00f2f13d1f8e94f3701dadf9c7d3 Mon Sep 17 00:00:00 2001 From: Mats Kindahl Date: Wed, 17 Mar 2010 15:28:49 +0100 Subject: BUG#49618: Field length stored incorrectly in binary log for InnoDB The class Field_bit_as_char stores the metadata for the field incorrecly because bytes_in_rec and bit_len are set to (field_length + 7 ) / 8 and 0 respectively, while Field_bit has the correct values field_length / 8 and field_length % 8. Solved the problem by re-computing the values for the metadata based on the field_length instead of using the bytes_in_rec and bit_len variables. To handle compatibility with old server, a table map flag was added to indicate that the bit computation is exact. If the flag is clear, the slave computes the number of bytes required to store the bit field and compares that instead, effectively allowing replication *without conversion* from any field length that require the same number of bytes to store. mysql-test/suite/rpl/t/rpl_typeconv_innodb.test: Adding test to check compatibility for bit field replication when using InnoDB sql/field.cc: Extending compatible_field_size() with flags from table map to allow fields to check master info. sql/field.h: Extending compatible_field_size() with flags from table map to allow fields to check master info. sql/log.cc: Removing table map flags since they are not used outside table map class. sql/log_event.cc: Removing flags parameter from table map constructor since it is not used and does not have to be exposed. sql/log_event.h: Adding flag to denote that bit length for bit field type is exact and not potentially rounded to even bytes. sql/rpl_utility.cc: Adding fields to table_def to store table map flags. sql/rpl_utility.h: Removing obsolete comment and adding flags to store table map flags from master. --- sql/field.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sql/field.h') diff --git a/sql/field.h b/sql/field.h index 784b9133790..0ed5e6d4cac 100644 --- a/sql/field.h +++ b/sql/field.h @@ -165,7 +165,7 @@ public: */ virtual uint32 pack_length_in_rec() const { return pack_length(); } virtual int compatible_field_size(uint field_metadata, - const Relay_log_info *); + const Relay_log_info *, uint16 mflags); virtual uint pack_length_from_metadata(uint field_metadata) { return field_metadata; } /* @@ -803,7 +803,7 @@ public: uint pack_length_from_metadata(uint field_metadata); uint row_pack_length() { return pack_length(); } int compatible_field_size(uint field_metadata, - const Relay_log_info *rli); + const Relay_log_info *rli, uint16 mflags); uint is_equal(Create_field *new_field); virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data, bool low_byte_first); @@ -1498,7 +1498,7 @@ public: return (((field_metadata >> 4) & 0x300) ^ 0x300) + (field_metadata & 0x00ff); } int compatible_field_size(uint field_metadata, - const Relay_log_info *rli); + const Relay_log_info *rli, uint16 mflags); uint row_pack_length() { return (field_length + 1); } int pack_cmp(const uchar *a,const uchar *b,uint key_length, my_bool insert_or_update); @@ -1962,7 +1962,7 @@ public: uint row_pack_length() { return (bytes_in_rec + ((bit_len > 0) ? 1 : 0)); } int compatible_field_size(uint field_metadata, - const Relay_log_info *rli); + const Relay_log_info *rli, uint16 mflags); void sql_type(String &str) const; virtual uchar *pack(uchar *to, const uchar *from, uint max_length, bool low_byte_first); -- cgit v1.2.1