492.3.2
by Lee
code clean up to moving functions into drizzled/functions directory - Item_num_op and Item_numhybrid |
1 |
/** Copyright (C) 2000-2003 MySQL AB
|
1
by brian
clean slate |
2 |
|
3 |
This program is free software; you can redistribute it and/or modify
|
|
4 |
it under the terms of the GNU General Public License as published by
|
|
5 |
the Free Software Foundation; version 2 of the License.
|
|
6 |
||
7 |
This program is distributed in the hope that it will be useful,
|
|
8 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10 |
GNU General Public License for more details.
|
|
11 |
||
12 |
You should have received a copy of the GNU General Public License
|
|
13 |
along with this program; if not, write to the Free Software
|
|
14 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
15 |
||
16 |
||
17 |
/**
|
|
18 |
@file
|
|
19 |
||
20 |
@brief
|
|
21 |
This file defines all numerical functions
|
|
22 |
*/
|
|
23 |
||
243.1.17
by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.) |
24 |
#include <drizzled/server_includes.h> |
212.5.28
by Monty Taylor
Moved my_bit and my_list |
25 |
#include <mysys/my_bit.h> |
520.6.7
by Monty Taylor
Moved a bunch of crap out of common_includes. |
26 |
#include <drizzled/slave.h> |
549
by Monty Taylor
Took gettext.h out of header files. |
27 |
#include <drizzled/error.h> |
1
by brian
clean slate |
28 |
|
29 |
bool check_reserved_words(LEX_STRING *name) |
|
30 |
{
|
|
31 |
if (!my_strcasecmp(system_charset_info, name->str, "GLOBAL") || |
|
32 |
!my_strcasecmp(system_charset_info, name->str, "LOCAL") || |
|
33 |
!my_strcasecmp(system_charset_info, name->str, "SESSION")) |
|
56
by brian
Next pass of true/false update. |
34 |
return true; |
35 |
return false; |
|
1
by brian
clean slate |
36 |
}
|
37 |
||
38 |
||
39 |
/**
|
|
40 |
@return
|
|
56
by brian
Next pass of true/false update. |
41 |
true if item is a constant
|
1
by brian
clean slate |
42 |
*/
|
43 |
||
44 |
bool
|
|
45 |
eval_const_cond(COND *cond) |
|
46 |
{
|
|
56
by brian
Next pass of true/false update. |
47 |
return ((Item_func*) cond)->val_int() ? true : false; |
1
by brian
clean slate |
48 |
}
|
49 |
||
50 |
||
51 |
void Item_func::fix_num_length_and_dec() |
|
52 |
{
|
|
482
by Brian Aker
Remove uint. |
53 |
uint32_t fl_length= 0; |
1
by brian
clean slate |
54 |
decimals=0; |
482
by Brian Aker
Remove uint. |
55 |
for (uint32_t i=0 ; i < arg_count ; i++) |
1
by brian
clean slate |
56 |
{
|
57 |
set_if_bigger(decimals,args[i]->decimals); |
|
58 |
set_if_bigger(fl_length, args[i]->max_length); |
|
59 |
}
|
|
60 |
max_length=float_length(decimals); |
|
61 |
if (fl_length > max_length) |
|
62 |
{
|
|
63 |
decimals= NOT_FIXED_DEC; |
|
64 |
max_length= float_length(NOT_FIXED_DEC); |
|
65 |
}
|
|
66 |
}
|
|
67 |
||
68 |
/**
|
|
69 |
Set max_length/decimals of function if function is fixed point and
|
|
70 |
result length/precision depends on argument ones.
|
|
71 |
*/
|
|
72 |
||
73 |
void Item_func::count_decimal_length() |
|
74 |
{
|
|
75 |
int max_int_part= 0; |
|
76 |
decimals= 0; |
|
77 |
unsigned_flag= 1; |
|
482
by Brian Aker
Remove uint. |
78 |
for (uint32_t i=0 ; i < arg_count ; i++) |
1
by brian
clean slate |
79 |
{
|
80 |
set_if_bigger(decimals, args[i]->decimals); |
|
81 |
set_if_bigger(max_int_part, args[i]->decimal_int_part()); |
|
82 |
set_if_smaller(unsigned_flag, args[i]->unsigned_flag); |
|
83 |
}
|
|
398.1.4
by Monty Taylor
Renamed max/min. |
84 |
int precision= cmin(max_int_part + decimals, DECIMAL_MAX_PRECISION); |
1
by brian
clean slate |
85 |
max_length= my_decimal_precision_to_length(precision, decimals, |
86 |
unsigned_flag); |
|
87 |
}
|
|
88 |
||
89 |
||
90 |
/**
|
|
91 |
Set max_length of if it is maximum length of its arguments.
|
|
92 |
*/
|
|
93 |
||
94 |
void Item_func::count_only_length() |
|
95 |
{
|
|
96 |
max_length= 0; |
|
97 |
unsigned_flag= 0; |
|
482
by Brian Aker
Remove uint. |
98 |
for (uint32_t i=0 ; i < arg_count ; i++) |
1
by brian
clean slate |
99 |
{
|
100 |
set_if_bigger(max_length, args[i]->max_length); |
|
101 |
set_if_bigger(unsigned_flag, args[i]->unsigned_flag); |
|
102 |
}
|
|
103 |
}
|
|
104 |
||
105 |
||
106 |
/**
|
|
107 |
Set max_length/decimals of function if function is floating point and
|
|
108 |
result length/precision depends on argument ones.
|
|
109 |
*/
|
|
110 |
||
111 |
void Item_func::count_real_length() |
|
112 |
{
|
|
205
by Brian Aker
uint32 -> uin32_t |
113 |
uint32_t length= 0; |
1
by brian
clean slate |
114 |
decimals= 0; |
115 |
max_length= 0; |
|
482
by Brian Aker
Remove uint. |
116 |
for (uint32_t i=0 ; i < arg_count ; i++) |
1
by brian
clean slate |
117 |
{
|
118 |
if (decimals != NOT_FIXED_DEC) |
|
119 |
{
|
|
120 |
set_if_bigger(decimals, args[i]->decimals); |
|
121 |
set_if_bigger(length, (args[i]->max_length - args[i]->decimals)); |
|
122 |
}
|
|
123 |
set_if_bigger(max_length, args[i]->max_length); |
|
124 |
}
|
|
125 |
if (decimals != NOT_FIXED_DEC) |
|
126 |
{
|
|
127 |
max_length= length; |
|
128 |
length+= decimals; |
|
129 |
if (length < max_length) // If previous operation gave overflow |
|
163
by Brian Aker
Merge Monty's code. |
130 |
max_length= UINT32_MAX; |
1
by brian
clean slate |
131 |
else
|
132 |
max_length= length; |
|
133 |
}
|
|
134 |
}
|
|
135 |
||
136 |
||
137 |
||
138 |
void Item_func::signal_divide_by_null() |
|
139 |
{
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
140 |
Session *session= current_session; |
141 |
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, ER_DIVISION_BY_ZERO, ER(ER_DIVISION_BY_ZERO)); |
|
1
by brian
clean slate |
142 |
null_value= 1; |
143 |
}
|
|
144 |
||
145 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
146 |
Item *Item_func::get_tmp_table_item(Session *session) |
1
by brian
clean slate |
147 |
{
|
148 |
if (!with_sum_func && !const_item() && functype() != SUSERVAR_FUNC) |
|
149 |
return new Item_field(result_field); |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
150 |
return copy_or_same(session); |
1
by brian
clean slate |
151 |
}
|
152 |
||
153 |
/*
|
|
154 |
When a user variable is updated (in a SET command or a query like
|
|
155 |
SELECT @a:= ).
|
|
156 |
*/
|
|
157 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
158 |
bool Item_func_set_user_var::fix_fields(Session *session, Item **ref) |
1
by brian
clean slate |
159 |
{
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
160 |
assert(fixed == 0); |
1
by brian
clean slate |
161 |
/* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
162 |
if (Item_func::fix_fields(session, ref) || |
163 |
!(entry= get_variable(&session->user_vars, name, 1))) |
|
56
by brian
Next pass of true/false update. |
164 |
return true; |
1
by brian
clean slate |
165 |
/*
|
166 |
Remember the last query which updated it, this way a query can later know
|
|
167 |
if this variable is a constant item in the query (it is if update_query_id
|
|
168 |
is different from query_id).
|
|
169 |
*/
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
170 |
entry->update_query_id= session->query_id; |
1
by brian
clean slate |
171 |
/*
|
172 |
As it is wrong and confusing to associate any
|
|
173 |
character set with NULL, @a should be latin2
|
|
174 |
after this query sequence:
|
|
175 |
||
176 |
SET @a=_latin2'string';
|
|
177 |
SET @a=NULL;
|
|
178 |
||
179 |
I.e. the second query should not change the charset
|
|
180 |
to the current default value, but should keep the
|
|
181 |
original value assigned during the first query.
|
|
182 |
In order to do it, we don't copy charset
|
|
183 |
from the argument if the argument is NULL
|
|
184 |
and the variable has previously been initialized.
|
|
185 |
*/
|
|
186 |
null_item= (args[0]->type() == NULL_ITEM); |
|
187 |
if (!entry->collation.collation || !null_item) |
|
188 |
entry->collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT); |
|
189 |
collation.set(entry->collation.collation, DERIVATION_IMPLICIT); |
|
190 |
cached_result_type= args[0]->result_type(); |
|
56
by brian
Next pass of true/false update. |
191 |
return false; |
1
by brian
clean slate |
192 |
}
|
193 |
||
194 |
||
195 |
void
|
|
196 |
Item_func_set_user_var::fix_length_and_dec() |
|
197 |
{
|
|
198 |
maybe_null=args[0]->maybe_null; |
|
199 |
max_length=args[0]->max_length; |
|
200 |
decimals=args[0]->decimals; |
|
201 |
collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT); |
|
202 |
}
|
|
203 |
||
204 |
||
205 |
/*
|
|
206 |
Mark field in read_map
|
|
207 |
||
208 |
NOTES
|
|
209 |
This is used by filesort to register used fields in a a temporary
|
|
210 |
column read set or to register used fields in a view
|
|
211 |
*/
|
|
212 |
||
481
by Brian Aker
Remove all of uchar. |
213 |
bool Item_func_set_user_var::register_field_in_read_map(unsigned char *arg) |
1
by brian
clean slate |
214 |
{
|
215 |
if (result_field) |
|
216 |
{
|
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
217 |
Table *table= (Table *) arg; |
1
by brian
clean slate |
218 |
if (result_field->table == table || !table) |
219 |
bitmap_set_bit(result_field->table->read_set, result_field->field_index); |
|
383.7.1
by Andrey Zhakov
Initial submit of code and tests |
220 |
if (result_field->vcol_info && result_field->vcol_info->expr_item) |
221 |
return result_field->vcol_info-> |
|
222 |
expr_item->walk(&Item::register_field_in_read_map, 1, arg); |
|
223 |
}
|
|
224 |
return 0; |
|
225 |
}
|
|
226 |
||
227 |
||
228 |
/*
|
|
229 |
Mark field in bitmap supplied as *arg
|
|
230 |
||
231 |
*/
|
|
232 |
||
481.3.1
by Monty Taylor
Merged vcol stuff. |
233 |
bool Item_func_set_user_var::register_field_in_bitmap(unsigned char *arg) |
383.7.1
by Andrey Zhakov
Initial submit of code and tests |
234 |
{
|
235 |
MY_BITMAP *bitmap = (MY_BITMAP *) arg; |
|
236 |
assert(bitmap); |
|
237 |
if (result_field) |
|
238 |
{
|
|
239 |
bitmap_set_bit(bitmap, result_field->field_index); |
|
1
by brian
clean slate |
240 |
}
|
241 |
return 0; |
|
242 |
}
|
|
243 |
||
244 |
||
245 |
/**
|
|
246 |
Set value to user variable.
|
|
247 |
||
248 |
@param entry pointer to structure representing variable
|
|
249 |
@param set_null should we set NULL value ?
|
|
250 |
@param ptr pointer to buffer with new value
|
|
251 |
@param length length of new value
|
|
252 |
@param type type of new value
|
|
253 |
@param cs charset info for new value
|
|
254 |
@param dv derivation for new value
|
|
255 |
@param unsigned_arg indiates if a value of type INT_RESULT is unsigned
|
|
256 |
||
257 |
@note Sets error and fatal error if allocation fails.
|
|
258 |
||
259 |
@retval
|
|
260 |
false success
|
|
261 |
@retval
|
|
262 |
true failure
|
|
263 |
*/
|
|
264 |
||
492.3.32
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
265 |
#define extra_size sizeof(double)
|
266 |
||
1
by brian
clean slate |
267 |
static bool |
482
by Brian Aker
Remove uint. |
268 |
update_hash(user_var_entry *entry, bool set_null, void *ptr, uint32_t length, |
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
269 |
Item_result type, const CHARSET_INFO * const cs, Derivation dv, |
1
by brian
clean slate |
270 |
bool unsigned_arg) |
271 |
{
|
|
272 |
if (set_null) |
|
273 |
{
|
|
274 |
char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry)); |
|
275 |
if (entry->value && entry->value != pos) |
|
477
by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that. |
276 |
free(entry->value); |
1
by brian
clean slate |
277 |
entry->value= 0; |
278 |
entry->length= 0; |
|
279 |
}
|
|
280 |
else
|
|
281 |
{
|
|
282 |
if (type == STRING_RESULT) |
|
283 |
length++; // Store strings with end \0 |
|
284 |
if (length <= extra_size) |
|
285 |
{
|
|
286 |
/* Save value in value struct */
|
|
287 |
char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry)); |
|
288 |
if (entry->value != pos) |
|
289 |
{
|
|
290 |
if (entry->value) |
|
477
by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that. |
291 |
free(entry->value); |
1
by brian
clean slate |
292 |
entry->value=pos; |
293 |
}
|
|
294 |
}
|
|
295 |
else
|
|
296 |
{
|
|
297 |
/* Allocate variable */
|
|
298 |
if (entry->length != length) |
|
299 |
{
|
|
300 |
char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry)); |
|
301 |
if (entry->value == pos) |
|
302 |
entry->value=0; |
|
303 |
entry->value= (char*) my_realloc(entry->value, length, |
|
304 |
MYF(MY_ALLOW_ZERO_PTR | MY_WME | |
|
305 |
ME_FATALERROR)); |
|
306 |
if (!entry->value) |
|
307 |
return 1; |
|
308 |
}
|
|
309 |
}
|
|
310 |
if (type == STRING_RESULT) |
|
311 |
{
|
|
312 |
length--; // Fix length change above |
|
313 |
entry->value[length]= 0; // Store end \0 |
|
314 |
}
|
|
315 |
memcpy(entry->value,ptr,length); |
|
316 |
if (type == DECIMAL_RESULT) |
|
317 |
((my_decimal*)entry->value)->fix_buffer_pointer(); |
|
318 |
entry->length= length; |
|
319 |
entry->collation.set(cs, dv); |
|
320 |
entry->unsigned_flag= unsigned_arg; |
|
321 |
}
|
|
322 |
entry->type=type; |
|
323 |
return 0; |
|
324 |
}
|
|
325 |
||
326 |
||
327 |
bool
|
|
482
by Brian Aker
Remove uint. |
328 |
Item_func_set_user_var::update_hash(void *ptr, uint32_t length, |
1
by brian
clean slate |
329 |
Item_result res_type, |
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
330 |
const CHARSET_INFO * const cs, Derivation dv, |
1
by brian
clean slate |
331 |
bool unsigned_arg) |
332 |
{
|
|
333 |
/*
|
|
334 |
If we set a variable explicitely to NULL then keep the old
|
|
335 |
result type of the variable
|
|
336 |
*/
|
|
337 |
if ((null_value= args[0]->null_value) && null_item) |
|
338 |
res_type= entry->type; // Don't change type of item |
|
339 |
if (::update_hash(entry, (null_value= args[0]->null_value), |
|
340 |
ptr, length, res_type, cs, dv, unsigned_arg)) |
|
341 |
{
|
|
342 |
null_value= 1; |
|
343 |
return 1; |
|
344 |
}
|
|
345 |
return 0; |
|
346 |
}
|
|
347 |
||
348 |
||
349 |
/** Get the value of a variable as a double. */
|
|
350 |
||
275
by Brian Aker
Full removal of my_bool from central server. |
351 |
double user_var_entry::val_real(bool *null_value) |
1
by brian
clean slate |
352 |
{
|
353 |
if ((*null_value= (value == 0))) |
|
354 |
return 0.0; |
|
355 |
||
356 |
switch (type) { |
|
357 |
case REAL_RESULT: |
|
358 |
return *(double*) value; |
|
359 |
case INT_RESULT: |
|
152
by Brian Aker
longlong replacement |
360 |
return (double) *(int64_t*) value; |
1
by brian
clean slate |
361 |
case DECIMAL_RESULT: |
362 |
{
|
|
363 |
double result; |
|
364 |
my_decimal2double(E_DEC_FATAL_ERROR, (my_decimal *)value, &result); |
|
365 |
return result; |
|
366 |
}
|
|
367 |
case STRING_RESULT: |
|
368 |
return my_atof(value); // This is null terminated |
|
369 |
case ROW_RESULT: |
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
370 |
assert(1); // Impossible |
1
by brian
clean slate |
371 |
break; |
372 |
}
|
|
373 |
return 0.0; // Impossible |
|
374 |
}
|
|
375 |
||
376 |
||
377 |
/** Get the value of a variable as an integer. */
|
|
378 |
||
275
by Brian Aker
Full removal of my_bool from central server. |
379 |
int64_t user_var_entry::val_int(bool *null_value) const |
1
by brian
clean slate |
380 |
{
|
381 |
if ((*null_value= (value == 0))) |
|
398.1.8
by Monty Taylor
Enabled -Wlong-long. |
382 |
return 0L; |
1
by brian
clean slate |
383 |
|
384 |
switch (type) { |
|
385 |
case REAL_RESULT: |
|
152
by Brian Aker
longlong replacement |
386 |
return (int64_t) *(double*) value; |
1
by brian
clean slate |
387 |
case INT_RESULT: |
152
by Brian Aker
longlong replacement |
388 |
return *(int64_t*) value; |
1
by brian
clean slate |
389 |
case DECIMAL_RESULT: |
390 |
{
|
|
152
by Brian Aker
longlong replacement |
391 |
int64_t result; |
1
by brian
clean slate |
392 |
my_decimal2int(E_DEC_FATAL_ERROR, (my_decimal *)value, 0, &result); |
393 |
return result; |
|
394 |
}
|
|
395 |
case STRING_RESULT: |
|
396 |
{
|
|
397 |
int error; |
|
398 |
return my_strtoll10(value, (char**) 0, &error);// String is null terminated |
|
399 |
}
|
|
400 |
case ROW_RESULT: |
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
401 |
assert(1); // Impossible |
1
by brian
clean slate |
402 |
break; |
403 |
}
|
|
398.1.8
by Monty Taylor
Enabled -Wlong-long. |
404 |
return 0L; // Impossible |
1
by brian
clean slate |
405 |
}
|
406 |
||
407 |
||
408 |
/** Get the value of a variable as a string. */
|
|
409 |
||
275
by Brian Aker
Full removal of my_bool from central server. |
410 |
String *user_var_entry::val_str(bool *null_value, String *str, |
482
by Brian Aker
Remove uint. |
411 |
uint32_t decimals) |
1
by brian
clean slate |
412 |
{
|
413 |
if ((*null_value= (value == 0))) |
|
414 |
return (String*) 0; |
|
415 |
||
416 |
switch (type) { |
|
417 |
case REAL_RESULT: |
|
418 |
str->set_real(*(double*) value, decimals, &my_charset_bin); |
|
419 |
break; |
|
420 |
case INT_RESULT: |
|
421 |
if (!unsigned_flag) |
|
152
by Brian Aker
longlong replacement |
422 |
str->set(*(int64_t*) value, &my_charset_bin); |
1
by brian
clean slate |
423 |
else
|
151
by Brian Aker
Ulonglong to uint64_t |
424 |
str->set(*(uint64_t*) value, &my_charset_bin); |
1
by brian
clean slate |
425 |
break; |
426 |
case DECIMAL_RESULT: |
|
427 |
my_decimal2string(E_DEC_FATAL_ERROR, (my_decimal *)value, 0, 0, 0, str); |
|
428 |
break; |
|
429 |
case STRING_RESULT: |
|
430 |
if (str->copy(value, length, collation.collation)) |
|
431 |
str= 0; // EOM error |
|
432 |
case ROW_RESULT: |
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
433 |
assert(1); // Impossible |
1
by brian
clean slate |
434 |
break; |
435 |
}
|
|
436 |
return(str); |
|
437 |
}
|
|
438 |
||
439 |
/** Get the value of a variable as a decimal. */
|
|
440 |
||
275
by Brian Aker
Full removal of my_bool from central server. |
441 |
my_decimal *user_var_entry::val_decimal(bool *null_value, my_decimal *val) |
1
by brian
clean slate |
442 |
{
|
443 |
if ((*null_value= (value == 0))) |
|
444 |
return 0; |
|
445 |
||
446 |
switch (type) { |
|
447 |
case REAL_RESULT: |
|
448 |
double2my_decimal(E_DEC_FATAL_ERROR, *(double*) value, val); |
|
449 |
break; |
|
450 |
case INT_RESULT: |
|
152
by Brian Aker
longlong replacement |
451 |
int2my_decimal(E_DEC_FATAL_ERROR, *(int64_t*) value, 0, val); |
1
by brian
clean slate |
452 |
break; |
453 |
case DECIMAL_RESULT: |
|
454 |
val= (my_decimal *)value; |
|
455 |
break; |
|
456 |
case STRING_RESULT: |
|
457 |
str2my_decimal(E_DEC_FATAL_ERROR, value, length, collation.collation, val); |
|
458 |
break; |
|
459 |
case ROW_RESULT: |
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
460 |
assert(1); // Impossible |
1
by brian
clean slate |
461 |
break; |
462 |
}
|
|
463 |
return(val); |
|
464 |
}
|
|
465 |
||
466 |
/**
|
|
467 |
This functions is invoked on SET \@variable or
|
|
468 |
\@variable:= expression.
|
|
469 |
||
470 |
Evaluate (and check expression), store results.
|
|
471 |
||
472 |
@note
|
|
473 |
For now it always return OK. All problem with value evaluating
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
474 |
will be caught by session->is_error() check in sql_set_variables().
|
1
by brian
clean slate |
475 |
|
476 |
@retval
|
|
56
by brian
Next pass of true/false update. |
477 |
false OK.
|
1
by brian
clean slate |
478 |
*/
|
479 |
||
480 |
bool
|
|
481 |
Item_func_set_user_var::check(bool use_result_field) |
|
482 |
{
|
|
483 |
if (use_result_field && !result_field) |
|
56
by brian
Next pass of true/false update. |
484 |
use_result_field= false; |
1
by brian
clean slate |
485 |
|
486 |
switch (cached_result_type) { |
|
487 |
case REAL_RESULT: |
|
488 |
{
|
|
489 |
save_result.vreal= use_result_field ? result_field->val_real() : |
|
490 |
args[0]->val_real(); |
|
491 |
break; |
|
492 |
}
|
|
493 |
case INT_RESULT: |
|
494 |
{
|
|
495 |
save_result.vint= use_result_field ? result_field->val_int() : |
|
496 |
args[0]->val_int(); |
|
497 |
unsigned_flag= use_result_field ? ((Field_num*)result_field)->unsigned_flag: |
|
498 |
args[0]->unsigned_flag; |
|
499 |
break; |
|
500 |
}
|
|
501 |
case STRING_RESULT: |
|
502 |
{
|
|
503 |
save_result.vstr= use_result_field ? result_field->val_str(&value) : |
|
504 |
args[0]->val_str(&value); |
|
505 |
break; |
|
506 |
}
|
|
507 |
case DECIMAL_RESULT: |
|
508 |
{
|
|
509 |
save_result.vdec= use_result_field ? |
|
510 |
result_field->val_decimal(&decimal_buff) : |
|
511 |
args[0]->val_decimal(&decimal_buff); |
|
512 |
break; |
|
513 |
}
|
|
514 |
case ROW_RESULT: |
|
515 |
default: |
|
516 |
// This case should never be chosen
|
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
517 |
assert(0); |
1
by brian
clean slate |
518 |
break; |
519 |
}
|
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
520 |
return(false); |
1
by brian
clean slate |
521 |
}
|
522 |
||
523 |
||
524 |
/**
|
|
525 |
This functions is invoked on
|
|
526 |
SET \@variable or \@variable:= expression.
|
|
527 |
||
528 |
@note
|
|
529 |
We have to store the expression as such in the variable, independent of
|
|
530 |
the value method used by the user
|
|
531 |
||
532 |
@retval
|
|
533 |
0 OK
|
|
534 |
@retval
|
|
535 |
1 EOM Error
|
|
536 |
||
537 |
*/
|
|
538 |
||
539 |
bool
|
|
540 |
Item_func_set_user_var::update() |
|
541 |
{
|
|
542 |
bool res= false; |
|
543 |
||
544 |
switch (cached_result_type) { |
|
545 |
case REAL_RESULT: |
|
546 |
{
|
|
547 |
res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal), |
|
548 |
REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0); |
|
549 |
break; |
|
550 |
}
|
|
551 |
case INT_RESULT: |
|
552 |
{
|
|
553 |
res= update_hash((void*) &save_result.vint, sizeof(save_result.vint), |
|
554 |
INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, |
|
555 |
unsigned_flag); |
|
556 |
break; |
|
557 |
}
|
|
558 |
case STRING_RESULT: |
|
559 |
{
|
|
560 |
if (!save_result.vstr) // Null value |
|
561 |
res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin, |
|
562 |
DERIVATION_IMPLICIT, 0); |
|
563 |
else
|
|
564 |
res= update_hash((void*) save_result.vstr->ptr(), |
|
565 |
save_result.vstr->length(), STRING_RESULT, |
|
566 |
save_result.vstr->charset(), |
|
567 |
DERIVATION_IMPLICIT, 0); |
|
568 |
break; |
|
569 |
}
|
|
570 |
case DECIMAL_RESULT: |
|
571 |
{
|
|
572 |
if (!save_result.vdec) // Null value |
|
573 |
res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin, |
|
574 |
DERIVATION_IMPLICIT, 0); |
|
575 |
else
|
|
576 |
res= update_hash((void*) save_result.vdec, |
|
577 |
sizeof(my_decimal), DECIMAL_RESULT, |
|
578 |
&my_charset_bin, DERIVATION_IMPLICIT, 0); |
|
579 |
break; |
|
580 |
}
|
|
581 |
case ROW_RESULT: |
|
582 |
default: |
|
583 |
// This case should never be chosen
|
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
584 |
assert(0); |
1
by brian
clean slate |
585 |
break; |
586 |
}
|
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
587 |
return(res); |
1
by brian
clean slate |
588 |
}
|
589 |
||
590 |
||
591 |
double Item_func_set_user_var::val_real() |
|
592 |
{
|
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
593 |
assert(fixed == 1); |
1
by brian
clean slate |
594 |
check(0); |
595 |
update(); // Store expression |
|
596 |
return entry->val_real(&null_value); |
|
597 |
}
|
|
598 |
||
152
by Brian Aker
longlong replacement |
599 |
int64_t Item_func_set_user_var::val_int() |
1
by brian
clean slate |
600 |
{
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
601 |
assert(fixed == 1); |
1
by brian
clean slate |
602 |
check(0); |
603 |
update(); // Store expression |
|
604 |
return entry->val_int(&null_value); |
|
605 |
}
|
|
606 |
||
607 |
String *Item_func_set_user_var::val_str(String *str) |
|
608 |
{
|
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
609 |
assert(fixed == 1); |
1
by brian
clean slate |
610 |
check(0); |
611 |
update(); // Store expression |
|
612 |
return entry->val_str(&null_value, str, decimals); |
|
613 |
}
|
|
614 |
||
615 |
||
616 |
my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val) |
|
617 |
{
|
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
618 |
assert(fixed == 1); |
1
by brian
clean slate |
619 |
check(0); |
620 |
update(); // Store expression |
|
621 |
return entry->val_decimal(&null_value, val); |
|
622 |
}
|
|
623 |
||
624 |
||
625 |
double Item_func_set_user_var::val_result() |
|
626 |
{
|
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
627 |
assert(fixed == 1); |
56
by brian
Next pass of true/false update. |
628 |
check(true); |
1
by brian
clean slate |
629 |
update(); // Store expression |
630 |
return entry->val_real(&null_value); |
|
631 |
}
|
|
632 |
||
152
by Brian Aker
longlong replacement |
633 |
int64_t Item_func_set_user_var::val_int_result() |
1
by brian
clean slate |
634 |
{
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
635 |
assert(fixed == 1); |
56
by brian
Next pass of true/false update. |
636 |
check(true); |
1
by brian
clean slate |
637 |
update(); // Store expression |
638 |
return entry->val_int(&null_value); |
|
639 |
}
|
|
640 |
||
641 |
String *Item_func_set_user_var::str_result(String *str) |
|
642 |
{
|
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
643 |
assert(fixed == 1); |
56
by brian
Next pass of true/false update. |
644 |
check(true); |
1
by brian
clean slate |
645 |
update(); // Store expression |
646 |
return entry->val_str(&null_value, str, decimals); |
|
647 |
}
|
|
648 |
||
649 |
||
650 |
my_decimal *Item_func_set_user_var::val_decimal_result(my_decimal *val) |
|
651 |
{
|
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
652 |
assert(fixed == 1); |
56
by brian
Next pass of true/false update. |
653 |
check(true); |
1
by brian
clean slate |
654 |
update(); // Store expression |
655 |
return entry->val_decimal(&null_value, val); |
|
656 |
}
|
|
657 |
||
658 |
||
659 |
void Item_func_set_user_var::print(String *str, enum_query_type query_type) |
|
660 |
{
|
|
661 |
str->append(STRING_WITH_LEN("(@")); |
|
662 |
str->append(name.str, name.length); |
|
663 |
str->append(STRING_WITH_LEN(":=")); |
|
664 |
args[0]->print(str, query_type); |
|
665 |
str->append(')'); |
|
666 |
}
|
|
667 |
||
668 |
||
669 |
void Item_func_set_user_var::print_as_stmt(String *str, |
|
670 |
enum_query_type query_type) |
|
671 |
{
|
|
672 |
str->append(STRING_WITH_LEN("set @")); |
|
673 |
str->append(name.str, name.length); |
|
674 |
str->append(STRING_WITH_LEN(":=")); |
|
675 |
args[0]->print(str, query_type); |
|
676 |
str->append(')'); |
|
677 |
}
|
|
678 |
||
679 |
bool Item_func_set_user_var::send(Protocol *protocol, String *str_arg) |
|
680 |
{
|
|
681 |
if (result_field) |
|
682 |
{
|
|
683 |
check(1); |
|
684 |
update(); |
|
685 |
return protocol->store(result_field); |
|
686 |
}
|
|
687 |
return Item::send(protocol, str_arg); |
|
688 |
}
|
|
689 |
||
690 |
void Item_func_set_user_var::make_field(Send_field *tmp_field) |
|
691 |
{
|
|
692 |
if (result_field) |
|
693 |
{
|
|
694 |
result_field->make_field(tmp_field); |
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
695 |
assert(tmp_field->table_name != 0); |
1
by brian
clean slate |
696 |
if (Item::name) |
697 |
tmp_field->col_name=Item::name; // Use user supplied name |
|
698 |
}
|
|
699 |
else
|
|
700 |
Item::make_field(tmp_field); |
|
701 |
}
|
|
702 |
||
703 |
||
704 |
/*
|
|
705 |
Save the value of a user variable into a field
|
|
706 |
||
707 |
SYNOPSIS
|
|
708 |
save_in_field()
|
|
709 |
field target field to save the value to
|
|
710 |
no_conversion flag indicating whether conversions are allowed
|
|
711 |
||
712 |
DESCRIPTION
|
|
713 |
Save the function value into a field and update the user variable
|
|
714 |
accordingly. If a result field is defined and the target field doesn't
|
|
715 |
coincide with it then the value from the result field will be used as
|
|
716 |
the new value of the user variable.
|
|
717 |
||
718 |
The reason to have this method rather than simply using the result
|
|
719 |
field in the val_xxx() methods is that the value from the result field
|
|
720 |
not always can be used when the result field is defined.
|
|
721 |
Let's consider the following cases:
|
|
722 |
1) when filling a tmp table the result field is defined but the value of it
|
|
723 |
is undefined because it has to be produced yet. Thus we can't use it.
|
|
724 |
2) on execution of an INSERT ... SELECT statement the save_in_field()
|
|
725 |
function will be called to fill the data in the new record. If the SELECT
|
|
726 |
part uses a tmp table then the result field is defined and should be
|
|
727 |
used in order to get the correct result.
|
|
728 |
||
729 |
The difference between the SET_USER_VAR function and regular functions
|
|
730 |
like CONCAT is that the Item_func objects for the regular functions are
|
|
731 |
replaced by Item_field objects after the values of these functions have
|
|
732 |
been stored in a tmp table. Yet an object of the Item_field class cannot
|
|
733 |
be used to update a user variable.
|
|
734 |
Due to this we have to handle the result field in a special way here and
|
|
735 |
in the Item_func_set_user_var::send() function.
|
|
736 |
||
737 |
RETURN VALUES
|
|
56
by brian
Next pass of true/false update. |
738 |
false Ok
|
739 |
true Error
|
|
1
by brian
clean slate |
740 |
*/
|
741 |
||
742 |
int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions, |
|
743 |
bool can_use_result_field) |
|
744 |
{
|
|
745 |
bool use_result_field= (!can_use_result_field ? 0 : |
|
746 |
(result_field && result_field != field)); |
|
747 |
int error; |
|
748 |
||
749 |
/* Update the value of the user variable */
|
|
750 |
check(use_result_field); |
|
751 |
update(); |
|
752 |
||
753 |
if (result_type() == STRING_RESULT || |
|
754 |
(result_type() == REAL_RESULT && field->result_type() == STRING_RESULT)) |
|
755 |
{
|
|
756 |
String *result; |
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
757 |
const CHARSET_INFO * const cs= collation.collation; |
1
by brian
clean slate |
758 |
char buff[MAX_FIELD_WIDTH]; // Alloc buffer for small columns |
759 |
str_value.set_quick(buff, sizeof(buff), cs); |
|
760 |
result= entry->val_str(&null_value, &str_value, decimals); |
|
761 |
||
762 |
if (null_value) |
|
763 |
{
|
|
764 |
str_value.set_quick(0, 0, cs); |
|
765 |
return set_field_to_null_with_conversions(field, no_conversions); |
|
766 |
}
|
|
767 |
||
56
by brian
Next pass of true/false update. |
768 |
/* NOTE: If null_value == false, "result" must be not NULL. */
|
1
by brian
clean slate |
769 |
|
770 |
field->set_notnull(); |
|
771 |
error=field->store(result->ptr(),result->length(),cs); |
|
772 |
str_value.set_quick(0, 0, cs); |
|
773 |
}
|
|
774 |
else if (result_type() == REAL_RESULT) |
|
775 |
{
|
|
776 |
double nr= entry->val_real(&null_value); |
|
777 |
if (null_value) |
|
778 |
return set_field_to_null(field); |
|
779 |
field->set_notnull(); |
|
780 |
error=field->store(nr); |
|
781 |
}
|
|
782 |
else if (result_type() == DECIMAL_RESULT) |
|
783 |
{
|
|
784 |
my_decimal decimal_value; |
|
785 |
my_decimal *val= entry->val_decimal(&null_value, &decimal_value); |
|
786 |
if (null_value) |
|
787 |
return set_field_to_null(field); |
|
788 |
field->set_notnull(); |
|
789 |
error=field->store_decimal(val); |
|
790 |
}
|
|
791 |
else
|
|
792 |
{
|
|
152
by Brian Aker
longlong replacement |
793 |
int64_t nr= entry->val_int(&null_value); |
1
by brian
clean slate |
794 |
if (null_value) |
795 |
return set_field_to_null_with_conversions(field, no_conversions); |
|
796 |
field->set_notnull(); |
|
797 |
error=field->store(nr, unsigned_flag); |
|
798 |
}
|
|
799 |
return error; |
|
800 |
}
|
|
801 |
||
802 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
803 |
bool Item_user_var_as_out_param::fix_fields(Session *session, Item **ref) |
1
by brian
clean slate |
804 |
{
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
805 |
assert(fixed == 0); |
520.1.22
by Brian Aker
Second pass of thd cleanup |
806 |
if (Item::fix_fields(session, ref) || |
807 |
!(entry= get_variable(&session->user_vars, name, 1))) |
|
56
by brian
Next pass of true/false update. |
808 |
return true; |
1
by brian
clean slate |
809 |
entry->type= STRING_RESULT; |
810 |
/*
|
|
811 |
Let us set the same collation which is used for loading
|
|
812 |
of fields in LOAD DATA INFILE.
|
|
813 |
(Since Item_user_var_as_out_param is used only there).
|
|
814 |
*/
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
815 |
entry->collation.set(session->variables.collation_database); |
816 |
entry->update_query_id= session->query_id; |
|
56
by brian
Next pass of true/false update. |
817 |
return false; |
1
by brian
clean slate |
818 |
}
|
819 |
||
820 |
||
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
821 |
void Item_user_var_as_out_param::set_null_value(const CHARSET_INFO * const cs) |
1
by brian
clean slate |
822 |
{
|
56
by brian
Next pass of true/false update. |
823 |
::update_hash(entry, true, 0, 0, STRING_RESULT, cs, |
1
by brian
clean slate |
824 |
DERIVATION_IMPLICIT, 0 /* unsigned_arg */); |
825 |
}
|
|
826 |
||
827 |
||
482
by Brian Aker
Remove uint. |
828 |
void Item_user_var_as_out_param::set_value(const char *str, uint32_t length, |
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
829 |
const CHARSET_INFO * const cs) |
1
by brian
clean slate |
830 |
{
|
56
by brian
Next pass of true/false update. |
831 |
::update_hash(entry, false, (void*)str, length, STRING_RESULT, cs, |
1
by brian
clean slate |
832 |
DERIVATION_IMPLICIT, 0 /* unsigned_arg */); |
833 |
}
|
|
834 |
||
835 |
||
836 |
double Item_user_var_as_out_param::val_real() |
|
837 |
{
|
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
838 |
assert(0); |
1
by brian
clean slate |
839 |
return 0.0; |
840 |
}
|
|
841 |
||
842 |
||
152
by Brian Aker
longlong replacement |
843 |
int64_t Item_user_var_as_out_param::val_int() |
1
by brian
clean slate |
844 |
{
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
845 |
assert(0); |
1
by brian
clean slate |
846 |
return 0; |
847 |
}
|
|
848 |
||
849 |
||
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
850 |
String* Item_user_var_as_out_param::val_str(String *str __attribute__((unused))) |
77.1.15
by Monty Taylor
Bunch of warning cleanups. |
851 |
{
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
852 |
assert(0); |
77.1.15
by Monty Taylor
Bunch of warning cleanups. |
853 |
return 0; |
854 |
}
|
|
855 |
||
856 |
||
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
857 |
my_decimal* Item_user_var_as_out_param::val_decimal(my_decimal *decimal_buffer __attribute__((unused))) |
77.1.15
by Monty Taylor
Bunch of warning cleanups. |
858 |
{
|
51.1.20
by Jay Pipes
Removed/replaced DBUG symbols and fixed TRUE/FALSEs |
859 |
assert(0); |
77.1.15
by Monty Taylor
Bunch of warning cleanups. |
860 |
return 0; |
861 |
}
|
|
862 |
||
863 |
||
864 |
void Item_user_var_as_out_param::print(String *str, |
|
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
865 |
enum_query_type query_type __attribute__((unused))) |
1
by brian
clean slate |
866 |
{
|
867 |
str->append('@'); |
|
868 |
str->append(name.str,name.length); |
|
869 |
}
|
|
870 |
||
871 |
/***************************************************************************
|
|
872 |
System variables
|
|
873 |
****************************************************************************/
|
|
874 |
||
875 |
/**
|
|
876 |
Return value of an system variable base[.name] as a constant item.
|
|
877 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
878 |
@param session Thread handler
|
1
by brian
clean slate |
879 |
@param var_type global / session
|
880 |
@param name Name of base or system variable
|
|
881 |
@param component Component.
|
|
882 |
||
883 |
@note
|
|
884 |
If component.str = 0 then the variable name is in 'name'
|
|
885 |
||
886 |
@return
|
|
887 |
- 0 : error
|
|
888 |
- # : constant item
|
|
889 |
*/
|