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/update_hash.h>
24
#include <drizzled/field/num.h>
25
#include <drizzled/session.h>
28
When a user variable is updated (in a SET command or a query like
32
bool Item_func_set_user_var::fix_fields(Session *session, Item **ref)
35
/* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
36
if (Item_func::fix_fields(session, ref) ||
37
!(entry= session->getVariable(name, true)))
40
Remember the last query which updated it, this way a query can later know
41
if this variable is a constant item in the query (it is if update_query_id
42
is different from query_id).
44
entry->update_query_id= session->query_id;
46
As it is wrong and confusing to associate any
47
character set with NULL, @a should be latin2
48
after this query sequence:
50
SET @a=_latin2'string';
53
I.e. the second query should not change the charset
54
to the current default value, but should keep the
55
original value assigned during the first query.
56
In order to do it, we don't copy charset
57
from the argument if the argument is NULL
58
and the variable has previously been initialized.
60
null_item= (args[0]->type() == NULL_ITEM);
61
if (!entry->collation.collation || !null_item)
62
entry->collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
63
collation.set(entry->collation.collation, DERIVATION_IMPLICIT);
64
cached_result_type= args[0]->result_type();
69
Item_func_set_user_var::fix_length_and_dec()
71
maybe_null=args[0]->maybe_null;
72
max_length=args[0]->max_length;
73
decimals=args[0]->decimals;
74
collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
78
Mark field in read_map
81
This is used by filesort to register used fields in a a temporary
82
column read set or to register used fields in a view
85
bool Item_func_set_user_var::register_field_in_read_map(unsigned char *arg)
89
Table *table= (Table *) arg;
90
if (result_field->table == table || !table)
91
result_field->table->setReadSet(result_field->field_index);
98
Item_func_set_user_var::update_hash(void *ptr, uint32_t length,
100
const CHARSET_INFO * const cs, Derivation dv,
104
If we set a variable explicitely to NULL then keep the old
105
result type of the variable
107
if ((null_value= args[0]->null_value) && null_item)
108
res_type= entry->type; // Don't change type of item
109
if (::update_hash(entry, (null_value= args[0]->null_value),
110
ptr, length, res_type, cs, dv, unsigned_arg))
119
This functions is invoked on SET \@variable or
120
\@variable:= expression.
122
Evaluate (and check expression), store results.
125
For now it always return OK. All problem with value evaluating
126
will be caught by session->is_error() check in sql_set_variables().
133
Item_func_set_user_var::check(bool use_result_field)
135
if (use_result_field && !result_field)
136
use_result_field= false;
138
switch (cached_result_type) {
141
save_result.vreal= use_result_field ? result_field->val_real() :
147
save_result.vint= use_result_field ? result_field->val_int() :
149
unsigned_flag= use_result_field ? ((Field_num*)result_field)->unsigned_flag:
150
args[0]->unsigned_flag;
155
save_result.vstr= use_result_field ? result_field->val_str(&value) :
156
args[0]->val_str(&value);
161
save_result.vdec= use_result_field ?
162
result_field->val_decimal(&decimal_buff) :
163
args[0]->val_decimal(&decimal_buff);
168
// This case should never be chosen
176
This functions is invoked on
177
SET \@variable or \@variable:= expression.
180
We have to store the expression as such in the variable, independent of
181
the value method used by the user
191
Item_func_set_user_var::update()
195
switch (cached_result_type) {
198
res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
199
REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0);
204
res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
205
INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT,
211
if (!save_result.vstr) // Null value
212
res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin,
213
DERIVATION_IMPLICIT, 0);
215
res= update_hash((void*) save_result.vstr->ptr(),
216
save_result.vstr->length(), STRING_RESULT,
217
save_result.vstr->charset(),
218
DERIVATION_IMPLICIT, 0);
223
if (!save_result.vdec) // Null value
224
res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin,
225
DERIVATION_IMPLICIT, 0);
227
res= update_hash((void*) save_result.vdec,
228
sizeof(my_decimal), DECIMAL_RESULT,
229
&my_charset_bin, DERIVATION_IMPLICIT, 0);
234
// This case should never be chosen
241
double Item_func_set_user_var::val_real()
245
update(); // Store expression
246
return entry->val_real(&null_value);
249
int64_t Item_func_set_user_var::val_int()
253
update(); // Store expression
254
return entry->val_int(&null_value);
257
String *Item_func_set_user_var::val_str(String *str)
261
update(); // Store expression
262
return entry->val_str(&null_value, str, decimals);
266
my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val)
270
update(); // Store expression
271
return entry->val_decimal(&null_value, val);
274
double Item_func_set_user_var::val_result()
278
update(); // Store expression
279
return entry->val_real(&null_value);
282
int64_t Item_func_set_user_var::val_int_result()
286
update(); // Store expression
287
return entry->val_int(&null_value);
290
String *Item_func_set_user_var::str_result(String *str)
294
update(); // Store expression
295
return entry->val_str(&null_value, str, decimals);
299
my_decimal *Item_func_set_user_var::val_decimal_result(my_decimal *val)
303
update(); // Store expression
304
return entry->val_decimal(&null_value, val);
307
void Item_func_set_user_var::print(String *str, enum_query_type query_type)
309
str->append(STRING_WITH_LEN("(@"));
310
str->append(name.str, name.length);
311
str->append(STRING_WITH_LEN(":="));
312
args[0]->print(str, query_type);
317
void Item_func_set_user_var::print_as_stmt(String *str,
318
enum_query_type query_type)
320
str->append(STRING_WITH_LEN("set @"));
321
str->append(name.str, name.length);
322
str->append(STRING_WITH_LEN(":="));
323
args[0]->print(str, query_type);
327
bool Item_func_set_user_var::send(Protocol *protocol, String *str_arg)
333
return protocol->store(result_field);
335
return Item::send(protocol, str_arg);
338
void Item_func_set_user_var::make_field(SendField *tmp_field)
342
result_field->make_field(tmp_field);
343
assert(tmp_field->table_name != 0);
345
tmp_field->col_name=Item::name; // Use user supplied name
348
Item::make_field(tmp_field);
352
Save the value of a user variable into a field
356
field target field to save the value to
357
no_conversion flag indicating whether conversions are allowed
360
Save the function value into a field and update the user variable
361
accordingly. If a result field is defined and the target field doesn't
362
coincide with it then the value from the result field will be used as
363
the new value of the user variable.
365
The reason to have this method rather than simply using the result
366
field in the val_xxx() methods is that the value from the result field
367
not always can be used when the result field is defined.
368
Let's consider the following cases:
369
1) when filling a tmp table the result field is defined but the value of it
370
is undefined because it has to be produced yet. Thus we can't use it.
371
2) on execution of an INSERT ... SELECT statement the save_in_field()
372
function will be called to fill the data in the new record. If the SELECT
373
part uses a tmp table then the result field is defined and should be
374
used in order to get the correct result.
376
The difference between the SET_USER_VAR function and regular functions
377
like CONCAT is that the Item_func objects for the regular functions are
378
replaced by Item_field objects after the values of these functions have
379
been stored in a tmp table. Yet an object of the Item_field class cannot
380
be used to update a user variable.
381
Due to this we have to handle the result field in a special way here and
382
in the Item_func_set_user_var::send() function.
389
int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
390
bool can_use_result_field)
392
bool use_result_field= (!can_use_result_field ? 0 :
393
(result_field && result_field != field));
396
/* Update the value of the user variable */
397
check(use_result_field);
400
if (result_type() == STRING_RESULT ||
401
(result_type() == REAL_RESULT && field->result_type() == STRING_RESULT))
404
const CHARSET_INFO * const cs= collation.collation;
405
char buff[MAX_FIELD_WIDTH]; // Alloc buffer for small columns
406
str_value.set_quick(buff, sizeof(buff), cs);
407
result= entry->val_str(&null_value, &str_value, decimals);
411
str_value.set_quick(0, 0, cs);
412
return set_field_to_null_with_conversions(field, no_conversions);
415
/* NOTE: If null_value == false, "result" must be not NULL. */
417
field->set_notnull();
418
error=field->store(result->ptr(),result->length(),cs);
419
str_value.set_quick(0, 0, cs);
421
else if (result_type() == REAL_RESULT)
423
double nr= entry->val_real(&null_value);
425
return set_field_to_null(field);
426
field->set_notnull();
427
error=field->store(nr);
429
else if (result_type() == DECIMAL_RESULT)
431
my_decimal decimal_value;
432
my_decimal *val= entry->val_decimal(&null_value, &decimal_value);
434
return set_field_to_null(field);
435
field->set_notnull();
436
error=field->store_decimal(val);
440
int64_t nr= entry->val_int(&null_value);
442
return set_field_to_null_with_conversions(field, no_conversions);
443
field->set_notnull();
444
error=field->store(nr, unsigned_flag);