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.
This commit is contained in:
parent
d45d542aad
commit
b16b2683e5
@ -655,7 +655,8 @@ void **thd_ha_data(const MYSQL_THD thd, const struct handlerton *hton);
|
|||||||
int thd_tx_isolation(const MYSQL_THD thd);
|
int thd_tx_isolation(const MYSQL_THD thd);
|
||||||
char *thd_security_context(MYSQL_THD thd, char *buffer, unsigned int length,
|
char *thd_security_context(MYSQL_THD thd, char *buffer, unsigned int length,
|
||||||
unsigned int max_query_len);
|
unsigned int max_query_len);
|
||||||
|
/* Increments the row counter, see THD::row_count */
|
||||||
|
void thd_inc_row_count(MYSQL_THD thd);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -5276,7 +5276,7 @@ drop table t1;
|
|||||||
create table t1(a int, b int) engine=csv;
|
create table t1(a int, b int) engine=csv;
|
||||||
repair table t1;
|
repair table t1;
|
||||||
Table Op Msg_type Msg_text
|
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
|
test.t1 repair status OK
|
||||||
check table t1;
|
check table t1;
|
||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
|
12
sql/field.cc
12
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)
|
my_decimal *Field::val_decimal(my_decimal *decimal)
|
||||||
{
|
{
|
||||||
/* This never have to be called */
|
/* This never have to be called */
|
||||||
|
@ -100,6 +100,8 @@ public:
|
|||||||
virtual int store(longlong nr, bool unsigned_val)=0;
|
virtual int store(longlong nr, bool unsigned_val)=0;
|
||||||
virtual int store_decimal(const my_decimal *d)=0;
|
virtual int store_decimal(const my_decimal *d)=0;
|
||||||
virtual int store_time(MYSQL_TIME *ltime, timestamp_type t_type);
|
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 double val_real(void)=0;
|
||||||
virtual longlong val_int(void)=0;
|
virtual longlong val_int(void)=0;
|
||||||
virtual my_decimal *val_decimal(my_decimal *);
|
virtual my_decimal *val_decimal(my_decimal *);
|
||||||
|
@ -494,6 +494,13 @@ enum enum_parsing_place
|
|||||||
struct st_table;
|
struct st_table;
|
||||||
class THD;
|
class THD;
|
||||||
|
|
||||||
|
enum enum_check_fields
|
||||||
|
{
|
||||||
|
CHECK_FIELD_IGNORE,
|
||||||
|
CHECK_FIELD_WARN,
|
||||||
|
CHECK_FIELD_ERROR_FOR_NULL
|
||||||
|
};
|
||||||
|
|
||||||
/* Struct to handle simple linked lists */
|
/* Struct to handle simple linked lists */
|
||||||
|
|
||||||
typedef struct st_sql_list {
|
typedef struct st_sql_list {
|
||||||
|
@ -253,6 +253,11 @@ int thd_tx_isolation(const THD *thd)
|
|||||||
return (int) thd->variables.tx_isolation;
|
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
|
Dumps a text description of a thread, its security context
|
||||||
|
@ -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_duplicates { DUP_ERROR, DUP_REPLACE, DUP_UPDATE };
|
||||||
enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON,
|
enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON,
|
||||||
DELAY_KEY_WRITE_ALL };
|
DELAY_KEY_WRITE_ALL };
|
||||||
enum enum_check_fields
|
|
||||||
{ CHECK_FIELD_IGNORE, CHECK_FIELD_WARN, CHECK_FIELD_ERROR_FOR_NULL };
|
|
||||||
enum enum_mark_columns
|
enum enum_mark_columns
|
||||||
{ MARK_COLUMNS_NONE, MARK_COLUMNS_READ, MARK_COLUMNS_WRITE};
|
{ MARK_COLUMNS_NONE, MARK_COLUMNS_READ, MARK_COLUMNS_WRITE};
|
||||||
|
|
||||||
|
@ -45,8 +45,6 @@ TODO:
|
|||||||
#pragma implementation // gcc: Class implementation
|
#pragma implementation // gcc: Class implementation
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MYSQL_SERVER 1
|
|
||||||
|
|
||||||
#include "mysql_priv.h"
|
#include "mysql_priv.h"
|
||||||
#include <mysql/plugin.h>
|
#include <mysql/plugin.h>
|
||||||
#include "ha_tina.h"
|
#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 (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;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1002,7 +1001,6 @@ int ha_tina::delete_row(const uchar * buf)
|
|||||||
|
|
||||||
int ha_tina::rnd_init(bool scan)
|
int ha_tina::rnd_init(bool scan)
|
||||||
{
|
{
|
||||||
THD *thd= table ? table->in_use : current_thd;
|
|
||||||
DBUG_ENTER("ha_tina::rnd_init");
|
DBUG_ENTER("ha_tina::rnd_init");
|
||||||
|
|
||||||
/* set buffer to the beginning of the file */
|
/* set buffer to the beginning of the file */
|
||||||
@ -1014,7 +1012,6 @@ int ha_tina::rnd_init(bool scan)
|
|||||||
stats.records= 0;
|
stats.records= 0;
|
||||||
records_is_known= 0;
|
records_is_known= 0;
|
||||||
chain_ptr= chain;
|
chain_ptr= chain;
|
||||||
thd->count_cuted_fields= CHECK_FIELD_WARN; // To find wrong values
|
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
@ -1298,9 +1295,9 @@ int ha_tina::repair(THD* thd, HA_CHECK_OPT* check_opt)
|
|||||||
current_position= next_position= 0;
|
current_position= next_position= 0;
|
||||||
|
|
||||||
/* Read the file row-by-row. If everything is ok, repair is not needed. */
|
/* 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)))
|
while (!(rc= find_current_row(buf)))
|
||||||
{
|
{
|
||||||
|
thd_inc_row_count(thd);
|
||||||
rows_repaired++;
|
rows_repaired++;
|
||||||
current_position= next_position;
|
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 */
|
/* set current position to the beginning of the file */
|
||||||
current_position= next_position= 0;
|
current_position= next_position= 0;
|
||||||
/* Read the file row-by-row. If everything is ok, repair is not needed. */
|
/* 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)))
|
while (!(rc= find_current_row(buf)))
|
||||||
{
|
{
|
||||||
|
thd_inc_row_count(thd);
|
||||||
count--;
|
count--;
|
||||||
current_position= next_position;
|
current_position= next_position;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user