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>
30
#include <drizzled/field/int64_t.h>
31
#include <drizzled/field/long.h>
32
#include <drizzled/field/double.h>
33
#include <drizzled/field/fdecimal.h>
35
#include <drizzled/util/math.h>
36
#include <drizzled/session.h>
38
#if defined(CMATH_NAMESPACE)
39
using namespace CMATH_NAMESPACE;
44
void Item_func::set_arguments(List<Item> &list)
47
arg_count=list.elements;
48
args= tmp_arg; // If 2 arguments
49
if (arg_count <= 2 || (args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
51
List_iterator_fast<Item> li(list);
53
Item **save_args= args;
58
with_sum_func|=item->with_sum_func;
61
list.empty(); // Fields are used
64
Item_func::Item_func(List<Item> &list)
70
Item_func::Item_func(Session *session, Item_func *item)
71
:Item_result_field(session, item),
72
allowed_arg_cols(item->allowed_arg_cols),
73
arg_count(item->arg_count),
74
used_tables_cache(item->used_tables_cache),
75
not_null_tables_cache(item->not_null_tables_cache),
76
const_item_cache(item->const_item_cache)
84
if (!(args=(Item**) session->alloc(sizeof(Item*)*arg_count)))
87
memcpy(args, item->args, sizeof(Item*)*arg_count);
93
Resolve references to table column for a function and its argument
98
ref Pointer to where this object is used. This reference
99
is used if we want to replace this object with another
100
one (for example in the summary functions).
103
Call fix_fields() for all arguments to the function. The main intention
104
is to allow all Item_field() objects to setup pointers to the table fields.
106
Sets as a side effect the following class variables:
107
maybe_null Set if any argument may return NULL
108
with_sum_func Set if any of the arguments contains a sum function
109
used_tables_cache Set to union of the tables used by arguments
111
str_value.charset If this is a string function, set this to the
112
character set for the first argument.
113
If any argument is binary, this is set to binary
115
If for any item any of the defaults are wrong, then this can
116
be fixed in the fix_length_and_dec() function that is called
117
after this one or by writing a specialized fix_fields() for the
122
true Got error. Stored with my_error().
126
Item_func::fix_fields(Session *session, Item **ref __attribute__((unused)))
129
Item **arg,**arg_end;
130
void *save_session_marker= session->session_marker;
131
unsigned char buff[STACK_BUFF_ALLOC]; // Max argument in function
132
session->session_marker= 0;
133
used_tables_cache= not_null_tables_cache= 0;
136
if (check_stack_overrun(session, STACK_MIN_SIZE, buff))
137
return true; // Fatal error if flag is set!
139
{ // Print purify happy
140
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
144
We can't yet set item to *arg as fix_fields may change *arg
145
We shouldn't call fix_fields() twice, so check 'fixed' field first
147
if ((!(*arg)->fixed && (*arg)->fix_fields(session, arg)))
148
return true; /* purecov: inspected */
151
if (allowed_arg_cols)
153
if (item->check_cols(allowed_arg_cols))
158
/* we have to fetch allowed_arg_cols from first argument */
159
assert(arg == args); // it is first argument
160
allowed_arg_cols= item->cols();
161
assert(allowed_arg_cols); // Can't be 0 any more
164
if (item->maybe_null)
167
with_sum_func= with_sum_func || item->with_sum_func;
168
used_tables_cache|= item->used_tables();
169
not_null_tables_cache|= item->not_null_tables();
170
const_item_cache&= item->const_item();
171
with_subselect|= item->with_subselect;
174
fix_length_and_dec();
175
if (session->is_error()) // An error inside fix_length_and_dec occured
178
session->session_marker= save_session_marker;
183
void Item_func::fix_after_pullout(st_select_lex *new_parent,
184
Item **ref __attribute__((unused)))
186
Item **arg,**arg_end;
188
used_tables_cache= not_null_tables_cache= 0;
193
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
195
(*arg)->fix_after_pullout(new_parent, arg);
198
used_tables_cache|= item->used_tables();
199
not_null_tables_cache|= item->not_null_tables();
200
const_item_cache&= item->const_item();
206
bool Item_func::walk(Item_processor processor, bool walk_subquery,
207
unsigned char *argument)
211
Item **arg,**arg_end;
212
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
214
if ((*arg)->walk(processor, walk_subquery, argument))
218
return (this->*processor)(argument);
221
void Item_func::traverse_cond(Cond_traverser traverser,
222
void *argument, traverse_order order)
226
Item **arg,**arg_end;
230
(*traverser)(this, argument);
231
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
233
(*arg)->traverse_cond(traverser, argument, order);
237
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
239
(*arg)->traverse_cond(traverser, argument, order);
241
(*traverser)(this, argument);
245
(*traverser)(this, argument);
250
Transform an Item_func object with a transformer callback function.
252
The function recursively applies the transform method to each
253
argument of the Item_func node.
254
If the call of the method for an argument item returns a new item
255
the old item is substituted for a new one.
256
After this the transformer is applied to the root node
257
of the Item_func object.
258
@param transformer the transformer callback function to be applied to
259
the nodes of the tree of the object
260
@param argument parameter to be passed to the transformer
263
Item returned as the result of transformation of the root node
266
Item *Item_func::transform(Item_transformer transformer, unsigned char *argument)
270
Item **arg,**arg_end;
271
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
273
Item *new_item= (*arg)->transform(transformer, argument);
278
Session::change_item_tree() should be called only if the tree was
279
really transformed, i.e. when a new item has been created.
280
Otherwise we'll be allocating a lot of unnecessary memory for
281
change records at each execution.
283
if (*arg != new_item)
284
current_session->change_item_tree(arg, new_item);
287
return (this->*transformer)(argument);
292
Compile Item_func object with a processor and a transformer
295
First the function applies the analyzer to the root node of
296
the Item_func object. Then if the analizer succeeeds (returns true)
297
the function recursively applies the compile method to each argument
298
of the Item_func node.
299
If the call of the method for an argument item returns a new item
300
the old item is substituted for a new one.
301
After this the transformer is applied to the root node
302
of the Item_func object.
304
@param analyzer the analyzer callback function to be applied to the
305
nodes of the tree of the object
306
@param[in,out] arg_p parameter to be passed to the processor
307
@param transformer the transformer callback function to be applied to the
308
nodes of the tree of the object
309
@param arg_t parameter to be passed to the transformer
312
Item returned as the result of transformation of the root node
315
Item *Item_func::compile(Item_analyzer analyzer, unsigned char **arg_p,
316
Item_transformer transformer, unsigned char *arg_t)
318
if (!(this->*analyzer)(arg_p))
322
Item **arg,**arg_end;
323
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
326
The same parameter value of arg_p must be passed
327
to analyze any argument of the condition formula.
329
unsigned char *arg_v= *arg_p;
330
Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t);
331
if (new_item && *arg != new_item)
332
current_session->change_item_tree(arg, new_item);
335
return (this->*transformer)(arg_t);
339
See comments in Item_cmp_func::split_sum_func()
342
void Item_func::split_sum_func(Session *session, Item **ref_pointer_array,
345
Item **arg, **arg_end;
346
for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
347
(*arg)->split_sum_func(session, ref_pointer_array, fields, arg, true);
351
void Item_func::update_used_tables()
355
for (uint32_t i=0 ; i < arg_count ; i++)
357
args[i]->update_used_tables();
358
used_tables_cache|=args[i]->used_tables();
359
const_item_cache&=args[i]->const_item();
364
table_map Item_func::used_tables() const
366
return used_tables_cache;
370
table_map Item_func::not_null_tables() const
372
return not_null_tables_cache;
376
void Item_func::print(String *str, enum_query_type query_type)
378
str->append(func_name());
380
print_args(str, 0, query_type);
385
void Item_func::print_args(String *str, uint32_t from, enum_query_type query_type)
387
for (uint32_t i=from ; i < arg_count ; i++)
391
args[i]->print(str, query_type);
396
void Item_func::print_op(String *str, enum_query_type query_type)
399
for (uint32_t i=0 ; i < arg_count-1 ; i++)
401
args[i]->print(str, query_type);
403
str->append(func_name());
406
args[arg_count-1]->print(str, query_type);
411
bool Item_func::eq(const Item *item, bool binary_cmp) const
413
/* Assume we don't have rtti */
416
if (item->type() != FUNC_ITEM)
418
Item_func *item_func=(Item_func*) item;
419
Item_func::Functype func_type;
420
if ((func_type= functype()) != item_func->functype() ||
421
arg_count != item_func->arg_count ||
422
(func_type != Item_func::FUNC_SP &&
423
func_name() != item_func->func_name()) ||
424
(func_type == Item_func::FUNC_SP &&
425
my_strcasecmp(system_charset_info, func_name(), item_func->func_name())))
427
for (uint32_t i=0; i < arg_count ; i++)
428
if (!args[i]->eq(item_func->args[i], binary_cmp))
434
bool Item_func::get_arg0_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date)
436
return (null_value=args[0]->get_date(ltime, fuzzy_date));
440
bool Item_func::get_arg0_time(DRIZZLE_TIME *ltime)
442
return (null_value=args[0]->get_time(ltime));
446
bool Item_func::is_null()
453
Field *Item_func::tmp_table_field(Table *table)
457
switch (result_type()) {
459
if (max_length > MY_INT32_NUM_DECIMAL_DIGITS)
460
field= new Field_int64_t(max_length, maybe_null, name, unsigned_flag);
462
field= new Field_long(max_length, maybe_null, name, unsigned_flag);
465
field= new Field_double(max_length, maybe_null, name, decimals);
468
return make_string_field(table);
471
field= new Field_new_decimal(
472
my_decimal_precision_to_length(decimal_precision(),
475
maybe_null, name, decimals, unsigned_flag);
479
// This case should never be chosen
490
my_decimal *Item_func::val_decimal(my_decimal *decimal_value)
493
int2my_decimal(E_DEC_FATAL_ERROR, val_int(), unsigned_flag, decimal_value);
494
return decimal_value;
498
bool Item_func::agg_arg_collations(DTCollation &c, Item **items,
499
uint32_t nitems, uint32_t flags)
501
return agg_item_collations(c, func_name(), items, nitems, flags, 1);
505
bool Item_func::agg_arg_collations_for_comparison(DTCollation &c,
510
return agg_item_collations_for_comparison(c, func_name(),
511
items, nitems, flags);
515
bool Item_func::agg_arg_charsets(DTCollation &c, Item **items, uint32_t nitems,
516
uint32_t flags, int item_sep)
518
return agg_item_charsets(c, func_name(), items, nitems, flags, item_sep);
522
double Item_func::fix_result(double value)