Drizzled Public API Documentation

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