~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_select.cc

  • Committer: Brian Aker
  • Date: 2010-12-07 09:12:12 UTC
  • mto: This revision was merged to the branch mainline in revision 1985.
  • Revision ID: brian@tangent.org-20101207091212-1m0w20tck6z7632m
This is a fix for bug lp:686197

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
  @file
18
18
 
19
19
  @brief
20
 
  select_query and join optimization
 
20
  mysql_select and join optimization
21
21
 
22
22
  @defgroup Query_Optimizer  Query Optimizer
23
23
  @{
52
52
#include "drizzled/records.h"
53
53
#include "drizzled/internal/iocache.h"
54
54
#include "drizzled/drizzled.h"
55
 
#include "drizzled/plugin/storage_engine.h"
56
55
 
57
56
#include "drizzled/sql_union.h"
58
57
#include "drizzled/optimizer/key_field.h"
79
78
static Item* part_of_refkey(Table *form,Field *field);
80
79
static bool cmp_buffer_with_ref(JoinTable *tab);
81
80
static void change_cond_ref_to_const(Session *session,
82
 
                                     list<COND_CMP>& save_list,
 
81
                                     vector<COND_CMP>& save_list,
83
82
                                     Item *and_father,
84
83
                                     Item *cond,
85
84
                                     Item *field,
132
131
    unit->set_limit(unit->global_parameters);
133
132
    session->session_marker= 0;
134
133
    /*
135
 
      'options' of select_query will be set in JOIN, as far as JOIN for
 
134
      'options' of mysql_select will be set in JOIN, as far as JOIN for
136
135
      every PS/SP execution new, we will not need reset this flag if
137
136
      setup_tables_done_option changed for next rexecution
138
137
    */
139
 
    res= select_query(session,
140
 
                      &select_lex->ref_pointer_array,
 
138
    res= mysql_select(session, &select_lex->ref_pointer_array,
141
139
                      (TableList*) select_lex->table_list.first,
142
 
                      select_lex->with_wild,
143
 
                      select_lex->item_list,
 
140
                      select_lex->with_wild, select_lex->item_list,
144
141
                      select_lex->where,
145
142
                      select_lex->order_list.elements +
146
143
                      select_lex->group_list.elements,
271
268
 
272
269
/*****************************************************************************
273
270
  Check fields, find best join, do the select and output fields.
274
 
  select_query assumes that all tables are already opened
 
271
  mysql_select assumes that all tables are already opened
275
272
*****************************************************************************/
276
273
 
277
274
/*
351
348
  @retval
352
349
    true   an error
353
350
*/
354
 
bool select_query(Session *session,
 
351
bool mysql_select(Session *session,
355
352
                  Item ***rref_pointer_array,
356
353
                  TableList *tables, 
357
354
                  uint32_t wild_num, 
573
570
  sz= sizeof(optimizer::KeyField) *
574
571
      (((session->lex->current_select->cond_count+1)*2 +
575
572
        session->lex->current_select->between_count)*m+1);
576
 
  if (! (key_fields= (optimizer::KeyField*) session->getMemRoot()->allocate(sz)))
 
573
  if (! (key_fields= (optimizer::KeyField*) session->alloc(sz)))
577
574
    return true;
578
575
  and_level= 0;
579
576
  field= end= key_fields;
932
929
 
933
930
  /*
934
931
    we should restore old value of count_cuted_fields because
935
 
    store_val_in_field can be called from insert_query
 
932
    store_val_in_field can be called from mysql_insert
936
933
    with select_insert, which make count_cuted_fields= 1
937
934
   */
938
935
  enum_check_fields old_count_cuted_fields= session->count_cuted_fields;
1005
1002
  j->ref.key_length=length;
1006
1003
  j->ref.key=(int) key;
1007
1004
  if (!(j->ref.key_buff= (unsigned char*) session->calloc(ALIGN_SIZE(length)*2)) ||
1008
 
      !(j->ref.key_copy= (StoredKey**) session->getMemRoot()->allocate((sizeof(StoredKey*) *
 
1005
      !(j->ref.key_copy= (StoredKey**) session->alloc((sizeof(StoredKey*) *
1009
1006
               (keyparts+1)))) ||
1010
 
      !(j->ref.items=    (Item**) session->getMemRoot()->allocate(sizeof(Item*)*keyparts)) ||
1011
 
      !(j->ref.cond_guards= (bool**) session->getMemRoot()->allocate(sizeof(uint*)*keyparts)))
 
1007
      !(j->ref.items=    (Item**) session->alloc(sizeof(Item*)*keyparts)) ||
 
1008
      !(j->ref.cond_guards= (bool**) session->alloc(sizeof(uint*)*keyparts)))
1012
1009
  {
1013
1010
    return(true);
1014
1011
  }
2308
2305
  @param cond       condition whose multiple equalities are to be checked
2309
2306
  @param table      constant table that has been read
2310
2307
*/
2311
 
void update_const_equal_items(COND *cond, JoinTable *tab)
 
2308
static void update_const_equal_items(COND *cond, JoinTable *tab)
2312
2309
{
2313
2310
  if (!(cond->used_tables() & tab->table->map))
2314
2311
    return;
2365
2362
  and_level
2366
2363
*/
2367
2364
static void change_cond_ref_to_const(Session *session,
2368
 
                                     list<COND_CMP>& save_list,
 
2365
                                     vector<COND_CMP>& save_list,
2369
2366
                                     Item *and_father,
2370
2367
                                     Item *cond,
2371
2368
                                     Item *field,
2378
2375
    Item *item;
2379
2376
    while ((item=li++))
2380
2377
      change_cond_ref_to_const(session, save_list, and_level ? cond : item, item, field, value);
2381
 
 
2382
2378
    return;
2383
2379
  }
2384
2380
  if (cond->eq_cmp_result() == Item::COND_OK)
2471
2467
}
2472
2468
 
2473
2469
static void propagate_cond_constants(Session *session, 
2474
 
                                     list<COND_CMP>& save_list, 
 
2470
                                     vector<COND_CMP>& save_list, 
2475
2471
                                     COND *and_father, 
2476
2472
                                     COND *cond)
2477
2473
{
2480
2476
    bool and_level= ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC;
2481
2477
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
2482
2478
    Item *item;
2483
 
    list<COND_CMP> save;
 
2479
    vector<COND_CMP> save;
2484
2480
    while ((item=li++))
2485
2481
    {
2486
2482
      propagate_cond_constants(session, save, and_level ? cond : item, item);
2488
2484
    if (and_level)
2489
2485
    {
2490
2486
      // Handle other found items
2491
 
      for (list<COND_CMP>::iterator iter= save.begin(); iter != save.end(); ++iter)
 
2487
      for (vector<COND_CMP>::iterator iter= save.begin(); iter != save.end(); ++iter)
2492
2488
      {
2493
 
        Item **args= iter->second->arguments();
2494
 
        if (not args[0]->const_item())
 
2489
        Item **args= iter->cmp_func->arguments();
 
2490
        if (!args[0]->const_item())
2495
2491
        {
2496
 
          change_cond_ref_to_const(session, save, iter->first,
2497
 
                                   iter->first, args[0], args[1] );
 
2492
          change_cond_ref_to_const( session, save, iter->and_level,
 
2493
                                    iter->and_level, args[0], args[1] );
2498
2494
        }
2499
2495
      }
2500
2496
    }
2607
2603
         position:
2608
2604
          1. join->cur_embedding_map - bitmap of pairs of brackets (aka nested
2609
2605
             joins) we've opened but didn't close.
2610
 
          2. {each NestedJoin class not simplified away}->counter - number
 
2606
          2. {each nested_join_st structure not simplified away}->counter - number
2611
2607
             of this nested join's children that have already been added to to
2612
2608
             the partial join order.
2613
2609
  @endverbatim
2685
2681
                             &join->cond_equal);
2686
2682
 
2687
2683
    /* change field = field to field = const for each found field = const */
2688
 
    list<COND_CMP> temp;
 
2684
    vector<COND_CMP> temp;
2689
2685
    propagate_cond_constants(session, temp, conds, conds);
2690
2686
    /*
2691
2687
      Remove all instances of item == item
3054
3050
    table->emptyRecord();
3055
3051
    if (table->group && join->tmp_table_param.sum_func_count &&
3056
3052
        table->getShare()->sizeKeys() && !table->cursor->inited)
3057
 
    {
3058
 
      int tmp_error;
3059
 
      tmp_error= table->cursor->startIndexScan(0, 0);
3060
 
      if (tmp_error != 0)
3061
 
      {
3062
 
        table->print_error(tmp_error, MYF(0));
3063
 
        return -1;
3064
 
      }
3065
 
    }
 
3053
      table->cursor->startIndexScan(0, 0);
3066
3054
  }
3067
3055
  /* Set up select_end */
3068
3056
  Next_select_func end_select= setup_end_select_func(join);
3368
3356
  return 0;
3369
3357
}
3370
3358
 
 
3359
int join_read_const_table(JoinTable *tab, optimizer::Position *pos)
 
3360
{
 
3361
  int error;
 
3362
  Table *table=tab->table;
 
3363
  table->const_table=1;
 
3364
  table->null_row=0;
 
3365
  table->status=STATUS_NO_RECORD;
 
3366
 
 
3367
  if (tab->type == AM_SYSTEM)
 
3368
  {
 
3369
    if ((error=join_read_system(tab)))
 
3370
    {                                           // Info for DESCRIBE
 
3371
      tab->info="const row not found";
 
3372
      /* Mark for EXPLAIN that the row was not found */
 
3373
      pos->setFanout(0.0);
 
3374
      pos->clearRefDependMap();
 
3375
      if (! table->maybe_null || error > 0)
 
3376
        return(error);
 
3377
    }
 
3378
  }
 
3379
  else
 
3380
  {
 
3381
    if (! table->key_read && 
 
3382
        table->covering_keys.test(tab->ref.key) && 
 
3383
        ! table->no_keyread &&
 
3384
        (int) table->reginfo.lock_type <= (int) TL_READ_WITH_SHARED_LOCKS)
 
3385
    {
 
3386
      table->key_read=1;
 
3387
      table->cursor->extra(HA_EXTRA_KEYREAD);
 
3388
      tab->index= tab->ref.key;
 
3389
    }
 
3390
    error=join_read_const(tab);
 
3391
    if (table->key_read)
 
3392
    {
 
3393
      table->key_read=0;
 
3394
      table->cursor->extra(HA_EXTRA_NO_KEYREAD);
 
3395
    }
 
3396
    if (error)
 
3397
    {
 
3398
      tab->info="unique row not found";
 
3399
      /* Mark for EXPLAIN that the row was not found */
 
3400
      pos->setFanout(0.0);
 
3401
      pos->clearRefDependMap();
 
3402
      if (!table->maybe_null || error > 0)
 
3403
        return(error);
 
3404
    }
 
3405
  }
 
3406
  if (*tab->on_expr_ref && !table->null_row)
 
3407
  {
 
3408
    if ((table->null_row= test((*tab->on_expr_ref)->val_int() == 0)))
 
3409
      table->mark_as_null_row();
 
3410
  }
 
3411
  if (!table->null_row)
 
3412
    table->maybe_null=0;
 
3413
 
 
3414
  /* Check appearance of new constant items in Item_equal objects */
 
3415
  Join *join= tab->join;
 
3416
  if (join->conds)
 
3417
    update_const_equal_items(join->conds, tab);
 
3418
  TableList *tbl;
 
3419
  for (tbl= join->select_lex->leaf_tables; tbl; tbl= tbl->next_leaf)
 
3420
  {
 
3421
    TableList *embedded;
 
3422
    TableList *embedding= tbl;
 
3423
    do
 
3424
    {
 
3425
      embedded= embedding;
 
3426
      if (embedded->on_expr)
 
3427
         update_const_equal_items(embedded->on_expr, tab);
 
3428
      embedding= embedded->getEmbedding();
 
3429
    }
 
3430
    while (embedding &&
 
3431
           embedding->getNestedJoin()->join_list.head() == embedded);
 
3432
  }
 
3433
 
 
3434
  return(0);
 
3435
}
 
3436
 
 
3437
int join_read_system(JoinTable *tab)
 
3438
{
 
3439
  Table *table= tab->table;
 
3440
  int error;
 
3441
  if (table->status & STATUS_GARBAGE)           // If first read
 
3442
  {
 
3443
    if ((error=table->cursor->read_first_row(table->getInsertRecord(),
 
3444
                                           table->getShare()->getPrimaryKey())))
 
3445
    {
 
3446
      if (error != HA_ERR_END_OF_FILE)
 
3447
        return table->report_error(error);
 
3448
      tab->table->mark_as_null_row();
 
3449
      table->emptyRecord();                     // Make empty record
 
3450
      return -1;
 
3451
    }
 
3452
    table->storeRecord();
 
3453
  }
 
3454
  else if (!table->status)                      // Only happens with left join
 
3455
    table->restoreRecord();                     // restore old record
 
3456
  table->null_row=0;
 
3457
  return table->status ? -1 : 0;
 
3458
}
 
3459
 
3371
3460
/**
3372
3461
  Read a (constant) table when there is at most one matching row.
3373
3462
 
3439
3528
 
3440
3529
  if (!table->cursor->inited)
3441
3530
  {
3442
 
    error= table->cursor->startIndexScan(tab->ref.key, tab->sorted);
3443
 
    if (error != 0)
3444
 
    {
3445
 
      table->print_error(error, MYF(0));
3446
 
    }
 
3531
    table->cursor->startIndexScan(tab->ref.key, tab->sorted);
3447
3532
  }
3448
3533
 
3449
3534
  /* TODO: Why don't we do "Late NULLs Filtering" here? */
3491
3576
 
3492
3577
  /* Initialize the index first */
3493
3578
  if (!table->cursor->inited)
3494
 
  {
3495
 
    error= table->cursor->startIndexScan(tab->ref.key, tab->sorted);
3496
 
    if (error != 0)
3497
 
      return table->report_error(error);
3498
 
  }
 
3579
    table->cursor->startIndexScan(tab->ref.key, tab->sorted);
3499
3580
 
3500
3581
  /* Perform "Late NULLs Filtering" (see internals manual for explanations) */
3501
3582
  for (uint32_t i= 0 ; i < tab->ref.key_parts ; i++)
3529
3610
  Table *table= tab->table;
3530
3611
 
3531
3612
  if (!table->cursor->inited)
3532
 
  {
3533
 
    error= table->cursor->startIndexScan(tab->ref.key, tab->sorted);
3534
 
    if (error != 0)
3535
 
      return table->report_error(error);
3536
 
  }
 
3613
    table->cursor->startIndexScan(tab->ref.key, tab->sorted);
3537
3614
  if (cp_buffer_from_ref(tab->join->session, &tab->ref))
3538
3615
    return -1;
3539
3616
  if ((error=table->cursor->index_read_last_map(table->getInsertRecord(),
3648
3725
  if (tab->select && tab->select->quick && tab->select->quick->reset())
3649
3726
    return 1;
3650
3727
 
3651
 
  if (tab->read_record.init_read_record(tab->join->session, tab->table, tab->select, 1, true))
3652
 
    return 1;
 
3728
  tab->read_record.init_read_record(tab->join->session, tab->table, tab->select, 1, true);
3653
3729
 
3654
3730
  return (*tab->read_record.read_record)(&tab->read_record);
3655
3731
}
3682
3758
  }
3683
3759
 
3684
3760
  if (!table->cursor->inited)
3685
 
  {
3686
 
    error= table->cursor->startIndexScan(tab->index, tab->sorted);
3687
 
    if (error != 0)
3688
 
    {
3689
 
      table->report_error(error);
3690
 
      return -1;
3691
 
    }
3692
 
  }
 
3761
    table->cursor->startIndexScan(tab->index, tab->sorted);
3693
3762
  if ((error=tab->table->cursor->index_first(tab->table->getInsertRecord())))
3694
3763
  {
3695
3764
    if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
3748
3817
  tab->read_record.index=tab->index;
3749
3818
  tab->read_record.record=table->getInsertRecord();
3750
3819
  if (!table->cursor->inited)
3751
 
  {
3752
 
    error= table->cursor->startIndexScan(tab->index, 1);
3753
 
    if (error != 0)
3754
 
      return table->report_error(error);
3755
 
  }
 
3820
    table->cursor->startIndexScan(tab->index, 1);
3756
3821
  if ((error= tab->table->cursor->index_last(tab->table->getInsertRecord())))
3757
3822
    return table->report_error(error);
3758
3823
 
3832
3897
              error=join->result->send_data(*join->fields) ? 1 : 0;
3833
3898
            join->send_records++;
3834
3899
          }
3835
 
          if (join->rollup.getState() != Rollup::STATE_NONE && error <= 0)
 
3900
          if (join->rollup.state != ROLLUP::STATE_NONE && error <= 0)
3836
3901
          {
3837
3902
            if (join->rollup_send_data((uint32_t) (idx+1)))
3838
3903
              error= 1;
3922
3987
            return NESTED_LOOP_ERROR;
3923
3988
          }
3924
3989
        }
3925
 
        if (join->rollup.getState() != Rollup::STATE_NONE)
 
3990
        if (join->rollup.state != ROLLUP::STATE_NONE)
3926
3991
        {
3927
3992
          if (join->rollup_write_data((uint32_t) (idx+1), table))
3928
3993
            return NESTED_LOOP_ERROR;
5031
5096
  org_record=(char*) (record=table->getInsertRecord())+offset;
5032
5097
  new_record=(char*) table->getUpdateRecord()+offset;
5033
5098
 
5034
 
  if ((error= cursor->startTableScan(1)))
5035
 
    goto err;
5036
 
 
 
5099
  cursor->startTableScan(1);
5037
5100
  error=cursor->rnd_next(record);
5038
5101
  for (;;)
5039
5102
  {
5150
5213
    return(1);
5151
5214
  }
5152
5215
 
5153
 
  if ((error= cursor->startTableScan(1)))
5154
 
    goto err;
5155
 
 
 
5216
  cursor->startTableScan(1);
5156
5217
  key_pos= &key_buffer[0];
5157
5218
  for (;;)
5158
5219
  {
5364
5425
    if (!count || count > fields.elements)
5365
5426
    {
5366
5427
      my_error(ER_BAD_FIELD_ERROR, MYF(0),
5367
 
               order_item->full_name(), session->where());
 
5428
               order_item->full_name(), session->where);
5368
5429
      return true;
5369
5430
    }
5370
5431
    order->item= ref_pointer_array + count - 1;
5441
5502
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_NON_UNIQ_ERROR,
5442
5503
                          ER(ER_NON_UNIQ_ERROR),
5443
5504
                          ((Item_ident*) order_item)->field_name,
5444
 
                          session->where());
 
5505
                          session->where);
5445
5506
    }
5446
5507
  }
5447
5508
 
5483
5544
                List<Item> &all_fields,
5484
5545
                Order *order)
5485
5546
{
5486
 
  session->setWhere("order clause");
 
5547
  session->where="order clause";
5487
5548
  for (; order; order=order->next)
5488
5549
  {
5489
5550
    if (find_order_in_list(session, ref_pointer_array, tables, order, fields,
5534
5595
 
5535
5596
  uint32_t org_fields=all_fields.elements;
5536
5597
 
5537
 
  session->setWhere("group statement");
 
5598
  session->where="group statement";
5538
5599
  for (ord= order; ord; ord= ord->next)
5539
5600
  {
5540
5601
    if (find_order_in_list(session, ref_pointer_array, tables, ord, fields,
5637
5698
  {
5638
5699
    if (order->in_field_list)
5639
5700
    {
5640
 
      Order *ord=(Order*) session->getMemRoot()->duplicate((char*) order,sizeof(Order));
 
5701
      Order *ord=(Order*) session->memdup((char*) order,sizeof(Order));
5641
5702
      if (!ord)
5642
5703
        return 0;
5643
5704
      *prev=ord;
6292
6353
{
6293
6354
  /* List is reversed => we should reverse it before using */
6294
6355
  List_iterator_fast<TableList> ti(*tables);
6295
 
  TableList **table= (TableList **)session->getMemRoot()->allocate(sizeof(TableList*) *
 
6356
  TableList **table= (TableList **)session->alloc(sizeof(TableList*) *
6296
6357
                                                tables->elements);
6297
6358
  if (table == 0)
6298
6359
    return;  // out of memory