1
/* Copyright (C) 2000-2003 MySQL AB
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.
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.
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 */
21
Functions to copy data to or from fields
23
This could be done with a single short function but opencoding this
24
gives much more speed.
27
#include <drizzled/server_includes.h>
29
static void do_field_eq(Copy_field *copy)
31
memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
34
static void do_field_1(Copy_field *copy)
36
copy->to_ptr[0]=copy->from_ptr[0];
39
static void do_field_2(Copy_field *copy)
41
copy->to_ptr[0]=copy->from_ptr[0];
42
copy->to_ptr[1]=copy->from_ptr[1];
45
static void do_field_3(Copy_field *copy)
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];
52
static void do_field_4(Copy_field *copy)
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];
60
static void do_field_6(Copy_field *copy)
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];
70
static void do_field_8(Copy_field *copy)
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];
83
static void do_field_to_null_str(Copy_field *copy)
85
if (*copy->from_null_ptr & copy->from_bit)
87
memset(copy->to_ptr, 0, copy->from_length);
88
copy->to_null_ptr[0]=1; // Always bit 1
92
copy->to_null_ptr[0]=0;
93
memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
98
static void do_outer_field_to_null_str(Copy_field *copy)
100
if (*copy->null_row ||
101
(copy->from_null_ptr && (*copy->from_null_ptr & copy->from_bit)))
103
memset(copy->to_ptr, 0, copy->from_length);
104
copy->to_null_ptr[0]=1; // Always bit 1
108
copy->to_null_ptr[0]=0;
109
memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
115
set_field_to_null(Field *field)
117
if (field->real_maybe_null())
124
if (field->table->in_use->count_cuted_fields == CHECK_FIELD_WARN)
126
field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
129
if (!field->table->in_use->no_errors)
130
my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name);
136
Set field to NULL or TIMESTAMP or to next auto_increment number.
138
@param field Field to update
139
@param no_conversions Set to 1 if we should return 1 if field can't
141
If set to 0 we will do store the 'default value'
142
if the field is a special field. If not we will
146
0 Field could take 0 or an automatic conversion was used
148
-1 Field could not take NULL and no conversion was used.
149
If no_conversion was not set, an error message is printed
153
set_field_to_null_with_conversions(Field *field, bool no_conversions)
155
if (field->real_maybe_null())
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).
169
if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
171
((Field_timestamp*) field)->set_time();
172
return 0; // Ok to set time to NULL
175
if (field == field->table->next_number_field)
177
field->table->auto_increment_field_not_null= false;
178
return 0; // field is set in fill_record()
180
if (field->table->in_use->count_cuted_fields == CHECK_FIELD_WARN)
182
field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_BAD_NULL_ERROR, 1);
185
if (!field->table->in_use->no_errors)
186
my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name);
191
static void do_skip(Copy_field *copy __attribute__((unused)))
196
static void do_copy_null(Copy_field *copy)
198
if (*copy->from_null_ptr & copy->from_bit)
200
*copy->to_null_ptr|=copy->to_bit;
201
copy->to_field->reset();
205
*copy->to_null_ptr&= ~copy->to_bit;
206
(copy->do_copy2)(copy);
211
static void do_outer_field_null(Copy_field *copy)
213
if (*copy->null_row ||
214
(copy->from_null_ptr && (*copy->from_null_ptr & copy->from_bit)))
216
*copy->to_null_ptr|=copy->to_bit;
217
copy->to_field->reset();
221
*copy->to_null_ptr&= ~copy->to_bit;
222
(copy->do_copy2)(copy);
227
static void do_copy_not_null(Copy_field *copy)
229
if (*copy->from_null_ptr & copy->from_bit)
231
copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
232
ER_WARN_DATA_TRUNCATED, 1);
233
copy->to_field->reset();
236
(copy->do_copy2)(copy);
240
static void do_copy_maybe_null(Copy_field *copy)
242
*copy->to_null_ptr&= ~copy->to_bit;
243
(copy->do_copy2)(copy);
246
/* timestamp and next_number has special handling in case of NULL values */
248
static void do_copy_timestamp(Copy_field *copy)
250
if (*copy->from_null_ptr & copy->from_bit)
252
/* Same as in set_field_to_null_with_conversions() */
253
((Field_timestamp*) copy->to_field)->set_time();
256
(copy->do_copy2)(copy);
260
static void do_copy_next_number(Copy_field *copy)
262
if (*copy->from_null_ptr & copy->from_bit)
264
/* Same as in set_field_to_null_with_conversions() */
265
copy->to_field->table->auto_increment_field_not_null= false;
266
copy->to_field->reset();
269
(copy->do_copy2)(copy);
273
static void do_copy_blob(Copy_field *copy)
275
ulong length=((Field_blob*) copy->from_field)->get_length();
276
((Field_blob*) copy->to_field)->store_length(length);
277
memcpy(copy->to_ptr,copy->from_ptr,sizeof(char*));
280
static void do_conv_blob(Copy_field *copy)
282
copy->from_field->val_str(©->tmp);
283
((Field_blob *) copy->to_field)->store(copy->tmp.ptr(),
285
copy->tmp.charset());
288
/** Save blob in copy->tmp for GROUP BY. */
290
static void do_save_blob(Copy_field *copy)
292
char buff[MAX_FIELD_WIDTH];
293
String res(buff,sizeof(buff),copy->tmp.charset());
294
copy->from_field->val_str(&res);
296
((Field_blob *) copy->to_field)->store(copy->tmp.ptr(),
298
copy->tmp.charset());
302
static void do_field_string(Copy_field *copy)
304
char buff[MAX_FIELD_WIDTH];
305
copy->tmp.set_quick(buff,sizeof(buff),copy->tmp.charset());
306
copy->from_field->val_str(©->tmp);
307
copy->to_field->store(copy->tmp.c_ptr_quick(),copy->tmp.length(),
308
copy->tmp.charset());
312
static void do_field_enum(Copy_field *copy)
314
if (copy->from_field->val_int() == 0)
315
((Field_enum *) copy->to_field)->store_type((uint64_t) 0);
317
do_field_string(copy);
321
static void do_field_int(Copy_field *copy)
323
int64_t value= copy->from_field->val_int();
324
copy->to_field->store(value,
325
test(copy->from_field->flags & UNSIGNED_FLAG));
328
static void do_field_real(Copy_field *copy)
330
double value=copy->from_field->val_real();
331
copy->to_field->store(value);
335
static void do_field_decimal(Copy_field *copy)
338
copy->to_field->store_decimal(copy->from_field->val_decimal(&value));
343
string copy for single byte characters set when to string is shorter than
347
static void do_cut_string(Copy_field *copy)
349
const CHARSET_INFO * const cs= copy->from_field->charset();
350
memcpy(copy->to_ptr,copy->from_ptr,copy->to_length);
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)
358
copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
359
ER_WARN_DATA_TRUNCATED, 1);
365
string copy for multi byte characters set when to string is shorter than
369
static void do_cut_string_complex(Copy_field *copy)
370
{ // Shorter string field
371
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,
375
(char*) copy->from_ptr,
377
copy->to_length / cs->mbmaxlen,
379
if (copy->to_length < copy_length)
380
copy_length= copy->to_length;
381
memcpy(copy->to_ptr, copy->from_ptr, copy_length);
383
/* Check if we lost any important characters */
384
if (well_formed_error ||
385
cs->cset->scan(cs, (char*) copy->from_ptr + copy_length,
387
MY_SEQ_SPACES) < (copy->from_length - copy_length))
389
copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
390
ER_WARN_DATA_TRUNCATED, 1);
393
if (copy_length < copy->to_length)
394
cs->cset->fill(cs, (char*) copy->to_ptr + copy_length,
395
copy->to_length - copy_length, ' ');
401
static void do_expand_binary(Copy_field *copy)
403
const CHARSET_INFO * const cs= copy->from_field->charset();
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');
411
static void do_expand_string(Copy_field *copy)
413
const CHARSET_INFO * const cs= copy->from_field->charset();
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, ' ');
420
static void do_varstring1(Copy_field *copy)
422
uint32_t length= (uint) *(unsigned char*) copy->from_ptr;
423
if (length > copy->to_length- 1)
425
length=copy->to_length - 1;
426
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);
430
*(unsigned char*) copy->to_ptr= (unsigned char) length;
431
memcpy(copy->to_ptr+1, copy->from_ptr + 1, length);
435
static void do_varstring1_mb(Copy_field *copy)
437
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,
443
(char*) from_ptr + from_length,
444
to_char_length, &well_formed_error);
445
if (length < from_length)
447
if (current_thd->count_cuted_fields)
448
copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
449
ER_WARN_DATA_TRUNCATED, 1);
451
*copy->to_ptr= (unsigned char) length;
452
memcpy(copy->to_ptr + 1, from_ptr, length);
456
static void do_varstring2(Copy_field *copy)
458
uint32_t length=uint2korr(copy->from_ptr);
459
if (length > copy->to_length- HA_KEY_BLOB_LENGTH)
461
length=copy->to_length-HA_KEY_BLOB_LENGTH;
462
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);
466
int2store(copy->to_ptr,length);
467
memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, copy->from_ptr + HA_KEY_BLOB_LENGTH,
472
static void do_varstring2_mb(Copy_field *copy)
474
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,
480
(char*) from_beg + from_length,
481
char_length, &well_formed_error);
482
if (length < from_length)
484
if (current_thd->count_cuted_fields)
485
copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
486
ER_WARN_DATA_TRUNCATED, 1);
488
int2store(copy->to_ptr, length);
489
memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, from_beg, length);
493
/***************************************************************************
494
** The different functions that fills in a Copy_field class
495
***************************************************************************/
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
505
void Copy_field::set(unsigned char *to,Field *from)
509
from_length=from->pack_length();
510
if (from->maybe_null())
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= (unsigned char*) to_ptr++;
517
if (from->table->maybe_null)
519
null_row= &from->table->null_row;
520
do_copy= do_outer_field_to_null_str;
523
do_copy= do_field_to_null_str;
527
to_null_ptr= 0; // For easy debugging
528
do_copy= do_field_eq;
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
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.
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.
548
void Copy_field::set(Field *to,Field *from,bool save)
550
if (to->type() == DRIZZLE_TYPE_NULL)
552
to_null_ptr=0; // For easy debugging
560
from_length=from->pack_length();
562
to_length=to_field->pack_length();
564
// set up null handling
565
from_null_ptr=to_null_ptr=0;
566
if (from->maybe_null())
568
from_null_ptr= from->null_ptr;
569
from_bit= from->null_bit;
570
if (to_field->real_maybe_null())
572
to_null_ptr= to->null_ptr;
573
to_bit= to->null_bit;
575
do_copy= do_copy_null;
578
null_row= &from->table->null_row;
579
do_copy= do_outer_field_null;
584
if (to_field->type() == DRIZZLE_TYPE_TIMESTAMP)
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;
589
do_copy= do_copy_not_null;
592
else if (to_field->real_maybe_null())
594
to_null_ptr= to->null_ptr;
595
to_bit= to->null_bit;
596
do_copy= do_copy_maybe_null;
601
if ((to->flags & BLOB_FLAG) && save)
602
do_copy2= do_save_blob;
604
do_copy2= get_copy_func(to,from);
605
if (!do_copy) // Not null
610
Copy_field::Copy_func *
611
Copy_field::get_copy_func(Field *to,Field *from)
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)
617
if (!(from->flags & BLOB_FLAG) || from->charset() != to->charset())
619
if (from_length != to_length || !compatible_db_low_byte_first)
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;
629
if (to->result_type() == DECIMAL_RESULT)
630
return do_field_decimal;
631
// Check if identical fields
632
if (from->result_type() == STRING_RESULT)
635
If we are copying date or datetime's we have to check the dates
636
if we don't allow 'all' dates.
638
if (to->real_type() != from->real_type() ||
639
!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))
642
if (from->real_type() == DRIZZLE_TYPE_ENUM)
643
if (to->result_type() != STRING_RESULT)
644
return do_field_int; // Convert SET to number
645
return do_field_string;
647
if (to->real_type() == DRIZZLE_TYPE_ENUM)
649
if (!to->eq_def(from))
651
if (from->real_type() == DRIZZLE_TYPE_ENUM &&
652
to->real_type() == DRIZZLE_TYPE_ENUM)
653
return do_field_enum;
655
return do_field_string;
658
else if (to->charset() != from->charset())
659
return do_field_string;
660
else if (to->real_type() == DRIZZLE_TYPE_VARCHAR)
662
if (((Field_varstring*) to)->length_bytes !=
663
((Field_varstring*) from)->length_bytes)
664
return do_field_string;
665
if (to_length != from_length)
666
return (((Field_varstring*) to)->length_bytes == 1 ?
667
(from->charset()->mbmaxlen == 1 ? do_varstring1 :
669
(from->charset()->mbmaxlen == 1 ? do_varstring2 :
672
else if (to_length < from_length)
673
return (from->charset()->mbmaxlen == 1 ?
674
do_cut_string : do_cut_string_complex);
675
else if (to_length > from_length)
677
if (to->charset() == &my_charset_bin)
678
return do_expand_binary;
680
return do_expand_string;
684
else if (to->real_type() != from->real_type() ||
685
to_length != from_length ||
686
!compatible_db_low_byte_first)
688
if (to->result_type() == STRING_RESULT)
689
return do_field_string;
690
if (to->result_type() == INT_RESULT)
692
return do_field_real;
696
if (!to->eq_def(from) || !compatible_db_low_byte_first)
698
if (to->result_type() == INT_RESULT)
701
return do_field_real;
707
case 1: return do_field_1;
708
case 2: return do_field_2;
709
case 3: return do_field_3;
710
case 4: return do_field_4;
711
case 6: return do_field_6;
712
case 8: return do_field_8;
718
/** Simple quick field convert that is called on insert. */
720
int field_conv(Field *to,Field *from)
722
if (to->real_type() == from->real_type() &&
723
!(to->type() == DRIZZLE_TYPE_BLOB && to->table->copy_blobs))
725
/* Please god, will someone rewrite this to be readable :( */
726
if (to->pack_length() == from->pack_length() &&
727
!(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))) &&
730
from->charset() == to->charset() &&
731
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))
734
{ // Identical fields
736
/* This may happen if one does 'UPDATE ... SET x=x' */
737
if (to->ptr != from->ptr)
739
memcpy(to->ptr,from->ptr,to->pack_length());
743
if (to->type() == DRIZZLE_TYPE_BLOB)
744
{ // Be sure the value is stored
745
Field_blob *blob=(Field_blob*) to;
746
from->val_str(&blob->value);
748
Copy value if copy_blobs is set, or source is not a string and
749
we have a pointer to its internal string conversion buffer.
751
if (to->table->copy_blobs ||
752
(!blob->value.is_alloced() &&
753
from->real_type() != DRIZZLE_TYPE_VARCHAR))
755
return blob->store(blob->value.ptr(),blob->value.length(),from->charset());
757
if (from->real_type() == DRIZZLE_TYPE_ENUM &&
758
to->real_type() == DRIZZLE_TYPE_ENUM &&
759
from->val_int() == 0)
761
((Field_enum *)(to))->store_type(0);
764
else if ((from->result_type() == STRING_RESULT &&
765
(to->result_type() == STRING_RESULT ||
766
(from->real_type() != DRIZZLE_TYPE_ENUM))))
768
char buff[MAX_FIELD_WIDTH];
769
String result(buff,sizeof(buff),from->charset());
770
from->val_str(&result);
772
We use c_ptr_quick() here to make it easier if to is a float/double
773
as the conversion routines will do a copy of the result doesn't
774
end with \0. Can be replaced with .ptr() when we have our own
775
string->double conversion.
777
return to->store(result.c_ptr_quick(),result.length(),from->charset());
779
else if (from->result_type() == REAL_RESULT)
780
return to->store(from->val_real());
781
else if (from->result_type() == DECIMAL_RESULT)
784
return to->store_decimal(from->val_decimal(&buff));
787
return to->store(from->val_int(), test(from->flags & UNSIGNED_FLAG));