~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/item/param.cc

  • Committer: Brian Aker
  • Date: 2009-01-24 09:43:35 UTC
  • Revision ID: brian@gir-3.local-20090124094335-6qdtvc35gl5fvivz
Adding in an example singe thread scheduler

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