~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/item/param.cc

  • Committer: Brian Aker
  • Date: 2008-12-09 17:33:02 UTC
  • mfrom: (656.1.54 devel)
  • Revision ID: brian@tangent.org-20081209173302-aptngvc7efxnatnt
Merge from Monty.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008 Sun Microsystems
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; version 2 of the License.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 */
 
19
 
 
20
#include <drizzled/server_includes.h>
 
21
#include CSTDINT_H
 
22
#include <drizzled/session.h>
 
23
#include <drizzled/item/param.h>
 
24
#include CMATH_H
 
25
 
 
26
Item *Item_param::safe_charset_converter(const CHARSET_INFO * const tocs)
 
27
{
 
28
  if (const_item())
 
29
  {
 
30
    uint32_t cnv_errors;
 
31
    String *ostr= val_str(&cnvstr);
 
32
    cnvitem->str_value.copy(ostr->ptr(), ostr->length(),
 
33
                            ostr->charset(), tocs, &cnv_errors);
 
34
    if (cnv_errors)
 
35
       return NULL;
 
36
    cnvitem->str_value.mark_as_const();
 
37
    cnvitem->max_length= cnvitem->str_value.numchars() * tocs->mbmaxlen;
 
38
    return cnvitem;
 
39
  }
 
40
  return NULL;
 
41
}
 
42
 
 
43
/**
 
44
  Default function of Item_param::set_param_func, so in case
 
45
  of malformed packet the server won't SIGSEGV.
 
46
*/
 
47
 
 
48
static void
 
49
default_set_param_func(Item_param *param, unsigned char **, ulong)
 
50
{
 
51
  param->set_null();
 
52
}
 
53
 
 
54
Item_param::Item_param(uint32_t pos_in_query_arg) :
 
55
  state(NO_VALUE),
 
56
  item_result_type(STRING_RESULT),
 
57
  /* Don't pretend to be a literal unless value for this item is set. */
 
58
  item_type(PARAM_ITEM),
 
59
  param_type(DRIZZLE_TYPE_VARCHAR),
 
60
  pos_in_query(pos_in_query_arg),
 
61
  set_param_func(default_set_param_func),
 
62
  limit_clause_param(false)
 
63
{
 
64
  name= (char*) "?";
 
65
  /*
 
66
    Since we can't say whenever this item can be NULL or cannot be NULL
 
67
    before mysql_stmt_execute(), so we assuming that it can be NULL until
 
68
    value is set.
 
69
  */
 
70
  maybe_null= 1;
 
71
  cnvitem= new Item_string("", 0, &my_charset_bin, DERIVATION_COERCIBLE);
 
72
  cnvstr.set(cnvbuf, sizeof(cnvbuf), &my_charset_bin);
 
73
}
 
74
 
 
75
void Item_param::set_null()
 
76
{
 
77
  /* These are cleared after each execution by reset() method */
 
78
  null_value= 1;
 
79
  /*
 
80
    Because of NULL and string values we need to set max_length for each new
 
81
    placeholder value: user can submit NULL for any placeholder type, and
 
82
    string length can be different in each execution.
 
83
  */
 
84
  max_length= 0;
 
85
  decimals= 0;
 
86
  state= NULL_VALUE;
 
87
  item_type= Item::NULL_ITEM;
 
88
  return;
 
89
}
 
90
 
 
91
void Item_param::set_int(int64_t i, uint32_t max_length_arg)
 
92
{
 
93
  value.integer= (int64_t) i;
 
94
  state= INT_VALUE;
 
95
  max_length= max_length_arg;
 
96
  decimals= 0;
 
97
  maybe_null= 0;
 
98
  return;
 
99
}
 
100
 
 
101
void Item_param::set_double(double d)
 
102
{
 
103
  value.real= d;
 
104
  state= REAL_VALUE;
 
105
  max_length= DBL_DIG + 8;
 
106
  decimals= NOT_FIXED_DEC;
 
107
  maybe_null= 0;
 
108
  return;
 
109
}
 
110
 
 
111
/**
 
112
  Set decimal parameter value from string.
 
113
 
 
114
  @param str      character string
 
115
  @param length   string length
 
116
 
 
117
  @note
 
118
    As we use character strings to send decimal values in
 
119
    binary protocol, we use str2my_decimal to convert it to
 
120
    internal decimal value.
 
121
*/
 
122
 
 
123
void Item_param::set_decimal(char *str, ulong length)
 
124
{
 
125
  char *end;
 
126
 
 
127
  end= str+length;
 
128
  str2my_decimal((uint)E_DEC_FATAL_ERROR, str, &decimal_value, &end);
 
129
  state= DECIMAL_VALUE;
 
130
  decimals= decimal_value.frac;
 
131
  max_length= my_decimal_precision_to_length(decimal_value.precision(),
 
132
                                             decimals, unsigned_flag);
 
133
  maybe_null= 0;
 
134
  return;
 
135
}
 
136
 
 
137
/**
 
138
  Set parameter value from DRIZZLE_TIME value.
 
139
 
 
140
  @param tm              datetime value to set (time_type is ignored)
 
141
  @param type            type of datetime value
 
142
  @param max_length_arg  max length of datetime value as string
 
143
 
 
144
  @note
 
145
    If we value to be stored is not normalized, zero value will be stored
 
146
    instead and proper warning will be produced. This function relies on
 
147
    the fact that even wrong value sent over binary protocol fits into
 
148
    MAX_DATE_STRING_REP_LENGTH buffer.
 
149
*/
 
150
void Item_param::set_time(DRIZZLE_TIME *tm,
 
151
                          enum enum_drizzle_timestamp_type time_type,
 
152
                          uint32_t max_length_arg)
 
153
{
 
154
  value.time= *tm;
 
155
  value.time.time_type= time_type;
 
156
 
 
157
  if (value.time.year > 9999 || value.time.month > 12 ||
 
158
      value.time.day > 31 ||
 
159
      ((time_type != DRIZZLE_TIMESTAMP_TIME) && value.time.hour > 23) ||
 
160
      value.time.minute > 59 || value.time.second > 59)
 
161
  {
 
162
    char buff[MAX_DATE_STRING_REP_LENGTH];
 
163
    uint32_t length= my_TIME_to_str(&value.time, buff);
 
164
    make_truncated_value_warning(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
165
                                 buff, length, time_type, 0);
 
166
    set_zero_time(&value.time, DRIZZLE_TIMESTAMP_ERROR);
 
167
  }
 
168
 
 
169
  state= TIME_VALUE;
 
170
  maybe_null= 0;
 
171
  max_length= max_length_arg;
 
172
  decimals= 0;
 
173
  return;
 
174
}
 
175
 
 
176
 
 
177
bool Item_param::set_str(const char *str, ulong length)
 
178
{
 
179
  /*
 
180
    Assign string with no conversion: data is converted only after it's
 
181
    been written to the binary log.
 
182
  */
 
183
  uint32_t dummy_errors;
 
184
  if (str_value.copy(str, length, &my_charset_bin, &my_charset_bin,
 
185
                     &dummy_errors))
 
186
    return(true);
 
187
  state= STRING_VALUE;
 
188
  max_length= length;
 
189
  maybe_null= 0;
 
190
  /* max_length and decimals are set after charset conversion */
 
191
  /* sic: str may be not null-terminated */
 
192
  return(false);
 
193
}
 
194
 
 
195
bool Item_param::set_longdata(const char *str, ulong length)
 
196
{
 
197
  /*
 
198
    If client character set is multibyte, end of long data packet
 
199
    may hit at the middle of a multibyte character.  Additionally,
 
200
    if binary log is open we must write long data value to the
 
201
    binary log in character set of client. This is why we can't
 
202
    convert long data to connection character set as it comes
 
203
    (here), and first have to concatenate all pieces together,
 
204
    write query to the binary log and only then perform conversion.
 
205
  */
 
206
  if (str_value.append(str, length, &my_charset_bin))
 
207
    return(true);
 
208
  state= LONG_DATA_VALUE;
 
209
  maybe_null= 0;
 
210
 
 
211
  return(false);
 
212
}
 
213
 
 
214
 
 
215
/**
 
216
  Set parameter value from user variable value.
 
217
 
 
218
  @param session   Current thread
 
219
  @param entry User variable structure (NULL means use NULL value)
 
220
 
 
221
  @retval
 
222
    0 OK
 
223
  @retval
 
224
    1 Out of memory
 
225
*/
 
226
 
 
227
bool Item_param::set_from_user_var(Session *session, const user_var_entry *entry)
 
228
{
 
229
  if (entry && entry->value)
 
230
  {
 
231
    item_result_type= entry->type;
 
232
    unsigned_flag= entry->unsigned_flag;
 
233
    if (limit_clause_param)
 
234
    {
 
235
      bool unused;
 
236
      set_int(entry->val_int(&unused), MY_INT64_NUM_DECIMAL_DIGITS); item_type= Item::INT_ITEM;
 
237
      return(!unsigned_flag && value.integer < 0 ? 1 : 0);
 
238
    }
 
239
    switch (item_result_type) {
 
240
    case REAL_RESULT:
 
241
      set_double(*(double*)entry->value);
 
242
      item_type= Item::REAL_ITEM;
 
243
      break;
 
244
    case INT_RESULT:
 
245
      set_int(*(int64_t*)entry->value, MY_INT64_NUM_DECIMAL_DIGITS);
 
246
      item_type= Item::INT_ITEM;
 
247
      break;
 
248
    case STRING_RESULT:
 
249
    {
 
250
      const CHARSET_INFO * const fromcs= entry->collation.collation;
 
251
      const CHARSET_INFO * const tocs= session->variables.collation_connection;
 
252
      uint32_t dummy_offset;
 
253
 
 
254
      value.cs_info.character_set_of_placeholder=
 
255
        value.cs_info.character_set_client= fromcs;
 
256
      /*
 
257
        Setup source and destination character sets so that they
 
258
        are different only if conversion is necessary: this will
 
259
        make later checks easier.
 
260
      */
 
261
      value.cs_info.final_character_set_of_str_value=
 
262
        String::needs_conversion(0, fromcs, tocs, &dummy_offset) ?
 
263
        tocs : fromcs;
 
264
      /*
 
265
        Exact value of max_length is not known unless data is converted to
 
266
        charset of connection, so we have to set it later.
 
267
      */
 
268
      item_type= Item::STRING_ITEM;
 
269
 
 
270
      if (set_str((const char *)entry->value, entry->length))
 
271
        return(1);
 
272
      break;
 
273
    }
 
274
    case DECIMAL_RESULT:
 
275
    {
 
276
      const my_decimal *ent_value= (const my_decimal *)entry->value;
 
277
      my_decimal2decimal(ent_value, &decimal_value);
 
278
      state= DECIMAL_VALUE;
 
279
      decimals= ent_value->frac;
 
280
      max_length= my_decimal_precision_to_length(ent_value->precision(),
 
281
                                                 decimals, unsigned_flag);
 
282
      item_type= Item::DECIMAL_ITEM;
 
283
      break;
 
284
    }
 
285
    default:
 
286
      assert(0);
 
287
      set_null();
 
288
    }
 
289
  }
 
290
  else
 
291
    set_null();
 
292
 
 
293
  return(0);
 
294
}
 
295
 
 
296
/**
 
297
  Resets parameter after execution.
 
298
 
 
299
  @note
 
300
    We clear null_value here instead of setting it in set_* methods,
 
301
    because we want more easily handle case for long data.
 
302
*/
 
303
 
 
304
void Item_param::reset()
 
305
{
 
306
  /* Shrink string buffer if it's bigger than max possible CHAR column */
 
307
  if (str_value.alloced_length() > MAX_CHAR_WIDTH)
 
308
    str_value.free();
 
309
  else
 
310
    str_value.length(0);
 
311
  str_value_ptr.length(0);
 
312
  /*
 
313
    We must prevent all charset conversions until data has been written
 
314
    to the binary log.
 
315
  */
 
316
  str_value.set_charset(&my_charset_bin);
 
317
  collation.set(&my_charset_bin, DERIVATION_COERCIBLE);
 
318
  state= NO_VALUE;
 
319
  maybe_null= 1;
 
320
  null_value= 0;
 
321
  /*
 
322
    Don't reset item_type to PARAM_ITEM: it's only needed to guard
 
323
    us from item optimizations at prepare stage, when item doesn't yet
 
324
    contain a literal of some kind.
 
325
    In all other cases when this object is accessed its value is
 
326
    set (this assumption is guarded by 'state' and
 
327
    assertS(state != NO_VALUE) in all Item_param::get_*
 
328
    methods).
 
329
  */
 
330
  return;
 
331
}
 
332
 
 
333
int Item_param::save_in_field(Field *field, bool no_conversions)
 
334
{
 
335
  field->set_notnull();
 
336
 
 
337
  switch (state) {
 
338
  case INT_VALUE:
 
339
    return field->store(value.integer, unsigned_flag);
 
340
  case REAL_VALUE:
 
341
    return field->store(value.real);
 
342
  case DECIMAL_VALUE:
 
343
    return field->store_decimal(&decimal_value);
 
344
  case TIME_VALUE:
 
345
    field->store_time(&value.time, value.time.time_type);
 
346
    return 0;
 
347
  case STRING_VALUE:
 
348
  case LONG_DATA_VALUE:
 
349
    return field->store(str_value.ptr(), str_value.length(),
 
350
                        str_value.charset());
 
351
  case NULL_VALUE:
 
352
    return set_field_to_null_with_conversions(field, no_conversions);
 
353
  case NO_VALUE:
 
354
  default:
 
355
    assert(0);
 
356
  }
 
357
  return 1;
 
358
}
 
359
 
 
360
bool Item_param::get_time(DRIZZLE_TIME *res)
 
361
{
 
362
  if (state == TIME_VALUE)
 
363
  {
 
364
    *res= value.time;
 
365
    return 0;
 
366
  }
 
367
  /*
 
368
    If parameter value isn't supplied assertion will fire in val_str()
 
369
    which is called from Item::get_time().
 
370
  */
 
371
  return Item::get_time(res);
 
372
}
 
373
 
 
374
 
 
375
bool Item_param::get_date(DRIZZLE_TIME *res, uint32_t fuzzydate)
 
376
{
 
377
  if (state == TIME_VALUE)
 
378
  {
 
379
    *res= value.time;
 
380
    return 0;
 
381
  }
 
382
  return Item::get_date(res, fuzzydate);
 
383
}
 
384
 
 
385
 
 
386
double Item_param::val_real()
 
387
{
 
388
  switch (state) {
 
389
  case REAL_VALUE:
 
390
    return value.real;
 
391
  case INT_VALUE:
 
392
    return (double) value.integer;
 
393
  case DECIMAL_VALUE:
 
394
  {
 
395
    double result;
 
396
    my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &result);
 
397
    return result;
 
398
  }
 
399
  case STRING_VALUE:
 
400
  case LONG_DATA_VALUE:
 
401
  {
 
402
    int dummy_err;
 
403
    char *end_not_used;
 
404
    return my_strntod(str_value.charset(), (char*) str_value.ptr(),
 
405
                      str_value.length(), &end_not_used, &dummy_err);
 
406
  }
 
407
  case TIME_VALUE:
 
408
    /*
 
409
      This works for example when user says SELECT ?+0.0 and supplies
 
410
      time value for the placeholder.
 
411
    */
 
412
    return uint64_t2double(TIME_to_uint64_t(&value.time));
 
413
  case NULL_VALUE:
 
414
    return 0.0;
 
415
  default:
 
416
    assert(0);
 
417
  }
 
418
  return 0.0;
 
419
}
 
420
 
 
421
 
 
422
int64_t Item_param::val_int()
 
423
{
 
424
  switch (state) {
 
425
  case REAL_VALUE:
 
426
    return (int64_t) rint(value.real);
 
427
  case INT_VALUE:
 
428
    return value.integer;
 
429
  case DECIMAL_VALUE:
 
430
  {
 
431
    int64_t i;
 
432
    my_decimal2int(E_DEC_FATAL_ERROR, &decimal_value, unsigned_flag, &i);
 
433
    return i;
 
434
  }
 
435
  case STRING_VALUE:
 
436
  case LONG_DATA_VALUE:
 
437
    {
 
438
      int dummy_err;
 
439
      return my_strntoll(str_value.charset(), str_value.ptr(),
 
440
                         str_value.length(), 10, (char**) 0, &dummy_err);
 
441
    }
 
442
  case TIME_VALUE:
 
443
    return (int64_t) TIME_to_uint64_t(&value.time);
 
444
  case NULL_VALUE:
 
445
    return 0;
 
446
  default:
 
447
    assert(0);
 
448
  }
 
449
  return 0;
 
450
}
 
451
 
 
452
 
 
453
my_decimal *Item_param::val_decimal(my_decimal *dec)
 
454
{
 
455
  switch (state) {
 
456
  case DECIMAL_VALUE:
 
457
    return &decimal_value;
 
458
  case REAL_VALUE:
 
459
    double2my_decimal(E_DEC_FATAL_ERROR, value.real, dec);
 
460
    return dec;
 
461
  case INT_VALUE:
 
462
    int2my_decimal(E_DEC_FATAL_ERROR, value.integer, unsigned_flag, dec);
 
463
    return dec;
 
464
  case STRING_VALUE:
 
465
  case LONG_DATA_VALUE:
 
466
    string2my_decimal(E_DEC_FATAL_ERROR, &str_value, dec);
 
467
    return dec;
 
468
  case TIME_VALUE:
 
469
  {
 
470
    int64_t i= (int64_t) TIME_to_uint64_t(&value.time);
 
471
    int2my_decimal(E_DEC_FATAL_ERROR, i, 0, dec);
 
472
    return dec;
 
473
  }
 
474
  case NULL_VALUE:
 
475
    return 0;
 
476
  default:
 
477
    assert(0);
 
478
  }
 
479
  return 0;
 
480
}
 
481
 
 
482
 
 
483
String *Item_param::val_str(String* str)
 
484
{
 
485
  switch (state) {
 
486
  case STRING_VALUE:
 
487
  case LONG_DATA_VALUE:
 
488
    return &str_value_ptr;
 
489
  case REAL_VALUE:
 
490
    str->set_real(value.real, NOT_FIXED_DEC, &my_charset_bin);
 
491
    return str;
 
492
  case INT_VALUE:
 
493
    str->set(value.integer, &my_charset_bin);
 
494
    return str;
 
495
  case DECIMAL_VALUE:
 
496
    if (my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value,
 
497
                          0, 0, 0, str) <= 1)
 
498
      return str;
 
499
    return NULL;
 
500
  case TIME_VALUE:
 
501
  {
 
502
    if (str->reserve(MAX_DATE_STRING_REP_LENGTH))
 
503
      break;
 
504
    str->length((uint) my_TIME_to_str(&value.time, (char*) str->ptr()));
 
505
    str->set_charset(&my_charset_bin);
 
506
    return str;
 
507
  }
 
508
  case NULL_VALUE:
 
509
    return NULL;
 
510
  default:
 
511
    assert(0);
 
512
  }
 
513
  return str;
 
514
}
 
515
 
 
516
/**
 
517
  Return Param item values in string format, for generating the dynamic
 
518
  query used in update/binary logs.
 
519
 
 
520
  @todo
 
521
    - Change interface and implementation to fill log data in place
 
522
    and avoid one more memcpy/alloc between str and log string.
 
523
    - In case of error we need to notify replication
 
524
    that binary log contains wrong statement
 
525
*/
 
526
 
 
527
const String *Item_param::query_val_str(String* str) const
 
528
{
 
529
  switch (state) {
 
530
  case INT_VALUE:
 
531
    str->set_int(value.integer, unsigned_flag, &my_charset_bin);
 
532
    break;
 
533
  case REAL_VALUE:
 
534
    str->set_real(value.real, NOT_FIXED_DEC, &my_charset_bin);
 
535
    break;
 
536
  case DECIMAL_VALUE:
 
537
    if (my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value,
 
538
                          0, 0, 0, str) > 1)
 
539
      return &my_null_string;
 
540
    break;
 
541
  case TIME_VALUE:
 
542
    {
 
543
      char *buf, *ptr;
 
544
      str->length(0);
 
545
      /*
 
546
        TODO: in case of error we need to notify replication
 
547
        that binary log contains wrong statement
 
548
      */
 
549
      if (str->reserve(MAX_DATE_STRING_REP_LENGTH+3))
 
550
        break;
 
551
 
 
552
      /* Create date string inplace */
 
553
      buf= str->c_ptr_quick();
 
554
      ptr= buf;
 
555
      *ptr++= '\'';
 
556
      ptr+= (uint) my_TIME_to_str(&value.time, ptr);
 
557
      *ptr++= '\'';
 
558
      str->length((uint32_t) (ptr - buf));
 
559
      break;
 
560
    }
 
561
  case STRING_VALUE:
 
562
  case LONG_DATA_VALUE:
 
563
    {
 
564
      str->length(0);
 
565
      append_query_string(value.cs_info.character_set_client, &str_value, str);
 
566
      break;
 
567
    }
 
568
  case NULL_VALUE:
 
569
    return &my_null_string;
 
570
  default:
 
571
    assert(0);
 
572
  }
 
573
  return str;
 
574
}
 
575
 
 
576
 
 
577
/**
 
578
  Convert string from client character set to the character set of
 
579
  connection.
 
580
*/
 
581
 
 
582
bool Item_param::convert_str_value(Session *session)
 
583
{
 
584
  bool rc= false;
 
585
  if (state == STRING_VALUE || state == LONG_DATA_VALUE)
 
586
  {
 
587
    /*
 
588
      Check is so simple because all charsets were set up properly
 
589
      in setup_one_conversion_function, where typecode of
 
590
      placeholder was also taken into account: the variables are different
 
591
      here only if conversion is really necessary.
 
592
    */
 
593
    if (value.cs_info.final_character_set_of_str_value !=
 
594
        value.cs_info.character_set_of_placeholder)
 
595
    {
 
596
      rc= session->convert_string(&str_value,
 
597
                              value.cs_info.character_set_of_placeholder,
 
598
                              value.cs_info.final_character_set_of_str_value);
 
599
    }
 
600
    else
 
601
      str_value.set_charset(value.cs_info.final_character_set_of_str_value);
 
602
    /* Here str_value is guaranteed to be in final_character_set_of_str_value */
 
603
 
 
604
    max_length= str_value.length();
 
605
    decimals= 0;
 
606
    /*
 
607
      str_value_ptr is returned from val_str(). It must be not alloced
 
608
      to prevent it's modification by val_str() invoker.
 
609
    */
 
610
    str_value_ptr.set(str_value.ptr(), str_value.length(),
 
611
                      str_value.charset());
 
612
    /* Synchronize item charset with value charset */
 
613
    collation.set(str_value.charset(), DERIVATION_COERCIBLE);
 
614
  }
 
615
  return rc;
 
616
}
 
617
 
 
618
 
 
619
bool Item_param::basic_const_item() const
 
620
{
 
621
  if (state == NO_VALUE || state == TIME_VALUE)
 
622
    return false;
 
623
  return true;
 
624
}
 
625
 
 
626
 
 
627
Item *
 
628
Item_param::clone_item()
 
629
{
 
630
  /* see comments in the header file */
 
631
  switch (state) {
 
632
  case NULL_VALUE:
 
633
    return new Item_null(name);
 
634
  case INT_VALUE:
 
635
    return (unsigned_flag ?
 
636
            new Item_uint(name, value.integer, max_length) :
 
637
            new Item_int(name, value.integer, max_length));
 
638
  case REAL_VALUE:
 
639
    return new Item_float(name, value.real, decimals, max_length);
 
640
  case STRING_VALUE:
 
641
  case LONG_DATA_VALUE:
 
642
    return new Item_string(name, str_value.c_ptr_quick(), str_value.length(),
 
643
                           str_value.charset());
 
644
  case TIME_VALUE:
 
645
    break;
 
646
  case NO_VALUE:
 
647
  default:
 
648
    assert(0);
 
649
  };
 
650
  return 0;
 
651
}
 
652
 
 
653
 
 
654
bool
 
655
Item_param::eq(const Item *arg, bool binary_cmp) const
 
656
{
 
657
  Item *item;
 
658
  if (!basic_const_item() || !arg->basic_const_item() || arg->type() != type())
 
659
    return false;
 
660
  /*
 
661
    We need to cast off const to call val_int(). This should be OK for
 
662
    a basic constant.
 
663
  */
 
664
  item= (Item*) arg;
 
665
 
 
666
  switch (state) {
 
667
  case NULL_VALUE:
 
668
    return true;
 
669
  case INT_VALUE:
 
670
    return value.integer == item->val_int() &&
 
671
           unsigned_flag == item->unsigned_flag;
 
672
  case REAL_VALUE:
 
673
    return value.real == item->val_real();
 
674
  case STRING_VALUE:
 
675
  case LONG_DATA_VALUE:
 
676
    if (binary_cmp)
 
677
      return !stringcmp(&str_value, &item->str_value);
 
678
    return !sortcmp(&str_value, &item->str_value, collation.collation);
 
679
  default:
 
680
    break;
 
681
  }
 
682
  return false;
 
683
}
 
684
 
 
685
/* End of Item_param related */
 
686
 
 
687
void Item_param::print(String *str, enum_query_type)
 
688
{
 
689
  if (state == NO_VALUE)
 
690
  {
 
691
    str->append('?');
 
692
  }
 
693
  else
 
694
  {
 
695
    char buffer[STRING_BUFFER_USUAL_SIZE];
 
696
    String tmp(buffer, sizeof(buffer), &my_charset_bin);
 
697
    const String *res;
 
698
    res= query_val_str(&tmp);
 
699
    str->append(*res);
 
700
  }
 
701
}