mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 04:22:27 +01:00
0afb6ff660
(Needed for "list of pushes" web page and autopush) include/mysql.h: Fix to embedded server to be able to run tests on it libmysql/libmysql.c: Fix to embedded server to be able to run tests on it libmysqld/emb_qcache.cc: Fix to embedded server to be able to run tests on it libmysqld/embedded_priv.h: Fix to embedded server to be able to run tests on it libmysqld/lib_sql.cc: Fix to embedded server to be able to run tests on it libmysqld/libmysqld.c: Fix to embedded server to be able to run tests on it mysql-test/mysql-test-run.sh: Fix to embedded server to be able to run tests on it mysql-test/r/binlog.result: Updated test for embedded server mysql-test/r/ctype_cp932.result: Updated test for embedded server mysql-test/r/innodb.result: Updated test for embedded server mysql-test/r/mysqltest.result: Updated test for embedded server mysql-test/r/query_cache.result: Updated test for embedded server mysql-test/r/query_cache_notembedded.result: Updated test for embedded server mysql-test/r/sp-error.result: Updated test for embedded server mysql-test/r/sp.result: Updated test for embedded server mysql-test/r/subselect.result: Updated test for embedded server mysql-test/r/view.result: Updated test for embedded server mysql-test/r/view_grant.result: Updated test for embedded server mysql-test/t/backup.test: Updated test for embedded server mysql-test/t/binlog.test: Updated test for embedded server mysql-test/t/blackhole.test: Updated test for embedded server mysql-test/t/compress.test: Updated test for embedded server mysql-test/t/ctype_cp932.test: Updated test for embedded server mysql-test/t/delayed.test: Updated test for embedded server mysql-test/t/handler.test: Updated test for embedded server mysql-test/t/innodb.test: Updated test for embedded server mysql-test/t/mysql.test: Updated test for embedded server mysql-test/t/mysql_client_test.test: Updated test for embedded server mysql-test/t/mysqltest.test: Updated test for embedded server mysql-test/t/query_cache.test: Updated test for embedded server mysql-test/t/query_cache_notembedded.test: Updated test for embedded server mysql-test/t/read_only.test: Updated test for embedded server mysql-test/t/skip_grants.test: Updated test for embedded server mysql-test/t/sp-destruct.test: Updated test for embedded server mysql-test/t/sp-error.test: Updated test for embedded server mysql-test/t/sp-threads.test: Updated test for embedded server mysql-test/t/sp.test: Updated test for embedded server mysql-test/t/subselect.test: Updated test for embedded server mysql-test/t/temp_table.test: Updated test for embedded server mysql-test/t/view.test: Updated test for embedded server mysql-test/t/view_grant.test: Updated test for embedded server mysql-test/t/wait_timeout.test: Updated test for embedded server mysys/mf_dirname.c: Review fix: Don't access data outside of array mysys/my_bitmap.c: Remove compiler warnings scripts/mysql_fix_privilege_tables.sql: Add flush privileges to .sql script so that one doesn't have to reboot mysqld when one runs the mysql_fix_privilege_script sql-common/client.c: Updated test for embedded server sql/item.cc: Remove DBUG_PRINT statement that can cause crashes when running with --debug sql/mysqld.cc: Fix to embedded server to be able to run tests on it sql/protocol.cc: Fix to embedded server to be able to run tests on it (Trivial reconstruction of code) sql/protocol.h: Fix to embedded server to be able to run tests on it sql/sql_base.cc: Better comment sql/sql_class.cc: Fix to embedded server to be able to run tests on it sql/sql_class.h: Fix to embedded server to be able to run tests on it sql/sql_cursor.cc: Fix to embedded server to be able to run tests on it sql/sql_parse.cc: Fix to embedded server to be able to run tests on it Don't crash for disabled commands when using embedded server sql/sql_prepare.cc: Fix to embedded server to be able to run tests on it mysql-test/r/ctype_cp932_notembedded.result: New BitKeeper file ``mysql-test/r/ctype_cp932_notembedded.result'' mysql-test/r/innodb_notembedded.result: New BitKeeper file ``mysql-test/r/innodb_notembedded.result'' mysql-test/r/sp.result.orig: New BitKeeper file ``mysql-test/r/sp.result.orig'' mysql-test/r/sp_notembedded.result: New BitKeeper file ``mysql-test/r/sp_notembedded.result'' mysql-test/r/subselect_notembedded.result: New BitKeeper file ``mysql-test/r/subselect_notembedded.result'' mysql-test/t/ctype_cp932_notembedded.test: New BitKeeper file ``mysql-test/t/ctype_cp932_notembedded.test'' mysql-test/t/innodb_notembedded.test: New BitKeeper file ``mysql-test/t/innodb_notembedded.test'' mysql-test/t/sp.test.orig: New BitKeeper file ``mysql-test/t/sp.test.orig'' mysql-test/t/sp_notembedded.test: New BitKeeper file ``mysql-test/t/sp_notembedded.test'' mysql-test/t/subselect_notembedded.test: New BitKeeper file ``mysql-test/t/subselect_notembedded.test''
458 lines
11 KiB
C++
458 lines
11 KiB
C++
/* Copyright (C) 2000-2003 MySQL AB
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
|
|
#include "mysql_priv.h"
|
|
#ifdef HAVE_QUERY_CACHE
|
|
#include <mysql.h>
|
|
#include "emb_qcache.h"
|
|
#include "embedded_priv.h"
|
|
|
|
void Querycache_stream::store_char(char c)
|
|
{
|
|
if (data_end == cur_data)
|
|
use_next_block(TRUE);
|
|
*(cur_data++)= c;
|
|
#ifndef DBUG_OFF
|
|
stored_size++;
|
|
#endif
|
|
}
|
|
|
|
void Querycache_stream::store_short(ushort s)
|
|
{
|
|
#ifndef DBUG_OFF
|
|
stored_size+= 2;
|
|
#endif
|
|
if (data_end - cur_data > 1)
|
|
{
|
|
int2store(cur_data, s);
|
|
cur_data+= 2;
|
|
return;
|
|
}
|
|
if (data_end == cur_data)
|
|
{
|
|
use_next_block(TRUE);
|
|
int2store(cur_data, s);
|
|
cur_data+= 2;
|
|
return;
|
|
}
|
|
*cur_data= ((byte *)(&s))[0];
|
|
use_next_block(TRUE);
|
|
*(cur_data++)= ((byte *)(&s))[1];
|
|
}
|
|
|
|
void Querycache_stream::store_int(uint i)
|
|
{
|
|
#ifndef DBUG_OFF
|
|
stored_size+= 4;
|
|
#endif
|
|
size_t rest_len= data_end - cur_data;
|
|
if (rest_len > 3)
|
|
{
|
|
int4store(cur_data, i);
|
|
cur_data+= 4;
|
|
return;
|
|
}
|
|
if (!rest_len)
|
|
{
|
|
use_next_block(TRUE);
|
|
int4store(cur_data, i);
|
|
cur_data+= 4;
|
|
return;
|
|
}
|
|
char buf[4];
|
|
int4store(buf, i);
|
|
memcpy(cur_data, buf, rest_len);
|
|
use_next_block(TRUE);
|
|
memcpy(cur_data, buf+rest_len, 4-rest_len);
|
|
cur_data+= 4-rest_len;
|
|
}
|
|
|
|
void Querycache_stream::store_ll(ulonglong ll)
|
|
{
|
|
#ifndef DBUG_OFF
|
|
stored_size+= 8;
|
|
#endif
|
|
size_t rest_len= data_end - cur_data;
|
|
if (rest_len > 7)
|
|
{
|
|
int8store(cur_data, ll);
|
|
cur_data+= 8;
|
|
return;
|
|
}
|
|
if (!rest_len)
|
|
{
|
|
use_next_block(TRUE);
|
|
int8store(cur_data, ll);
|
|
cur_data+= 8;
|
|
return;
|
|
}
|
|
memcpy(cur_data, &ll, rest_len);
|
|
use_next_block(TRUE);
|
|
memcpy(cur_data, ((byte*)&ll)+rest_len, 8-rest_len);
|
|
cur_data+= 8-rest_len;
|
|
}
|
|
|
|
void Querycache_stream::store_str_only(const char *str, uint str_len)
|
|
{
|
|
#ifndef DBUG_OFF
|
|
stored_size+= str_len;
|
|
#endif
|
|
do
|
|
{
|
|
size_t rest_len= data_end - cur_data;
|
|
if (rest_len >= str_len)
|
|
{
|
|
memcpy(cur_data, str, str_len);
|
|
cur_data+= str_len;
|
|
return;
|
|
}
|
|
memcpy(cur_data, str, rest_len);
|
|
use_next_block(TRUE);
|
|
str_len-= rest_len;
|
|
str+= rest_len;
|
|
} while(str_len);
|
|
}
|
|
|
|
void Querycache_stream::store_str(const char *str, uint str_len)
|
|
{
|
|
store_int(str_len);
|
|
store_str_only(str, str_len);
|
|
}
|
|
|
|
void Querycache_stream::store_safe_str(const char *str, uint str_len)
|
|
{
|
|
if (str)
|
|
{
|
|
store_int(str_len+1);
|
|
store_str_only(str, str_len);
|
|
}
|
|
else
|
|
store_int(0);
|
|
}
|
|
|
|
char Querycache_stream::load_char()
|
|
{
|
|
if (cur_data == data_end)
|
|
use_next_block(FALSE);
|
|
return *(cur_data++);
|
|
}
|
|
|
|
ushort Querycache_stream::load_short()
|
|
{
|
|
ushort result;
|
|
if (data_end-cur_data > 1)
|
|
{
|
|
result= uint2korr(cur_data);
|
|
cur_data+= 2;
|
|
return result;
|
|
}
|
|
if (data_end == cur_data)
|
|
{
|
|
use_next_block(FALSE);
|
|
result= uint2korr(cur_data);
|
|
cur_data+= 2;
|
|
return result;
|
|
}
|
|
((byte*)&result)[0]= *cur_data;
|
|
use_next_block(FALSE);
|
|
((byte*)&result)[1]= *(cur_data++);
|
|
return result;
|
|
}
|
|
|
|
uint Querycache_stream::load_int()
|
|
{
|
|
int result;
|
|
size_t rest_len= data_end - cur_data;
|
|
if (rest_len > 3)
|
|
{
|
|
result= uint4korr(cur_data);
|
|
cur_data+= 4;
|
|
return result;
|
|
}
|
|
if (!rest_len)
|
|
{
|
|
use_next_block(FALSE);
|
|
result= uint4korr(cur_data);
|
|
cur_data+= 4;
|
|
return result;
|
|
}
|
|
char buf[4];
|
|
memcpy(buf, cur_data, rest_len);
|
|
use_next_block(FALSE);
|
|
memcpy(buf+rest_len, cur_data, 4-rest_len);
|
|
cur_data+= 4-rest_len;
|
|
result= uint4korr(buf);
|
|
return result;
|
|
}
|
|
|
|
ulonglong Querycache_stream::load_ll()
|
|
{
|
|
ulonglong result;
|
|
size_t rest_len= data_end - cur_data;
|
|
if (rest_len > 7)
|
|
{
|
|
result= uint8korr(cur_data);
|
|
cur_data+= 8;
|
|
return result;
|
|
}
|
|
if (!rest_len)
|
|
{
|
|
use_next_block(FALSE);
|
|
result= uint8korr(cur_data);
|
|
cur_data+= 8;
|
|
return result;
|
|
}
|
|
memcpy(&result, cur_data, rest_len);
|
|
use_next_block(FALSE);
|
|
memcpy(((byte*)&result)+rest_len, cur_data, 8-rest_len);
|
|
cur_data+= 8-rest_len;
|
|
return result;
|
|
}
|
|
|
|
void Querycache_stream::load_str_only(char *buffer, uint str_len)
|
|
{
|
|
do
|
|
{
|
|
size_t rest_len= data_end - cur_data;
|
|
if (rest_len >= str_len)
|
|
{
|
|
memcpy(buffer, cur_data, str_len);
|
|
cur_data+= str_len;
|
|
buffer+= str_len;
|
|
break;
|
|
}
|
|
memcpy(buffer, cur_data, rest_len);
|
|
use_next_block(FALSE);
|
|
str_len-= rest_len;
|
|
buffer+= rest_len;
|
|
} while(str_len);
|
|
*buffer= 0;
|
|
}
|
|
|
|
char *Querycache_stream::load_str(MEM_ROOT *alloc, uint *str_len)
|
|
{
|
|
char *result;
|
|
*str_len= load_int();
|
|
if (!(result= alloc_root(alloc, *str_len + 1)))
|
|
return 0;
|
|
load_str_only(result, *str_len);
|
|
return result;
|
|
}
|
|
|
|
int Querycache_stream::load_safe_str(MEM_ROOT *alloc, char **str, uint *str_len)
|
|
{
|
|
if (!(*str_len= load_int()))
|
|
{
|
|
*str= NULL;
|
|
return 0;
|
|
}
|
|
(*str_len)--;
|
|
if (!(*str= alloc_root(alloc, *str_len + 1)))
|
|
return 1;
|
|
load_str_only(*str, *str_len);
|
|
return 0;
|
|
}
|
|
|
|
int Querycache_stream::load_column(MEM_ROOT *alloc, char** column)
|
|
{
|
|
int len;
|
|
if (!(len = load_int()))
|
|
{
|
|
*column= NULL;
|
|
return 0;
|
|
}
|
|
len--;
|
|
if (!(*column= (char *)alloc_root(alloc, len + sizeof(uint) + 1)))
|
|
return 1;
|
|
*((uint*)*column)= len;
|
|
(*column)+= sizeof(uint);
|
|
load_str_only(*column, len);
|
|
return 1;
|
|
}
|
|
|
|
uint emb_count_querycache_size(THD *thd)
|
|
{
|
|
uint result= 0;
|
|
MYSQL_FIELD *field;
|
|
MYSQL_FIELD *field_end;
|
|
MYSQL_ROWS *cur_row;
|
|
my_ulonglong n_rows;
|
|
MYSQL_DATA *data= thd->first_data;
|
|
|
|
while (data->embedded_info->next)
|
|
data= data->embedded_info->next;
|
|
field= data->embedded_info->fields_list;
|
|
field_end= field + data->fields;
|
|
|
|
if (!field)
|
|
return result;
|
|
*data->embedded_info->prev_ptr= NULL; // this marks the last record
|
|
cur_row= data->data;
|
|
n_rows= data->rows;
|
|
/* n_fields + n_rows + (field_info + strlen * n_rows) * n_fields */
|
|
result+= (uint) (4+8 + (42 + 4*n_rows)*data->fields);
|
|
|
|
for(; field < field_end; field++)
|
|
{
|
|
result+= field->name_length + field->table_length +
|
|
field->org_name_length + field->org_table_length + field->db_length +
|
|
field->catalog_length;
|
|
if (field->def)
|
|
result+= field->def_length;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
void emb_store_querycache_result(Querycache_stream *dst, THD *thd)
|
|
{
|
|
MYSQL_FIELD *field;
|
|
MYSQL_FIELD *field_end;
|
|
MYSQL_ROWS *cur_row;
|
|
my_ulonglong n_rows;
|
|
MYSQL_DATA *data= thd->first_data;
|
|
|
|
DBUG_ENTER("emb_store_querycache_result");
|
|
|
|
while (data->embedded_info->next)
|
|
data= data->embedded_info->next;
|
|
field= data->embedded_info->fields_list;
|
|
field_end= field + data->fields;
|
|
|
|
if (!field)
|
|
DBUG_VOID_RETURN;
|
|
|
|
*data->embedded_info->prev_ptr= NULL; // this marks the last record
|
|
cur_row= data->data;
|
|
n_rows= data->rows;
|
|
|
|
dst->store_int((uint)data->fields);
|
|
dst->store_ll((ulonglong)n_rows);
|
|
|
|
for(; field < field_end; field++)
|
|
{
|
|
dst->store_int((uint)field->length);
|
|
dst->store_int((uint)field->max_length);
|
|
dst->store_char((char)field->type);
|
|
dst->store_short((ushort)field->flags);
|
|
dst->store_short((ushort)field->charsetnr);
|
|
dst->store_char((char)field->decimals);
|
|
dst->store_str(field->name, field->name_length);
|
|
dst->store_str(field->table, field->table_length);
|
|
dst->store_str(field->org_name, field->org_name_length);
|
|
dst->store_str(field->org_table, field->org_table_length);
|
|
dst->store_str(field->db, field->db_length);
|
|
dst->store_str(field->catalog, field->catalog_length);
|
|
dst->store_safe_str(field->def, field->def_length);
|
|
}
|
|
|
|
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++)
|
|
{
|
|
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_VOID_RETURN;
|
|
}
|
|
|
|
int emb_load_querycache_result(THD *thd, Querycache_stream *src)
|
|
{
|
|
MYSQL_DATA *data= thd->alloc_new_dataset();
|
|
MYSQL_FIELD *field;
|
|
MYSQL_FIELD *field_end;
|
|
MEM_ROOT *f_alloc;
|
|
MYSQL_ROWS *row, *end_row;
|
|
MYSQL_ROWS **prev_row;
|
|
ulonglong rows;
|
|
MYSQL_ROW columns;
|
|
DBUG_ENTER("emb_load_querycache_result");
|
|
|
|
if (!data)
|
|
goto err;
|
|
init_alloc_root(&data->alloc, 8192,0);
|
|
f_alloc= &data->alloc;
|
|
|
|
data->fields= src->load_int();
|
|
rows= src->load_ll();
|
|
|
|
if (!(field= (MYSQL_FIELD *)
|
|
alloc_root(f_alloc,data->fields*sizeof(MYSQL_FIELD))))
|
|
goto err;
|
|
data->embedded_info->fields_list= field;
|
|
for(field_end= field+data->fields; field < field_end; field++)
|
|
{
|
|
field->length= src->load_int();
|
|
field->max_length= (unsigned int)src->load_int();
|
|
field->type= (enum enum_field_types)src->load_char();
|
|
field->flags= (unsigned int)src->load_short();
|
|
field->charsetnr= (unsigned int)src->load_short();
|
|
field->decimals= (unsigned int)src->load_char();
|
|
|
|
if (!(field->name= src->load_str(f_alloc, &field->name_length)) ||
|
|
!(field->table= src->load_str(f_alloc,&field->table_length)) ||
|
|
!(field->org_name= src->load_str(f_alloc, &field->org_name_length)) ||
|
|
!(field->org_table= src->load_str(f_alloc, &field->org_table_length))||
|
|
!(field->db= src->load_str(f_alloc, &field->db_length)) ||
|
|
!(field->catalog= src->load_str(f_alloc, &field->catalog_length)) ||
|
|
src->load_safe_str(f_alloc, &field->def, &field->def_length))
|
|
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->data= row;
|
|
if (!rows)
|
|
goto return_ok;
|
|
|
|
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;
|
|
data->embedded_info->prev_ptr= prev_row;
|
|
return_ok:
|
|
send_eof(thd);
|
|
DBUG_RETURN(0);
|
|
err:
|
|
DBUG_RETURN(1);
|
|
}
|
|
|
|
#endif /*HAVE_QUERY_CACHE*/
|
|
|