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