~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/handler.cc

  • Committer: Monty Taylor
  • Date: 2008-11-07 00:24:33 UTC
  • mfrom: (575.2.2 devel)
  • mto: This revision was merged to the branch mainline in revision 579.
  • Revision ID: monty@inaugust.com-20081107002433-vj1371j0ko3i194x
MergedĀ fromĀ devel.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1028
1028
#endif
1029
1029
 
1030
1030
 
1031
 
  for (info.len= MAX_XID_LIST_SIZE ; 
 
1031
  for (info.len= MAX_XID_LIST_SIZE ;
1032
1032
       info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
1033
1033
  {
1034
1034
    info.list=(XID *)my_malloc(info.len*sizeof(XID), MYF(0));
1039
1039
    return(1);
1040
1040
  }
1041
1041
 
1042
 
  plugin_foreach(NULL, xarecover_handlerton, 
 
1042
  plugin_foreach(NULL, xarecover_handlerton,
1043
1043
                 DRIZZLE_STORAGE_ENGINE_PLUGIN, &info);
1044
1044
 
1045
1045
  free((unsigned char*)info.list);
1046
1046
  if (info.found_foreign_xids)
1047
 
    sql_print_warning(_("Found %d prepared XA transactions"), 
 
1047
    sql_print_warning(_("Found %d prepared XA transactions"),
1048
1048
                      info.found_foreign_xids);
1049
1049
  if (info.dry_run && info.found_my_xids)
1050
1050
  {
1142
1142
 
1143
1143
int ha_release_temporary_latches(Session *session)
1144
1144
{
1145
 
  plugin_foreach(session, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN, 
 
1145
  plugin_foreach(session, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN,
1146
1146
                 NULL);
1147
1147
 
1148
1148
  return 0;
1292
1292
                             void *arg __attribute__((unused)))
1293
1293
{
1294
1294
  handlerton *hton= plugin_data(plugin, handlerton *);
1295
 
  if (hton->state == SHOW_OPTION_YES && hton->flush_logs && 
 
1295
  if (hton->state == SHOW_OPTION_YES && hton->flush_logs &&
1296
1296
      hton->flush_logs(hton))
1297
1297
    return true;
1298
1298
  return false;
1433
1433
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
1434
1434
  /*
1435
1435
    Allocate handler->ref here because otherwise ha_open will allocate it
1436
 
    on this->table->mem_root and we will not be able to reclaim that memory 
 
1436
    on this->table->mem_root and we will not be able to reclaim that memory
1437
1437
    when the clone handler object is destroyed.
1438
1438
  */
1439
1439
  if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
1582
1582
    (void) extra(HA_EXTRA_NO_READCHECK);        // Not needed in SQL
1583
1583
 
1584
1584
    /* ref is already allocated for us if we're called from handler::clone() */
1585
 
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root, 
 
1585
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
1586
1586
                                          ALIGN_SIZE(ref_length)*2)))
1587
1587
    {
1588
1588
      close();
1859
1859
        /* avoid overflow in formula, with this if() */
1860
1860
        if (nb_already_reserved_intervals <= AUTO_INC_DEFAULT_NB_MAX_BITS)
1861
1861
        {
1862
 
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS * 
 
1862
          nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS *
1863
1863
            (1 << nb_already_reserved_intervals);
1864
1864
          set_if_smaller(nb_desired_values, AUTO_INC_DEFAULT_NB_MAX);
1865
1865
        }
1873
1873
                         &nb_reserved_values);
1874
1874
      if (nr == ~(uint64_t) 0)
1875
1875
        return(HA_ERR_AUTOINC_READ_FAILED);  // Mark failure
1876
 
      
 
1876
 
1877
1877
      /*
1878
1878
        That rounding below should not be needed when all engines actually
1879
1879
        respect offset and increment in get_auto_increment(). But they don't
1884
1884
      */
1885
1885
      nr= compute_next_insert_id(nr-1, variables);
1886
1886
    }
1887
 
    
 
1887
 
1888
1888
    if (table->s->next_number_keypart == 0)
1889
1889
    {
1890
1890
      /* We must defer the appending until "nr" has been possibly truncated */
2856
2856
  char name_buff[FN_REFLEN];
2857
2857
  const char *name;
2858
2858
  TABLE_SHARE share;
2859
 
  
 
2859
 
2860
2860
  init_tmp_table_share(session, &share, db, 0, table_name, path);
2861
2861
  if (open_table_def(session, &share, 0) ||
2862
2862
      open_table_from_share(session, &share, "", 0, (uint) READ_ALL, 0, &table,
3054
3054
{
3055
3055
  const char *db;
3056
3056
  const char *name;
3057
 
  unsigned char **frmblob; 
 
3057
  unsigned char **frmblob;
3058
3058
  size_t *frmlen;
3059
3059
};
3060
3060
 
3064
3064
  st_discover_args *vargs= (st_discover_args *)arg;
3065
3065
  handlerton *hton= plugin_data(plugin, handlerton *);
3066
3066
  if (hton->state == SHOW_OPTION_YES && hton->discover &&
3067
 
      (!(hton->discover(hton, session, vargs->db, vargs->name, 
3068
 
                        vargs->frmblob, 
 
3067
      (!(hton->discover(hton, session, vargs->db, vargs->name,
 
3068
                        vargs->frmblob,
3069
3069
                        vargs->frmlen))))
3070
3070
    return true;
3071
3071
 
3225
3225
  ha_rows rows, total_rows= 0;
3226
3226
  uint32_t n_ranges=0;
3227
3227
  Session *session= current_session;
3228
 
  
 
3228
 
3229
3229
  /* Default MRR implementation doesn't need buffer */
3230
3230
  *bufsz= 0;
3231
3231
 
3234
3234
  {
3235
3235
    if (unlikely(session->killed != 0))
3236
3236
      return HA_POS_ERROR;
3237
 
    
 
3237
 
3238
3238
    n_ranges++;
3239
3239
    key_range *min_endp, *max_endp;
3240
3240
    {
3245
3245
      rows= 1; /* there can be at most one row */
3246
3246
    else
3247
3247
    {
3248
 
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp, 
 
3248
      if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp,
3249
3249
                                                        max_endp)))
3250
3250
      {
3251
3251
        /* Can't scan one range => can't do MRR scan at all */
3255
3255
    }
3256
3256
    total_rows += rows;
3257
3257
  }
3258
 
  
 
3258
 
3259
3259
  if (total_rows != HA_POS_ERROR)
3260
3260
  {
3261
3261
    /* The following calculation is the same as in multi_range_read_info(): */
3328
3328
/**
3329
3329
  Initialize the MRR scan
3330
3330
 
3331
 
  Initialize the MRR scan. This function may do heavyweight scan 
 
3331
  Initialize the MRR scan. This function may do heavyweight scan
3332
3332
  initialization like row prefetching/sorting/etc (NOTE: but better not do
3333
3333
  it here as we may not need it, e.g. if we never satisfy WHERE clause on
3334
3334
  previous tables. For many implementations it would be natural to do such
3335
3335
  initializations in the first multi_read_range_next() call)
3336
3336
 
3337
3337
  mode is a combination of the following flags: HA_MRR_SORTED,
3338
 
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION 
 
3338
  HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION
3339
3339
 
3340
3340
  @param seq             Range sequence to be traversed
3341
3341
  @param seq_init_param  First parameter for seq->init()
3347
3347
    One must have called index_init() before calling this function. Several
3348
3348
    multi_range_read_init() calls may be made in course of one query.
3349
3349
 
3350
 
    Until WL#2623 is done (see its text, section 3.2), the following will 
 
3350
    Until WL#2623 is done (see its text, section 3.2), the following will
3351
3351
    also hold:
3352
3352
    The caller will guarantee that if "seq->init == mrr_ranges_array_init"
3353
3353
    then seq_init_param is an array of n_ranges KEY_MULTI_RANGE structures.
3354
3354
    This property will only be used by NDB handler until WL#2623 is done.
3355
 
     
 
3355
 
3356
3356
    Buffer memory management is done according to the following scenario:
3357
3357
    The caller allocates the buffer and provides it to the callee by filling
3358
3358
    the members of HANDLER_BUFFER structure.
3447
3447
 
3448
3448
 
3449
3449
/* **************************************************************************
3450
 
 * DS-MRR implementation 
 
3450
 * DS-MRR implementation
3451
3451
 ***************************************************************************/
3452
3452
 
3453
3453
/**
3490
3490
 
3491
3491
  is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
3492
3492
  rowids_buf_end= buf->buffer_end;
3493
 
  
 
3493
 
3494
3494
  elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
3495
 
  rowids_buf_last= rowids_buf + 
 
3495
  rowids_buf_last= rowids_buf +
3496
3496
                      ((rowids_buf_end - rowids_buf)/ elem_size)*
3497
3497
                      elem_size;
3498
3498
  rowids_buf_end= rowids_buf_last;
3499
3499
 
3500
3500
  /* Create a separate handler object to do rndpos() calls. */
3501
3501
  Session *session= current_session;
3502
 
  if (!(new_h2= h->clone(session->mem_root)) || 
 
3502
  if (!(new_h2= h->clone(session->mem_root)) ||
3503
3503
      new_h2->ha_external_lock(session, F_RDLCK))
3504
3504
  {
3505
3505
    delete new_h2;
3518
3518
  table->prepare_for_position();
3519
3519
  new_h2->extra(HA_EXTRA_KEYREAD);
3520
3520
 
3521
 
  if (h2->ha_index_init(keyno, false) || 
 
3521
  if (h2->ha_index_init(keyno, false) ||
3522
3522
      h2->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges,
3523
3523
                                         mode, buf))
3524
3524
    goto error;
3525
3525
  use_default_impl= false;
3526
 
  
 
3526
 
3527
3527
  if (pushed_cond)
3528
3528
    h2->idx_cond_push(keyno, pushed_cond);
3529
3529
  if (dsmrr_fill_buffer(new_h2))
3533
3533
    If the above call has scanned through all intervals in *seq, then
3534
3534
    adjust *buf to indicate that the remaining buffer space will not be used.
3535
3535
  */
3536
 
  if (dsmrr_eof) 
 
3536
  if (dsmrr_eof)
3537
3537
    buf->end_of_used_area= rowids_buf_last;
3538
3538
 
3539
3539
  if (h->ha_rnd_init(false))
3540
3540
    goto error;
3541
 
  
 
3541
 
3542
3542
  return(0);
3543
3543
error:
3544
3544
  h2->ha_index_or_rnd_end();
3573
3573
  DS-MRR: Fill the buffer with rowids and sort it by rowid
3574
3574
 
3575
3575
  {This is an internal function of DiskSweep MRR implementation}
3576
 
  Scan the MRR ranges and collect ROWIDs (or {ROWID, range_id} pairs) into 
3577
 
  buffer. When the buffer is full or scan is completed, sort the buffer by 
 
3576
  Scan the MRR ranges and collect ROWIDs (or {ROWID, range_id} pairs) into
 
3577
  buffer. When the buffer is full or scan is completed, sort the buffer by
3578
3578
  rowid and return.
3579
 
  
3580
 
  The function assumes that rowids buffer is empty when it is invoked. 
3581
 
  
 
3579
 
 
3580
  The function assumes that rowids buffer is empty when it is invoked.
 
3581
 
3582
3582
  @param h  Table handler
3583
3583
 
3584
3584
  @retval 0      OK, the next portion of rowids is in the buffer,
3592
3592
  int res = 0;
3593
3593
 
3594
3594
  rowids_buf_cur= rowids_buf;
3595
 
  while ((rowids_buf_cur < rowids_buf_end) && 
 
3595
  while ((rowids_buf_cur < rowids_buf_end) &&
3596
3596
         !(res= h2->handler::multi_range_read_next(&range_info)))
3597
3597
  {
3598
3598
    /* Put rowid, or {rowid, range_id} pair into the buffer */
3608
3608
  }
3609
3609
 
3610
3610
  if (res && res != HA_ERR_END_OF_FILE)
3611
 
    return(res); 
 
3611
    return(res);
3612
3612
  dsmrr_eof= test(res == HA_ERR_END_OF_FILE);
3613
3613
 
3614
3614
  /* Sort the buffer contents by rowid */
3615
3615
  uint32_t elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
3616
3616
  uint32_t n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
3617
 
  
 
3617
 
3618
3618
  my_qsort2(rowids_buf, n_rowids, elem_size, (qsort2_cmp)rowid_cmp,
3619
3619
            (void*)h);
3620
3620
  rowids_buf_last= rowids_buf_cur;
3630
3630
int DsMrr_impl::dsmrr_next(handler *h, char **range_info)
3631
3631
{
3632
3632
  int res;
3633
 
  
 
3633
 
3634
3634
  if (use_default_impl)
3635
3635
    return h->handler::multi_range_read_next(range_info);
3636
 
    
 
3636
 
3637
3637
  if (rowids_buf_cur == rowids_buf_last)
3638
3638
  {
3639
3639
    if (dsmrr_eof)
3645
3645
    if (res)
3646
3646
      goto end;
3647
3647
  }
3648
 
  
 
3648
 
3649
3649
  /* Return EOF if there are no rowids in the buffer after re-fill attempt */
3650
3650
  if (rowids_buf_cur == rowids_buf_last)
3651
3651
  {
3673
3673
*/
3674
3674
int DsMrr_impl::dsmrr_info(uint32_t keyno, uint32_t n_ranges, uint32_t rows, uint32_t *bufsz,
3675
3675
                           uint32_t *flags, COST_VECT *cost)
3676
 
{  
 
3676
{
3677
3677
  int res;
3678
3678
  uint32_t def_flags= *flags;
3679
3679
  uint32_t def_bufsz= *bufsz;
3683
3683
                                         &def_flags, cost);
3684
3684
  assert(!res);
3685
3685
 
3686
 
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) || 
 
3686
  if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
3687
3687
      choose_mrr_impl(keyno, rows, &def_flags, &def_bufsz, cost))
3688
3688
  {
3689
3689
    /* Default implementation is choosen */
3699
3699
*/
3700
3700
 
3701
3701
ha_rows DsMrr_impl::dsmrr_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
3702
 
                                 void *seq_init_param, uint32_t n_ranges, 
 
3702
                                 void *seq_init_param, uint32_t n_ranges,
3703
3703
                                 uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3704
3704
{
3705
3705
  ha_rows rows;
3707
3707
  uint32_t def_bufsz= *bufsz;
3708
3708
  /* Get cost/flags/mem_usage of default MRR implementation */
3709
3709
  rows= h->handler::multi_range_read_info_const(keyno, seq, seq_init_param,
3710
 
                                                n_ranges, &def_bufsz, 
 
3710
                                                n_ranges, &def_bufsz,
3711
3711
                                                &def_flags, cost);
3712
3712
  if (rows == HA_POS_ERROR)
3713
3713
  {
3794
3794
  COST_VECT dsmrr_cost;
3795
3795
  bool res;
3796
3796
  Session *session= current_session;
3797
 
  if ((session->variables.optimizer_use_mrr == 2) || 
 
3797
  if ((session->variables.optimizer_use_mrr == 2) ||
3798
3798
      (*flags & HA_MRR_INDEX_ONLY) || (*flags & HA_MRR_SORTED) ||
3799
 
      (keyno == table->s->primary_key && 
3800
 
       h->primary_key_is_clustered()) || 
 
3799
      (keyno == table->s->primary_key &&
 
3800
       h->primary_key_is_clustered()) ||
3801
3801
       key_uses_partial_cols(keyno))
3802
3802
  {
3803
3803
    /* Use the default implementation */
3804
3804
    *flags |= HA_MRR_USE_DEFAULT_IMPL;
3805
3805
    return true;
3806
3806
  }
3807
 
  
3808
 
  uint32_t add_len= table->key_info[keyno].key_length + h->ref_length; 
 
3807
 
 
3808
  uint32_t add_len= table->key_info[keyno].key_length + h->ref_length;
3809
3809
  *bufsz -= add_len;
3810
3810
  if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
3811
3811
    return true;
3812
3812
  *bufsz += add_len;
3813
 
  
 
3813
 
3814
3814
  bool force_dsmrr;
3815
 
  /* 
 
3815
  /*
3816
3816
    If @@optimizer_use_mrr==force, then set cost of DS-MRR to be minimum of
3817
3817
    DS-MRR and Default implementations cost. This allows one to force use of
3818
3818
    DS-MRR whenever it is applicable without affecting other cost-based
3871
3871
 
3872
3872
  /* Number of iterations we'll make with full buffer */
3873
3873
  n_full_steps= (uint)floor(rows2double(rows) / max_buff_entries);
3874
 
  
3875
 
  /* 
3876
 
    Get numbers of rows we'll be processing in 
3877
 
     - non-last sweep, with full buffer 
 
3874
 
 
3875
  /*
 
3876
    Get numbers of rows we'll be processing in
 
3877
     - non-last sweep, with full buffer
3878
3878
     - last iteration, with non-full buffer
3879
3879
  */
3880
3880
  rows_in_full_step= max_buff_entries;
3881
3881
  rows_in_last_step= rows % max_buff_entries;
3882
 
  
 
3882
 
3883
3883
  /* Adjust buffer size if we expect to use only part of the buffer */
3884
3884
  if (n_full_steps)
3885
3885
  {
3889
3889
  else
3890
3890
  {
3891
3891
    cost->zero();
3892
 
    *buffer_size= cmax((ulong)*buffer_size, 
3893
 
                      (size_t)(1.2*rows_in_last_step) * elem_size + 
 
3892
    *buffer_size= cmax((ulong)*buffer_size,
 
3893
                      (size_t)(1.2*rows_in_last_step) * elem_size +
3894
3894
                      h->ref_length + table->key_info[keynr].key_length);
3895
3895
  }
3896
 
  
 
3896
 
3897
3897
  COST_VECT last_step_cost;
3898
3898
  get_sort_and_sweep_cost(table, rows_in_last_step, &last_step_cost);
3899
3899
  cost->add(&last_step_cost);
3900
 
 
 
3900
 
3901
3901
  if (n_full_steps != 0)
3902
3902
    cost->mem_cost= *buffer_size;
3903
3903
  else
3904
3904
    cost->mem_cost= (double)rows_in_last_step * elem_size;
3905
 
  
 
3905
 
3906
3906
  /* Total cost of all index accesses */
3907
3907
  index_read_cost= h->index_only_read_time(keynr, (double)rows);
3908
3908
  cost->add_io(index_read_cost, 1 /* Random seeks */);
3910
3910
}
3911
3911
 
3912
3912
 
3913
 
/* 
 
3913
/*
3914
3914
  Get cost of one sort-and-sweep step
3915
3915
 
3916
3916
  SYNOPSIS
3925
3925
     - read #nrows records from table in a sweep.
3926
3926
*/
3927
3927
 
3928
 
static 
 
3928
static
3929
3929
void get_sort_and_sweep_cost(Table *table, ha_rows nrows, COST_VECT *cost)
3930
3930
{
3931
3931
  if (nrows)
3959
3959
  Time to move the disk head is proportional to head travel distance.
3960
3960
 
3961
3961
  Time to wait for the plate to rotate depends on whether the disk head
3962
 
  was moved or not. 
 
3962
  was moved or not.
3963
3963
 
3964
3964
  If disk head wasn't moved, the wait time is proportional to distance
3965
3965
  between the previous block and the block we're reading.
3970
3970
 
3971
3971
  Our cost units are "random disk seeks". The cost of random disk seek is
3972
3972
  actually not a constant, it depends one range of cylinders we're going
3973
 
  to access. We make it constant by introducing a fuzzy concept of "typical 
 
3973
  to access. We make it constant by introducing a fuzzy concept of "typical
3974
3974
  datafile length" (it's fuzzy as it's hard to tell whether it should
3975
3975
  include index file, temp.tables etc). Then random seek cost is:
3976
3976
 
3985
3985
  @param cost         OUT  The cost.
3986
3986
*/
3987
3987
 
3988
 
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted, 
 
3988
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted,
3989
3989
                         COST_VECT *cost)
3990
3990
{
3991
3991
  cost->zero();
4064
4064
                           start_key->keypart_map,
4065
4065
                           start_key->flag);
4066
4066
  if (result)
4067
 
    return((result == HA_ERR_KEY_NOT_FOUND) 
 
4067
    return((result == HA_ERR_KEY_NOT_FOUND)
4068
4068
                ? HA_ERR_END_OF_FILE
4069
4069
                : result);
4070
4070
 
4332
4332
        continue;
4333
4333
 
4334
4334
      Table **const end_ptr= lock->table + lock->table_count;
4335
 
      for (Table **table_ptr= lock->table ; 
 
4335
      for (Table **table_ptr= lock->table ;
4336
4336
           table_ptr != end_ptr ;
4337
4337
           ++table_ptr)
4338
4338
      {