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, Inc.
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>
26
#include <drizzled/user_var_entry.h>
32
When a user variable is updated (in a SET command or a query like
36
bool Item_func_set_user_var::fix_fields(Session *session, Item **ref)
39
/* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
40
if (Item_func::fix_fields(session, ref) ||
41
!(entry= session->getVariable(name, true)))
44
Remember the last query which updated it, this way a query can later know
45
if this variable is a constant item in the query (it is if update_query_id
46
is different from query_id).
48
entry->update_query_id= session->getQueryId();
50
As it is wrong and confusing to associate any
51
character set with NULL, @a should be latin2
52
after this query sequence:
54
SET @a=_latin2'string';
57
I.e. the second query should not change the charset
58
to the current default value, but should keep the
59
original value assigned during the first query.
60
In order to do it, we don't copy charset
61
from the argument if the argument is NULL
62
and the variable has previously been initialized.
64
null_item= (args[0]->type() == NULL_ITEM);
65
if (!entry->collation.collation || !null_item)
66
entry->collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
67
collation.set(entry->collation.collation, DERIVATION_IMPLICIT);
68
cached_result_type= args[0]->result_type();
73
Item_func_set_user_var::fix_length_and_dec()
75
maybe_null=args[0]->maybe_null;
76
max_length=args[0]->max_length;
77
decimals=args[0]->decimals;
78
collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
82
Mark field in read_map
85
This is used by filesort to register used fields in a a temporary
86
column read set or to register used fields in a view
89
bool Item_func_set_user_var::register_field_in_read_map(unsigned char *arg)
93
Table *table= (Table *) arg;
94
if (result_field->getTable() == table || !table)
95
result_field->getTable()->setReadSet(result_field->position());
102
Item_func_set_user_var::update_hash(void *ptr, uint32_t length,
103
Item_result res_type,
104
const CHARSET_INFO * const cs, Derivation dv,
108
If we set a variable explicitely to NULL then keep the old
109
result type of the variable
111
if ((null_value= args[0]->null_value) && null_item)
112
res_type= entry->type; // Don't change type of item
113
if (entry->update_hash((null_value= args[0]->null_value),
114
ptr, length, res_type, cs, dv, unsigned_arg))
123
This functions is invoked on SET \@variable or
124
\@variable:= expression.
126
Evaluate (and check expression), store results.
129
For now it always return OK. All problem with value evaluating
130
will be caught by session->is_error() check in sql_set_variables().
137
Item_func_set_user_var::check(bool use_result_field)
139
if (use_result_field && !result_field)
140
use_result_field= false;
142
switch (cached_result_type) {
145
save_result.vreal= use_result_field ? result_field->val_real() :
151
save_result.vint= use_result_field ? result_field->val_int() :
153
unsigned_flag= use_result_field ? ((Field_num*)result_field)->unsigned_flag:
154
args[0]->unsigned_flag;
159
save_result.vstr= use_result_field ? result_field->val_str_internal(&value) :
160
args[0]->val_str(&value);
165
save_result.vdec= use_result_field ?
166
result_field->val_decimal(&decimal_buff) :
167
args[0]->val_decimal(&decimal_buff);
171
// This case should never be chosen
180
This functions is invoked on
181
SET \@variable or \@variable:= expression.
184
We have to store the expression as such in the variable, independent of
185
the value method used by the user
195
Item_func_set_user_var::update()
199
switch (cached_result_type) {
202
res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
203
REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0);
209
res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
210
INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT,
217
if (!save_result.vstr) // Null value
218
res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin,
219
DERIVATION_IMPLICIT, 0);
221
res= update_hash((void*) save_result.vstr->ptr(),
222
save_result.vstr->length(), STRING_RESULT,
223
save_result.vstr->charset(),
224
DERIVATION_IMPLICIT, 0);
230
if (!save_result.vdec) // Null value
231
res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin,
232
DERIVATION_IMPLICIT, 0);
234
res= update_hash((void*) save_result.vdec,
235
sizeof(type::Decimal), DECIMAL_RESULT,
236
&my_charset_bin, DERIVATION_IMPLICIT, 0);
241
// This case should never be chosen
249
double Item_func_set_user_var::val_real()
253
update(); // Store expression
254
return entry->val_real(&null_value);
257
int64_t Item_func_set_user_var::val_int()
261
update(); // Store expression
262
return entry->val_int(&null_value);
265
String *Item_func_set_user_var::val_str(String *str)
269
update(); // Store expression
270
return entry->val_str(&null_value, str, decimals);
274
type::Decimal *Item_func_set_user_var::val_decimal(type::Decimal *val)
278
update(); // Store expression
279
return entry->val_decimal(&null_value, val);
282
double Item_func_set_user_var::val_result()
286
update(); // Store expression
287
return entry->val_real(&null_value);
290
int64_t Item_func_set_user_var::val_int_result()
294
update(); // Store expression
295
return entry->val_int(&null_value);
298
String *Item_func_set_user_var::str_result(String *str)
302
update(); // Store expression
303
return entry->val_str(&null_value, str, decimals);
307
type::Decimal *Item_func_set_user_var::val_decimal_result(type::Decimal *val)
311
update(); // Store expression
312
return entry->val_decimal(&null_value, val);
315
void Item_func_set_user_var::print(String *str, enum_query_type query_type)
317
str->append(STRING_WITH_LEN("(@"));
318
str->append(name.str, name.length);
319
str->append(STRING_WITH_LEN(":="));
320
args[0]->print(str, query_type);
324
bool Item_func_set_user_var::send(plugin::Client *client, String *str_arg)
330
return client->store(result_field);
332
return Item::send(client, str_arg);
335
void Item_func_set_user_var::make_field(SendField *tmp_field)
339
result_field->make_field(tmp_field);
340
assert(tmp_field->table_name != 0);
342
tmp_field->col_name=Item::name; // Use user supplied name
346
Item::make_field(tmp_field);
351
Save the value of a user variable into a field
355
field target field to save the value to
356
no_conversion flag indicating whether conversions are allowed
359
Save the function value into a field and update the user variable
360
accordingly. If a result field is defined and the target field doesn't
361
coincide with it then the value from the result field will be used as
362
the new value of the user variable.
364
The reason to have this method rather than simply using the result
365
field in the val_xxx() methods is that the value from the result field
366
not always can be used when the result field is defined.
367
Let's consider the following cases:
368
1) when filling a tmp table the result field is defined but the value of it
369
is undefined because it has to be produced yet. Thus we can't use it.
370
2) on execution of an INSERT ... SELECT statement the save_in_field()
371
function will be called to fill the data in the new record. If the SELECT
372
part uses a tmp table then the result field is defined and should be
373
used in order to get the correct result.
375
The difference between the SET_USER_VAR function and regular functions
376
like CONCAT is that the Item_func objects for the regular functions are
377
replaced by Item_field objects after the values of these functions have
378
been stored in a tmp table. Yet an object of the Item_field class cannot
379
be used to update a user variable.
380
Due to this we have to handle the result field in a special way here and
381
in the Item_func_set_user_var::send() function.
388
int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
389
bool can_use_result_field)
391
bool use_result_field= (!can_use_result_field ? 0 :
392
(result_field && result_field != field));
395
/* Update the value of the user variable */
396
check(use_result_field);
399
if (result_type() == STRING_RESULT ||
400
(result_type() == REAL_RESULT && field->result_type() == STRING_RESULT))
403
const CHARSET_INFO * const cs= collation.collation;
404
char buff[MAX_FIELD_WIDTH]; // Alloc buffer for small columns
405
str_value.set_quick(buff, sizeof(buff), cs);
406
result= entry->val_str(&null_value, &str_value, decimals);
410
str_value.set_quick(0, 0, cs);
411
return set_field_to_null_with_conversions(field, no_conversions);
414
/* NOTE: If null_value == false, "result" must be not NULL. */
416
field->set_notnull();
417
error=field->store(result->ptr(),result->length(),cs);
418
str_value.set_quick(0, 0, cs);
420
else if (result_type() == REAL_RESULT)
422
double nr= entry->val_real(&null_value);
424
return set_field_to_null(field);
425
field->set_notnull();
426
error=field->store(nr);
428
else if (result_type() == DECIMAL_RESULT)
430
type::Decimal decimal_value;
431
type::Decimal *val= entry->val_decimal(&null_value, &decimal_value);
433
return set_field_to_null(field);
434
field->set_notnull();
435
error=field->store_decimal(val);
439
int64_t nr= entry->val_int(&null_value);
441
return set_field_to_null_with_conversions(field, no_conversions);
442
field->set_notnull();
443
error=field->store(nr, unsigned_flag);
449
} /* namespace drizzled */