~drizzle-trunk/drizzle/development

1 by brian
clean slate
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
17
/**
18
  @file
19
20
  @brief
21
  Functions to copy data to or from fields
22
23
    This could be done with a single short function but opencoding this
24
    gives much more speed.
25
*/
26
243.1.17 by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.)
27
#include <drizzled/server_includes.h>
550 by Monty Taylor
Moved error.h into just the files that need it.
28
#include <drizzled/error.h>
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
29
#include <drizzled/table.h>
30
#include <drizzled/session.h>
1 by brian
clean slate
31
584.5.1 by Monty Taylor
Removed field includes from field.h.
32
#include <drizzled/field/str.h>
33
#include <drizzled/field/longstr.h>
34
#include <drizzled/field/num.h>
35
#include <drizzled/field/blob.h>
36
#include <drizzled/field/enum.h>
37
#include <drizzled/field/null.h>
38
#include <drizzled/field/date.h>
670.1.1 by Monty Taylor
Renamed fdecimal.* to decimal.*. Let's see how many things we can break!
39
#include <drizzled/field/decimal.h>
584.5.1 by Monty Taylor
Removed field includes from field.h.
40
#include <drizzled/field/real.h>
41
#include <drizzled/field/double.h>
42
#include <drizzled/field/long.h>
43
#include <drizzled/field/int64_t.h>
44
#include <drizzled/field/num.h>
45
#include <drizzled/field/timestamp.h>
46
#include <drizzled/field/datetime.h>
47
#include <drizzled/field/varstring.h>
48
49
1 by brian
clean slate
50
static void do_field_eq(Copy_field *copy)
51
{
52
  memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
53
}
54
55
static void do_field_1(Copy_field *copy)
56
{
57
  copy->to_ptr[0]=copy->from_ptr[0];
58
}
59
60
static void do_field_2(Copy_field *copy)
61
{
62
  copy->to_ptr[0]=copy->from_ptr[0];
63
  copy->to_ptr[1]=copy->from_ptr[1];
64
}
65
66
static void do_field_3(Copy_field *copy)
67
{
68
  copy->to_ptr[0]=copy->from_ptr[0];
69
  copy->to_ptr[1]=copy->from_ptr[1];
70
  copy->to_ptr[2]=copy->from_ptr[2];
71
}
72
73
static void do_field_4(Copy_field *copy)
74
{
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
}
80
81
static void do_field_6(Copy_field *copy)
82
{						// For blob field
83
  copy->to_ptr[0]=copy->from_ptr[0];
84
  copy->to_ptr[1]=copy->from_ptr[1];
85
  copy->to_ptr[2]=copy->from_ptr[2];
86
  copy->to_ptr[3]=copy->from_ptr[3];
87
  copy->to_ptr[4]=copy->from_ptr[4];
88
  copy->to_ptr[5]=copy->from_ptr[5];
89
}
90
91
static void do_field_8(Copy_field *copy)
92
{
93
  copy->to_ptr[0]=copy->from_ptr[0];
94
  copy->to_ptr[1]=copy->from_ptr[1];
95
  copy->to_ptr[2]=copy->from_ptr[2];
96
  copy->to_ptr[3]=copy->from_ptr[3];
97
  copy->to_ptr[4]=copy->from_ptr[4];
98
  copy->to_ptr[5]=copy->from_ptr[5];
99
  copy->to_ptr[6]=copy->from_ptr[6];
100
  copy->to_ptr[7]=copy->from_ptr[7];
101
}
102
103
104
static void do_field_to_null_str(Copy_field *copy)
105
{
106
  if (*copy->from_null_ptr & copy->from_bit)
107
  {
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
108
    memset(copy->to_ptr, 0, copy->from_length);
1 by brian
clean slate
109
    copy->to_null_ptr[0]=1;			// Always bit 1
110
  }
111
  else
112
  {
113
    copy->to_null_ptr[0]=0;
114
    memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
115
  }
116
}
117
118
119
static void do_outer_field_to_null_str(Copy_field *copy)
120
{
121
  if (*copy->null_row ||
122
      (copy->from_null_ptr && (*copy->from_null_ptr & copy->from_bit)))
123
  {
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
124
    memset(copy->to_ptr, 0, copy->from_length);
1 by brian
clean slate
125
    copy->to_null_ptr[0]=1;			// Always bit 1
126
  }
127
  else
128
  {
129
    copy->to_null_ptr[0]=0;
130
    memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
131
  }
132
}
133
134
135
int
136
set_field_to_null(Field *field)
137
{
138
  if (field->real_maybe_null())
139
  {
140
    field->set_null();
141
    field->reset();
142
    return 0;
143
  }
144
  field->reset();
685.4.2 by Jay Pipes
Added back truncation warnings. The NULL error is triggered from: session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL, not CHECK_FIELD_WARN
145
  if (field->table->in_use->count_cuted_fields == CHECK_FIELD_WARN)
146
  {
147
    field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
148
    return 0;
149
  }
1 by brian
clean slate
150
  if (!field->table->in_use->no_errors)
151
    my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name);
152
  return -1;
153
}
154
155
156
/**
157
  Set field to NULL or TIMESTAMP or to next auto_increment number.
158
159
  @param field           Field to update
160
  @param no_conversions  Set to 1 if we should return 1 if field can't
161
                         take null values.
162
                         If set to 0 we will do store the 'default value'
163
                         if the field is a special field. If not we will
164
                         give an error.
165
166
  @retval
167
    0    Field could take 0 or an automatic conversion was used
168
  @retval
169
    -1   Field could not take NULL and no conversion was used.
170
    If no_conversion was not set, an error message is printed
171
*/
172
173
int
174
set_field_to_null_with_conversions(Field *field, bool no_conversions)
175
{
176
  if (field->real_maybe_null())
177
  {
178
    field->set_null();
179
    field->reset();
180
    return 0;
181
  }
182
  if (no_conversions)
183
    return -1;
184
185
  /*
186
    Check if this is a special type, which will get a special walue
187
    when set to NULL (TIMESTAMP fields which allow setting to NULL
188
    are handled by first check).
189
  */
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
190
  if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
1 by brian
clean slate
191
  {
192
    ((Field_timestamp*) field)->set_time();
193
    return 0;					// Ok to set time to NULL
194
  }
195
  field->reset();
196
  if (field == field->table->next_number_field)
197
  {
163 by Brian Aker
Merge Monty's code.
198
    field->table->auto_increment_field_not_null= false;
1 by brian
clean slate
199
    return 0;				  // field is set in fill_record()
200
  }
685.4.2 by Jay Pipes
Added back truncation warnings. The NULL error is triggered from: session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL, not CHECK_FIELD_WARN
201
  if (field->table->in_use->count_cuted_fields == CHECK_FIELD_WARN)
202
  {
203
    field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_BAD_NULL_ERROR, 1);
204
    return 0;
205
  }
1 by brian
clean slate
206
  if (!field->table->in_use->no_errors)
207
    my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name);
208
  return -1;
209
}
210
211
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
212
static void do_skip(Copy_field *)
1 by brian
clean slate
213
{
214
}
215
216
217
static void do_copy_null(Copy_field *copy)
218
{
219
  if (*copy->from_null_ptr & copy->from_bit)
220
  {
221
    *copy->to_null_ptr|=copy->to_bit;
222
    copy->to_field->reset();
223
  }
224
  else
225
  {
226
    *copy->to_null_ptr&= ~copy->to_bit;
227
    (copy->do_copy2)(copy);
228
  }
229
}
230
231
232
static void do_outer_field_null(Copy_field *copy)
233
{
234
  if (*copy->null_row ||
235
      (copy->from_null_ptr && (*copy->from_null_ptr & copy->from_bit)))
236
  {
237
    *copy->to_null_ptr|=copy->to_bit;
238
    copy->to_field->reset();
239
  }
240
  else
241
  {
242
    *copy->to_null_ptr&= ~copy->to_bit;
243
    (copy->do_copy2)(copy);
244
  }
245
}
246
247
248
static void do_copy_not_null(Copy_field *copy)
249
{
250
  if (*copy->from_null_ptr & copy->from_bit)
251
  {
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
252
    copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
212.5.42 by Monty Taylor
Ding dong include is dead.
253
                                ER_WARN_DATA_TRUNCATED, 1);
1 by brian
clean slate
254
    copy->to_field->reset();
255
  }
256
  else
257
    (copy->do_copy2)(copy);
258
}
259
260
261
static void do_copy_maybe_null(Copy_field *copy)
262
{
263
  *copy->to_null_ptr&= ~copy->to_bit;
264
  (copy->do_copy2)(copy);
265
}
266
267
/* timestamp and next_number has special handling in case of NULL values */
268
269
static void do_copy_timestamp(Copy_field *copy)
270
{
271
  if (*copy->from_null_ptr & copy->from_bit)
272
  {
273
    /* Same as in set_field_to_null_with_conversions() */
274
    ((Field_timestamp*) copy->to_field)->set_time();
275
  }
276
  else
277
    (copy->do_copy2)(copy);
278
}
279
280
281
static void do_copy_next_number(Copy_field *copy)
282
{
283
  if (*copy->from_null_ptr & copy->from_bit)
284
  {
285
    /* Same as in set_field_to_null_with_conversions() */
163 by Brian Aker
Merge Monty's code.
286
    copy->to_field->table->auto_increment_field_not_null= false;
1 by brian
clean slate
287
    copy->to_field->reset();
288
  }
289
  else
290
    (copy->do_copy2)(copy);
291
}
292
293
294
static void do_copy_blob(Copy_field *copy)
295
{
296
  ulong length=((Field_blob*) copy->from_field)->get_length();
297
  ((Field_blob*) copy->to_field)->store_length(length);
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
298
  memcpy(copy->to_ptr,copy->from_ptr,sizeof(char*));
1 by brian
clean slate
299
}
300
301
static void do_conv_blob(Copy_field *copy)
302
{
303
  copy->from_field->val_str(&copy->tmp);
304
  ((Field_blob *) copy->to_field)->store(copy->tmp.ptr(),
305
					 copy->tmp.length(),
306
					 copy->tmp.charset());
307
}
308
309
/** Save blob in copy->tmp for GROUP BY. */
310
311
static void do_save_blob(Copy_field *copy)
312
{
313
  char buff[MAX_FIELD_WIDTH];
314
  String res(buff,sizeof(buff),copy->tmp.charset());
315
  copy->from_field->val_str(&res);
316
  copy->tmp.copy(res);
317
  ((Field_blob *) copy->to_field)->store(copy->tmp.ptr(),
318
					 copy->tmp.length(),
319
					 copy->tmp.charset());
320
}
321
322
323
static void do_field_string(Copy_field *copy)
324
{
325
  char buff[MAX_FIELD_WIDTH];
326
  copy->tmp.set_quick(buff,sizeof(buff),copy->tmp.charset());
327
  copy->from_field->val_str(&copy->tmp);
328
  copy->to_field->store(copy->tmp.c_ptr_quick(),copy->tmp.length(),
329
                        copy->tmp.charset());
330
}
331
332
333
static void do_field_enum(Copy_field *copy)
334
{
335
  if (copy->from_field->val_int() == 0)
151 by Brian Aker
Ulonglong to uint64_t
336
    ((Field_enum *) copy->to_field)->store_type((uint64_t) 0);
1 by brian
clean slate
337
  else
338
    do_field_string(copy);
339
}
340
341
342
static void do_field_int(Copy_field *copy)
343
{
152 by Brian Aker
longlong replacement
344
  int64_t value= copy->from_field->val_int();
1 by brian
clean slate
345
  copy->to_field->store(value,
346
                        test(copy->from_field->flags & UNSIGNED_FLAG));
347
}
348
349
static void do_field_real(Copy_field *copy)
350
{
351
  double value=copy->from_field->val_real();
352
  copy->to_field->store(value);
353
}
354
355
356
static void do_field_decimal(Copy_field *copy)
357
{
358
  my_decimal value;
359
  copy->to_field->store_decimal(copy->from_field->val_decimal(&value));
360
}
361
362
363
/**
364
  string copy for single byte characters set when to string is shorter than
365
  from string.
366
*/
367
368
static void do_cut_string(Copy_field *copy)
369
{
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
370
  const CHARSET_INFO * const cs= copy->from_field->charset();
1 by brian
clean slate
371
  memcpy(copy->to_ptr,copy->from_ptr,copy->to_length);
372
373
  /* Check if we loosed any important characters */
374
  if (cs->cset->scan(cs,
375
                     (char*) copy->from_ptr + copy->to_length,
376
                     (char*) copy->from_ptr + copy->from_length,
377
                     MY_SEQ_SPACES) < copy->from_length - copy->to_length)
378
  {
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
379
    copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
212.5.42 by Monty Taylor
Ding dong include is dead.
380
                                ER_WARN_DATA_TRUNCATED, 1);
1 by brian
clean slate
381
  }
382
}
383
384
385
/**
386
  string copy for multi byte characters set when to string is shorter than
387
  from string.
388
*/
389
390
static void do_cut_string_complex(Copy_field *copy)
391
{						// Shorter string field
392
  int well_formed_error;
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
393
  const CHARSET_INFO * const cs= copy->from_field->charset();
481 by Brian Aker
Remove all of uchar.
394
  const unsigned char *from_end= copy->from_ptr + copy->from_length;
482 by Brian Aker
Remove uint.
395
  uint32_t copy_length= cs->cset->well_formed_len(cs,
1 by brian
clean slate
396
                                              (char*) copy->from_ptr,
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
397
                                              (char*) from_end,
1 by brian
clean slate
398
                                              copy->to_length / cs->mbmaxlen,
399
                                              &well_formed_error);
400
  if (copy->to_length < copy_length)
401
    copy_length= copy->to_length;
402
  memcpy(copy->to_ptr, copy->from_ptr, copy_length);
403
404
  /* Check if we lost any important characters */
405
  if (well_formed_error ||
406
      cs->cset->scan(cs, (char*) copy->from_ptr + copy_length,
407
                     (char*) from_end,
408
                     MY_SEQ_SPACES) < (copy->from_length - copy_length))
409
  {
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
410
    copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
212.5.42 by Monty Taylor
Ding dong include is dead.
411
                                ER_WARN_DATA_TRUNCATED, 1);
1 by brian
clean slate
412
  }
413
414
  if (copy_length < copy->to_length)
415
    cs->cset->fill(cs, (char*) copy->to_ptr + copy_length,
416
                   copy->to_length - copy_length, ' ');
417
}
418
419
420
421
422
static void do_expand_binary(Copy_field *copy)
423
{
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
424
  const CHARSET_INFO * const cs= copy->from_field->charset();
1 by brian
clean slate
425
  memcpy(copy->to_ptr,copy->from_ptr,copy->from_length);
426
  cs->cset->fill(cs, (char*) copy->to_ptr+copy->from_length,
427
                     copy->to_length-copy->from_length, '\0');
428
}
429
430
431
432
static void do_expand_string(Copy_field *copy)
433
{
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
434
  const CHARSET_INFO * const cs= copy->from_field->charset();
1 by brian
clean slate
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, ' ');
438
}
439
440
441
static void do_varstring1(Copy_field *copy)
442
{
895 by Brian Aker
Completion (?) of uint conversion.
443
  uint32_t length= (uint32_t) *(unsigned char*) copy->from_ptr;
1 by brian
clean slate
444
  if (length > copy->to_length- 1)
445
  {
446
    length=copy->to_length - 1;
447
    if (copy->from_field->table->in_use->count_cuted_fields)
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
448
      copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
212.5.42 by Monty Taylor
Ding dong include is dead.
449
                                  ER_WARN_DATA_TRUNCATED, 1);
1 by brian
clean slate
450
  }
481 by Brian Aker
Remove all of uchar.
451
  *(unsigned char*) copy->to_ptr= (unsigned char) length;
1 by brian
clean slate
452
  memcpy(copy->to_ptr+1, copy->from_ptr + 1, length);
453
}
454
455
456
static void do_varstring1_mb(Copy_field *copy)
457
{
458
  int well_formed_error;
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
459
  const CHARSET_INFO * const cs= copy->from_field->charset();
895 by Brian Aker
Completion (?) of uint conversion.
460
  uint32_t from_length= (uint32_t) *(unsigned char*) copy->from_ptr;
481 by Brian Aker
Remove all of uchar.
461
  const unsigned char *from_ptr= copy->from_ptr + 1;
482 by Brian Aker
Remove uint.
462
  uint32_t to_char_length= (copy->to_length - 1) / cs->mbmaxlen;
463
  uint32_t length= cs->cset->well_formed_len(cs, (char*) from_ptr,
1 by brian
clean slate
464
                                         (char*) from_ptr + from_length,
465
                                         to_char_length, &well_formed_error);
466
  if (length < from_length)
467
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
468
    if (current_session->count_cuted_fields)
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
469
      copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
212.5.42 by Monty Taylor
Ding dong include is dead.
470
                                  ER_WARN_DATA_TRUNCATED, 1);
1 by brian
clean slate
471
  }
481 by Brian Aker
Remove all of uchar.
472
  *copy->to_ptr= (unsigned char) length;
1 by brian
clean slate
473
  memcpy(copy->to_ptr + 1, from_ptr, length);
474
}
475
476
477
static void do_varstring2(Copy_field *copy)
478
{
482 by Brian Aker
Remove uint.
479
  uint32_t length=uint2korr(copy->from_ptr);
1 by brian
clean slate
480
  if (length > copy->to_length- HA_KEY_BLOB_LENGTH)
481
  {
482
    length=copy->to_length-HA_KEY_BLOB_LENGTH;
483
    if (copy->from_field->table->in_use->count_cuted_fields)
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
484
      copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
212.5.42 by Monty Taylor
Ding dong include is dead.
485
                                  ER_WARN_DATA_TRUNCATED, 1);
1 by brian
clean slate
486
  }
487
  int2store(copy->to_ptr,length);
488
  memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, copy->from_ptr + HA_KEY_BLOB_LENGTH,
489
         length);
490
}
491
492
493
static void do_varstring2_mb(Copy_field *copy)
494
{
495
  int well_formed_error;
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
496
  const CHARSET_INFO * const cs= copy->from_field->charset();
482 by Brian Aker
Remove uint.
497
  uint32_t char_length= (copy->to_length - HA_KEY_BLOB_LENGTH) / cs->mbmaxlen;
498
  uint32_t from_length= uint2korr(copy->from_ptr);
481 by Brian Aker
Remove all of uchar.
499
  const unsigned char *from_beg= copy->from_ptr + HA_KEY_BLOB_LENGTH;
482 by Brian Aker
Remove uint.
500
  uint32_t length= cs->cset->well_formed_len(cs, (char*) from_beg,
1 by brian
clean slate
501
                                         (char*) from_beg + from_length,
502
                                         char_length, &well_formed_error);
503
  if (length < from_length)
504
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
505
    if (current_session->count_cuted_fields)
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
506
      copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
212.5.42 by Monty Taylor
Ding dong include is dead.
507
                                  ER_WARN_DATA_TRUNCATED, 1);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
508
  }
1 by brian
clean slate
509
  int2store(copy->to_ptr, length);
510
  memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, from_beg, length);
511
}
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
512
1 by brian
clean slate
513
514
/***************************************************************************
515
** The different functions that fills in a Copy_field class
516
***************************************************************************/
517
518
/**
519
  copy of field to maybe null string.
520
  If field is null then the all bytes are set to 0.
521
  if field is not null then the first byte is set to 1 and the rest of the
522
  string is the field value.
523
  The 'to' buffer should have a size of field->pack_length()+1
524
*/
525
481 by Brian Aker
Remove all of uchar.
526
void Copy_field::set(unsigned char *to,Field *from)
1 by brian
clean slate
527
{
528
  from_ptr=from->ptr;
529
  to_ptr=to;
530
  from_length=from->pack_length();
531
  if (from->maybe_null())
532
  {
533
    from_null_ptr=from->null_ptr;
534
    from_bit=	  from->null_bit;
535
    to_ptr[0]=	  1;				// Null as default value
481 by Brian Aker
Remove all of uchar.
536
    to_null_ptr=  (unsigned char*) to_ptr++;
1 by brian
clean slate
537
    to_bit=	  1;
538
    if (from->table->maybe_null)
539
    {
540
      null_row=   &from->table->null_row;
541
      do_copy=	  do_outer_field_to_null_str;
542
    }
543
    else
544
      do_copy=	  do_field_to_null_str;
545
  }
546
  else
547
  {
548
    to_null_ptr=  0;				// For easy debugging
549
    do_copy=	  do_field_eq;
550
  }
551
}
552
553
554
/*
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
555
  To do:
1 by brian
clean slate
556
557
  If 'save\ is set to true and the 'from' is a blob field, do_copy is set to
558
  do_save_blob rather than do_conv_blob.  The only differences between them
559
  appears to be:
560
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
561
  - do_save_blob allocates and uses an intermediate buffer before calling
562
    Field_blob::store. Is this in order to trigger the call to
1 by brian
clean slate
563
    well_formed_copy_nchars, by changing the pointer copy->tmp.ptr()?
564
    That call will take place anyway in all known cases.
565
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
566
  - The above causes a truncation to MAX_FIELD_WIDTH. Is this the intended
1 by brian
clean slate
567
    effect? Truncation is handled by well_formed_copy_nchars anyway.
568
 */
569
void Copy_field::set(Field *to,Field *from,bool save)
570
{
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
571
  if (to->type() == DRIZZLE_TYPE_NULL)
1 by brian
clean slate
572
  {
573
    to_null_ptr=0;				// For easy debugging
574
    to_ptr=0;
575
    do_copy=do_skip;
576
    return;
577
  }
578
  from_field=from;
579
  to_field=to;
580
  from_ptr=from->ptr;
581
  from_length=from->pack_length();
582
  to_ptr=  to->ptr;
583
  to_length=to_field->pack_length();
584
585
  // set up null handling
586
  from_null_ptr=to_null_ptr=0;
587
  if (from->maybe_null())
588
  {
589
    from_null_ptr=	from->null_ptr;
590
    from_bit=		from->null_bit;
591
    if (to_field->real_maybe_null())
592
    {
593
      to_null_ptr=	to->null_ptr;
594
      to_bit=		to->null_bit;
595
      if (from_null_ptr)
596
	do_copy=	do_copy_null;
597
      else
598
      {
599
	null_row=	&from->table->null_row;
600
	do_copy=	do_outer_field_null;
601
      }
602
    }
603
    else
604
    {
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
605
      if (to_field->type() == DRIZZLE_TYPE_TIMESTAMP)
1 by brian
clean slate
606
        do_copy= do_copy_timestamp;               // Automatic timestamp
607
      else if (to_field == to_field->table->next_number_field)
608
        do_copy= do_copy_next_number;
609
      else
610
        do_copy= do_copy_not_null;
611
    }
612
  }
613
  else if (to_field->real_maybe_null())
614
  {
615
    to_null_ptr=	to->null_ptr;
616
    to_bit=		to->null_bit;
617
    do_copy= do_copy_maybe_null;
618
  }
619
  else
620
   do_copy=0;
621
622
  if ((to->flags & BLOB_FLAG) && save)
623
    do_copy2= do_save_blob;
624
  else
625
    do_copy2= get_copy_func(to,from);
626
  if (!do_copy)					// Not null
627
    do_copy=do_copy2;
628
}
629
630
631
Copy_field::Copy_func *
632
Copy_field::get_copy_func(Field *to,Field *from)
633
{
634
  bool compatible_db_low_byte_first= (to->table->s->db_low_byte_first ==
635
                                     from->table->s->db_low_byte_first);
636
  if (to->flags & BLOB_FLAG)
637
  {
638
    if (!(from->flags & BLOB_FLAG) || from->charset() != to->charset())
639
      return do_conv_blob;
640
    if (from_length != to_length || !compatible_db_low_byte_first)
641
    {
642
      // Correct pointer to point at char pointer
643
      to_ptr+=   to_length - to->table->s->blob_ptr_size;
644
      from_ptr+= from_length- from->table->s->blob_ptr_size;
645
      return do_copy_blob;
646
    }
647
  }
648
  else
649
  {
650
    if (to->result_type() == DECIMAL_RESULT)
651
      return do_field_decimal;
652
    // Check if identical fields
653
    if (from->result_type() == STRING_RESULT)
654
    {
655
      /*
656
        If we are copying date or datetime's we have to check the dates
657
        if we don't allow 'all' dates.
658
      */
659
      if (to->real_type() != from->real_type() ||
660
          !compatible_db_low_byte_first ||
575.5.1 by David Axmark
Changed NEWDATE to DATE. One failing test but I think its somewhere else in the code
661
          (((to->table->in_use->variables.sql_mode & (MODE_NO_ZERO_DATE | MODE_INVALID_DATES)) && to->type() == DRIZZLE_TYPE_DATE) || to->type() == DRIZZLE_TYPE_DATETIME))
1 by brian
clean slate
662
      {
325 by Brian Aker
Remove SET
663
	if (from->real_type() == DRIZZLE_TYPE_ENUM)
1 by brian
clean slate
664
	  if (to->result_type() != STRING_RESULT)
665
	    return do_field_int;		// Convert SET to number
666
	return do_field_string;
667
      }
325 by Brian Aker
Remove SET
668
      if (to->real_type() == DRIZZLE_TYPE_ENUM)
1 by brian
clean slate
669
      {
670
	if (!to->eq_def(from))
671
        {
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
672
          if (from->real_type() == DRIZZLE_TYPE_ENUM &&
673
              to->real_type() == DRIZZLE_TYPE_ENUM)
1 by brian
clean slate
674
            return do_field_enum;
675
          else
676
            return do_field_string;
677
        }
678
      }
679
      else if (to->charset() != from->charset())
680
	return do_field_string;
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
681
      else if (to->real_type() == DRIZZLE_TYPE_VARCHAR)
1 by brian
clean slate
682
      {
683
        if (((Field_varstring*) to)->length_bytes !=
684
            ((Field_varstring*) from)->length_bytes)
685
          return do_field_string;
686
        if (to_length != from_length)
687
          return (((Field_varstring*) to)->length_bytes == 1 ?
688
                  (from->charset()->mbmaxlen == 1 ? do_varstring1 :
689
                                                    do_varstring1_mb) :
690
                  (from->charset()->mbmaxlen == 1 ? do_varstring2 :
691
                                                    do_varstring2_mb));
692
      }
693
      else if (to_length < from_length)
694
	return (from->charset()->mbmaxlen == 1 ?
695
                do_cut_string : do_cut_string_complex);
696
      else if (to_length > from_length)
697
      {
698
        if (to->charset() == &my_charset_bin)
699
          return do_expand_binary;
700
        else
701
          return do_expand_string;
702
      }
703
704
    }
705
    else if (to->real_type() != from->real_type() ||
706
	     to_length != from_length ||
707
             !compatible_db_low_byte_first)
708
    {
80 by Brian Aker
Most of the removal of dead DECIMAL type
709
      if (to->result_type() == STRING_RESULT)
1 by brian
clean slate
710
	return do_field_string;
711
      if (to->result_type() == INT_RESULT)
712
	return do_field_int;
713
      return do_field_real;
714
    }
715
    else
716
    {
717
      if (!to->eq_def(from) || !compatible_db_low_byte_first)
718
      {
719
	if (to->result_type() == INT_RESULT)
720
	  return do_field_int;
721
	else
722
	  return do_field_real;
723
      }
724
    }
725
  }
726
    /* Eq fields */
727
  switch (to_length) {
728
  case 1: return do_field_1;
729
  case 2: return do_field_2;
730
  case 3: return do_field_3;
731
  case 4: return do_field_4;
732
  case 6: return do_field_6;
733
  case 8: return do_field_8;
734
  }
735
  return do_field_eq;
736
}
737
738
739
/** Simple quick field convert that is called on insert. */
740
741
int field_conv(Field *to,Field *from)
742
{
743
  if (to->real_type() == from->real_type() &&
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
744
      !(to->type() == DRIZZLE_TYPE_BLOB && to->table->copy_blobs))
1 by brian
clean slate
745
  {
746
    /* Please god, will someone rewrite this to be readable :( */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
747
    if (to->pack_length() == from->pack_length() &&
748
        !(to->flags & UNSIGNED_FLAG && !(from->flags & UNSIGNED_FLAG)) &&
749
        to->real_type() != DRIZZLE_TYPE_ENUM &&
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
750
        (to->real_type() != DRIZZLE_TYPE_NEWDECIMAL || (to->field_length == from->field_length && (((Field_num*)to)->dec == ((Field_num*)from)->dec))) &&
1 by brian
clean slate
751
        from->charset() == to->charset() &&
752
	to->table->s->db_low_byte_first == from->table->s->db_low_byte_first &&
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
753
        (!(to->table->in_use->variables.sql_mode & (MODE_NO_ZERO_DATE | MODE_INVALID_DATES)) || (to->type() != DRIZZLE_TYPE_DATE && to->type() != DRIZZLE_TYPE_DATETIME)) &&
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
754
        (from->real_type() != DRIZZLE_TYPE_VARCHAR || ((Field_varstring*)from)->length_bytes == ((Field_varstring*)to)->length_bytes))
1 by brian
clean slate
755
    {						// Identical fields
756
      /* This may happen if one does 'UPDATE ... SET x=x' */
757
      if (to->ptr != from->ptr)
758
        memcpy(to->ptr,from->ptr,to->pack_length());
759
      return 0;
760
    }
761
  }
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
762
  if (to->type() == DRIZZLE_TYPE_BLOB)
1 by brian
clean slate
763
  {						// Be sure the value is stored
764
    Field_blob *blob=(Field_blob*) to;
765
    from->val_str(&blob->value);
766
    /*
767
      Copy value if copy_blobs is set, or source is not a string and
768
      we have a pointer to its internal string conversion buffer.
769
    */
770
    if (to->table->copy_blobs ||
771
        (!blob->value.is_alloced() &&
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
772
         from->real_type() != DRIZZLE_TYPE_VARCHAR))
1 by brian
clean slate
773
      blob->value.copy();
774
    return blob->store(blob->value.ptr(),blob->value.length(),from->charset());
775
  }
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
776
  if (from->real_type() == DRIZZLE_TYPE_ENUM &&
777
      to->real_type() == DRIZZLE_TYPE_ENUM &&
1 by brian
clean slate
778
      from->val_int() == 0)
779
  {
780
    ((Field_enum *)(to))->store_type(0);
781
    return 0;
782
  }
783
  else if ((from->result_type() == STRING_RESULT &&
784
            (to->result_type() == STRING_RESULT ||
325 by Brian Aker
Remove SET
785
             (from->real_type() != DRIZZLE_TYPE_ENUM))))
1 by brian
clean slate
786
  {
787
    char buff[MAX_FIELD_WIDTH];
788
    String result(buff,sizeof(buff),from->charset());
789
    from->val_str(&result);
790
    /*
791
      We use c_ptr_quick() here to make it easier if to is a float/double
792
      as the conversion routines will do a copy of the result doesn't
793
      end with \0. Can be replaced with .ptr() when we have our own
794
      string->double conversion.
795
    */
796
    return to->store(result.c_ptr_quick(),result.length(),from->charset());
797
  }
798
  else if (from->result_type() == REAL_RESULT)
799
    return to->store(from->val_real());
800
  else if (from->result_type() == DECIMAL_RESULT)
801
  {
802
    my_decimal buff;
803
    return to->store_decimal(from->val_decimal(&buff));
804
  }
805
  else
806
    return to->store(from->val_int(), test(from->flags & UNSIGNED_FLAG));
807
}