Commit 0a91dbcf authored by unknown's avatar unknown

BUG#28971 - ALTER TABLE followed by UPDATE for a CSV table

            make server crash

UPDATE against CSV table may cause server crash or update a table with wrong
values.

CSV can write only a whole row at once. That means it must read all columns,
that it is not going to update, and write them along with updated columns.
But only limited set of columns was read, those that were needed for the
UPDATE query.

With this fix all columns are read in case we're performing an UPDATE.


mysql-test/r/csv.result:
  A test case for BUG#28971.
mysql-test/t/csv.test:
  A test case for BUG#28971.
  Flush tables is here just to make crash more probable. If we remove it,
  fields will have old values from previous query and server won't crash.
storage/csv/ha_tina.cc:
  CSV engine is not capable to update single column,
  because it can only write a row at once. Thus we must
  read all columns if a table is opened for update.
parent 837ba138
...@@ -5240,3 +5240,11 @@ CREATE TABLE `bug21328` ( ...@@ -5240,3 +5240,11 @@ CREATE TABLE `bug21328` (
insert into bug21328 values (1,NULL,NULL); insert into bug21328 values (1,NULL,NULL);
alter table bug21328 engine=myisam; alter table bug21328 engine=myisam;
drop table bug21328; drop table bug21328;
create table t1(a blob, b int) engine=csv;
insert into t1 values('a', 1);
flush tables;
update t1 set b=2;
select * from t1;
a b
a 2
drop table t1;
...@@ -1653,3 +1653,14 @@ CREATE TABLE `bug21328` ( ...@@ -1653,3 +1653,14 @@ CREATE TABLE `bug21328` (
insert into bug21328 values (1,NULL,NULL); insert into bug21328 values (1,NULL,NULL);
alter table bug21328 engine=myisam; alter table bug21328 engine=myisam;
drop table bug21328; drop table bug21328;
#
# BUG#28971 - ALTER TABLE followed by UPDATE for a CSV table make server
# crash
#
create table t1(a blob, b int) engine=csv;
insert into t1 values('a', 1);
flush tables;
update t1 set b=2;
select * from t1;
drop table t1;
...@@ -590,6 +590,7 @@ int ha_tina::find_current_row(uchar *buf) ...@@ -590,6 +590,7 @@ int ha_tina::find_current_row(uchar *buf)
int eoln_len; int eoln_len;
my_bitmap_map *org_bitmap; my_bitmap_map *org_bitmap;
int error; int error;
bool read_all;
DBUG_ENTER("ha_tina::find_current_row"); DBUG_ENTER("ha_tina::find_current_row");
/* /*
...@@ -601,6 +602,8 @@ int ha_tina::find_current_row(uchar *buf) ...@@ -601,6 +602,8 @@ int ha_tina::find_current_row(uchar *buf)
local_saved_data_file_length, &eoln_len)) == 0) local_saved_data_file_length, &eoln_len)) == 0)
DBUG_RETURN(HA_ERR_END_OF_FILE); DBUG_RETURN(HA_ERR_END_OF_FILE);
/* We must read all columns in case a table is opened for update */
read_all= !bitmap_is_clear_all(table->write_set);
/* Avoid asserts in ::store() for columns that are not going to be updated */ /* Avoid asserts in ::store() for columns that are not going to be updated */
org_bitmap= dbug_tmp_use_all_columns(table, table->write_set); org_bitmap= dbug_tmp_use_all_columns(table, table->write_set);
error= HA_ERR_CRASHED_ON_USAGE; error= HA_ERR_CRASHED_ON_USAGE;
...@@ -678,7 +681,7 @@ int ha_tina::find_current_row(uchar *buf) ...@@ -678,7 +681,7 @@ int ha_tina::find_current_row(uchar *buf)
goto err; goto err;
} }
if (bitmap_is_set(table->read_set, (*field)->field_index)) if (read_all || bitmap_is_set(table->read_set, (*field)->field_index))
(*field)->store(buffer.ptr(), buffer.length(), system_charset_info); (*field)->store(buffer.ptr(), buffer.length(), system_charset_info);
} }
next_position= end_offset + eoln_len; next_position= end_offset + eoln_len;
......
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