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
19 #include "emb_qcache.h"
20 #include "embedded_priv.h"
22 void Querycache_stream::store_uchar(uchar c
)
24 if (data_end
== cur_data
)
32 void Querycache_stream::store_short(ushort s
)
37 if (data_end
- cur_data
> 1)
39 int2store(cur_data
, s
);
43 if (data_end
== cur_data
)
46 int2store(cur_data
, s
);
50 *cur_data
= ((uchar
*)(&s
))[0];
52 *(cur_data
++)= ((uchar
*)(&s
))[1];
55 void Querycache_stream::store_int(uint i
)
60 size_t rest_len
= data_end
- cur_data
;
63 int4store(cur_data
, i
);
70 int4store(cur_data
, i
);
76 memcpy(cur_data
, buf
, rest_len
);
78 memcpy(cur_data
, buf
+rest_len
, 4-rest_len
);
79 cur_data
+= 4-rest_len
;
82 void Querycache_stream::store_ll(ulonglong ll
)
87 size_t rest_len
= data_end
- cur_data
;
90 int8store(cur_data
, ll
);
97 int8store(cur_data
, ll
);
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
)
110 stored_size
+= str_len
;
114 size_t rest_len
= data_end
- cur_data
;
115 if (rest_len
>= str_len
)
117 memcpy(cur_data
, str
, str_len
);
121 memcpy(cur_data
, str
, rest_len
);
122 use_next_block(TRUE
);
128 void Querycache_stream::store_str(const char *str
, uint str_len
)
131 store_str_only(str
, str_len
);
134 void Querycache_stream::store_safe_str(const char *str
, uint str_len
)
138 store_int(str_len
+1);
139 store_str_only(str
, str_len
);
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()
155 if (data_end
-cur_data
> 1)
157 result
= uint2korr(cur_data
);
161 if (data_end
== cur_data
)
163 use_next_block(FALSE
);
164 result
= uint2korr(cur_data
);
168 ((uchar
*)&result
)[0]= *cur_data
;
169 use_next_block(FALSE
);
170 ((uchar
*)&result
)[1]= *(cur_data
++);
174 uint
Querycache_stream::load_int()
177 size_t rest_len
= data_end
- cur_data
;
180 result
= uint4korr(cur_data
);
186 use_next_block(FALSE
);
187 result
= uint4korr(cur_data
);
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
);
200 ulonglong
Querycache_stream::load_ll()
203 size_t rest_len
= data_end
- cur_data
;
206 result
= uint8korr(cur_data
);
212 use_next_block(FALSE
);
213 result
= uint8korr(cur_data
);
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
;
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
);
236 memcpy(buffer
, cur_data
, rest_len
);
237 use_next_block(FALSE
);
244 char *Querycache_stream::load_str(MEM_ROOT
*alloc
, uint
*str_len
)
247 *str_len
= load_int();
248 if (!(result
= (char*) alloc_root(alloc
, *str_len
+ 1)))
250 load_str_only(result
, *str_len
);
254 int Querycache_stream::load_safe_str(MEM_ROOT
*alloc
, char **str
, uint
*str_len
)
256 if (!(*str_len
= load_int()))
262 if (!(*str
= (char*) alloc_root(alloc
, *str_len
+ 1)))
264 load_str_only(*str
, *str_len
);
268 int Querycache_stream::load_column(MEM_ROOT
*alloc
, char** column
)
271 if (!(len
= load_int()))
277 if (!(*column
= (char *)alloc_root(alloc
, len
+ sizeof(uint
) + 1)))
279 *((uint
*)*column
)= len
;
280 (*column
)+= sizeof(uint
);
281 load_str_only(*column
, len
);
285 uint
emb_count_querycache_size(THD
*thd
)
289 MYSQL_FIELD
*field_end
;
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
;
301 *data
->embedded_info
->prev_ptr
= NULL
; // this marks the last record
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
;
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
;
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
++)
331 result
+= *(uint
*)((*col
) - sizeof(uint
));
337 void emb_store_querycache_result(Querycache_stream
*dst
, THD
*thd
)
340 MYSQL_FIELD
*field_end
;
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
;
355 *data
->embedded_info
->prev_ptr
= NULL
; // this marks the last record
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
);
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
);
401 int emb_load_querycache_result(THD
*thd
, Querycache_stream
*src
)
403 MYSQL_DATA
*data
= thd
->alloc_new_dataset();
405 MYSQL_FIELD
*field_end
;
407 MYSQL_ROWS
*row
, *end_row
;
408 MYSQL_ROWS
**prev_row
;
411 DBUG_ENTER("emb_load_querycache_result");
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
))))
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
))
447 if (thd
->protocol
== &thd
->protocol_binary
)
450 row
= (MYSQL_ROWS
*)alloc_root(&data
->alloc
,
451 (size_t) (rows
* sizeof(MYSQL_ROWS
)));
455 for (prev_row
= &row
->next
; row
< end_row
; prev_row
= &row
->next
, row
++)
458 row
->data
= (MYSQL_ROW
) src
->load_str(&data
->alloc
, &length
);
464 row
= (MYSQL_ROWS
*)alloc_root(&data
->alloc
,
465 (uint
) (rows
* sizeof(MYSQL_ROWS
) +
466 rows
*(data
->fields
+1)*sizeof(char*)));
468 columns
= (MYSQL_ROW
)end_row
;
472 for (prev_row
= &row
->next
; row
< end_row
; prev_row
= &row
->next
, row
++)
476 MYSQL_ROW col_end
= columns
+ data
->fields
;
477 for (; columns
< col_end
; columns
++)
478 src
->load_column(&data
->alloc
, columns
);
484 data
->embedded_info
->prev_ptr
= prev_row
;
486 net_send_eof(thd
, thd
->server_status
, thd
->total_warn_count
);
492 #endif /*HAVE_QUERY_CACHE*/