~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/cursor.cc

  • Committer: Brian Aker
  • Date: 2009-10-16 10:27:33 UTC
  • mfrom: (1183.1.4 merge)
  • Revision ID: brian@gaz-20091016102733-b10po5oup0hjlilh
Merge Engine changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 */
19
19
 
20
20
/**
21
 
  @file handler.cc
 
21
  @file Cursor.cc
22
22
 
23
23
  Handler-calling-functions
24
24
*/
66
66
 
67
67
 
68
68
/**
69
 
  Register handler error messages for use with my_error().
 
69
  Register Cursor error messages for use with my_error().
70
70
 
71
71
  @retval
72
72
    0           OK
92
92
  SETMSG(HA_ERR_WRONG_INDEX,            "Wrong index given to function");
93
93
  SETMSG(HA_ERR_CRASHED,                ER(ER_NOT_KEYFILE));
94
94
  SETMSG(HA_ERR_WRONG_IN_RECORD,        ER(ER_CRASHED_ON_USAGE));
95
 
  SETMSG(HA_ERR_OUT_OF_MEM,             "Table handler out of memory");
 
95
  SETMSG(HA_ERR_OUT_OF_MEM,             "Table Cursor out of memory");
96
96
  SETMSG(HA_ERR_NOT_A_TABLE,            "Incorrect file format '%.64s'");
97
97
  SETMSG(HA_ERR_WRONG_COMMAND,          "Command not supported");
98
98
  SETMSG(HA_ERR_OLD_FILE,               ER(ER_OLD_KEYFILE));
134
134
 
135
135
 
136
136
/**
137
 
  Unregister handler error messages.
 
137
  Unregister Cursor error messages.
138
138
 
139
139
  @retval
140
140
    0           OK
391
391
  in it unless the engine says so. Thus, in order to be
392
392
  a part of a transaction, the engine must "register" itself.
393
393
  This is done by invoking trans_register_ha() server call.
394
 
  Normally the engine registers itself whenever handler::external_lock()
 
394
  Normally the engine registers itself whenever Cursor::external_lock()
395
395
  is called. trans_register_ha() can be invoked many times: if
396
396
  an engine is already registered, the call does nothing.
397
397
  In case autocommit is not set, the engine must register itself
402
402
  Note, that although the registration interface in itself is
403
403
  fairly clear, the current usage practice often leads to undesired
404
404
  effects. E.g. since a call to trans_register_ha() in most engines
405
 
  is embedded into implementation of handler::external_lock(), some
 
405
  is embedded into implementation of Cursor::external_lock(), some
406
406
  DDL statements start a transaction (at least from the server
407
407
  point of view) even though they are not expected to. E.g.
408
408
  CREATE TABLE does not start a transaction, since
409
 
  handler::external_lock() is never called during CREATE TABLE. But
410
 
  CREATE TABLE ... SELECT does, since handler::external_lock() is
 
409
  Cursor::external_lock() is never called during CREATE TABLE. But
 
410
  CREATE TABLE ... SELECT does, since Cursor::external_lock() is
411
411
  called for the table that is being selected from. This has no
412
412
  practical effects currently, but must be kept in mind
413
413
  nevertheless.
416
416
  of the work.
417
417
 
418
418
  During statement execution, whenever any of data-modifying
419
 
  PSEA API methods is used, e.g. handler::write_row() or
420
 
  handler::update_row(), the read-write flag is raised in the
 
419
  PSEA API methods is used, e.g. Cursor::write_row() or
 
420
  Cursor::update_row(), the read-write flag is raised in the
421
421
  statement transaction for the involved engine.
422
422
  Currently All PSEA calls are "traced", and the data can not be
423
423
  changed in a way other than issuing a PSEA call. Important:
943
943
 
944
944
 
945
945
/****************************************************************************
946
 
** General handler functions
 
946
** General Cursor functions
947
947
****************************************************************************/
948
 
handler::~handler(void)
 
948
Cursor::~Cursor(void)
949
949
{
950
950
  assert(locked == false);
951
951
  /* TODO: assert(inited == NONE); */
952
952
}
953
953
 
954
954
 
955
 
handler *handler::clone(MEM_ROOT *mem_root)
 
955
Cursor *Cursor::clone(MEM_ROOT *mem_root)
956
956
{
957
 
  handler *new_handler= plugin::StorageEngine::getNewHandler(table->s, mem_root, table->s->db_type());
 
957
  Cursor *new_handler= table->s->db_type()->getCursor(table->s, mem_root);
 
958
 
958
959
  /*
959
 
    Allocate handler->ref here because otherwise ha_open will allocate it
 
960
    Allocate Cursor->ref here because otherwise ha_open will allocate it
960
961
    on this->table->mem_root and we will not be able to reclaim that memory
961
 
    when the clone handler object is destroyed.
 
962
    when the clone Cursor object is destroyed.
962
963
  */
963
964
  if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
964
965
    return NULL;
970
971
  return NULL;
971
972
}
972
973
 
973
 
int handler::ha_index_init(uint32_t idx, bool sorted)
 
974
int Cursor::ha_index_init(uint32_t idx, bool sorted)
974
975
{
975
976
  int result;
976
977
  assert(inited == NONE);
980
981
  return result;
981
982
}
982
983
 
983
 
int handler::ha_index_end()
 
984
int Cursor::ha_index_end()
984
985
{
985
986
  assert(inited==INDEX);
986
987
  inited=NONE;
988
989
  return(index_end());
989
990
}
990
991
 
991
 
int handler::ha_rnd_init(bool scan)
 
992
int Cursor::ha_rnd_init(bool scan)
992
993
{
993
994
  int result;
994
995
  assert(inited==NONE || (inited==RND && scan));
997
998
  return result;
998
999
}
999
1000
 
1000
 
int handler::ha_rnd_end()
 
1001
int Cursor::ha_rnd_end()
1001
1002
{
1002
1003
  assert(inited==RND);
1003
1004
  inited=NONE;
1004
1005
  return(rnd_end());
1005
1006
}
1006
1007
 
1007
 
int handler::ha_index_or_rnd_end()
 
1008
int Cursor::ha_index_or_rnd_end()
1008
1009
{
1009
1010
  return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
1010
1011
}
1011
1012
 
1012
 
handler::Table_flags handler::ha_table_flags() const
 
1013
Cursor::Table_flags Cursor::ha_table_flags() const
1013
1014
{
1014
1015
  return cached_table_flags;
1015
1016
}
1016
1017
 
1017
 
void handler::ha_start_bulk_insert(ha_rows rows)
 
1018
void Cursor::ha_start_bulk_insert(ha_rows rows)
1018
1019
{
1019
1020
  estimation_rows_to_insert= rows;
1020
1021
  start_bulk_insert(rows);
1021
1022
}
1022
1023
 
1023
 
int handler::ha_end_bulk_insert()
 
1024
int Cursor::ha_end_bulk_insert()
1024
1025
{
1025
1026
  estimation_rows_to_insert= 0;
1026
1027
  return end_bulk_insert();
1027
1028
}
1028
1029
 
1029
 
void handler::change_table_ptr(Table *table_arg, TableShare *share)
 
1030
void Cursor::change_table_ptr(Table *table_arg, TableShare *share)
1030
1031
{
1031
1032
  table= table_arg;
1032
1033
  table_share= share;
1033
1034
}
1034
1035
 
1035
 
const key_map *handler::keys_to_use_for_scanning()
 
1036
const key_map *Cursor::keys_to_use_for_scanning()
1036
1037
{
1037
1038
  return &key_map_empty;
1038
1039
}
1039
1040
 
1040
 
bool handler::has_transactions()
 
1041
bool Cursor::has_transactions()
1041
1042
{
1042
1043
  return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
1043
1044
}
1044
1045
 
1045
 
void handler::ha_statistic_increment(ulong SSV::*offset) const
 
1046
void Cursor::ha_statistic_increment(ulong SSV::*offset) const
1046
1047
{
1047
1048
  status_var_increment(table->in_use->status_var.*offset);
1048
1049
}
1049
1050
 
1050
 
void **handler::ha_data(Session *session) const
 
1051
void **Cursor::ha_data(Session *session) const
1051
1052
{
1052
1053
  return session_ha_data(session, engine);
1053
1054
}
1054
1055
 
1055
 
Session *handler::ha_session(void) const
 
1056
Session *Cursor::ha_session(void) const
1056
1057
{
1057
1058
  assert(!table || !table->in_use || table->in_use == current_session);
1058
1059
  return (table && table->in_use) ? table->in_use : current_session;
1059
1060
}
1060
1061
 
1061
1062
 
1062
 
bool handler::is_fatal_error(int error, uint32_t flags)
 
1063
bool Cursor::is_fatal_error(int error, uint32_t flags)
1063
1064
{
1064
1065
  if (!error ||
1065
1066
      ((flags & HA_CHECK_DUP_KEY) &&
1070
1071
}
1071
1072
 
1072
1073
 
1073
 
ha_rows handler::records() { return stats.records; }
 
1074
ha_rows Cursor::records() { return stats.records; }
1074
1075
 
1075
1076
/**
1076
 
  Open database-handler.
 
1077
  Open database-Cursor.
1077
1078
 
1078
1079
  Try O_RDONLY if cannot open as O_RDWR
1079
1080
  Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set
1080
1081
*/
1081
 
int handler::ha_open(Table *table_arg, const char *name, int mode,
 
1082
int Cursor::ha_open(Table *table_arg, const char *name, int mode,
1082
1083
                     int test_if_locked)
1083
1084
{
1084
1085
  int error;
1106
1107
      table->db_stat|=HA_READ_ONLY;
1107
1108
    (void) extra(HA_EXTRA_NO_READCHECK);        // Not needed in SQL
1108
1109
 
1109
 
    /* ref is already allocated for us if we're called from handler::clone() */
 
1110
    /* ref is already allocated for us if we're called from Cursor::clone() */
1110
1111
    if (!ref && !(ref= (unsigned char*) alloc_root(&table->mem_root,
1111
1112
                                          ALIGN_SIZE(ref_length)*2)))
1112
1113
    {
1127
1128
  handlers for random position
1128
1129
*/
1129
1130
 
1130
 
int handler::rnd_pos_by_record(unsigned char *record)
 
1131
int Cursor::rnd_pos_by_record(unsigned char *record)
1131
1132
{
1132
1133
  register int error;
1133
1134
 
1146
1147
  This is never called for InnoDB tables, as these table types
1147
1148
  has the HA_STATS_RECORDS_IS_EXACT set.
1148
1149
*/
1149
 
int handler::read_first_row(unsigned char * buf, uint32_t primary_key)
 
1150
int Cursor::read_first_row(unsigned char * buf, uint32_t primary_key)
1150
1151
{
1151
1152
  register int error;
1152
1153
 
1198
1199
}
1199
1200
 
1200
1201
 
1201
 
void handler::adjust_next_insert_id_after_explicit_value(uint64_t nr)
 
1202
void Cursor::adjust_next_insert_id_after_explicit_value(uint64_t nr)
1202
1203
{
1203
1204
  /*
1204
1205
    If we have set Session::next_insert_id previously and plan to insert an
1272
1273
    reserved for us.
1273
1274
 
1274
1275
  - In both cases, for the following rows we use those reserved values without
1275
 
    calling the handler again (we just progress in the interval, computing
 
1276
    calling the Cursor again (we just progress in the interval, computing
1276
1277
    each new value from the previous one). Until we have exhausted them, then
1277
1278
    we either take the next provided interval or call get_auto_increment()
1278
1279
    again to reserve a new interval.
1319
1320
#define AUTO_INC_DEFAULT_NB_MAX_BITS 16
1320
1321
#define AUTO_INC_DEFAULT_NB_MAX ((1 << AUTO_INC_DEFAULT_NB_MAX_BITS) - 1)
1321
1322
 
1322
 
int handler::update_auto_increment()
 
1323
int Cursor::update_auto_increment()
1323
1324
{
1324
1325
  uint64_t nr, nb_reserved_values;
1325
1326
  bool append= false;
1364
1365
    else
1365
1366
    {
1366
1367
      /*
1367
 
        handler::estimation_rows_to_insert was set by
1368
 
        handler::ha_start_bulk_insert(); if 0 it means "unknown".
 
1368
        Cursor::estimation_rows_to_insert was set by
 
1369
        Cursor::ha_start_bulk_insert(); if 0 it means "unknown".
1369
1370
      */
1370
1371
      uint32_t nb_already_reserved_intervals=
1371
1372
        session->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
1467
1468
 
1468
1469
 
1469
1470
/**
1470
 
  Reserves an interval of auto_increment values from the handler.
 
1471
  Reserves an interval of auto_increment values from the Cursor.
1471
1472
 
1472
1473
  offset and increment means that we want values to be of the form
1473
1474
  offset + N * increment, where N>=0 is integer.
1478
1479
  @param offset
1479
1480
  @param increment
1480
1481
  @param nb_desired_values   how many values we want
1481
 
  @param first_value         (OUT) the first value reserved by the handler
1482
 
  @param nb_reserved_values  (OUT) how many values the handler reserved
 
1482
  @param first_value         (OUT) the first value reserved by the Cursor
 
1483
  @param nb_reserved_values  (OUT) how many values the Cursor reserved
1483
1484
*/
1484
 
void handler::get_auto_increment(uint64_t ,
 
1485
void Cursor::get_auto_increment(uint64_t ,
1485
1486
                                 uint64_t ,
1486
1487
                                 uint64_t ,
1487
1488
                                 uint64_t *first_value,
1498
1499
    error=index_last(table->record[1]);
1499
1500
    /*
1500
1501
      MySQL implicitely assumes such method does locking (as MySQL decides to
1501
 
      use nr+increment without checking again with the handler, in
1502
 
      handler::update_auto_increment()), so reserves to infinite.
 
1502
      use nr+increment without checking again with the Cursor, in
 
1503
      Cursor::update_auto_increment()), so reserves to infinite.
1503
1504
    */
1504
1505
    *nb_reserved_values= UINT64_MAX;
1505
1506
  }
1532
1533
}
1533
1534
 
1534
1535
 
1535
 
void handler::ha_release_auto_increment()
 
1536
void Cursor::ha_release_auto_increment()
1536
1537
{
1537
1538
  release_auto_increment();
1538
1539
  insert_id_for_cur_row= 0;
1549
1550
}
1550
1551
 
1551
1552
 
1552
 
void handler::print_keydup_error(uint32_t key_nr, const char *msg)
 
1553
void Cursor::print_keydup_error(uint32_t key_nr, const char *msg)
1553
1554
{
1554
1555
  /* Write the duplicated key in the error message */
1555
1556
  char key[MAX_KEY_LENGTH];
1578
1579
 
1579
1580
 
1580
1581
/**
1581
 
  Print error that we got from handler function.
 
1582
  Print error that we got from Cursor function.
1582
1583
 
1583
1584
  @note
1584
1585
    In case of delete table it's only safe to use the following parts of
1586
1587
    - table->s->path
1587
1588
    - table->alias
1588
1589
*/
1589
 
void handler::print_error(int error, myf errflag)
 
1590
void Cursor::print_error(int error, myf errflag)
1590
1591
{
1591
1592
  int textno=ER_GET_ERRNO;
1592
1593
  switch (error) {
1747
1748
  default:
1748
1749
    {
1749
1750
      /* The error was "unknown" to this function.
1750
 
         Ask handler if it has got a message for this error */
 
1751
         Ask Cursor if it has got a message for this error */
1751
1752
      bool temporary= false;
1752
1753
      String str;
1753
1754
      temporary= get_error_message(error, &str);
1772
1773
 
1773
1774
 
1774
1775
/**
1775
 
  Return an error message specific to this handler.
 
1776
  Return an error message specific to this Cursor.
1776
1777
 
1777
 
  @param error  error code previously returned by handler
 
1778
  @param error  error code previously returned by Cursor
1778
1779
  @param buf    pointer to String where to add error message
1779
1780
 
1780
1781
  @return
1781
1782
    Returns true if this is a temporary error
1782
1783
*/
1783
 
bool handler::get_error_message(int , String* )
 
1784
bool Cursor::get_error_message(int , String* )
1784
1785
{
1785
1786
  return false;
1786
1787
}
1787
1788
 
1788
1789
 
1789
1790
/* Code left, but Drizzle has no legacy yet (while MySQL did) */
1790
 
int handler::check_old_types()
 
1791
int Cursor::check_old_types()
1791
1792
{
1792
1793
  return 0;
1793
1794
}
1796
1797
  @return
1797
1798
    key if error because of duplicated keys
1798
1799
*/
1799
 
uint32_t handler::get_dup_key(int error)
 
1800
uint32_t Cursor::get_dup_key(int error)
1800
1801
{
1801
1802
  table->file->errkey  = (uint32_t) -1;
1802
1803
  if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
1806
1807
  return(table->file->errkey);
1807
1808
}
1808
1809
 
1809
 
void handler::drop_table(const char *)
 
1810
void Cursor::drop_table(const char *)
1810
1811
{
1811
1812
  close();
1812
1813
}
1827
1828
  @retval
1828
1829
    HA_ADMIN_NOT_IMPLEMENTED
1829
1830
*/
1830
 
int handler::ha_check(Session *, HA_CHECK_OPT *)
 
1831
int Cursor::ha_check(Session *, HA_CHECK_OPT *)
1831
1832
{
1832
1833
  return HA_ADMIN_OK;
1833
1834
}
1839
1840
 
1840
1841
inline
1841
1842
void
1842
 
handler::mark_trx_read_write()
 
1843
Cursor::mark_trx_read_write()
1843
1844
{
1844
1845
  Ha_trx_info *ha_info= &ha_session()->ha_data[engine->getSlot()].ha_info[0];
1845
1846
  /*
1859
1860
/**
1860
1861
  Bulk update row: public interface.
1861
1862
 
1862
 
  @sa handler::bulk_update_row()
 
1863
  @sa Cursor::bulk_update_row()
1863
1864
*/
1864
1865
 
1865
1866
int
1866
 
handler::ha_bulk_update_row(const unsigned char *old_data, unsigned char *new_data,
 
1867
Cursor::ha_bulk_update_row(const unsigned char *old_data, unsigned char *new_data,
1867
1868
                            uint32_t *dup_key_found)
1868
1869
{
1869
1870
  mark_trx_read_write();
1875
1876
/**
1876
1877
  Delete all rows: public interface.
1877
1878
 
1878
 
  @sa handler::delete_all_rows()
 
1879
  @sa Cursor::delete_all_rows()
1879
1880
*/
1880
1881
 
1881
1882
int
1882
 
handler::ha_delete_all_rows()
 
1883
Cursor::ha_delete_all_rows()
1883
1884
{
1884
1885
  mark_trx_read_write();
1885
1886
 
1890
1891
/**
1891
1892
  Reset auto increment: public interface.
1892
1893
 
1893
 
  @sa handler::reset_auto_increment()
 
1894
  @sa Cursor::reset_auto_increment()
1894
1895
*/
1895
1896
 
1896
1897
int
1897
 
handler::ha_reset_auto_increment(uint64_t value)
 
1898
Cursor::ha_reset_auto_increment(uint64_t value)
1898
1899
{
1899
1900
  mark_trx_read_write();
1900
1901
 
1905
1906
/**
1906
1907
  Optimize table: public interface.
1907
1908
 
1908
 
  @sa handler::optimize()
 
1909
  @sa Cursor::optimize()
1909
1910
*/
1910
1911
 
1911
1912
int
1912
 
handler::ha_optimize(Session* session, HA_CHECK_OPT* check_opt)
 
1913
Cursor::ha_optimize(Session* session, HA_CHECK_OPT* check_opt)
1913
1914
{
1914
1915
  mark_trx_read_write();
1915
1916
 
1920
1921
/**
1921
1922
  Analyze table: public interface.
1922
1923
 
1923
 
  @sa handler::analyze()
 
1924
  @sa Cursor::analyze()
1924
1925
*/
1925
1926
 
1926
1927
int
1927
 
handler::ha_analyze(Session* session, HA_CHECK_OPT* check_opt)
 
1928
Cursor::ha_analyze(Session* session, HA_CHECK_OPT* check_opt)
1928
1929
{
1929
1930
  mark_trx_read_write();
1930
1931
 
1934
1935
/**
1935
1936
  Disable indexes: public interface.
1936
1937
 
1937
 
  @sa handler::disable_indexes()
 
1938
  @sa Cursor::disable_indexes()
1938
1939
*/
1939
1940
 
1940
1941
int
1941
 
handler::ha_disable_indexes(uint32_t mode)
 
1942
Cursor::ha_disable_indexes(uint32_t mode)
1942
1943
{
1943
1944
  mark_trx_read_write();
1944
1945
 
1949
1950
/**
1950
1951
  Enable indexes: public interface.
1951
1952
 
1952
 
  @sa handler::enable_indexes()
 
1953
  @sa Cursor::enable_indexes()
1953
1954
*/
1954
1955
 
1955
1956
int
1956
 
handler::ha_enable_indexes(uint32_t mode)
 
1957
Cursor::ha_enable_indexes(uint32_t mode)
1957
1958
{
1958
1959
  mark_trx_read_write();
1959
1960
 
1964
1965
/**
1965
1966
  Discard or import tablespace: public interface.
1966
1967
 
1967
 
  @sa handler::discard_or_import_tablespace()
 
1968
  @sa Cursor::discard_or_import_tablespace()
1968
1969
*/
1969
1970
 
1970
1971
int
1971
 
handler::ha_discard_or_import_tablespace(bool discard)
 
1972
Cursor::ha_discard_or_import_tablespace(bool discard)
1972
1973
{
1973
1974
  mark_trx_read_write();
1974
1975
 
1978
1979
/**
1979
1980
  Drop table in the engine: public interface.
1980
1981
 
1981
 
  @sa handler::drop_table()
 
1982
  @sa Cursor::drop_table()
1982
1983
*/
1983
1984
 
1984
1985
void
1985
 
handler::closeMarkForDelete(const char *name)
 
1986
Cursor::closeMarkForDelete(const char *name)
1986
1987
{
1987
1988
  mark_trx_read_write();
1988
1989
 
1991
1992
 
1992
1993
/**
1993
1994
  Tell the storage engine that it is allowed to "disable transaction" in the
1994
 
  handler. It is a hint that ACID is not required - it is used in NDB for
 
1995
  Cursor. It is a hint that ACID is not required - it is used in NDB for
1995
1996
  ALTER Table, for example, when data are copied to temporary table.
1996
1997
  A storage engine may treat this hint any way it likes. NDB for example
1997
1998
  starts to commit every now and then automatically.
2017
2018
  return error;
2018
2019
}
2019
2020
 
2020
 
int handler::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
 
2021
int Cursor::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
2021
2022
{
2022
2023
  int error;
2023
2024
  if (!(error=index_next(buf)))
2069
2070
 
2070
2071
 
2071
2072
/****************************************************************************
2072
 
** Some general functions that isn't in the handler class
 
2073
** Some general functions that isn't in the Cursor class
2073
2074
****************************************************************************/
2074
2075
 
2075
 
 
2076
 
void st_ha_check_opt::init()
2077
 
{
2078
 
  flags= 0; 
2079
 
  use_frm= false;
2080
 
}
2081
 
 
2082
2076
/**
2083
2077
  Calculate cost of 'index only' scan for given index and number of records
2084
2078
 
2088
2082
  @note
2089
2083
    It is assumed that we will read trough the whole key range and that all
2090
2084
    key blocks are half full (normally things are much better). It is also
2091
 
    assumed that each time we read the next key from the index, the handler
 
2085
    assumed that each time we read the next key from the index, the Cursor
2092
2086
    performs a random seek, thus the cost is proportional to the number of
2093
2087
    blocks read.
2094
2088
 
2095
2089
  @todo
2096
 
    Consider joining this function and handler::read_time() into one
2097
 
    handler::read_time(keynr, records, ranges, bool index_only) function.
 
2090
    Consider joining this function and Cursor::read_time() into one
 
2091
    Cursor::read_time(keynr, records, ranges, bool index_only) function.
2098
2092
 
2099
2093
  @return
2100
2094
    Estimated cost of 'index only' scan
2101
2095
*/
2102
2096
 
2103
 
double handler::index_only_read_time(uint32_t keynr, double key_records)
 
2097
double Cursor::index_only_read_time(uint32_t keynr, double key_records)
2104
2098
{
2105
2099
  uint32_t keys_per_block= (stats.block_size/2/
2106
2100
                        (table->key_info[keynr].key_length + ref_length) + 1);
2145
2139
*/
2146
2140
 
2147
2141
ha_rows
2148
 
handler::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
 
2142
Cursor::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
2149
2143
                                     void *seq_init_param,
2150
2144
                                     uint32_t ,
2151
2145
                                     uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
2236
2230
    other Error or can't perform the requested scan
2237
2231
*/
2238
2232
 
2239
 
int handler::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
 
2233
int Cursor::multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t n_rows,
2240
2234
                                   uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
2241
2235
{
2242
2236
  *bufsz= 0; /* Default implementation doesn't need a buffer */
2281
2275
    also hold:
2282
2276
    The caller will guarantee that if "seq->init == mrr_ranges_array_init"
2283
2277
    then seq_init_param is an array of n_ranges KEY_MULTI_RANGE structures.
2284
 
    This property will only be used by NDB handler until WL#2623 is done.
 
2278
    This property will only be used by NDB Cursor until WL#2623 is done.
2285
2279
 
2286
2280
    Buffer memory management is done according to the following scenario:
2287
2281
    The caller allocates the buffer and provides it to the callee by filling
2297
2291
*/
2298
2292
 
2299
2293
int
2300
 
handler::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
 
2294
Cursor::multi_range_read_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
2301
2295
                               uint32_t n_ranges, uint32_t mode,
2302
2296
                               HANDLER_BUFFER *)
2303
2297
{
2322
2316
  @retval other  Error code
2323
2317
*/
2324
2318
 
2325
 
int handler::multi_range_read_next(char **range_info)
 
2319
int Cursor::multi_range_read_next(char **range_info)
2326
2320
{
2327
2321
  int result= 0;
2328
2322
  int range_res= 0;
2376
2370
}
2377
2371
 
2378
2372
 
2379
 
/**
2380
 
  Get cost of reading nrows table records in a "disk sweep"
2381
 
 
2382
 
  A disk sweep read is a sequence of handler->rnd_pos(rowid) calls that made
2383
 
  for an ordered sequence of rowids.
2384
 
 
2385
 
  We assume hard disk IO. The read is performed as follows:
2386
 
 
2387
 
   1. The disk head is moved to the needed cylinder
2388
 
   2. The controller waits for the plate to rotate
2389
 
   3. The data is transferred
2390
 
 
2391
 
  Time to do #3 is insignificant compared to #2+#1.
2392
 
 
2393
 
  Time to move the disk head is proportional to head travel distance.
2394
 
 
2395
 
  Time to wait for the plate to rotate depends on whether the disk head
2396
 
  was moved or not.
2397
 
 
2398
 
  If disk head wasn't moved, the wait time is proportional to distance
2399
 
  between the previous block and the block we're reading.
2400
 
 
2401
 
  If the head was moved, we don't know how much we'll need to wait for the
2402
 
  plate to rotate. We assume the wait time to be a variate with a mean of
2403
 
  0.5 of full rotation time.
2404
 
 
2405
 
  Our cost units are "random disk seeks". The cost of random disk seek is
2406
 
  actually not a constant, it depends one range of cylinders we're going
2407
 
  to access. We make it constant by introducing a fuzzy concept of "typical
2408
 
  datafile length" (it's fuzzy as it's hard to tell whether it should
2409
 
  include index file, temp.tables etc). Then random seek cost is:
2410
 
 
2411
 
    1 = half_rotation_cost + move_cost * 1/3 * typical_data_file_length
2412
 
 
2413
 
  We define half_rotation_cost as DISK_SEEK_BASE_COST=0.9.
2414
 
 
2415
 
  @param table             Table to be accessed
2416
 
  @param nrows             Number of rows to retrieve
2417
 
  @param interrupted       true <=> Assume that the disk sweep will be
2418
 
                           interrupted by other disk IO. false - otherwise.
2419
 
  @param cost         OUT  The cost.
2420
 
*/
2421
 
 
2422
 
void get_sweep_read_cost(Table *table, ha_rows nrows, bool interrupted,
2423
 
                         COST_VECT *cost)
2424
 
{
2425
 
  cost->zero();
2426
 
  if (table->file->primary_key_is_clustered())
2427
 
  {
2428
 
    cost->io_count= table->file->read_time(table->s->primary_key,
2429
 
                                           (uint32_t) nrows, nrows);
2430
 
  }
2431
 
  else
2432
 
  {
2433
 
    double n_blocks=
2434
 
      ceil(uint64_t2double(table->file->stats.data_file_length) / IO_SIZE);
2435
 
    double busy_blocks=
2436
 
      n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(nrows)));
2437
 
    if (busy_blocks < 1.0)
2438
 
      busy_blocks= 1.0;
2439
 
 
2440
 
    cost->io_count= busy_blocks;
2441
 
 
2442
 
    if (!interrupted)
2443
 
    {
2444
 
      /* Assume reading is done in one 'sweep' */
2445
 
      cost->avg_io_cost= (DISK_SEEK_BASE_COST +
2446
 
                          DISK_SEEK_PROP_COST*n_blocks/busy_blocks);
2447
 
    }
2448
 
  }
2449
 
}
2450
 
 
2451
 
 
2452
2373
/* **************************************************************************
2453
2374
 * DS-MRR implementation ends
2454
2375
 ***************************************************************************/
2471
2392
  @retval
2472
2393
    \#                  Error code
2473
2394
*/
2474
 
int handler::read_range_first(const key_range *start_key,
2475
 
                              const key_range *end_key,
2476
 
                              bool eq_range_arg,
2477
 
                              bool )
 
2395
int Cursor::read_range_first(const key_range *start_key,
 
2396
                             const key_range *end_key,
 
2397
                             bool eq_range_arg,
 
2398
                             bool )
2478
2399
{
2479
2400
  int result;
2480
2401
 
2518
2439
  @retval
2519
2440
    \#                  Error code
2520
2441
*/
2521
 
int handler::read_range_next()
 
2442
int Cursor::read_range_next()
2522
2443
{
2523
2444
  int result;
2524
2445
 
2551
2472
    - -1  : Key is less than range
2552
2473
    - 1   : Key is larger than range
2553
2474
*/
2554
 
int handler::compare_key(key_range *range)
 
2475
int Cursor::compare_key(key_range *range)
2555
2476
{
2556
2477
  int cmp;
2557
2478
  if (!range || in_range_check_pushed_down)
2568
2489
  This is used by index condition pushdown implementation.
2569
2490
*/
2570
2491
 
2571
 
int handler::compare_key2(key_range *range)
 
2492
int Cursor::compare_key2(key_range *range)
2572
2493
{
2573
2494
  int cmp;
2574
2495
  if (!range)
2579
2500
  return cmp;
2580
2501
}
2581
2502
 
2582
 
int handler::index_read_idx_map(unsigned char * buf, uint32_t index,
 
2503
int Cursor::index_read_idx_map(unsigned char * buf, uint32_t index,
2583
2504
                                const unsigned char * key,
2584
2505
                                key_part_map keypart_map,
2585
2506
                                enum ha_rkey_function find_flag)
2641
2562
  return false; //error;
2642
2563
}
2643
2564
 
2644
 
int handler::ha_external_lock(Session *session, int lock_type)
 
2565
int Cursor::ha_external_lock(Session *session, int lock_type)
2645
2566
{
2646
2567
  /*
2647
2568
    Whether this is lock or unlock, this should be true, and is to verify that
2664
2585
 
2665
2586
 
2666
2587
/**
2667
 
  Check handler usage and reset state of file to after 'open'
 
2588
  Check Cursor usage and reset state of file to after 'open'
2668
2589
*/
2669
 
int handler::ha_reset()
 
2590
int Cursor::ha_reset()
2670
2591
{
2671
2592
  /* Check that we have called all proper deallocation functions */
2672
2593
  assert((unsigned char*) table->def_read_set.getBitmap() +
2684
2605
}
2685
2606
 
2686
2607
 
2687
 
int handler::ha_write_row(unsigned char *buf)
 
2608
int Cursor::ha_write_row(unsigned char *buf)
2688
2609
{
2689
2610
  int error;
2690
2611
 
2692
2613
   * If we have a timestamp column, update it to the current time 
2693
2614
   * 
2694
2615
   * @TODO Technically, the below two lines can be take even further out of the
2695
 
   * handler interface and into the fill_record() method.
 
2616
   * Cursor interface and into the fill_record() method.
2696
2617
   */
2697
2618
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
2698
2619
    table->timestamp_field->set_time();
2711
2632
}
2712
2633
 
2713
2634
 
2714
 
int handler::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
 
2635
int Cursor::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
2715
2636
{
2716
2637
  int error;
2717
2638
 
2734
2655
  return 0;
2735
2656
}
2736
2657
 
2737
 
int handler::ha_delete_row(const unsigned char *buf)
 
2658
int Cursor::ha_delete_row(const unsigned char *buf)
2738
2659
{
2739
2660
  int error;
2740
2661