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
21
#include <drizzled/server_includes.h>
26
#include <drizzled/sql_string.h>
27
#include <drizzled/sql_list.h>
29
#include <drizzled/functions/int.h>
31
#include <drizzled/util/math.h>
33
#if defined(CMATH_NAMESPACE)
34
using namespace CMATH_NAMESPACE;
39
void Item_func::set_arguments(List<Item> &list)
42
arg_count=list.elements;
43
args= tmp_arg; // If 2 arguments
44
if (arg_count <= 2 || (args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
46
List_iterator_fast<Item> li(list);
48
Item **save_args= args;
53
with_sum_func|=item->with_sum_func;
56
list.empty(); // Fields are used
59
Item_func::Item_func(List<Item> &list)
65
Item_func::Item_func(Session *session, Item_func *item)
66
:Item_result_field(session, item),
67
allowed_arg_cols(item->allowed_arg_cols),
68
arg_count(item->arg_count),
69
used_tables_cache(item->used_tables_cache),
70
not_null_tables_cache(item->not_null_tables_cache),
71
const_item_cache(item->const_item_cache)
79
if (!(args=(Item**) session->alloc(sizeof(Item*)*arg_count)))
82
memcpy(args, item->args, sizeof(Item*)*arg_count);
88
Resolve references to table column for a function and its argument
93
ref Pointer to where this object is used. This reference
94
is used if we want to replace this object with another
95
one (for example in the summary functions).
98
Call fix_fields() for all arguments to the function. The main intention
99
is to allow all Item_field() objects to setup pointers to the table fields.
101
Sets as a side effect the following class variables:
102
maybe_null Set if any argument may return NULL
103
with_sum_func Set if any of the arguments contains a sum function
104
used_tables_cache Set to union of the tables used by arguments
106
str_value.charset If this is a string function, set this to the
107
character set for the first argument.
108
If any argument is binary, this is set to binary
110
If for any item any of the defaults are wrong, then this can
111
be fixed in the fix_length_and_dec() function that is called
112
after this one or by writing a specialized fix_fields() for the
117
true Got error. Stored with my_error().
121
Item_func::fix_fields(Session *session, Item **ref __attribute__((unused)))
124
Item **arg,**arg_end;
125
void *save_session_marker= session->session_marker;
126
unsigned char buff[STACK_BUFF_ALLOC]; // Max argument in function
127
session->session_marker= 0;
128
used_tables_cache= not_null_tables_cache= 0;
131
if (check_stack_overrun(session, STACK_MIN_SIZE, buff))
132
return true; // Fatal error if flag is set!
134
{ // Print purify happy
135
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
139
We can't yet set item to *arg as fix_fields may change *arg
140
We shouldn't call fix_fields() twice, so check 'fixed' field first
142
if ((!(*arg)->fixed && (*arg)->fix_fields(session, arg)))
143
return true; /* purecov: inspected */
146
if (allowed_arg_cols)
148
if (item->check_cols(allowed_arg_cols))
153
/* we have to fetch allowed_arg_cols from first argument */
154
assert(arg == args); // it is first argument
155
allowed_arg_cols= item->cols();
156
assert(allowed_arg_cols); // Can't be 0 any more
159
if (item->maybe_null)
162
with_sum_func= with_sum_func || item->with_sum_func;
163
used_tables_cache|= item->used_tables();
164
not_null_tables_cache|= item->not_null_tables();
165
const_item_cache&= item->const_item();
166
with_subselect|= item->with_subselect;
169
fix_length_and_dec();
170
if (session->is_error()) // An error inside fix_length_and_dec occured
173
session->session_marker= save_session_marker;
178
void Item_func::fix_after_pullout(st_select_lex *new_parent,
179
Item **ref __attribute__((unused)))
181
Item **arg,**arg_end;
183
used_tables_cache= not_null_tables_cache= 0;
188
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
190
(*arg)->fix_after_pullout(new_parent, arg);
193
used_tables_cache|= item->used_tables();
194
not_null_tables_cache|= item->not_null_tables();
195
const_item_cache&= item->const_item();
201
bool Item_func::walk(Item_processor processor, bool walk_subquery,
202
unsigned char *argument)
206
Item **arg,**arg_end;
207
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
209
if ((*arg)->walk(processor, walk_subquery, argument))
213
return (this->*processor)(argument);
216
void Item_func::traverse_cond(Cond_traverser traverser,
217
void *argument, traverse_order order)
221
Item **arg,**arg_end;
225
(*traverser)(this, argument);
226
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
228
(*arg)->traverse_cond(traverser, argument, order);
232
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
234
(*arg)->traverse_cond(traverser, argument, order);
236
(*traverser)(this, argument);
240
(*traverser)(this, argument);
245
Transform an Item_func object with a transformer callback function.
247
The function recursively applies the transform method to each
248
argument of the Item_func node.
249
If the call of the method for an argument item returns a new item
250
the old item is substituted for a new one.
251
After this the transformer is applied to the root node
252
of the Item_func object.
253
@param transformer the transformer callback function to be applied to
254
the nodes of the tree of the object
255
@param argument parameter to be passed to the transformer
258
Item returned as the result of transformation of the root node
261
Item *Item_func::transform(Item_transformer transformer, unsigned char *argument)
265
Item **arg,**arg_end;
266
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
268
Item *new_item= (*arg)->transform(transformer, argument);
273
Session::change_item_tree() should be called only if the tree was
274
really transformed, i.e. when a new item has been created.
275
Otherwise we'll be allocating a lot of unnecessary memory for
276
change records at each execution.
278
if (*arg != new_item)
279
current_session->change_item_tree(arg, new_item);
282
return (this->*transformer)(argument);
287
Compile Item_func object with a processor and a transformer
290
First the function applies the analyzer to the root node of
291
the Item_func object. Then if the analizer succeeeds (returns true)
292
the function recursively applies the compile method to each argument
293
of the Item_func node.
294
If the call of the method for an argument item returns a new item
295
the old item is substituted for a new one.
296
After this the transformer is applied to the root node
297
of the Item_func object.
299
@param analyzer the analyzer callback function to be applied to the
300
nodes of the tree of the object
301
@param[in,out] arg_p parameter to be passed to the processor
302
@param transformer the transformer callback function to be applied to the
303
nodes of the tree of the object
304
@param arg_t parameter to be passed to the transformer
307
Item returned as the result of transformation of the root node
310
Item *Item_func::compile(Item_analyzer analyzer, unsigned char **arg_p,
311
Item_transformer transformer, unsigned char *arg_t)
313
if (!(this->*analyzer)(arg_p))
317
Item **arg,**arg_end;
318
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
321
The same parameter value of arg_p must be passed
322
to analyze any argument of the condition formula.
324
unsigned char *arg_v= *arg_p;
325
Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t);
326
if (new_item && *arg != new_item)
327
current_session->change_item_tree(arg, new_item);
330
return (this->*transformer)(arg_t);
334
See comments in Item_cmp_func::split_sum_func()
337
void Item_func::split_sum_func(Session *session, Item **ref_pointer_array,
340
Item **arg, **arg_end;
341
for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
342
(*arg)->split_sum_func2(session, ref_pointer_array, fields, arg, true);
346
void Item_func::update_used_tables()
350
for (uint32_t i=0 ; i < arg_count ; i++)
352
args[i]->update_used_tables();
353
used_tables_cache|=args[i]->used_tables();
354
const_item_cache&=args[i]->const_item();
359
table_map Item_func::used_tables() const
361
return used_tables_cache;
365
table_map Item_func::not_null_tables() const
367
return not_null_tables_cache;
371
void Item_func::print(String *str, enum_query_type query_type)
373
str->append(func_name());
375
print_args(str, 0, query_type);
380
void Item_func::print_args(String *str, uint32_t from, enum_query_type query_type)
382
for (uint32_t i=from ; i < arg_count ; i++)
386
args[i]->print(str, query_type);
391
void Item_func::print_op(String *str, enum_query_type query_type)
394
for (uint32_t i=0 ; i < arg_count-1 ; i++)
396
args[i]->print(str, query_type);
398
str->append(func_name());
401
args[arg_count-1]->print(str, query_type);
406
bool Item_func::eq(const Item *item, bool binary_cmp) const
408
/* Assume we don't have rtti */
411
if (item->type() != FUNC_ITEM)
413
Item_func *item_func=(Item_func*) item;
414
Item_func::Functype func_type;
415
if ((func_type= functype()) != item_func->functype() ||
416
arg_count != item_func->arg_count ||
417
(func_type != Item_func::FUNC_SP &&
418
func_name() != item_func->func_name()) ||
419
(func_type == Item_func::FUNC_SP &&
420
my_strcasecmp(system_charset_info, func_name(), item_func->func_name())))
422
for (uint32_t i=0; i < arg_count ; i++)
423
if (!args[i]->eq(item_func->args[i], binary_cmp))
429
bool Item_func::get_arg0_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date)
431
return (null_value=args[0]->get_date(ltime, fuzzy_date));
435
bool Item_func::get_arg0_time(DRIZZLE_TIME *ltime)
437
return (null_value=args[0]->get_time(ltime));
441
bool Item_func::is_null()
448
Field *Item_func::tmp_table_field(Table *table)
452
switch (result_type()) {
454
if (max_length > MY_INT32_NUM_DECIMAL_DIGITS)
455
field= new Field_int64_t(max_length, maybe_null, name, unsigned_flag);
457
field= new Field_long(max_length, maybe_null, name, unsigned_flag);
460
field= new Field_double(max_length, maybe_null, name, decimals);
463
return make_string_field(table);
466
field= new Field_new_decimal(
467
my_decimal_precision_to_length(decimal_precision(),
470
maybe_null, name, decimals, unsigned_flag);
474
// This case should never be chosen
485
my_decimal *Item_func::val_decimal(my_decimal *decimal_value)
488
int2my_decimal(E_DEC_FATAL_ERROR, val_int(), unsigned_flag, decimal_value);
489
return decimal_value;
493
bool Item_func::agg_arg_collations(DTCollation &c, Item **items,
494
uint32_t nitems, uint32_t flags)
496
return agg_item_collations(c, func_name(), items, nitems, flags, 1);
500
bool Item_func::agg_arg_collations_for_comparison(DTCollation &c,
505
return agg_item_collations_for_comparison(c, func_name(),
506
items, nitems, flags);
510
bool Item_func::agg_arg_charsets(DTCollation &c, Item **items, uint32_t nitems,
511
uint32_t flags, int item_sep)
513
return agg_item_charsets(c, func_name(), items, nitems, flags, item_sep);
517
double Item_func::fix_result(double value)