1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems
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.
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.
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
20
#include <drizzled/server_includes.h>
21
#include <drizzled/session.h>
22
#include <drizzled/item/uint.h>
23
#include <drizzled/item/null.h>
24
#include <drizzled/item/float.h>
25
#include <drizzled/item/param.h>
26
#include <drizzled/sql_string.h>
27
#include <drizzled/util/convert.h>
28
#include <mystrings/utf8.h>
30
Item *Item_param::safe_charset_converter(const CHARSET_INFO * const tocs)
35
String *ostr= val_str(&cnvstr);
36
cnvitem->str_value.copy(ostr->ptr(), ostr->length(),
37
ostr->charset(), tocs, &cnv_errors);
40
cnvitem->str_value.mark_as_const();
41
cnvitem->max_length= cnvitem->str_value.numchars() * tocs->mbmaxlen;
48
Default function of Item_param::set_param_func, so in case
49
of malformed packet the server won't SIGSEGV.
53
default_set_param_func(Item_param *param, unsigned char **, ulong)
58
Item_param::Item_param(uint32_t pos_in_query_arg) :
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)
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
75
cnvitem= new Item_string("", 0, &my_charset_bin, DERIVATION_COERCIBLE);
76
cnvstr.set(cnvbuf, sizeof(cnvbuf), &my_charset_bin);
79
void Item_param::set_null()
81
/* These are cleared after each execution by reset() method */
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.
91
item_type= Item::NULL_ITEM;
95
void Item_param::set_int(int64_t i, uint32_t max_length_arg)
97
value.integer= (int64_t) i;
99
max_length= max_length_arg;
105
void Item_param::set_double(double d)
109
max_length= DBL_DIG + 8;
110
decimals= NOT_FIXED_DEC;
116
Set decimal parameter value from string.
118
@param str character string
119
@param length string length
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.
127
void Item_param::set_decimal(char *str, ulong length)
132
str2my_decimal((uint32_t)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);
142
Set parameter value from DRIZZLE_TIME value.
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
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.
154
void Item_param::set_time(DRIZZLE_TIME *tm,
155
enum enum_drizzle_timestamp_type time_type,
156
uint32_t max_length_arg)
159
value.time.time_type= time_type;
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)
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);
175
max_length= max_length_arg;
181
bool Item_param::set_str(const char *str, ulong length)
184
Assign string with no conversion: data is converted only after it's
185
been written to the binary log.
187
uint32_t dummy_errors;
188
if (str_value.copy(str, length, &my_charset_bin, &my_charset_bin,
194
/* max_length and decimals are set after charset conversion */
195
/* sic: str may be not null-terminated */
199
bool Item_param::set_longdata(const char *str, ulong length)
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.
210
if (str_value.append(str, length, &my_charset_bin))
212
state= LONG_DATA_VALUE;
220
Set parameter value from user variable value.
222
@param session Current thread
223
@param entry User variable structure (NULL means use NULL value)
231
bool Item_param::set_from_user_var(Session *session, const user_var_entry *entry)
233
if (entry && entry->value)
235
item_result_type= entry->type;
236
unsigned_flag= entry->unsigned_flag;
237
if (limit_clause_param)
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);
243
switch (item_result_type) {
245
set_double(*(double*)entry->value);
246
item_type= Item::REAL_ITEM;
249
set_int(*(int64_t*)entry->value, MY_INT64_NUM_DECIMAL_DIGITS);
250
item_type= Item::INT_ITEM;
254
const CHARSET_INFO * const fromcs= entry->collation.collation;
255
const CHARSET_INFO * const tocs= session->variables.getCollation();
256
uint32_t dummy_offset;
258
value.cs_info.character_set_of_placeholder=
259
value.cs_info.character_set_client= fromcs;
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.
265
value.cs_info.final_character_set_of_str_value=
266
String::needs_conversion(0, fromcs, tocs, &dummy_offset) ?
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.
272
item_type= Item::STRING_ITEM;
274
if (set_str((const char *)entry->value, entry->length))
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;
301
Resets parameter after execution.
304
We clear null_value here instead of setting it in set_* methods,
305
because we want more easily handle case for long data.
308
void Item_param::reset()
310
/* Shrink string buffer if it's bigger than max possible CHAR column */
311
if (str_value.alloced_length() > MAX_CHAR_WIDTH)
315
str_value_ptr.length(0);
317
We must prevent all charset conversions until data has been written
320
str_value.set_charset(&my_charset_bin);
321
collation.set(&my_charset_bin, DERIVATION_COERCIBLE);
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_*
337
int Item_param::save_in_field(Field *field, bool no_conversions)
339
field->set_notnull();
343
return field->store(value.integer, unsigned_flag);
345
return field->store(value.real);
347
return field->store_decimal(&decimal_value);
349
field->store_time(&value.time, value.time.time_type);
352
case LONG_DATA_VALUE:
353
return field->store(str_value.ptr(), str_value.length(),
354
str_value.charset());
356
return set_field_to_null_with_conversions(field, no_conversions);
364
bool Item_param::get_time(DRIZZLE_TIME *res)
366
if (state == TIME_VALUE)
372
If parameter value isn't supplied assertion will fire in val_str()
373
which is called from Item::get_time().
375
return Item::get_time(res);
379
bool Item_param::get_date(DRIZZLE_TIME *res, uint32_t fuzzydate)
381
if (state == TIME_VALUE)
386
return Item::get_date(res, fuzzydate);
390
double Item_param::val_real()
396
return (double) value.integer;
400
my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &result);
404
case LONG_DATA_VALUE:
408
return my_strntod(str_value.charset(), (char*) str_value.ptr(),
409
str_value.length(), &end_not_used, &dummy_err);
413
This works for example when user says SELECT ?+0.0 and supplies
414
time value for the placeholder.
416
return uint64_t2double(TIME_to_uint64_t(&value.time));
426
int64_t Item_param::val_int()
430
return (int64_t) rint(value.real);
432
return value.integer;
436
my_decimal2int(E_DEC_FATAL_ERROR, &decimal_value, unsigned_flag, &i);
440
case LONG_DATA_VALUE:
443
return my_strntoll(str_value.charset(), str_value.ptr(),
444
str_value.length(), 10, (char**) 0, &dummy_err);
447
return (int64_t) TIME_to_uint64_t(&value.time);
457
my_decimal *Item_param::val_decimal(my_decimal *dec)
461
return &decimal_value;
463
double2my_decimal(E_DEC_FATAL_ERROR, value.real, dec);
466
int2my_decimal(E_DEC_FATAL_ERROR, value.integer, unsigned_flag, dec);
469
case LONG_DATA_VALUE:
470
string2my_decimal(E_DEC_FATAL_ERROR, &str_value, dec);
474
int64_t i= (int64_t) TIME_to_uint64_t(&value.time);
475
int2my_decimal(E_DEC_FATAL_ERROR, i, 0, dec);
487
String *Item_param::val_str(String* str)
491
case LONG_DATA_VALUE:
492
return &str_value_ptr;
494
str->set_real(value.real, NOT_FIXED_DEC, &my_charset_bin);
497
str->set(value.integer, &my_charset_bin);
500
if (my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value,
506
if (str->reserve(MAX_DATE_STRING_REP_LENGTH))
508
str->length((uint32_t) my_TIME_to_str(&value.time, (char*) str->ptr()));
509
str->set_charset(&my_charset_bin);
520
/* TODO: fact next two functions out */
522
Transforms a string into "" or its expression in 0x... form.
525
static char *str_to_hex(char *to, const char *from, uint32_t len)
531
to+= (size_t) drizzled_string_to_hex(to, from, len);
534
to= strcpy(to, "\"\"")+2;
535
return to; // pointer to end 0 of 'to'
541
Add escape characters to a string (blob?) to make it suitable for a insert
542
to should at least have place for length*2+1 chars
543
Returns the length of the to string
547
_escape_string(char *to,const char *from, uint32_t length)
549
const char *to_start= to;
550
const char *end, *to_end=to_start + 2*length;
551
bool overflow= false;
552
for (end= from + length; from < end; from++)
556
if (!U8_IS_SINGLE(*from))
558
tmp_length= U8_LENGTH(*(uint32_t*)from);
559
if (to + tmp_length > to_end)
570
case 0: /* Must be escaped for 'mysql' */
573
case '\n': /* Must be escaped for logs */
585
case '"': /* Better safe than sorry */
588
case '\032': /* This gives problems on Win32 */
613
return overflow ? (size_t) -1 : (size_t) (to - to_start);
617
Append a version of the 'from' string suitable for use in a query to
618
the 'to' string. To generate a correct escaping, the character set
619
information in 'csinfo' is used.
623
append_query_string(const CHARSET_INFO * const csinfo,
624
String const *from, String *to)
627
uint32_t const orig_len= to->length();
628
if (to->reserve(orig_len + from->length()*2+3))
631
beg= to->c_ptr_quick() + to->length();
633
if (csinfo->escape_with_backslash_is_dangerous)
634
ptr= str_to_hex(ptr, from->ptr(), from->length());
638
ptr+= _escape_string(ptr, from->ptr(), from->length());
641
to->length(orig_len + ptr - beg);
647
Return Param item values in string format, for generating the dynamic
648
query used in update/binary logs.
651
- Change interface and implementation to fill log data in place
652
and avoid one more memcpy/alloc between str and log string.
653
- In case of error we need to notify replication
654
that binary log contains wrong statement
657
const String *Item_param::query_val_str(String* str) const
661
str->set_int(value.integer, unsigned_flag, &my_charset_bin);
664
str->set_real(value.real, NOT_FIXED_DEC, &my_charset_bin);
667
if (my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value,
669
return &my_null_string;
676
TODO: in case of error we need to notify replication
677
that binary log contains wrong statement
679
if (str->reserve(MAX_DATE_STRING_REP_LENGTH+3))
682
/* Create date string inplace */
683
buf= str->c_ptr_quick();
686
ptr+= (uint32_t) my_TIME_to_str(&value.time, ptr);
688
str->length((uint32_t) (ptr - buf));
692
case LONG_DATA_VALUE:
695
append_query_string(value.cs_info.character_set_client, &str_value, str);
699
return &my_null_string;
707
bool Item_param::basic_const_item() const
709
if (state == NO_VALUE || state == TIME_VALUE)
716
Item_param::clone_item()
718
/* see comments in the header file */
721
return new Item_null(name);
723
return (unsigned_flag ?
724
new Item_uint(name, value.integer, max_length) :
725
new Item_int(name, value.integer, max_length));
727
return new Item_float(name, value.real, decimals, max_length);
729
case LONG_DATA_VALUE:
730
return new Item_string(name, str_value.c_ptr_quick(), str_value.length(),
731
str_value.charset());
743
Item_param::eq(const Item *arg, bool binary_cmp) const
746
if (!basic_const_item() || !arg->basic_const_item() || arg->type() != type())
749
We need to cast off const to call val_int(). This should be OK for
758
return value.integer == item->val_int() &&
759
unsigned_flag == item->unsigned_flag;
761
return value.real == item->val_real();
763
case LONG_DATA_VALUE:
765
return !stringcmp(&str_value, &item->str_value);
766
return !sortcmp(&str_value, &item->str_value, collation.collation);
773
/* End of Item_param related */
775
void Item_param::print(String *str, enum_query_type)
777
if (state == NO_VALUE)
783
char buffer[STRING_BUFFER_USUAL_SIZE];
784
String tmp(buffer, sizeof(buffer), &my_charset_bin);
786
res= query_val_str(&tmp);