mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / sql / field_conv.cc
blob3c60bca74b9175915bb60d7b9124a6fb78ca6e81
1 /*
2 Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
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.
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.
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
19 /**
20 @file
22 @brief
23 Functions to copy data to or from fields
25 This could be done with a single short function but opencoding this
26 gives much more speed.
29 #include "mysql_priv.h"
30 #include <m_ctype.h>
32 static void do_field_eq(Copy_field *copy)
34 memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
37 static void do_field_1(Copy_field *copy)
39 copy->to_ptr[0]=copy->from_ptr[0];
42 static void do_field_2(Copy_field *copy)
44 copy->to_ptr[0]=copy->from_ptr[0];
45 copy->to_ptr[1]=copy->from_ptr[1];
48 static void do_field_3(Copy_field *copy)
50 copy->to_ptr[0]=copy->from_ptr[0];
51 copy->to_ptr[1]=copy->from_ptr[1];
52 copy->to_ptr[2]=copy->from_ptr[2];
55 static void do_field_4(Copy_field *copy)
57 copy->to_ptr[0]=copy->from_ptr[0];
58 copy->to_ptr[1]=copy->from_ptr[1];
59 copy->to_ptr[2]=copy->from_ptr[2];
60 copy->to_ptr[3]=copy->from_ptr[3];
63 static void do_field_6(Copy_field *copy)
64 { // For blob field
65 copy->to_ptr[0]=copy->from_ptr[0];
66 copy->to_ptr[1]=copy->from_ptr[1];
67 copy->to_ptr[2]=copy->from_ptr[2];
68 copy->to_ptr[3]=copy->from_ptr[3];
69 copy->to_ptr[4]=copy->from_ptr[4];
70 copy->to_ptr[5]=copy->from_ptr[5];
73 static void do_field_8(Copy_field *copy)
75 copy->to_ptr[0]=copy->from_ptr[0];
76 copy->to_ptr[1]=copy->from_ptr[1];
77 copy->to_ptr[2]=copy->from_ptr[2];
78 copy->to_ptr[3]=copy->from_ptr[3];
79 copy->to_ptr[4]=copy->from_ptr[4];
80 copy->to_ptr[5]=copy->from_ptr[5];
81 copy->to_ptr[6]=copy->from_ptr[6];
82 copy->to_ptr[7]=copy->from_ptr[7];
86 static void do_field_to_null_str(Copy_field *copy)
88 if (*copy->from_null_ptr & copy->from_bit)
90 bzero(copy->to_ptr,copy->from_length);
91 copy->to_null_ptr[0]=1; // Always bit 1
93 else
95 copy->to_null_ptr[0]=0;
96 memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
101 static void do_outer_field_to_null_str(Copy_field *copy)
103 if (*copy->null_row ||
104 (copy->from_null_ptr && (*copy->from_null_ptr & copy->from_bit)))
106 bzero(copy->to_ptr,copy->from_length);
107 copy->to_null_ptr[0]=1; // Always bit 1
109 else
111 copy->to_null_ptr[0]=0;
112 memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
118 set_field_to_null(Field *field)
120 if (field->real_maybe_null())
122 field->set_null();
123 field->reset();
124 return 0;
126 field->reset();
127 switch (field->table->in_use->count_cuted_fields) {
128 case CHECK_FIELD_WARN:
129 field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
130 /* fall through */
131 case CHECK_FIELD_IGNORE:
132 return 0;
133 case CHECK_FIELD_ERROR_FOR_NULL:
134 if (!field->table->in_use->no_errors)
135 my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name);
136 return -1;
138 DBUG_ASSERT(0); // impossible
139 return -1;
144 Set field to NULL or TIMESTAMP or to next auto_increment number.
146 @param field Field to update
147 @param no_conversions Set to 1 if we should return 1 if field can't
148 take null values.
149 If set to 0 we will do store the 'default value'
150 if the field is a special field. If not we will
151 give an error.
153 @retval
154 0 Field could take 0 or an automatic conversion was used
155 @retval
156 -1 Field could not take NULL and no conversion was used.
157 If no_conversion was not set, an error message is printed
161 set_field_to_null_with_conversions(Field *field, bool no_conversions)
163 if (field->real_maybe_null())
165 field->set_null();
166 field->reset();
167 return 0;
169 if (no_conversions)
170 return -1;
173 Check if this is a special type, which will get a special walue
174 when set to NULL (TIMESTAMP fields which allow setting to NULL
175 are handled by first check).
177 if (field->type() == MYSQL_TYPE_TIMESTAMP)
179 ((Field_timestamp*) field)->set_time();
180 return 0; // Ok to set time to NULL
183 // Note: we ignore any potential failure of reset() here.
184 field->reset();
186 if (field == field->table->next_number_field)
188 field->table->auto_increment_field_not_null= FALSE;
189 return 0; // field is set in fill_record()
191 switch (field->table->in_use->count_cuted_fields) {
192 case CHECK_FIELD_WARN:
193 field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_BAD_NULL_ERROR, 1);
194 /* fall through */
195 case CHECK_FIELD_IGNORE:
196 return 0;
197 case CHECK_FIELD_ERROR_FOR_NULL:
198 if (!field->table->in_use->no_errors)
199 my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name);
200 return -1;
202 DBUG_ASSERT(0); // impossible
203 return -1;
207 static void do_skip(Copy_field *copy __attribute__((unused)))
212 static void do_copy_null(Copy_field *copy)
214 if (*copy->from_null_ptr & copy->from_bit)
216 *copy->to_null_ptr|=copy->to_bit;
217 copy->to_field->reset();
219 else
221 *copy->to_null_ptr&= ~copy->to_bit;
222 (copy->do_copy2)(copy);
227 static void do_outer_field_null(Copy_field *copy)
229 if (*copy->null_row ||
230 (copy->from_null_ptr && (*copy->from_null_ptr & copy->from_bit)))
232 *copy->to_null_ptr|=copy->to_bit;
233 copy->to_field->reset();
235 else
237 *copy->to_null_ptr&= ~copy->to_bit;
238 (copy->do_copy2)(copy);
243 static void do_copy_not_null(Copy_field *copy)
245 if (*copy->from_null_ptr & copy->from_bit)
247 copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
248 WARN_DATA_TRUNCATED, 1);
249 copy->to_field->reset();
251 else
252 (copy->do_copy2)(copy);
256 static void do_copy_maybe_null(Copy_field *copy)
258 *copy->to_null_ptr&= ~copy->to_bit;
259 (copy->do_copy2)(copy);
262 /* timestamp and next_number has special handling in case of NULL values */
264 static void do_copy_timestamp(Copy_field *copy)
266 if (*copy->from_null_ptr & copy->from_bit)
268 /* Same as in set_field_to_null_with_conversions() */
269 ((Field_timestamp*) copy->to_field)->set_time();
271 else
272 (copy->do_copy2)(copy);
276 static void do_copy_next_number(Copy_field *copy)
278 if (*copy->from_null_ptr & copy->from_bit)
280 /* Same as in set_field_to_null_with_conversions() */
281 copy->to_field->table->auto_increment_field_not_null= FALSE;
282 copy->to_field->reset();
284 else
285 (copy->do_copy2)(copy);
289 static void do_copy_blob(Copy_field *copy)
291 ulong length=((Field_blob*) copy->from_field)->get_length();
292 ((Field_blob*) copy->to_field)->store_length(length);
293 memcpy_fixed(copy->to_ptr,copy->from_ptr,sizeof(char*));
296 static void do_conv_blob(Copy_field *copy)
298 copy->from_field->val_str(&copy->tmp);
299 ((Field_blob *) copy->to_field)->store(copy->tmp.ptr(),
300 copy->tmp.length(),
301 copy->tmp.charset());
304 /** Save blob in copy->tmp for GROUP BY. */
306 static void do_save_blob(Copy_field *copy)
308 char buff[MAX_FIELD_WIDTH];
309 String res(buff,sizeof(buff),copy->tmp.charset());
310 copy->from_field->val_str(&res);
311 copy->tmp.copy(res);
312 ((Field_blob *) copy->to_field)->store(copy->tmp.ptr(),
313 copy->tmp.length(),
314 copy->tmp.charset());
318 static void do_field_string(Copy_field *copy)
320 char buff[MAX_FIELD_WIDTH];
321 copy->tmp.set_quick(buff,sizeof(buff),copy->tmp.charset());
322 copy->from_field->val_str(&copy->tmp);
323 copy->to_field->store(copy->tmp.c_ptr_quick(),copy->tmp.length(),
324 copy->tmp.charset());
328 static void do_field_enum(Copy_field *copy)
330 if (copy->from_field->val_int() == 0)
331 ((Field_enum *) copy->to_field)->store_type((ulonglong) 0);
332 else
333 do_field_string(copy);
337 static void do_field_varbinary_pre50(Copy_field *copy)
339 char buff[MAX_FIELD_WIDTH];
340 copy->tmp.set_quick(buff,sizeof(buff),copy->tmp.charset());
341 copy->from_field->val_str(&copy->tmp);
343 /* Use the same function as in 4.1 to trim trailing spaces */
344 uint length= my_lengthsp_8bit(&my_charset_bin, copy->tmp.c_ptr_quick(),
345 copy->from_field->field_length);
347 copy->to_field->store(copy->tmp.c_ptr_quick(), length,
348 copy->tmp.charset());
352 static void do_field_int(Copy_field *copy)
354 longlong value= copy->from_field->val_int();
355 copy->to_field->store(value,
356 test(copy->from_field->flags & UNSIGNED_FLAG));
359 static void do_field_real(Copy_field *copy)
361 double value=copy->from_field->val_real();
362 copy->to_field->store(value);
366 static void do_field_decimal(Copy_field *copy)
368 my_decimal value;
369 copy->to_field->store_decimal(copy->from_field->val_decimal(&value));
374 string copy for single byte characters set when to string is shorter than
375 from string.
378 static void do_cut_string(Copy_field *copy)
380 CHARSET_INFO *cs= copy->from_field->charset();
381 memcpy(copy->to_ptr,copy->from_ptr,copy->to_length);
383 /* Check if we loosed any important characters */
384 if (cs->cset->scan(cs,
385 (char*) copy->from_ptr + copy->to_length,
386 (char*) copy->from_ptr + copy->from_length,
387 MY_SEQ_SPACES) < copy->from_length - copy->to_length)
389 copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
390 WARN_DATA_TRUNCATED, 1);
396 string copy for multi byte characters set when to string is shorter than
397 from string.
400 static void do_cut_string_complex(Copy_field *copy)
401 { // Shorter string field
402 int well_formed_error;
403 CHARSET_INFO *cs= copy->from_field->charset();
404 const uchar *from_end= copy->from_ptr + copy->from_length;
405 uint copy_length= cs->cset->well_formed_len(cs,
406 (char*) copy->from_ptr,
407 (char*) from_end,
408 copy->to_length / cs->mbmaxlen,
409 &well_formed_error);
410 if (copy->to_length < copy_length)
411 copy_length= copy->to_length;
412 memcpy(copy->to_ptr, copy->from_ptr, copy_length);
414 /* Check if we lost any important characters */
415 if (well_formed_error ||
416 cs->cset->scan(cs, (char*) copy->from_ptr + copy_length,
417 (char*) from_end,
418 MY_SEQ_SPACES) < (copy->from_length - copy_length))
420 copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
421 WARN_DATA_TRUNCATED, 1);
424 if (copy_length < copy->to_length)
425 cs->cset->fill(cs, (char*) copy->to_ptr + copy_length,
426 copy->to_length - copy_length, ' ');
432 static void do_expand_binary(Copy_field *copy)
434 CHARSET_INFO *cs= copy->from_field->charset();
435 memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
436 cs->cset->fill(cs, (char*) copy->to_ptr+copy->from_length,
437 copy->to_length-copy->from_length, '\0');
442 static void do_expand_string(Copy_field *copy)
444 CHARSET_INFO *cs= copy->from_field->charset();
445 memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
446 cs->cset->fill(cs, (char*) copy->to_ptr+copy->from_length,
447 copy->to_length-copy->from_length, ' ');
451 static void do_varstring1(Copy_field *copy)
453 uint length= (uint) *(uchar*) copy->from_ptr;
454 if (length > copy->to_length- 1)
456 length=copy->to_length - 1;
457 if (copy->from_field->table->in_use->count_cuted_fields)
458 copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
459 WARN_DATA_TRUNCATED, 1);
461 *(uchar*) copy->to_ptr= (uchar) length;
462 memcpy(copy->to_ptr+1, copy->from_ptr + 1, length);
466 static void do_varstring1_mb(Copy_field *copy)
468 int well_formed_error;
469 CHARSET_INFO *cs= copy->from_field->charset();
470 uint from_length= (uint) *(uchar*) copy->from_ptr;
471 const uchar *from_ptr= copy->from_ptr + 1;
472 uint to_char_length= (copy->to_length - 1) / cs->mbmaxlen;
473 uint length= cs->cset->well_formed_len(cs, (char*) from_ptr,
474 (char*) from_ptr + from_length,
475 to_char_length, &well_formed_error);
476 if (length < from_length)
478 if (current_thd->count_cuted_fields)
479 copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
480 WARN_DATA_TRUNCATED, 1);
482 *copy->to_ptr= (uchar) length;
483 memcpy(copy->to_ptr + 1, from_ptr, length);
487 static void do_varstring2(Copy_field *copy)
489 uint length=uint2korr(copy->from_ptr);
490 if (length > copy->to_length- HA_KEY_BLOB_LENGTH)
492 length=copy->to_length-HA_KEY_BLOB_LENGTH;
493 if (copy->from_field->table->in_use->count_cuted_fields)
494 copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
495 WARN_DATA_TRUNCATED, 1);
497 int2store(copy->to_ptr,length);
498 memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, copy->from_ptr + HA_KEY_BLOB_LENGTH,
499 length);
503 static void do_varstring2_mb(Copy_field *copy)
505 int well_formed_error;
506 CHARSET_INFO *cs= copy->from_field->charset();
507 uint char_length= (copy->to_length - HA_KEY_BLOB_LENGTH) / cs->mbmaxlen;
508 uint from_length= uint2korr(copy->from_ptr);
509 const uchar *from_beg= copy->from_ptr + HA_KEY_BLOB_LENGTH;
510 uint length= cs->cset->well_formed_len(cs, (char*) from_beg,
511 (char*) from_beg + from_length,
512 char_length, &well_formed_error);
513 if (length < from_length)
515 if (current_thd->count_cuted_fields)
516 copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
517 WARN_DATA_TRUNCATED, 1);
519 int2store(copy->to_ptr, length);
520 memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, from_beg, length);
524 /***************************************************************************
525 ** The different functions that fills in a Copy_field class
526 ***************************************************************************/
529 copy of field to maybe null string.
530 If field is null then the all bytes are set to 0.
531 if field is not null then the first byte is set to 1 and the rest of the
532 string is the field value.
533 The 'to' buffer should have a size of field->pack_length()+1
536 void Copy_field::set(uchar *to,Field *from)
538 from_ptr=from->ptr;
539 to_ptr=to;
540 from_length=from->pack_length();
541 if (from->maybe_null())
543 from_null_ptr=from->null_ptr;
544 from_bit= from->null_bit;
545 to_ptr[0]= 1; // Null as default value
546 to_null_ptr= (uchar*) to_ptr++;
547 to_bit= 1;
548 if (from->table->maybe_null)
550 null_row= &from->table->null_row;
551 do_copy= do_outer_field_to_null_str;
553 else
554 do_copy= do_field_to_null_str;
556 else
558 to_null_ptr= 0; // For easy debugging
559 do_copy= do_field_eq;
565 To do:
567 If 'save\ is set to true and the 'from' is a blob field, do_copy is set to
568 do_save_blob rather than do_conv_blob. The only differences between them
569 appears to be:
571 - do_save_blob allocates and uses an intermediate buffer before calling
572 Field_blob::store. Is this in order to trigger the call to
573 well_formed_copy_nchars, by changing the pointer copy->tmp.ptr()?
574 That call will take place anyway in all known cases.
576 - The above causes a truncation to MAX_FIELD_WIDTH. Is this the intended
577 effect? Truncation is handled by well_formed_copy_nchars anyway.
579 void Copy_field::set(Field *to,Field *from,bool save)
581 if (to->type() == MYSQL_TYPE_NULL)
583 to_null_ptr=0; // For easy debugging
584 to_ptr=0;
585 do_copy=do_skip;
586 return;
588 from_field=from;
589 to_field=to;
590 from_ptr=from->ptr;
591 from_length=from->pack_length();
592 to_ptr= to->ptr;
593 to_length=to_field->pack_length();
595 // set up null handling
596 from_null_ptr=to_null_ptr=0;
597 if (from->maybe_null())
599 from_null_ptr= from->null_ptr;
600 from_bit= from->null_bit;
601 if (to_field->real_maybe_null())
603 to_null_ptr= to->null_ptr;
604 to_bit= to->null_bit;
605 if (from_null_ptr)
606 do_copy= do_copy_null;
607 else
609 null_row= &from->table->null_row;
610 do_copy= do_outer_field_null;
613 else
615 if (to_field->type() == MYSQL_TYPE_TIMESTAMP)
616 do_copy= do_copy_timestamp; // Automatic timestamp
617 else if (to_field == to_field->table->next_number_field)
618 do_copy= do_copy_next_number;
619 else
620 do_copy= do_copy_not_null;
623 else if (to_field->real_maybe_null())
625 to_null_ptr= to->null_ptr;
626 to_bit= to->null_bit;
627 do_copy= do_copy_maybe_null;
629 else
630 do_copy=0;
632 if ((to->flags & BLOB_FLAG) && save)
633 do_copy2= do_save_blob;
634 else
635 do_copy2= get_copy_func(to,from);
636 if (!do_copy) // Not null
637 do_copy=do_copy2;
641 Copy_field::Copy_func *
642 Copy_field::get_copy_func(Field *to,Field *from)
644 bool compatible_db_low_byte_first= (to->table->s->db_low_byte_first ==
645 from->table->s->db_low_byte_first);
646 if (to->flags & BLOB_FLAG)
648 if (!(from->flags & BLOB_FLAG) || from->charset() != to->charset())
649 return do_conv_blob;
650 if (from_length != to_length || !compatible_db_low_byte_first)
652 // Correct pointer to point at char pointer
653 to_ptr+= to_length - to->table->s->blob_ptr_size;
654 from_ptr+= from_length- from->table->s->blob_ptr_size;
655 return do_copy_blob;
658 else
660 if (to->real_type() == MYSQL_TYPE_BIT ||
661 from->real_type() == MYSQL_TYPE_BIT)
662 return do_field_int;
663 if (to->result_type() == DECIMAL_RESULT)
664 return do_field_decimal;
665 // Check if identical fields
666 if (from->result_type() == STRING_RESULT)
669 Detect copy from pre 5.0 varbinary to varbinary as of 5.0 and
670 use special copy function that removes trailing spaces and thus
671 repairs data.
673 if (from->type() == MYSQL_TYPE_VAR_STRING && !from->has_charset() &&
674 to->type() == MYSQL_TYPE_VARCHAR && !to->has_charset())
675 return do_field_varbinary_pre50;
678 If we are copying date or datetime's we have to check the dates
679 if we don't allow 'all' dates.
681 if (to->real_type() != from->real_type() ||
682 !compatible_db_low_byte_first ||
683 (((to->table->in_use->variables.sql_mode &
684 (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | MODE_INVALID_DATES)) &&
685 to->type() == MYSQL_TYPE_DATE) ||
686 to->type() == MYSQL_TYPE_DATETIME))
688 if (from->real_type() == MYSQL_TYPE_ENUM ||
689 from->real_type() == MYSQL_TYPE_SET)
690 if (to->result_type() != STRING_RESULT)
691 return do_field_int; // Convert SET to number
692 return do_field_string;
694 if (to->real_type() == MYSQL_TYPE_ENUM ||
695 to->real_type() == MYSQL_TYPE_SET)
697 if (!to->eq_def(from))
699 if (from->real_type() == MYSQL_TYPE_ENUM &&
700 to->real_type() == MYSQL_TYPE_ENUM)
701 return do_field_enum;
702 else
703 return do_field_string;
706 else if (to->charset() != from->charset())
707 return do_field_string;
708 else if (to->real_type() == MYSQL_TYPE_VARCHAR)
710 if (((Field_varstring*) to)->length_bytes !=
711 ((Field_varstring*) from)->length_bytes)
712 return do_field_string;
713 else
714 return (((Field_varstring*) to)->length_bytes == 1 ?
715 (from->charset()->mbmaxlen == 1 ? do_varstring1 :
716 do_varstring1_mb) :
717 (from->charset()->mbmaxlen == 1 ? do_varstring2 :
718 do_varstring2_mb));
720 else if (to_length < from_length)
721 return (from->charset()->mbmaxlen == 1 ?
722 do_cut_string : do_cut_string_complex);
723 else if (to_length > from_length)
725 if (to->charset() == &my_charset_bin)
726 return do_expand_binary;
727 else
728 return do_expand_string;
732 else if (to->real_type() != from->real_type() ||
733 to_length != from_length ||
734 !compatible_db_low_byte_first)
736 if (to->real_type() == MYSQL_TYPE_DECIMAL ||
737 to->result_type() == STRING_RESULT)
738 return do_field_string;
739 if (to->result_type() == INT_RESULT)
740 return do_field_int;
741 return do_field_real;
743 else
745 if (!to->eq_def(from) || !compatible_db_low_byte_first)
747 if (to->real_type() == MYSQL_TYPE_DECIMAL)
748 return do_field_string;
749 if (to->result_type() == INT_RESULT)
750 return do_field_int;
751 else
752 return do_field_real;
756 /* Eq fields */
757 switch (to_length) {
758 case 1: return do_field_1;
759 case 2: return do_field_2;
760 case 3: return do_field_3;
761 case 4: return do_field_4;
762 case 6: return do_field_6;
763 case 8: return do_field_8;
765 return do_field_eq;
769 /** Simple quick field convert that is called on insert. */
771 int field_conv(Field *to,Field *from)
773 if (to->real_type() == from->real_type() &&
774 !(to->type() == MYSQL_TYPE_BLOB && to->table->copy_blobs))
776 if (to->pack_length() == from->pack_length() &&
777 !(to->flags & UNSIGNED_FLAG && !(from->flags & UNSIGNED_FLAG)) &&
778 to->real_type() != MYSQL_TYPE_ENUM &&
779 to->real_type() != MYSQL_TYPE_SET &&
780 to->real_type() != MYSQL_TYPE_BIT &&
781 (to->real_type() != MYSQL_TYPE_NEWDECIMAL ||
782 (to->field_length == from->field_length &&
783 (((Field_num*)to)->dec == ((Field_num*)from)->dec))) &&
784 from->charset() == to->charset() &&
785 to->table->s->db_low_byte_first == from->table->s->db_low_byte_first &&
786 (!(to->table->in_use->variables.sql_mode &
787 (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | MODE_INVALID_DATES)) ||
788 (to->type() != MYSQL_TYPE_DATE &&
789 to->type() != MYSQL_TYPE_DATETIME)) &&
790 (from->real_type() != MYSQL_TYPE_VARCHAR ||
791 ((Field_varstring*)from)->length_bytes ==
792 ((Field_varstring*)to)->length_bytes))
793 { // Identical fields
794 // to->ptr==from->ptr may happen if one does 'UPDATE ... SET x=x'
795 memmove(to->ptr, from->ptr, to->pack_length());
796 return 0;
799 if (to->type() == MYSQL_TYPE_BLOB)
800 { // Be sure the value is stored
801 Field_blob *blob=(Field_blob*) to;
802 from->val_str(&blob->value);
804 Copy value if copy_blobs is set, or source is not a string and
805 we have a pointer to its internal string conversion buffer.
807 if (to->table->copy_blobs ||
808 (!blob->value.is_alloced() &&
809 from->real_type() != MYSQL_TYPE_STRING &&
810 from->real_type() != MYSQL_TYPE_VARCHAR))
811 blob->value.copy();
812 return blob->store(blob->value.ptr(),blob->value.length(),from->charset());
814 if (from->real_type() == MYSQL_TYPE_ENUM &&
815 to->real_type() == MYSQL_TYPE_ENUM &&
816 from->val_int() == 0)
818 ((Field_enum *)(to))->store_type(0);
819 return 0;
821 else if ((from->result_type() == STRING_RESULT &&
822 (to->result_type() == STRING_RESULT ||
823 (from->real_type() != MYSQL_TYPE_ENUM &&
824 from->real_type() != MYSQL_TYPE_SET))) ||
825 to->type() == MYSQL_TYPE_DECIMAL)
827 char buff[MAX_FIELD_WIDTH];
828 String result(buff,sizeof(buff),from->charset());
829 from->val_str(&result);
831 We use c_ptr_quick() here to make it easier if to is a float/double
832 as the conversion routines will do a copy of the result doesn't
833 end with \0. Can be replaced with .ptr() when we have our own
834 string->double conversion.
836 return to->store(result.c_ptr_quick(),result.length(),from->charset());
838 else if (from->result_type() == REAL_RESULT)
839 return to->store(from->val_real());
840 else if (from->result_type() == DECIMAL_RESULT)
842 my_decimal buff;
843 return to->store_decimal(from->val_decimal(&buff));
845 else
846 return to->store(from->val_int(), test(from->flags & UNSIGNED_FLAG));