Drizzled Public API Documentation

varstring.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/varstring.h>
24 #include <drizzled/table.h>
25 #include <drizzled/session.h>
26 #include <plugin/myisam/myisam.h>
27 
28 #include <string>
29 
30 using namespace std;
31 
32 namespace drizzled
33 {
34 
35 /****************************************************************************
36  VARCHAR type
37  Data in field->ptr is stored as:
38  1 or 2 bytes length-prefix-header (from Field_varstring::length_bytes)
39  data
40 
41  NOTE:
42  When VARCHAR is stored in a key (for handler::index_read() etc) it's always
43  stored with a 2 byte prefix. (Just like blob keys).
44 
45  Normally length_bytes is calculated as (field_length < 256 : 1 ? 2)
46  The exception is if there is a prefix key field that is part of a long
47  VARCHAR, in which case field_length for this may be 1 but the length_bytes
48  is 2.
49 ****************************************************************************/
50 
51 const uint32_t Field_varstring::MAX_SIZE= UINT16_MAX;
52 
53 Field_varstring::Field_varstring(unsigned char *ptr_arg,
54  uint32_t len_arg,
55  uint32_t length_bytes_arg,
56  unsigned char *null_ptr_arg,
57  unsigned char null_bit_arg,
58  const char *field_name_arg,
59  const charset_info_st * const cs) :
60  Field_str(ptr_arg,
61  len_arg,
62  null_ptr_arg,
63  null_bit_arg,
64  field_name_arg, cs),
65 length_bytes(length_bytes_arg)
66 {
67 }
68 
69 Field_varstring::Field_varstring(uint32_t len_arg,
70  bool maybe_null_arg,
71  const char *field_name_arg,
72  const charset_info_st * const cs) :
73  Field_str((unsigned char*) 0,
74  len_arg,
75  maybe_null_arg ? (unsigned char*) "": 0,
76  0,
77  field_name_arg,
78  cs),
79  length_bytes(len_arg < 256 ? 1 :2)
80 {
81 }
82 
83 int Field_varstring::store(const char *from,uint32_t length, const charset_info_st * const cs)
84 {
85  uint32_t copy_length;
86  const char *well_formed_error_pos;
87  const char *cannot_convert_error_pos;
88  const char *from_end_pos;
89 
90  ASSERT_COLUMN_MARKED_FOR_WRITE;
91 
92  copy_length= well_formed_copy_nchars(field_charset,
93  (char*) ptr + length_bytes,
94  field_length,
95  cs, from, length,
96  field_length / field_charset->mbmaxlen,
97  &well_formed_error_pos,
98  &cannot_convert_error_pos,
99  &from_end_pos);
100 
101  if (length_bytes == 1)
102  *ptr= (unsigned char) copy_length;
103  else
104  int2store(ptr, copy_length);
105 
106  if (check_string_copy_error(this, well_formed_error_pos,
107  cannot_convert_error_pos, from + length, cs))
108  return 2;
109 
110  return report_if_important_data(from_end_pos, from + length);
111 }
112 
113 
114 int Field_varstring::store(int64_t nr, bool unsigned_val)
115 {
116  char buff[64];
117  uint32_t length;
118  length= (uint32_t) (field_charset->cset->int64_t10_to_str)(field_charset,
119  buff,
120  sizeof(buff),
121  (unsigned_val ? 10: -10),
122  nr);
123  return Field_varstring::store(buff, length, field_charset);
124 }
125 
126 
127 double Field_varstring::val_real(void) const
128 {
129  int not_used;
130  char *end_not_used;
131 
132  ASSERT_COLUMN_MARKED_FOR_READ;
133 
134  uint32_t length= length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
135 
136  return my_strntod(field_charset, (char*) ptr+length_bytes, length,
137  &end_not_used, &not_used);
138 }
139 
140 
141 int64_t Field_varstring::val_int(void) const
142 {
143  int not_used;
144  char *end_not_used;
145  uint32_t length;
146 
147  ASSERT_COLUMN_MARKED_FOR_READ;
148 
149  length= length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
150 
151  return my_strntoll(field_charset, (char*) ptr+length_bytes, length, 10,
152  &end_not_used, &not_used);
153 }
154 
155 String *Field_varstring::val_str(String *, String *val_ptr) const
156 {
157  uint32_t length= length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
158 
159  ASSERT_COLUMN_MARKED_FOR_READ;
160 
161  val_ptr->set((const char*) ptr+length_bytes, length, field_charset);
162 
163  return val_ptr;
164 }
165 
166 
167 type::Decimal *Field_varstring::val_decimal(type::Decimal *decimal_value) const
168 {
169  uint32_t length;
170 
171  ASSERT_COLUMN_MARKED_FOR_READ;
172 
173  length= length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
174 
175  decimal_value->store(E_DEC_FATAL_ERROR, (char*) ptr+length_bytes, length, charset());
176 
177  return decimal_value;
178 }
179 
180 
181 int Field_varstring::cmp_max(const unsigned char *a_ptr, const unsigned char *b_ptr,
182  uint32_t max_len)
183 {
184  uint32_t a_length, b_length;
185  int diff;
186 
187  if (length_bytes == 1)
188  {
189  a_length= (uint32_t) *a_ptr;
190  b_length= (uint32_t) *b_ptr;
191  }
192  else
193  {
194  a_length= uint2korr(a_ptr);
195  b_length= uint2korr(b_ptr);
196  }
197  set_if_smaller(a_length, max_len);
198  set_if_smaller(b_length, max_len);
199  diff= field_charset->coll->strnncollsp(field_charset,
200  a_ptr+
201  length_bytes,
202  a_length,
203  b_ptr+
204  length_bytes,
205  b_length,0);
206  return diff;
207 }
208 
209 
215 int Field_varstring::key_cmp(const unsigned char *key_ptr, uint32_t max_key_length)
216 {
217  uint32_t length= length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
218  uint32_t local_char_length= max_key_length / field_charset->mbmaxlen;
219 
220  local_char_length= my_charpos(field_charset, ptr + length_bytes,
221  ptr + length_bytes + length, local_char_length);
222  set_if_smaller(length, local_char_length);
223  return field_charset->coll->strnncollsp(field_charset,
224  ptr + length_bytes,
225  length,
226  key_ptr+
227  HA_KEY_BLOB_LENGTH,
228  uint2korr(key_ptr), 0);
229 }
230 
231 
240 int Field_varstring::key_cmp(const unsigned char *a,const unsigned char *b)
241 {
242  return field_charset->coll->strnncollsp(field_charset,
243  a + HA_KEY_BLOB_LENGTH,
244  uint2korr(a),
245  b + HA_KEY_BLOB_LENGTH,
246  uint2korr(b),
247  0);
248 }
249 
250 
251 void Field_varstring::sort_string(unsigned char *to,uint32_t length)
252 {
253  uint32_t tot_length= length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
254 
255  if (field_charset == &my_charset_bin)
256  {
257  /* Store length last in high-byte order to sort longer strings first */
258  if (length_bytes == 1)
259  to[length-1]= tot_length;
260  else
261  mi_int2store(to+length-2, tot_length);
262  length-= length_bytes;
263  }
264 
265  tot_length= field_charset->strnxfrm(to, length, ptr + length_bytes, tot_length);
266  assert(tot_length == length);
267 }
268 
269 
270 enum ha_base_keytype Field_varstring::key_type() const
271 {
272  enum ha_base_keytype res;
273 
274  if (binary())
275  res= length_bytes == 1 ? HA_KEYTYPE_VARBINARY1 : HA_KEYTYPE_VARBINARY2;
276  else
277  res= length_bytes == 1 ? HA_KEYTYPE_VARTEXT1 : HA_KEYTYPE_VARTEXT2;
278  return res;
279 }
280 
281 
283 {
284  return length_bytes == 1 ? 1 + (uint32_t) (unsigned char) *ptr : 2 + uint2korr(ptr);
285 }
286 
287 /*
288  Functions to create a packed row.
289  Here the number of length bytes are depending on the given max_length
290 */
291 
292 unsigned char *Field_varstring::pack(unsigned char *to, const unsigned char *from,
293  uint32_t max_length,
294  bool )
295 {
296  uint32_t length= length_bytes == 1 ? (uint32_t) *from : uint2korr(from);
297  set_if_smaller(max_length, field_length);
298  if (length > max_length)
299  length=max_length;
300 
301  /* Length always stored little-endian */
302  *to++= length & 0xFF;
303  if (max_length > 255)
304  *to++= (length >> 8) & 0xFF;
305 
306  /* Store bytes of string */
307  if (length > 0)
308  memcpy(to, from+length_bytes, length);
309  return to+length;
310 }
311 
312 
328 const unsigned char *
329 Field_varstring::unpack(unsigned char *to, const unsigned char *from,
330  uint32_t param_data,
331  bool )
332 {
333  uint32_t length;
334  uint32_t l_bytes= (param_data && (param_data < field_length)) ?
335  (param_data <= 255) ? 1 : 2 : length_bytes;
336  if (l_bytes == 1)
337  {
338  to[0]= *from++;
339  length= to[0];
340  if (length_bytes == 2)
341  to[1]= 0;
342  }
343  else /* l_bytes == 2 */
344  {
345  length= uint2korr(from);
346  to[0]= *from++;
347  to[1]= *from++;
348  }
349  if (length)
350  memcpy(to+ length_bytes, from, length);
351  return from+length;
352 }
353 
354 
355 uint32_t Field_varstring::max_packed_col_length(uint32_t max_length)
356 {
357  return (max_length > 255 ? 2 : 1)+max_length;
358 }
359 
360 uint32_t Field_varstring::get_key_image(basic_string<unsigned char> &buff, uint32_t length)
361 {
362  /* Key is always stored with 2 bytes */
363  const uint32_t key_len= 2;
364  uint32_t f_length= length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
365  uint32_t local_char_length= length / field_charset->mbmaxlen;
366  unsigned char *pos= ptr+length_bytes;
367  local_char_length= my_charpos(field_charset, pos, pos + f_length,
368  local_char_length);
369  set_if_smaller(f_length, local_char_length);
370  unsigned char len_buff[key_len];
371  int2store(len_buff,f_length);
372  buff.append(len_buff);
373  buff.append(pos, f_length);
374  if (f_length < length)
375  {
376  /*
377  Must clear this as we do a memcmp in optimizer/range.cc to detect
378  identical keys
379  */
380  buff.append(length-f_length, 0);
381  }
382  return key_len+f_length;
383 }
384 
385 
386 uint32_t Field_varstring::get_key_image(unsigned char *buff, uint32_t length)
387 {
388  uint32_t f_length= length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
389  uint32_t local_char_length= length / field_charset->mbmaxlen;
390  unsigned char *pos= ptr+length_bytes;
391  local_char_length= my_charpos(field_charset, pos, pos + f_length,
392  local_char_length);
393  set_if_smaller(f_length, local_char_length);
394  /* Key is always stored with 2 bytes */
395  int2store(buff,f_length);
396  memcpy(buff+HA_KEY_BLOB_LENGTH, pos, f_length);
397  if (f_length < length)
398  {
399  /*
400  Must clear this as we do a memcmp in optimizer/range.cc to detect
401  identical keys
402  */
403  memset(buff+HA_KEY_BLOB_LENGTH+f_length, 0, (length-f_length));
404  }
405  return HA_KEY_BLOB_LENGTH+f_length;
406 }
407 
408 void Field_varstring::set_key_image(const unsigned char *buff, uint32_t length)
409 {
410  length= uint2korr(buff); // Real length is here
411  (void) Field_varstring::store((const char*) buff+HA_KEY_BLOB_LENGTH, length, field_charset);
412 }
413 
414 int Field_varstring::cmp_binary(const unsigned char *a_ptr,
415  const unsigned char *b_ptr,
416  uint32_t max_length)
417 {
418  uint32_t a_length,b_length;
419 
420  if (length_bytes == 1)
421  {
422  a_length= (uint32_t) *a_ptr;
423  b_length= (uint32_t) *b_ptr;
424  }
425  else
426  {
427  a_length= uint2korr(a_ptr);
428  b_length= uint2korr(b_ptr);
429  }
430  set_if_smaller(a_length, max_length);
431  set_if_smaller(b_length, max_length);
432  if (a_length != b_length)
433  return 1;
434  return memcmp(a_ptr+length_bytes, b_ptr+length_bytes, a_length);
435 }
436 
437 
438 Field *Field_varstring::new_field(memory::Root *root, Table *new_table, bool keep_type)
439 {
440  Field_varstring *res= (Field_varstring*) Field::new_field(root, new_table,
441  keep_type);
442  if (res)
443  res->length_bytes= length_bytes;
444  return res;
445 }
446 
447 
448 Field *Field_varstring::new_key_field(memory::Root *root,
449  Table *new_table,
450  unsigned char *new_ptr, unsigned char *new_null_ptr,
451  uint32_t new_null_bit)
452 {
453  Field_varstring *res;
454  if ((res= (Field_varstring*) Field::new_key_field(root,
455  new_table,
456  new_ptr,
457  new_null_ptr,
458  new_null_bit)))
459  {
460  /* Keys length prefixes are always packed with 2 bytes */
461  res->length_bytes= 2;
462  }
463  return res;
464 }
465 
466 } /* namespace drizzled */
TODO: Rename this file - func.h is stupid.
virtual unsigned char * pack(unsigned char *to, const unsigned char *from, uint32_t max_length, bool low_byte_first)
Definition: varstring.cc:292
uint32_t get_key_image(unsigned char *buff, uint32_t length)
Definition: varstring.cc:386
virtual const unsigned char * unpack(unsigned char *to, const unsigned char *from, uint32_t param_data, bool low_byte_first)
Definition: varstring.cc:329
int key_cmp(const unsigned char *, const unsigned char *)
Definition: varstring.cc:240