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/param.h>
26
Item *Item_param::safe_charset_converter(const CHARSET_INFO * const tocs)
31
String *ostr= val_str(&cnvstr);
32
cnvitem->str_value.copy(ostr->ptr(), ostr->length(),
33
ostr->charset(), tocs, &cnv_errors);
36
cnvitem->str_value.mark_as_const();
37
cnvitem->max_length= cnvitem->str_value.numchars() * tocs->mbmaxlen;
44
Default function of Item_param::set_param_func, so in case
45
of malformed packet the server won't SIGSEGV.
49
default_set_param_func(Item_param *param, unsigned char **, ulong)
54
Item_param::Item_param(uint32_t pos_in_query_arg) :
56
item_result_type(STRING_RESULT),
57
/* Don't pretend to be a literal unless value for this item is set. */
58
item_type(PARAM_ITEM),
59
param_type(DRIZZLE_TYPE_VARCHAR),
60
pos_in_query(pos_in_query_arg),
61
set_param_func(default_set_param_func),
62
limit_clause_param(false)
66
Since we can't say whenever this item can be NULL or cannot be NULL
67
before mysql_stmt_execute(), so we assuming that it can be NULL until
71
cnvitem= new Item_string("", 0, &my_charset_bin, DERIVATION_COERCIBLE);
72
cnvstr.set(cnvbuf, sizeof(cnvbuf), &my_charset_bin);
75
void Item_param::set_null()
77
/* These are cleared after each execution by reset() method */
80
Because of NULL and string values we need to set max_length for each new
81
placeholder value: user can submit NULL for any placeholder type, and
82
string length can be different in each execution.
87
item_type= Item::NULL_ITEM;
91
void Item_param::set_int(int64_t i, uint32_t max_length_arg)
93
value.integer= (int64_t) i;
95
max_length= max_length_arg;
101
void Item_param::set_double(double d)
105
max_length= DBL_DIG + 8;
106
decimals= NOT_FIXED_DEC;
112
Set decimal parameter value from string.
114
@param str character string
115
@param length string length
118
As we use character strings to send decimal values in
119
binary protocol, we use str2my_decimal to convert it to
120
internal decimal value.
123
void Item_param::set_decimal(char *str, ulong length)
128
str2my_decimal((uint)E_DEC_FATAL_ERROR, str, &decimal_value, &end);
129
state= DECIMAL_VALUE;
130
decimals= decimal_value.frac;
131
max_length= my_decimal_precision_to_length(decimal_value.precision(),
132
decimals, unsigned_flag);
138
Set parameter value from DRIZZLE_TIME value.
140
@param tm datetime value to set (time_type is ignored)
141
@param type type of datetime value
142
@param max_length_arg max length of datetime value as string
145
If we value to be stored is not normalized, zero value will be stored
146
instead and proper warning will be produced. This function relies on
147
the fact that even wrong value sent over binary protocol fits into
148
MAX_DATE_STRING_REP_LENGTH buffer.
150
void Item_param::set_time(DRIZZLE_TIME *tm,
151
enum enum_drizzle_timestamp_type time_type,
152
uint32_t max_length_arg)
155
value.time.time_type= time_type;
157
if (value.time.year > 9999 || value.time.month > 12 ||
158
value.time.day > 31 ||
159
((time_type != DRIZZLE_TIMESTAMP_TIME) && value.time.hour > 23) ||
160
value.time.minute > 59 || value.time.second > 59)
162
char buff[MAX_DATE_STRING_REP_LENGTH];
163
uint32_t length= my_TIME_to_str(&value.time, buff);
164
make_truncated_value_warning(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
165
buff, length, time_type, 0);
166
set_zero_time(&value.time, DRIZZLE_TIMESTAMP_ERROR);
171
max_length= max_length_arg;
177
bool Item_param::set_str(const char *str, ulong length)
180
Assign string with no conversion: data is converted only after it's
181
been written to the binary log.
183
uint32_t dummy_errors;
184
if (str_value.copy(str, length, &my_charset_bin, &my_charset_bin,
190
/* max_length and decimals are set after charset conversion */
191
/* sic: str may be not null-terminated */
195
bool Item_param::set_longdata(const char *str, ulong length)
198
If client character set is multibyte, end of long data packet
199
may hit at the middle of a multibyte character. Additionally,
200
if binary log is open we must write long data value to the
201
binary log in character set of client. This is why we can't
202
convert long data to connection character set as it comes
203
(here), and first have to concatenate all pieces together,
204
write query to the binary log and only then perform conversion.
206
if (str_value.append(str, length, &my_charset_bin))
208
state= LONG_DATA_VALUE;
216
Set parameter value from user variable value.
218
@param session Current thread
219
@param entry User variable structure (NULL means use NULL value)
227
bool Item_param::set_from_user_var(Session *session, const user_var_entry *entry)
229
if (entry && entry->value)
231
item_result_type= entry->type;
232
unsigned_flag= entry->unsigned_flag;
233
if (limit_clause_param)
236
set_int(entry->val_int(&unused), MY_INT64_NUM_DECIMAL_DIGITS); item_type= Item::INT_ITEM;
237
return(!unsigned_flag && value.integer < 0 ? 1 : 0);
239
switch (item_result_type) {
241
set_double(*(double*)entry->value);
242
item_type= Item::REAL_ITEM;
245
set_int(*(int64_t*)entry->value, MY_INT64_NUM_DECIMAL_DIGITS);
246
item_type= Item::INT_ITEM;
250
const CHARSET_INFO * const fromcs= entry->collation.collation;
251
const CHARSET_INFO * const tocs= session->variables.collation_connection;
252
uint32_t dummy_offset;
254
value.cs_info.character_set_of_placeholder=
255
value.cs_info.character_set_client= fromcs;
257
Setup source and destination character sets so that they
258
are different only if conversion is necessary: this will
259
make later checks easier.
261
value.cs_info.final_character_set_of_str_value=
262
String::needs_conversion(0, fromcs, tocs, &dummy_offset) ?
265
Exact value of max_length is not known unless data is converted to
266
charset of connection, so we have to set it later.
268
item_type= Item::STRING_ITEM;
270
if (set_str((const char *)entry->value, entry->length))
276
const my_decimal *ent_value= (const my_decimal *)entry->value;
277
my_decimal2decimal(ent_value, &decimal_value);
278
state= DECIMAL_VALUE;
279
decimals= ent_value->frac;
280
max_length= my_decimal_precision_to_length(ent_value->precision(),
281
decimals, unsigned_flag);
282
item_type= Item::DECIMAL_ITEM;
297
Resets parameter after execution.
300
We clear null_value here instead of setting it in set_* methods,
301
because we want more easily handle case for long data.
304
void Item_param::reset()
306
/* Shrink string buffer if it's bigger than max possible CHAR column */
307
if (str_value.alloced_length() > MAX_CHAR_WIDTH)
311
str_value_ptr.length(0);
313
We must prevent all charset conversions until data has been written
316
str_value.set_charset(&my_charset_bin);
317
collation.set(&my_charset_bin, DERIVATION_COERCIBLE);
322
Don't reset item_type to PARAM_ITEM: it's only needed to guard
323
us from item optimizations at prepare stage, when item doesn't yet
324
contain a literal of some kind.
325
In all other cases when this object is accessed its value is
326
set (this assumption is guarded by 'state' and
327
assertS(state != NO_VALUE) in all Item_param::get_*
333
int Item_param::save_in_field(Field *field, bool no_conversions)
335
field->set_notnull();
339
return field->store(value.integer, unsigned_flag);
341
return field->store(value.real);
343
return field->store_decimal(&decimal_value);
345
field->store_time(&value.time, value.time.time_type);
348
case LONG_DATA_VALUE:
349
return field->store(str_value.ptr(), str_value.length(),
350
str_value.charset());
352
return set_field_to_null_with_conversions(field, no_conversions);
360
bool Item_param::get_time(DRIZZLE_TIME *res)
362
if (state == TIME_VALUE)
368
If parameter value isn't supplied assertion will fire in val_str()
369
which is called from Item::get_time().
371
return Item::get_time(res);
375
bool Item_param::get_date(DRIZZLE_TIME *res, uint32_t fuzzydate)
377
if (state == TIME_VALUE)
382
return Item::get_date(res, fuzzydate);
386
double Item_param::val_real()
392
return (double) value.integer;
396
my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &result);
400
case LONG_DATA_VALUE:
404
return my_strntod(str_value.charset(), (char*) str_value.ptr(),
405
str_value.length(), &end_not_used, &dummy_err);
409
This works for example when user says SELECT ?+0.0 and supplies
410
time value for the placeholder.
412
return uint64_t2double(TIME_to_uint64_t(&value.time));
422
int64_t Item_param::val_int()
426
return (int64_t) rint(value.real);
428
return value.integer;
432
my_decimal2int(E_DEC_FATAL_ERROR, &decimal_value, unsigned_flag, &i);
436
case LONG_DATA_VALUE:
439
return my_strntoll(str_value.charset(), str_value.ptr(),
440
str_value.length(), 10, (char**) 0, &dummy_err);
443
return (int64_t) TIME_to_uint64_t(&value.time);
453
my_decimal *Item_param::val_decimal(my_decimal *dec)
457
return &decimal_value;
459
double2my_decimal(E_DEC_FATAL_ERROR, value.real, dec);
462
int2my_decimal(E_DEC_FATAL_ERROR, value.integer, unsigned_flag, dec);
465
case LONG_DATA_VALUE:
466
string2my_decimal(E_DEC_FATAL_ERROR, &str_value, dec);
470
int64_t i= (int64_t) TIME_to_uint64_t(&value.time);
471
int2my_decimal(E_DEC_FATAL_ERROR, i, 0, dec);
483
String *Item_param::val_str(String* str)
487
case LONG_DATA_VALUE:
488
return &str_value_ptr;
490
str->set_real(value.real, NOT_FIXED_DEC, &my_charset_bin);
493
str->set(value.integer, &my_charset_bin);
496
if (my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value,
502
if (str->reserve(MAX_DATE_STRING_REP_LENGTH))
504
str->length((uint) my_TIME_to_str(&value.time, (char*) str->ptr()));
505
str->set_charset(&my_charset_bin);
517
Return Param item values in string format, for generating the dynamic
518
query used in update/binary logs.
521
- Change interface and implementation to fill log data in place
522
and avoid one more memcpy/alloc between str and log string.
523
- In case of error we need to notify replication
524
that binary log contains wrong statement
527
const String *Item_param::query_val_str(String* str) const
531
str->set_int(value.integer, unsigned_flag, &my_charset_bin);
534
str->set_real(value.real, NOT_FIXED_DEC, &my_charset_bin);
537
if (my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value,
539
return &my_null_string;
546
TODO: in case of error we need to notify replication
547
that binary log contains wrong statement
549
if (str->reserve(MAX_DATE_STRING_REP_LENGTH+3))
552
/* Create date string inplace */
553
buf= str->c_ptr_quick();
556
ptr+= (uint) my_TIME_to_str(&value.time, ptr);
558
str->length((uint32_t) (ptr - buf));
562
case LONG_DATA_VALUE:
565
append_query_string(value.cs_info.character_set_client, &str_value, str);
569
return &my_null_string;
578
Convert string from client character set to the character set of
582
bool Item_param::convert_str_value(Session *session)
585
if (state == STRING_VALUE || state == LONG_DATA_VALUE)
588
Check is so simple because all charsets were set up properly
589
in setup_one_conversion_function, where typecode of
590
placeholder was also taken into account: the variables are different
591
here only if conversion is really necessary.
593
if (value.cs_info.final_character_set_of_str_value !=
594
value.cs_info.character_set_of_placeholder)
596
rc= session->convert_string(&str_value,
597
value.cs_info.character_set_of_placeholder,
598
value.cs_info.final_character_set_of_str_value);
601
str_value.set_charset(value.cs_info.final_character_set_of_str_value);
602
/* Here str_value is guaranteed to be in final_character_set_of_str_value */
604
max_length= str_value.length();
607
str_value_ptr is returned from val_str(). It must be not alloced
608
to prevent it's modification by val_str() invoker.
610
str_value_ptr.set(str_value.ptr(), str_value.length(),
611
str_value.charset());
612
/* Synchronize item charset with value charset */
613
collation.set(str_value.charset(), DERIVATION_COERCIBLE);
619
bool Item_param::basic_const_item() const
621
if (state == NO_VALUE || state == TIME_VALUE)
628
Item_param::clone_item()
630
/* see comments in the header file */
633
return new Item_null(name);
635
return (unsigned_flag ?
636
new Item_uint(name, value.integer, max_length) :
637
new Item_int(name, value.integer, max_length));
639
return new Item_float(name, value.real, decimals, max_length);
641
case LONG_DATA_VALUE:
642
return new Item_string(name, str_value.c_ptr_quick(), str_value.length(),
643
str_value.charset());
655
Item_param::eq(const Item *arg, bool binary_cmp) const
658
if (!basic_const_item() || !arg->basic_const_item() || arg->type() != type())
661
We need to cast off const to call val_int(). This should be OK for
670
return value.integer == item->val_int() &&
671
unsigned_flag == item->unsigned_flag;
673
return value.real == item->val_real();
675
case LONG_DATA_VALUE:
677
return !stringcmp(&str_value, &item->str_value);
678
return !sortcmp(&str_value, &item->str_value, collation.collation);
685
/* End of Item_param related */
687
void Item_param::print(String *str, enum_query_type)
689
if (state == NO_VALUE)
695
char buffer[STRING_BUFFER_USUAL_SIZE];
696
String tmp(buffer, sizeof(buffer), &my_charset_bin);
698
res= query_val_str(&tmp);