From b16b2683e5a7e9b1eae9a59b477b8eb0517b6c68 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Jul 2007 17:17:58 +0500 Subject: [PATCH] Complementary fix for bug #29353: inserting a negative value to a csv table leads to the table corruption New Field::store() method implemented to explicitly set thd->count_cuted_fields before value storing, instead of (incorrectly) setting it in the CSV storage engine. Thread row counter now properly incremented during check and repair in the CSV engine. include/mysql/plugin.h: Complementary fix for bug #29353: inserting a negative value to a csv table leads to the table corruption - thd_inc_row_count() function prototype added, which allows a storage engine to increment thread row counter. mysql-test/r/csv.result: Complementary fix for bug #29353: inserting a negative value to a csv table leads to the table corruption - result adjusted. sql/field.cc: Complementary fix for bug #29353: inserting a negative value to a csv table leads to the table corruption - Field::store(const char *to, uint length, CHARSET_INFO *cs, enum_check_fields check_level) method introduced in order to explicitly set count_cuted_fields before a ::store call, then reset it back after. sql/field.h: Complementary fix for bug #29353: inserting a negative value to a csv table leads to the table corruption - Field::store(const char *to, uint length, CHARSET_INFO *cs, enum_check_fields check_level) method introduced in order to explicitly set count_cuted_fields before a ::store call, then reset it back after. sql/mysql_priv.h: Complementary fix for bug #29353: inserting a negative value to a csv table leads to the table corruption - enum enum_check_fields moved from sql/sql_class.h to sql/mysql_priv.h as it's used now in the field.h sql/sql_class.cc: Complementary fix for bug #29353: inserting a negative value to a csv table leads to the table corruption - implementation of the new thd_inc_row_count() function which increments thread row counter. sql/sql_class.h: Complementary fix for bug #29353: inserting a negative value to a csv table leads to the table corruption - enum enum_check_fields moved from sql/sql_class.h to sql/mysql_priv.h as it's used now in the field.h storage/csv/ha_tina.cc: Complementary fix for bug #29353: inserting a negative value to a csv table leads to the table corruption - removed #define MYSQL_SERVER 1 - "a storage engine should not need internals of the server" - removed thd->count_cuted_fields= CHECK_FIELD_WARN as we are not allowed to access internals of THD. - used new Field::store() method to explicitly set thd->count_cuted_fields to CHECK_FIELD_WARN - thd_inc_row_count() calls added to ha_tina::repair() and ha_tina::check() to get proper row count values. --- include/mysql/plugin.h | 3 ++- mysql-test/r/csv.result | 2 +- sql/field.cc | 12 ++++++++++++ sql/field.h | 2 ++ sql/mysql_priv.h | 7 +++++++ sql/sql_class.cc | 5 +++++ sql/sql_class.h | 2 -- storage/csv/ha_tina.cc | 11 ++++------- 8 files changed, 33 insertions(+), 11 deletions(-) diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index 7b224695324..dd540225deb 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -655,7 +655,8 @@ void **thd_ha_data(const MYSQL_THD thd, const struct handlerton *hton); int thd_tx_isolation(const MYSQL_THD thd); char *thd_security_context(MYSQL_THD thd, char *buffer, unsigned int length, unsigned int max_query_len); - +/* Increments the row counter, see THD::row_count */ +void thd_inc_row_count(MYSQL_THD thd); #ifdef __cplusplus } diff --git a/mysql-test/r/csv.result b/mysql-test/r/csv.result index e7cdd612a25..5076220f74b 100644 --- a/mysql-test/r/csv.result +++ b/mysql-test/r/csv.result @@ -5276,7 +5276,7 @@ drop table t1; create table t1(a int, b int) engine=csv; repair table t1; Table Op Msg_type Msg_text -test.t1 repair Warning Data truncated for column 'a' at row 1 +test.t1 repair Warning Data truncated for column 'a' at row 5 test.t1 repair status OK check table t1; Table Op Msg_type Msg_text diff --git a/sql/field.cc b/sql/field.cc index 55a93ed46d6..332a654c89f 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1360,6 +1360,18 @@ bool Field::send_binary(Protocol *protocol) } +int Field::store(const char *to, uint length, CHARSET_INFO *cs, + enum_check_fields check_level) +{ + int res; + enum_check_fields old_check_level= table->in_use->count_cuted_fields; + table->in_use->count_cuted_fields= check_level; + res= store(to, length, cs); + table->in_use->count_cuted_fields= old_check_level; + return res; +} + + my_decimal *Field::val_decimal(my_decimal *decimal) { /* This never have to be called */ diff --git a/sql/field.h b/sql/field.h index a0fe0f2e57e..ef76cb47d36 100644 --- a/sql/field.h +++ b/sql/field.h @@ -100,6 +100,8 @@ public: virtual int store(longlong nr, bool unsigned_val)=0; virtual int store_decimal(const my_decimal *d)=0; virtual int store_time(MYSQL_TIME *ltime, timestamp_type t_type); + int store(const char *to, uint length, CHARSET_INFO *cs, + enum_check_fields check_level); virtual double val_real(void)=0; virtual longlong val_int(void)=0; virtual my_decimal *val_decimal(my_decimal *); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 5a50b03282f..9264ca295d9 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -494,6 +494,13 @@ enum enum_parsing_place struct st_table; class THD; +enum enum_check_fields +{ + CHECK_FIELD_IGNORE, + CHECK_FIELD_WARN, + CHECK_FIELD_ERROR_FOR_NULL +}; + /* Struct to handle simple linked lists */ typedef struct st_sql_list { diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 40b37ed7405..e279e23ab69 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -253,6 +253,11 @@ int thd_tx_isolation(const THD *thd) return (int) thd->variables.tx_isolation; } +extern "C" +void thd_inc_row_count(THD *thd) +{ + thd->row_count++; +} /* Dumps a text description of a thread, its security context diff --git a/sql/sql_class.h b/sql/sql_class.h index c46adc62c7c..c3ee71e3297 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -39,8 +39,6 @@ enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY, RNEXT_SAME }; enum enum_duplicates { DUP_ERROR, DUP_REPLACE, DUP_UPDATE }; enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON, DELAY_KEY_WRITE_ALL }; -enum enum_check_fields -{ CHECK_FIELD_IGNORE, CHECK_FIELD_WARN, CHECK_FIELD_ERROR_FOR_NULL }; enum enum_mark_columns { MARK_COLUMNS_NONE, MARK_COLUMNS_READ, MARK_COLUMNS_WRITE}; diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc index 239d47890ed..2ee96fd5d05 100644 --- a/storage/csv/ha_tina.cc +++ b/storage/csv/ha_tina.cc @@ -45,8 +45,6 @@ TODO: #pragma implementation // gcc: Class implementation #endif -#define MYSQL_SERVER 1 - #include "mysql_priv.h" #include #include "ha_tina.h" @@ -675,7 +673,8 @@ int ha_tina::find_current_row(uchar *buf) if (bitmap_is_set(table->read_set, (*field)->field_index)) { - if ((*field)->store(buffer.ptr(), buffer.length(), buffer.charset())) + if ((*field)->store(buffer.ptr(), buffer.length(), buffer.charset(), + CHECK_FIELD_WARN)) goto err; } } @@ -1002,7 +1001,6 @@ int ha_tina::delete_row(const uchar * buf) int ha_tina::rnd_init(bool scan) { - THD *thd= table ? table->in_use : current_thd; DBUG_ENTER("ha_tina::rnd_init"); /* set buffer to the beginning of the file */ @@ -1014,7 +1012,6 @@ int ha_tina::rnd_init(bool scan) stats.records= 0; records_is_known= 0; chain_ptr= chain; - thd->count_cuted_fields= CHECK_FIELD_WARN; // To find wrong values DBUG_RETURN(0); } @@ -1298,9 +1295,9 @@ int ha_tina::repair(THD* thd, HA_CHECK_OPT* check_opt) current_position= next_position= 0; /* Read the file row-by-row. If everything is ok, repair is not needed. */ - thd->count_cuted_fields= CHECK_FIELD_WARN; // To find wrong values while (!(rc= find_current_row(buf))) { + thd_inc_row_count(thd); rows_repaired++; current_position= next_position; } @@ -1464,9 +1461,9 @@ int ha_tina::check(THD* thd, HA_CHECK_OPT* check_opt) /* set current position to the beginning of the file */ current_position= next_position= 0; /* Read the file row-by-row. If everything is ok, repair is not needed. */ - thd->count_cuted_fields= CHECK_FIELD_WARN; // To find wrong values while (!(rc= find_current_row(buf))) { + thd_inc_row_count(thd); count--; current_position= next_position; }