~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/item_func.cc

  • Committer: Brian Aker
  • Date: 2008-10-08 02:28:58 UTC
  • mfrom: (489.1.13 codestyle)
  • Revision ID: brian@tangent.org-20081008022858-ea8esagkxmn0dupc
Merge of Monty's work.

Show diffs side-by-side

added added

removed removed

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