~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/item/param.cc

  • Committer: Mark Atwood
  • Date: 2009-03-04 01:02:00 UTC
  • mto: (968.2.20 mordred)
  • mto: This revision was merged to the branch mainline in revision 971.
  • Revision ID: me@mark.atwood.name-20090304010200-t1n4xxdoil2yae9a
add gearman logging plugin

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