mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
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.
This commit is contained in:

parent
8c26615204
commit
ee5403110d
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
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)
|
||||
{
|
||||
/* This never have to be called */
|
||||
|
@ -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 *);
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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};
|
||||
|
||||
|
@ -45,8 +45,6 @@ TODO:
|
||||
#pragma implementation // gcc: Class implementation
|
||||
#endif
|
||||
|
||||
#define MYSQL_SERVER 1
|
||||
|
||||
#include "mysql_priv.h"
|
||||
#include <mysql/plugin.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 ((*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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user