Drizzled Public API Documentation

blob.cc
1 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3  *
4  * Copyright (C) 2008 MySQL
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 
22 #include <config.h>
23 #include <drizzled/field/blob.h>
24 #include <drizzled/table.h>
25 #include <drizzled/session.h>
26 #include <plugin/myisam/myisam.h>
27 #include <drizzled/system_variables.h>
28 
29 #include <string>
30 #include <algorithm>
31 
32 using namespace std;
33 
34 namespace drizzled {
35 
36 static uint32_t blob_pack_length_to_max_length(uint32_t arg)
37 {
38  return max(UINT32_MAX,
39  (uint32_t)((INT64_C(1) << min(arg, 4U) * 8) - INT64_C(1)));
40 }
41 
42 
43 /****************************************************************************
44 ** blob type
45 ** A blob is saved as a length and a pointer. The length is stored in the
46 ** packlength slot and is sizeof(uint32_t) (4 bytes)
47 ****************************************************************************/
48 
49 Field_blob::Field_blob(unsigned char *ptr_arg,
50  unsigned char *null_ptr_arg,
51  unsigned char null_bit_arg,
52  const char *field_name_arg,
53  TableShare *share,
54  const charset_info_st * const cs)
55  :Field_str(ptr_arg,
56  blob_pack_length_to_max_length(sizeof(uint32_t)),
57  null_ptr_arg,
58  null_bit_arg,
59  field_name_arg,
60  cs)
61 {
62  flags|= BLOB_FLAG;
63  share->blob_fields++;
64  /* TODO: why do not fill table->getShare()->blob_field array here? */
65 }
66 
67 void Field_blob::store_length(unsigned char *i_ptr,
68  uint32_t i_number,
69  bool low_byte_first)
70 {
71 #ifndef WORDS_BIGENDIAN
72  (void)low_byte_first;
73 #endif
74 
75 #ifdef WORDS_BIGENDIAN
76  if (low_byte_first)
77  {
78  int4store(i_ptr,i_number);
79  }
80  else
81 #endif
82  longstore(i_ptr,i_number);
83 }
84 
85 
86 void Field_blob::store_length(unsigned char *i_ptr, uint32_t i_number)
87 {
88  store_length(i_ptr, i_number, getTable()->getShare()->db_low_byte_first);
89 }
90 
91 
92 uint32_t Field_blob::get_length(const unsigned char *pos,
93  bool low_byte_first) const
94 {
95 #ifndef WORDS_BIGENDIAN
96  (void)low_byte_first;
97 #endif
98  uint32_t tmp;
99 #ifdef WORDS_BIGENDIAN
100  if (low_byte_first)
101  tmp=uint4korr(pos);
102  else
103 #endif
104  longget(tmp,pos);
105  return (uint32_t) tmp;
106 }
107 
108 
109 uint32_t Field_blob::get_packed_size(const unsigned char *ptr_arg,
110  bool low_byte_first)
111 {
112  return sizeof(uint32_t) + get_length(ptr_arg, low_byte_first);
113 }
114 
115 
116 uint32_t Field_blob::get_length(uint32_t row_offset) const
117 {
118  return get_length(ptr+row_offset,
119  getTable()->getShare()->db_low_byte_first);
120 }
121 
122 
123 uint32_t Field_blob::get_length(const unsigned char *ptr_arg) const
124 {
125  return get_length(ptr_arg, getTable()->getShare()->db_low_byte_first);
126 }
127 
128 
138 void Field_blob::put_length(unsigned char *pos, uint32_t length)
139 {
140  int4store(pos, length);
141 }
142 
143 
144 int Field_blob::store(const char *from,uint32_t length, const charset_info_st * const cs)
145 {
146  uint32_t copy_length, new_length;
147  const char *well_formed_error_pos;
148  const char *cannot_convert_error_pos;
149  const char *from_end_pos, *tmp;
150  char buff[STRING_BUFFER_USUAL_SIZE];
151  String tmpstr(buff,sizeof(buff), &my_charset_bin);
152 
153  ASSERT_COLUMN_MARKED_FOR_WRITE;
154 
155  if (!length)
156  {
157  memset(ptr, 0, Field_blob::pack_length());
158  return 0;
159  }
160 
161  if (from == value.ptr())
162  {
163  if (!String::needs_conversion(length, cs, field_charset))
164  {
165  Field_blob::store_length(length);
166  memmove(ptr+sizeof(uint32_t), &from, sizeof(char*));
167  return 0;
168  }
169  tmpstr.copy(from, length, cs);
170  from= tmpstr.ptr();
171  }
172 
173  new_length= min(max_data_length(), field_charset->mbmaxlen * length);
174  value.alloc(new_length);
175 
176  /*
177  "length" is OK as "nchars" argument to well_formed_copy_nchars as this
178  is never used to limit the length of the data. The cut of long data
179  is done with the new_length value.
180  */
181  copy_length= well_formed_copy_nchars(field_charset,
182  (char*) value.ptr(), new_length,
183  cs, from, length,
184  length,
185  &well_formed_error_pos,
186  &cannot_convert_error_pos,
187  &from_end_pos);
188 
189  Field_blob::store_length(copy_length);
190  tmp= value.ptr();
191  memmove(ptr+sizeof(uint32_t), &tmp, sizeof(char*));
192 
193  if (check_string_copy_error(this, well_formed_error_pos,
194  cannot_convert_error_pos, from + length, cs))
195  return 2;
196 
197  return report_if_important_data(from_end_pos, from + length);
198 }
199 
200 int Field_blob::store(double nr)
201 {
202  const charset_info_st * const cs=charset();
203  ASSERT_COLUMN_MARKED_FOR_WRITE;
204  value.set_real(nr, NOT_FIXED_DEC, cs);
205  return Field_blob::store(value.ptr(),(uint32_t) value.length(), cs);
206 }
207 
208 int Field_blob::store(int64_t nr, bool unsigned_val)
209 {
210  const charset_info_st * const cs=charset();
211  ASSERT_COLUMN_MARKED_FOR_WRITE;
212  value.set_int(nr, unsigned_val, cs);
213  return Field_blob::store(value.ptr(), (uint32_t) value.length(), cs);
214 }
215 
216 
217 double Field_blob::val_real(void) const
218 {
219  int not_used;
220  char *end_not_used, *blob;
221  uint32_t length;
222  const charset_info_st *cs;
223 
224  ASSERT_COLUMN_MARKED_FOR_READ;
225 
226  memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
227  if (!blob)
228  return 0.0;
229  length= get_length(ptr);
230  cs= charset();
231  return my_strntod(cs, blob, length, &end_not_used, &not_used);
232 }
233 
234 
235 int64_t Field_blob::val_int(void) const
236 {
237  int not_used;
238  char *blob;
239 
240  ASSERT_COLUMN_MARKED_FOR_READ;
241 
242  memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
243  if (!blob)
244  return 0;
245  uint32_t length= get_length(ptr);
246  return my_strntoll(charset(),blob,length,10,NULL,&not_used);
247 }
248 
249 String *Field_blob::val_str(String *, String *val_ptr) const
250 {
251  char *blob;
252 
253  ASSERT_COLUMN_MARKED_FOR_READ;
254 
255  memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
256  if (!blob)
257  val_ptr->set("",0,charset()); // A bit safer than ->length(0)
258  else
259  val_ptr->set(blob,get_length(ptr),charset());
260  return val_ptr;
261 }
262 
263 
264 type::Decimal *Field_blob::val_decimal(type::Decimal *decimal_value) const
265 {
266  const char *blob;
267  size_t length;
268 
269  ASSERT_COLUMN_MARKED_FOR_READ;
270 
271  memcpy(&blob, ptr+sizeof(uint32_t), sizeof(const unsigned char*));
272  if (!blob)
273  {
274  blob= "";
275  length= 0;
276  }
277  else
278  {
279  length= get_length(ptr);
280  }
281 
282  decimal_value->store(E_DEC_FATAL_ERROR, blob, length, charset());
283 
284  return decimal_value;
285 }
286 
287 
288 int Field_blob::cmp(const unsigned char *a,uint32_t a_length, const unsigned char *b,
289  uint32_t b_length)
290 {
291  return field_charset->coll->strnncollsp(field_charset,
292  a, a_length, b, b_length,
293  0);
294 }
295 
296 
297 int Field_blob::cmp_max(const unsigned char *a_ptr, const unsigned char *b_ptr,
298  uint32_t max_length)
299 {
300  unsigned char *blob1,*blob2;
301  memcpy(&blob1,a_ptr+sizeof(uint32_t),sizeof(char*));
302  memcpy(&blob2,b_ptr+sizeof(uint32_t),sizeof(char*));
303  uint32_t a_len= get_length(a_ptr), b_len= get_length(b_ptr);
304  set_if_smaller(a_len, max_length);
305  set_if_smaller(b_len, max_length);
306  return Field_blob::cmp(blob1,a_len,blob2,b_len);
307 }
308 
309 
310 int Field_blob::cmp_binary(const unsigned char *a_ptr, const unsigned char *b_ptr,
311  uint32_t max_length)
312 {
313  char *a,*b;
314  uint32_t diff;
315  uint32_t a_length,b_length;
316  memcpy(&a,a_ptr+sizeof(uint32_t),sizeof(char*));
317  memcpy(&b,b_ptr+sizeof(uint32_t),sizeof(char*));
318 
319  a_length= get_length(a_ptr);
320 
321  if (a_length > max_length)
322  a_length= max_length;
323 
324  b_length= get_length(b_ptr);
325 
326  if (b_length > max_length)
327  b_length= max_length;
328 
329  diff= memcmp(a,b,min(a_length,b_length));
330 
331  return diff ? diff : (unsigned int) (a_length - b_length);
332 }
333 
334 /* The following is used only when comparing a key */
335 uint32_t Field_blob::get_key_image(unsigned char *buff, uint32_t length)
336 {
337  uint32_t blob_length= get_length(ptr);
338  unsigned char *blob= get_ptr();
339  uint32_t local_char_length= length / field_charset->mbmaxlen;
340  local_char_length= my_charpos(field_charset, blob, blob + blob_length,
341  local_char_length);
342  set_if_smaller(blob_length, local_char_length);
343 
344  if ((uint32_t) length > blob_length)
345  {
346  /*
347  Must clear this as we do a memcmp in optimizer/range.cc to detect
348  identical keys
349  */
350  memset(buff+HA_KEY_BLOB_LENGTH+blob_length, 0, (length-blob_length));
351  length=(uint32_t) blob_length;
352  }
353  int2store(buff,length);
354  memcpy(buff+HA_KEY_BLOB_LENGTH, blob, length);
355  return HA_KEY_BLOB_LENGTH+length;
356 }
357 
358 uint32_t Field_blob::get_key_image(basic_string<unsigned char> &buff, uint32_t length)
359 {
360  uint32_t blob_length= get_length(ptr);
361  unsigned char* blob= get_ptr();
362  uint32_t local_char_length= length / field_charset->mbmaxlen;
363  local_char_length= my_charpos(field_charset, blob, blob + blob_length,
364  local_char_length);
365  set_if_smaller(blob_length, local_char_length);
366 
367  unsigned char len_buff[HA_KEY_BLOB_LENGTH];
368  int2store(len_buff,length);
369  buff.append(len_buff);
370  buff.append(blob, blob_length);
371 
372  if (length > blob_length)
373  {
374  /*
375  Must clear this as we do a memcmp in optimizer/range.cc to detect
376  identical keys
377  */
378 
379  buff.append(length-blob_length, '0');
380  }
381  return HA_KEY_BLOB_LENGTH+length;
382 }
383 
384 void Field_blob::set_key_image(const unsigned char *buff,uint32_t length)
385 {
386  length= uint2korr(buff);
387  (void) Field_blob::store((const char*) buff+HA_KEY_BLOB_LENGTH, length, field_charset);
388 }
389 
390 int Field_blob::key_cmp(const unsigned char *key_ptr, uint32_t max_key_length)
391 {
392  unsigned char *blob1;
393  uint32_t blob_length=get_length(ptr);
394  memcpy(&blob1,ptr+sizeof(uint32_t),sizeof(char*));
395  const charset_info_st * const cs= charset();
396  uint32_t local_char_length= max_key_length / cs->mbmaxlen;
397  local_char_length= my_charpos(cs, blob1, blob1+blob_length,
398  local_char_length);
399  set_if_smaller(blob_length, local_char_length);
400  return Field_blob::cmp(blob1, blob_length,
401  key_ptr+HA_KEY_BLOB_LENGTH,
402  uint2korr(key_ptr));
403 }
404 
405 int Field_blob::key_cmp(const unsigned char *a,const unsigned char *b)
406 {
407  return Field_blob::cmp(a+HA_KEY_BLOB_LENGTH, uint2korr(a),
408  b+HA_KEY_BLOB_LENGTH, uint2korr(b));
409 }
410 
411 uint32_t Field_blob::sort_length() const
412 {
413  return (uint32_t) (getTable()->getSession()->variables.max_sort_length +
414  (field_charset == &my_charset_bin ? 0 : sizeof(uint32_t)));
415 }
416 
417 void Field_blob::sort_string(unsigned char *to,uint32_t length)
418 {
419  unsigned char *blob;
420  uint32_t blob_length=get_length();
421 
422  if (!blob_length)
423  memset(to, 0, length);
424  else
425  {
426  if (field_charset == &my_charset_bin)
427  {
428  unsigned char *pos;
429 
430  /*
431  Store length of blob last in blob to shorter blobs before longer blobs
432  */
433  length-= sizeof(uint32_t); // size of stored blob length
434  pos= to+length;
435 
436  mi_int4store(pos, blob_length);
437  }
438  memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
439 
440  blob_length= field_charset->strnxfrm(to, length, blob, blob_length);
441  assert(blob_length == length);
442  }
443 }
444 
445 uint32_t Field_blob::pack_length() const
446 {
447  return (uint32_t) (sizeof(uint32_t) + portable_sizeof_char_ptr);
448 }
449 
450 unsigned char *Field_blob::pack(unsigned char *to, const unsigned char *from,
451  uint32_t max_length, bool low_byte_first)
452 {
453  unsigned char *save= ptr;
454  ptr= (unsigned char*) from;
455  uint32_t length= get_length(); // Length of from string
456 
457  /*
458  Store max length, which will occupy packlength bytes. If the max
459  length given is smaller than the actual length of the blob, we
460  just store the initial bytes of the blob.
461  */
462  store_length(to, min(length, max_length), low_byte_first);
463 
464  /*
465  Store the actual blob data, which will occupy 'length' bytes.
466  */
467  if (length > 0)
468  {
469  from= get_ptr();
470  memcpy(to+sizeof(uint32_t), from,length);
471  }
472 
473  ptr= save; // Restore org row pointer
474  return(to+sizeof(uint32_t)+length);
475 }
476 
494 const unsigned char *Field_blob::unpack(unsigned char *,
495  const unsigned char *from,
496  uint32_t,
497  bool low_byte_first)
498 {
499  uint32_t const length= get_length(from, low_byte_first);
500  getTable()->setWriteSet(position());
501  store(reinterpret_cast<const char*>(from) + sizeof(uint32_t),
502  length, field_charset);
503  return(from + sizeof(uint32_t) + length);
504 }
505 
508 unsigned char *
509 Field_blob::pack_key(unsigned char *to, const unsigned char *from, uint32_t max_length,
510  bool )
511 {
512  unsigned char *save= ptr;
513  ptr= (unsigned char*) from;
514  uint32_t length=get_length(); // Length of from string
515  uint32_t local_char_length= ((field_charset->mbmaxlen > 1) ?
516  max_length/field_charset->mbmaxlen : max_length);
517  if (length)
518  from= get_ptr();
519  if (length > local_char_length)
520  local_char_length= my_charpos(field_charset, from, from+length,
521  local_char_length);
522  set_if_smaller(length, local_char_length);
523  *to++= (unsigned char) length;
524  if (max_length > 255) // 2 byte length
525  *to++= (unsigned char) (length >> 8);
526  memcpy(to, from, length);
527  ptr=save; // Restore org row pointer
528  return to+length;
529 }
530 
531 
540 {
541  return (uint32_t) 4294967295U;
542 }
543 
544 } /* namespace drizzled */
virtual uint32_t max_data_length() const
Definition: blob.h:103
TODO: Rename this file - func.h is stupid.
void put_length(unsigned char *pos, uint32_t length)
Definition: blob.cc:138
virtual const unsigned char * unpack(unsigned char *to, const unsigned char *from, uint32_t, bool low_byte_first)
Definition: blob.cc:494
unsigned char * pack_key(unsigned char *to, const unsigned char *from, uint32_t max_length, bool low_byte_first)
Definition: blob.cc:509
uint32_t get_key_image(unsigned char *buff, uint32_t length)
Definition: blob.cc:335
uint32_t max_display_length()
Definition: blob.cc:539
virtual unsigned char * pack(unsigned char *to, const unsigned char *from, uint32_t max_length, bool low_byte_first)
Definition: blob.cc:450
uint32_t pack_length() const
Definition: blob.cc:445
drizzle_system_variables & variables
Definition: session.h:199
uint32_t get_packed_size(const unsigned char *ptr_arg, bool low_byte_first)
Definition: blob.cc:109
unsigned char * ptr
Definition: field.h:71