emb_qcache.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:10k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000-2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #include "mysql_priv.h"
  14. #ifdef HAVE_QUERY_CACHE
  15. #include <mysql.h>
  16. #include "emb_qcache.h"
  17. void Querycache_stream::store_char(char c)
  18. {
  19.   if (data_end == cur_data)
  20.     use_next_block(TRUE);
  21.   *(cur_data++)= c;
  22. #ifndef DBUG_OFF
  23.   stored_size++;
  24. #endif
  25. }
  26. void Querycache_stream::store_short(ushort s)
  27. {
  28. #ifndef DBUG_OFF
  29.   stored_size+= 2;
  30. #endif
  31.   if (data_end - cur_data > 1)
  32.   {
  33.     int2store(cur_data, s);
  34.     cur_data+= 2;
  35.     return;
  36.   }
  37.   if (data_end == cur_data)
  38.   {
  39.     use_next_block(TRUE);
  40.     int2store(cur_data, s);
  41.     cur_data+= 2;
  42.     return;
  43.   }
  44.   *cur_data= ((byte *)(&s))[0];
  45.   use_next_block(TRUE);
  46.   *(cur_data++)= ((byte *)(&s))[1];
  47. }
  48. void Querycache_stream::store_int(uint i)
  49. {
  50. #ifndef DBUG_OFF
  51.   stored_size+= 4;
  52. #endif
  53.   size_t rest_len= data_end - cur_data;
  54.   if (rest_len > 3)
  55.   {
  56.     int4store(cur_data, i);
  57.     cur_data+= 4;
  58.     return;
  59.   }
  60.   if (!rest_len)
  61.   {
  62.     use_next_block(TRUE);
  63.     int4store(cur_data, i);
  64.     cur_data+= 4;
  65.     return;
  66.   }
  67.   char buf[4];
  68.   int4store(buf, i);
  69.   memcpy(cur_data, buf, rest_len);
  70.   use_next_block(TRUE);
  71.   memcpy(cur_data, buf+rest_len, 4-rest_len);
  72.   cur_data+= 4-rest_len;
  73. }
  74. void Querycache_stream::store_ll(ulonglong ll)
  75. {
  76. #ifndef DBUG_OFF
  77.   stored_size+= 8;
  78. #endif
  79.   size_t rest_len= data_end - cur_data;
  80.   if (rest_len > 7)
  81.   {
  82.     int8store(cur_data, ll);
  83.     cur_data+= 8;
  84.     return;
  85.   }
  86.   if (!rest_len)
  87.   {
  88.     use_next_block(TRUE);
  89.     int8store(cur_data, ll);
  90.     cur_data+= 8;
  91.     return;
  92.   }
  93.   memcpy(cur_data, &ll, rest_len);
  94.   use_next_block(TRUE);
  95.   memcpy(cur_data, ((byte*)&ll)+rest_len, 8-rest_len);
  96.   cur_data+= 8-rest_len;
  97. }
  98. void Querycache_stream::store_str_only(const char *str, uint str_len)
  99. {
  100. #ifndef DBUG_OFF
  101.   stored_size+= str_len;
  102. #endif
  103.   do
  104.   {
  105.     size_t rest_len= data_end - cur_data;
  106.     if (rest_len >= str_len)
  107.     {
  108.       memcpy(cur_data, str, str_len);
  109.       cur_data+= str_len;
  110.       return;
  111.     }
  112.     memcpy(cur_data, str, rest_len);
  113.     use_next_block(TRUE);
  114.     str_len-= rest_len;
  115.     str+= rest_len;
  116.   } while(str_len);
  117. }
  118. void Querycache_stream::store_str(const char *str, uint str_len)
  119. {
  120.   store_int(str_len);
  121.   store_str_only(str, str_len);
  122. }
  123. void Querycache_stream::store_safe_str(const char *str, uint str_len)
  124. {
  125.   if (str)
  126.   {
  127.     store_int(str_len+1);
  128.     store_str_only(str, str_len);
  129.   }
  130.   else
  131.     store_int(0);
  132. }
  133. char Querycache_stream::load_char()
  134. {
  135.   if (cur_data == data_end)
  136.     use_next_block(FALSE);
  137.   return *(cur_data++);
  138. }
  139. ushort Querycache_stream::load_short()
  140. {
  141.   ushort result;
  142.   if (data_end-cur_data > 1)
  143.   {
  144.     result= uint2korr(cur_data);
  145.     cur_data+= 2;
  146.     return result;
  147.   }
  148.   if (data_end == cur_data)
  149.   {
  150.     use_next_block(FALSE);
  151.     result= uint2korr(cur_data);
  152.     cur_data+= 2;
  153.     return result;
  154.   }
  155.   ((byte*)&result)[0]= *cur_data;
  156.   use_next_block(FALSE);
  157.   ((byte*)&result)[1]= *(cur_data++);
  158.   return result;
  159. }
  160. uint Querycache_stream::load_int()
  161. {
  162.   int result;
  163.   size_t rest_len= data_end - cur_data;
  164.   if (rest_len > 3)
  165.   {
  166.     result= uint4korr(cur_data);
  167.     cur_data+= 4;
  168.     return result;
  169.   }
  170.   if (!rest_len)
  171.   {
  172.     use_next_block(FALSE);
  173.     result= uint4korr(cur_data);
  174.     cur_data+= 4;
  175.     return result;
  176.   }
  177.   char buf[4];
  178.   memcpy(buf, cur_data, rest_len);
  179.   use_next_block(FALSE);
  180.   memcpy(buf+rest_len, cur_data, 4-rest_len);
  181.   cur_data+= 4-rest_len;
  182.   result= uint4korr(buf);
  183.   return result;
  184. }
  185. ulonglong Querycache_stream::load_ll()
  186. {
  187.   ulonglong result;
  188.   size_t rest_len= data_end - cur_data;
  189.   if (rest_len > 7)
  190.   {
  191.     result= uint8korr(cur_data);
  192.     cur_data+= 8;
  193.     return result;
  194.   }
  195.   if (!rest_len)
  196.   {
  197.     use_next_block(FALSE);
  198.     result= uint8korr(cur_data);
  199.     cur_data+= 8;
  200.     return result;
  201.   }
  202.   memcpy(&result, cur_data, rest_len);
  203.   use_next_block(FALSE);
  204.   memcpy(((byte*)&result)+rest_len, cur_data, 8-rest_len);
  205.   cur_data+= 8-rest_len;
  206.   return result;
  207. }
  208. void Querycache_stream::load_str_only(char *buffer, uint str_len)
  209. {
  210.   do
  211.   {
  212.     size_t rest_len= data_end - cur_data;
  213.     if (rest_len >= str_len)
  214.     {
  215.       memcpy(buffer, cur_data, str_len);
  216.       cur_data+= str_len;
  217.       buffer+= str_len;
  218.       break;
  219.     }
  220.     memcpy(buffer, cur_data, rest_len);
  221.     use_next_block(FALSE);
  222.     str_len-= rest_len;
  223.     buffer+= rest_len;
  224.   } while(str_len);
  225.   *buffer= 0;
  226. }
  227. char *Querycache_stream::load_str(MEM_ROOT *alloc, uint *str_len)
  228. {
  229.   char *result;
  230.   *str_len= load_int();
  231.   if (!(result= alloc_root(alloc, *str_len + 1)))
  232.     return 0;
  233.   load_str_only(result, *str_len);
  234.   return result;
  235. }
  236. int Querycache_stream::load_safe_str(MEM_ROOT *alloc, char **str, uint *str_len)
  237. {
  238.   if (!(*str_len= load_int()))
  239.   {
  240.     *str= NULL;
  241.     return 0;
  242.   }
  243.   (*str_len)--;
  244.   if (!(*str= alloc_root(alloc, *str_len + 1)))
  245.     return 1;
  246.   load_str_only(*str, *str_len);
  247.   return 0;
  248. }
  249. int Querycache_stream::load_column(MEM_ROOT *alloc, char** column)
  250. {
  251.   int len;
  252.   if (!(len = load_int()))
  253.   {
  254.     *column= NULL;
  255.     return 0;
  256.   }
  257.   len--;
  258.   if (!(*column= (char *)alloc_root(alloc, len + sizeof(uint) + 1)))
  259.     return 1;
  260.   *((uint*)*column)= len;
  261.   (*column)+= sizeof(uint);
  262.   load_str_only(*column, len);
  263.   return 1;
  264. }
  265. uint emb_count_querycache_size(THD *thd)
  266. {
  267.   uint result;
  268.   MYSQL *mysql= thd->mysql;
  269.   MYSQL_FIELD *field= mysql->fields;
  270.   MYSQL_FIELD *field_end= field + mysql->field_count;
  271.   MYSQL_ROWS *cur_row=NULL;
  272.   my_ulonglong n_rows=0;
  273.   
  274.   if (!field)
  275.     return 0;
  276.   if (thd->data)
  277.   {
  278.     *thd->data->prev_ptr= NULL; // this marks the last record
  279.     cur_row= thd->data->data;
  280.     n_rows= thd->data->rows;
  281.   }
  282.   result= (uint) (4+8 + (42 + 4*n_rows)*mysql->field_count);
  283.   for(; field < field_end; field++)
  284.   {
  285.     result+= field->name_length + field->table_length +
  286.       field->org_name_length + field->org_table_length + field->db_length +
  287.       field->catalog_length;
  288.     if (field->def)
  289.       result+= field->def_length;
  290.   }
  291.   
  292.   for (; cur_row; cur_row=cur_row->next)
  293.   {
  294.     MYSQL_ROW col= cur_row->data;
  295.     MYSQL_ROW col_end= col + mysql->field_count;
  296.     for (; col < col_end; col++)
  297.       if (*col)
  298. result+= *(uint *)((*col) - sizeof(uint));
  299.   }
  300.   return result;
  301. }
  302. void emb_store_querycache_result(Querycache_stream *dst, THD *thd)
  303. {
  304.   MYSQL *mysql= thd->mysql;
  305.   MYSQL_FIELD *field= mysql->fields;
  306.   MYSQL_FIELD *field_end= field + mysql->field_count;
  307.   MYSQL_ROWS *cur_row= NULL;
  308.   my_ulonglong n_rows= 0;
  309.   if (!field)
  310.     return;
  311.   if (thd->data)
  312.   {
  313.     *thd->data->prev_ptr= NULL; // this marks the last record
  314.     cur_row= thd->data->data;
  315.     n_rows= thd->data->rows;
  316.   }
  317.   dst->store_int((uint)mysql->field_count);
  318.   dst->store_ll((uint)n_rows);
  319.   for(; field < field_end; field++)
  320.   {
  321.     dst->store_int((uint)field->length);
  322.     dst->store_int((uint)field->max_length);
  323.     dst->store_char((char)field->type);
  324.     dst->store_short((ushort)field->flags);
  325.     dst->store_short((ushort)field->charsetnr);
  326.     dst->store_char((char)field->decimals);
  327.     dst->store_str(field->name, field->name_length);
  328.     dst->store_str(field->table, field->table_length);
  329.     dst->store_str(field->org_name, field->org_name_length);
  330.     dst->store_str(field->org_table, field->org_table_length);
  331.     dst->store_str(field->db, field->db_length);
  332.     dst->store_str(field->catalog, field->catalog_length);
  333.     dst->store_safe_str(field->def, field->def_length);
  334.   }
  335.   
  336.   for (; cur_row; cur_row=cur_row->next)
  337.   {
  338.     MYSQL_ROW col= cur_row->data;
  339.     MYSQL_ROW col_end= col + mysql->field_count;
  340.     for (; col < col_end; col++)
  341.     {
  342.       uint len= *col ? *(uint *)((*col) - sizeof(uint)) : 0;
  343.       dst->store_safe_str(*col, len);
  344.     }
  345.   }
  346.   DBUG_ASSERT(emb_count_querycache_size(thd) == dst->stored_size);
  347. }
  348. int emb_load_querycache_result(THD *thd, Querycache_stream *src)
  349. {
  350.   MYSQL *mysql= thd->mysql;
  351.   MYSQL_DATA *data;
  352.   MYSQL_FIELD *field;
  353.   MYSQL_FIELD *field_end;
  354.   MEM_ROOT *f_alloc= &mysql->field_alloc;
  355.   MYSQL_ROWS *row, *end_row;
  356.   MYSQL_ROWS **prev_row;
  357.   ulonglong rows;
  358.   MYSQL_ROW columns;
  359.   mysql->field_count= src->load_int();
  360.   rows= src->load_ll();
  361.   if (!(field= (MYSQL_FIELD *)
  362. alloc_root(&mysql->field_alloc,mysql->field_count*sizeof(MYSQL_FIELD))))
  363.     goto err;
  364.   mysql->fields= field;
  365.   for(field_end= field+mysql->field_count; field < field_end; field++)
  366.   {
  367.     field->length= src->load_int();
  368.     field->max_length= (unsigned int)src->load_int();
  369.     field->type= (enum enum_field_types)src->load_char();
  370.     field->flags= (unsigned int)src->load_short();
  371.     field->charsetnr= (unsigned int)src->load_short();
  372.     field->decimals= (unsigned int)src->load_char();
  373.     if (!(field->name= src->load_str(f_alloc, &field->name_length))          ||
  374. !(field->table= src->load_str(f_alloc,&field->table_length))         ||
  375. !(field->org_name= src->load_str(f_alloc, &field->org_name_length))  ||
  376. !(field->org_table= src->load_str(f_alloc, &field->org_table_length))||
  377. !(field->db= src->load_str(f_alloc, &field->db_length))              ||
  378. !(field->catalog= src->load_str(f_alloc, &field->catalog_length))    ||
  379. src->load_safe_str(f_alloc, &field->def, &field->def_length))
  380.       goto err;
  381.   }
  382.   
  383.   if (!rows)
  384.     return 0;
  385.   if (!(data= (MYSQL_DATA*)my_malloc(sizeof(MYSQL_DATA), 
  386.      MYF(MY_WME | MY_ZEROFILL))))
  387.     goto err;
  388.   thd->data= data;
  389.   init_alloc_root(&data->alloc, 8192,0);
  390.   row= (MYSQL_ROWS *)alloc_root(&data->alloc, (uint) (rows * sizeof(MYSQL_ROWS) +
  391. rows * (mysql->field_count+1)*sizeof(char*)));
  392.   end_row= row + rows;
  393.   columns= (MYSQL_ROW)end_row;
  394.   
  395.   data->rows= rows;
  396.   data->fields= mysql->field_count;
  397.   data->data= row;
  398.   for (prev_row= &row->next; row < end_row; prev_row= &row->next, row++)
  399.   {
  400.     *prev_row= row;
  401.     row->data= columns;
  402.     MYSQL_ROW col_end= columns + mysql->field_count;
  403.     for (; columns < col_end; columns++)
  404.       src->load_column(&data->alloc, columns);
  405.     *(columns++)= NULL;
  406.   }
  407.   *prev_row= NULL;
  408.   data->prev_ptr= prev_row;
  409.   return 0;
  410. err:
  411.   return 1;
  412. }
  413. #endif /*HAVE_QUERY_CACHE*/