492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
1 |
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
2 |
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
|
|
3 |
*
|
|
1999.6.1
by kalebral at gmail
update Copyright strings to a more common format to help with creating the master debian copyright file |
4 |
* Copyright (C) 2008 Sun Microsystems, Inc.
|
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
5 |
*
|
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.
|
|
9 |
*
|
|
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.
|
|
14 |
*
|
|
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
|
|
18 |
*/
|
|
19 |
||
1241.9.36
by Monty Taylor
ZOMG. I deleted drizzled/server_includes.h. |
20 |
#include "config.h" |
1280.1.10
by Monty Taylor
Put everything in drizzled into drizzled namespace. |
21 |
|
670.1.20
by Monty Taylor
Renamed functions to function... everything else is singular. |
22 |
#include <drizzled/function/set_user_var.h> |
584.5.1
by Monty Taylor
Removed field includes from field.h. |
23 |
#include <drizzled/field/num.h> |
584.1.15
by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes. |
24 |
#include <drizzled/session.h> |
971.6.1
by Eric Day
Renamed Protocol to Client, cleaned up some unnecessary methods along the way. |
25 |
#include <drizzled/plugin/client.h> |
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
26 |
|
1280.1.10
by Monty Taylor
Put everything in drizzled into drizzled namespace. |
27 |
namespace drizzled |
28 |
{
|
|
971.3.65
by Eric Day
Namespace cleanup for Protocol and Listen. |
29 |
|
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
30 |
/*
|
31 |
When a user variable is updated (in a SET command or a query like
|
|
32 |
SELECT @a:= ).
|
|
33 |
*/
|
|
34 |
||
35 |
bool Item_func_set_user_var::fix_fields(Session *session, Item **ref) |
|
36 |
{
|
|
37 |
assert(fixed == 0); |
|
38 |
/* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
|
|
39 |
if (Item_func::fix_fields(session, ref) || |
|
995
by Brian Aker
Refactor get_variable to session |
40 |
!(entry= session->getVariable(name, true))) |
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
41 |
return true; |
42 |
/*
|
|
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).
|
|
46 |
*/
|
|
1273.1.1
by Jay Pipes
* Changes Session::warn_id to Session::warn_query_id |
47 |
entry->update_query_id= session->getQueryId(); |
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
48 |
/*
|
49 |
As it is wrong and confusing to associate any
|
|
50 |
character set with NULL, @a should be latin2
|
|
51 |
after this query sequence:
|
|
52 |
||
53 |
SET @a=_latin2'string';
|
|
54 |
SET @a=NULL;
|
|
55 |
||
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.
|
|
62 |
*/
|
|
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(); |
|
68 |
return false; |
|
69 |
}
|
|
70 |
||
71 |
void
|
|
72 |
Item_func_set_user_var::fix_length_and_dec() |
|
73 |
{
|
|
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); |
|
78 |
}
|
|
79 |
||
80 |
/*
|
|
81 |
Mark field in read_map
|
|
82 |
||
83 |
NOTES
|
|
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
|
|
86 |
*/
|
|
87 |
||
88 |
bool Item_func_set_user_var::register_field_in_read_map(unsigned char *arg) |
|
89 |
{
|
|
90 |
if (result_field) |
|
91 |
{
|
|
92 |
Table *table= (Table *) arg; |
|
1660.1.3
by Brian Aker
Encapsulate Table in field |
93 |
if (result_field->getTable() == table || !table) |
1999.4.2
by Brian Aker
Encapsulate the field's position. |
94 |
result_field->getTable()->setReadSet(result_field->position()); |
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
95 |
}
|
96 |
return 0; |
|
97 |
}
|
|
98 |
||
99 |
||
100 |
bool
|
|
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, |
|
104 |
bool unsigned_arg) |
|
105 |
{
|
|
106 |
/*
|
|
107 |
If we set a variable explicitely to NULL then keep the old
|
|
108 |
result type of the variable
|
|
109 |
*/
|
|
110 |
if ((null_value= args[0]->null_value) && null_item) |
|
111 |
res_type= entry->type; // Don't change type of item |
|
1089.1.5
by Brian Aker
Cleanup of user_var |
112 |
if (entry->update_hash((null_value= args[0]->null_value), |
113 |
ptr, length, res_type, cs, dv, unsigned_arg)) |
|
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
114 |
{
|
115 |
null_value= 1; |
|
116 |
return 1; |
|
117 |
}
|
|
118 |
return 0; |
|
119 |
}
|
|
120 |
||
121 |
/**
|
|
122 |
This functions is invoked on SET \@variable or
|
|
123 |
\@variable:= expression.
|
|
124 |
||
125 |
Evaluate (and check expression), store results.
|
|
126 |
||
127 |
@note
|
|
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().
|
|
130 |
||
131 |
@retval
|
|
132 |
false OK.
|
|
133 |
*/
|
|
134 |
||
135 |
bool
|
|
136 |
Item_func_set_user_var::check(bool use_result_field) |
|
137 |
{
|
|
138 |
if (use_result_field && !result_field) |
|
139 |
use_result_field= false; |
|
140 |
||
141 |
switch (cached_result_type) { |
|
142 |
case REAL_RESULT: |
|
2008
by Brian Aker
Formatting + remove default from switch/case. |
143 |
{
|
144 |
save_result.vreal= use_result_field ? result_field->val_real() : |
|
145 |
args[0]->val_real(); |
|
146 |
break; |
|
147 |
}
|
|
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
148 |
case INT_RESULT: |
2008
by Brian Aker
Formatting + remove default from switch/case. |
149 |
{
|
150 |
save_result.vint= use_result_field ? result_field->val_int() : |
|
151 |
args[0]->val_int(); |
|
152 |
unsigned_flag= use_result_field ? ((Field_num*)result_field)->unsigned_flag: |
|
153 |
args[0]->unsigned_flag; |
|
154 |
break; |
|
155 |
}
|
|
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
156 |
case STRING_RESULT: |
2008
by Brian Aker
Formatting + remove default from switch/case. |
157 |
{
|
158 |
save_result.vstr= use_result_field ? result_field->val_str_internal(&value) : |
|
159 |
args[0]->val_str(&value); |
|
160 |
break; |
|
161 |
}
|
|
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
162 |
case DECIMAL_RESULT: |
2008
by Brian Aker
Formatting + remove default from switch/case. |
163 |
{
|
164 |
save_result.vdec= use_result_field ? |
|
165 |
result_field->val_decimal(&decimal_buff) : |
|
166 |
args[0]->val_decimal(&decimal_buff); |
|
167 |
break; |
|
168 |
}
|
|
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
169 |
case ROW_RESULT: |
170 |
// This case should never be chosen
|
|
171 |
assert(0); |
|
172 |
break; |
|
173 |
}
|
|
2008
by Brian Aker
Formatting + remove default from switch/case. |
174 |
|
175 |
return false; |
|
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
176 |
}
|
177 |
||
178 |
/**
|
|
179 |
This functions is invoked on
|
|
180 |
SET \@variable or \@variable:= expression.
|
|
181 |
||
182 |
@note
|
|
183 |
We have to store the expression as such in the variable, independent of
|
|
184 |
the value method used by the user
|
|
185 |
||
186 |
@retval
|
|
187 |
0 OK
|
|
188 |
@retval
|
|
189 |
1 EOM Error
|
|
190 |
||
191 |
*/
|
|
192 |
||
193 |
bool
|
|
194 |
Item_func_set_user_var::update() |
|
195 |
{
|
|
196 |
bool res= false; |
|
197 |
||
198 |
switch (cached_result_type) { |
|
199 |
case REAL_RESULT: |
|
2008
by Brian Aker
Formatting + remove default from switch/case. |
200 |
{
|
201 |
res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal), |
|
202 |
REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0); |
|
203 |
break; |
|
204 |
}
|
|
205 |
||
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
206 |
case INT_RESULT: |
2008
by Brian Aker
Formatting + remove default from switch/case. |
207 |
{
|
208 |
res= update_hash((void*) &save_result.vint, sizeof(save_result.vint), |
|
209 |
INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, |
|
210 |
unsigned_flag); |
|
211 |
break; |
|
212 |
}
|
|
213 |
||
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
214 |
case STRING_RESULT: |
2008
by Brian Aker
Formatting + remove default from switch/case. |
215 |
{
|
216 |
if (!save_result.vstr) // Null value |
|
217 |
res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin, |
|
218 |
DERIVATION_IMPLICIT, 0); |
|
219 |
else
|
|
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); |
|
224 |
break; |
|
225 |
}
|
|
226 |
||
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
227 |
case DECIMAL_RESULT: |
2008
by Brian Aker
Formatting + remove default from switch/case. |
228 |
{
|
229 |
if (!save_result.vdec) // Null value |
|
230 |
res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin, |
|
231 |
DERIVATION_IMPLICIT, 0); |
|
232 |
else
|
|
233 |
res= update_hash((void*) save_result.vdec, |
|
234 |
sizeof(my_decimal), DECIMAL_RESULT, |
|
235 |
&my_charset_bin, DERIVATION_IMPLICIT, 0); |
|
236 |
break; |
|
237 |
}
|
|
238 |
||
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
239 |
case ROW_RESULT: |
240 |
// This case should never be chosen
|
|
241 |
assert(0); |
|
242 |
break; |
|
243 |
}
|
|
2008
by Brian Aker
Formatting + remove default from switch/case. |
244 |
|
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
245 |
return(res); |
246 |
}
|
|
247 |
||
248 |
double Item_func_set_user_var::val_real() |
|
249 |
{
|
|
250 |
assert(fixed == 1); |
|
251 |
check(0); |
|
252 |
update(); // Store expression |
|
253 |
return entry->val_real(&null_value); |
|
254 |
}
|
|
255 |
||
256 |
int64_t Item_func_set_user_var::val_int() |
|
257 |
{
|
|
258 |
assert(fixed == 1); |
|
259 |
check(0); |
|
260 |
update(); // Store expression |
|
261 |
return entry->val_int(&null_value); |
|
262 |
}
|
|
263 |
||
264 |
String *Item_func_set_user_var::val_str(String *str) |
|
265 |
{
|
|
266 |
assert(fixed == 1); |
|
267 |
check(0); |
|
268 |
update(); // Store expression |
|
269 |
return entry->val_str(&null_value, str, decimals); |
|
270 |
}
|
|
271 |
||
272 |
||
273 |
my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val) |
|
274 |
{
|
|
275 |
assert(fixed == 1); |
|
276 |
check(0); |
|
277 |
update(); // Store expression |
|
278 |
return entry->val_decimal(&null_value, val); |
|
279 |
}
|
|
280 |
||
281 |
double Item_func_set_user_var::val_result() |
|
282 |
{
|
|
283 |
assert(fixed == 1); |
|
284 |
check(true); |
|
285 |
update(); // Store expression |
|
286 |
return entry->val_real(&null_value); |
|
287 |
}
|
|
288 |
||
289 |
int64_t Item_func_set_user_var::val_int_result() |
|
290 |
{
|
|
291 |
assert(fixed == 1); |
|
292 |
check(true); |
|
293 |
update(); // Store expression |
|
294 |
return entry->val_int(&null_value); |
|
295 |
}
|
|
296 |
||
297 |
String *Item_func_set_user_var::str_result(String *str) |
|
298 |
{
|
|
299 |
assert(fixed == 1); |
|
300 |
check(true); |
|
301 |
update(); // Store expression |
|
302 |
return entry->val_str(&null_value, str, decimals); |
|
303 |
}
|
|
304 |
||
305 |
||
306 |
my_decimal *Item_func_set_user_var::val_decimal_result(my_decimal *val) |
|
307 |
{
|
|
308 |
assert(fixed == 1); |
|
309 |
check(true); |
|
310 |
update(); // Store expression |
|
311 |
return entry->val_decimal(&null_value, val); |
|
312 |
}
|
|
313 |
||
314 |
void Item_func_set_user_var::print(String *str, enum_query_type query_type) |
|
315 |
{
|
|
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); |
|
320 |
str->append(')'); |
|
321 |
}
|
|
322 |
||
971.6.1
by Eric Day
Renamed Protocol to Client, cleaned up some unnecessary methods along the way. |
323 |
bool Item_func_set_user_var::send(plugin::Client *client, String *str_arg) |
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
324 |
{
|
325 |
if (result_field) |
|
326 |
{
|
|
327 |
check(1); |
|
328 |
update(); |
|
971.6.1
by Eric Day
Renamed Protocol to Client, cleaned up some unnecessary methods along the way. |
329 |
return client->store(result_field); |
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
330 |
}
|
971.6.1
by Eric Day
Renamed Protocol to Client, cleaned up some unnecessary methods along the way. |
331 |
return Item::send(client, str_arg); |
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
332 |
}
|
333 |
||
1052.2.4
by Nathan Williams
No actual code changes. Changed Send_field to SendField to be consistent with coding standards. |
334 |
void Item_func_set_user_var::make_field(SendField *tmp_field) |
492.3.35
by Lee
more changes to move functions from item_func.cc/h to the functions directory |
335 |
{
|
336 |
if (result_field) |
|
337 |
{
|
|
338 |
result_field->make_field(tmp_field); |
|
339 |
assert(tmp_field->table_name != 0); |
|
340 |
if (Item::name) |
|
341 |
tmp_field->col_name=Item::name; // Use user supplied name |
|
342 |
}
|
|
343 |
else
|
|
344 |
Item::make_field(tmp_field); |
|
345 |
}
|
|
346 |
||
347 |
/*
|
|
348 |
Save the value of a user variable into a field
|
|
349 |
||
350 |
SYNOPSIS
|
|
351 |
save_in_field()
|
|
352 |
field target field to save the value to
|
|
353 |
no_conversion flag indicating whether conversions are allowed
|
|
354 |
||
355 |
DESCRIPTION
|
|
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.
|
|
360 |
||
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.
|
|
371 |
||
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.
|
|
379 |
||
380 |
RETURN VALUES
|
|
381 |
false Ok
|
|
382 |
true Error
|
|
383 |
*/
|
|
384 |
||
385 |
int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions, |
|
386 |
bool can_use_result_field) |
|
387 |
{
|
|
388 |
bool use_result_field= (!can_use_result_field ? 0 : |
|
389 |
(result_field && result_field != field)); |
|
390 |
int error; |
|
391 |
||
392 |
/* Update the value of the user variable */
|
|
393 |
check(use_result_field); |
|
394 |
update(); |
|
395 |
||
396 |
if (result_type() == STRING_RESULT || |
|
397 |
(result_type() == REAL_RESULT && field->result_type() == STRING_RESULT)) |
|
398 |
{
|
|
399 |
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); |
|
404 |
||
405 |
if (null_value) |
|
406 |
{
|
|
407 |
str_value.set_quick(0, 0, cs); |
|
408 |
return set_field_to_null_with_conversions(field, no_conversions); |
|
409 |
}
|
|
410 |
||
411 |
/* NOTE: If null_value == false, "result" must be not NULL. */
|
|
412 |
||
413 |
field->set_notnull(); |
|
414 |
error=field->store(result->ptr(),result->length(),cs); |
|
415 |
str_value.set_quick(0, 0, cs); |
|
416 |
}
|
|
417 |
else if (result_type() == REAL_RESULT) |
|
418 |
{
|
|
419 |
double nr= entry->val_real(&null_value); |
|
420 |
if (null_value) |
|
421 |
return set_field_to_null(field); |
|
422 |
field->set_notnull(); |
|
423 |
error=field->store(nr); |
|
424 |
}
|
|
425 |
else if (result_type() == DECIMAL_RESULT) |
|
426 |
{
|
|
427 |
my_decimal decimal_value; |
|
428 |
my_decimal *val= entry->val_decimal(&null_value, &decimal_value); |
|
429 |
if (null_value) |
|
430 |
return set_field_to_null(field); |
|
431 |
field->set_notnull(); |
|
432 |
error=field->store_decimal(val); |
|
433 |
}
|
|
434 |
else
|
|
435 |
{
|
|
436 |
int64_t nr= entry->val_int(&null_value); |
|
437 |
if (null_value) |
|
438 |
return set_field_to_null_with_conversions(field, no_conversions); |
|
439 |
field->set_notnull(); |
|
440 |
error=field->store(nr, unsigned_flag); |
|
441 |
}
|
|
442 |
return error; |
|
443 |
}
|
|
444 |
||
445 |
||
1280.1.10
by Monty Taylor
Put everything in drizzled into drizzled namespace. |
446 |
} /* namespace drizzled */ |