~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/blob.cc

  • Committer: Mark Atwood
  • Date: 2008-07-12 11:37:59 UTC
  • mto: This revision was merged to the branch mainline in revision 139.
  • Revision ID: me@mark.atwood.name-20080712113759-nrjn1bq1e0shuory
Add hello_world() UDF

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 
28
 
#include <string>
29
 
#include <algorithm>
30
 
 
31
 
using namespace std;
32
 
 
33
 
namespace drizzled
34
 
{
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 * 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)
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)
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)
124
 
{
125
 
  return get_length(ptr_arg, getTable()->getShare()->db_low_byte_first);
126
 
}
127
 
 
128
 
 
129
 
/**
130
 
  Put a blob length field into a record buffer.
131
 
 
132
 
  Blob length is always stored in sizeof(uint32_t) (4 bytes)
133
 
 
134
 
  @param pos                 Pointer into the record buffer.
135
 
  @param length              The length value to put.
136
 
*/
137
 
 
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 * 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
 
    size_t dummy_offset;
164
 
    if (!String::needs_conversion(length, cs, field_charset, &dummy_offset))
165
 
    {
166
 
      Field_blob::store_length(length);
167
 
      memmove(ptr+sizeof(uint32_t), &from, sizeof(char*));
168
 
      return 0;
169
 
    }
170
 
    if (tmpstr.copy(from, length, cs))
171
 
      goto oom_error;
172
 
    from= tmpstr.ptr();
173
 
  }
174
 
 
175
 
  new_length= min(max_data_length(), field_charset->mbmaxlen * length);
176
 
  if (value.alloc(new_length))
177
 
    goto oom_error;
178
 
 
179
 
  /*
180
 
    "length" is OK as "nchars" argument to well_formed_copy_nchars as this
181
 
    is never used to limit the length of the data. The cut of long data
182
 
    is done with the new_length value.
183
 
  */
184
 
  copy_length= well_formed_copy_nchars(field_charset,
185
 
                                       (char*) value.ptr(), new_length,
186
 
                                       cs, from, length,
187
 
                                       length,
188
 
                                       &well_formed_error_pos,
189
 
                                       &cannot_convert_error_pos,
190
 
                                       &from_end_pos);
191
 
 
192
 
  Field_blob::store_length(copy_length);
193
 
  tmp= value.ptr();
194
 
  memmove(ptr+sizeof(uint32_t), &tmp, sizeof(char*));
195
 
 
196
 
  if (check_string_copy_error(this, well_formed_error_pos,
197
 
                              cannot_convert_error_pos, from + length, cs))
198
 
    return 2;
199
 
 
200
 
  return report_if_important_data(from_end_pos, from + length);
201
 
 
202
 
oom_error:
203
 
  /* Fatal OOM error */
204
 
  memset(ptr, 0, Field_blob::pack_length());
205
 
  return -1;
206
 
}
207
 
 
208
 
 
209
 
int Field_blob::store(double nr)
210
 
{
211
 
  const CHARSET_INFO * const cs=charset();
212
 
  ASSERT_COLUMN_MARKED_FOR_WRITE;
213
 
  value.set_real(nr, NOT_FIXED_DEC, cs);
214
 
  return Field_blob::store(value.ptr(),(uint32_t) value.length(), cs);
215
 
}
216
 
 
217
 
 
218
 
int Field_blob::store(int64_t nr, bool unsigned_val)
219
 
{
220
 
  const CHARSET_INFO * const cs=charset();
221
 
  ASSERT_COLUMN_MARKED_FOR_WRITE;
222
 
  value.set_int(nr, unsigned_val, cs);
223
 
  return Field_blob::store(value.ptr(), (uint32_t) value.length(), cs);
224
 
}
225
 
 
226
 
 
227
 
double Field_blob::val_real(void)
228
 
{
229
 
  int not_used;
230
 
  char *end_not_used, *blob;
231
 
  uint32_t length;
232
 
  const CHARSET_INFO *cs;
233
 
 
234
 
  ASSERT_COLUMN_MARKED_FOR_READ;
235
 
 
236
 
  memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
237
 
  if (!blob)
238
 
    return 0.0;
239
 
  length= get_length(ptr);
240
 
  cs= charset();
241
 
  return my_strntod(cs, blob, length, &end_not_used, &not_used);
242
 
}
243
 
 
244
 
 
245
 
int64_t Field_blob::val_int(void)
246
 
{
247
 
  int not_used;
248
 
  char *blob;
249
 
 
250
 
  ASSERT_COLUMN_MARKED_FOR_READ;
251
 
 
252
 
  memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
253
 
  if (!blob)
254
 
    return 0;
255
 
  uint32_t length=get_length(ptr);
256
 
  return my_strntoll(charset(),blob,length,10,NULL,&not_used);
257
 
}
258
 
 
259
 
String *Field_blob::val_str(String *,
260
 
                            String *val_ptr)
261
 
{
262
 
  char *blob;
263
 
 
264
 
  ASSERT_COLUMN_MARKED_FOR_READ;
265
 
 
266
 
  memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
267
 
  if (!blob)
268
 
    val_ptr->set("",0,charset());       // A bit safer than ->length(0)
269
 
  else
270
 
    val_ptr->set((const char*) blob,get_length(ptr),charset());
271
 
  return val_ptr;
272
 
}
273
 
 
274
 
 
275
 
my_decimal *Field_blob::val_decimal(my_decimal *decimal_value)
276
 
{
277
 
  const char *blob;
278
 
  size_t length;
279
 
 
280
 
  ASSERT_COLUMN_MARKED_FOR_READ;
281
 
 
282
 
  memcpy(&blob, ptr+sizeof(uint32_t), sizeof(const unsigned char*));
283
 
  if (!blob)
284
 
  {
285
 
    blob= "";
286
 
    length= 0;
287
 
  }
288
 
  else
289
 
    length= get_length(ptr);
290
 
 
291
 
  str2my_decimal(E_DEC_FATAL_ERROR, blob, length, charset(),
292
 
                 decimal_value);
293
 
  return decimal_value;
294
 
}
295
 
 
296
 
 
297
 
int Field_blob::cmp(const unsigned char *a,uint32_t a_length, const unsigned char *b,
298
 
                    uint32_t b_length)
299
 
{
300
 
  return field_charset->coll->strnncollsp(field_charset,
301
 
                                          a, a_length, b, b_length,
302
 
                                          0);
303
 
}
304
 
 
305
 
 
306
 
int Field_blob::cmp_max(const unsigned char *a_ptr, const unsigned char *b_ptr,
307
 
                        uint32_t max_length)
308
 
{
309
 
  unsigned char *blob1,*blob2;
310
 
  memcpy(&blob1,a_ptr+sizeof(uint32_t),sizeof(char*));
311
 
  memcpy(&blob2,b_ptr+sizeof(uint32_t),sizeof(char*));
312
 
  uint32_t a_len= get_length(a_ptr), b_len= get_length(b_ptr);
313
 
  set_if_smaller(a_len, max_length);
314
 
  set_if_smaller(b_len, max_length);
315
 
  return Field_blob::cmp(blob1,a_len,blob2,b_len);
316
 
}
317
 
 
318
 
 
319
 
int Field_blob::cmp_binary(const unsigned char *a_ptr, const unsigned char *b_ptr,
320
 
                           uint32_t max_length)
321
 
{
322
 
  char *a,*b;
323
 
  uint32_t diff;
324
 
  uint32_t a_length,b_length;
325
 
  memcpy(&a,a_ptr+sizeof(uint32_t),sizeof(char*));
326
 
  memcpy(&b,b_ptr+sizeof(uint32_t),sizeof(char*));
327
 
 
328
 
  a_length= get_length(a_ptr);
329
 
 
330
 
  if (a_length > max_length)
331
 
    a_length= max_length;
332
 
 
333
 
  b_length= get_length(b_ptr);
334
 
 
335
 
  if (b_length > max_length)
336
 
    b_length= max_length;
337
 
 
338
 
  diff= memcmp(a,b,min(a_length,b_length));
339
 
 
340
 
  return diff ? diff : (unsigned int) (a_length - b_length);
341
 
}
342
 
 
343
 
/* The following is used only when comparing a key */
344
 
uint32_t Field_blob::get_key_image(unsigned char *buff, uint32_t length)
345
 
{
346
 
  uint32_t blob_length= get_length(ptr);
347
 
  unsigned char *blob;
348
 
 
349
 
  get_ptr(&blob);
350
 
  uint32_t local_char_length= length / field_charset->mbmaxlen;
351
 
  local_char_length= my_charpos(field_charset, blob, blob + blob_length,
352
 
                          local_char_length);
353
 
  set_if_smaller(blob_length, local_char_length);
354
 
 
355
 
  if ((uint32_t) length > blob_length)
356
 
  {
357
 
    /*
358
 
      Must clear this as we do a memcmp in optimizer/range.cc to detect
359
 
      identical keys
360
 
    */
361
 
    memset(buff+HA_KEY_BLOB_LENGTH+blob_length, 0, (length-blob_length));
362
 
    length=(uint32_t) blob_length;
363
 
  }
364
 
  int2store(buff,length);
365
 
  memcpy(buff+HA_KEY_BLOB_LENGTH, blob, length);
366
 
  return HA_KEY_BLOB_LENGTH+length;
367
 
}
368
 
 
369
 
 
370
 
uint32_t Field_blob::get_key_image(basic_string<unsigned char> &buff, uint32_t length)
371
 
{
372
 
  uint32_t blob_length= get_length(ptr);
373
 
  unsigned char *blob;
374
 
 
375
 
  get_ptr(&blob);
376
 
  uint32_t local_char_length= length / field_charset->mbmaxlen;
377
 
  local_char_length= my_charpos(field_charset, blob, blob + blob_length,
378
 
                                local_char_length);
379
 
  set_if_smaller(blob_length, local_char_length);
380
 
 
381
 
  unsigned char len_buff[HA_KEY_BLOB_LENGTH];
382
 
  int2store(len_buff,length);
383
 
  buff.append(len_buff);
384
 
  buff.append(blob, blob_length);
385
 
 
386
 
  if (length > blob_length)
387
 
  {
388
 
    /*
389
 
      Must clear this as we do a memcmp in optimizer/range.cc to detect
390
 
      identical keys
391
 
    */
392
 
 
393
 
    buff.append(length-blob_length, '0');
394
 
  }
395
 
  return HA_KEY_BLOB_LENGTH+length;
396
 
}
397
 
 
398
 
void Field_blob::set_key_image(const unsigned char *buff,uint32_t length)
399
 
{
400
 
  length= uint2korr(buff);
401
 
  (void) Field_blob::store((const char*) buff+HA_KEY_BLOB_LENGTH, length, field_charset);
402
 
}
403
 
 
404
 
int Field_blob::key_cmp(const unsigned char *key_ptr, uint32_t max_key_length)
405
 
{
406
 
  unsigned char *blob1;
407
 
  uint32_t blob_length=get_length(ptr);
408
 
  memcpy(&blob1,ptr+sizeof(uint32_t),sizeof(char*));
409
 
  const CHARSET_INFO * const cs= charset();
410
 
  uint32_t local_char_length= max_key_length / cs->mbmaxlen;
411
 
  local_char_length= my_charpos(cs, blob1, blob1+blob_length,
412
 
                                local_char_length);
413
 
  set_if_smaller(blob_length, local_char_length);
414
 
  return Field_blob::cmp(blob1, blob_length,
415
 
                         key_ptr+HA_KEY_BLOB_LENGTH,
416
 
                         uint2korr(key_ptr));
417
 
}
418
 
 
419
 
int Field_blob::key_cmp(const unsigned char *a,const unsigned char *b)
420
 
{
421
 
  return Field_blob::cmp(a+HA_KEY_BLOB_LENGTH, uint2korr(a),
422
 
                         b+HA_KEY_BLOB_LENGTH, uint2korr(b));
423
 
}
424
 
 
425
 
uint32_t Field_blob::sort_length() const
426
 
{
427
 
  return (uint32_t) (current_session->variables.max_sort_length +
428
 
                     (field_charset == &my_charset_bin ? 0 : sizeof(uint32_t)));
429
 
}
430
 
 
431
 
void Field_blob::sort_string(unsigned char *to,uint32_t length)
432
 
{
433
 
  unsigned char *blob;
434
 
  uint32_t blob_length=get_length();
435
 
 
436
 
  if (!blob_length)
437
 
    memset(to, 0, length);
438
 
  else
439
 
  {
440
 
    if (field_charset == &my_charset_bin)
441
 
    {
442
 
      unsigned char *pos;
443
 
 
444
 
      /*
445
 
        Store length of blob last in blob to shorter blobs before longer blobs
446
 
      */
447
 
      length-= sizeof(uint32_t); // size of stored blob length
448
 
      pos= to+length;
449
 
 
450
 
      mi_int4store(pos, blob_length);
451
 
    }
452
 
    memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
453
 
 
454
 
    blob_length=my_strnxfrm(field_charset,
455
 
                            to, length, blob, blob_length);
456
 
    assert(blob_length == length);
457
 
  }
458
 
}
459
 
 
460
 
uint32_t Field_blob::pack_length() const
461
 
{
462
 
  return (uint32_t) (sizeof(uint32_t) + portable_sizeof_char_ptr);
463
 
}
464
 
 
465
 
void Field_blob::sql_type(String &res) const
466
 
{
467
 
  if (charset() == &my_charset_bin)
468
 
    res.set_ascii(STRING_WITH_LEN("blob"));
469
 
  else
470
 
    res.set_ascii(STRING_WITH_LEN("text"));
471
 
}
472
 
 
473
 
unsigned char *Field_blob::pack(unsigned char *to, const unsigned char *from,
474
 
                                uint32_t max_length, bool low_byte_first)
475
 
{
476
 
  unsigned char *save= ptr;
477
 
  ptr= (unsigned char*) from;
478
 
  uint32_t length= get_length();                        // Length of from string
479
 
 
480
 
  /*
481
 
    Store max length, which will occupy packlength bytes. If the max
482
 
    length given is smaller than the actual length of the blob, we
483
 
    just store the initial bytes of the blob.
484
 
  */
485
 
  store_length(to, min(length, max_length), low_byte_first);
486
 
 
487
 
  /*
488
 
    Store the actual blob data, which will occupy 'length' bytes.
489
 
   */
490
 
  if (length > 0)
491
 
  {
492
 
    get_ptr((unsigned char**) &from);
493
 
    memcpy(to+sizeof(uint32_t), from,length);
494
 
  }
495
 
 
496
 
  ptr= save;                                    // Restore org row pointer
497
 
  return(to+sizeof(uint32_t)+length);
498
 
}
499
 
 
500
 
/**
501
 
   Unpack a blob field from row data.
502
 
 
503
 
   This method is used to unpack a blob field from a master whose size of
504
 
   the field is less than that of the slave. Note: This method is included
505
 
   to satisfy inheritance rules, but is not needed for blob fields. It
506
 
   simply is used as a pass-through to the original unpack() method for
507
 
   blob fields.
508
 
 
509
 
   @param   to         Destination of the data
510
 
   @param   from       Source of the data
511
 
   @param   param_data @c true if base types should be stored in little-
512
 
                       endian format, @c false if native format should
513
 
                       be used.
514
 
 
515
 
   @return  New pointer into memory based on from + length of the data
516
 
*/
517
 
const unsigned char *Field_blob::unpack(unsigned char *,
518
 
                                        const unsigned char *from,
519
 
                                        uint32_t,
520
 
                                        bool low_byte_first)
521
 
{
522
 
  uint32_t const length= get_length(from, low_byte_first);
523
 
  getTable()->setWriteSet(position());
524
 
  store(reinterpret_cast<const char*>(from) + sizeof(uint32_t),
525
 
        length, field_charset);
526
 
  return(from + sizeof(uint32_t) + length);
527
 
}
528
 
 
529
 
/** Create a packed key that will be used for storage from a MySQL row. */
530
 
 
531
 
unsigned char *
532
 
Field_blob::pack_key(unsigned char *to, const unsigned char *from, uint32_t max_length,
533
 
                     bool )
534
 
{
535
 
  unsigned char *save= ptr;
536
 
  ptr= (unsigned char*) from;
537
 
  uint32_t length=get_length();        // Length of from string
538
 
  uint32_t local_char_length= ((field_charset->mbmaxlen > 1) ?
539
 
                           max_length/field_charset->mbmaxlen : max_length);
540
 
  if (length)
541
 
    get_ptr((unsigned char**) &from);
542
 
  if (length > local_char_length)
543
 
    local_char_length= my_charpos(field_charset, from, from+length,
544
 
                                  local_char_length);
545
 
  set_if_smaller(length, local_char_length);
546
 
  *to++= (unsigned char) length;
547
 
  if (max_length > 255)                         // 2 byte length
548
 
    *to++= (unsigned char) (length >> 8);
549
 
  memcpy(to, from, length);
550
 
  ptr=save;                                     // Restore org row pointer
551
 
  return to+length;
552
 
}
553
 
 
554
 
 
555
 
/**
556
 
  maximum possible display length for blob.
557
 
 
558
 
  @return
559
 
    length
560
 
*/
561
 
 
562
 
uint32_t Field_blob::max_display_length()
563
 
{
564
 
    return (uint32_t) 4294967295U;
565
 
}
566
 
 
567
 
} /* namespace drizzled */