~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/optimizer/sum.cc

Big merge.

Show diffs side-by-side

added added

removed removed

Lines of Context:
60
60
namespace drizzled
61
61
{
62
62
 
63
 
static bool find_key_for_maxmin(bool max_fl, 
64
 
                                table_reference_st *ref, 
 
63
static bool find_key_for_maxmin(bool max_fl,
 
64
                                table_reference_st *ref,
65
65
                                Field* field,
66
 
                                COND *cond, 
 
66
                                COND *cond,
67
67
                                uint32_t *range_fl,
68
68
                                uint32_t *key_prefix_length);
69
69
 
70
 
static int reckey_in_range(bool max_fl, 
71
 
                           table_reference_st *ref, 
 
70
static int reckey_in_range(bool max_fl,
 
71
                           table_reference_st *ref,
72
72
                           Field* field,
73
 
                           COND *cond, 
74
 
                           uint32_t range_fl, 
 
73
                           COND *cond,
 
74
                           uint32_t range_fl,
75
75
                           uint32_t prefix_len);
76
76
 
77
 
static int maxmin_in_range(bool max_fl, Field* field, COND *cond);
 
77
static int maxmin_in_range(bool max_fl, Field *field, COND *cond);
78
78
 
79
79
 
80
80
/*
92
92
    UINT64_MAX  Error: Could not calculate number of rows
93
93
    #                   Multiplication of number of rows in all tables
94
94
*/
95
 
 
96
95
static uint64_t get_exact_record_count(TableList *tables)
97
96
{
98
97
  uint64_t count= 1;
115
114
  int const_result= 1;
116
115
  bool recalc_const_item= false;
117
116
  uint64_t count= 1;
118
 
  bool is_exact_count= true; 
 
117
  bool is_exact_count= true;
119
118
  bool maybe_exact_count= true;
120
119
  table_map removed_tables= 0;
121
120
  table_map outer_tables= 0;
122
121
  table_map used_tables= 0;
123
122
  table_map where_tables= 0;
124
 
  Item *item;
 
123
  Item *item= NULL;
125
124
  int error;
126
125
 
127
126
  if (conds)
135
134
   */
136
135
  for (TableList *tl= tables; tl; tl= tl->next_leaf)
137
136
  {
138
 
    TableList *embedded;
139
 
    for (embedded= tl ; embedded; embedded= embedded->embedding)
 
137
    TableList *embedded= NULL;
 
138
    for (embedded= tl; embedded; embedded= embedded->embedding)
140
139
    {
141
140
      if (embedded->on_expr)
142
141
        break;
195
194
    if (item->type() == Item::SUM_FUNC_ITEM)
196
195
    {
197
196
      Item_sum *item_sum= (((Item_sum*) item));
198
 
      switch (item_sum->sum_func()) 
 
197
      switch (item_sum->sum_func())
199
198
      {
200
199
        case Item_sum::COUNT_FUNC:
201
200
          /*
250
249
                 Type of range for the key part for this field will be
251
250
                 returned in range_fl.
252
251
               */
253
 
              if (table->cursor->inited || 
 
252
              if (table->cursor->inited ||
254
253
                  (outer_tables & table->map) ||
255
 
                  ! find_key_for_maxmin(0, 
256
 
                                        &ref, 
257
 
                                        item_field->field, 
 
254
                  ! find_key_for_maxmin(0,
 
255
                                        &ref,
 
256
                                        item_field->field,
258
257
                                        conds,
259
 
                                        &range_fl, 
 
258
                                        &range_fl,
260
259
                                        &prefix_len))
261
260
              {
262
261
                const_result= 0;
285
284
                   nullable column, test if there is an exact match for the key.
286
285
                 */
287
286
                if (! (range_fl & NEAR_MIN))
 
287
                {
288
288
                  /*
289
289
                     Closed interval: Either The MIN argument is non-nullable, or
290
290
                     we have a >= predicate for the MIN argument.
293
293
                                                       ref.key_buff,
294
294
                                                       make_prev_keypart_map(ref.key_parts),
295
295
                                                       HA_READ_KEY_OR_NEXT);
 
296
                }
296
297
                else
297
298
                {
298
299
                  /*
335
336
                }
336
337
              }
337
338
              /* Verify that the read tuple indeed matches the search key */
338
 
              if (! error && 
339
 
                  reckey_in_range(0, 
340
 
                                  &ref, 
 
339
              if (! error &&
 
340
                  reckey_in_range(0,
 
341
                                  &ref,
341
342
                                  item_field->field,
342
 
                                  conds, 
343
 
                                  range_fl, 
 
343
                                  conds,
 
344
                                  range_fl,
344
345
                                  prefix_len))
345
346
              {
346
347
                error= HA_ERR_KEY_NOT_FOUND;
416
417
                 Type of range for the key part for this field will be
417
418
                 returned in range_fl.
418
419
               */
419
 
              if (table->cursor->inited || 
 
420
              if (table->cursor->inited ||
420
421
                  (outer_tables & table->map) ||
421
 
                  ! find_key_for_maxmin(1, 
422
 
                                        &ref, 
423
 
                                        item_field->field, 
 
422
                  ! find_key_for_maxmin(1,
 
423
                                        &ref,
 
424
                                        item_field->field,
424
425
                                        conds,
425
 
                                        &range_fl, 
 
426
                                        &range_fl,
426
427
                                        &prefix_len))
427
428
              {
428
429
                const_result= 0;
436
437
              }
437
438
              else
438
439
              {
439
 
                error= table->cursor->index_read_map(table->record[0], 
 
440
                error= table->cursor->index_read_map(table->record[0],
440
441
                                                     key_buff,
441
442
                                                     make_prev_keypart_map(ref.key_parts),
442
443
                                                     range_fl & NEAR_MAX ?
443
444
                                                     HA_READ_BEFORE_KEY :
444
445
                                                     HA_READ_PREFIX_LAST_OR_PREV);
445
446
              }
446
 
              if (! error && 
447
 
                  reckey_in_range(1, 
448
 
                                  &ref, 
 
447
              if (! error &&
 
448
                  reckey_in_range(1,
 
449
                                  &ref,
449
450
                                  item_field->field,
450
 
                                  conds, 
451
 
                                  range_fl, 
 
451
                                  conds,
 
452
                                  range_fl,
452
453
                                  prefix_len))
453
454
              {
454
455
                error= HA_ERR_KEY_NOT_FOUND;
530
531
}
531
532
 
532
533
 
533
 
bool optimizer::simple_pred(Item_func *func_item, Item **args, bool *inv_order)
 
534
bool optimizer::simple_pred(Item_func *func_item, Item **args, bool &inv_order)
534
535
{
535
536
  Item *item= NULL;
536
 
  *inv_order= 0;
537
 
  switch (func_item->argument_count()) {
 
537
  inv_order= false;
 
538
  switch (func_item->argument_count())
 
539
  {
538
540
  case 0:
539
541
    /* MULT_EQUAL_FUNC */
540
542
    {
582
584
        return 0;
583
585
      }
584
586
      args[0]= item;
585
 
      *inv_order= 1;
 
587
      inv_order= true;
586
588
    }
587
589
    else
588
590
    {
643
645
  @retval
644
646
    1        We can use index to get MIN/MAX value
645
647
*/
646
 
 
647
 
static bool matching_cond(bool max_fl, 
648
 
                          table_reference_st *ref, 
 
648
static bool matching_cond(bool max_fl,
 
649
                          table_reference_st *ref,
649
650
                          KEY *keyinfo,
650
 
                          KEY_PART_INFO *field_part, 
 
651
                          KEY_PART_INFO *field_part,
651
652
                          COND *cond,
652
 
                          key_part_map *key_part_used, 
 
653
                          key_part_map *key_part_used,
653
654
                          uint32_t *range_fl,
654
655
                          uint32_t *prefix_len)
655
656
{
678
679
    Item *item;
679
680
    while ((item= li++))
680
681
    {
681
 
      if (! matching_cond(max_fl, 
682
 
                          ref, 
683
 
                          keyinfo, 
684
 
                          field_part, 
 
682
      if (! matching_cond(max_fl,
 
683
                          ref,
 
684
                          keyinfo,
 
685
                          field_part,
685
686
                          item,
686
 
                          key_part_used, 
687
 
                          range_fl, 
 
687
                          key_part_used,
 
688
                          range_fl,
688
689
                          prefix_len))
689
690
      {
690
691
        return 0;
704
705
  bool is_null= false;
705
706
  bool between= false;
706
707
 
707
 
  switch (((Item_func*) cond)->functype()) 
 
708
  switch (((Item_func*) cond)->functype())
708
709
  {
709
710
  case Item_func::ISNULL_FUNC:
710
711
    is_null= 1;     /* fall through */
735
736
  bool inv;
736
737
 
737
738
  /* Test if this is a comparison of a field and constant */
738
 
  if (! optimizer::simple_pred((Item_func*) cond, args, &inv))
 
739
  if (! optimizer::simple_pred((Item_func*) cond, args, inv))
739
740
  {
740
741
    return 0;
741
742
  }
894
895
    1   Can use key to optimize MIN()/MAX().
895
896
    In this case ref, range_fl and prefix_len are updated
896
897
*/
897
 
 
898
 
 
899
 
static bool find_key_for_maxmin(bool max_fl, 
 
898
static bool find_key_for_maxmin(bool max_fl,
900
899
                                table_reference_st *ref,
901
 
                                Field* field, 
 
900
                                Field* field,
902
901
                                COND *cond,
903
 
                                uint32_t *range_fl, 
 
902
                                uint32_t *range_fl,
904
903
                                uint32_t *prefix_len)
905
904
{
906
905
  if (! (field->flags & PART_KEY_FLAG))
955
954
        ref->key_parts= 0;
956
955
        key_part_map key_part_used= 0;
957
956
        *range_fl= NO_MIN_RANGE | NO_MAX_RANGE;
958
 
        if (matching_cond(max_fl, 
959
 
                          ref, 
960
 
                          keyinfo, 
961
 
                          part, 
 
957
        if (matching_cond(max_fl,
 
958
                          ref,
 
959
                          keyinfo,
 
960
                          part,
962
961
                          cond,
963
 
                          &key_part_used, 
964
 
                          range_fl, 
 
962
                          &key_part_used,
 
963
                          range_fl,
965
964
                          prefix_len) &&
966
965
            ! (key_part_to_use & ~key_part_used))
967
966
        {
1022
1021
  @retval
1023
1022
    1        WHERE was not true for the found row
1024
1023
*/
1025
 
static int reckey_in_range(bool max_fl, 
1026
 
                           table_reference_st *ref, 
 
1024
static int reckey_in_range(bool max_fl,
 
1025
                           table_reference_st *ref,
1027
1026
                           Field* field,
1028
 
                           COND *cond, 
1029
 
                           uint32_t range_fl, 
 
1027
                           COND *cond,
 
1028
                           uint32_t range_fl,
1030
1029
                           uint32_t prefix_len)
1031
1030
{
1032
1031
  if (key_cmp_if_same(field->table, ref->key_buff, ref->key, prefix_len))
1075
1074
    return 0;
1076
1075
  }
1077
1076
  bool less_fl= false;
1078
 
  switch (((Item_func*) cond)->functype()) 
 
1077
  switch (((Item_func*) cond)->functype())
1079
1078
  {
1080
1079
  case Item_func::BETWEEN:
1081
1080
    return cond->val_int() == 0;                // Return 1 if WHERE is false