~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to sql/field_conv.cc

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

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