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/function/set_user_var.h>
23
#include <drizzled/function/get_variable.h>
24
#include <drizzled/function/update_hash.h>
25
#include <drizzled/field/num.h>
26
#include <drizzled/virtual_column_info.h>
27
#include <drizzled/session.h>
30
When a user variable is updated (in a SET command or a query like
34
bool Item_func_set_user_var::fix_fields(Session *session, Item **ref)
37
/* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
38
if (Item_func::fix_fields(session, ref) ||
39
!(entry= get_variable(&session->user_vars, name, 1)))
42
Remember the last query which updated it, this way a query can later know
43
if this variable is a constant item in the query (it is if update_query_id
44
is different from query_id).
46
entry->update_query_id= session->query_id;
48
As it is wrong and confusing to associate any
49
character set with NULL, @a should be latin2
50
after this query sequence:
52
SET @a=_latin2'string';
55
I.e. the second query should not change the charset
56
to the current default value, but should keep the
57
original value assigned during the first query.
58
In order to do it, we don't copy charset
59
from the argument if the argument is NULL
60
and the variable has previously been initialized.
62
null_item= (args[0]->type() == NULL_ITEM);
63
if (!entry->collation.collation || !null_item)
64
entry->collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
65
collation.set(entry->collation.collation, DERIVATION_IMPLICIT);
66
cached_result_type= args[0]->result_type();
71
Item_func_set_user_var::fix_length_and_dec()
73
maybe_null=args[0]->maybe_null;
74
max_length=args[0]->max_length;
75
decimals=args[0]->decimals;
76
collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
80
Mark field in read_map
83
This is used by filesort to register used fields in a a temporary
84
column read set or to register used fields in a view
87
bool Item_func_set_user_var::register_field_in_read_map(unsigned char *arg)
91
Table *table= (Table *) arg;
92
if (result_field->table == table || !table)
93
bitmap_set_bit(result_field->table->read_set, result_field->field_index);
94
if (result_field->vcol_info && result_field->vcol_info->expr_item)
95
return result_field->vcol_info->
96
expr_item->walk(&Item::register_field_in_read_map, 1, arg);
102
Mark field in bitmap supplied as *arg
106
bool Item_func_set_user_var::register_field_in_bitmap(unsigned char *arg)
108
MY_BITMAP *bitmap = (MY_BITMAP *) arg;
112
bitmap_set_bit(bitmap, result_field->field_index);
118
Item_func_set_user_var::update_hash(void *ptr, uint32_t length,
119
Item_result res_type,
120
const CHARSET_INFO * const cs, Derivation dv,
124
If we set a variable explicitely to NULL then keep the old
125
result type of the variable
127
if ((null_value= args[0]->null_value) && null_item)
128
res_type= entry->type; // Don't change type of item
129
if (::update_hash(entry, (null_value= args[0]->null_value),
130
ptr, length, res_type, cs, dv, unsigned_arg))
139
This functions is invoked on SET \@variable or
140
\@variable:= expression.
142
Evaluate (and check expression), store results.
145
For now it always return OK. All problem with value evaluating
146
will be caught by session->is_error() check in sql_set_variables().
153
Item_func_set_user_var::check(bool use_result_field)
155
if (use_result_field && !result_field)
156
use_result_field= false;
158
switch (cached_result_type) {
161
save_result.vreal= use_result_field ? result_field->val_real() :
167
save_result.vint= use_result_field ? result_field->val_int() :
169
unsigned_flag= use_result_field ? ((Field_num*)result_field)->unsigned_flag:
170
args[0]->unsigned_flag;
175
save_result.vstr= use_result_field ? result_field->val_str(&value) :
176
args[0]->val_str(&value);
181
save_result.vdec= use_result_field ?
182
result_field->val_decimal(&decimal_buff) :
183
args[0]->val_decimal(&decimal_buff);
188
// This case should never be chosen
196
This functions is invoked on
197
SET \@variable or \@variable:= expression.
200
We have to store the expression as such in the variable, independent of
201
the value method used by the user
211
Item_func_set_user_var::update()
215
switch (cached_result_type) {
218
res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
219
REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0);
224
res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
225
INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT,
231
if (!save_result.vstr) // Null value
232
res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin,
233
DERIVATION_IMPLICIT, 0);
235
res= update_hash((void*) save_result.vstr->ptr(),
236
save_result.vstr->length(), STRING_RESULT,
237
save_result.vstr->charset(),
238
DERIVATION_IMPLICIT, 0);
243
if (!save_result.vdec) // Null value
244
res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin,
245
DERIVATION_IMPLICIT, 0);
247
res= update_hash((void*) save_result.vdec,
248
sizeof(my_decimal), DECIMAL_RESULT,
249
&my_charset_bin, DERIVATION_IMPLICIT, 0);
254
// This case should never be chosen
261
double Item_func_set_user_var::val_real()
265
update(); // Store expression
266
return entry->val_real(&null_value);
269
int64_t Item_func_set_user_var::val_int()
273
update(); // Store expression
274
return entry->val_int(&null_value);
277
String *Item_func_set_user_var::val_str(String *str)
281
update(); // Store expression
282
return entry->val_str(&null_value, str, decimals);
286
my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val)
290
update(); // Store expression
291
return entry->val_decimal(&null_value, val);
294
double Item_func_set_user_var::val_result()
298
update(); // Store expression
299
return entry->val_real(&null_value);
302
int64_t Item_func_set_user_var::val_int_result()
306
update(); // Store expression
307
return entry->val_int(&null_value);
310
String *Item_func_set_user_var::str_result(String *str)
314
update(); // Store expression
315
return entry->val_str(&null_value, str, decimals);
319
my_decimal *Item_func_set_user_var::val_decimal_result(my_decimal *val)
323
update(); // Store expression
324
return entry->val_decimal(&null_value, val);
327
void Item_func_set_user_var::print(String *str, enum_query_type query_type)
329
str->append(STRING_WITH_LEN("(@"));
330
str->append(name.str, name.length);
331
str->append(STRING_WITH_LEN(":="));
332
args[0]->print(str, query_type);
337
void Item_func_set_user_var::print_as_stmt(String *str,
338
enum_query_type query_type)
340
str->append(STRING_WITH_LEN("set @"));
341
str->append(name.str, name.length);
342
str->append(STRING_WITH_LEN(":="));
343
args[0]->print(str, query_type);
347
bool Item_func_set_user_var::send(Protocol *protocol, String *str_arg)
353
return protocol->store(result_field);
355
return Item::send(protocol, str_arg);
358
void Item_func_set_user_var::make_field(Send_field *tmp_field)
362
result_field->make_field(tmp_field);
363
assert(tmp_field->table_name != 0);
365
tmp_field->col_name=Item::name; // Use user supplied name
368
Item::make_field(tmp_field);
372
Save the value of a user variable into a field
376
field target field to save the value to
377
no_conversion flag indicating whether conversions are allowed
380
Save the function value into a field and update the user variable
381
accordingly. If a result field is defined and the target field doesn't
382
coincide with it then the value from the result field will be used as
383
the new value of the user variable.
385
The reason to have this method rather than simply using the result
386
field in the val_xxx() methods is that the value from the result field
387
not always can be used when the result field is defined.
388
Let's consider the following cases:
389
1) when filling a tmp table the result field is defined but the value of it
390
is undefined because it has to be produced yet. Thus we can't use it.
391
2) on execution of an INSERT ... SELECT statement the save_in_field()
392
function will be called to fill the data in the new record. If the SELECT
393
part uses a tmp table then the result field is defined and should be
394
used in order to get the correct result.
396
The difference between the SET_USER_VAR function and regular functions
397
like CONCAT is that the Item_func objects for the regular functions are
398
replaced by Item_field objects after the values of these functions have
399
been stored in a tmp table. Yet an object of the Item_field class cannot
400
be used to update a user variable.
401
Due to this we have to handle the result field in a special way here and
402
in the Item_func_set_user_var::send() function.
409
int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
410
bool can_use_result_field)
412
bool use_result_field= (!can_use_result_field ? 0 :
413
(result_field && result_field != field));
416
/* Update the value of the user variable */
417
check(use_result_field);
420
if (result_type() == STRING_RESULT ||
421
(result_type() == REAL_RESULT && field->result_type() == STRING_RESULT))
424
const CHARSET_INFO * const cs= collation.collation;
425
char buff[MAX_FIELD_WIDTH]; // Alloc buffer for small columns
426
str_value.set_quick(buff, sizeof(buff), cs);
427
result= entry->val_str(&null_value, &str_value, decimals);
431
str_value.set_quick(0, 0, cs);
432
return set_field_to_null_with_conversions(field, no_conversions);
435
/* NOTE: If null_value == false, "result" must be not NULL. */
437
field->set_notnull();
438
error=field->store(result->ptr(),result->length(),cs);
439
str_value.set_quick(0, 0, cs);
441
else if (result_type() == REAL_RESULT)
443
double nr= entry->val_real(&null_value);
445
return set_field_to_null(field);
446
field->set_notnull();
447
error=field->store(nr);
449
else if (result_type() == DECIMAL_RESULT)
451
my_decimal decimal_value;
452
my_decimal *val= entry->val_decimal(&null_value, &decimal_value);
454
return set_field_to_null(field);
455
field->set_notnull();
456
error=field->store_decimal(val);
460
int64_t nr= entry->val_int(&null_value);
462
return set_field_to_null_with_conversions(field, no_conversions);
463
field->set_notnull();
464
error=field->store(nr, unsigned_flag);