summaryrefslogtreecommitdiff
path: root/libmysqld
diff options
context:
space:
mode:
authorunknown <hf@deer.(none)>2003-12-01 17:19:10 +0400
committerunknown <hf@deer.(none)>2003-12-01 17:19:10 +0400
commit5d90d9406eb23052916482d4b4f76631a507cfe9 (patch)
tree126aa9404b20610fed02f1d2fb10aac967ed5334 /libmysqld
parent046b80bbeb074aeea3158c8108d93e6e6215d2e2 (diff)
downloadmariadb-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.am4
-rw-r--r--libmysqld/emb_qcache.cc430
-rw-r--r--libmysqld/emb_qcache.h61
-rw-r--r--libmysqld/lib_sql.cc9
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;