~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
243.1.17 by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.)
27
#include <drizzled/server_includes.h>
1 by brian
clean slate
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
  {
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
126
    field->set_warning(DRIZZLE_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
  {
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
182
    field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_BAD_NULL_ERROR, 1);
1 by brian
clean slate
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
  {
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
231
    copy->to_field->set_warning(DRIZZLE_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_int(Copy_field *copy)
322
{
152 by Brian Aker
longlong replacement
323
  int64_t value= copy->from_field->val_int();
1 by brian
clean slate
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
{
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
349
  const CHARSET_INFO * const cs= copy->from_field->charset();
1 by brian
clean slate
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
  {
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
358
    copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
212.5.42 by Monty Taylor
Ding dong include is dead.
359
                                ER_WARN_DATA_TRUNCATED, 1);
1 by brian
clean slate
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;
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
372
  const CHARSET_INFO * const cs= copy->from_field->charset();
1 by brian
clean slate
373
  const uchar *from_end= copy->from_ptr + copy->from_length;
374
  uint 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
  {
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
389
    copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
212.5.42 by Monty Taylor
Ding dong include is dead.
390
                                ER_WARN_DATA_TRUNCATED, 1);
1 by brian
clean slate
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
{
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
403
  const CHARSET_INFO * const cs= copy->from_field->charset();
1 by brian
clean slate
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
{
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
413
  const CHARSET_INFO * const cs= copy->from_field->charset();
1 by brian
clean slate
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
  uint length= (uint) *(uchar*) 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)
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
427
      copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
212.5.42 by Monty Taylor
Ding dong include is dead.
428
                                  ER_WARN_DATA_TRUNCATED, 1);
1 by brian
clean slate
429
  }
430
  *(uchar*) copy->to_ptr= (uchar) 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;
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
438
  const CHARSET_INFO * const cs= copy->from_field->charset();
1 by brian
clean slate
439
  uint from_length= (uint) *(uchar*) copy->from_ptr;
440
  const uchar *from_ptr= copy->from_ptr + 1;
441
  uint to_char_length= (copy->to_length - 1) / cs->mbmaxlen;
442
  uint 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)
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
448
      copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
212.5.42 by Monty Taylor
Ding dong include is dead.
449
                                  ER_WARN_DATA_TRUNCATED, 1);
1 by brian
clean slate
450
  }
451
  *copy->to_ptr= (uchar) length;
452
  memcpy(copy->to_ptr + 1, from_ptr, length);
453
}
454
455
456
static void do_varstring2(Copy_field *copy)
457
{
458
  uint 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)
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
463
      copy->to_field->set_warning(DRIZZLE_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
  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;
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
475
  const CHARSET_INFO * const cs= copy->from_field->charset();
1 by brian
clean slate
476
  uint char_length= (copy->to_length - HA_KEY_BLOB_LENGTH) / cs->mbmaxlen;
477
  uint from_length= uint2korr(copy->from_ptr);
478
  const uchar *from_beg= copy->from_ptr + HA_KEY_BLOB_LENGTH;
479
  uint 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)
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
485
      copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
212.5.42 by Monty Taylor
Ding dong include is dead.
486
                                  ER_WARN_DATA_TRUNCATED, 1);
1 by brian
clean slate
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(uchar *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=  (uchar*) 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
{
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
550
  if (to->type() == DRIZZLE_TYPE_NULL)
1 by brian
clean slate
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
    {
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
584
      if (to_field->type() == DRIZZLE_TYPE_TIMESTAMP)
1 by brian
clean slate
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 ||
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
640
          (((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
641
      {
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
642
	if (from->real_type() == DRIZZLE_TYPE_ENUM ||
643
	    from->real_type() == DRIZZLE_TYPE_SET)
1 by brian
clean slate
644
	  if (to->result_type() != STRING_RESULT)
645
	    return do_field_int;		// Convert SET to number
646
	return do_field_string;
647
      }
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
648
      if (to->real_type() == DRIZZLE_TYPE_ENUM ||
649
	  to->real_type() == DRIZZLE_TYPE_SET)
1 by brian
clean slate
650
      {
651
	if (!to->eq_def(from))
652
        {
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
653
          if (from->real_type() == DRIZZLE_TYPE_ENUM &&
654
              to->real_type() == DRIZZLE_TYPE_ENUM)
1 by brian
clean slate
655
            return do_field_enum;
656
          else
657
            return do_field_string;
658
        }
659
      }
660
      else if (to->charset() != from->charset())
661
	return do_field_string;
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
662
      else if (to->real_type() == DRIZZLE_TYPE_VARCHAR)
1 by brian
clean slate
663
      {
664
        if (((Field_varstring*) to)->length_bytes !=
665
            ((Field_varstring*) from)->length_bytes)
666
          return do_field_string;
667
        if (to_length != from_length)
668
          return (((Field_varstring*) to)->length_bytes == 1 ?
669
                  (from->charset()->mbmaxlen == 1 ? do_varstring1 :
670
                                                    do_varstring1_mb) :
671
                  (from->charset()->mbmaxlen == 1 ? do_varstring2 :
672
                                                    do_varstring2_mb));
673
      }
674
      else if (to_length < from_length)
675
	return (from->charset()->mbmaxlen == 1 ?
676
                do_cut_string : do_cut_string_complex);
677
      else if (to_length > from_length)
678
      {
679
        if (to->charset() == &my_charset_bin)
680
          return do_expand_binary;
681
        else
682
          return do_expand_string;
683
      }
684
685
    }
686
    else if (to->real_type() != from->real_type() ||
687
	     to_length != from_length ||
688
             !compatible_db_low_byte_first)
689
    {
80 by Brian Aker
Most of the removal of dead DECIMAL type
690
      if (to->result_type() == STRING_RESULT)
1 by brian
clean slate
691
	return do_field_string;
692
      if (to->result_type() == INT_RESULT)
693
	return do_field_int;
694
      return do_field_real;
695
    }
696
    else
697
    {
698
      if (!to->eq_def(from) || !compatible_db_low_byte_first)
699
      {
700
	if (to->result_type() == INT_RESULT)
701
	  return do_field_int;
702
	else
703
	  return do_field_real;
704
      }
705
    }
706
  }
707
    /* Eq fields */
708
  switch (to_length) {
709
  case 1: return do_field_1;
710
  case 2: return do_field_2;
711
  case 3: return do_field_3;
712
  case 4: return do_field_4;
713
  case 6: return do_field_6;
714
  case 8: return do_field_8;
715
  }
716
  return do_field_eq;
717
}
718
719
720
/** Simple quick field convert that is called on insert. */
721
722
int field_conv(Field *to,Field *from)
723
{
724
  if (to->real_type() == from->real_type() &&
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
725
      !(to->type() == DRIZZLE_TYPE_BLOB && to->table->copy_blobs))
1 by brian
clean slate
726
  {
727
    /* Please god, will someone rewrite this to be readable :( */
728
    if (to->pack_length() == from->pack_length() && 
729
        !(to->flags & UNSIGNED_FLAG && !(from->flags & UNSIGNED_FLAG)) && 
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
730
        to->real_type() != DRIZZLE_TYPE_ENUM && 
731
        to->real_type() != DRIZZLE_TYPE_SET &&
732
        (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
733
        from->charset() == to->charset() &&
734
	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
735
        (!(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)) && 
736
        (from->real_type() != DRIZZLE_TYPE_VARCHAR || ((Field_varstring*)from)->length_bytes == ((Field_varstring*)to)->length_bytes))
1 by brian
clean slate
737
    {						// Identical fields
738
#ifdef HAVE_purify
739
      /* This may happen if one does 'UPDATE ... SET x=x' */
740
      if (to->ptr != from->ptr)
741
#endif
742
        memcpy(to->ptr,from->ptr,to->pack_length());
743
      return 0;
744
    }
745
  }
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
746
  if (to->type() == DRIZZLE_TYPE_BLOB)
1 by brian
clean slate
747
  {						// Be sure the value is stored
748
    Field_blob *blob=(Field_blob*) to;
749
    from->val_str(&blob->value);
750
    /*
751
      Copy value if copy_blobs is set, or source is not a string and
752
      we have a pointer to its internal string conversion buffer.
753
    */
754
    if (to->table->copy_blobs ||
755
        (!blob->value.is_alloced() &&
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
756
         from->real_type() != DRIZZLE_TYPE_VARCHAR))
1 by brian
clean slate
757
      blob->value.copy();
758
    return blob->store(blob->value.ptr(),blob->value.length(),from->charset());
759
  }
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
760
  if (from->real_type() == DRIZZLE_TYPE_ENUM &&
761
      to->real_type() == DRIZZLE_TYPE_ENUM &&
1 by brian
clean slate
762
      from->val_int() == 0)
763
  {
764
    ((Field_enum *)(to))->store_type(0);
765
    return 0;
766
  }
767
  else if ((from->result_type() == STRING_RESULT &&
768
            (to->result_type() == STRING_RESULT ||
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
769
             (from->real_type() != DRIZZLE_TYPE_ENUM &&
770
              from->real_type() != DRIZZLE_TYPE_SET))))
1 by brian
clean slate
771
  {
772
    char buff[MAX_FIELD_WIDTH];
773
    String result(buff,sizeof(buff),from->charset());
774
    from->val_str(&result);
775
    /*
776
      We use c_ptr_quick() here to make it easier if to is a float/double
777
      as the conversion routines will do a copy of the result doesn't
778
      end with \0. Can be replaced with .ptr() when we have our own
779
      string->double conversion.
780
    */
781
    return to->store(result.c_ptr_quick(),result.length(),from->charset());
782
  }
783
  else if (from->result_type() == REAL_RESULT)
784
    return to->store(from->val_real());
785
  else if (from->result_type() == DECIMAL_RESULT)
786
  {
787
    my_decimal buff;
788
    return to->store_decimal(from->val_decimal(&buff));
789
  }
790
  else
791
    return to->store(from->val_int(), test(from->flags & UNSIGNED_FLAG));
792
}