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/field/num.h>
24
#include <drizzled/session.h>
25
#include <drizzled/plugin/client.h>
27
using namespace drizzled;
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= session->getVariable(name, true)))
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
result_field->table->setReadSet(result_field->field_index);
100
Item_func_set_user_var::update_hash(void *ptr, uint32_t length,
101
Item_result res_type,
102
const CHARSET_INFO * const cs, Derivation dv,
106
If we set a variable explicitely to NULL then keep the old
107
result type of the variable
109
if ((null_value= args[0]->null_value) && null_item)
110
res_type= entry->type; // Don't change type of item
111
if (entry->update_hash((null_value= args[0]->null_value),
112
ptr, length, res_type, cs, dv, unsigned_arg))
121
This functions is invoked on SET \@variable or
122
\@variable:= expression.
124
Evaluate (and check expression), store results.
127
For now it always return OK. All problem with value evaluating
128
will be caught by session->is_error() check in sql_set_variables().
135
Item_func_set_user_var::check(bool use_result_field)
137
if (use_result_field && !result_field)
138
use_result_field= false;
140
switch (cached_result_type) {
143
save_result.vreal= use_result_field ? result_field->val_real() :
149
save_result.vint= use_result_field ? result_field->val_int() :
151
unsigned_flag= use_result_field ? ((Field_num*)result_field)->unsigned_flag:
152
args[0]->unsigned_flag;
157
save_result.vstr= use_result_field ? result_field->val_str(&value) :
158
args[0]->val_str(&value);
163
save_result.vdec= use_result_field ?
164
result_field->val_decimal(&decimal_buff) :
165
args[0]->val_decimal(&decimal_buff);
170
// This case should never be chosen
178
This functions is invoked on
179
SET \@variable or \@variable:= expression.
182
We have to store the expression as such in the variable, independent of
183
the value method used by the user
193
Item_func_set_user_var::update()
197
switch (cached_result_type) {
200
res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
201
REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0);
206
res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
207
INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT,
213
if (!save_result.vstr) // Null value
214
res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin,
215
DERIVATION_IMPLICIT, 0);
217
res= update_hash((void*) save_result.vstr->ptr(),
218
save_result.vstr->length(), STRING_RESULT,
219
save_result.vstr->charset(),
220
DERIVATION_IMPLICIT, 0);
225
if (!save_result.vdec) // Null value
226
res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin,
227
DERIVATION_IMPLICIT, 0);
229
res= update_hash((void*) save_result.vdec,
230
sizeof(my_decimal), DECIMAL_RESULT,
231
&my_charset_bin, DERIVATION_IMPLICIT, 0);
236
// This case should never be chosen
243
double Item_func_set_user_var::val_real()
247
update(); // Store expression
248
return entry->val_real(&null_value);
251
int64_t Item_func_set_user_var::val_int()
255
update(); // Store expression
256
return entry->val_int(&null_value);
259
String *Item_func_set_user_var::val_str(String *str)
263
update(); // Store expression
264
return entry->val_str(&null_value, str, decimals);
268
my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val)
272
update(); // Store expression
273
return entry->val_decimal(&null_value, val);
276
double Item_func_set_user_var::val_result()
280
update(); // Store expression
281
return entry->val_real(&null_value);
284
int64_t Item_func_set_user_var::val_int_result()
288
update(); // Store expression
289
return entry->val_int(&null_value);
292
String *Item_func_set_user_var::str_result(String *str)
296
update(); // Store expression
297
return entry->val_str(&null_value, str, decimals);
301
my_decimal *Item_func_set_user_var::val_decimal_result(my_decimal *val)
305
update(); // Store expression
306
return entry->val_decimal(&null_value, val);
309
void Item_func_set_user_var::print(String *str, enum_query_type query_type)
311
str->append(STRING_WITH_LEN("(@"));
312
str->append(name.str, name.length);
313
str->append(STRING_WITH_LEN(":="));
314
args[0]->print(str, query_type);
319
void Item_func_set_user_var::print_as_stmt(String *str,
320
enum_query_type query_type)
322
str->append(STRING_WITH_LEN("set @"));
323
str->append(name.str, name.length);
324
str->append(STRING_WITH_LEN(":="));
325
args[0]->print(str, query_type);
329
bool Item_func_set_user_var::send(plugin::Client *client, String *str_arg)
335
return client->store(result_field);
337
return Item::send(client, str_arg);
340
void Item_func_set_user_var::make_field(SendField *tmp_field)
344
result_field->make_field(tmp_field);
345
assert(tmp_field->table_name != 0);
347
tmp_field->col_name=Item::name; // Use user supplied name
350
Item::make_field(tmp_field);
354
Save the value of a user variable into a field
358
field target field to save the value to
359
no_conversion flag indicating whether conversions are allowed
362
Save the function value into a field and update the user variable
363
accordingly. If a result field is defined and the target field doesn't
364
coincide with it then the value from the result field will be used as
365
the new value of the user variable.
367
The reason to have this method rather than simply using the result
368
field in the val_xxx() methods is that the value from the result field
369
not always can be used when the result field is defined.
370
Let's consider the following cases:
371
1) when filling a tmp table the result field is defined but the value of it
372
is undefined because it has to be produced yet. Thus we can't use it.
373
2) on execution of an INSERT ... SELECT statement the save_in_field()
374
function will be called to fill the data in the new record. If the SELECT
375
part uses a tmp table then the result field is defined and should be
376
used in order to get the correct result.
378
The difference between the SET_USER_VAR function and regular functions
379
like CONCAT is that the Item_func objects for the regular functions are
380
replaced by Item_field objects after the values of these functions have
381
been stored in a tmp table. Yet an object of the Item_field class cannot
382
be used to update a user variable.
383
Due to this we have to handle the result field in a special way here and
384
in the Item_func_set_user_var::send() function.
391
int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
392
bool can_use_result_field)
394
bool use_result_field= (!can_use_result_field ? 0 :
395
(result_field && result_field != field));
398
/* Update the value of the user variable */
399
check(use_result_field);
402
if (result_type() == STRING_RESULT ||
403
(result_type() == REAL_RESULT && field->result_type() == STRING_RESULT))
406
const CHARSET_INFO * const cs= collation.collation;
407
char buff[MAX_FIELD_WIDTH]; // Alloc buffer for small columns
408
str_value.set_quick(buff, sizeof(buff), cs);
409
result= entry->val_str(&null_value, &str_value, decimals);
413
str_value.set_quick(0, 0, cs);
414
return set_field_to_null_with_conversions(field, no_conversions);
417
/* NOTE: If null_value == false, "result" must be not NULL. */
419
field->set_notnull();
420
error=field->store(result->ptr(),result->length(),cs);
421
str_value.set_quick(0, 0, cs);
423
else if (result_type() == REAL_RESULT)
425
double nr= entry->val_real(&null_value);
427
return set_field_to_null(field);
428
field->set_notnull();
429
error=field->store(nr);
431
else if (result_type() == DECIMAL_RESULT)
433
my_decimal decimal_value;
434
my_decimal *val= entry->val_decimal(&null_value, &decimal_value);
436
return set_field_to_null(field);
437
field->set_notnull();
438
error=field->store_decimal(val);
442
int64_t nr= entry->val_int(&null_value);
444
return set_field_to_null_with_conversions(field, no_conversions);
445
field->set_notnull();
446
error=field->store(nr, unsigned_flag);