select 数据

http://www.programgo.com/article/73361220588/;jsessionid=A91A8B2A2F2E0BFCB207B6DB20B7121E

 http://blog.csdn.net/wudongxu/article/details/6683846

http://www.soso.io/article/83289.html

 

ha_innobase::open

  ib_table = dict_table_get(norm_name, TRUE, ignore_err);

  prebuilt = row_create_prebuilt(ib_table, table->s->reclength);

 

ha_innobase::rnd_next

  if(第一次查找)  

    index_first(buf);

  else

    general_fetch(buf, ROW_SEL_NEXT, 0);

void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
              SQL_SELECT *select,
              int use_record_cache, bool print_error, 
                      bool disable_rr_cache)
{
  IO_CACHE *tempfile;
  DBUG_ENTER("init_read_record");

  bzero((char*) info,sizeof(*info));
  info->thd=thd;
  info->table=table;
  info->file= table->file;
  info->forms= &info->table;        /* Only one table */
  
  if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE &&
      !table->sort.addon_field)
    (void) table->file->extra(HA_EXTRA_MMAP);
  
  if (table->sort.addon_field)
  {
    info->rec_buf= table->sort.addon_buf;
    info->ref_length= table->sort.addon_length;
  }
  else
  {
    empty_record(table);
    info->record= table->record[0];
    info->ref_length= table->file->ref_length;
  }
  info->select=select;
  info->print_error=print_error;
  info->unlock_row= rr_unlock_row;
  info->ignore_not_found_rows= 0;
  table->status=0;            /* And it's always found */

  if (select && my_b_inited(&select->file))
    tempfile= &select->file;
  else if (select && select->quick && select->quick->clustered_pk_range())
  {
    /*
      In case of QUICK_INDEX_MERGE_SELECT with clustered pk range we have to
      use its own access method(i.e QUICK_INDEX_MERGE_SELECT::get_next()) as
      sort file does not contain rowids which satisfy clustered pk range.
    */
    tempfile= 0;
  }
  else
    tempfile= table->sort.io_cache;
  if (tempfile && my_b_inited(tempfile)) // Test if ref-records was used
  {
    DBUG_PRINT("info",("using rr_from_tempfile"));
    info->read_record= (table->sort.addon_field ?
                        rr_unpack_from_tempfile : rr_from_tempfile);
    info->io_cache=tempfile;
    reinit_io_cache(info->io_cache,READ_CACHE,0L,0,0);
    info->ref_pos=table->file->ref;
    if (!table->file->inited)
      table->file->ha_rnd_init(0);

    /*
      table->sort.addon_field is checked because if we use addon fields,
      it doesn't make sense to use cache - we don't read from the table
      and table->sort.io_cache is read sequentially
    */
    if (!disable_rr_cache &&
        !table->sort.addon_field &&
        ! (specialflag & SPECIAL_SAFE_MODE) &&
    thd->variables.read_rnd_buff_size &&
    !(table->file->ha_table_flags() & HA_FAST_KEY_READ) &&
    (table->db_stat & HA_READ_ONLY ||
     table->reginfo.lock_type <= TL_READ_NO_INSERT) &&
    (ulonglong) table->s->reclength* (table->file->stats.records+
                                          table->file->stats.deleted) >
    (ulonglong) MIN_FILE_LENGTH_TO_USE_ROW_CACHE &&
    info->io_cache->end_of_file/info->ref_length * table->s->reclength >
    (my_off_t) MIN_ROWS_TO_USE_TABLE_CACHE &&
    !table->s->blob_fields &&
        info->ref_length <= MAX_REFLENGTH)
    {
      if (! init_rr_cache(thd, info))
      {
    DBUG_PRINT("info",("using rr_from_cache"));
    info->read_record=rr_from_cache;
      }
    }
  }
  else if (select && select->quick)
  {
    DBUG_PRINT("info",("using rr_quick"));
    info->read_record=rr_quick;
  }
  else if (table->sort.record_pointers)
  {
    DBUG_PRINT("info",("using record_pointers"));
    table->file->ha_rnd_init(0);
    info->cache_pos=table->sort.record_pointers;
    info->cache_end=info->cache_pos+ 
                    table->sort.found_records*info->ref_length;
    info->read_record= (table->sort.addon_field ?
                        rr_unpack_from_buffer : rr_from_pointers);
  }
  else
  {
    DBUG_PRINT("info",("using rr_sequential"));
    info->read_record=rr_sequential;
    table->file->ha_rnd_init(1);
    /* We can use record cache if we don't update dynamic length tables */
    if (!table->no_cache &&
    (use_record_cache > 0 ||
     (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY ||
     !(table->s->db_options_in_use & HA_OPTION_PACK_RECORD) ||
     (use_record_cache < 0 &&
      !(table->file->ha_table_flags() & HA_NOT_DELETE_WITH_CACHE))))
      (void) table->file->extra_opt(HA_EXTRA_CACHE,
                  thd->variables.read_buff_size);
  }
  /* Condition pushdown to storage engine */
  if ((thd->variables.optimizer_switch &
       OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN) && 
      select && select->cond && 
      (select->cond->used_tables() & table->map) &&
      !table->file->pushed_cond)
    table->file->cond_push(select->cond);

  DBUG_VOID_RETURN;
} /* init_read_record */

 

 

int rr_sequential(READ_RECORD *info)
{
  int tmp;
  while ((tmp=info->file->rnd_next(info->record)))
  {
    /*
      rnd_next can return RECORD_DELETED for MyISAM when one thread is
      reading and another deleting without locks.
    */
    if (info->thd->killed || (tmp != HA_ERR_RECORD_DELETED))
    {
      tmp= rr_handle_error(info, tmp);
      break;
    }
  }
  return tmp;
}

 

 

在调用rnd_next之前,先调用 index_init,其再调用change_active_index,作用是将prebuilt->index的值赋值给prebuilt->search_tuple

扫表时读取下一行,当然也可作为读取第一行数据

/*****************************************************************//**
Reads the next row in a table scan (also used to read the FIRST row in a table scan).
@return    0, HA_ERR_END_OF_FILE, or error number */
UNIV_INTERN
int
ha_innobase::rnd_next(
/*==================*/
    uchar*    buf)    /*!< in/out: returns the row in this buffer,
            in MySQL format */
{
    int    error;

    if (start_of_scan) {
        error = index_first(buf);
        start_of_scan = 0;
    } else {
        error = general_fetch(buf, ROW_SEL_NEXT, 0);
    }

    DBUG_RETURN(error);
}

 

 

    

index_first的实现

 

/********************************************************************//**
Positions a cursor on the first record in an index and reads the
corresponding row to buf.
@return    0, HA_ERR_END_OF_FILE, or error code */
UNIV_INTERN
int
ha_innobase::index_first(uchar*    buf)    /*!< in/out: buffer for the row */
{
    int    error;
    error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
    DBUG_RETURN(error);
}

 

 

UNIV_INTERN
int
ha_innobase::index_read(
/*====================*/
    uchar*        buf,        /*!< in/out: buffer for the returned
                    row */
    const uchar*    key_ptr,    /*!< in: key value; if this is NULL
                    we position the cursor at the
                    start or end of index; this can
                    also contain an InnoDB row id, in
                    which case key_len is the InnoDB
                    row id length; the key value can
                    also be a prefix of a full key value,
                    and the last column can be a prefix
                    of a full column */
    uint            key_len,/*!< in: key value length */
    enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
{
    ulint        mode;
    dict_index_t*    index;
    ulint        match_mode    = 0;
    int        error;
    ulint        ret;

    DBUG_ENTER("index_read");
    DEBUG_SYNC_C("ha_innobase_index_read_begin");

    index = prebuilt->index;

    if (UNIV_UNLIKELY(index == NULL) || dict_index_is_corrupted(index)) {
        prebuilt->index_usable = FALSE;
        DBUG_RETURN(HA_ERR_CRASHED);
    }
    

    /* Note that if the index for which the search template is built is not
    necessarily prebuilt->index, but can also be the clustered index */

    if (prebuilt->sql_stat_start) {
        build_template(prebuilt, user_thd, table, ROW_MYSQL_REC_FIELDS);
    }

    if (key_ptr) {
        /* Convert the search key value to InnoDB format into
        prebuilt->search_tuple */

        row_sel_convert_mysql_key_to_innobase(
            prebuilt->search_tuple,
            srch_key_val1, sizeof(srch_key_val1),
            index,
            (byte*) key_ptr,
            (ulint) key_len,
            prebuilt->trx);
        DBUG_ASSERT(prebuilt->search_tuple->n_fields > 0);
    } else {
        /* We position the cursor to the last or the first entry
        in the index */ //重要!!!! 设置fields dtuple_set_n_fields(prebuilt->search_tuple, 0);
    }

    mode = convert_search_mode_to_innobase(find_flag);

    match_mode = 0;

    if (find_flag == HA_READ_KEY_EXACT) {

        match_mode = ROW_SEL_EXACT;

    } else if (find_flag == HA_READ_PREFIX
           || find_flag == HA_READ_PREFIX_LAST) {

        match_mode = ROW_SEL_EXACT_PREFIX;
    }

    last_match_mode = (uint) match_mode;

    if (mode != PAGE_CUR_UNSUPP) {
        ret = row_search_for_mysql((byte*) buf, mode, prebuilt,match_mode, 0);
    } else {
        ret = DB_UNSUPPORTED;
    }

    switch (ret) {
    case DB_SUCCESS:
        error = 0;
        table->status = 0;
        break;
    case DB_RECORD_NOT_FOUND:
        error = HA_ERR_KEY_NOT_FOUND;
        table->status = STATUS_NOT_FOUND;
        break;
    case DB_END_OF_INDEX:
        error = HA_ERR_KEY_NOT_FOUND;
        table->status = STATUS_NOT_FOUND;
        break;
    default:
        error = convert_error_code_to_mysql((int) ret,
                            prebuilt->table->flags,
                            user_thd);
        table->status = STATUS_NOT_FOUND;
        break;
    }

    DBUG_RETURN(error);
}

 

 

row_search_for_mysql函数

 

 

 

 

你可能感兴趣的:(select 数据)