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>
25
#include <drizzled/sql_string.h>
26
#include <drizzled/sql_list.h>
28
#include <drizzled/functions/int.h>
31
void Item_func::set_arguments(List<Item> &list)
34
arg_count=list.elements;
35
args= tmp_arg; // If 2 arguments
36
if (arg_count <= 2 || (args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
38
List_iterator_fast<Item> li(list);
40
Item **save_args= args;
45
with_sum_func|=item->with_sum_func;
48
list.empty(); // Fields are used
51
Item_func::Item_func(List<Item> &list)
57
Item_func::Item_func(Session *session, Item_func *item)
58
:Item_result_field(session, item),
59
allowed_arg_cols(item->allowed_arg_cols),
60
arg_count(item->arg_count),
61
used_tables_cache(item->used_tables_cache),
62
not_null_tables_cache(item->not_null_tables_cache),
63
const_item_cache(item->const_item_cache)
71
if (!(args=(Item**) session->alloc(sizeof(Item*)*arg_count)))
74
memcpy(args, item->args, sizeof(Item*)*arg_count);
80
Resolve references to table column for a function and its argument
85
ref Pointer to where this object is used. This reference
86
is used if we want to replace this object with another
87
one (for example in the summary functions).
90
Call fix_fields() for all arguments to the function. The main intention
91
is to allow all Item_field() objects to setup pointers to the table fields.
93
Sets as a side effect the following class variables:
94
maybe_null Set if any argument may return NULL
95
with_sum_func Set if any of the arguments contains a sum function
96
used_tables_cache Set to union of the tables used by arguments
98
str_value.charset If this is a string function, set this to the
99
character set for the first argument.
100
If any argument is binary, this is set to binary
102
If for any item any of the defaults are wrong, then this can
103
be fixed in the fix_length_and_dec() function that is called
104
after this one or by writing a specialized fix_fields() for the
109
true Got error. Stored with my_error().
113
Item_func::fix_fields(Session *session, Item **ref __attribute__((unused)))
116
Item **arg,**arg_end;
117
void *save_session_marker= session->session_marker;
118
unsigned char buff[STACK_BUFF_ALLOC]; // Max argument in function
119
session->session_marker= 0;
120
used_tables_cache= not_null_tables_cache= 0;
123
if (check_stack_overrun(session, STACK_MIN_SIZE, buff))
124
return true; // Fatal error if flag is set!
126
{ // Print purify happy
127
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
131
We can't yet set item to *arg as fix_fields may change *arg
132
We shouldn't call fix_fields() twice, so check 'fixed' field first
134
if ((!(*arg)->fixed && (*arg)->fix_fields(session, arg)))
135
return true; /* purecov: inspected */
138
if (allowed_arg_cols)
140
if (item->check_cols(allowed_arg_cols))
145
/* we have to fetch allowed_arg_cols from first argument */
146
assert(arg == args); // it is first argument
147
allowed_arg_cols= item->cols();
148
assert(allowed_arg_cols); // Can't be 0 any more
151
if (item->maybe_null)
154
with_sum_func= with_sum_func || item->with_sum_func;
155
used_tables_cache|= item->used_tables();
156
not_null_tables_cache|= item->not_null_tables();
157
const_item_cache&= item->const_item();
158
with_subselect|= item->with_subselect;
161
fix_length_and_dec();
162
if (session->is_error()) // An error inside fix_length_and_dec occured
165
session->session_marker= save_session_marker;
170
void Item_func::fix_after_pullout(st_select_lex *new_parent,
171
Item **ref __attribute__((unused)))
173
Item **arg,**arg_end;
175
used_tables_cache= not_null_tables_cache= 0;
180
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
182
(*arg)->fix_after_pullout(new_parent, arg);
185
used_tables_cache|= item->used_tables();
186
not_null_tables_cache|= item->not_null_tables();
187
const_item_cache&= item->const_item();
193
bool Item_func::walk(Item_processor processor, bool walk_subquery,
194
unsigned char *argument)
198
Item **arg,**arg_end;
199
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
201
if ((*arg)->walk(processor, walk_subquery, argument))
205
return (this->*processor)(argument);
208
void Item_func::traverse_cond(Cond_traverser traverser,
209
void *argument, traverse_order order)
213
Item **arg,**arg_end;
217
(*traverser)(this, argument);
218
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
220
(*arg)->traverse_cond(traverser, argument, order);
224
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
226
(*arg)->traverse_cond(traverser, argument, order);
228
(*traverser)(this, argument);
232
(*traverser)(this, argument);
237
Transform an Item_func object with a transformer callback function.
239
The function recursively applies the transform method to each
240
argument of the Item_func node.
241
If the call of the method for an argument item returns a new item
242
the old item is substituted for a new one.
243
After this the transformer is applied to the root node
244
of the Item_func object.
245
@param transformer the transformer callback function to be applied to
246
the nodes of the tree of the object
247
@param argument parameter to be passed to the transformer
250
Item returned as the result of transformation of the root node
253
Item *Item_func::transform(Item_transformer transformer, unsigned char *argument)
257
Item **arg,**arg_end;
258
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
260
Item *new_item= (*arg)->transform(transformer, argument);
265
Session::change_item_tree() should be called only if the tree was
266
really transformed, i.e. when a new item has been created.
267
Otherwise we'll be allocating a lot of unnecessary memory for
268
change records at each execution.
270
if (*arg != new_item)
271
current_session->change_item_tree(arg, new_item);
274
return (this->*transformer)(argument);
279
Compile Item_func object with a processor and a transformer
282
First the function applies the analyzer to the root node of
283
the Item_func object. Then if the analizer succeeeds (returns true)
284
the function recursively applies the compile method to each argument
285
of the Item_func node.
286
If the call of the method for an argument item returns a new item
287
the old item is substituted for a new one.
288
After this the transformer is applied to the root node
289
of the Item_func object.
291
@param analyzer the analyzer callback function to be applied to the
292
nodes of the tree of the object
293
@param[in,out] arg_p parameter to be passed to the processor
294
@param transformer the transformer callback function to be applied to the
295
nodes of the tree of the object
296
@param arg_t parameter to be passed to the transformer
299
Item returned as the result of transformation of the root node
302
Item *Item_func::compile(Item_analyzer analyzer, unsigned char **arg_p,
303
Item_transformer transformer, unsigned char *arg_t)
305
if (!(this->*analyzer)(arg_p))
309
Item **arg,**arg_end;
310
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
313
The same parameter value of arg_p must be passed
314
to analyze any argument of the condition formula.
316
unsigned char *arg_v= *arg_p;
317
Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t);
318
if (new_item && *arg != new_item)
319
current_session->change_item_tree(arg, new_item);
322
return (this->*transformer)(arg_t);
326
See comments in Item_cmp_func::split_sum_func()
329
void Item_func::split_sum_func(Session *session, Item **ref_pointer_array,
332
Item **arg, **arg_end;
333
for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
334
(*arg)->split_sum_func2(session, ref_pointer_array, fields, arg, true);
338
void Item_func::update_used_tables()
342
for (uint32_t i=0 ; i < arg_count ; i++)
344
args[i]->update_used_tables();
345
used_tables_cache|=args[i]->used_tables();
346
const_item_cache&=args[i]->const_item();
351
table_map Item_func::used_tables() const
353
return used_tables_cache;
357
table_map Item_func::not_null_tables() const
359
return not_null_tables_cache;
363
void Item_func::print(String *str, enum_query_type query_type)
365
str->append(func_name());
367
print_args(str, 0, query_type);
372
void Item_func::print_args(String *str, uint32_t from, enum_query_type query_type)
374
for (uint32_t i=from ; i < arg_count ; i++)
378
args[i]->print(str, query_type);
383
void Item_func::print_op(String *str, enum_query_type query_type)
386
for (uint32_t i=0 ; i < arg_count-1 ; i++)
388
args[i]->print(str, query_type);
390
str->append(func_name());
393
args[arg_count-1]->print(str, query_type);
398
bool Item_func::eq(const Item *item, bool binary_cmp) const
400
/* Assume we don't have rtti */
403
if (item->type() != FUNC_ITEM)
405
Item_func *item_func=(Item_func*) item;
406
Item_func::Functype func_type;
407
if ((func_type= functype()) != item_func->functype() ||
408
arg_count != item_func->arg_count ||
409
(func_type != Item_func::FUNC_SP &&
410
func_name() != item_func->func_name()) ||
411
(func_type == Item_func::FUNC_SP &&
412
my_strcasecmp(system_charset_info, func_name(), item_func->func_name())))
414
for (uint32_t i=0; i < arg_count ; i++)
415
if (!args[i]->eq(item_func->args[i], binary_cmp))
421
bool Item_func::get_arg0_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date)
423
return (null_value=args[0]->get_date(ltime, fuzzy_date));
427
bool Item_func::get_arg0_time(DRIZZLE_TIME *ltime)
429
return (null_value=args[0]->get_time(ltime));
433
bool Item_func::is_null()
440
Field *Item_func::tmp_table_field(Table *table)
444
switch (result_type()) {
446
if (max_length > MY_INT32_NUM_DECIMAL_DIGITS)
447
field= new Field_int64_t(max_length, maybe_null, name, unsigned_flag);
449
field= new Field_long(max_length, maybe_null, name, unsigned_flag);
452
field= new Field_double(max_length, maybe_null, name, decimals);
455
return make_string_field(table);
458
field= new Field_new_decimal(
459
my_decimal_precision_to_length(decimal_precision(),
462
maybe_null, name, decimals, unsigned_flag);
466
// This case should never be chosen
477
my_decimal *Item_func::val_decimal(my_decimal *decimal_value)
480
int2my_decimal(E_DEC_FATAL_ERROR, val_int(), unsigned_flag, decimal_value);
481
return decimal_value;
485
bool Item_func::agg_arg_collations(DTCollation &c, Item **items,
486
uint32_t nitems, uint32_t flags)
488
return agg_item_collations(c, func_name(), items, nitems, flags, 1);
492
bool Item_func::agg_arg_collations_for_comparison(DTCollation &c,
497
return agg_item_collations_for_comparison(c, func_name(),
498
items, nitems, flags);
502
bool Item_func::agg_arg_charsets(DTCollation &c, Item **items, uint32_t nitems,
503
uint32_t flags, int item_sep)
505
return agg_item_charsets(c, func_name(), items, nitems, flags, item_sep);
509
double Item_func::fix_result(double value)
511
if (CMATH_NAMESPACE::isfinite(value))