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.
parent 8c266152
...@@ -655,7 +655,8 @@ void **thd_ha_data(const MYSQL_THD thd, const struct handlerton *hton); ...@@ -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; ...@@ -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
......
...@@ -1360,6 +1360,18 @@ bool Field::send_binary(Protocol *protocol) ...@@ -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 @@ class Field ...@@ -100,6 +100,8 @@ class Field
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 ...@@ -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) ...@@ -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 }; ...@@ -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 @@ ...@@ -45,8 +45,6 @@
#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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment