~drizzle-trunk/drizzle/development

1 by brian
clean slate
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
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
  {
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
87
    memset(copy->to_ptr, 0, copy->from_length);
1 by brian
clean slate
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
  {
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
103
    memset(copy->to_ptr, 0, copy->from_length);
1 by brian
clean slate
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
  {
212.5.42 by Monty Taylor
Ding dong include is dead.
126
    field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
1 by brian
clean slate
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
  */
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
169
  if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
1 by brian
clean slate
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
  {
163 by Brian Aker
Merge Monty's code.
177
    field->table->auto_increment_field_not_null= false;
1 by brian
clean slate
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(MYSQL_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(MYSQL_ERROR::WARN_LEVEL_WARN,
212.5.42 by Monty Taylor
Ding dong include is dead.
232
                                ER_WARN_DATA_TRUNCATED, 1);
1 by brian
clean slate
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() */
163 by Brian Aker
Merge Monty's code.
265
    copy->to_field->table->auto_increment_field_not_null= false;
1 by brian
clean slate
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);
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
277
  memcpy(copy->to_ptr,copy->from_ptr,sizeof(char*));
1 by brian
clean slate
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)
151 by Brian Aker
Ulonglong to uint64_t
315
    ((Field_enum *) copy->to_field)->store_type((uint64_t) 0);
1 by brian
clean slate
316
  else
317
    do_field_string(copy);
318
}
319
320
321
static void do_field_varbinary_pre50(Copy_field *copy)
322
{
323
  char buff[MAX_FIELD_WIDTH];
324
  copy->tmp.set_quick(buff,sizeof(buff),copy->tmp.charset());
325
  copy->from_field->val_str(&copy->tmp);
326
327
  /* Use the same function as in 4.1 to trim trailing spaces */
328
  uint length= my_lengthsp_8bit(&my_charset_bin, copy->tmp.c_ptr_quick(),
329
                                copy->from_field->field_length);
330
331
  copy->to_field->store(copy->tmp.c_ptr_quick(), length,
332
                        copy->tmp.charset());
333
}
334
335
336
static void do_field_int(Copy_field *copy)
337
{
152 by Brian Aker
longlong replacement
338
  int64_t value= copy->from_field->val_int();
1 by brian
clean slate
339
  copy->to_field->store(value,
340
                        test(copy->from_field->flags & UNSIGNED_FLAG));
341
}
342
343
static void do_field_real(Copy_field *copy)
344
{
345
  double value=copy->from_field->val_real();
346
  copy->to_field->store(value);
347
}
348
349
350
static void do_field_decimal(Copy_field *copy)
351
{
352
  my_decimal value;
353
  copy->to_field->store_decimal(copy->from_field->val_decimal(&value));
354
}
355
356
357
/**
358
  string copy for single byte characters set when to string is shorter than
359
  from string.
360
*/
361
362
static void do_cut_string(Copy_field *copy)
363
{
364
  CHARSET_INFO *cs= copy->from_field->charset();
365
  memcpy(copy->to_ptr,copy->from_ptr,copy->to_length);
366
367
  /* Check if we loosed any important characters */
368
  if (cs->cset->scan(cs,
369
                     (char*) copy->from_ptr + copy->to_length,
370
                     (char*) copy->from_ptr + copy->from_length,
371
                     MY_SEQ_SPACES) < copy->from_length - copy->to_length)
372
  {
373
    copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
212.5.42 by Monty Taylor
Ding dong include is dead.
374
                                ER_WARN_DATA_TRUNCATED, 1);
1 by brian
clean slate
375
  }
376
}
377
378
379
/**
380
  string copy for multi byte characters set when to string is shorter than
381
  from string.
382
*/
383
384
static void do_cut_string_complex(Copy_field *copy)
385
{						// Shorter string field
386
  int well_formed_error;
387
  CHARSET_INFO *cs= copy->from_field->charset();
388
  const uchar *from_end= copy->from_ptr + copy->from_length;
389
  uint copy_length= cs->cset->well_formed_len(cs,
390
                                              (char*) copy->from_ptr,
391
                                              (char*) from_end, 
392
                                              copy->to_length / cs->mbmaxlen,
393
                                              &well_formed_error);
394
  if (copy->to_length < copy_length)
395
    copy_length= copy->to_length;
396
  memcpy(copy->to_ptr, copy->from_ptr, copy_length);
397
398
  /* Check if we lost any important characters */
399
  if (well_formed_error ||
400
      cs->cset->scan(cs, (char*) copy->from_ptr + copy_length,
401
                     (char*) from_end,
402
                     MY_SEQ_SPACES) < (copy->from_length - copy_length))
403
  {
404
    copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
212.5.42 by Monty Taylor
Ding dong include is dead.
405
                                ER_WARN_DATA_TRUNCATED, 1);
1 by brian
clean slate
406
  }
407
408
  if (copy_length < copy->to_length)
409
    cs->cset->fill(cs, (char*) copy->to_ptr + copy_length,
410
                   copy->to_length - copy_length, ' ');
411
}
412
413
414
415
416
static void do_expand_binary(Copy_field *copy)
417
{
418
  CHARSET_INFO *cs= copy->from_field->charset();
419
  memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
420
  cs->cset->fill(cs, (char*) copy->to_ptr+copy->from_length,
421
                     copy->to_length-copy->from_length, '\0');
422
}
423
424
425
426
static void do_expand_string(Copy_field *copy)
427
{
428
  CHARSET_INFO *cs= copy->from_field->charset();
429
  memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
430
  cs->cset->fill(cs, (char*) copy->to_ptr+copy->from_length,
431
                     copy->to_length-copy->from_length, ' ');
432
}
433
434
435
static void do_varstring1(Copy_field *copy)
436
{
437
  uint length= (uint) *(uchar*) copy->from_ptr;
438
  if (length > copy->to_length- 1)
439
  {
440
    length=copy->to_length - 1;
441
    if (copy->from_field->table->in_use->count_cuted_fields)
442
      copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
212.5.42 by Monty Taylor
Ding dong include is dead.
443
                                  ER_WARN_DATA_TRUNCATED, 1);
1 by brian
clean slate
444
  }
445
  *(uchar*) copy->to_ptr= (uchar) length;
446
  memcpy(copy->to_ptr+1, copy->from_ptr + 1, length);
447
}
448
449
450
static void do_varstring1_mb(Copy_field *copy)
451
{
452
  int well_formed_error;
453
  CHARSET_INFO *cs= copy->from_field->charset();
454
  uint from_length= (uint) *(uchar*) copy->from_ptr;
455
  const uchar *from_ptr= copy->from_ptr + 1;
456
  uint to_char_length= (copy->to_length - 1) / cs->mbmaxlen;
457
  uint length= cs->cset->well_formed_len(cs, (char*) from_ptr,
458
                                         (char*) from_ptr + from_length,
459
                                         to_char_length, &well_formed_error);
460
  if (length < from_length)
461
  {
462
    if (current_thd->count_cuted_fields)
463
      copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
212.5.42 by Monty Taylor
Ding dong include is dead.
464
                                  ER_WARN_DATA_TRUNCATED, 1);
1 by brian
clean slate
465
  }
466
  *copy->to_ptr= (uchar) length;
467
  memcpy(copy->to_ptr + 1, from_ptr, length);
468
}
469
470
471
static void do_varstring2(Copy_field *copy)
472
{
473
  uint length=uint2korr(copy->from_ptr);
474
  if (length > copy->to_length- HA_KEY_BLOB_LENGTH)
475
  {
476
    length=copy->to_length-HA_KEY_BLOB_LENGTH;
477
    if (copy->from_field->table->in_use->count_cuted_fields)
478
      copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
212.5.42 by Monty Taylor
Ding dong include is dead.
479
                                  ER_WARN_DATA_TRUNCATED, 1);
1 by brian
clean slate
480
  }
481
  int2store(copy->to_ptr,length);
482
  memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, copy->from_ptr + HA_KEY_BLOB_LENGTH,
483
         length);
484
}
485
486
487
static void do_varstring2_mb(Copy_field *copy)
488
{
489
  int well_formed_error;
490
  CHARSET_INFO *cs= copy->from_field->charset();
491
  uint char_length= (copy->to_length - HA_KEY_BLOB_LENGTH) / cs->mbmaxlen;
492
  uint from_length= uint2korr(copy->from_ptr);
493
  const uchar *from_beg= copy->from_ptr + HA_KEY_BLOB_LENGTH;
494
  uint length= cs->cset->well_formed_len(cs, (char*) from_beg,
495
                                         (char*) from_beg + from_length,
496
                                         char_length, &well_formed_error);
497
  if (length < from_length)
498
  {
499
    if (current_thd->count_cuted_fields)
500
      copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
212.5.42 by Monty Taylor
Ding dong include is dead.
501
                                  ER_WARN_DATA_TRUNCATED, 1);
1 by brian
clean slate
502
  }  
503
  int2store(copy->to_ptr, length);
504
  memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, from_beg, length);
505
}
506
 
507
508
/***************************************************************************
509
** The different functions that fills in a Copy_field class
510
***************************************************************************/
511
512
/**
513
  copy of field to maybe null string.
514
  If field is null then the all bytes are set to 0.
515
  if field is not null then the first byte is set to 1 and the rest of the
516
  string is the field value.
517
  The 'to' buffer should have a size of field->pack_length()+1
518
*/
519
520
void Copy_field::set(uchar *to,Field *from)
521
{
522
  from_ptr=from->ptr;
523
  to_ptr=to;
524
  from_length=from->pack_length();
525
  if (from->maybe_null())
526
  {
527
    from_null_ptr=from->null_ptr;
528
    from_bit=	  from->null_bit;
529
    to_ptr[0]=	  1;				// Null as default value
530
    to_null_ptr=  (uchar*) to_ptr++;
531
    to_bit=	  1;
532
    if (from->table->maybe_null)
533
    {
534
      null_row=   &from->table->null_row;
535
      do_copy=	  do_outer_field_to_null_str;
536
    }
537
    else
538
      do_copy=	  do_field_to_null_str;
539
  }
540
  else
541
  {
542
    to_null_ptr=  0;				// For easy debugging
543
    do_copy=	  do_field_eq;
544
  }
545
}
546
547
548
/*
549
  To do: 
550
551
  If 'save\ is set to true and the 'from' is a blob field, do_copy is set to
552
  do_save_blob rather than do_conv_blob.  The only differences between them
553
  appears to be:
554
555
  - do_save_blob allocates and uses an intermediate buffer before calling 
556
    Field_blob::store. Is this in order to trigger the call to 
557
    well_formed_copy_nchars, by changing the pointer copy->tmp.ptr()?
558
    That call will take place anyway in all known cases.
559
560
  - The above causes a truncation to MAX_FIELD_WIDTH. Is this the intended 
561
    effect? Truncation is handled by well_formed_copy_nchars anyway.
562
 */
563
void Copy_field::set(Field *to,Field *from,bool save)
564
{
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
565
  if (to->type() == DRIZZLE_TYPE_NULL)
1 by brian
clean slate
566
  {
567
    to_null_ptr=0;				// For easy debugging
568
    to_ptr=0;
569
    do_copy=do_skip;
570
    return;
571
  }
572
  from_field=from;
573
  to_field=to;
574
  from_ptr=from->ptr;
575
  from_length=from->pack_length();
576
  to_ptr=  to->ptr;
577
  to_length=to_field->pack_length();
578
579
  // set up null handling
580
  from_null_ptr=to_null_ptr=0;
581
  if (from->maybe_null())
582
  {
583
    from_null_ptr=	from->null_ptr;
584
    from_bit=		from->null_bit;
585
    if (to_field->real_maybe_null())
586
    {
587
      to_null_ptr=	to->null_ptr;
588
      to_bit=		to->null_bit;
589
      if (from_null_ptr)
590
	do_copy=	do_copy_null;
591
      else
592
      {
593
	null_row=	&from->table->null_row;
594
	do_copy=	do_outer_field_null;
595
      }
596
    }
597
    else
598
    {
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
599
      if (to_field->type() == DRIZZLE_TYPE_TIMESTAMP)
1 by brian
clean slate
600
        do_copy= do_copy_timestamp;               // Automatic timestamp
601
      else if (to_field == to_field->table->next_number_field)
602
        do_copy= do_copy_next_number;
603
      else
604
        do_copy= do_copy_not_null;
605
    }
606
  }
607
  else if (to_field->real_maybe_null())
608
  {
609
    to_null_ptr=	to->null_ptr;
610
    to_bit=		to->null_bit;
611
    do_copy= do_copy_maybe_null;
612
  }
613
  else
614
   do_copy=0;
615
616
  if ((to->flags & BLOB_FLAG) && save)
617
    do_copy2= do_save_blob;
618
  else
619
    do_copy2= get_copy_func(to,from);
620
  if (!do_copy)					// Not null
621
    do_copy=do_copy2;
622
}
623
624
625
Copy_field::Copy_func *
626
Copy_field::get_copy_func(Field *to,Field *from)
627
{
628
  bool compatible_db_low_byte_first= (to->table->s->db_low_byte_first ==
629
                                     from->table->s->db_low_byte_first);
630
  if (to->flags & BLOB_FLAG)
631
  {
632
    if (!(from->flags & BLOB_FLAG) || from->charset() != to->charset())
633
      return do_conv_blob;
634
    if (from_length != to_length || !compatible_db_low_byte_first)
635
    {
636
      // Correct pointer to point at char pointer
637
      to_ptr+=   to_length - to->table->s->blob_ptr_size;
638
      from_ptr+= from_length- from->table->s->blob_ptr_size;
639
      return do_copy_blob;
640
    }
641
  }
642
  else
643
  {
644
    if (to->result_type() == DECIMAL_RESULT)
645
      return do_field_decimal;
646
    // Check if identical fields
647
    if (from->result_type() == STRING_RESULT)
648
    {
649
      /*
650
        Detect copy from pre 5.0 varbinary to varbinary as of 5.0 and
651
        use special copy function that removes trailing spaces and thus
652
        repairs data.
653
      */
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
654
      if (from->type() == DRIZZLE_TYPE_VAR_STRING && !from->has_charset() &&
655
          to->type() == DRIZZLE_TYPE_VARCHAR && !to->has_charset())
1 by brian
clean slate
656
        return do_field_varbinary_pre50;
657
658
      /*
659
        If we are copying date or datetime's we have to check the dates
660
        if we don't allow 'all' dates.
661
      */
662
      if (to->real_type() != from->real_type() ||
663
          !compatible_db_low_byte_first ||
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
664
          (((to->table->in_use->variables.sql_mode & (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | MODE_INVALID_DATES)) && to->type() == DRIZZLE_TYPE_NEWDATE) || to->type() == DRIZZLE_TYPE_DATETIME))
1 by brian
clean slate
665
      {
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
666
	if (from->real_type() == DRIZZLE_TYPE_ENUM ||
667
	    from->real_type() == DRIZZLE_TYPE_SET)
1 by brian
clean slate
668
	  if (to->result_type() != STRING_RESULT)
669
	    return do_field_int;		// Convert SET to number
670
	return do_field_string;
671
      }
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
672
      if (to->real_type() == DRIZZLE_TYPE_ENUM ||
673
	  to->real_type() == DRIZZLE_TYPE_SET)
1 by brian
clean slate
674
      {
675
	if (!to->eq_def(from))
676
        {
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
677
          if (from->real_type() == DRIZZLE_TYPE_ENUM &&
678
              to->real_type() == DRIZZLE_TYPE_ENUM)
1 by brian
clean slate
679
            return do_field_enum;
680
          else
681
            return do_field_string;
682
        }
683
      }
684
      else if (to->charset() != from->charset())
685
	return do_field_string;
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
686
      else if (to->real_type() == DRIZZLE_TYPE_VARCHAR)
1 by brian
clean slate
687
      {
688
        if (((Field_varstring*) to)->length_bytes !=
689
            ((Field_varstring*) from)->length_bytes)
690
          return do_field_string;
691
        if (to_length != from_length)
692
          return (((Field_varstring*) to)->length_bytes == 1 ?
693
                  (from->charset()->mbmaxlen == 1 ? do_varstring1 :
694
                                                    do_varstring1_mb) :
695
                  (from->charset()->mbmaxlen == 1 ? do_varstring2 :
696
                                                    do_varstring2_mb));
697
      }
698
      else if (to_length < from_length)
699
	return (from->charset()->mbmaxlen == 1 ?
700
                do_cut_string : do_cut_string_complex);
701
      else if (to_length > from_length)
702
      {
703
        if (to->charset() == &my_charset_bin)
704
          return do_expand_binary;
705
        else
706
          return do_expand_string;
707
      }
708
709
    }
710
    else if (to->real_type() != from->real_type() ||
711
	     to_length != from_length ||
712
             !compatible_db_low_byte_first)
713
    {
80 by Brian Aker
Most of the removal of dead DECIMAL type
714
      if (to->result_type() == STRING_RESULT)
1 by brian
clean slate
715
	return do_field_string;
716
      if (to->result_type() == INT_RESULT)
717
	return do_field_int;
718
      return do_field_real;
719
    }
720
    else
721
    {
722
      if (!to->eq_def(from) || !compatible_db_low_byte_first)
723
      {
724
	if (to->result_type() == INT_RESULT)
725
	  return do_field_int;
726
	else
727
	  return do_field_real;
728
      }
729
    }
730
  }
731
    /* Eq fields */
732
  switch (to_length) {
733
  case 1: return do_field_1;
734
  case 2: return do_field_2;
735
  case 3: return do_field_3;
736
  case 4: return do_field_4;
737
  case 6: return do_field_6;
738
  case 8: return do_field_8;
739
  }
740
  return do_field_eq;
741
}
742
743
744
/** Simple quick field convert that is called on insert. */
745
746
int field_conv(Field *to,Field *from)
747
{
748
  if (to->real_type() == from->real_type() &&
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
749
      !(to->type() == DRIZZLE_TYPE_BLOB && to->table->copy_blobs))
1 by brian
clean slate
750
  {
751
    /* Please god, will someone rewrite this to be readable :( */
752
    if (to->pack_length() == from->pack_length() && 
753
        !(to->flags & UNSIGNED_FLAG && !(from->flags & UNSIGNED_FLAG)) && 
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
754
        to->real_type() != DRIZZLE_TYPE_ENUM && 
755
        to->real_type() != DRIZZLE_TYPE_SET &&
756
        (to->real_type() != DRIZZLE_TYPE_NEWDECIMAL || (to->field_length == from->field_length && (((Field_num*)to)->dec == ((Field_num*)from)->dec))) &&
1 by brian
clean slate
757
        from->charset() == to->charset() &&
758
	to->table->s->db_low_byte_first == from->table->s->db_low_byte_first &&
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
759
        (!(to->table->in_use->variables.sql_mode & (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | MODE_INVALID_DATES)) || (to->type() != DRIZZLE_TYPE_NEWDATE && to->type() != DRIZZLE_TYPE_DATETIME)) && 
760
        (from->real_type() != DRIZZLE_TYPE_VARCHAR || ((Field_varstring*)from)->length_bytes == ((Field_varstring*)to)->length_bytes))
1 by brian
clean slate
761
    {						// Identical fields
762
#ifdef HAVE_purify
763
      /* This may happen if one does 'UPDATE ... SET x=x' */
764
      if (to->ptr != from->ptr)
765
#endif
766
        memcpy(to->ptr,from->ptr,to->pack_length());
767
      return 0;
768
    }
769
  }
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
770
  if (to->type() == DRIZZLE_TYPE_BLOB)
1 by brian
clean slate
771
  {						// Be sure the value is stored
772
    Field_blob *blob=(Field_blob*) to;
773
    from->val_str(&blob->value);
774
    /*
775
      Copy value if copy_blobs is set, or source is not a string and
776
      we have a pointer to its internal string conversion buffer.
777
    */
778
    if (to->table->copy_blobs ||
779
        (!blob->value.is_alloced() &&
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
780
         from->real_type() != DRIZZLE_TYPE_STRING &&
781
         from->real_type() != DRIZZLE_TYPE_VARCHAR))
1 by brian
clean slate
782
      blob->value.copy();
783
    return blob->store(blob->value.ptr(),blob->value.length(),from->charset());
784
  }
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
785
  if (from->real_type() == DRIZZLE_TYPE_ENUM &&
786
      to->real_type() == DRIZZLE_TYPE_ENUM &&
1 by brian
clean slate
787
      from->val_int() == 0)
788
  {
789
    ((Field_enum *)(to))->store_type(0);
790
    return 0;
791
  }
792
  else if ((from->result_type() == STRING_RESULT &&
793
            (to->result_type() == STRING_RESULT ||
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
794
             (from->real_type() != DRIZZLE_TYPE_ENUM &&
795
              from->real_type() != DRIZZLE_TYPE_SET))))
1 by brian
clean slate
796
  {
797
    char buff[MAX_FIELD_WIDTH];
798
    String result(buff,sizeof(buff),from->charset());
799
    from->val_str(&result);
800
    /*
801
      We use c_ptr_quick() here to make it easier if to is a float/double
802
      as the conversion routines will do a copy of the result doesn't
803
      end with \0. Can be replaced with .ptr() when we have our own
804
      string->double conversion.
805
    */
806
    return to->store(result.c_ptr_quick(),result.length(),from->charset());
807
  }
808
  else if (from->result_type() == REAL_RESULT)
809
    return to->store(from->val_real());
810
  else if (from->result_type() == DECIMAL_RESULT)
811
  {
812
    my_decimal buff;
813
    return to->store_decimal(from->val_decimal(&buff));
814
  }
815
  else
816
    return to->store(from->val_int(), test(from->flags & UNSIGNED_FLAG));
817
}