~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/functions/func.cc

  • Committer: Brian Aker
  • Date: 2008-07-07 14:25:25 UTC
  • mto: (77.1.25 codestyle)
  • mto: This revision was merged to the branch mainline in revision 82.
  • Revision ID: brian@tangent.org-20080707142525-xzy2nl3ie2ebwfln
LL() cleanup

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems
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
 
 
20
 
#include <drizzled/server_includes.h>
21
 
 
22
 
#include CSTDINT_H
23
 
#include <cassert>
24
 
 
25
 
#include <drizzled/version.h>
26
 
 
27
 
#include <drizzled/sql_string.h>
28
 
#include <drizzled/sql_list.h>
29
 
 
30
 
#include <drizzled/functions/int.h>
31
 
 
32
 
 
33
 
void Item_func::set_arguments(List<Item> &list)
34
 
{
35
 
  allowed_arg_cols= 1;
36
 
  arg_count=list.elements;
37
 
  args= tmp_arg;                                // If 2 arguments
38
 
  if (arg_count <= 2 || (args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
39
 
  {
40
 
    List_iterator_fast<Item> li(list);
41
 
    Item *item;
42
 
    Item **save_args= args;
43
 
 
44
 
    while ((item=li++))
45
 
    {
46
 
      *(save_args++)= item;
47
 
      with_sum_func|=item->with_sum_func;
48
 
    }
49
 
  }
50
 
  list.empty();          // Fields are used
51
 
}
52
 
 
53
 
Item_func::Item_func(List<Item> &list)
54
 
  :allowed_arg_cols(1)
55
 
{
56
 
  set_arguments(list);
57
 
}
58
 
 
59
 
Item_func::Item_func(THD *thd, Item_func *item)
60
 
  :Item_result_field(thd, item),
61
 
   allowed_arg_cols(item->allowed_arg_cols),
62
 
   arg_count(item->arg_count),
63
 
   used_tables_cache(item->used_tables_cache),
64
 
   not_null_tables_cache(item->not_null_tables_cache),
65
 
   const_item_cache(item->const_item_cache)
66
 
{
67
 
  if (arg_count)
68
 
  {
69
 
    if (arg_count <=2)
70
 
      args= tmp_arg;
71
 
    else
72
 
    {
73
 
      if (!(args=(Item**) thd->alloc(sizeof(Item*)*arg_count)))
74
 
        return;
75
 
    }
76
 
    memcpy(args, item->args, sizeof(Item*)*arg_count);
77
 
  }
78
 
}
79
 
 
80
 
 
81
 
/*
82
 
  Resolve references to table column for a function and its argument
83
 
 
84
 
  SYNOPSIS:
85
 
  fix_fields()
86
 
  thd    Thread object
87
 
  ref    Pointer to where this object is used.  This reference
88
 
  is used if we want to replace this object with another
89
 
  one (for example in the summary functions).
90
 
 
91
 
  DESCRIPTION
92
 
  Call fix_fields() for all arguments to the function.  The main intention
93
 
  is to allow all Item_field() objects to setup pointers to the table fields.
94
 
 
95
 
  Sets as a side effect the following class variables:
96
 
  maybe_null  Set if any argument may return NULL
97
 
  with_sum_func  Set if any of the arguments contains a sum function
98
 
  used_tables_cache Set to union of the tables used by arguments
99
 
 
100
 
  str_value.charset If this is a string function, set this to the
101
 
  character set for the first argument.
102
 
  If any argument is binary, this is set to binary
103
 
 
104
 
  If for any item any of the defaults are wrong, then this can
105
 
  be fixed in the fix_length_and_dec() function that is called
106
 
  after this one or by writing a specialized fix_fields() for the
107
 
  item.
108
 
 
109
 
  RETURN VALUES
110
 
  false  ok
111
 
  true  Got error.  Stored with my_error().
112
 
*/
113
 
 
114
 
bool
115
 
Item_func::fix_fields(THD *thd, Item **ref __attribute__((unused)))
116
 
{
117
 
  assert(fixed == 0);
118
 
  Item **arg,**arg_end;
119
 
  void *save_thd_marker= thd->thd_marker;
120
 
  unsigned char buff[STACK_BUFF_ALLOC];      // Max argument in function
121
 
  thd->thd_marker= 0;
122
 
  used_tables_cache= not_null_tables_cache= 0;
123
 
  const_item_cache=1;
124
 
 
125
 
  if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
126
 
    return true;        // Fatal error if flag is set!
127
 
  if (arg_count)
128
 
  {            // Print purify happy
129
 
    for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
130
 
    {
131
 
      Item *item;
132
 
      /*
133
 
        We can't yet set item to *arg as fix_fields may change *arg
134
 
        We shouldn't call fix_fields() twice, so check 'fixed' field first
135
 
      */
136
 
      if ((!(*arg)->fixed && (*arg)->fix_fields(thd, arg)))
137
 
        return true;        /* purecov: inspected */
138
 
      item= *arg;
139
 
 
140
 
      if (allowed_arg_cols)
141
 
      {
142
 
        if (item->check_cols(allowed_arg_cols))
143
 
          return 1;
144
 
      }
145
 
      else
146
 
      {
147
 
        /*  we have to fetch allowed_arg_cols from first argument */
148
 
        assert(arg == args); // it is first argument
149
 
        allowed_arg_cols= item->cols();
150
 
        assert(allowed_arg_cols); // Can't be 0 any more
151
 
      }
152
 
 
153
 
      if (item->maybe_null)
154
 
        maybe_null=1;
155
 
 
156
 
      with_sum_func= with_sum_func || item->with_sum_func;
157
 
      used_tables_cache|=     item->used_tables();
158
 
      not_null_tables_cache|= item->not_null_tables();
159
 
      const_item_cache&=      item->const_item();
160
 
      with_subselect|=        item->with_subselect;
161
 
    }
162
 
  }
163
 
  fix_length_and_dec();
164
 
  if (thd->is_error()) // An error inside fix_length_and_dec occured
165
 
    return true;
166
 
  fixed= 1;
167
 
  thd->thd_marker= save_thd_marker;
168
 
  return false;
169
 
}
170
 
 
171
 
 
172
 
void Item_func::fix_after_pullout(st_select_lex *new_parent,
173
 
                                  Item **ref __attribute__((unused)))
174
 
{
175
 
  Item **arg,**arg_end;
176
 
 
177
 
  used_tables_cache= not_null_tables_cache= 0;
178
 
  const_item_cache=1;
179
 
 
180
 
  if (arg_count)
181
 
  {
182
 
    for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
183
 
    {
184
 
      (*arg)->fix_after_pullout(new_parent, arg);
185
 
      Item *item= *arg;
186
 
 
187
 
      used_tables_cache|=     item->used_tables();
188
 
      not_null_tables_cache|= item->not_null_tables();
189
 
      const_item_cache&=      item->const_item();
190
 
    }
191
 
  }
192
 
}
193
 
 
194
 
 
195
 
bool Item_func::walk(Item_processor processor, bool walk_subquery,
196
 
                     unsigned char *argument)
197
 
{
198
 
  if (arg_count)
199
 
  {
200
 
    Item **arg,**arg_end;
201
 
    for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
202
 
    {
203
 
      if ((*arg)->walk(processor, walk_subquery, argument))
204
 
        return 1;
205
 
    }
206
 
  }
207
 
  return (this->*processor)(argument);
208
 
}
209
 
 
210
 
void Item_func::traverse_cond(Cond_traverser traverser,
211
 
                              void *argument, traverse_order order)
212
 
{
213
 
  if (arg_count)
214
 
  {
215
 
    Item **arg,**arg_end;
216
 
 
217
 
    switch (order) {
218
 
    case(PREFIX):
219
 
      (*traverser)(this, argument);
220
 
      for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
221
 
      {
222
 
        (*arg)->traverse_cond(traverser, argument, order);
223
 
      }
224
 
      break;
225
 
    case (POSTFIX):
226
 
      for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
227
 
      {
228
 
        (*arg)->traverse_cond(traverser, argument, order);
229
 
      }
230
 
      (*traverser)(this, argument);
231
 
    }
232
 
  }
233
 
  else
234
 
    (*traverser)(this, argument);
235
 
}
236
 
 
237
 
 
238
 
/**
239
 
   Transform an Item_func object with a transformer callback function.
240
 
 
241
 
   The function recursively applies the transform method to each
242
 
   argument of the Item_func node.
243
 
   If the call of the method for an argument item returns a new item
244
 
   the old item is substituted for a new one.
245
 
   After this the transformer is applied to the root node
246
 
   of the Item_func object.
247
 
   @param transformer   the transformer callback function to be applied to
248
 
   the nodes of the tree of the object
249
 
   @param argument      parameter to be passed to the transformer
250
 
 
251
 
   @return
252
 
   Item returned as the result of transformation of the root node
253
 
*/
254
 
 
255
 
Item *Item_func::transform(Item_transformer transformer, unsigned char *argument)
256
 
{
257
 
  if (arg_count)
258
 
  {
259
 
    Item **arg,**arg_end;
260
 
    for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
261
 
    {
262
 
      Item *new_item= (*arg)->transform(transformer, argument);
263
 
      if (!new_item)
264
 
        return 0;
265
 
 
266
 
      /*
267
 
        THD::change_item_tree() should be called only if the tree was
268
 
        really transformed, i.e. when a new item has been created.
269
 
        Otherwise we'll be allocating a lot of unnecessary memory for
270
 
        change records at each execution.
271
 
      */
272
 
      if (*arg != new_item)
273
 
        current_thd->change_item_tree(arg, new_item);
274
 
    }
275
 
  }
276
 
  return (this->*transformer)(argument);
277
 
}
278
 
 
279
 
 
280
 
/**
281
 
   Compile Item_func object with a processor and a transformer
282
 
   callback functions.
283
 
 
284
 
   First the function applies the analyzer to the root node of
285
 
   the Item_func object. Then if the analizer succeeeds (returns true)
286
 
   the function recursively applies the compile method to each argument
287
 
   of the Item_func node.
288
 
   If the call of the method for an argument item returns a new item
289
 
   the old item is substituted for a new one.
290
 
   After this the transformer is applied to the root node
291
 
   of the Item_func object.
292
 
 
293
 
   @param analyzer      the analyzer callback function to be applied to the
294
 
   nodes of the tree of the object
295
 
   @param[in,out] arg_p parameter to be passed to the processor
296
 
   @param transformer   the transformer callback function to be applied to the
297
 
   nodes of the tree of the object
298
 
   @param arg_t         parameter to be passed to the transformer
299
 
 
300
 
   @return
301
 
   Item returned as the result of transformation of the root node
302
 
*/
303
 
 
304
 
Item *Item_func::compile(Item_analyzer analyzer, unsigned char **arg_p,
305
 
                         Item_transformer transformer, unsigned char *arg_t)
306
 
{
307
 
  if (!(this->*analyzer)(arg_p))
308
 
    return 0;
309
 
  if (arg_count)
310
 
  {
311
 
    Item **arg,**arg_end;
312
 
    for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
313
 
    {
314
 
      /*
315
 
        The same parameter value of arg_p must be passed
316
 
        to analyze any argument of the condition formula.
317
 
      */
318
 
      unsigned char *arg_v= *arg_p;
319
 
      Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t);
320
 
      if (new_item && *arg != new_item)
321
 
        current_thd->change_item_tree(arg, new_item);
322
 
    }
323
 
  }
324
 
  return (this->*transformer)(arg_t);
325
 
}
326
 
 
327
 
/**
328
 
   See comments in Item_cmp_func::split_sum_func()
329
 
*/
330
 
 
331
 
void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array,
332
 
                               List<Item> &fields)
333
 
{
334
 
  Item **arg, **arg_end;
335
 
  for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
336
 
    (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg, true);
337
 
}
338
 
 
339
 
 
340
 
void Item_func::update_used_tables()
341
 
{
342
 
  used_tables_cache=0;
343
 
  const_item_cache=1;
344
 
  for (uint32_t i=0 ; i < arg_count ; i++)
345
 
  {
346
 
    args[i]->update_used_tables();
347
 
    used_tables_cache|=args[i]->used_tables();
348
 
    const_item_cache&=args[i]->const_item();
349
 
  }
350
 
}
351
 
 
352
 
 
353
 
table_map Item_func::used_tables() const
354
 
{
355
 
  return used_tables_cache;
356
 
}
357
 
 
358
 
 
359
 
table_map Item_func::not_null_tables() const
360
 
{
361
 
  return not_null_tables_cache;
362
 
}
363
 
 
364
 
 
365
 
void Item_func::print(String *str, enum_query_type query_type)
366
 
{
367
 
  str->append(func_name());
368
 
  str->append('(');
369
 
  print_args(str, 0, query_type);
370
 
  str->append(')');
371
 
}
372
 
 
373
 
 
374
 
void Item_func::print_args(String *str, uint32_t from, enum_query_type query_type)
375
 
{
376
 
  for (uint32_t i=from ; i < arg_count ; i++)
377
 
  {
378
 
    if (i != from)
379
 
      str->append(',');
380
 
    args[i]->print(str, query_type);
381
 
  }
382
 
}
383
 
 
384
 
 
385
 
void Item_func::print_op(String *str, enum_query_type query_type)
386
 
{
387
 
  str->append('(');
388
 
  for (uint32_t i=0 ; i < arg_count-1 ; i++)
389
 
  {
390
 
    args[i]->print(str, query_type);
391
 
    str->append(' ');
392
 
    str->append(func_name());
393
 
    str->append(' ');
394
 
  }
395
 
  args[arg_count-1]->print(str, query_type);
396
 
  str->append(')');
397
 
}
398
 
 
399
 
 
400
 
bool Item_func::eq(const Item *item, bool binary_cmp) const
401
 
{
402
 
  /* Assume we don't have rtti */
403
 
  if (this == item)
404
 
    return 1;
405
 
  if (item->type() != FUNC_ITEM)
406
 
    return 0;
407
 
  Item_func *item_func=(Item_func*) item;
408
 
  Item_func::Functype func_type;
409
 
  if ((func_type= functype()) != item_func->functype() ||
410
 
      arg_count != item_func->arg_count ||
411
 
      (func_type != Item_func::FUNC_SP &&
412
 
       func_name() != item_func->func_name()) ||
413
 
      (func_type == Item_func::FUNC_SP &&
414
 
       my_strcasecmp(system_charset_info, func_name(), item_func->func_name())))
415
 
    return 0;
416
 
  for (uint32_t i=0; i < arg_count ; i++)
417
 
    if (!args[i]->eq(item_func->args[i], binary_cmp))
418
 
      return 0;
419
 
  return 1;
420
 
}
421
 
 
422
 
 
423
 
bool Item_func::get_arg0_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date)
424
 
{
425
 
  return (null_value=args[0]->get_date(ltime, fuzzy_date));
426
 
}
427
 
 
428
 
 
429
 
bool Item_func::get_arg0_time(DRIZZLE_TIME *ltime)
430
 
{
431
 
  return (null_value=args[0]->get_time(ltime));
432
 
}
433
 
 
434
 
 
435
 
bool Item_func::is_null()
436
 
{
437
 
  update_null_value();
438
 
  return null_value;
439
 
}
440
 
 
441
 
 
442
 
Field *Item_func::tmp_table_field(Table *table)
443
 
{
444
 
  Field *field;
445
 
 
446
 
  switch (result_type()) {
447
 
  case INT_RESULT:
448
 
    if (max_length > MY_INT32_NUM_DECIMAL_DIGITS)
449
 
      field= new Field_int64_t(max_length, maybe_null, name, unsigned_flag);
450
 
    else
451
 
      field= new Field_long(max_length, maybe_null, name, unsigned_flag);
452
 
    break;
453
 
  case REAL_RESULT:
454
 
    field= new Field_double(max_length, maybe_null, name, decimals);
455
 
    break;
456
 
  case STRING_RESULT:
457
 
    return make_string_field(table);
458
 
    break;
459
 
  case DECIMAL_RESULT:
460
 
    field= new Field_new_decimal(
461
 
                       my_decimal_precision_to_length(decimal_precision(),
462
 
                                                      decimals,
463
 
                                                      unsigned_flag),
464
 
                       maybe_null, name, decimals, unsigned_flag);
465
 
    break;
466
 
  case ROW_RESULT:
467
 
  default:
468
 
    // This case should never be chosen
469
 
    assert(0);
470
 
    field= 0;
471
 
    break;
472
 
  }
473
 
  if (field)
474
 
    field->init(table);
475
 
  return field;
476
 
}
477
 
 
478
 
 
479
 
my_decimal *Item_func::val_decimal(my_decimal *decimal_value)
480
 
{
481
 
  assert(fixed);
482
 
  int2my_decimal(E_DEC_FATAL_ERROR, val_int(), unsigned_flag, decimal_value);
483
 
  return decimal_value;
484
 
}
485
 
 
486
 
 
487
 
bool Item_func::agg_arg_collations(DTCollation &c, Item **items,
488
 
                                   uint32_t nitems, uint32_t flags)
489
 
{
490
 
  return agg_item_collations(c, func_name(), items, nitems, flags, 1);
491
 
}
492
 
 
493
 
 
494
 
bool Item_func::agg_arg_collations_for_comparison(DTCollation &c,
495
 
                                                  Item **items,
496
 
                                                  uint32_t nitems,
497
 
                                                  uint32_t flags)
498
 
{
499
 
  return agg_item_collations_for_comparison(c, func_name(),
500
 
                                            items, nitems, flags);
501
 
}
502
 
 
503
 
 
504
 
bool Item_func::agg_arg_charsets(DTCollation &c, Item **items, uint32_t nitems,
505
 
                                 uint32_t flags, int item_sep)
506
 
{
507
 
  return agg_item_charsets(c, func_name(), items, nitems, flags, item_sep);
508
 
}
509
 
 
510
 
 
511
 
double Item_func::fix_result(double value)
512
 
{
513
 
  if (CMATH_NAMESPACE::isfinite(value))
514
 
    return value;
515
 
  null_value=1;
516
 
  return 0.0;
517
 
}