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>
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((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);
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((uint) 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= octet2hex(to, from, len);
534
to= strcpy(to, "\"\"")+2;
535
return to; // pointer to end 0 of 'to'
539
/* Borrowed from libicu header */
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)\
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
560
drizzle_escape_string(char *to,const char *from, uint32_t length)
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++)
569
if (!U8_IS_SINGLE(*from))
571
tmp_length= U8_LENGTH(*from);
572
if (to + tmp_length > to_end)
583
case 0: /* Must be escaped for 'mysql' */
586
case '\n': /* Must be escaped for logs */
598
case '"': /* Better safe than sorry */
601
case '\032': /* This gives problems on Win32 */
626
return overflow ? (size_t) -1 : (size_t) (to - to_start);
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.
636
append_query_string(const CHARSET_INFO * const csinfo,
637
String const *from, String *to)
640
uint32_t const orig_len= to->length();
641
if (to->reserve(orig_len + from->length()*2+3))
644
beg= to->c_ptr_quick() + to->length();
646
if (csinfo->escape_with_backslash_is_dangerous)
647
ptr= str_to_hex(ptr, from->ptr(), from->length());
651
ptr+= drizzle_escape_string(ptr, from->ptr(), from->length());
654
to->length(orig_len + ptr - beg);
660
Return Param item values in string format, for generating the dynamic
661
query used in update/binary logs.
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
670
const String *Item_param::query_val_str(String* str) const
674
str->set_int(value.integer, unsigned_flag, &my_charset_bin);
677
str->set_real(value.real, NOT_FIXED_DEC, &my_charset_bin);
680
if (my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value,
682
return &my_null_string;
689
TODO: in case of error we need to notify replication
690
that binary log contains wrong statement
692
if (str->reserve(MAX_DATE_STRING_REP_LENGTH+3))
695
/* Create date string inplace */
696
buf= str->c_ptr_quick();
699
ptr+= (uint) my_TIME_to_str(&value.time, ptr);
701
str->length((uint32_t) (ptr - buf));
705
case LONG_DATA_VALUE:
708
append_query_string(value.cs_info.character_set_client, &str_value, str);
712
return &my_null_string;
721
Convert string from client character set to the character set of
725
bool Item_param::convert_str_value(Session *session)
728
if (state == STRING_VALUE || state == LONG_DATA_VALUE)
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.
736
if (value.cs_info.final_character_set_of_str_value !=
737
value.cs_info.character_set_of_placeholder)
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);
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 */
747
max_length= str_value.length();
750
str_value_ptr is returned from val_str(). It must be not alloced
751
to prevent it's modification by val_str() invoker.
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);
762
bool Item_param::basic_const_item() const
764
if (state == NO_VALUE || state == TIME_VALUE)
771
Item_param::clone_item()
773
/* see comments in the header file */
776
return new Item_null(name);
778
return (unsigned_flag ?
779
new Item_uint(name, value.integer, max_length) :
780
new Item_int(name, value.integer, max_length));
782
return new Item_float(name, value.real, decimals, max_length);
784
case LONG_DATA_VALUE:
785
return new Item_string(name, str_value.c_ptr_quick(), str_value.length(),
786
str_value.charset());
798
Item_param::eq(const Item *arg, bool binary_cmp) const
801
if (!basic_const_item() || !arg->basic_const_item() || arg->type() != type())
804
We need to cast off const to call val_int(). This should be OK for
813
return value.integer == item->val_int() &&
814
unsigned_flag == item->unsigned_flag;
816
return value.real == item->val_real();
818
case LONG_DATA_VALUE:
820
return !stringcmp(&str_value, &item->str_value);
821
return !sortcmp(&str_value, &item->str_value, collation.collation);
828
/* End of Item_param related */
830
void Item_param::print(String *str, enum_query_type)
832
if (state == NO_VALUE)
838
char buffer[STRING_BUFFER_USUAL_SIZE];
839
String tmp(buffer, sizeof(buffer), &my_charset_bin);
841
res= query_val_str(&tmp);