~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to sql/field_conv.cc

  • Committer: Monty Taylor
  • Date: 2008-07-05 18:10:38 UTC
  • mto: This revision was merged to the branch mainline in revision 63.
  • Revision ID: monty@inaugust.com-20080705181038-0ih0nnamu5qrut0y
Fixed prototypes. Cleaned define a little bit.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
    gives much more speed.
25
25
*/
26
26
 
27
 
#include <drizzled/server_includes.h>
 
27
#include "mysql_priv.h"
 
28
#include <m_ctype.h>
28
29
 
29
30
static void do_field_eq(Copy_field *copy)
30
31
{
84
85
{
85
86
  if (*copy->from_null_ptr & copy->from_bit)
86
87
  {
87
 
    memset(copy->to_ptr, 0, copy->from_length);
 
88
    bzero(copy->to_ptr,copy->from_length);
88
89
    copy->to_null_ptr[0]=1;                     // Always bit 1
89
90
  }
90
91
  else
100
101
  if (*copy->null_row ||
101
102
      (copy->from_null_ptr && (*copy->from_null_ptr & copy->from_bit)))
102
103
  {
103
 
    memset(copy->to_ptr, 0, copy->from_length);
 
104
    bzero(copy->to_ptr,copy->from_length);
104
105
    copy->to_null_ptr[0]=1;                     // Always bit 1
105
106
  }
106
107
  else
123
124
  field->reset();
124
125
  if (field->table->in_use->count_cuted_fields == CHECK_FIELD_WARN)
125
126
  {
126
 
    field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
 
127
    field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
127
128
    return 0;
128
129
  }
129
130
  if (!field->table->in_use->no_errors)
166
167
    when set to NULL (TIMESTAMP fields which allow setting to NULL
167
168
    are handled by first check).
168
169
  */
169
 
  if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
 
170
  if (field->type() == MYSQL_TYPE_TIMESTAMP)
170
171
  {
171
172
    ((Field_timestamp*) field)->set_time();
172
173
    return 0;                                   // Ok to set time to NULL
174
175
  field->reset();
175
176
  if (field == field->table->next_number_field)
176
177
  {
177
 
    field->table->auto_increment_field_not_null= false;
 
178
    field->table->auto_increment_field_not_null= FALSE;
178
179
    return 0;                             // field is set in fill_record()
179
180
  }
180
181
  if (field->table->in_use->count_cuted_fields == CHECK_FIELD_WARN)
181
182
  {
182
 
    field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_BAD_NULL_ERROR, 1);
 
183
    field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_BAD_NULL_ERROR, 1);
183
184
    return 0;
184
185
  }
185
186
  if (!field->table->in_use->no_errors)
228
229
{
229
230
  if (*copy->from_null_ptr & copy->from_bit)
230
231
  {
231
 
    copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
232
 
                                ER_WARN_DATA_TRUNCATED, 1);
 
232
    copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
 
233
                                WARN_DATA_TRUNCATED, 1);
233
234
    copy->to_field->reset();
234
235
  }
235
236
  else
262
263
  if (*copy->from_null_ptr & copy->from_bit)
263
264
  {
264
265
    /* Same as in set_field_to_null_with_conversions() */
265
 
    copy->to_field->table->auto_increment_field_not_null= false;
 
266
    copy->to_field->table->auto_increment_field_not_null= FALSE;
266
267
    copy->to_field->reset();
267
268
  }
268
269
  else
274
275
{
275
276
  ulong length=((Field_blob*) copy->from_field)->get_length();
276
277
  ((Field_blob*) copy->to_field)->store_length(length);
277
 
  memcpy(copy->to_ptr,copy->from_ptr,sizeof(char*));
 
278
  memcpy_fixed(copy->to_ptr,copy->from_ptr,sizeof(char*));
278
279
}
279
280
 
280
281
static void do_conv_blob(Copy_field *copy)
312
313
static void do_field_enum(Copy_field *copy)
313
314
{
314
315
  if (copy->from_field->val_int() == 0)
315
 
    ((Field_enum *) copy->to_field)->store_type((uint64_t) 0);
 
316
    ((Field_enum *) copy->to_field)->store_type((ulonglong) 0);
316
317
  else
317
318
    do_field_string(copy);
318
319
}
319
320
 
320
321
 
 
322
static void do_field_varbinary_pre50(Copy_field *copy)
 
323
{
 
324
  char buff[MAX_FIELD_WIDTH];
 
325
  copy->tmp.set_quick(buff,sizeof(buff),copy->tmp.charset());
 
326
  copy->from_field->val_str(&copy->tmp);
 
327
 
 
328
  /* Use the same function as in 4.1 to trim trailing spaces */
 
329
  uint length= my_lengthsp_8bit(&my_charset_bin, copy->tmp.c_ptr_quick(),
 
330
                                copy->from_field->field_length);
 
331
 
 
332
  copy->to_field->store(copy->tmp.c_ptr_quick(), length,
 
333
                        copy->tmp.charset());
 
334
}
 
335
 
 
336
 
321
337
static void do_field_int(Copy_field *copy)
322
338
{
323
 
  int64_t value= copy->from_field->val_int();
 
339
  longlong value= copy->from_field->val_int();
324
340
  copy->to_field->store(value,
325
341
                        test(copy->from_field->flags & UNSIGNED_FLAG));
326
342
}
346
362
 
347
363
static void do_cut_string(Copy_field *copy)
348
364
{
349
 
  const CHARSET_INFO * const cs= copy->from_field->charset();
 
365
  CHARSET_INFO *cs= copy->from_field->charset();
350
366
  memcpy(copy->to_ptr,copy->from_ptr,copy->to_length);
351
367
 
352
368
  /* Check if we loosed any important characters */
355
371
                     (char*) copy->from_ptr + copy->from_length,
356
372
                     MY_SEQ_SPACES) < copy->from_length - copy->to_length)
357
373
  {
358
 
    copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
359
 
                                ER_WARN_DATA_TRUNCATED, 1);
 
374
    copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
 
375
                                WARN_DATA_TRUNCATED, 1);
360
376
  }
361
377
}
362
378
 
369
385
static void do_cut_string_complex(Copy_field *copy)
370
386
{                                               // Shorter string field
371
387
  int well_formed_error;
372
 
  const CHARSET_INFO * const cs= copy->from_field->charset();
373
 
  const unsigned char *from_end= copy->from_ptr + copy->from_length;
374
 
  uint32_t copy_length= cs->cset->well_formed_len(cs,
 
388
  CHARSET_INFO *cs= copy->from_field->charset();
 
389
  const uchar *from_end= copy->from_ptr + copy->from_length;
 
390
  uint copy_length= cs->cset->well_formed_len(cs,
375
391
                                              (char*) copy->from_ptr,
376
392
                                              (char*) from_end, 
377
393
                                              copy->to_length / cs->mbmaxlen,
386
402
                     (char*) from_end,
387
403
                     MY_SEQ_SPACES) < (copy->from_length - copy_length))
388
404
  {
389
 
    copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
390
 
                                ER_WARN_DATA_TRUNCATED, 1);
 
405
    copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
 
406
                                WARN_DATA_TRUNCATED, 1);
391
407
  }
392
408
 
393
409
  if (copy_length < copy->to_length)
400
416
 
401
417
static void do_expand_binary(Copy_field *copy)
402
418
{
403
 
  const CHARSET_INFO * const cs= copy->from_field->charset();
 
419
  CHARSET_INFO *cs= copy->from_field->charset();
404
420
  memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
405
421
  cs->cset->fill(cs, (char*) copy->to_ptr+copy->from_length,
406
422
                     copy->to_length-copy->from_length, '\0');
410
426
 
411
427
static void do_expand_string(Copy_field *copy)
412
428
{
413
 
  const CHARSET_INFO * const cs= copy->from_field->charset();
 
429
  CHARSET_INFO *cs= copy->from_field->charset();
414
430
  memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
415
431
  cs->cset->fill(cs, (char*) copy->to_ptr+copy->from_length,
416
432
                     copy->to_length-copy->from_length, ' ');
419
435
 
420
436
static void do_varstring1(Copy_field *copy)
421
437
{
422
 
  uint32_t length= (uint) *(unsigned char*) copy->from_ptr;
 
438
  uint length= (uint) *(uchar*) copy->from_ptr;
423
439
  if (length > copy->to_length- 1)
424
440
  {
425
441
    length=copy->to_length - 1;
426
442
    if (copy->from_field->table->in_use->count_cuted_fields)
427
 
      copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
428
 
                                  ER_WARN_DATA_TRUNCATED, 1);
 
443
      copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
 
444
                                  WARN_DATA_TRUNCATED, 1);
429
445
  }
430
 
  *(unsigned char*) copy->to_ptr= (unsigned char) length;
 
446
  *(uchar*) copy->to_ptr= (uchar) length;
431
447
  memcpy(copy->to_ptr+1, copy->from_ptr + 1, length);
432
448
}
433
449
 
435
451
static void do_varstring1_mb(Copy_field *copy)
436
452
{
437
453
  int well_formed_error;
438
 
  const CHARSET_INFO * const cs= copy->from_field->charset();
439
 
  uint32_t from_length= (uint) *(unsigned char*) copy->from_ptr;
440
 
  const unsigned char *from_ptr= copy->from_ptr + 1;
441
 
  uint32_t to_char_length= (copy->to_length - 1) / cs->mbmaxlen;
442
 
  uint32_t length= cs->cset->well_formed_len(cs, (char*) from_ptr,
 
454
  CHARSET_INFO *cs= copy->from_field->charset();
 
455
  uint from_length= (uint) *(uchar*) copy->from_ptr;
 
456
  const uchar *from_ptr= copy->from_ptr + 1;
 
457
  uint to_char_length= (copy->to_length - 1) / cs->mbmaxlen;
 
458
  uint length= cs->cset->well_formed_len(cs, (char*) from_ptr,
443
459
                                         (char*) from_ptr + from_length,
444
460
                                         to_char_length, &well_formed_error);
445
461
  if (length < from_length)
446
462
  {
447
463
    if (current_thd->count_cuted_fields)
448
 
      copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
449
 
                                  ER_WARN_DATA_TRUNCATED, 1);
 
464
      copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
 
465
                                  WARN_DATA_TRUNCATED, 1);
450
466
  }
451
 
  *copy->to_ptr= (unsigned char) length;
 
467
  *copy->to_ptr= (uchar) length;
452
468
  memcpy(copy->to_ptr + 1, from_ptr, length);
453
469
}
454
470
 
455
471
 
456
472
static void do_varstring2(Copy_field *copy)
457
473
{
458
 
  uint32_t length=uint2korr(copy->from_ptr);
 
474
  uint length=uint2korr(copy->from_ptr);
459
475
  if (length > copy->to_length- HA_KEY_BLOB_LENGTH)
460
476
  {
461
477
    length=copy->to_length-HA_KEY_BLOB_LENGTH;
462
478
    if (copy->from_field->table->in_use->count_cuted_fields)
463
 
      copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
464
 
                                  ER_WARN_DATA_TRUNCATED, 1);
 
479
      copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
 
480
                                  WARN_DATA_TRUNCATED, 1);
465
481
  }
466
482
  int2store(copy->to_ptr,length);
467
483
  memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, copy->from_ptr + HA_KEY_BLOB_LENGTH,
472
488
static void do_varstring2_mb(Copy_field *copy)
473
489
{
474
490
  int well_formed_error;
475
 
  const CHARSET_INFO * const cs= copy->from_field->charset();
476
 
  uint32_t char_length= (copy->to_length - HA_KEY_BLOB_LENGTH) / cs->mbmaxlen;
477
 
  uint32_t from_length= uint2korr(copy->from_ptr);
478
 
  const unsigned char *from_beg= copy->from_ptr + HA_KEY_BLOB_LENGTH;
479
 
  uint32_t length= cs->cset->well_formed_len(cs, (char*) from_beg,
 
491
  CHARSET_INFO *cs= copy->from_field->charset();
 
492
  uint char_length= (copy->to_length - HA_KEY_BLOB_LENGTH) / cs->mbmaxlen;
 
493
  uint from_length= uint2korr(copy->from_ptr);
 
494
  const uchar *from_beg= copy->from_ptr + HA_KEY_BLOB_LENGTH;
 
495
  uint length= cs->cset->well_formed_len(cs, (char*) from_beg,
480
496
                                         (char*) from_beg + from_length,
481
497
                                         char_length, &well_formed_error);
482
498
  if (length < from_length)
483
499
  {
484
500
    if (current_thd->count_cuted_fields)
485
 
      copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
486
 
                                  ER_WARN_DATA_TRUNCATED, 1);
 
501
      copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
 
502
                                  WARN_DATA_TRUNCATED, 1);
487
503
  }  
488
504
  int2store(copy->to_ptr, length);
489
505
  memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, from_beg, length);
502
518
  The 'to' buffer should have a size of field->pack_length()+1
503
519
*/
504
520
 
505
 
void Copy_field::set(unsigned char *to,Field *from)
 
521
void Copy_field::set(uchar *to,Field *from)
506
522
{
507
523
  from_ptr=from->ptr;
508
524
  to_ptr=to;
512
528
    from_null_ptr=from->null_ptr;
513
529
    from_bit=     from->null_bit;
514
530
    to_ptr[0]=    1;                            // Null as default value
515
 
    to_null_ptr=  (unsigned char*) to_ptr++;
 
531
    to_null_ptr=  (uchar*) to_ptr++;
516
532
    to_bit=       1;
517
533
    if (from->table->maybe_null)
518
534
    {
547
563
 */
548
564
void Copy_field::set(Field *to,Field *from,bool save)
549
565
{
550
 
  if (to->type() == DRIZZLE_TYPE_NULL)
 
566
  if (to->type() == MYSQL_TYPE_NULL)
551
567
  {
552
568
    to_null_ptr=0;                              // For easy debugging
553
569
    to_ptr=0;
581
597
    }
582
598
    else
583
599
    {
584
 
      if (to_field->type() == DRIZZLE_TYPE_TIMESTAMP)
 
600
      if (to_field->type() == MYSQL_TYPE_TIMESTAMP)
585
601
        do_copy= do_copy_timestamp;               // Automatic timestamp
586
602
      else if (to_field == to_field->table->next_number_field)
587
603
        do_copy= do_copy_next_number;
626
642
  }
627
643
  else
628
644
  {
 
645
    if (to->real_type() == MYSQL_TYPE_BIT ||
 
646
        from->real_type() == MYSQL_TYPE_BIT)
 
647
      return do_field_int;
629
648
    if (to->result_type() == DECIMAL_RESULT)
630
649
      return do_field_decimal;
631
650
    // Check if identical fields
632
651
    if (from->result_type() == STRING_RESULT)
633
652
    {
634
653
      /*
 
654
        Detect copy from pre 5.0 varbinary to varbinary as of 5.0 and
 
655
        use special copy function that removes trailing spaces and thus
 
656
        repairs data.
 
657
      */
 
658
      if (from->type() == MYSQL_TYPE_VAR_STRING && !from->has_charset() &&
 
659
          to->type() == MYSQL_TYPE_VARCHAR && !to->has_charset())
 
660
        return do_field_varbinary_pre50;
 
661
 
 
662
      /*
635
663
        If we are copying date or datetime's we have to check the dates
636
664
        if we don't allow 'all' dates.
637
665
      */
638
666
      if (to->real_type() != from->real_type() ||
639
667
          !compatible_db_low_byte_first ||
640
 
          (((to->table->in_use->variables.sql_mode & (MODE_NO_ZERO_DATE | MODE_INVALID_DATES)) && to->type() == DRIZZLE_TYPE_NEWDATE) || to->type() == DRIZZLE_TYPE_DATETIME))
 
668
          (((to->table->in_use->variables.sql_mode & (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | MODE_INVALID_DATES)) && to->type() == MYSQL_TYPE_DATE) || to->type() == MYSQL_TYPE_DATETIME))
641
669
      {
642
 
        if (from->real_type() == DRIZZLE_TYPE_ENUM)
 
670
        if (from->real_type() == MYSQL_TYPE_ENUM ||
 
671
            from->real_type() == MYSQL_TYPE_SET)
643
672
          if (to->result_type() != STRING_RESULT)
644
673
            return do_field_int;                // Convert SET to number
645
674
        return do_field_string;
646
675
      }
647
 
      if (to->real_type() == DRIZZLE_TYPE_ENUM)
 
676
      if (to->real_type() == MYSQL_TYPE_ENUM ||
 
677
          to->real_type() == MYSQL_TYPE_SET)
648
678
      {
649
679
        if (!to->eq_def(from))
650
680
        {
651
 
          if (from->real_type() == DRIZZLE_TYPE_ENUM &&
652
 
              to->real_type() == DRIZZLE_TYPE_ENUM)
 
681
          if (from->real_type() == MYSQL_TYPE_ENUM &&
 
682
              to->real_type() == MYSQL_TYPE_ENUM)
653
683
            return do_field_enum;
654
684
          else
655
685
            return do_field_string;
657
687
      }
658
688
      else if (to->charset() != from->charset())
659
689
        return do_field_string;
660
 
      else if (to->real_type() == DRIZZLE_TYPE_VARCHAR)
 
690
      else if (to->real_type() == MYSQL_TYPE_VARCHAR)
661
691
      {
662
692
        if (((Field_varstring*) to)->length_bytes !=
663
693
            ((Field_varstring*) from)->length_bytes)
685
715
             to_length != from_length ||
686
716
             !compatible_db_low_byte_first)
687
717
    {
688
 
      if (to->result_type() == STRING_RESULT)
 
718
      if (to->real_type() == MYSQL_TYPE_DECIMAL ||
 
719
          to->result_type() == STRING_RESULT)
689
720
        return do_field_string;
690
721
      if (to->result_type() == INT_RESULT)
691
722
        return do_field_int;
695
726
    {
696
727
      if (!to->eq_def(from) || !compatible_db_low_byte_first)
697
728
      {
 
729
        if (to->real_type() == MYSQL_TYPE_DECIMAL)
 
730
          return do_field_string;
698
731
        if (to->result_type() == INT_RESULT)
699
732
          return do_field_int;
700
733
        else
720
753
int field_conv(Field *to,Field *from)
721
754
{
722
755
  if (to->real_type() == from->real_type() &&
723
 
      !(to->type() == DRIZZLE_TYPE_BLOB && to->table->copy_blobs))
 
756
      !(to->type() == MYSQL_TYPE_BLOB && to->table->copy_blobs))
724
757
  {
725
758
    /* Please god, will someone rewrite this to be readable :( */
726
759
    if (to->pack_length() == from->pack_length() && 
727
760
        !(to->flags & UNSIGNED_FLAG && !(from->flags & UNSIGNED_FLAG)) && 
728
 
        to->real_type() != DRIZZLE_TYPE_ENUM && 
729
 
        (to->real_type() != DRIZZLE_TYPE_NEWDECIMAL || (to->field_length == from->field_length && (((Field_num*)to)->dec == ((Field_num*)from)->dec))) &&
 
761
        to->real_type() != MYSQL_TYPE_ENUM && 
 
762
        to->real_type() != MYSQL_TYPE_SET && to->real_type() != MYSQL_TYPE_BIT &&
 
763
        (to->real_type() != MYSQL_TYPE_NEWDECIMAL || (to->field_length == from->field_length && (((Field_num*)to)->dec == ((Field_num*)from)->dec))) &&
730
764
        from->charset() == to->charset() &&
731
765
        to->table->s->db_low_byte_first == from->table->s->db_low_byte_first &&
732
 
        (!(to->table->in_use->variables.sql_mode & (MODE_NO_ZERO_DATE | MODE_INVALID_DATES)) || (to->type() != DRIZZLE_TYPE_NEWDATE && to->type() != DRIZZLE_TYPE_DATETIME)) && 
733
 
        (from->real_type() != DRIZZLE_TYPE_VARCHAR || ((Field_varstring*)from)->length_bytes == ((Field_varstring*)to)->length_bytes))
 
766
        (!(to->table->in_use->variables.sql_mode & (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | MODE_INVALID_DATES)) || (to->type() != MYSQL_TYPE_DATE && to->type() != MYSQL_TYPE_DATETIME)) && 
 
767
        (from->real_type() != MYSQL_TYPE_VARCHAR || ((Field_varstring*)from)->length_bytes == ((Field_varstring*)to)->length_bytes))
734
768
    {                                           // Identical fields
735
769
#ifdef HAVE_purify
736
770
      /* This may happen if one does 'UPDATE ... SET x=x' */
740
774
      return 0;
741
775
    }
742
776
  }
743
 
  if (to->type() == DRIZZLE_TYPE_BLOB)
 
777
  if (to->type() == MYSQL_TYPE_BLOB)
744
778
  {                                             // Be sure the value is stored
745
779
    Field_blob *blob=(Field_blob*) to;
746
780
    from->val_str(&blob->value);
750
784
    */
751
785
    if (to->table->copy_blobs ||
752
786
        (!blob->value.is_alloced() &&
753
 
         from->real_type() != DRIZZLE_TYPE_VARCHAR))
 
787
         from->real_type() != MYSQL_TYPE_STRING &&
 
788
         from->real_type() != MYSQL_TYPE_VARCHAR))
754
789
      blob->value.copy();
755
790
    return blob->store(blob->value.ptr(),blob->value.length(),from->charset());
756
791
  }
757
 
  if (from->real_type() == DRIZZLE_TYPE_ENUM &&
758
 
      to->real_type() == DRIZZLE_TYPE_ENUM &&
 
792
  if (from->real_type() == MYSQL_TYPE_ENUM &&
 
793
      to->real_type() == MYSQL_TYPE_ENUM &&
759
794
      from->val_int() == 0)
760
795
  {
761
796
    ((Field_enum *)(to))->store_type(0);
763
798
  }
764
799
  else if ((from->result_type() == STRING_RESULT &&
765
800
            (to->result_type() == STRING_RESULT ||
766
 
             (from->real_type() != DRIZZLE_TYPE_ENUM))))
 
801
             (from->real_type() != MYSQL_TYPE_ENUM &&
 
802
              from->real_type() != MYSQL_TYPE_SET))) ||
 
803
           to->type() == MYSQL_TYPE_DECIMAL)
767
804
  {
768
805
    char buff[MAX_FIELD_WIDTH];
769
806
    String result(buff,sizeof(buff),from->charset());