~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field_conv.cc

Moved base64.h to mysys.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000-2003 MySQL AB
2
 
 
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.
6
 
 
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.
11
 
 
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
 
 
16
 
 
17
 
/**
18
 
  @file
19
 
 
20
 
  @brief
21
 
  Functions to copy data to or from fields
22
 
 
23
 
    This could be done with a single short function but opencoding this
24
 
    gives much more speed.
25
 
*/
26
 
 
27
 
#include <drizzled/server_includes.h>
28
 
 
29
 
static void do_field_eq(Copy_field *copy)
30
 
{
31
 
  memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
32
 
}
33
 
 
34
 
static void do_field_1(Copy_field *copy)
35
 
{
36
 
  copy->to_ptr[0]=copy->from_ptr[0];
37
 
}
38
 
 
39
 
static void do_field_2(Copy_field *copy)
40
 
{
41
 
  copy->to_ptr[0]=copy->from_ptr[0];
42
 
  copy->to_ptr[1]=copy->from_ptr[1];
43
 
}
44
 
 
45
 
static void do_field_3(Copy_field *copy)
46
 
{
47
 
  copy->to_ptr[0]=copy->from_ptr[0];
48
 
  copy->to_ptr[1]=copy->from_ptr[1];
49
 
  copy->to_ptr[2]=copy->from_ptr[2];
50
 
}
51
 
 
52
 
static void do_field_4(Copy_field *copy)
53
 
{
54
 
  copy->to_ptr[0]=copy->from_ptr[0];
55
 
  copy->to_ptr[1]=copy->from_ptr[1];
56
 
  copy->to_ptr[2]=copy->from_ptr[2];
57
 
  copy->to_ptr[3]=copy->from_ptr[3];
58
 
}
59
 
 
60
 
static void do_field_6(Copy_field *copy)
61
 
{                                               // For blob field
62
 
  copy->to_ptr[0]=copy->from_ptr[0];
63
 
  copy->to_ptr[1]=copy->from_ptr[1];
64
 
  copy->to_ptr[2]=copy->from_ptr[2];
65
 
  copy->to_ptr[3]=copy->from_ptr[3];
66
 
  copy->to_ptr[4]=copy->from_ptr[4];
67
 
  copy->to_ptr[5]=copy->from_ptr[5];
68
 
}
69
 
 
70
 
static void do_field_8(Copy_field *copy)
71
 
{
72
 
  copy->to_ptr[0]=copy->from_ptr[0];
73
 
  copy->to_ptr[1]=copy->from_ptr[1];
74
 
  copy->to_ptr[2]=copy->from_ptr[2];
75
 
  copy->to_ptr[3]=copy->from_ptr[3];
76
 
  copy->to_ptr[4]=copy->from_ptr[4];
77
 
  copy->to_ptr[5]=copy->from_ptr[5];
78
 
  copy->to_ptr[6]=copy->from_ptr[6];
79
 
  copy->to_ptr[7]=copy->from_ptr[7];
80
 
}
81
 
 
82
 
 
83
 
static void do_field_to_null_str(Copy_field *copy)
84
 
{
85
 
  if (*copy->from_null_ptr & copy->from_bit)
86
 
  {
87
 
    memset(copy->to_ptr, 0, copy->from_length);
88
 
    copy->to_null_ptr[0]=1;                     // Always bit 1
89
 
  }
90
 
  else
91
 
  {
92
 
    copy->to_null_ptr[0]=0;
93
 
    memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
94
 
  }
95
 
}
96
 
 
97
 
 
98
 
static void do_outer_field_to_null_str(Copy_field *copy)
99
 
{
100
 
  if (*copy->null_row ||
101
 
      (copy->from_null_ptr && (*copy->from_null_ptr & copy->from_bit)))
102
 
  {
103
 
    memset(copy->to_ptr, 0, copy->from_length);
104
 
    copy->to_null_ptr[0]=1;                     // Always bit 1
105
 
  }
106
 
  else
107
 
  {
108
 
    copy->to_null_ptr[0]=0;
109
 
    memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
110
 
  }
111
 
}
112
 
 
113
 
 
114
 
int
115
 
set_field_to_null(Field *field)
116
 
{
117
 
  if (field->real_maybe_null())
118
 
  {
119
 
    field->set_null();
120
 
    field->reset();
121
 
    return 0;
122
 
  }
123
 
  field->reset();
124
 
  if (field->table->in_use->count_cuted_fields == CHECK_FIELD_WARN)
125
 
  {
126
 
    field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
127
 
    return 0;
128
 
  }
129
 
  if (!field->table->in_use->no_errors)
130
 
    my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name);
131
 
  return -1;
132
 
}
133
 
 
134
 
 
135
 
/**
136
 
  Set field to NULL or TIMESTAMP or to next auto_increment number.
137
 
 
138
 
  @param field           Field to update
139
 
  @param no_conversions  Set to 1 if we should return 1 if field can't
140
 
                         take null values.
141
 
                         If set to 0 we will do store the 'default value'
142
 
                         if the field is a special field. If not we will
143
 
                         give an error.
144
 
 
145
 
  @retval
146
 
    0    Field could take 0 or an automatic conversion was used
147
 
  @retval
148
 
    -1   Field could not take NULL and no conversion was used.
149
 
    If no_conversion was not set, an error message is printed
150
 
*/
151
 
 
152
 
int
153
 
set_field_to_null_with_conversions(Field *field, bool no_conversions)
154
 
{
155
 
  if (field->real_maybe_null())
156
 
  {
157
 
    field->set_null();
158
 
    field->reset();
159
 
    return 0;
160
 
  }
161
 
  if (no_conversions)
162
 
    return -1;
163
 
 
164
 
  /*
165
 
    Check if this is a special type, which will get a special walue
166
 
    when set to NULL (TIMESTAMP fields which allow setting to NULL
167
 
    are handled by first check).
168
 
  */
169
 
  if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
170
 
  {
171
 
    ((Field_timestamp*) field)->set_time();
172
 
    return 0;                                   // Ok to set time to NULL
173
 
  }
174
 
  field->reset();
175
 
  if (field == field->table->next_number_field)
176
 
  {
177
 
    field->table->auto_increment_field_not_null= false;
178
 
    return 0;                             // field is set in fill_record()
179
 
  }
180
 
  if (field->table->in_use->count_cuted_fields == CHECK_FIELD_WARN)
181
 
  {
182
 
    field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_BAD_NULL_ERROR, 1);
183
 
    return 0;
184
 
  }
185
 
  if (!field->table->in_use->no_errors)
186
 
    my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name);
187
 
  return -1;
188
 
}
189
 
 
190
 
 
191
 
static void do_skip(Copy_field *copy __attribute__((unused)))
192
 
{
193
 
}
194
 
 
195
 
 
196
 
static void do_copy_null(Copy_field *copy)
197
 
{
198
 
  if (*copy->from_null_ptr & copy->from_bit)
199
 
  {
200
 
    *copy->to_null_ptr|=copy->to_bit;
201
 
    copy->to_field->reset();
202
 
  }
203
 
  else
204
 
  {
205
 
    *copy->to_null_ptr&= ~copy->to_bit;
206
 
    (copy->do_copy2)(copy);
207
 
  }
208
 
}
209
 
 
210
 
 
211
 
static void do_outer_field_null(Copy_field *copy)
212
 
{
213
 
  if (*copy->null_row ||
214
 
      (copy->from_null_ptr && (*copy->from_null_ptr & copy->from_bit)))
215
 
  {
216
 
    *copy->to_null_ptr|=copy->to_bit;
217
 
    copy->to_field->reset();
218
 
  }
219
 
  else
220
 
  {
221
 
    *copy->to_null_ptr&= ~copy->to_bit;
222
 
    (copy->do_copy2)(copy);
223
 
  }
224
 
}
225
 
 
226
 
 
227
 
static void do_copy_not_null(Copy_field *copy)
228
 
{
229
 
  if (*copy->from_null_ptr & copy->from_bit)
230
 
  {
231
 
    copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
232
 
                                ER_WARN_DATA_TRUNCATED, 1);
233
 
    copy->to_field->reset();
234
 
  }
235
 
  else
236
 
    (copy->do_copy2)(copy);
237
 
}
238
 
 
239
 
 
240
 
static void do_copy_maybe_null(Copy_field *copy)
241
 
{
242
 
  *copy->to_null_ptr&= ~copy->to_bit;
243
 
  (copy->do_copy2)(copy);
244
 
}
245
 
 
246
 
/* timestamp and next_number has special handling in case of NULL values */
247
 
 
248
 
static void do_copy_timestamp(Copy_field *copy)
249
 
{
250
 
  if (*copy->from_null_ptr & copy->from_bit)
251
 
  {
252
 
    /* Same as in set_field_to_null_with_conversions() */
253
 
    ((Field_timestamp*) copy->to_field)->set_time();
254
 
  }
255
 
  else
256
 
    (copy->do_copy2)(copy);
257
 
}
258
 
 
259
 
 
260
 
static void do_copy_next_number(Copy_field *copy)
261
 
{
262
 
  if (*copy->from_null_ptr & copy->from_bit)
263
 
  {
264
 
    /* Same as in set_field_to_null_with_conversions() */
265
 
    copy->to_field->table->auto_increment_field_not_null= false;
266
 
    copy->to_field->reset();
267
 
  }
268
 
  else
269
 
    (copy->do_copy2)(copy);
270
 
}
271
 
 
272
 
 
273
 
static void do_copy_blob(Copy_field *copy)
274
 
{
275
 
  ulong length=((Field_blob*) copy->from_field)->get_length();
276
 
  ((Field_blob*) copy->to_field)->store_length(length);
277
 
  memcpy(copy->to_ptr,copy->from_ptr,sizeof(char*));
278
 
}
279
 
 
280
 
static void do_conv_blob(Copy_field *copy)
281
 
{
282
 
  copy->from_field->val_str(&copy->tmp);
283
 
  ((Field_blob *) copy->to_field)->store(copy->tmp.ptr(),
284
 
                                         copy->tmp.length(),
285
 
                                         copy->tmp.charset());
286
 
}
287
 
 
288
 
/** Save blob in copy->tmp for GROUP BY. */
289
 
 
290
 
static void do_save_blob(Copy_field *copy)
291
 
{
292
 
  char buff[MAX_FIELD_WIDTH];
293
 
  String res(buff,sizeof(buff),copy->tmp.charset());
294
 
  copy->from_field->val_str(&res);
295
 
  copy->tmp.copy(res);
296
 
  ((Field_blob *) copy->to_field)->store(copy->tmp.ptr(),
297
 
                                         copy->tmp.length(),
298
 
                                         copy->tmp.charset());
299
 
}
300
 
 
301
 
 
302
 
static void do_field_string(Copy_field *copy)
303
 
{
304
 
  char buff[MAX_FIELD_WIDTH];
305
 
  copy->tmp.set_quick(buff,sizeof(buff),copy->tmp.charset());
306
 
  copy->from_field->val_str(&copy->tmp);
307
 
  copy->to_field->store(copy->tmp.c_ptr_quick(),copy->tmp.length(),
308
 
                        copy->tmp.charset());
309
 
}
310
 
 
311
 
 
312
 
static void do_field_enum(Copy_field *copy)
313
 
{
314
 
  if (copy->from_field->val_int() == 0)
315
 
    ((Field_enum *) copy->to_field)->store_type((uint64_t) 0);
316
 
  else
317
 
    do_field_string(copy);
318
 
}
319
 
 
320
 
 
321
 
static void do_field_int(Copy_field *copy)
322
 
{
323
 
  int64_t value= copy->from_field->val_int();
324
 
  copy->to_field->store(value,
325
 
                        test(copy->from_field->flags & UNSIGNED_FLAG));
326
 
}
327
 
 
328
 
static void do_field_real(Copy_field *copy)
329
 
{
330
 
  double value=copy->from_field->val_real();
331
 
  copy->to_field->store(value);
332
 
}
333
 
 
334
 
 
335
 
static void do_field_decimal(Copy_field *copy)
336
 
{
337
 
  my_decimal value;
338
 
  copy->to_field->store_decimal(copy->from_field->val_decimal(&value));
339
 
}
340
 
 
341
 
 
342
 
/**
343
 
  string copy for single byte characters set when to string is shorter than
344
 
  from string.
345
 
*/
346
 
 
347
 
static void do_cut_string(Copy_field *copy)
348
 
{
349
 
  const CHARSET_INFO * const cs= copy->from_field->charset();
350
 
  memcpy(copy->to_ptr,copy->from_ptr,copy->to_length);
351
 
 
352
 
  /* Check if we loosed any important characters */
353
 
  if (cs->cset->scan(cs,
354
 
                     (char*) copy->from_ptr + copy->to_length,
355
 
                     (char*) copy->from_ptr + copy->from_length,
356
 
                     MY_SEQ_SPACES) < copy->from_length - copy->to_length)
357
 
  {
358
 
    copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
359
 
                                ER_WARN_DATA_TRUNCATED, 1);
360
 
  }
361
 
}
362
 
 
363
 
 
364
 
/**
365
 
  string copy for multi byte characters set when to string is shorter than
366
 
  from string.
367
 
*/
368
 
 
369
 
static void do_cut_string_complex(Copy_field *copy)
370
 
{                                               // Shorter string field
371
 
  int well_formed_error;
372
 
  const CHARSET_INFO * const cs= copy->from_field->charset();
373
 
  const unsigned char *from_end= copy->from_ptr + copy->from_length;
374
 
  uint32_t copy_length= cs->cset->well_formed_len(cs,
375
 
                                              (char*) copy->from_ptr,
376
 
                                              (char*) from_end, 
377
 
                                              copy->to_length / cs->mbmaxlen,
378
 
                                              &well_formed_error);
379
 
  if (copy->to_length < copy_length)
380
 
    copy_length= copy->to_length;
381
 
  memcpy(copy->to_ptr, copy->from_ptr, copy_length);
382
 
 
383
 
  /* Check if we lost any important characters */
384
 
  if (well_formed_error ||
385
 
      cs->cset->scan(cs, (char*) copy->from_ptr + copy_length,
386
 
                     (char*) from_end,
387
 
                     MY_SEQ_SPACES) < (copy->from_length - copy_length))
388
 
  {
389
 
    copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
390
 
                                ER_WARN_DATA_TRUNCATED, 1);
391
 
  }
392
 
 
393
 
  if (copy_length < copy->to_length)
394
 
    cs->cset->fill(cs, (char*) copy->to_ptr + copy_length,
395
 
                   copy->to_length - copy_length, ' ');
396
 
}
397
 
 
398
 
 
399
 
 
400
 
 
401
 
static void do_expand_binary(Copy_field *copy)
402
 
{
403
 
  const CHARSET_INFO * const cs= copy->from_field->charset();
404
 
  memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
405
 
  cs->cset->fill(cs, (char*) copy->to_ptr+copy->from_length,
406
 
                     copy->to_length-copy->from_length, '\0');
407
 
}
408
 
 
409
 
 
410
 
 
411
 
static void do_expand_string(Copy_field *copy)
412
 
{
413
 
  const CHARSET_INFO * const cs= copy->from_field->charset();
414
 
  memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
415
 
  cs->cset->fill(cs, (char*) copy->to_ptr+copy->from_length,
416
 
                     copy->to_length-copy->from_length, ' ');
417
 
}
418
 
 
419
 
 
420
 
static void do_varstring1(Copy_field *copy)
421
 
{
422
 
  uint32_t length= (uint) *(unsigned char*) copy->from_ptr;
423
 
  if (length > copy->to_length- 1)
424
 
  {
425
 
    length=copy->to_length - 1;
426
 
    if (copy->from_field->table->in_use->count_cuted_fields)
427
 
      copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
428
 
                                  ER_WARN_DATA_TRUNCATED, 1);
429
 
  }
430
 
  *(unsigned char*) copy->to_ptr= (unsigned char) length;
431
 
  memcpy(copy->to_ptr+1, copy->from_ptr + 1, length);
432
 
}
433
 
 
434
 
 
435
 
static void do_varstring1_mb(Copy_field *copy)
436
 
{
437
 
  int well_formed_error;
438
 
  const CHARSET_INFO * const cs= copy->from_field->charset();
439
 
  uint32_t from_length= (uint) *(unsigned char*) copy->from_ptr;
440
 
  const unsigned char *from_ptr= copy->from_ptr + 1;
441
 
  uint32_t to_char_length= (copy->to_length - 1) / cs->mbmaxlen;
442
 
  uint32_t length= cs->cset->well_formed_len(cs, (char*) from_ptr,
443
 
                                         (char*) from_ptr + from_length,
444
 
                                         to_char_length, &well_formed_error);
445
 
  if (length < from_length)
446
 
  {
447
 
    if (current_thd->count_cuted_fields)
448
 
      copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
449
 
                                  ER_WARN_DATA_TRUNCATED, 1);
450
 
  }
451
 
  *copy->to_ptr= (unsigned char) length;
452
 
  memcpy(copy->to_ptr + 1, from_ptr, length);
453
 
}
454
 
 
455
 
 
456
 
static void do_varstring2(Copy_field *copy)
457
 
{
458
 
  uint32_t length=uint2korr(copy->from_ptr);
459
 
  if (length > copy->to_length- HA_KEY_BLOB_LENGTH)
460
 
  {
461
 
    length=copy->to_length-HA_KEY_BLOB_LENGTH;
462
 
    if (copy->from_field->table->in_use->count_cuted_fields)
463
 
      copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
464
 
                                  ER_WARN_DATA_TRUNCATED, 1);
465
 
  }
466
 
  int2store(copy->to_ptr,length);
467
 
  memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, copy->from_ptr + HA_KEY_BLOB_LENGTH,
468
 
         length);
469
 
}
470
 
 
471
 
 
472
 
static void do_varstring2_mb(Copy_field *copy)
473
 
{
474
 
  int well_formed_error;
475
 
  const CHARSET_INFO * const cs= copy->from_field->charset();
476
 
  uint32_t char_length= (copy->to_length - HA_KEY_BLOB_LENGTH) / cs->mbmaxlen;
477
 
  uint32_t from_length= uint2korr(copy->from_ptr);
478
 
  const unsigned char *from_beg= copy->from_ptr + HA_KEY_BLOB_LENGTH;
479
 
  uint32_t length= cs->cset->well_formed_len(cs, (char*) from_beg,
480
 
                                         (char*) from_beg + from_length,
481
 
                                         char_length, &well_formed_error);
482
 
  if (length < from_length)
483
 
  {
484
 
    if (current_thd->count_cuted_fields)
485
 
      copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
486
 
                                  ER_WARN_DATA_TRUNCATED, 1);
487
 
  }  
488
 
  int2store(copy->to_ptr, length);
489
 
  memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, from_beg, length);
490
 
}
491
 
 
492
 
 
493
 
/***************************************************************************
494
 
** The different functions that fills in a Copy_field class
495
 
***************************************************************************/
496
 
 
497
 
/**
498
 
  copy of field to maybe null string.
499
 
  If field is null then the all bytes are set to 0.
500
 
  if field is not null then the first byte is set to 1 and the rest of the
501
 
  string is the field value.
502
 
  The 'to' buffer should have a size of field->pack_length()+1
503
 
*/
504
 
 
505
 
void Copy_field::set(unsigned char *to,Field *from)
506
 
{
507
 
  from_ptr=from->ptr;
508
 
  to_ptr=to;
509
 
  from_length=from->pack_length();
510
 
  if (from->maybe_null())
511
 
  {
512
 
    from_null_ptr=from->null_ptr;
513
 
    from_bit=     from->null_bit;
514
 
    to_ptr[0]=    1;                            // Null as default value
515
 
    to_null_ptr=  (unsigned char*) to_ptr++;
516
 
    to_bit=       1;
517
 
    if (from->table->maybe_null)
518
 
    {
519
 
      null_row=   &from->table->null_row;
520
 
      do_copy=    do_outer_field_to_null_str;
521
 
    }
522
 
    else
523
 
      do_copy=    do_field_to_null_str;
524
 
  }
525
 
  else
526
 
  {
527
 
    to_null_ptr=  0;                            // For easy debugging
528
 
    do_copy=      do_field_eq;
529
 
  }
530
 
}
531
 
 
532
 
 
533
 
/*
534
 
  To do: 
535
 
 
536
 
  If 'save\ is set to true and the 'from' is a blob field, do_copy is set to
537
 
  do_save_blob rather than do_conv_blob.  The only differences between them
538
 
  appears to be:
539
 
 
540
 
  - do_save_blob allocates and uses an intermediate buffer before calling 
541
 
    Field_blob::store. Is this in order to trigger the call to 
542
 
    well_formed_copy_nchars, by changing the pointer copy->tmp.ptr()?
543
 
    That call will take place anyway in all known cases.
544
 
 
545
 
  - The above causes a truncation to MAX_FIELD_WIDTH. Is this the intended 
546
 
    effect? Truncation is handled by well_formed_copy_nchars anyway.
547
 
 */
548
 
void Copy_field::set(Field *to,Field *from,bool save)
549
 
{
550
 
  if (to->type() == DRIZZLE_TYPE_NULL)
551
 
  {
552
 
    to_null_ptr=0;                              // For easy debugging
553
 
    to_ptr=0;
554
 
    do_copy=do_skip;
555
 
    return;
556
 
  }
557
 
  from_field=from;
558
 
  to_field=to;
559
 
  from_ptr=from->ptr;
560
 
  from_length=from->pack_length();
561
 
  to_ptr=  to->ptr;
562
 
  to_length=to_field->pack_length();
563
 
 
564
 
  // set up null handling
565
 
  from_null_ptr=to_null_ptr=0;
566
 
  if (from->maybe_null())
567
 
  {
568
 
    from_null_ptr=      from->null_ptr;
569
 
    from_bit=           from->null_bit;
570
 
    if (to_field->real_maybe_null())
571
 
    {
572
 
      to_null_ptr=      to->null_ptr;
573
 
      to_bit=           to->null_bit;
574
 
      if (from_null_ptr)
575
 
        do_copy=        do_copy_null;
576
 
      else
577
 
      {
578
 
        null_row=       &from->table->null_row;
579
 
        do_copy=        do_outer_field_null;
580
 
      }
581
 
    }
582
 
    else
583
 
    {
584
 
      if (to_field->type() == DRIZZLE_TYPE_TIMESTAMP)
585
 
        do_copy= do_copy_timestamp;               // Automatic timestamp
586
 
      else if (to_field == to_field->table->next_number_field)
587
 
        do_copy= do_copy_next_number;
588
 
      else
589
 
        do_copy= do_copy_not_null;
590
 
    }
591
 
  }
592
 
  else if (to_field->real_maybe_null())
593
 
  {
594
 
    to_null_ptr=        to->null_ptr;
595
 
    to_bit=             to->null_bit;
596
 
    do_copy= do_copy_maybe_null;
597
 
  }
598
 
  else
599
 
   do_copy=0;
600
 
 
601
 
  if ((to->flags & BLOB_FLAG) && save)
602
 
    do_copy2= do_save_blob;
603
 
  else
604
 
    do_copy2= get_copy_func(to,from);
605
 
  if (!do_copy)                                 // Not null
606
 
    do_copy=do_copy2;
607
 
}
608
 
 
609
 
 
610
 
Copy_field::Copy_func *
611
 
Copy_field::get_copy_func(Field *to,Field *from)
612
 
{
613
 
  bool compatible_db_low_byte_first= (to->table->s->db_low_byte_first ==
614
 
                                     from->table->s->db_low_byte_first);
615
 
  if (to->flags & BLOB_FLAG)
616
 
  {
617
 
    if (!(from->flags & BLOB_FLAG) || from->charset() != to->charset())
618
 
      return do_conv_blob;
619
 
    if (from_length != to_length || !compatible_db_low_byte_first)
620
 
    {
621
 
      // Correct pointer to point at char pointer
622
 
      to_ptr+=   to_length - to->table->s->blob_ptr_size;
623
 
      from_ptr+= from_length- from->table->s->blob_ptr_size;
624
 
      return do_copy_blob;
625
 
    }
626
 
  }
627
 
  else
628
 
  {
629
 
    if (to->result_type() == DECIMAL_RESULT)
630
 
      return do_field_decimal;
631
 
    // Check if identical fields
632
 
    if (from->result_type() == STRING_RESULT)
633
 
    {
634
 
      /*
635
 
        If we are copying date or datetime's we have to check the dates
636
 
        if we don't allow 'all' dates.
637
 
      */
638
 
      if (to->real_type() != from->real_type() ||
639
 
          !compatible_db_low_byte_first ||
640
 
          (((to->table->in_use->variables.sql_mode & (MODE_NO_ZERO_DATE | MODE_INVALID_DATES)) && to->type() == DRIZZLE_TYPE_NEWDATE) || to->type() == DRIZZLE_TYPE_DATETIME))
641
 
      {
642
 
        if (from->real_type() == DRIZZLE_TYPE_ENUM)
643
 
          if (to->result_type() != STRING_RESULT)
644
 
            return do_field_int;                // Convert SET to number
645
 
        return do_field_string;
646
 
      }
647
 
      if (to->real_type() == DRIZZLE_TYPE_ENUM)
648
 
      {
649
 
        if (!to->eq_def(from))
650
 
        {
651
 
          if (from->real_type() == DRIZZLE_TYPE_ENUM &&
652
 
              to->real_type() == DRIZZLE_TYPE_ENUM)
653
 
            return do_field_enum;
654
 
          else
655
 
            return do_field_string;
656
 
        }
657
 
      }
658
 
      else if (to->charset() != from->charset())
659
 
        return do_field_string;
660
 
      else if (to->real_type() == DRIZZLE_TYPE_VARCHAR)
661
 
      {
662
 
        if (((Field_varstring*) to)->length_bytes !=
663
 
            ((Field_varstring*) from)->length_bytes)
664
 
          return do_field_string;
665
 
        if (to_length != from_length)
666
 
          return (((Field_varstring*) to)->length_bytes == 1 ?
667
 
                  (from->charset()->mbmaxlen == 1 ? do_varstring1 :
668
 
                                                    do_varstring1_mb) :
669
 
                  (from->charset()->mbmaxlen == 1 ? do_varstring2 :
670
 
                                                    do_varstring2_mb));
671
 
      }
672
 
      else if (to_length < from_length)
673
 
        return (from->charset()->mbmaxlen == 1 ?
674
 
                do_cut_string : do_cut_string_complex);
675
 
      else if (to_length > from_length)
676
 
      {
677
 
        if (to->charset() == &my_charset_bin)
678
 
          return do_expand_binary;
679
 
        else
680
 
          return do_expand_string;
681
 
      }
682
 
 
683
 
    }
684
 
    else if (to->real_type() != from->real_type() ||
685
 
             to_length != from_length ||
686
 
             !compatible_db_low_byte_first)
687
 
    {
688
 
      if (to->result_type() == STRING_RESULT)
689
 
        return do_field_string;
690
 
      if (to->result_type() == INT_RESULT)
691
 
        return do_field_int;
692
 
      return do_field_real;
693
 
    }
694
 
    else
695
 
    {
696
 
      if (!to->eq_def(from) || !compatible_db_low_byte_first)
697
 
      {
698
 
        if (to->result_type() == INT_RESULT)
699
 
          return do_field_int;
700
 
        else
701
 
          return do_field_real;
702
 
      }
703
 
    }
704
 
  }
705
 
    /* Eq fields */
706
 
  switch (to_length) {
707
 
  case 1: return do_field_1;
708
 
  case 2: return do_field_2;
709
 
  case 3: return do_field_3;
710
 
  case 4: return do_field_4;
711
 
  case 6: return do_field_6;
712
 
  case 8: return do_field_8;
713
 
  }
714
 
  return do_field_eq;
715
 
}
716
 
 
717
 
 
718
 
/** Simple quick field convert that is called on insert. */
719
 
 
720
 
int field_conv(Field *to,Field *from)
721
 
{
722
 
  if (to->real_type() == from->real_type() &&
723
 
      !(to->type() == DRIZZLE_TYPE_BLOB && to->table->copy_blobs))
724
 
  {
725
 
    /* Please god, will someone rewrite this to be readable :( */
726
 
    if (to->pack_length() == from->pack_length() && 
727
 
        !(to->flags & UNSIGNED_FLAG && !(from->flags & UNSIGNED_FLAG)) && 
728
 
        to->real_type() != DRIZZLE_TYPE_ENUM && 
729
 
        (to->real_type() != DRIZZLE_TYPE_NEWDECIMAL || (to->field_length == from->field_length && (((Field_num*)to)->dec == ((Field_num*)from)->dec))) &&
730
 
        from->charset() == to->charset() &&
731
 
        to->table->s->db_low_byte_first == from->table->s->db_low_byte_first &&
732
 
        (!(to->table->in_use->variables.sql_mode & (MODE_NO_ZERO_DATE | MODE_INVALID_DATES)) || (to->type() != DRIZZLE_TYPE_NEWDATE && to->type() != DRIZZLE_TYPE_DATETIME)) && 
733
 
        (from->real_type() != DRIZZLE_TYPE_VARCHAR || ((Field_varstring*)from)->length_bytes == ((Field_varstring*)to)->length_bytes))
734
 
    {                                           // Identical fields
735
 
#ifdef HAVE_purify
736
 
      /* This may happen if one does 'UPDATE ... SET x=x' */
737
 
      if (to->ptr != from->ptr)
738
 
#endif
739
 
        memcpy(to->ptr,from->ptr,to->pack_length());
740
 
      return 0;
741
 
    }
742
 
  }
743
 
  if (to->type() == DRIZZLE_TYPE_BLOB)
744
 
  {                                             // Be sure the value is stored
745
 
    Field_blob *blob=(Field_blob*) to;
746
 
    from->val_str(&blob->value);
747
 
    /*
748
 
      Copy value if copy_blobs is set, or source is not a string and
749
 
      we have a pointer to its internal string conversion buffer.
750
 
    */
751
 
    if (to->table->copy_blobs ||
752
 
        (!blob->value.is_alloced() &&
753
 
         from->real_type() != DRIZZLE_TYPE_VARCHAR))
754
 
      blob->value.copy();
755
 
    return blob->store(blob->value.ptr(),blob->value.length(),from->charset());
756
 
  }
757
 
  if (from->real_type() == DRIZZLE_TYPE_ENUM &&
758
 
      to->real_type() == DRIZZLE_TYPE_ENUM &&
759
 
      from->val_int() == 0)
760
 
  {
761
 
    ((Field_enum *)(to))->store_type(0);
762
 
    return 0;
763
 
  }
764
 
  else if ((from->result_type() == STRING_RESULT &&
765
 
            (to->result_type() == STRING_RESULT ||
766
 
             (from->real_type() != DRIZZLE_TYPE_ENUM))))
767
 
  {
768
 
    char buff[MAX_FIELD_WIDTH];
769
 
    String result(buff,sizeof(buff),from->charset());
770
 
    from->val_str(&result);
771
 
    /*
772
 
      We use c_ptr_quick() here to make it easier if to is a float/double
773
 
      as the conversion routines will do a copy of the result doesn't
774
 
      end with \0. Can be replaced with .ptr() when we have our own
775
 
      string->double conversion.
776
 
    */
777
 
    return to->store(result.c_ptr_quick(),result.length(),from->charset());
778
 
  }
779
 
  else if (from->result_type() == REAL_RESULT)
780
 
    return to->store(from->val_real());
781
 
  else if (from->result_type() == DECIMAL_RESULT)
782
 
  {
783
 
    my_decimal buff;
784
 
    return to->store_decimal(from->val_decimal(&buff));
785
 
  }
786
 
  else
787
 
    return to->store(from->val_int(), test(from->flags & UNSIGNED_FLAG));
788
 
}