diff options
author | unknown <hf@deer.(none)> | 2003-12-01 17:19:10 +0400 |
---|---|---|
committer | unknown <hf@deer.(none)> | 2003-12-01 17:19:10 +0400 |
commit | 5d90d9406eb23052916482d4b4f76631a507cfe9 (patch) | |
tree | 126aa9404b20610fed02f1d2fb10aac967ed5334 /libmysqld | |
parent | 046b80bbeb074aeea3158c8108d93e6e6215d2e2 (diff) | |
download | mariadb-git-5d90d9406eb23052916482d4b4f76631a507cfe9.tar.gz |
SCRUM
WL#1246 (Query cache in embedded library)
libmysqld/Makefile.am:
New files added to the project
libmysqld/lib_sql.cc:
added initialization of 'newborn' fields:
catalog, catalog_length, def_length
sql/sql_cache.cc:
Code added to provide query-cache in embedded library
query_cache_insert isn't called during the query execution
in embedded library. So we call it in query_cache_end_of_result.
Parameter of query_cache_end_of_result changed to get access to
the recordset
sql/sql_cache.h:
function's parameter changed
sql/sql_parse.cc:
we don't need these anymore
Diffstat (limited to 'libmysqld')
-rw-r--r-- | libmysqld/Makefile.am | 4 | ||||
-rw-r--r-- | libmysqld/emb_qcache.cc | 430 | ||||
-rw-r--r-- | libmysqld/emb_qcache.h | 61 | ||||
-rw-r--r-- | libmysqld/lib_sql.cc | 9 |
4 files changed, 502 insertions, 2 deletions
diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index 95cbd4ec826..e51fb5e315e 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -33,10 +33,10 @@ INCLUDES= @MT_INCLUDES@ @bdb_includes@ -I$(top_srcdir)/include \ noinst_LIBRARIES = libmysqld_int.a pkglib_LIBRARIES = libmysqld.a SUBDIRS = . examples -libmysqld_sources= libmysqld.c lib_sql.cc +libmysqld_sources= libmysqld.c lib_sql.cc emb_qcache.cc libmysqlsources = errmsg.c get_password.c libmysql.c client.c pack.c -noinst_HEADERS = embedded_priv.h +noinst_HEADERS = embedded_priv.h emb_qcache.h sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \ ha_innodb.cc ha_berkeley.cc ha_heap.cc ha_isam.cc ha_isammrg.cc \ diff --git a/libmysqld/emb_qcache.cc b/libmysqld/emb_qcache.cc new file mode 100644 index 00000000000..0374ab58784 --- /dev/null +++ b/libmysqld/emb_qcache.cc @@ -0,0 +1,430 @@ +/* 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" + +void Querycache_stream::store_char(char c) +{ + if (data_end == cur_data) + use_next_block(); + *(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(); + int2store(cur_data, s); + cur_data+= 2; + return; + } + *cur_data= ((byte *)(&s))[0]; + use_next_block(); + *(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(); + int4store(cur_data, i); + cur_data+= 4; + return; + } + memcpy(cur_data, &i, rest_len); + use_next_block(); + memcpy(cur_data, ((byte*)&i)+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(); + int8store(cur_data, ll); + cur_data+= 8; + return; + } + memcpy(cur_data, &ll, rest_len); + use_next_block(); + 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(); + 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(); + 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(); + result= uint2korr(cur_data); + cur_data+= 2; + return result; + } + ((byte*)&result)[0]= *cur_data; + use_next_block(); + ((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(); + result= uint4korr(cur_data); + cur_data+= 4; + return result; + } + memcpy(&result, cur_data, rest_len); + use_next_block(); + memcpy(((byte*)&result)+rest_len, cur_data, 4-rest_len); + cur_data+= 4-rest_len; + 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(); + result= uint8korr(cur_data); + cur_data+= 8; + return result; + } + memcpy(&result, cur_data, rest_len); + use_next_block(); + 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(); + 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 + 4 + 1))) + return 1; + int4store(*column, len); + (*column)+= 4; + load_str_only(*column, len); + return 1; +} + +uint emb_count_querycache_size(THD *thd) +{ + uint result; + MYSQL *mysql= thd->mysql; + MYSQL_FIELD *field= mysql->fields; + MYSQL_FIELD *field_end= field + mysql->field_count; + + *thd->data->prev_ptr= NULL; // this marks the last record + MYSQL_ROWS *cur_row= thd->data->data; + + result= 4+8 + (42 + 4*thd->data->rows)*mysql->field_count; + + 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 + mysql->field_count; + 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 *mysql= thd->mysql; + MYSQL_FIELD *field= mysql->fields; + MYSQL_FIELD *field_end= field + mysql->field_count; + + *thd->data->prev_ptr= NULL; // this marks the last record + MYSQL_ROWS *cur_row= thd->data->data; + + dst->store_int((uint)mysql->field_count); + dst->store_ll((uint)thd->data->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 + mysql->field_count; + 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); +} + +int emb_load_querycache_result(THD *thd, Querycache_stream *src) +{ + MYSQL *mysql= thd->mysql; + MYSQL_DATA *data; + MYSQL_FIELD *field; + MYSQL_FIELD *field_end; + MEM_ROOT *f_alloc= &mysql->field_alloc; + MYSQL_ROWS *row, *end_row; + MYSQL_ROWS **prev_row; + ulonglong rows; + MYSQL_ROW columns; + + mysql->field_count= src->load_int(); + rows= src->load_ll(); + + if (!(field= (MYSQL_FIELD *) + alloc_root(&mysql->field_alloc,mysql->field_count*sizeof(MYSQL_FIELD)))) + goto err; + mysql->fields= field; + for(field_end= field+mysql->field_count; 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; + } + + if (!rows) + return 0; + if (!(data= (MYSQL_DATA*)my_malloc(sizeof(MYSQL_DATA), + MYF(MY_WME | MY_ZEROFILL)))) + goto err; + thd->data= data; + init_alloc_root(&data->alloc, 8192,0); + row= (MYSQL_ROWS *)alloc_root(&data->alloc, rows * sizeof(MYSQL_ROWS) + + rows * (mysql->field_count+1)*sizeof(char*)); + end_row= row + rows; + columns= (MYSQL_ROW)end_row; + + data->rows= rows; + data->fields= mysql->field_count; + 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 + mysql->field_count; + uint len; + for (; columns < col_end; columns++) + src->load_column(&data->alloc, columns); + + *(columns++)= NULL; + } + *prev_row= NULL; + data->prev_ptr= prev_row; + + return 0; +err: + return 1; +} + +#endif /*HAVE_QUERY_CACHE*/ + diff --git a/libmysqld/emb_qcache.h b/libmysqld/emb_qcache.h new file mode 100644 index 00000000000..32ce19847ff --- /dev/null +++ b/libmysqld/emb_qcache.h @@ -0,0 +1,61 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +class Querycache_stream +{ + byte *cur_data; + byte *data_end; + Query_cache_block *block; + uint headers_len; +public: +#ifndef DBUG_OFF + uint stored_size; +#endif + Querycache_stream(Query_cache_block *ini_block, uint ini_headers_len) : + block(ini_block), headers_len(ini_headers_len) + { + use_next_block(); +#ifndef DBUG_OFF + stored_size= 0; +#endif + } + void use_next_block() + { + cur_data= ((byte*)block)+headers_len; + data_end= cur_data + (block->used-headers_len); + } + + void store_char(char c); + void store_short(ushort s); + void store_int(uint i); + void store_ll(ulonglong ll); + void store_str_only(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); + + char load_char(); + ushort load_short(); + uint load_int(); + ulonglong load_ll(); + void load_str_only(char *buffer, uint str_len); + char *load_str(MEM_ROOT *alloc, uint *str_len); + int load_safe_str(MEM_ROOT *alloc, char **str, uint *str_len); + int load_column(MEM_ROOT *alloc, char **column); +}; + +uint emb_count_querycache_size(THD *thd); +int emb_load_querycache_result(THD *thd, Querycache_stream *src); +void emb_store_querycache_result(Querycache_stream *dst, THD* thd); diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index d4cb916a89c..4e003b1d450 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -573,6 +573,9 @@ bool Protocol::send_fields(List<Item> *list, uint flag) client_field->org_name_length= strlen(client_field->org_name); client_field->org_table_length= strlen(client_field->org_table); client_field->charsetnr= server_field.charsetnr; + + client_field->catalog= strdup_root(field_alloc, "std"); + client_field->catalog_length= 3; if (INTERNAL_NUM_FIELD(client_field)) client_field->flags|= NUM_FLAG; @@ -583,9 +586,15 @@ bool Protocol::send_fields(List<Item> *list, uint flag) String tmp(buff, sizeof(buff), default_charset_info), *res; if (!(res=item->val_str(&tmp))) + { client_field->def= strdup_root(field_alloc, ""); + client_field->def_length= 0; + } else + { client_field->def= strdup_root(field_alloc, tmp.ptr()); + client_field->def_length= tmp.length(); + } } else client_field->def=0; |