1/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
2 Copyright (c) 2010, 2016, MariaDB
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16
17
18/**
19 @file
20
21 @brief
22 Functions to copy data to or from fields
23
24 This could be done with a single short function but opencoding this
25 gives much more speed.
26*/
27
28#include "mariadb.h"
29#include "sql_priv.h"
30#include "sql_class.h" // THD
31#include <m_ctype.h>
32
33static void do_field_eq(Copy_field *copy)
34{
35 memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
36}
37
38static void do_field_1(Copy_field *copy)
39{
40 copy->to_ptr[0]=copy->from_ptr[0];
41}
42
43static void do_field_2(Copy_field *copy)
44{
45 copy->to_ptr[0]=copy->from_ptr[0];
46 copy->to_ptr[1]=copy->from_ptr[1];
47}
48
49static void do_field_3(Copy_field *copy)
50{
51 copy->to_ptr[0]=copy->from_ptr[0];
52 copy->to_ptr[1]=copy->from_ptr[1];
53 copy->to_ptr[2]=copy->from_ptr[2];
54}
55
56static void do_field_4(Copy_field *copy)
57{
58 copy->to_ptr[0]=copy->from_ptr[0];
59 copy->to_ptr[1]=copy->from_ptr[1];
60 copy->to_ptr[2]=copy->from_ptr[2];
61 copy->to_ptr[3]=copy->from_ptr[3];
62}
63
64static void do_field_6(Copy_field *copy)
65{ // For blob field
66 copy->to_ptr[0]=copy->from_ptr[0];
67 copy->to_ptr[1]=copy->from_ptr[1];
68 copy->to_ptr[2]=copy->from_ptr[2];
69 copy->to_ptr[3]=copy->from_ptr[3];
70 copy->to_ptr[4]=copy->from_ptr[4];
71 copy->to_ptr[5]=copy->from_ptr[5];
72}
73
74static void do_field_8(Copy_field *copy)
75{
76 copy->to_ptr[0]=copy->from_ptr[0];
77 copy->to_ptr[1]=copy->from_ptr[1];
78 copy->to_ptr[2]=copy->from_ptr[2];
79 copy->to_ptr[3]=copy->from_ptr[3];
80 copy->to_ptr[4]=copy->from_ptr[4];
81 copy->to_ptr[5]=copy->from_ptr[5];
82 copy->to_ptr[6]=copy->from_ptr[6];
83 copy->to_ptr[7]=copy->from_ptr[7];
84}
85
86
87static void do_field_to_null_str(Copy_field *copy)
88{
89 if (*copy->from_null_ptr & copy->from_bit)
90 {
91 bzero(copy->to_ptr,copy->from_length);
92 copy->to_null_ptr[0]=1; // Always bit 1
93 }
94 else
95 {
96 copy->to_null_ptr[0]=0;
97 memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
98 }
99}
100
101
102static void do_outer_field_to_null_str(Copy_field *copy)
103{
104 if (*copy->null_row ||
105 (copy->from_null_ptr && (*copy->from_null_ptr & copy->from_bit)))
106 {
107 bzero(copy->to_ptr,copy->from_length);
108 copy->to_null_ptr[0]=1; // Always bit 1
109 }
110 else
111 {
112 copy->to_null_ptr[0]=0;
113 memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
114 }
115}
116
117
118static int set_bad_null_error(Field *field, int err)
119{
120 switch (field->table->in_use->count_cuted_fields) {
121 case CHECK_FIELD_WARN:
122 field->set_warning(Sql_condition::WARN_LEVEL_WARN, err, 1);
123 /* fall through */
124 case CHECK_FIELD_IGNORE:
125 case CHECK_FIELD_EXPRESSION:
126 return 0;
127 case CHECK_FIELD_ERROR_FOR_NULL:
128 if (!field->table->in_use->no_errors)
129 my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name.str);
130 return -1;
131 }
132 DBUG_ASSERT(0); // impossible
133 return -1;
134}
135
136
137int set_field_to_null(Field *field)
138{
139 if (field->table->null_catch_flags & CHECK_ROW_FOR_NULLS_TO_REJECT)
140 {
141 field->table->null_catch_flags|= REJECT_ROW_DUE_TO_NULL_FIELDS;
142 return -1;
143 }
144 if (field->real_maybe_null())
145 {
146 field->set_null();
147 field->reset();
148 return 0;
149 }
150 field->reset();
151 return set_bad_null_error(field, WARN_DATA_TRUNCATED);
152}
153
154
155/**
156 Set TIMESTAMP to NOW(), AUTO_INCREMENT to the next number, or report an error
157
158 @param field Field to update
159
160 @retval
161 0 Field could take 0 or an automatic conversion was used
162 @retval
163 -1 Field could not take NULL and no conversion was used.
164 If no_conversion was not set, an error message is printed
165*/
166
167int convert_null_to_field_value_or_error(Field *field)
168{
169 if (field->type() == MYSQL_TYPE_TIMESTAMP)
170 {
171 ((Field_timestamp*) field)->set_time();
172 return 0;
173 }
174
175 field->reset(); // Note: we ignore any potential failure of reset() here.
176
177 if (field == field->table->next_number_field)
178 {
179 field->table->auto_increment_field_not_null= FALSE;
180 return 0; // field is set in fill_record()
181 }
182 return set_bad_null_error(field, ER_BAD_NULL_ERROR);
183}
184
185/**
186 Set field to NULL or TIMESTAMP or to next auto_increment number.
187
188 @param field Field to update
189 @param no_conversions Set to 1 if we should return 1 if field can't
190 take null values.
191 If set to 0 we will do store the 'default value'
192 if the field is a special field. If not we will
193 give an error.
194
195 @retval
196 0 Field could take 0 or an automatic conversion was used
197 @retval
198 -1 Field could not take NULL and no conversion was used.
199 If no_conversion was not set, an error message is printed
200*/
201
202int
203set_field_to_null_with_conversions(Field *field, bool no_conversions)
204{
205 if (field->table->null_catch_flags & CHECK_ROW_FOR_NULLS_TO_REJECT)
206 {
207 field->table->null_catch_flags|= REJECT_ROW_DUE_TO_NULL_FIELDS;
208 return -1;
209 }
210 if (field->real_maybe_null())
211 {
212 field->set_null();
213 field->reset();
214 return 0;
215 }
216 if (no_conversions)
217 return -1;
218
219 return convert_null_to_field_value_or_error(field);
220}
221
222
223static void do_skip(Copy_field *copy __attribute__((unused)))
224{
225}
226
227
228/*
229 Copy: (NULLable field) -> (NULLable field)
230
231 note: if the record we're copying from is NULL-complemetned (i.e.
232 from_field->table->null_row==1), it will also have all NULLable columns to be
233 set to NULLs, so we dont need to check table->null_row here.
234*/
235
236static void do_copy_null(Copy_field *copy)
237{
238 if (*copy->from_null_ptr & copy->from_bit)
239 {
240 *copy->to_null_ptr|=copy->to_bit;
241 copy->to_field->reset();
242 }
243 else
244 {
245 *copy->to_null_ptr&= ~copy->to_bit;
246 (copy->do_copy2)(copy);
247 }
248}
249
250/*
251 Copy: (not-NULL field in table that can be NULL-complemented) -> (NULLable
252 field)
253*/
254
255static void do_outer_field_null(Copy_field *copy)
256{
257 if (*copy->null_row ||
258 (copy->from_null_ptr && (*copy->from_null_ptr & copy->from_bit)))
259 {
260 *copy->to_null_ptr|=copy->to_bit;
261 copy->to_field->reset();
262 }
263 else
264 {
265 *copy->to_null_ptr&= ~copy->to_bit;
266 (copy->do_copy2)(copy);
267 }
268}
269
270/*
271 Copy: (not-NULL field in table that can be NULL-complemented) -> (not-NULL
272 field)
273*/
274static void do_copy_nullable_row_to_notnull(Copy_field *copy)
275{
276 if (*copy->null_row ||
277 (copy->from_null_ptr && (*copy->from_null_ptr & copy->from_bit)))
278 {
279 copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN,
280 WARN_DATA_TRUNCATED, 1);
281 copy->to_field->reset();
282 }
283 else
284 {
285 (copy->do_copy2)(copy);
286 }
287
288}
289
290/* Copy: (NULL-able field) -> (not NULL-able field) */
291static void do_copy_not_null(Copy_field *copy)
292{
293 if (*copy->from_null_ptr & copy->from_bit)
294 {
295 copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN,
296 WARN_DATA_TRUNCATED, 1);
297 copy->to_field->reset();
298 }
299 else
300 (copy->do_copy2)(copy);
301}
302
303
304/* Copy: (non-NULLable field) -> (NULLable field) */
305static void do_copy_maybe_null(Copy_field *copy)
306{
307 *copy->to_null_ptr&= ~copy->to_bit;
308 (copy->do_copy2)(copy);
309}
310
311/* timestamp and next_number has special handling in case of NULL values */
312
313static void do_copy_timestamp(Copy_field *copy)
314{
315 if (*copy->from_null_ptr & copy->from_bit)
316 {
317 /* Same as in set_field_to_null_with_conversions() */
318 ((Field_timestamp*) copy->to_field)->set_time();
319 }
320 else
321 (copy->do_copy2)(copy);
322}
323
324
325static void do_copy_next_number(Copy_field *copy)
326{
327 if (*copy->from_null_ptr & copy->from_bit)
328 {
329 /* Same as in set_field_to_null_with_conversions() */
330 copy->to_field->table->auto_increment_field_not_null= FALSE;
331 copy->to_field->reset();
332 }
333 else
334 (copy->do_copy2)(copy);
335}
336
337
338void Field_blob::do_copy_blob(Copy_field *copy)
339{
340 ((Field_blob*) copy->to_field)->copy_value(((Field_blob*) copy->from_field));
341}
342
343void Field_blob::do_conv_blob(Copy_field *copy)
344{
345 copy->from_field->val_str(&copy->tmp);
346 ((Field_blob *) copy->to_field)->store(copy->tmp.ptr(),
347 copy->tmp.length(),
348 copy->tmp.charset());
349}
350
351/** Save blob in copy->tmp for GROUP BY. */
352
353static void do_save_blob(Copy_field *copy)
354{
355 char buff[MAX_FIELD_WIDTH];
356 String res(buff,sizeof(buff),copy->tmp.charset());
357 copy->from_field->val_str(&res);
358 copy->tmp.copy(res);
359 ((Field_blob *) copy->to_field)->store(copy->tmp.ptr(),
360 copy->tmp.length(),
361 copy->tmp.charset());
362}
363
364
365void Field::do_field_string(Copy_field *copy)
366{
367 char buff[MAX_FIELD_WIDTH];
368 String res(buff, sizeof(buff), copy->from_field->charset());
369 res.length(0U);
370
371 copy->from_field->val_str(&res);
372 copy->to_field->store(res.c_ptr_quick(), res.length(), res.charset());
373}
374
375
376void Field_enum::do_field_enum(Copy_field *copy)
377{
378 if (copy->from_field->val_int() == 0)
379 ((Field_enum *) copy->to_field)->store_type((ulonglong) 0);
380 else
381 do_field_string(copy);
382}
383
384
385static void do_field_varbinary_pre50(Copy_field *copy)
386{
387 char buff[MAX_FIELD_WIDTH];
388 copy->tmp.set_quick(buff,sizeof(buff),copy->tmp.charset());
389 copy->from_field->val_str(&copy->tmp);
390
391 /* Use the same function as in 4.1 to trim trailing spaces */
392 size_t length= my_lengthsp_8bit(&my_charset_bin, copy->tmp.c_ptr_quick(),
393 copy->from_field->field_length);
394
395 copy->to_field->store(copy->tmp.c_ptr_quick(), length,
396 copy->tmp.charset());
397}
398
399
400void Field::do_field_int(Copy_field *copy)
401{
402 longlong value= copy->from_field->val_int();
403 copy->to_field->store(value,
404 MY_TEST(copy->from_field->flags & UNSIGNED_FLAG));
405}
406
407void Field::do_field_real(Copy_field *copy)
408{
409 double value=copy->from_field->val_real();
410 copy->to_field->store(value);
411}
412
413
414void Field::do_field_decimal(Copy_field *copy)
415{
416 my_decimal value;
417 copy->to_field->store_decimal(copy->from_field->val_decimal(&value));
418}
419
420
421void Field::do_field_timestamp(Copy_field *copy)
422{
423 // XXX why couldn't we do it everywhere?
424 copy->from_field->save_in_field(copy->to_field);
425}
426
427
428void Field::do_field_temporal(Copy_field *copy)
429{
430 MYSQL_TIME ltime;
431 // TODO: we now need to check result
432 if (copy->from_field->get_date(&ltime, 0))
433 copy->to_field->reset();
434 else
435 copy->to_field->store_time_dec(&ltime, copy->from_field->decimals());
436}
437
438
439void Field_time::do_field_time(Copy_field *copy)
440{
441 MYSQL_TIME ltime;
442 if (copy->from_field->get_date(&ltime, TIME_TIME_ONLY))
443 copy->to_field->reset();
444 else
445 copy->to_field->store_time_dec(&ltime, copy->from_field->decimals());
446}
447
448
449/**
450 string copy for single byte characters set when to string is shorter than
451 from string.
452*/
453
454static void do_cut_string(Copy_field *copy)
455{
456 CHARSET_INFO *cs= copy->from_field->charset();
457 memcpy(copy->to_ptr,copy->from_ptr,copy->to_length);
458
459 /* Check if we loosed any important characters */
460 if (cs->cset->scan(cs,
461 (char*) copy->from_ptr + copy->to_length,
462 (char*) copy->from_ptr + copy->from_length,
463 MY_SEQ_SPACES) < copy->from_length - copy->to_length)
464 {
465 copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN,
466 WARN_DATA_TRUNCATED, 1);
467 }
468}
469
470
471/**
472 string copy for multi byte characters set when to string is shorter than
473 from string.
474*/
475
476static void do_cut_string_complex(Copy_field *copy)
477{ // Shorter string field
478 CHARSET_INFO *cs= copy->from_field->charset();
479 const uchar *from_end= copy->from_ptr + copy->from_length;
480 Well_formed_prefix prefix(cs,
481 (char*) copy->from_ptr,
482 (char*) from_end,
483 copy->to_length / cs->mbmaxlen);
484 size_t copy_length= prefix.length();
485 if (copy->to_length < copy_length)
486 copy_length= copy->to_length;
487 memcpy(copy->to_ptr, copy->from_ptr, copy_length);
488
489 /* Check if we lost any important characters */
490 if (unlikely(prefix.well_formed_error_pos() ||
491 cs->cset->scan(cs, (char*) copy->from_ptr + copy_length,
492 (char*) from_end,
493 MY_SEQ_SPACES) <
494 (copy->from_length - copy_length)))
495 {
496 copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN,
497 WARN_DATA_TRUNCATED, 1);
498 }
499
500 if (copy_length < copy->to_length)
501 cs->cset->fill(cs, (char*) copy->to_ptr + copy_length,
502 copy->to_length - copy_length, ' ');
503}
504
505
506
507
508static void do_expand_binary(Copy_field *copy)
509{
510 CHARSET_INFO *cs= copy->from_field->charset();
511 memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
512 cs->cset->fill(cs, (char*) copy->to_ptr+copy->from_length,
513 copy->to_length-copy->from_length, '\0');
514}
515
516
517
518static void do_expand_string(Copy_field *copy)
519{
520 CHARSET_INFO *cs= copy->from_field->charset();
521 memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
522 cs->cset->fill(cs, (char*) copy->to_ptr+copy->from_length,
523 copy->to_length-copy->from_length, ' ');
524}
525
526
527static void do_varstring1(Copy_field *copy)
528{
529 uint length= (uint) *(uchar*) copy->from_ptr;
530 if (length > copy->to_length- 1)
531 {
532 length=copy->to_length - 1;
533 if (copy->from_field->table->in_use->count_cuted_fields >
534 CHECK_FIELD_EXPRESSION &&
535 copy->to_field)
536 copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN,
537 WARN_DATA_TRUNCATED, 1);
538 }
539 *(uchar*) copy->to_ptr= (uchar) length;
540 memcpy(copy->to_ptr+1, copy->from_ptr + 1, length);
541}
542
543
544static void do_varstring1_mb(Copy_field *copy)
545{
546 CHARSET_INFO *cs= copy->from_field->charset();
547 uint from_length= (uint) *(uchar*) copy->from_ptr;
548 const uchar *from_ptr= copy->from_ptr + 1;
549 uint to_char_length= (copy->to_length - 1) / cs->mbmaxlen;
550 Well_formed_prefix prefix(cs, (char*) from_ptr, from_length, to_char_length);
551 if (prefix.length() < from_length)
552 {
553 if (current_thd->count_cuted_fields > CHECK_FIELD_EXPRESSION)
554 copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN,
555 WARN_DATA_TRUNCATED, 1);
556 }
557 *copy->to_ptr= (uchar) prefix.length();
558 memcpy(copy->to_ptr + 1, from_ptr, prefix.length());
559}
560
561
562static void do_varstring2(Copy_field *copy)
563{
564 uint length=uint2korr(copy->from_ptr);
565 if (length > copy->to_length- HA_KEY_BLOB_LENGTH)
566 {
567 length=copy->to_length-HA_KEY_BLOB_LENGTH;
568 if (copy->from_field->table->in_use->count_cuted_fields >
569 CHECK_FIELD_EXPRESSION &&
570 copy->to_field)
571 copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN,
572 WARN_DATA_TRUNCATED, 1);
573 }
574 int2store(copy->to_ptr,length);
575 memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, copy->from_ptr + HA_KEY_BLOB_LENGTH,
576 length);
577}
578
579
580static void do_varstring2_mb(Copy_field *copy)
581{
582 CHARSET_INFO *cs= copy->from_field->charset();
583 uint char_length= (copy->to_length - HA_KEY_BLOB_LENGTH) / cs->mbmaxlen;
584 uint from_length= uint2korr(copy->from_ptr);
585 const uchar *from_beg= copy->from_ptr + HA_KEY_BLOB_LENGTH;
586 Well_formed_prefix prefix(cs, (char*) from_beg, from_length, char_length);
587 if (prefix.length() < from_length)
588 {
589 if (current_thd->count_cuted_fields > CHECK_FIELD_EXPRESSION)
590 copy->to_field->set_warning(Sql_condition::WARN_LEVEL_WARN,
591 WARN_DATA_TRUNCATED, 1);
592 }
593 int2store(copy->to_ptr, prefix.length());
594 memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, from_beg, prefix.length());
595}
596
597
598/***************************************************************************
599** The different functions that fills in a Copy_field class
600***************************************************************************/
601
602/**
603 copy of field to maybe null string.
604 If field is null then the all bytes are set to 0.
605 if field is not null then the first byte is set to 1 and the rest of the
606 string is the field value.
607 The 'to' buffer should have a size of field->pack_length()+1
608*/
609
610void Copy_field::set(uchar *to,Field *from)
611{
612 from_ptr=from->ptr;
613 to_ptr=to;
614 from_length=from->pack_length_in_rec();
615 if (from->maybe_null())
616 {
617 from_null_ptr=from->null_ptr;
618 from_bit= from->null_bit;
619 to_ptr[0]= 1; // Null as default value
620 to_null_ptr= (uchar*) to_ptr++;
621 to_bit= 1;
622 if (from->table->maybe_null)
623 {
624 null_row= &from->table->null_row;
625 do_copy= do_outer_field_to_null_str;
626 }
627 else
628 do_copy= do_field_to_null_str;
629 }
630 else
631 {
632 to_null_ptr= 0; // For easy debugging
633 do_copy= do_field_eq;
634 }
635}
636
637
638/*
639 To do:
640
641 If 'save' is set to true and the 'from' is a blob field, do_copy is set to
642 do_save_blob rather than do_conv_blob. The only differences between them
643 appears to be:
644
645 - do_save_blob allocates and uses an intermediate buffer before calling
646 Field_blob::store. Is this in order to trigger the call to
647 well_formed_copy_nchars, by changing the pointer copy->tmp.ptr()?
648 That call will take place anyway in all known cases.
649 */
650void Copy_field::set(Field *to,Field *from,bool save)
651{
652 if (to->type() == MYSQL_TYPE_NULL)
653 {
654 to_null_ptr=0; // For easy debugging
655 to_ptr=0;
656 do_copy=do_skip;
657 return;
658 }
659 from_field=from;
660 to_field=to;
661 from_ptr=from->ptr;
662 from_length=from->pack_length_in_rec();
663 to_ptr= to->ptr;
664 to_length=to_field->pack_length_in_rec();
665
666 // set up null handling
667 from_null_ptr=to_null_ptr=0;
668 if (from->maybe_null())
669 {
670 from_null_ptr= from->null_ptr;
671 from_bit= from->null_bit;
672 if (to_field->real_maybe_null())
673 {
674 to_null_ptr= to->null_ptr;
675 to_bit= to->null_bit;
676 if (from_null_ptr)
677 do_copy= do_copy_null;
678 else
679 {
680 null_row= &from->table->null_row;
681 do_copy= do_outer_field_null;
682 }
683 }
684 else
685 {
686 if (to_field->type() == MYSQL_TYPE_TIMESTAMP)
687 do_copy= do_copy_timestamp; // Automatic timestamp
688 else if (to_field == to_field->table->next_number_field)
689 do_copy= do_copy_next_number;
690 else
691 {
692 if (!from_null_ptr)
693 {
694 null_row= &from->table->null_row;
695 do_copy= do_copy_nullable_row_to_notnull;
696 }
697 else
698 do_copy= do_copy_not_null;
699 }
700 }
701 }
702 else if (to_field->real_maybe_null())
703 {
704 to_null_ptr= to->null_ptr;
705 to_bit= to->null_bit;
706 do_copy= do_copy_maybe_null;
707 }
708 else
709 do_copy=0;
710
711 if ((to->flags & BLOB_FLAG) && save)
712 do_copy2= do_save_blob;
713 else
714 do_copy2= to->get_copy_func(from);
715 if (!do_copy) // Not null
716 do_copy=do_copy2;
717}
718
719
720Field::Copy_func *Field_timestamp::get_copy_func(const Field *from) const
721{
722 Field::Copy_func *copy= Field_temporal::get_copy_func(from);
723 if (copy == do_field_temporal && from->type() == MYSQL_TYPE_TIMESTAMP)
724 return do_field_timestamp;
725 else
726 return copy;
727}
728
729
730Field::Copy_func *Field_temporal::get_copy_func(const Field *from) const
731{
732 /* If types are not 100 % identical then convert trough get_date() */
733 if (from->cmp_type() == REAL_RESULT)
734 return do_field_string; // TODO: MDEV-9344
735 if (from->type() == MYSQL_TYPE_YEAR)
736 return do_field_string; // TODO: MDEV-9343
737 if (from->type() == MYSQL_TYPE_BIT)
738 return do_field_int;
739 if (!eq_def(from) ||
740 (table->in_use->variables.sql_mode &
741 (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE)))
742 return do_field_temporal;
743 return get_identical_copy_func();
744}
745
746
747Field::Copy_func *Field_varstring::get_copy_func(const Field *from) const
748{
749 if (from->type() == MYSQL_TYPE_BIT)
750 return do_field_int;
751 /*
752 Detect copy from pre 5.0 varbinary to varbinary as of 5.0 and
753 use special copy function that removes trailing spaces and thus
754 repairs data.
755 */
756 if (from->type() == MYSQL_TYPE_VAR_STRING && !from->has_charset() &&
757 !Field_varstring::has_charset())
758 return do_field_varbinary_pre50;
759 if (Field_varstring::real_type() != from->real_type() ||
760 Field_varstring::charset() != from->charset() ||
761 length_bytes != ((const Field_varstring*) from)->length_bytes ||
762 !compression_method() != !from->compression_method())
763 return do_field_string;
764 return length_bytes == 1 ?
765 (from->charset()->mbmaxlen == 1 ? do_varstring1 : do_varstring1_mb) :
766 (from->charset()->mbmaxlen == 1 ? do_varstring2 : do_varstring2_mb);
767}
768
769
770Field::Copy_func *Field_string::get_copy_func(const Field *from) const
771{
772 if (from->type() == MYSQL_TYPE_BIT)
773 return do_field_int;
774 if (Field_string::real_type() != from->real_type() ||
775 Field_string::charset() != from->charset())
776 return do_field_string;
777 if (Field_string::pack_length() < from->pack_length())
778 return (Field_string::charset()->mbmaxlen == 1 ?
779 do_cut_string : do_cut_string_complex);
780 if (Field_string::pack_length() > from->pack_length())
781 return Field_string::charset() == &my_charset_bin ? do_expand_binary :
782 do_expand_string;
783 return get_identical_copy_func();
784}
785
786
787Field::Copy_func *Field::get_identical_copy_func() const
788{
789 /* Identical field types */
790 switch (pack_length()) {
791 case 1: return do_field_1;
792 case 2: return do_field_2;
793 case 3: return do_field_3;
794 case 4: return do_field_4;
795 case 6: return do_field_6;
796 case 8: return do_field_8;
797 }
798 return do_field_eq;
799}
800
801
802bool Field_temporal::memcpy_field_possible(const Field *from) const
803{
804 return real_type() == from->real_type() &&
805 decimals() == from->decimals() &&
806 !sql_mode_for_dates(table->in_use);
807}
808
809
810static int field_conv_memcpy(Field *to, Field *from)
811{
812 /*
813 This may happen if one does 'UPDATE ... SET x=x'
814 The test is here mostly for valgrind, but can also be relevant
815 if memcpy() is implemented with prefetch-write
816 */
817 if (to->ptr != from->ptr)
818 memcpy(to->ptr,from->ptr, to->pack_length());
819 return 0;
820}
821
822
823/**
824 Copy value of the field with conversion.
825
826 @note Impossibility of simple copy should be checked before this call.
827
828 @param to The field to copy to
829
830 @retval TRUE ERROR
831 @retval FALSE OK
832
833*/
834static int field_conv_incompatible(Field *to, Field *from)
835{
836 return to->store_field(from);
837}
838
839
840/**
841 Simple quick field converter that is called on insert, e.g.:
842 INSERT INTO t1 (field1) SELECT field2 FROM t2;
843*/
844
845int field_conv(Field *to,Field *from)
846{
847 return to->memcpy_field_possible(from) ?
848 field_conv_memcpy(to, from) :
849 field_conv_incompatible(to, from);
850}
851
852
853fast_field_copier Field::get_fast_field_copier(const Field *from)
854{
855 DBUG_ENTER("Field::get_fast_field_copier");
856 DBUG_RETURN(memcpy_field_possible(from) ?
857 &field_conv_memcpy :
858 &field_conv_incompatible);
859}
860