~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/item/sum.cc

  • Committer: Monty Taylor
  • Date: 2008-12-08 01:15:27 UTC
  • mto: This revision was merged to the branch mainline in revision 670.
  • Revision ID: monty@inaugust.com-20081208011527-lq9m47jsmiiqn999
Replaced my hacked up m4/ac_system_extensions.m4 with the one from gnulib.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
  @brief
21
21
  Sum functions (COUNT, MIN...)
22
22
*/
23
 
#include "config.h"
24
 
#include <math.h>
 
23
#include <drizzled/server_includes.h>
25
24
#include <drizzled/sql_select.h>
26
25
#include <drizzled/error.h>
27
26
#include <drizzled/hybrid_type_traits.h>
30
29
#include <drizzled/sql_base.h>
31
30
 
32
31
#include <drizzled/item/sum.h>
33
 
#include <drizzled/field/decimal.h>
 
32
#include <drizzled/field/fdecimal.h>
34
33
#include <drizzled/field/double.h>
35
34
#include <drizzled/field/int64_t.h>
36
35
#include <drizzled/field/date.h>
 
36
#include <drizzled/field/timetype.h>
37
37
#include <drizzled/field/datetime.h>
38
38
 
39
 
#include "drizzled/internal/m_string.h"
40
 
 
41
 
#include <algorithm>
42
 
 
43
 
using namespace std;
44
 
 
45
 
namespace drizzled
46
 
{
 
39
#include CMATH_H
 
40
 
 
41
#if defined(CMATH_NAMESPACE)
 
42
using namespace CMATH_NAMESPACE;
 
43
#endif
47
44
 
48
45
extern my_decimal decimal_zero;
49
 
extern plugin::StorageEngine *heap_engine;
50
46
 
51
47
/**
52
48
  Prepare an aggregate function item for checking context conditions.
104
100
    If the context conditions are not met the method reports an error.
105
101
    If the set function is aggregated in some outer subquery the method
106
102
    adds it to the chain of items for such set functions that is attached
107
 
    to the the Select_Lex structure for this subquery.
 
103
    to the the st_select_lex structure for this subquery.
108
104
 
109
105
    A number of designated members of the object are used to check the
110
106
    conditions. They are specified in the comment before the Item_sum
255
251
    List_iterator<Item_field> of(outer_fields);
256
252
    while ((field= of++))
257
253
    {
258
 
      Select_Lex *sel= field->cached_table->select_lex;
 
254
      SELECT_LEX *sel= field->cached_table->select_lex;
259
255
      if (sel->nest_level < aggr_level)
260
256
      {
261
257
        if (in_sum_func)
267
263
          in_sum_func->outer_fields.push_back(field);
268
264
        }
269
265
        else
270
 
        {
271
 
          sel->full_group_by_flag.set(NON_AGG_FIELD_USED);
272
 
        }
 
266
          sel->full_group_by_flag|= NON_AGG_FIELD_USED;
273
267
      }
274
268
      if (sel->nest_level > aggr_level &&
275
 
          (sel->full_group_by_flag.test(SUM_FUNC_USED)) &&
276
 
          ! sel->group_list.elements)
 
269
          (sel->full_group_by_flag & SUM_FUNC_USED) &&
 
270
          !sel->group_list.elements)
277
271
      {
278
272
        my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
279
273
                   ER(ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0));
281
275
      }
282
276
    }
283
277
  }
284
 
  aggr_sel->full_group_by_flag.set(SUM_FUNC_USED);
 
278
  aggr_sel->full_group_by_flag|= SUM_FUNC_USED;
285
279
  update_used_tables();
286
280
  session->lex->in_sum_func= in_sum_func;
287
281
  return false;
314
308
 
315
309
bool Item_sum::register_sum_func(Session *session, Item **ref)
316
310
{
317
 
  Select_Lex *sl;
 
311
  SELECT_LEX *sl;
318
312
  nesting_map allow_sum_func= session->lex->allow_sum_func;
319
313
  for (sl= session->lex->current_select->master_unit()->outer_select() ;
320
314
       sl && sl->nest_level > max_arg_level;
356
350
      Mark Item_subselect(s) as containing aggregate function all the way up
357
351
      to aggregate function's calculation context.
358
352
      Note that we must not mark the Item of calculation context itself
359
 
      because with_sum_func on the calculation context Select_Lex is
 
353
      because with_sum_func on the calculation context st_select_lex is
360
354
      already set above.
361
355
 
362
356
      with_sum_func being set for an Item means that this Item refers
364
358
      or through intermediate items to an aggregate function that is calculated
365
359
      in a context "outside" of the Item (e.g. in the current or outer select).
366
360
 
367
 
      with_sum_func being set for an Select_Lex means that this Select_Lex
 
361
      with_sum_func being set for an st_select_lex means that this st_select_lex
368
362
      has aggregate functions directly referenced (i.e. not through a sub-select).
369
363
    */
370
364
    for (sl= session->lex->current_select;
380
374
Item_sum::Item_sum(List<Item> &list) :arg_count(list.elements),
381
375
  forced_const(false)
382
376
{
383
 
  if ((args=(Item**) memory::sql_alloc(sizeof(Item*)*arg_count)))
 
377
  if ((args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
384
378
  {
385
379
    uint32_t i=0;
386
380
    List_iterator_fast<Item> li(list);
418
412
 
419
413
void Item_sum::mark_as_sum_func()
420
414
{
421
 
  Select_Lex *cur_select= current_session->lex->current_select;
 
415
  SELECT_LEX *cur_select= current_session->lex->current_select;
422
416
  cur_select->n_sum_items++;
423
417
  cur_select->with_sum_func= 1;
424
418
  with_sum_func= 1;
425
419
}
426
420
 
427
421
 
428
 
void Item_sum::make_field(SendField *tmp_field)
 
422
void Item_sum::make_field(Send_field *tmp_field)
429
423
{
430
424
  if (args[0]->type() == Item::FIELD_ITEM && keep_field_type())
431
425
  {
503
497
}
504
498
 
505
499
 
506
 
Field *Item_sum::create_tmp_field(bool ,
 
500
Field *Item_sum::create_tmp_field(bool group __attribute__((unused)),
507
501
                                  Table *table,
508
502
                                  uint32_t convert_blob_length)
509
503
{
524
518
                               name, table->s, collation.collation);
525
519
    break;
526
520
  case DECIMAL_RESULT:
527
 
    field= new Field_decimal(max_length, maybe_null, name,
 
521
    field= new Field_new_decimal(max_length, maybe_null, name,
528
522
                                 decimals, unsigned_flag);
529
523
    break;
530
524
  case ROW_RESULT:
728
722
  case DRIZZLE_TYPE_DATE:
729
723
    field= new Field_date(maybe_null, name, collation.collation);
730
724
    break;
 
725
  case DRIZZLE_TYPE_TIME:
 
726
    field= new Field_time(maybe_null, name, collation.collation);
 
727
    break;
731
728
  case DRIZZLE_TYPE_TIMESTAMP:
732
729
  case DRIZZLE_TYPE_DATETIME:
733
730
    field= new Field_datetime(maybe_null, name, collation.collation);
876
873
 
877
874
/***************************************************************************/
878
875
 
 
876
#ifdef __cplusplus
 
877
extern "C" {
 
878
#endif
 
879
 
879
880
/* Declarations for auxilary C-callbacks */
880
881
 
881
882
static int simple_raw_key_cmp(void* arg, const void* key1, const void* key2)
885
886
 
886
887
 
887
888
static int item_sum_distinct_walk(void *element,
888
 
                                  uint32_t ,
 
889
                                  element_count num_of_dups __attribute__((unused)),
889
890
                                  void *item)
890
891
{
891
892
  return ((Item_sum_distinct*) (item))->unique_walk_function(element);
892
893
}
893
894
 
 
895
#ifdef __cplusplus
 
896
}
 
897
#endif
 
898
 
894
899
/* Item_sum_distinct */
895
900
 
896
901
Item_sum_distinct::Item_sum_distinct(Item *item_arg)
979
984
  case DECIMAL_RESULT:
980
985
    val.traits= Hybrid_type_traits_decimal::instance();
981
986
    if (table_field_type != DRIZZLE_TYPE_LONGLONG)
982
 
      table_field_type= DRIZZLE_TYPE_DECIMAL;
 
987
      table_field_type= DRIZZLE_TYPE_NEWDECIMAL;
983
988
    break;
984
989
  case ROW_RESULT:
985
990
  default:
1001
1006
*/
1002
1007
bool Item_sum_distinct::setup(Session *session)
1003
1008
{
1004
 
  List<CreateField> field_list;
1005
 
  CreateField field_def;                              /* field definition */
 
1009
  List<Create_field> field_list;
 
1010
  Create_field field_def;                              /* field definition */
1006
1011
  /* It's legal to call setup() more than once when in a subquery */
1007
1012
  if (tree)
1008
1013
    return(false);
1021
1026
  assert(args[0]->fixed);
1022
1027
 
1023
1028
  field_def.init_for_tmp_table(table_field_type, args[0]->max_length,
1024
 
                               args[0]->decimals, args[0]->maybe_null);
 
1029
                               args[0]->decimals, args[0]->maybe_null,
 
1030
                               args[0]->unsigned_flag);
1025
1031
 
1026
1032
  if (! (table= create_virtual_tmp_table(session, field_list)))
1027
1033
    return(true);
1035
1041
    simple_raw_key_cmp because the table contains numbers only; decimals
1036
1042
    are converted to binary representation as well.
1037
1043
  */
1038
 
  tree= new Unique(simple_raw_key_cmp, &tree_key_length,
1039
 
                   tree_key_length,
1040
 
                   (size_t)session->variables.max_heap_table_size);
 
1044
  tree= new Unique(simple_raw_key_cmp, &tree_key_length, tree_key_length,
 
1045
                   session->variables.max_heap_table_size);
1041
1046
 
1042
1047
  is_evaluated= false;
1043
1048
  return(tree == 0);
1160
1165
    AVG() will divide val by count. We need to reserve digits
1161
1166
    after decimal point as the result can be fractional.
1162
1167
  */
1163
 
  decimals= min(decimals + prec_increment, (unsigned int)NOT_FIXED_DEC);
 
1168
  decimals= cmin(decimals + prec_increment, (unsigned int)NOT_FIXED_DEC);
1164
1169
}
1165
1170
 
1166
1171
 
1222
1227
  if (hybrid_type == DECIMAL_RESULT)
1223
1228
  {
1224
1229
    int precision= args[0]->decimal_precision() + prec_increment;
1225
 
    decimals= min(args[0]->decimals + prec_increment, (unsigned int) DECIMAL_MAX_SCALE);
 
1230
    decimals= cmin(args[0]->decimals + prec_increment, (unsigned int) DECIMAL_MAX_SCALE);
1226
1231
    max_length= my_decimal_precision_to_length(precision, decimals,
1227
1232
                                               unsigned_flag);
1228
 
    f_precision= min(precision+DECIMAL_LONGLONG_DIGITS, DECIMAL_MAX_PRECISION);
 
1233
    f_precision= cmin(precision+DECIMAL_LONGLONG_DIGITS, DECIMAL_MAX_PRECISION);
1229
1234
    f_scale=  args[0]->decimals;
1230
1235
    dec_bin_size= my_decimal_get_binary_size(f_precision, f_scale);
1231
1236
  }
1232
1237
  else {
1233
 
    decimals= min(args[0]->decimals + prec_increment, (unsigned int) NOT_FIXED_DEC);
 
1238
    decimals= cmin(args[0]->decimals + prec_increment, (unsigned int) NOT_FIXED_DEC);
1234
1239
    max_length= args[0]->max_length + prec_increment;
1235
1240
  }
1236
1241
}
1243
1248
 
1244
1249
 
1245
1250
Field *Item_sum_avg::create_tmp_field(bool group, Table *table,
1246
 
                                      uint32_t )
 
1251
                                      uint32_t convert_blob_len __attribute__((unused)))
1247
1252
{
1248
1253
  Field *field;
1249
1254
  if (group)
1258
1263
                               0, name, table->s, &my_charset_bin);
1259
1264
  }
1260
1265
  else if (hybrid_type == DECIMAL_RESULT)
1261
 
    field= new Field_decimal(max_length, maybe_null, name,
1262
 
                             decimals, unsigned_flag);
 
1266
    field= new Field_new_decimal(max_length, maybe_null, name,
 
1267
                                 decimals, unsigned_flag);
1263
1268
  else
1264
1269
    field= new Field_double(max_length, maybe_null, name, decimals, true);
1265
1270
  if (field)
1427
1432
  switch (args[0]->result_type()) {
1428
1433
  case REAL_RESULT:
1429
1434
  case STRING_RESULT:
1430
 
    decimals= min(args[0]->decimals + 4, (int)NOT_FIXED_DEC);
 
1435
    decimals= cmin(args[0]->decimals + 4, NOT_FIXED_DEC);
1431
1436
    break;
1432
1437
  case INT_RESULT:
1433
1438
  case DECIMAL_RESULT:
1434
1439
  {
1435
1440
    int precision= args[0]->decimal_precision()*2 + prec_increment;
1436
 
    decimals= min(args[0]->decimals + prec_increment, (unsigned int) DECIMAL_MAX_SCALE);
 
1441
    decimals= cmin(args[0]->decimals + prec_increment, (unsigned int) DECIMAL_MAX_SCALE);
1437
1442
    max_length= my_decimal_precision_to_length(precision, decimals,
1438
1443
                                               unsigned_flag);
1439
1444
 
1459
1464
  pass around.
1460
1465
*/
1461
1466
Field *Item_sum_variance::create_tmp_field(bool group, Table *table,
1462
 
                                           uint32_t )
 
1467
                                           uint32_t convert_blob_len __attribute__((unused)))
1463
1468
{
1464
1469
  Field *field;
1465
1470
  if (group)
2508
2513
  return 0;
2509
2514
}
2510
2515
 
2511
 
static int count_distinct_walk(void *,
2512
 
                               uint32_t ,
 
2516
#ifdef __cplusplus
 
2517
extern "C" {
 
2518
#endif
 
2519
 
 
2520
static int count_distinct_walk(void *elem __attribute__((unused)),
 
2521
                               element_count count __attribute__((unused)),
2513
2522
                               void *arg)
2514
2523
{
2515
2524
  (*((uint64_t*)arg))++;
2516
2525
  return 0;
2517
2526
}
2518
2527
 
 
2528
#ifdef __cplusplus
 
2529
}
 
2530
#endif
 
2531
 
 
2532
 
 
2533
 
2519
2534
void Item_sum_count_distinct::cleanup()
2520
2535
{
2521
2536
  Item_sum_int::cleanup();
2570
2585
bool Item_sum_count_distinct::setup(Session *session)
2571
2586
{
2572
2587
  List<Item> list;
2573
 
  Select_Lex *select_lex= session->lex->current_select;
 
2588
  SELECT_LEX *select_lex= session->lex->current_select;
2574
2589
 
2575
2590
  /*
2576
2591
    Setup can be called twice for ROLLUP items. This is a bug.
2580
2595
  if (tree || table || tmp_table_param)
2581
2596
    return false;
2582
2597
 
2583
 
  if (!(tmp_table_param= new Tmp_Table_Param))
 
2598
  if (!(tmp_table_param= new TMP_TABLE_PARAM))
2584
2599
    return true;
2585
2600
 
2586
2601
  /* Create a table with an unique key over all parameters */
2603
2618
                                (select_lex->options | session->options),
2604
2619
                                HA_POS_ERROR, (char*)"")))
2605
2620
    return true;
2606
 
  table->cursor->extra(HA_EXTRA_NO_ROWS);               // Don't update rows
 
2621
  table->file->extra(HA_EXTRA_NO_ROWS);         // Don't update rows
2607
2622
  table->no_rows=1;
2608
2623
 
2609
 
  if (table->s->db_type() == heap_engine)
 
2624
  if (table->s->db_type() == heap_hton)
2610
2625
  {
2611
2626
    /*
2612
2627
      No blobs, otherwise it would have been MyISAM: set up a compare
2664
2679
    }
2665
2680
    assert(tree == 0);
2666
2681
    tree= new Unique(compare_key, cmp_arg, tree_key_length,
2667
 
                     (size_t)session->variables.max_heap_table_size);
 
2682
                     session->variables.max_heap_table_size);
2668
2683
    /*
2669
2684
      The only time tree_key_length could be 0 is if someone does
2670
2685
      count(distinct) on a char(0) field - stupid thing to do,
2695
2710
  }
2696
2711
  else if (table)
2697
2712
  {
2698
 
    table->cursor->extra(HA_EXTRA_NO_CACHE);
2699
 
    table->cursor->ha_delete_all_rows();
2700
 
    table->cursor->extra(HA_EXTRA_WRITE_CACHE);
 
2713
    table->file->extra(HA_EXTRA_NO_CACHE);
 
2714
    table->file->ha_delete_all_rows();
 
2715
    table->file->extra(HA_EXTRA_WRITE_CACHE);
2701
2716
  }
2702
2717
}
2703
2718
 
2724
2739
    */
2725
2740
    return tree->unique_add(table->record[0] + table->s->null_bytes);
2726
2741
  }
2727
 
  if ((error= table->cursor->ha_write_row(table->record[0])) &&
2728
 
      table->cursor->is_fatal_error(error, HA_CHECK_DUP))
 
2742
  if ((error= table->file->ha_write_row(table->record[0])) &&
 
2743
      table->file->is_fatal_error(error, HA_CHECK_DUP))
2729
2744
    return true;
2730
2745
  return false;
2731
2746
}
2750
2765
    return (int64_t) count;
2751
2766
  }
2752
2767
 
2753
 
  error= table->cursor->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
 
2768
  error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
2754
2769
 
2755
2770
  if(error)
2756
2771
  {
2757
 
    table->print_error(error, MYF(0));
 
2772
    table->file->print_error(error, MYF(0));
2758
2773
  }
2759
2774
 
2760
 
  return table->cursor->stats.records;
 
2775
  return table->file->stats.records;
2761
2776
}
2762
2777
 
2763
2778
/*****************************************************************************
2820
2835
 
2821
2836
 
2822
2837
/**
2823
 
  function of sort for syntax: GROUP_CONCAT(expr,... ORDER BY col,... )
 
2838
  function of sort for syntax: GROUP_CONCAT(expr,... order_st BY col,... )
2824
2839
*/
2825
2840
 
2826
2841
int group_concat_key_cmp_with_order(void* arg, const void* key1,
2867
2882
  Append data from current leaf to item->result.
2868
2883
*/
2869
2884
 
2870
 
int dump_leaf_key(unsigned char* key, uint32_t ,
 
2885
int dump_leaf_key(unsigned char* key, element_count count __attribute__((unused)),
2871
2886
                  Item_func_group_concat *item)
2872
2887
{
2873
2888
  Table *table= item->table;
2949
2964
                       bool distinct_arg, List<Item> *select_list,
2950
2965
                       SQL_LIST *order_list, String *separator_arg)
2951
2966
  :tmp_table_param(0), warning(0),
2952
 
   separator(separator_arg), tree(NULL), unique_filter(NULL), table(0),
 
2967
   separator(separator_arg), tree(0), unique_filter(NULL), table(0),
2953
2968
   order(0), context(context_arg),
2954
2969
   arg_count_order(order_list ? order_list->elements : 0),
2955
2970
   arg_count_field(select_list->elements),
2970
2985
           (for possible order items in temporare tables)
2971
2986
    order - arg_count_order
2972
2987
  */
2973
 
  if (!(args= (Item**) memory::sql_alloc(sizeof(Item*) * arg_count +
 
2988
  if (!(args= (Item**) sql_alloc(sizeof(Item*) * arg_count +
2974
2989
                                 sizeof(order_st*)*arg_count_order)))
2975
2990
    return;
2976
2991
 
3174
3189
  result.set_charset(collation.collation);
3175
3190
  result_field= 0;
3176
3191
  null_value= 1;
3177
 
  max_length= (size_t)session->variables.group_concat_max_len;
 
3192
  max_length= session->variables.group_concat_max_len;
 
3193
 
 
3194
  uint32_t offset;
 
3195
  if (separator->needs_conversion(separator->length(), separator->charset(),
 
3196
                                  collation.collation, &offset))
 
3197
  {
 
3198
    uint32_t buflen= collation.collation->mbmaxlen * separator->length();
 
3199
    uint32_t errors, conv_length;
 
3200
    char *buf;
 
3201
    String *new_separator;
 
3202
 
 
3203
    if (!(buf= (char*) session->alloc(buflen)) ||
 
3204
        !(new_separator= new(session->mem_root)
 
3205
                           String(buf, buflen, collation.collation)))
 
3206
      return true;
 
3207
 
 
3208
    conv_length= copy_and_convert(buf, buflen, collation.collation,
 
3209
                                  separator->ptr(), separator->length(),
 
3210
                                  separator->charset(), &errors);
 
3211
    new_separator->length(conv_length);
 
3212
    separator= new_separator;
 
3213
  }
3178
3214
 
3179
3215
  if (check_sum_func(session, ref))
3180
3216
    return true;
3187
3223
bool Item_func_group_concat::setup(Session *session)
3188
3224
{
3189
3225
  List<Item> list;
3190
 
  Select_Lex *select_lex= session->lex->current_select;
 
3226
  SELECT_LEX *select_lex= session->lex->current_select;
3191
3227
 
3192
3228
  /*
3193
3229
    Currently setup() can be called twice. Please add
3196
3232
  if (table || tree)
3197
3233
    return(false);
3198
3234
 
3199
 
  if (!(tmp_table_param= new Tmp_Table_Param))
 
3235
  if (!(tmp_table_param= new TMP_TABLE_PARAM))
3200
3236
    return(true);
3201
3237
 
3202
3238
  /* We'll convert all blobs to varchar fields in the temporary table */
3237
3273
  {
3238
3274
    /*
3239
3275
      Currently we have to force conversion of BLOB values to VARCHAR's
3240
 
      if we are to store them in TREE objects used for ORDER BY and
 
3276
      if we are to store them in TREE objects used for order_st BY and
3241
3277
      DISTINCT. This leads to truncation if the BLOB's size exceeds
3242
3278
      Field_varstring::MAX_SIZE.
3243
3279
    */
3249
3285
    We have to create a temporary table to get descriptions of fields
3250
3286
    (types, sizes and so on).
3251
3287
 
3252
 
    Note that in the table, we first have the ORDER BY fields, then the
 
3288
    Note that in the table, we first have the order_st BY fields, then the
3253
3289
    field list.
3254
3290
  */
3255
3291
  if (!(table= create_tmp_table(session, tmp_table_param, all_fields,
3257
3293
                                (select_lex->options | session->options),
3258
3294
                                HA_POS_ERROR, (char*) "")))
3259
3295
    return(true);
3260
 
  table->cursor->extra(HA_EXTRA_NO_ROWS);
 
3296
  table->file->extra(HA_EXTRA_NO_ROWS);
3261
3297
  table->no_rows= 1;
3262
3298
 
3263
3299
  /*
3272
3308
    tree= &tree_base;
3273
3309
    /*
3274
3310
      Create a tree for sorting. The tree is used to sort (according to the
3275
 
      syntax of this function). If there is no ORDER BY clause, we don't
 
3311
      syntax of this function). If there is no order_st BY clause, we don't
3276
3312
      create this tree.
3277
3313
    */
3278
 
    init_tree(tree, (uint32_t) min(session->variables.max_heap_table_size,
3279
 
                                   (uint64_t)(session->variables.sortbuff_size/16)), 
3280
 
              0,
 
3314
    init_tree(tree, (uint) cmin(session->variables.max_heap_table_size,
 
3315
                               session->variables.sortbuff_size/16), 0,
3281
3316
              tree_key_length,
3282
 
              group_concat_key_cmp_with_order , false, NULL, (void*) this);
 
3317
              group_concat_key_cmp_with_order , 0, NULL, (void*) this);
3283
3318
  }
3284
3319
 
3285
3320
  if (distinct)
3286
3321
    unique_filter= new Unique(group_concat_key_cmp_with_distinct,
3287
3322
                              (void*)this,
3288
3323
                              tree_key_length,
3289
 
                              (size_t)session->variables.max_heap_table_size);
 
3324
                              session->variables.max_heap_table_size);
3290
3325
 
3291
3326
  return(false);
3292
3327
}
3303
3338
  tree= 0;
3304
3339
}
3305
3340
 
3306
 
double Item_func_group_concat::val_real()
3307
 
{
3308
 
  String *res;  res=val_str(&str_value);
3309
 
  return res ? internal::my_atof(res->c_ptr()) : 0.0;
3310
 
}
3311
 
 
3312
 
int64_t Item_func_group_concat::val_int()
3313
 
{
3314
 
  String *res;
3315
 
  char *end_ptr;
3316
 
  int error;
3317
 
  if (!(res= val_str(&str_value)))
3318
 
    return (int64_t) 0;
3319
 
  end_ptr= (char*) res->ptr()+ res->length();
3320
 
  return internal::my_strtoll10(res->ptr(), &end_ptr, &error);
3321
 
}
3322
 
 
3323
 
String* Item_func_group_concat::val_str(String* )
 
3341
 
 
3342
String* Item_func_group_concat::val_str(String* str __attribute__((unused)))
3324
3343
{
3325
3344
  assert(fixed == 1);
3326
3345
  if (null_value)
3380
3399
  if (!original && unique_filter)
3381
3400
    delete unique_filter;
3382
3401
}
3383
 
 
3384
 
} /* namespace drizzled */