~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_select.cc

  • Committer: Lee Bieber
  • Date: 2010-12-23 23:11:00 UTC
  • mfrom: (2024.1.1 clean)
  • Revision ID: kalebral@gmail.com-20101223231100-0rqirgz7ugkl10yp
Merge Brian - session list cleanup

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,
 
138
    res= mysql_select(session,
140
139
                      &select_lex->ref_pointer_array,
141
140
                      (TableList*) select_lex->table_list.first,
142
141
                      select_lex->with_wild,
271
270
 
272
271
/*****************************************************************************
273
272
  Check fields, find best join, do the select and output fields.
274
 
  select_query assumes that all tables are already opened
 
273
  mysql_select assumes that all tables are already opened
275
274
*****************************************************************************/
276
275
 
277
276
/*
351
350
  @retval
352
351
    true   an error
353
352
*/
354
 
bool select_query(Session *session,
 
353
bool mysql_select(Session *session,
355
354
                  Item ***rref_pointer_array,
356
355
                  TableList *tables, 
357
356
                  uint32_t wild_num, 
573
572
  sz= sizeof(optimizer::KeyField) *
574
573
      (((session->lex->current_select->cond_count+1)*2 +
575
574
        session->lex->current_select->between_count)*m+1);
576
 
  if (! (key_fields= (optimizer::KeyField*) session->getMemRoot()->allocate(sz)))
 
575
  if (! (key_fields= (optimizer::KeyField*) session->alloc(sz)))
577
576
    return true;
578
577
  and_level= 0;
579
578
  field= end= key_fields;
932
931
 
933
932
  /*
934
933
    we should restore old value of count_cuted_fields because
935
 
    store_val_in_field can be called from insert_query
 
934
    store_val_in_field can be called from mysql_insert
936
935
    with select_insert, which make count_cuted_fields= 1
937
936
   */
938
937
  enum_check_fields old_count_cuted_fields= session->count_cuted_fields;
1005
1004
  j->ref.key_length=length;
1006
1005
  j->ref.key=(int) key;
1007
1006
  if (!(j->ref.key_buff= (unsigned char*) session->calloc(ALIGN_SIZE(length)*2)) ||
1008
 
      !(j->ref.key_copy= (StoredKey**) session->getMemRoot()->allocate((sizeof(StoredKey*) *
 
1007
      !(j->ref.key_copy= (StoredKey**) session->alloc((sizeof(StoredKey*) *
1009
1008
               (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)))
 
1009
      !(j->ref.items=    (Item**) session->alloc(sizeof(Item*)*keyparts)) ||
 
1010
      !(j->ref.cond_guards= (bool**) session->alloc(sizeof(uint*)*keyparts)))
1012
1011
  {
1013
1012
    return(true);
1014
1013
  }
2308
2307
  @param cond       condition whose multiple equalities are to be checked
2309
2308
  @param table      constant table that has been read
2310
2309
*/
2311
 
void update_const_equal_items(COND *cond, JoinTable *tab)
 
2310
static void update_const_equal_items(COND *cond, JoinTable *tab)
2312
2311
{
2313
2312
  if (!(cond->used_tables() & tab->table->map))
2314
2313
    return;
2365
2364
  and_level
2366
2365
*/
2367
2366
static void change_cond_ref_to_const(Session *session,
2368
 
                                     list<COND_CMP>& save_list,
 
2367
                                     vector<COND_CMP>& save_list,
2369
2368
                                     Item *and_father,
2370
2369
                                     Item *cond,
2371
2370
                                     Item *field,
2471
2470
}
2472
2471
 
2473
2472
static void propagate_cond_constants(Session *session, 
2474
 
                                     list<COND_CMP>& save_list, 
 
2473
                                     vector<COND_CMP>& save_list, 
2475
2474
                                     COND *and_father, 
2476
2475
                                     COND *cond)
2477
2476
{
2480
2479
    bool and_level= ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC;
2481
2480
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
2482
2481
    Item *item;
2483
 
    list<COND_CMP> save;
 
2482
    vector<COND_CMP> save;
2484
2483
    while ((item=li++))
2485
2484
    {
2486
2485
      propagate_cond_constants(session, save, and_level ? cond : item, item);
2488
2487
    if (and_level)
2489
2488
    {
2490
2489
      // Handle other found items
2491
 
      for (list<COND_CMP>::iterator iter= save.begin(); iter != save.end(); ++iter)
 
2490
      for (vector<COND_CMP>::iterator iter= save.begin(); iter != save.end(); ++iter)
2492
2491
      {
2493
 
        Item **args= iter->second->arguments();
 
2492
        Item **args= iter->cmp_func->arguments();
2494
2493
        if (not args[0]->const_item())
2495
2494
        {
2496
 
          change_cond_ref_to_const(session, save, iter->first,
2497
 
                                   iter->first, args[0], args[1] );
 
2495
          change_cond_ref_to_const(session, save_list, iter->and_level,
 
2496
                                   iter->and_level, args[0], args[1] );
2498
2497
        }
2499
2498
      }
2500
2499
    }
2607
2606
         position:
2608
2607
          1. join->cur_embedding_map - bitmap of pairs of brackets (aka nested
2609
2608
             joins) we've opened but didn't close.
2610
 
          2. {each NestedJoin class not simplified away}->counter - number
 
2609
          2. {each nested_join_st structure not simplified away}->counter - number
2611
2610
             of this nested join's children that have already been added to to
2612
2611
             the partial join order.
2613
2612
  @endverbatim
2685
2684
                             &join->cond_equal);
2686
2685
 
2687
2686
    /* change field = field to field = const for each found field = const */
2688
 
    list<COND_CMP> temp;
 
2687
    vector<COND_CMP> temp;
2689
2688
    propagate_cond_constants(session, temp, conds, conds);
2690
2689
    /*
2691
2690
      Remove all instances of item == item
3054
3053
    table->emptyRecord();
3055
3054
    if (table->group && join->tmp_table_param.sum_func_count &&
3056
3055
        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
 
    }
 
3056
      table->cursor->startIndexScan(0, 0);
3066
3057
  }
3067
3058
  /* Set up select_end */
3068
3059
  Next_select_func end_select= setup_end_select_func(join);
3368
3359
  return 0;
3369
3360
}
3370
3361
 
 
3362
int join_read_const_table(JoinTable *tab, optimizer::Position *pos)
 
3363
{
 
3364
  int error;
 
3365
  Table *table=tab->table;
 
3366
  table->const_table=1;
 
3367
  table->null_row=0;
 
3368
  table->status=STATUS_NO_RECORD;
 
3369
 
 
3370
  if (tab->type == AM_SYSTEM)
 
3371
  {
 
3372
    if ((error=join_read_system(tab)))
 
3373
    {                                           // Info for DESCRIBE
 
3374
      tab->info="const row not found";
 
3375
      /* Mark for EXPLAIN that the row was not found */
 
3376
      pos->setFanout(0.0);
 
3377
      pos->clearRefDependMap();
 
3378
      if (! table->maybe_null || error > 0)
 
3379
        return(error);
 
3380
    }
 
3381
  }
 
3382
  else
 
3383
  {
 
3384
    if (! table->key_read && 
 
3385
        table->covering_keys.test(tab->ref.key) && 
 
3386
        ! table->no_keyread &&
 
3387
        (int) table->reginfo.lock_type <= (int) TL_READ_WITH_SHARED_LOCKS)
 
3388
    {
 
3389
      table->key_read=1;
 
3390
      table->cursor->extra(HA_EXTRA_KEYREAD);
 
3391
      tab->index= tab->ref.key;
 
3392
    }
 
3393
    error=join_read_const(tab);
 
3394
    if (table->key_read)
 
3395
    {
 
3396
      table->key_read=0;
 
3397
      table->cursor->extra(HA_EXTRA_NO_KEYREAD);
 
3398
    }
 
3399
    if (error)
 
3400
    {
 
3401
      tab->info="unique row not found";
 
3402
      /* Mark for EXPLAIN that the row was not found */
 
3403
      pos->setFanout(0.0);
 
3404
      pos->clearRefDependMap();
 
3405
      if (!table->maybe_null || error > 0)
 
3406
        return(error);
 
3407
    }
 
3408
  }
 
3409
  if (*tab->on_expr_ref && !table->null_row)
 
3410
  {
 
3411
    if ((table->null_row= test((*tab->on_expr_ref)->val_int() == 0)))
 
3412
      table->mark_as_null_row();
 
3413
  }
 
3414
  if (!table->null_row)
 
3415
    table->maybe_null=0;
 
3416
 
 
3417
  /* Check appearance of new constant items in Item_equal objects */
 
3418
  Join *join= tab->join;
 
3419
  if (join->conds)
 
3420
    update_const_equal_items(join->conds, tab);
 
3421
  TableList *tbl;
 
3422
  for (tbl= join->select_lex->leaf_tables; tbl; tbl= tbl->next_leaf)
 
3423
  {
 
3424
    TableList *embedded;
 
3425
    TableList *embedding= tbl;
 
3426
    do
 
3427
    {
 
3428
      embedded= embedding;
 
3429
      if (embedded->on_expr)
 
3430
         update_const_equal_items(embedded->on_expr, tab);
 
3431
      embedding= embedded->getEmbedding();
 
3432
    }
 
3433
    while (embedding &&
 
3434
           embedding->getNestedJoin()->join_list.head() == embedded);
 
3435
  }
 
3436
 
 
3437
  return(0);
 
3438
}
 
3439
 
 
3440
int join_read_system(JoinTable *tab)
 
3441
{
 
3442
  Table *table= tab->table;
 
3443
  int error;
 
3444
  if (table->status & STATUS_GARBAGE)           // If first read
 
3445
  {
 
3446
    if ((error=table->cursor->read_first_row(table->getInsertRecord(),
 
3447
                                           table->getShare()->getPrimaryKey())))
 
3448
    {
 
3449
      if (error != HA_ERR_END_OF_FILE)
 
3450
        return table->report_error(error);
 
3451
      tab->table->mark_as_null_row();
 
3452
      table->emptyRecord();                     // Make empty record
 
3453
      return -1;
 
3454
    }
 
3455
    table->storeRecord();
 
3456
  }
 
3457
  else if (!table->status)                      // Only happens with left join
 
3458
    table->restoreRecord();                     // restore old record
 
3459
  table->null_row=0;
 
3460
  return table->status ? -1 : 0;
 
3461
}
 
3462
 
3371
3463
/**
3372
3464
  Read a (constant) table when there is at most one matching row.
3373
3465
 
3439
3531
 
3440
3532
  if (!table->cursor->inited)
3441
3533
  {
3442
 
    error= table->cursor->startIndexScan(tab->ref.key, tab->sorted);
3443
 
    if (error != 0)
3444
 
    {
3445
 
      table->print_error(error, MYF(0));
3446
 
    }
 
3534
    table->cursor->startIndexScan(tab->ref.key, tab->sorted);
3447
3535
  }
3448
3536
 
3449
3537
  /* TODO: Why don't we do "Late NULLs Filtering" here? */
3491
3579
 
3492
3580
  /* Initialize the index first */
3493
3581
  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
 
  }
 
3582
    table->cursor->startIndexScan(tab->ref.key, tab->sorted);
3499
3583
 
3500
3584
  /* Perform "Late NULLs Filtering" (see internals manual for explanations) */
3501
3585
  for (uint32_t i= 0 ; i < tab->ref.key_parts ; i++)
3529
3613
  Table *table= tab->table;
3530
3614
 
3531
3615
  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
 
  }
 
3616
    table->cursor->startIndexScan(tab->ref.key, tab->sorted);
3537
3617
  if (cp_buffer_from_ref(tab->join->session, &tab->ref))
3538
3618
    return -1;
3539
3619
  if ((error=table->cursor->index_read_last_map(table->getInsertRecord(),
3648
3728
  if (tab->select && tab->select->quick && tab->select->quick->reset())
3649
3729
    return 1;
3650
3730
 
3651
 
  if (tab->read_record.init_read_record(tab->join->session, tab->table, tab->select, 1, true))
3652
 
    return 1;
 
3731
  tab->read_record.init_read_record(tab->join->session, tab->table, tab->select, 1, true);
3653
3732
 
3654
3733
  return (*tab->read_record.read_record)(&tab->read_record);
3655
3734
}
3682
3761
  }
3683
3762
 
3684
3763
  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
 
  }
 
3764
    table->cursor->startIndexScan(tab->index, tab->sorted);
3693
3765
  if ((error=tab->table->cursor->index_first(tab->table->getInsertRecord())))
3694
3766
  {
3695
3767
    if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
3748
3820
  tab->read_record.index=tab->index;
3749
3821
  tab->read_record.record=table->getInsertRecord();
3750
3822
  if (!table->cursor->inited)
3751
 
  {
3752
 
    error= table->cursor->startIndexScan(tab->index, 1);
3753
 
    if (error != 0)
3754
 
      return table->report_error(error);
3755
 
  }
 
3823
    table->cursor->startIndexScan(tab->index, 1);
3756
3824
  if ((error= tab->table->cursor->index_last(tab->table->getInsertRecord())))
3757
3825
    return table->report_error(error);
3758
3826
 
3832
3900
              error=join->result->send_data(*join->fields) ? 1 : 0;
3833
3901
            join->send_records++;
3834
3902
          }
3835
 
          if (join->rollup.getState() != Rollup::STATE_NONE && error <= 0)
 
3903
          if (join->rollup.state != ROLLUP::STATE_NONE && error <= 0)
3836
3904
          {
3837
3905
            if (join->rollup_send_data((uint32_t) (idx+1)))
3838
3906
              error= 1;
3922
3990
            return NESTED_LOOP_ERROR;
3923
3991
          }
3924
3992
        }
3925
 
        if (join->rollup.getState() != Rollup::STATE_NONE)
 
3993
        if (join->rollup.state != ROLLUP::STATE_NONE)
3926
3994
        {
3927
3995
          if (join->rollup_write_data((uint32_t) (idx+1), table))
3928
3996
            return NESTED_LOOP_ERROR;
5031
5099
  org_record=(char*) (record=table->getInsertRecord())+offset;
5032
5100
  new_record=(char*) table->getUpdateRecord()+offset;
5033
5101
 
5034
 
  if ((error= cursor->startTableScan(1)))
5035
 
    goto err;
5036
 
 
 
5102
  cursor->startTableScan(1);
5037
5103
  error=cursor->rnd_next(record);
5038
5104
  for (;;)
5039
5105
  {
5150
5216
    return(1);
5151
5217
  }
5152
5218
 
5153
 
  if ((error= cursor->startTableScan(1)))
5154
 
    goto err;
5155
 
 
 
5219
  cursor->startTableScan(1);
5156
5220
  key_pos= &key_buffer[0];
5157
5221
  for (;;)
5158
5222
  {
5364
5428
    if (!count || count > fields.elements)
5365
5429
    {
5366
5430
      my_error(ER_BAD_FIELD_ERROR, MYF(0),
5367
 
               order_item->full_name(), session->where());
 
5431
               order_item->full_name(), session->where);
5368
5432
      return true;
5369
5433
    }
5370
5434
    order->item= ref_pointer_array + count - 1;
5441
5505
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_NON_UNIQ_ERROR,
5442
5506
                          ER(ER_NON_UNIQ_ERROR),
5443
5507
                          ((Item_ident*) order_item)->field_name,
5444
 
                          session->where());
 
5508
                          session->where);
5445
5509
    }
5446
5510
  }
5447
5511
 
5483
5547
                List<Item> &all_fields,
5484
5548
                Order *order)
5485
5549
{
5486
 
  session->setWhere("order clause");
 
5550
  session->where="order clause";
5487
5551
  for (; order; order=order->next)
5488
5552
  {
5489
5553
    if (find_order_in_list(session, ref_pointer_array, tables, order, fields,
5534
5598
 
5535
5599
  uint32_t org_fields=all_fields.elements;
5536
5600
 
5537
 
  session->setWhere("group statement");
 
5601
  session->where="group statement";
5538
5602
  for (ord= order; ord; ord= ord->next)
5539
5603
  {
5540
5604
    if (find_order_in_list(session, ref_pointer_array, tables, ord, fields,
5637
5701
  {
5638
5702
    if (order->in_field_list)
5639
5703
    {
5640
 
      Order *ord=(Order*) session->getMemRoot()->duplicate((char*) order,sizeof(Order));
 
5704
      Order *ord=(Order*) session->memdup((char*) order,sizeof(Order));
5641
5705
      if (!ord)
5642
5706
        return 0;
5643
5707
      *prev=ord;
6292
6356
{
6293
6357
  /* List is reversed => we should reverse it before using */
6294
6358
  List_iterator_fast<TableList> ti(*tables);
6295
 
  TableList **table= (TableList **)session->getMemRoot()->allocate(sizeof(TableList*) *
 
6359
  TableList **table= (TableList **)session->alloc(sizeof(TableList*) *
6296
6360
                                                tables->elements);
6297
6361
  if (table == 0)
6298
6362
    return;  // out of memory