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>
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>
28
#include <drizzled/sql_string.h>
29
#include <mystrings/utf8.h>
31
Item *Item_param::safe_charset_converter(const CHARSET_INFO * const tocs)
36
String *ostr= val_str(&cnvstr);
37
cnvitem->str_value.copy(ostr->ptr(), ostr->length(),
38
ostr->charset(), tocs, &cnv_errors);
41
cnvitem->str_value.mark_as_const();
42
cnvitem->max_length= cnvitem->str_value.numchars() * tocs->mbmaxlen;
49
Default function of Item_param::set_param_func, so in case
50
of malformed packet the server won't SIGSEGV.
54
default_set_param_func(Item_param *param, unsigned char **, ulong)
59
Item_param::Item_param(uint32_t pos_in_query_arg) :
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)
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
76
cnvitem= new Item_string("", 0, &my_charset_bin, DERIVATION_COERCIBLE);
77
cnvstr.set(cnvbuf, sizeof(cnvbuf), &my_charset_bin);
80
void Item_param::set_null()
82
/* These are cleared after each execution by reset() method */
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.
92
item_type= Item::NULL_ITEM;
96
void Item_param::set_int(int64_t i, uint32_t max_length_arg)
98
value.integer= (int64_t) i;
100
max_length= max_length_arg;
106
void Item_param::set_double(double d)
110
max_length= DBL_DIG + 8;
111
decimals= NOT_FIXED_DEC;
117
Set decimal parameter value from string.
119
@param str character string
120
@param length string length
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.
128
void Item_param::set_decimal(char *str, ulong 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);
143
Set parameter value from DRIZZLE_TIME value.
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
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.
155
void Item_param::set_time(DRIZZLE_TIME *tm,
156
enum enum_drizzle_timestamp_type time_type,
157
uint32_t max_length_arg)
160
value.time.time_type= time_type;
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)
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);
176
max_length= max_length_arg;
182
bool Item_param::set_str(const char *str, ulong length)
185
Assign string with no conversion: data is converted only after it's
186
been written to the binary log.
188
uint32_t dummy_errors;
189
if (str_value.copy(str, length, &my_charset_bin, &my_charset_bin,
195
/* max_length and decimals are set after charset conversion */
196
/* sic: str may be not null-terminated */
200
bool Item_param::set_longdata(const char *str, ulong length)
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.
211
if (str_value.append(str, length, &my_charset_bin))
213
state= LONG_DATA_VALUE;
221
Set parameter value from user variable value.
223
@param session Current thread
224
@param entry User variable structure (NULL means use NULL value)
232
bool Item_param::set_from_user_var(Session *session, const user_var_entry *entry)
234
if (entry && entry->value)
236
item_result_type= entry->type;
237
unsigned_flag= entry->unsigned_flag;
238
if (limit_clause_param)
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);
244
switch (item_result_type) {
246
set_double(*(double*)entry->value);
247
item_type= Item::REAL_ITEM;
250
set_int(*(int64_t*)entry->value, MY_INT64_NUM_DECIMAL_DIGITS);
251
item_type= Item::INT_ITEM;
255
const CHARSET_INFO * const fromcs= entry->collation.collation;
256
const CHARSET_INFO * const tocs= session->variables.getCollation();
257
uint32_t dummy_offset;
259
value.cs_info.character_set_of_placeholder=
260
value.cs_info.character_set_client= fromcs;
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.
266
value.cs_info.final_character_set_of_str_value=
267
String::needs_conversion(0, fromcs, tocs, &dummy_offset) ?
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.
273
item_type= Item::STRING_ITEM;
275
if (set_str((const char *)entry->value, entry->length))
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;
302
Resets parameter after execution.
305
We clear null_value here instead of setting it in set_* methods,
306
because we want more easily handle case for long data.
309
void Item_param::reset()
311
/* Shrink string buffer if it's bigger than max possible CHAR column */
312
if (str_value.alloced_length() > MAX_CHAR_WIDTH)
316
str_value_ptr.length(0);
318
We must prevent all charset conversions until data has been written
321
str_value.set_charset(&my_charset_bin);
322
collation.set(&my_charset_bin, DERIVATION_COERCIBLE);
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_*
338
int Item_param::save_in_field(Field *field, bool no_conversions)
340
field->set_notnull();
344
return field->store(value.integer, unsigned_flag);
346
return field->store(value.real);
348
return field->store_decimal(&decimal_value);
350
field->store_time(&value.time, value.time.time_type);
353
case LONG_DATA_VALUE:
354
return field->store(str_value.ptr(), str_value.length(),
355
str_value.charset());
357
return set_field_to_null_with_conversions(field, no_conversions);
365
bool Item_param::get_time(DRIZZLE_TIME *res)
367
if (state == TIME_VALUE)
373
If parameter value isn't supplied assertion will fire in val_str()
374
which is called from Item::get_time().
376
return Item::get_time(res);
380
bool Item_param::get_date(DRIZZLE_TIME *res, uint32_t fuzzydate)
382
if (state == TIME_VALUE)
387
return Item::get_date(res, fuzzydate);
391
double Item_param::val_real()
397
return (double) value.integer;
401
my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &result);
405
case LONG_DATA_VALUE:
409
return my_strntod(str_value.charset(), (char*) str_value.ptr(),
410
str_value.length(), &end_not_used, &dummy_err);
414
This works for example when user says SELECT ?+0.0 and supplies
415
time value for the placeholder.
417
return uint64_t2double(TIME_to_uint64_t(&value.time));
427
int64_t Item_param::val_int()
431
return (int64_t) rint(value.real);
433
return value.integer;
437
my_decimal2int(E_DEC_FATAL_ERROR, &decimal_value, unsigned_flag, &i);
441
case LONG_DATA_VALUE:
444
return my_strntoll(str_value.charset(), str_value.ptr(),
445
str_value.length(), 10, (char**) 0, &dummy_err);
448
return (int64_t) TIME_to_uint64_t(&value.time);
458
my_decimal *Item_param::val_decimal(my_decimal *dec)
462
return &decimal_value;
464
double2my_decimal(E_DEC_FATAL_ERROR, value.real, dec);
467
int2my_decimal(E_DEC_FATAL_ERROR, value.integer, unsigned_flag, dec);
470
case LONG_DATA_VALUE:
471
string2my_decimal(E_DEC_FATAL_ERROR, &str_value, dec);
475
int64_t i= (int64_t) TIME_to_uint64_t(&value.time);
476
int2my_decimal(E_DEC_FATAL_ERROR, i, 0, dec);
488
String *Item_param::val_str(String* str)
492
case LONG_DATA_VALUE:
493
return &str_value_ptr;
495
str->set_real(value.real, NOT_FIXED_DEC, &my_charset_bin);
498
str->set(value.integer, &my_charset_bin);
501
if (my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value,
507
if (str->reserve(MAX_DATE_STRING_REP_LENGTH))
509
str->length((uint32_t) my_TIME_to_str(&value.time, (char*) str->ptr()));
510
str->set_charset(&my_charset_bin);
521
/* TODO: fact next two functions out */
523
Transforms a string into "" or its expression in 0x... form.
526
static char *str_to_hex(char *to, const char *from, uint32_t len)
532
to= drizzleclient_drizzleclient_octet2hex(to, from, len);
535
to= strcpy(to, "\"\"")+2;
536
return to; // pointer to end 0 of 'to'
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
548
drizzleclient_escape_string(char *to,const char *from, uint32_t length)
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++)
557
if (!U8_IS_SINGLE(*from))
559
tmp_length= U8_LENGTH(*(uint32_t*)from);
560
if (to + tmp_length > to_end)
571
case 0: /* Must be escaped for 'mysql' */
574
case '\n': /* Must be escaped for logs */
586
case '"': /* Better safe than sorry */
589
case '\032': /* This gives problems on Win32 */
614
return overflow ? (size_t) -1 : (size_t) (to - to_start);
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.
624
append_query_string(const CHARSET_INFO * const csinfo,
625
String const *from, String *to)
628
uint32_t const orig_len= to->length();
629
if (to->reserve(orig_len + from->length()*2+3))
632
beg= to->c_ptr_quick() + to->length();
634
if (csinfo->escape_with_backslash_is_dangerous)
635
ptr= str_to_hex(ptr, from->ptr(), from->length());
639
ptr+= drizzleclient_escape_string(ptr, from->ptr(), from->length());
642
to->length(orig_len + ptr - beg);
648
Return Param item values in string format, for generating the dynamic
649
query used in update/binary logs.
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
658
const String *Item_param::query_val_str(String* str) const
662
str->set_int(value.integer, unsigned_flag, &my_charset_bin);
665
str->set_real(value.real, NOT_FIXED_DEC, &my_charset_bin);
668
if (my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value,
670
return &my_null_string;
677
TODO: in case of error we need to notify replication
678
that binary log contains wrong statement
680
if (str->reserve(MAX_DATE_STRING_REP_LENGTH+3))
683
/* Create date string inplace */
684
buf= str->c_ptr_quick();
687
ptr+= (uint32_t) my_TIME_to_str(&value.time, ptr);
689
str->length((uint32_t) (ptr - buf));
693
case LONG_DATA_VALUE:
696
append_query_string(value.cs_info.character_set_client, &str_value, str);
700
return &my_null_string;
709
Convert string from client character set to the character set of
713
bool Item_param::convert_str_value(Session *session)
716
if (state == STRING_VALUE || state == LONG_DATA_VALUE)
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.
724
if (value.cs_info.final_character_set_of_str_value !=
725
value.cs_info.character_set_of_placeholder)
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);
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 */
735
max_length= str_value.length();
738
str_value_ptr is returned from val_str(). It must be not alloced
739
to prevent it's modification by val_str() invoker.
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);
750
bool Item_param::basic_const_item() const
752
if (state == NO_VALUE || state == TIME_VALUE)
759
Item_param::clone_item()
761
/* see comments in the header file */
764
return new Item_null(name);
766
return (unsigned_flag ?
767
new Item_uint(name, value.integer, max_length) :
768
new Item_int(name, value.integer, max_length));
770
return new Item_float(name, value.real, decimals, max_length);
772
case LONG_DATA_VALUE:
773
return new Item_string(name, str_value.c_ptr_quick(), str_value.length(),
774
str_value.charset());
786
Item_param::eq(const Item *arg, bool binary_cmp) const
789
if (!basic_const_item() || !arg->basic_const_item() || arg->type() != type())
792
We need to cast off const to call val_int(). This should be OK for
801
return value.integer == item->val_int() &&
802
unsigned_flag == item->unsigned_flag;
804
return value.real == item->val_real();
806
case LONG_DATA_VALUE:
808
return !stringcmp(&str_value, &item->str_value);
809
return !sortcmp(&str_value, &item->str_value, collation.collation);
816
/* End of Item_param related */
818
void Item_param::print(String *str, enum_query_type)
820
if (state == NO_VALUE)
826
char buffer[STRING_BUFFER_USUAL_SIZE];
827
String tmp(buffer, sizeof(buffer), &my_charset_bin);
829
res= query_val_str(&tmp);