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
22
#include <drizzled/function/set_user_var.h>
23
#include <drizzled/field/num.h>
24
#include <drizzled/session.h>
25
#include <drizzled/plugin/client.h>
31
When a user variable is updated (in a SET command or a query like
35
bool Item_func_set_user_var::fix_fields(Session *session, Item **ref)
38
/* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
39
if (Item_func::fix_fields(session, ref) ||
40
!(entry= session->getVariable(name, true)))
43
Remember the last query which updated it, this way a query can later know
44
if this variable is a constant item in the query (it is if update_query_id
45
is different from query_id).
47
entry->update_query_id= session->getQueryId();
49
As it is wrong and confusing to associate any
50
character set with NULL, @a should be latin2
51
after this query sequence:
53
SET @a=_latin2'string';
56
I.e. the second query should not change the charset
57
to the current default value, but should keep the
58
original value assigned during the first query.
59
In order to do it, we don't copy charset
60
from the argument if the argument is NULL
61
and the variable has previously been initialized.
63
null_item= (args[0]->type() == NULL_ITEM);
64
if (!entry->collation.collation || !null_item)
65
entry->collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
66
collation.set(entry->collation.collation, DERIVATION_IMPLICIT);
67
cached_result_type= args[0]->result_type();
72
Item_func_set_user_var::fix_length_and_dec()
74
maybe_null=args[0]->maybe_null;
75
max_length=args[0]->max_length;
76
decimals=args[0]->decimals;
77
collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
81
Mark field in read_map
84
This is used by filesort to register used fields in a a temporary
85
column read set or to register used fields in a view
88
bool Item_func_set_user_var::register_field_in_read_map(unsigned char *arg)
92
Table *table= (Table *) arg;
93
if (result_field->table == table || !table)
94
result_field->table->setReadSet(result_field->field_index);
101
Item_func_set_user_var::update_hash(void *ptr, uint32_t length,
102
Item_result res_type,
103
const CHARSET_INFO * const cs, Derivation dv,
107
If we set a variable explicitely to NULL then keep the old
108
result type of the variable
110
if ((null_value= args[0]->null_value) && null_item)
111
res_type= entry->type; // Don't change type of item
112
if (entry->update_hash((null_value= args[0]->null_value),
113
ptr, length, res_type, cs, dv, unsigned_arg))
122
This functions is invoked on SET \@variable or
123
\@variable:= expression.
125
Evaluate (and check expression), store results.
128
For now it always return OK. All problem with value evaluating
129
will be caught by session->is_error() check in sql_set_variables().
136
Item_func_set_user_var::check(bool use_result_field)
138
if (use_result_field && !result_field)
139
use_result_field= false;
141
switch (cached_result_type) {
144
save_result.vreal= use_result_field ? result_field->val_real() :
150
save_result.vint= use_result_field ? result_field->val_int() :
152
unsigned_flag= use_result_field ? ((Field_num*)result_field)->unsigned_flag:
153
args[0]->unsigned_flag;
158
save_result.vstr= use_result_field ? result_field->val_str(&value) :
159
args[0]->val_str(&value);
164
save_result.vdec= use_result_field ?
165
result_field->val_decimal(&decimal_buff) :
166
args[0]->val_decimal(&decimal_buff);
171
// This case should never be chosen
179
This functions is invoked on
180
SET \@variable or \@variable:= expression.
183
We have to store the expression as such in the variable, independent of
184
the value method used by the user
194
Item_func_set_user_var::update()
198
switch (cached_result_type) {
201
res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
202
REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0);
207
res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
208
INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT,
214
if (!save_result.vstr) // Null value
215
res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin,
216
DERIVATION_IMPLICIT, 0);
218
res= update_hash((void*) save_result.vstr->ptr(),
219
save_result.vstr->length(), STRING_RESULT,
220
save_result.vstr->charset(),
221
DERIVATION_IMPLICIT, 0);
226
if (!save_result.vdec) // Null value
227
res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin,
228
DERIVATION_IMPLICIT, 0);
230
res= update_hash((void*) save_result.vdec,
231
sizeof(my_decimal), DECIMAL_RESULT,
232
&my_charset_bin, DERIVATION_IMPLICIT, 0);
237
// This case should never be chosen
244
double Item_func_set_user_var::val_real()
248
update(); // Store expression
249
return entry->val_real(&null_value);
252
int64_t Item_func_set_user_var::val_int()
256
update(); // Store expression
257
return entry->val_int(&null_value);
260
String *Item_func_set_user_var::val_str(String *str)
264
update(); // Store expression
265
return entry->val_str(&null_value, str, decimals);
269
my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val)
273
update(); // Store expression
274
return entry->val_decimal(&null_value, val);
277
double Item_func_set_user_var::val_result()
281
update(); // Store expression
282
return entry->val_real(&null_value);
285
int64_t Item_func_set_user_var::val_int_result()
289
update(); // Store expression
290
return entry->val_int(&null_value);
293
String *Item_func_set_user_var::str_result(String *str)
297
update(); // Store expression
298
return entry->val_str(&null_value, str, decimals);
302
my_decimal *Item_func_set_user_var::val_decimal_result(my_decimal *val)
306
update(); // Store expression
307
return entry->val_decimal(&null_value, val);
310
void Item_func_set_user_var::print(String *str, enum_query_type query_type)
312
str->append(STRING_WITH_LEN("(@"));
313
str->append(name.str, name.length);
314
str->append(STRING_WITH_LEN(":="));
315
args[0]->print(str, query_type);
319
bool Item_func_set_user_var::send(plugin::Client *client, String *str_arg)
325
return client->store(result_field);
327
return Item::send(client, str_arg);
330
void Item_func_set_user_var::make_field(SendField *tmp_field)
334
result_field->make_field(tmp_field);
335
assert(tmp_field->table_name != 0);
337
tmp_field->col_name=Item::name; // Use user supplied name
340
Item::make_field(tmp_field);
344
Save the value of a user variable into a field
348
field target field to save the value to
349
no_conversion flag indicating whether conversions are allowed
352
Save the function value into a field and update the user variable
353
accordingly. If a result field is defined and the target field doesn't
354
coincide with it then the value from the result field will be used as
355
the new value of the user variable.
357
The reason to have this method rather than simply using the result
358
field in the val_xxx() methods is that the value from the result field
359
not always can be used when the result field is defined.
360
Let's consider the following cases:
361
1) when filling a tmp table the result field is defined but the value of it
362
is undefined because it has to be produced yet. Thus we can't use it.
363
2) on execution of an INSERT ... SELECT statement the save_in_field()
364
function will be called to fill the data in the new record. If the SELECT
365
part uses a tmp table then the result field is defined and should be
366
used in order to get the correct result.
368
The difference between the SET_USER_VAR function and regular functions
369
like CONCAT is that the Item_func objects for the regular functions are
370
replaced by Item_field objects after the values of these functions have
371
been stored in a tmp table. Yet an object of the Item_field class cannot
372
be used to update a user variable.
373
Due to this we have to handle the result field in a special way here and
374
in the Item_func_set_user_var::send() function.
381
int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
382
bool can_use_result_field)
384
bool use_result_field= (!can_use_result_field ? 0 :
385
(result_field && result_field != field));
388
/* Update the value of the user variable */
389
check(use_result_field);
392
if (result_type() == STRING_RESULT ||
393
(result_type() == REAL_RESULT && field->result_type() == STRING_RESULT))
396
const CHARSET_INFO * const cs= collation.collation;
397
char buff[MAX_FIELD_WIDTH]; // Alloc buffer for small columns
398
str_value.set_quick(buff, sizeof(buff), cs);
399
result= entry->val_str(&null_value, &str_value, decimals);
403
str_value.set_quick(0, 0, cs);
404
return set_field_to_null_with_conversions(field, no_conversions);
407
/* NOTE: If null_value == false, "result" must be not NULL. */
409
field->set_notnull();
410
error=field->store(result->ptr(),result->length(),cs);
411
str_value.set_quick(0, 0, cs);
413
else if (result_type() == REAL_RESULT)
415
double nr= entry->val_real(&null_value);
417
return set_field_to_null(field);
418
field->set_notnull();
419
error=field->store(nr);
421
else if (result_type() == DECIMAL_RESULT)
423
my_decimal decimal_value;
424
my_decimal *val= entry->val_decimal(&null_value, &decimal_value);
426
return set_field_to_null(field);
427
field->set_notnull();
428
error=field->store_decimal(val);
432
int64_t nr= entry->val_int(&null_value);
434
return set_field_to_null_with_conversions(field, no_conversions);
435
field->set_notnull();
436
error=field->store(nr, unsigned_flag);
442
} /* namespace drizzled */