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->getTable() == table || !table)
94
result_field->getTable()->setReadSet(result_field->position());
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_internal(&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);
170
// 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);
208
res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
209
INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT,
216
if (!save_result.vstr) // Null value
217
res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin,
218
DERIVATION_IMPLICIT, 0);
220
res= update_hash((void*) save_result.vstr->ptr(),
221
save_result.vstr->length(), STRING_RESULT,
222
save_result.vstr->charset(),
223
DERIVATION_IMPLICIT, 0);
229
if (!save_result.vdec) // Null value
230
res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin,
231
DERIVATION_IMPLICIT, 0);
233
res= update_hash((void*) save_result.vdec,
234
sizeof(my_decimal), DECIMAL_RESULT,
235
&my_charset_bin, DERIVATION_IMPLICIT, 0);
240
// This case should never be chosen
248
double Item_func_set_user_var::val_real()
252
update(); // Store expression
253
return entry->val_real(&null_value);
256
int64_t Item_func_set_user_var::val_int()
260
update(); // Store expression
261
return entry->val_int(&null_value);
264
String *Item_func_set_user_var::val_str(String *str)
268
update(); // Store expression
269
return entry->val_str(&null_value, str, decimals);
273
my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val)
277
update(); // Store expression
278
return entry->val_decimal(&null_value, val);
281
double Item_func_set_user_var::val_result()
285
update(); // Store expression
286
return entry->val_real(&null_value);
289
int64_t Item_func_set_user_var::val_int_result()
293
update(); // Store expression
294
return entry->val_int(&null_value);
297
String *Item_func_set_user_var::str_result(String *str)
301
update(); // Store expression
302
return entry->val_str(&null_value, str, decimals);
306
my_decimal *Item_func_set_user_var::val_decimal_result(my_decimal *val)
310
update(); // Store expression
311
return entry->val_decimal(&null_value, val);
314
void Item_func_set_user_var::print(String *str, enum_query_type query_type)
316
str->append(STRING_WITH_LEN("(@"));
317
str->append(name.str, name.length);
318
str->append(STRING_WITH_LEN(":="));
319
args[0]->print(str, query_type);
323
bool Item_func_set_user_var::send(plugin::Client *client, String *str_arg)
329
return client->store(result_field);
331
return Item::send(client, str_arg);
334
void Item_func_set_user_var::make_field(SendField *tmp_field)
338
result_field->make_field(tmp_field);
339
assert(tmp_field->table_name != 0);
341
tmp_field->col_name=Item::name; // Use user supplied name
344
Item::make_field(tmp_field);
348
Save the value of a user variable into a field
352
field target field to save the value to
353
no_conversion flag indicating whether conversions are allowed
356
Save the function value into a field and update the user variable
357
accordingly. If a result field is defined and the target field doesn't
358
coincide with it then the value from the result field will be used as
359
the new value of the user variable.
361
The reason to have this method rather than simply using the result
362
field in the val_xxx() methods is that the value from the result field
363
not always can be used when the result field is defined.
364
Let's consider the following cases:
365
1) when filling a tmp table the result field is defined but the value of it
366
is undefined because it has to be produced yet. Thus we can't use it.
367
2) on execution of an INSERT ... SELECT statement the save_in_field()
368
function will be called to fill the data in the new record. If the SELECT
369
part uses a tmp table then the result field is defined and should be
370
used in order to get the correct result.
372
The difference between the SET_USER_VAR function and regular functions
373
like CONCAT is that the Item_func objects for the regular functions are
374
replaced by Item_field objects after the values of these functions have
375
been stored in a tmp table. Yet an object of the Item_field class cannot
376
be used to update a user variable.
377
Due to this we have to handle the result field in a special way here and
378
in the Item_func_set_user_var::send() function.
385
int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
386
bool can_use_result_field)
388
bool use_result_field= (!can_use_result_field ? 0 :
389
(result_field && result_field != field));
392
/* Update the value of the user variable */
393
check(use_result_field);
396
if (result_type() == STRING_RESULT ||
397
(result_type() == REAL_RESULT && field->result_type() == STRING_RESULT))
400
const CHARSET_INFO * const cs= collation.collation;
401
char buff[MAX_FIELD_WIDTH]; // Alloc buffer for small columns
402
str_value.set_quick(buff, sizeof(buff), cs);
403
result= entry->val_str(&null_value, &str_value, decimals);
407
str_value.set_quick(0, 0, cs);
408
return set_field_to_null_with_conversions(field, no_conversions);
411
/* NOTE: If null_value == false, "result" must be not NULL. */
413
field->set_notnull();
414
error=field->store(result->ptr(),result->length(),cs);
415
str_value.set_quick(0, 0, cs);
417
else if (result_type() == REAL_RESULT)
419
double nr= entry->val_real(&null_value);
421
return set_field_to_null(field);
422
field->set_notnull();
423
error=field->store(nr);
425
else if (result_type() == DECIMAL_RESULT)
427
my_decimal decimal_value;
428
my_decimal *val= entry->val_decimal(&null_value, &decimal_value);
430
return set_field_to_null(field);
431
field->set_notnull();
432
error=field->store_decimal(val);
436
int64_t nr= entry->val_int(&null_value);
438
return set_field_to_null_with_conversions(field, no_conversions);
439
field->set_notnull();
440
error=field->store(nr, unsigned_flag);
446
} /* namespace drizzled */