mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / libmysqld / emb_qcache.cc
blobc224c7742c844750e48642db4f3c72b5e79cd8a5
1 /* Copyright (c) 2000-2008 MySQL AB
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16 #include "mysql_priv.h"
17 #ifdef HAVE_QUERY_CACHE
18 #include <mysql.h>
19 #include "emb_qcache.h"
20 #include "embedded_priv.h"
22 void Querycache_stream::store_uchar(uchar c)
24 if (data_end == cur_data)
25 use_next_block(TRUE);
26 *(cur_data++)= c;
27 #ifndef DBUG_OFF
28 stored_size++;
29 #endif
32 void Querycache_stream::store_short(ushort s)
34 #ifndef DBUG_OFF
35 stored_size+= 2;
36 #endif
37 if (data_end - cur_data > 1)
39 int2store(cur_data, s);
40 cur_data+= 2;
41 return;
43 if (data_end == cur_data)
45 use_next_block(TRUE);
46 int2store(cur_data, s);
47 cur_data+= 2;
48 return;
50 *cur_data= ((uchar *)(&s))[0];
51 use_next_block(TRUE);
52 *(cur_data++)= ((uchar *)(&s))[1];
55 void Querycache_stream::store_int(uint i)
57 #ifndef DBUG_OFF
58 stored_size+= 4;
59 #endif
60 size_t rest_len= data_end - cur_data;
61 if (rest_len > 3)
63 int4store(cur_data, i);
64 cur_data+= 4;
65 return;
67 if (!rest_len)
69 use_next_block(TRUE);
70 int4store(cur_data, i);
71 cur_data+= 4;
72 return;
74 char buf[4];
75 int4store(buf, i);
76 memcpy(cur_data, buf, rest_len);
77 use_next_block(TRUE);
78 memcpy(cur_data, buf+rest_len, 4-rest_len);
79 cur_data+= 4-rest_len;
82 void Querycache_stream::store_ll(ulonglong ll)
84 #ifndef DBUG_OFF
85 stored_size+= 8;
86 #endif
87 size_t rest_len= data_end - cur_data;
88 if (rest_len > 7)
90 int8store(cur_data, ll);
91 cur_data+= 8;
92 return;
94 if (!rest_len)
96 use_next_block(TRUE);
97 int8store(cur_data, ll);
98 cur_data+= 8;
99 return;
101 memcpy(cur_data, &ll, rest_len);
102 use_next_block(TRUE);
103 memcpy(cur_data, ((uchar*)&ll)+rest_len, 8-rest_len);
104 cur_data+= 8-rest_len;
107 void Querycache_stream::store_str_only(const char *str, uint str_len)
109 #ifndef DBUG_OFF
110 stored_size+= str_len;
111 #endif
114 size_t rest_len= data_end - cur_data;
115 if (rest_len >= str_len)
117 memcpy(cur_data, str, str_len);
118 cur_data+= str_len;
119 return;
121 memcpy(cur_data, str, rest_len);
122 use_next_block(TRUE);
123 str_len-= rest_len;
124 str+= rest_len;
125 } while(str_len);
128 void Querycache_stream::store_str(const char *str, uint str_len)
130 store_int(str_len);
131 store_str_only(str, str_len);
134 void Querycache_stream::store_safe_str(const char *str, uint str_len)
136 if (str)
138 store_int(str_len+1);
139 store_str_only(str, str_len);
141 else
142 store_int(0);
145 uchar Querycache_stream::load_uchar()
147 if (cur_data == data_end)
148 use_next_block(FALSE);
149 return *(cur_data++);
152 ushort Querycache_stream::load_short()
154 ushort result;
155 if (data_end-cur_data > 1)
157 result= uint2korr(cur_data);
158 cur_data+= 2;
159 return result;
161 if (data_end == cur_data)
163 use_next_block(FALSE);
164 result= uint2korr(cur_data);
165 cur_data+= 2;
166 return result;
168 ((uchar*)&result)[0]= *cur_data;
169 use_next_block(FALSE);
170 ((uchar*)&result)[1]= *(cur_data++);
171 return result;
174 uint Querycache_stream::load_int()
176 int result;
177 size_t rest_len= data_end - cur_data;
178 if (rest_len > 3)
180 result= uint4korr(cur_data);
181 cur_data+= 4;
182 return result;
184 if (!rest_len)
186 use_next_block(FALSE);
187 result= uint4korr(cur_data);
188 cur_data+= 4;
189 return result;
191 char buf[4];
192 memcpy(buf, cur_data, rest_len);
193 use_next_block(FALSE);
194 memcpy(buf+rest_len, cur_data, 4-rest_len);
195 cur_data+= 4-rest_len;
196 result= uint4korr(buf);
197 return result;
200 ulonglong Querycache_stream::load_ll()
202 ulonglong result;
203 size_t rest_len= data_end - cur_data;
204 if (rest_len > 7)
206 result= uint8korr(cur_data);
207 cur_data+= 8;
208 return result;
210 if (!rest_len)
212 use_next_block(FALSE);
213 result= uint8korr(cur_data);
214 cur_data+= 8;
215 return result;
217 memcpy(&result, cur_data, rest_len);
218 use_next_block(FALSE);
219 memcpy(((uchar*)&result)+rest_len, cur_data, 8-rest_len);
220 cur_data+= 8-rest_len;
221 return result;
224 void Querycache_stream::load_str_only(char *buffer, uint str_len)
228 size_t rest_len= data_end - cur_data;
229 if (rest_len >= str_len)
231 memcpy(buffer, cur_data, str_len);
232 cur_data+= str_len;
233 buffer+= str_len;
234 break;
236 memcpy(buffer, cur_data, rest_len);
237 use_next_block(FALSE);
238 str_len-= rest_len;
239 buffer+= rest_len;
240 } while(str_len);
241 *buffer= 0;
244 char *Querycache_stream::load_str(MEM_ROOT *alloc, uint *str_len)
246 char *result;
247 *str_len= load_int();
248 if (!(result= (char*) alloc_root(alloc, *str_len + 1)))
249 return 0;
250 load_str_only(result, *str_len);
251 return result;
254 int Querycache_stream::load_safe_str(MEM_ROOT *alloc, char **str, uint *str_len)
256 if (!(*str_len= load_int()))
258 *str= NULL;
259 return 0;
261 (*str_len)--;
262 if (!(*str= (char*) alloc_root(alloc, *str_len + 1)))
263 return 1;
264 load_str_only(*str, *str_len);
265 return 0;
268 int Querycache_stream::load_column(MEM_ROOT *alloc, char** column)
270 int len;
271 if (!(len = load_int()))
273 *column= NULL;
274 return 0;
276 len--;
277 if (!(*column= (char *)alloc_root(alloc, len + sizeof(uint) + 1)))
278 return 1;
279 *((uint*)*column)= len;
280 (*column)+= sizeof(uint);
281 load_str_only(*column, len);
282 return 1;
285 uint emb_count_querycache_size(THD *thd)
287 uint result= 0;
288 MYSQL_FIELD *field;
289 MYSQL_FIELD *field_end;
290 MYSQL_ROWS *cur_row;
291 my_ulonglong n_rows;
292 MYSQL_DATA *data= thd->first_data;
294 while (data->embedded_info->next)
295 data= data->embedded_info->next;
296 field= data->embedded_info->fields_list;
297 field_end= field + data->fields;
299 if (!field)
300 return result;
301 *data->embedded_info->prev_ptr= NULL; // this marks the last record
302 cur_row= data->data;
303 n_rows= data->rows;
304 /* n_fields + n_rows + field_info * n_fields */
305 result+= (uint) (4+8 + 42*data->fields);
307 for(; field < field_end; field++)
309 result+= field->name_length + field->table_length +
310 field->org_name_length + field->org_table_length + field->db_length +
311 field->catalog_length;
312 if (field->def)
313 result+= field->def_length;
316 if (thd->protocol == &thd->protocol_binary)
318 result+= (uint) (4*n_rows);
319 for (; cur_row; cur_row=cur_row->next)
320 result+= cur_row->length;
322 else
324 result+= (uint) (4*n_rows*data->fields);
325 for (; cur_row; cur_row=cur_row->next)
327 MYSQL_ROW col= cur_row->data;
328 MYSQL_ROW col_end= col + data->fields;
329 for (; col < col_end; col++)
330 if (*col)
331 result+= *(uint *)((*col) - sizeof(uint));
334 return result;
337 void emb_store_querycache_result(Querycache_stream *dst, THD *thd)
339 MYSQL_FIELD *field;
340 MYSQL_FIELD *field_end;
341 MYSQL_ROWS *cur_row;
342 my_ulonglong n_rows;
343 MYSQL_DATA *data= thd->first_data;
345 DBUG_ENTER("emb_store_querycache_result");
347 while (data->embedded_info->next)
348 data= data->embedded_info->next;
349 field= data->embedded_info->fields_list;
350 field_end= field + data->fields;
352 if (!field)
353 DBUG_VOID_RETURN;
355 *data->embedded_info->prev_ptr= NULL; // this marks the last record
356 cur_row= data->data;
357 n_rows= data->rows;
359 dst->store_int((uint)data->fields);
360 dst->store_ll((ulonglong)n_rows);
362 for(; field < field_end; field++)
364 dst->store_int((uint)field->length);
365 dst->store_int((uint)field->max_length);
366 dst->store_uchar((uchar)field->type);
367 dst->store_short((ushort)field->flags);
368 dst->store_short((ushort)field->charsetnr);
369 dst->store_uchar((uchar)field->decimals);
370 dst->store_str(field->name, field->name_length);
371 dst->store_str(field->table, field->table_length);
372 dst->store_str(field->org_name, field->org_name_length);
373 dst->store_str(field->org_table, field->org_table_length);
374 dst->store_str(field->db, field->db_length);
375 dst->store_str(field->catalog, field->catalog_length);
376 dst->store_safe_str(field->def, field->def_length);
379 if (thd->protocol == &thd->protocol_binary)
381 for (; cur_row; cur_row=cur_row->next)
382 dst->store_str((char *) cur_row->data, cur_row->length);
384 else
386 for (; cur_row; cur_row=cur_row->next)
388 MYSQL_ROW col= cur_row->data;
389 MYSQL_ROW col_end= col + data->fields;
390 for (; col < col_end; col++)
392 uint len= *col ? *(uint *)((*col) - sizeof(uint)) : 0;
393 dst->store_safe_str(*col, len);
397 DBUG_ASSERT(emb_count_querycache_size(thd) == dst->stored_size);
398 DBUG_VOID_RETURN;
401 int emb_load_querycache_result(THD *thd, Querycache_stream *src)
403 MYSQL_DATA *data= thd->alloc_new_dataset();
404 MYSQL_FIELD *field;
405 MYSQL_FIELD *field_end;
406 MEM_ROOT *f_alloc;
407 MYSQL_ROWS *row, *end_row;
408 MYSQL_ROWS **prev_row;
409 ulonglong rows;
410 MYSQL_ROW columns;
411 DBUG_ENTER("emb_load_querycache_result");
413 if (!data)
414 goto err;
415 init_alloc_root(&data->alloc, 8192,0);
416 f_alloc= &data->alloc;
418 data->fields= src->load_int();
419 rows= src->load_ll();
421 if (!(field= (MYSQL_FIELD *)
422 alloc_root(f_alloc,data->fields*sizeof(MYSQL_FIELD))))
423 goto err;
424 data->embedded_info->fields_list= field;
425 for(field_end= field+data->fields; field < field_end; field++)
427 field->length= src->load_int();
428 field->max_length= (unsigned int)src->load_int();
429 field->type= (enum enum_field_types)src->load_uchar();
430 field->flags= (unsigned int)src->load_short();
431 field->charsetnr= (unsigned int)src->load_short();
432 field->decimals= src->load_uchar();
434 if (!(field->name= src->load_str(f_alloc, &field->name_length)) ||
435 !(field->table= src->load_str(f_alloc,&field->table_length)) ||
436 !(field->org_name= src->load_str(f_alloc, &field->org_name_length)) ||
437 !(field->org_table= src->load_str(f_alloc, &field->org_table_length))||
438 !(field->db= src->load_str(f_alloc, &field->db_length)) ||
439 !(field->catalog= src->load_str(f_alloc, &field->catalog_length)) ||
440 src->load_safe_str(f_alloc, &field->def, &field->def_length))
441 goto err;
444 data->rows= rows;
445 if (!rows)
446 goto return_ok;
447 if (thd->protocol == &thd->protocol_binary)
449 uint length;
450 row= (MYSQL_ROWS *)alloc_root(&data->alloc,
451 (size_t) (rows * sizeof(MYSQL_ROWS)));
452 end_row= row + rows;
453 data->data= row;
455 for (prev_row= &row->next; row < end_row; prev_row= &row->next, row++)
457 *prev_row= row;
458 row->data= (MYSQL_ROW) src->load_str(&data->alloc, &length);
459 row->length= length;
462 else
464 row= (MYSQL_ROWS *)alloc_root(&data->alloc,
465 (uint) (rows * sizeof(MYSQL_ROWS) +
466 rows*(data->fields+1)*sizeof(char*)));
467 end_row= row + rows;
468 columns= (MYSQL_ROW)end_row;
470 data->data= row;
472 for (prev_row= &row->next; row < end_row; prev_row= &row->next, row++)
474 *prev_row= row;
475 row->data= columns;
476 MYSQL_ROW col_end= columns + data->fields;
477 for (; columns < col_end; columns++)
478 src->load_column(&data->alloc, columns);
480 *(columns++)= NULL;
483 *prev_row= NULL;
484 data->embedded_info->prev_ptr= prev_row;
485 return_ok:
486 net_send_eof(thd, thd->server_status, thd->total_warn_count);
487 DBUG_RETURN(0);
488 err:
489 DBUG_RETURN(1);
492 #endif /*HAVE_QUERY_CACHE*/