From 5a1b7ddb683a34c0a512c890a11170e0b0b14da2 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 6 May 2008 21:43:46 +0500 Subject: Partial rollback of fix for bug #30059: End-space truncation is inconsistent or incorrect. For better conformance with standard, truncation procedure of CHAR columns has been changed to ignore truncation of trailing whitespace characters (note has been removed). Finally, for columns with non-binary charsets: 1. CHAR(N) columns silently ignore trailing whitespace truncation; 2. VARCHAR and TEXT columns issue Note about truncation. BLOBs and other columns with BINARY charset are unaffected. mysql-test/r/bdb.result: Rollback of bug #30059 fix. mysql-test/r/heap.result: Rollback of bug #30059 fix. mysql-test/r/innodb.result: Rollback of bug #30059 fix. mysql-test/r/myisam.result: Rollback of bug #30059 fix. mysql-test/r/strict.result: Rollback of bug #30059 fix. mysql-test/r/type_binary.result: Rollback of bug #30059 fix. mysql-test/r/warnings.result: Updated test case for bug #30059. sql/field.cc: Post-commit fix for bug #30059. The Field_longstr::report_if_important_data method has been changed to notify about trailing spaces only if the new count_spaces parameter is TRUE. The Field_string::store method has been changed to ignore trailing whitespace truncation (CHAR column type). sql/field.h: Post-commit fix for bug #30059. The Field_longstr::report_if_important_data method declaration has been changed to accept extra parameter: bool count_spaces. --- sql/field.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sql/field.h') diff --git a/sql/field.h b/sql/field.h index c82d65147ac..8d771a151a7 100644 --- a/sql/field.h +++ b/sql/field.h @@ -455,7 +455,8 @@ public: class Field_longstr :public Field_str { protected: - int report_if_important_data(const char *ptr, const char *end); + int report_if_important_data(const char *ptr, const char *end, + bool count_spaces); public: Field_longstr(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, -- cgit v1.2.1 From c8bc6a5d1bb53eb5231f229731a4429d8f0d2827 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Thu, 19 Jun 2008 18:02:04 +0500 Subject: Fixed bug #37076: TIMESTAMP/DATETIME/DATE values are not replicated correctly between machines with mixed endiannes mysql-test/extra/rpl_tests/rpl_row_basic.test: Added regression test for bug#37076. mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result: Added regression test for bug#37076. mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result: Added regression test for bug#37076. mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result: Added regression test for bug#37076. sql/field.h: Fixed bug #37076: TIMESTAMP/DATETIME/DATE values are not replicated correctly between machines with mixed endiannes pack and unpack virtual methods have been overloaded for Field_timestamp (TIMESTAMP domain), Field_datetime (DATETIME domain) and Field_date (DATE domain) classes to replicate data between platforms with different endiannes in a correct way like in Field_long and Field_longlong classes. Common code have been moved to private handle_int32 and handle_int64 private methods. --- sql/field.h | 182 ++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 116 insertions(+), 66 deletions(-) (limited to 'sql/field.h') diff --git a/sql/field.h b/sql/field.h index 479a71dfee5..c71f54d8165 100644 --- a/sql/field.h +++ b/sql/field.h @@ -529,6 +529,77 @@ private: */ virtual int do_save_field_metadata(uchar *metadata_ptr) { return 0; } + +protected: + /* + Helper function to pack()/unpack() int32 values + */ + static void handle_int32(uchar *to, const uchar *from, + bool low_byte_first_from, bool low_byte_first_to) + { + int32 val; +#ifdef WORDS_BIGENDIAN + if (low_byte_first_from) + val = sint4korr(from); + else +#endif + longget(val, from); + +#ifdef WORDS_BIGENDIAN + if (low_byte_first_to) + int4store(to, val); + else +#endif + longstore(to, val); + } + + /* + Helper function to pack()/unpack() int64 values + */ + static void handle_int64(uchar* to, const uchar *from, + bool low_byte_first_from, bool low_byte_first_to) + { + int64 val; +#ifdef WORDS_BIGENDIAN + if (low_byte_first_from) + val = sint8korr(from); + else +#endif + longlongget(val, from); + +#ifdef WORDS_BIGENDIAN + if (low_byte_first_to) + int8store(to, val); + else +#endif + longlongstore(to, val); + } + + uchar *pack_int32(uchar *to, const uchar *from, bool low_byte_first_to) + { + handle_int32(to, from, table->s->db_low_byte_first, low_byte_first_to); + return to + sizeof(int32); + } + + const uchar *unpack_int32(uchar* to, const uchar *from, + bool low_byte_first_from) + { + handle_int32(to, from, low_byte_first_from, table->s->db_low_byte_first); + return from + sizeof(int32); + } + + uchar *pack_int64(uchar* to, const uchar *from, bool low_byte_first_to) + { + handle_int64(to, from, table->s->db_low_byte_first, low_byte_first_to); + return to + sizeof(int64); + } + + const uchar *unpack_int64(uchar* to, const uchar *from, + bool low_byte_first_from) + { + handle_int64(to, from, low_byte_first_from, table->s->db_low_byte_first); + return from + sizeof(int64); + } }; @@ -916,43 +987,16 @@ public: void sql_type(String &str) const; uint32 max_display_length() { return MY_INT32_NUM_DECIMAL_DIGITS; } virtual uchar *pack(uchar* to, const uchar *from, - uint max_length, bool low_byte_first) + uint max_length __attribute__((unused)), + bool low_byte_first) { - int32 val; -#ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) - val = sint4korr(from); - else -#endif - longget(val, from); - -#ifdef WORDS_BIGENDIAN - if (low_byte_first) - int4store(to, val); - else -#endif - longstore(to, val); - return to + sizeof(val); + return pack_int32(to, from, low_byte_first); } - virtual const uchar *unpack(uchar* to, const uchar *from, - uint param_data, bool low_byte_first) + uint param_data __attribute__((unused)), + bool low_byte_first) { - int32 val; -#ifdef WORDS_BIGENDIAN - if (low_byte_first) - val = sint4korr(from); - else -#endif - longget(val, from); - -#ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) - int4store(to, val); - else -#endif - longstore(to, val); - return from + sizeof(val); + return unpack_int32(to, from, low_byte_first); } }; @@ -997,43 +1041,16 @@ public: bool can_be_compared_as_longlong() const { return TRUE; } uint32 max_display_length() { return 20; } virtual uchar *pack(uchar* to, const uchar *from, - uint max_length, bool low_byte_first) + uint max_length __attribute__((unused)), + bool low_byte_first) { - int64 val; -#ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) - val = sint8korr(from); - else -#endif - longlongget(val, from); - -#ifdef WORDS_BIGENDIAN - if (low_byte_first) - int8store(to, val); - else -#endif - longlongstore(to, val); - return to + sizeof(val); + return pack_int64(to, from, low_byte_first); } - virtual const uchar *unpack(uchar* to, const uchar *from, - uint param_data, bool low_byte_first) + uint param_data __attribute__((unused)), + bool low_byte_first) { - int64 val; -#ifdef WORDS_BIGENDIAN - if (low_byte_first) - val = sint8korr(from); - else -#endif - longlongget(val, from); - -#ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) - int8store(to, val); - else -#endif - longlongstore(to, val); - return from + sizeof(val); + return unpack_int64(to, from, low_byte_first); } }; #endif @@ -1207,6 +1224,17 @@ public: bool get_date(MYSQL_TIME *ltime,uint fuzzydate); bool get_time(MYSQL_TIME *ltime); timestamp_auto_set_type get_auto_set_type() const; + uchar *pack(uchar *to, const uchar *from, + uint max_length __attribute__((unused)), bool low_byte_first) + { + return pack_int32(to, from, low_byte_first); + } + const uchar *unpack(uchar* to, const uchar *from, + uint param_data __attribute__((unused)), + bool low_byte_first) + { + return unpack_int32(to, from, low_byte_first); + } }; @@ -1261,6 +1289,17 @@ public: void sql_type(String &str) const; bool can_be_compared_as_longlong() const { return TRUE; } bool zero_pack() const { return 1; } + uchar *pack(uchar* to, const uchar *from, + uint max_length __attribute__((unused)), bool low_byte_first) + { + return pack_int32(to, from, low_byte_first); + } + const uchar *unpack(uchar* to, const uchar *from, + uint param_data __attribute__((unused)), + bool low_byte_first) + { + return unpack_int32(to, from, low_byte_first); + } }; @@ -1374,6 +1413,17 @@ public: bool zero_pack() const { return 1; } bool get_date(MYSQL_TIME *ltime,uint fuzzydate); bool get_time(MYSQL_TIME *ltime); + uchar *pack(uchar* to, const uchar *from, + uint max_length __attribute__((unused)), bool low_byte_first) + { + return pack_int64(to, from, low_byte_first); + } + const uchar *unpack(uchar* to, const uchar *from, + uint param_data __attribute__((unused)), + bool low_byte_first) + { + return unpack_int64(to, from, low_byte_first); + } }; -- cgit v1.2.1 From 711305e2c5772d3fd1f555a27ebd5bcb94fd6a77 Mon Sep 17 00:00:00 2001 From: Mats Kindahl Date: Mon, 30 Jun 2008 22:11:18 +0200 Subject: BUG#37426: RBR breaks for CHAR() UTF-8 fields > 85 chars In order to handle CHAR() fields, 8 bits were reserved for the size of the CHAR field. However, instead of denoting the number of characters in the field, field_length was used which denotes the number of bytes in the field. Since UTF-8 fields can have three bytes per character (and has been extended to have four bytes per character in 6.0), an extra two bits have been encoded in the field metadata work for fields of type Field_string (i.e., CHAR fields). Since the metadata word is filled, the extra bits have been encoded in the upper 4 bits of the real type (the most significant byte of the metadata word) by computing the bitwise xor of the extra two bits. Since the upper 4 bits of the real type always is 1111 for Field_string, this means that for fields of length <256, the encoding is identical to the encoding used in pre-5.1.26 servers, but for lengths of 256 or more, an unrecognized type is formed, causing an old slave (that does not handle lengths of 256 or more) to stop. mysql-test/extra/rpl_tests/rpl_row_basic.test: Adding test cases for replicating UTF-8 fields of lengths of 256 or more (bytes). mysql-test/suite/binlog/r/binlog_base64_flag.result: Result file change. mysql-test/suite/binlog/t/binlog_base64_flag.test: Adding tests to trigger check that an error is generated when replicating from a 5.1.25 server for tables with a CHAR(128) but not when replicating a table with a CHAR(63). Although the bug indicates that the limit is 83, we elected to use CHAR(63) since 6.0 uses 4-byte UTF-8, and anything exceeding 63 would then cause the test to fail when the patch is merged to 6.0. mysql-test/suite/bugs/combinations: Adding combinations file to run all bug reports in all binlog modes (where applicable). mysql-test/suite/bugs/r/rpl_bug37426.result: Result file change. mysql-test/suite/bugs/t/rpl_bug37426.test: Added test for reported bug. mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result: Result file change. mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result: Result file change. sql/field.cc: Encoding an extra two bits in the most significant nibble (4 bits) of the metadata word. Adding assertions to ensure that no attempt is made to use lengths longer than supported. Extending compatible_field_size() function with an extra parameter holding a Relay_log_instace for error reporting. Field_string::compatible_field_size() now reports an error if field size for a CHAR is >255. sql/field.h: Field length is now computed from most significant 4 bits of metadata word, or is equal to the row pack length if there is no metadata. Extending compatible_field_size() function with an extra parameter holding a Relay_log_instace for error reporting. sql/rpl_utility.cc: Adding relay log parameter to compatible_field_size(). Minor refactoring to eliminate duplicate code. sql/slave.cc: Extending rpl_master_has_bug() with a single-argument predicate function and a parameter to the predicate function. The predicate function can be used to test for extra conditions for the bug before writing an error message. sql/slave.h: Extending rpl_master_has_bug() with a single-argument predicate function and a parameter to the predicate function. The predicate function can be used to test for extra conditions for the bug before writing an error message. Also removing gratuitous default argument. sql/sql_insert.cc: Changing calls to rpl_master_has_bug() to adapt to changed signature. --- sql/field.h | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'sql/field.h') diff --git a/sql/field.h b/sql/field.h index 479a71dfee5..6c6cab1e4f0 100644 --- a/sql/field.h +++ b/sql/field.h @@ -30,6 +30,8 @@ const uint32 max_field_size= (uint32) 4294967295U; class Send_field; class Protocol; class Create_field; +class Relay_log_info; + struct st_cache_field; int field_conv(Field *to,Field *from); @@ -162,7 +164,8 @@ public: table, which is located on disk). */ virtual uint32 pack_length_in_rec() const { return pack_length(); } - virtual int compatible_field_size(uint field_metadata); + virtual int compatible_field_size(uint field_metadata, + const Relay_log_info *); virtual uint pack_length_from_metadata(uint field_metadata) { return field_metadata; } /* @@ -716,7 +719,8 @@ public: uint32 pack_length() const { return (uint32) bin_size; } uint pack_length_from_metadata(uint field_metadata); uint row_pack_length() { return pack_length(); } - int compatible_field_size(uint field_metadata); + int compatible_field_size(uint field_metadata, + const Relay_log_info *rli); uint is_equal(Create_field *new_field); virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data, bool low_byte_first); @@ -1425,7 +1429,14 @@ public: virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data, bool low_byte_first); uint pack_length_from_metadata(uint field_metadata) - { return (field_metadata & 0x00ff); } + { + DBUG_PRINT("debug", ("field_metadata: 0x%04x", field_metadata)); + if (field_metadata == 0) + return row_pack_length(); + return (((field_metadata >> 4) & 0x300) ^ 0x300) + (field_metadata & 0x00ff); + } + int compatible_field_size(uint field_metadata, + const Relay_log_info *rli); 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); @@ -1878,7 +1889,8 @@ public: uint pack_length_from_metadata(uint field_metadata); uint row_pack_length() { return (bytes_in_rec + ((bit_len > 0) ? 1 : 0)); } - int compatible_field_size(uint field_metadata); + int compatible_field_size(uint field_metadata, + const Relay_log_info *rli); 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 From 548413824b85fa0550c8d9a297546b80ed1643e1 Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Thu, 24 Jul 2008 22:38:44 +0200 Subject: Bug#38002 table_cache consumes too much memory with blobs Tables in the table definition cache are keeping a cache buffer for blob fields which can consume a lot of memory. This patch introduces a maximum size threshold for these buffers. sql/sql_base.cc: Added function free_field_buffers_larger_than to reclaim memory from blob field buffers too large to be cached. sql/table.cc: Added function free_field_buffers_larger_than --- sql/field.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql/field.h') diff --git a/sql/field.h b/sql/field.h index 7d312dbd2b8..8e00cf013dc 100644 --- a/sql/field.h +++ b/sql/field.h @@ -13,7 +13,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - /* Because of the function new_field() all field classes that have static variables must declare the size_of() member function. @@ -1669,6 +1668,7 @@ public: } int reset(void) { bzero(ptr, packlength+sizeof(uchar*)); return 0; } void reset_fields() { bzero((uchar*) &value,sizeof(value)); } + uint32 get_field_buffer_size(void) { return value.alloced_length(); } #ifndef WORDS_BIGENDIAN static #endif -- cgit v1.2.1 From e04dfffb591b7533a3c31eec56df4fb7fedc3986 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Mon, 11 Aug 2008 10:10:00 -0600 Subject: Bug#38296 (low memory crash with many conditions in a query) This fix is for 5.0 only : back porting the 6.0 patch manually The parser code in sql/sql_yacc.yy needs to be more robust to out of memory conditions, so that when parsing a query fails due to OOM, the thread gracefully returns an error. Before this fix, a new/alloc returning NULL could: - cause a crash, if dereferencing the NULL pointer, - produce a corrupted parsed tree, containing NULL nodes, - alter the semantic of a query, by silently dropping token values or nodes With this fix: - C++ constructors are *not* executed with a NULL "this" pointer when operator new fails. This is achieved by declaring "operator new" with a "throw ()" clause, so that a failed new gracefully returns NULL on OOM conditions. - calls to new/alloc are tested for a NULL result, - The thread diagnostic area is set to an error status when OOM occurs. This ensures that a request failing in the server properly returns an ER_OUT_OF_RESOURCES error to the client. - OOM conditions cause the parser to stop immediately (MYSQL_YYABORT). This prevents causing further crashes when using a partially built parsed tree in further rules in the parser. No test scripts are provided, since automating OOM failures is not instrumented in the server. Tested under the debugger, to verify that an error in alloc_root cause the thread to returns gracefully all the way to the client application, with an ER_OUT_OF_RESOURCES error. --- sql/field.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sql/field.h') diff --git a/sql/field.h b/sql/field.h index 8d771a151a7..241ad61f339 100644 --- a/sql/field.h +++ b/sql/field.h @@ -48,7 +48,8 @@ class Field Field(const Item &); /* Prevent use of these */ void operator=(Field &); public: - static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); } + static void *operator new(size_t size) throw () + { return (void*) sql_alloc((uint) size); } static void operator delete(void *ptr_arg, size_t size) { TRASH(ptr_arg, size); } char *ptr; // Position to field in record -- cgit v1.2.1 From 54a59681d68d9e2edd1354443d35e54bd8373090 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Thu, 28 Aug 2008 02:10:37 +0500 Subject: Bug #37799: SELECT with a BIT column in WHERE clause returns unexpected result If: 1. a table has a not nullable BIT column c1 with a length shorter than 8 bits and some additional not nullable columns c2 etc, and 2. the WHERE clause is like: (c1 = constant) AND c2 ..., the SELECT query returns unexpected result set. The server stores BIT columns in a tricky way to save disk space: if column's bit length is not divisible by 8, the server places reminder bits among the null bits at the start of a record. The rest bytes are stored in the record itself, and Field::ptr points to these rest bytes. However if a bit length of the whole column is less than 8, there are no remaining bytes, and there is nothing to store in the record at its regular place. In this case Field::ptr points to bytes actually occupied by the next column in a record. If both columns (BIT and the next column) are NOT NULL, the Field::eq function incorrectly deduces that this is the same column, so query transformation/equal item elimination code (see build_equal_items_for_cond) may mix these columns and damage conditions containing references to them. mysql-test/r/type_bit.result: Added test case for bug #37799. mysql-test/t/type_bit.test: Added test case for bug #37799. sql/field.h: 1. The Field::eq function has been modified to take types of comparing columns into account to distinguish between BIT and not BIT columns referencing the same bytes in a record. 2. Unnecessary type comparison has been removed from the Field_bit::eq function (moved to Field::eq). --- sql/field.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sql/field.h') diff --git a/sql/field.h b/sql/field.h index 241ad61f339..7b2dda77095 100644 --- a/sql/field.h +++ b/sql/field.h @@ -138,7 +138,7 @@ public: virtual bool eq(Field *field) { return (ptr == field->ptr && null_ptr == field->null_ptr && - null_bit == field->null_bit); + null_bit == field->null_bit && field->type() == type()); } virtual bool eq_def(Field *field); @@ -1489,7 +1489,6 @@ public: bool eq(Field *field) { return (Field::eq(field) && - field->type() == type() && bit_ptr == ((Field_bit *)field)->bit_ptr && bit_ofs == ((Field_bit *)field)->bit_ofs); } -- cgit v1.2.1