Bug #30430 crash:./mtr --embedded-server --ps-protocol cache_innodb func_misc...

PS-protocol data is stored in different format - the MYSQL_RECORDS->data
contains the link to the record content, not to array of the links to
the field's contents. So we have to handle it separately for
embedded-server query cache.
parent 0fe103f9
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#include "emb_qcache.h" #include "emb_qcache.h"
#include "embedded_priv.h" #include "embedded_priv.h"
void Querycache_stream::store_char(char c) void Querycache_stream::store_uchar(uchar c)
{ {
if (data_end == cur_data) if (data_end == cur_data)
use_next_block(TRUE); use_next_block(TRUE);
...@@ -142,7 +142,7 @@ void Querycache_stream::store_safe_str(const char *str, uint str_len) ...@@ -142,7 +142,7 @@ void Querycache_stream::store_safe_str(const char *str, uint str_len)
store_int(0); store_int(0);
} }
char Querycache_stream::load_char() uchar Querycache_stream::load_uchar()
{ {
if (cur_data == data_end) if (cur_data == data_end)
use_next_block(FALSE); use_next_block(FALSE);
...@@ -301,8 +301,8 @@ uint emb_count_querycache_size(THD *thd) ...@@ -301,8 +301,8 @@ uint emb_count_querycache_size(THD *thd)
*data->embedded_info->prev_ptr= NULL; // this marks the last record *data->embedded_info->prev_ptr= NULL; // this marks the last record
cur_row= data->data; cur_row= data->data;
n_rows= data->rows; n_rows= data->rows;
/* n_fields + n_rows + (field_info + strlen * n_rows) * n_fields */ /* n_fields + n_rows + field_info * n_fields */
result+= (uint) (4+8 + (42 + 4*n_rows)*data->fields); result+= (uint) (4+8 + 42*data->fields);
for(; field < field_end; field++) for(; field < field_end; field++)
{ {
...@@ -313,13 +313,23 @@ uint emb_count_querycache_size(THD *thd) ...@@ -313,13 +313,23 @@ uint emb_count_querycache_size(THD *thd)
result+= field->def_length; result+= field->def_length;
} }
for (; cur_row; cur_row=cur_row->next) if (thd->protocol == &thd->protocol_binary)
{ {
MYSQL_ROW col= cur_row->data; result+= (uint) (4*n_rows);
MYSQL_ROW col_end= col + data->fields; for (; cur_row; cur_row=cur_row->next)
for (; col < col_end; col++) result+= cur_row->length;
if (*col) }
result+= *(uint *)((*col) - sizeof(uint)); else
{
result+= (uint) (4*n_rows*data->fields);
for (; cur_row; cur_row=cur_row->next)
{
MYSQL_ROW col= cur_row->data;
MYSQL_ROW col_end= col + data->fields;
for (; col < col_end; col++)
if (*col)
result+= *(uint *)((*col) - sizeof(uint));
}
} }
return result; return result;
} }
...@@ -353,10 +363,10 @@ void emb_store_querycache_result(Querycache_stream *dst, THD *thd) ...@@ -353,10 +363,10 @@ void emb_store_querycache_result(Querycache_stream *dst, THD *thd)
{ {
dst->store_int((uint)field->length); dst->store_int((uint)field->length);
dst->store_int((uint)field->max_length); dst->store_int((uint)field->max_length);
dst->store_char((char)field->type); dst->store_uchar((uchar)field->type);
dst->store_short((ushort)field->flags); dst->store_short((ushort)field->flags);
dst->store_short((ushort)field->charsetnr); dst->store_short((ushort)field->charsetnr);
dst->store_char((char)field->decimals); dst->store_uchar((uchar)field->decimals);
dst->store_str(field->name, field->name_length); dst->store_str(field->name, field->name_length);
dst->store_str(field->table, field->table_length); dst->store_str(field->table, field->table_length);
dst->store_str(field->org_name, field->org_name_length); dst->store_str(field->org_name, field->org_name_length);
...@@ -366,14 +376,22 @@ void emb_store_querycache_result(Querycache_stream *dst, THD *thd) ...@@ -366,14 +376,22 @@ void emb_store_querycache_result(Querycache_stream *dst, THD *thd)
dst->store_safe_str(field->def, field->def_length); dst->store_safe_str(field->def, field->def_length);
} }
for (; cur_row; cur_row=cur_row->next) if (thd->protocol == &thd->protocol_binary)
{ {
MYSQL_ROW col= cur_row->data; for (; cur_row; cur_row=cur_row->next)
MYSQL_ROW col_end= col + data->fields; dst->store_str((char *) cur_row->data, cur_row->length);
for (; col < col_end; col++) }
else
{
for (; cur_row; cur_row=cur_row->next)
{ {
uint len= *col ? *(uint *)((*col) - sizeof(uint)) : 0; MYSQL_ROW col= cur_row->data;
dst->store_safe_str(*col, len); MYSQL_ROW col_end= col + data->fields;
for (; col < col_end; col++)
{
uint len= *col ? *(uint *)((*col) - sizeof(uint)) : 0;
dst->store_safe_str(*col, len);
}
} }
} }
DBUG_ASSERT(emb_count_querycache_size(thd) == dst->stored_size); DBUG_ASSERT(emb_count_querycache_size(thd) == dst->stored_size);
...@@ -408,10 +426,10 @@ int emb_load_querycache_result(THD *thd, Querycache_stream *src) ...@@ -408,10 +426,10 @@ int emb_load_querycache_result(THD *thd, Querycache_stream *src)
{ {
field->length= src->load_int(); field->length= src->load_int();
field->max_length= (unsigned int)src->load_int(); field->max_length= (unsigned int)src->load_int();
field->type= (enum enum_field_types)src->load_char(); field->type= (enum enum_field_types)src->load_uchar();
field->flags= (unsigned int)src->load_short(); field->flags= (unsigned int)src->load_short();
field->charsetnr= (unsigned int)src->load_short(); field->charsetnr= (unsigned int)src->load_short();
field->decimals= (unsigned int)src->load_char(); field->decimals= src->load_uchar();
if (!(field->name= src->load_str(f_alloc, &field->name_length)) || if (!(field->name= src->load_str(f_alloc, &field->name_length)) ||
!(field->table= src->load_str(f_alloc,&field->table_length)) || !(field->table= src->load_str(f_alloc,&field->table_length)) ||
...@@ -423,26 +441,43 @@ int emb_load_querycache_result(THD *thd, Querycache_stream *src) ...@@ -423,26 +441,43 @@ int emb_load_querycache_result(THD *thd, Querycache_stream *src)
goto err; goto err;
} }
row= (MYSQL_ROWS *)alloc_root(&data->alloc,
(uint) (rows * sizeof(MYSQL_ROWS) +
rows*(data->fields+1)*sizeof(char*)));
end_row= row + rows;
columns= (MYSQL_ROW)end_row;
data->rows= rows; data->rows= rows;
data->data= row;
if (!rows) if (!rows)
goto return_ok; goto return_ok;
if (thd->protocol == &thd->protocol_binary)
{
uint length;
row= (MYSQL_ROWS *)alloc_root(&data->alloc, rows * sizeof(MYSQL_ROWS));
end_row= row + rows;
data->data= row;
for (prev_row= &row->next; row < end_row; prev_row= &row->next, row++) for (prev_row= &row->next; row < end_row; prev_row= &row->next, row++)
{
*prev_row= row;
row->data= (MYSQL_ROW) src->load_str(&data->alloc, &length);
row->length= length;
}
}
else
{ {
*prev_row= row; row= (MYSQL_ROWS *)alloc_root(&data->alloc,
row->data= columns; (uint) (rows * sizeof(MYSQL_ROWS) +
MYSQL_ROW col_end= columns + data->fields; rows*(data->fields+1)*sizeof(char*)));
for (; columns < col_end; columns++) end_row= row + rows;
src->load_column(&data->alloc, columns); columns= (MYSQL_ROW)end_row;
*(columns++)= NULL; data->data= row;
for (prev_row= &row->next; row < end_row; prev_row= &row->next, row++)
{
*prev_row= row;
row->data= columns;
MYSQL_ROW col_end= columns + data->fields;
for (; columns < col_end; columns++)
src->load_column(&data->alloc, columns);
*(columns++)= NULL;
}
} }
*prev_row= NULL; *prev_row= NULL;
data->embedded_info->prev_ptr= prev_row; data->embedded_info->prev_ptr= prev_row;
......
...@@ -58,7 +58,7 @@ class Querycache_stream ...@@ -58,7 +58,7 @@ class Querycache_stream
data_end= cur_data + (block->used-headers_len); data_end= cur_data + (block->used-headers_len);
} }
void store_char(char c); void store_uchar(uchar c);
void store_short(ushort s); void store_short(ushort s);
void store_int(uint i); void store_int(uint i);
void store_ll(ulonglong ll); void store_ll(ulonglong ll);
...@@ -66,7 +66,7 @@ class Querycache_stream ...@@ -66,7 +66,7 @@ class Querycache_stream
void store_str(const char *str, uint str_len); void store_str(const char *str, uint str_len);
void store_safe_str(const char *str, uint str_len); void store_safe_str(const char *str, uint str_len);
char load_char(); uchar load_uchar();
ushort load_short(); ushort load_short();
uint load_int(); uint load_int();
ulonglong load_ll(); ulonglong load_ll();
......
DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t1, t2;
select format(1.5555,0),format(123.5555,1),format(1234.5555,2),format(12345.55555,3),format(123456.5555,4),format(1234567.5555,5),format("12345.2399",2); select format(1.5555,0),format(123.5555,1),format(1234.5555,2),format(12345.55555,3),format(123456.5555,4),format(1234567.5555,5),format("12345.2399",2);
format(1.5555,0) format(123.5555,1) format(1234.5555,2) format(12345.55555,3) format(123456.5555,4) format(1234567.5555,5) format("12345.2399",2) format(1.5555,0) format(123.5555,1) format(1234.5555,2) format(12345.55555,3) format(123456.5555,4) format(1234567.5555,5) format("12345.2399",2)
2 123.6 1,234.56 12,345.556 123,456.5555 1,234,567.55550 12,345.24 2 123.6 1,234.56 12,345.556 123,456.5555 1,234,567.55550 12,345.24
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# #
--disable_warnings --disable_warnings
DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t1, t2;
--enable_warnings --enable_warnings
select format(1.5555,0),format(123.5555,1),format(1234.5555,2),format(12345.55555,3),format(123456.5555,4),format(1234567.5555,5),format("12345.2399",2); select format(1.5555,0),format(123.5555,1),format(1234.5555,2),format(12345.55555,3),format(123456.5555,4),format(1234567.5555,5),format("12345.2399",2);
......
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