1828
1658
reset_template(
1829
1659
/*===========*/
1830
row_prebuilt_t* prebuilt) /*!< in/out: prebuilt struct */
1832
prebuilt->keep_other_fields_on_keyread = 0;
1833
prebuilt->read_just_key = 0;
1837
void align_value(T& value, size_t align_val= 1024)
1839
value= value - (value % align_val);
1842
static void auto_extend_update(Session *, sql_var_t)
1844
srv_auto_extend_increment= innodb_auto_extend_increment.get();
1847
static void io_capacity_update(Session *, sql_var_t)
1849
srv_io_capacity= innodb_io_capacity.get();
1852
static void purge_batch_update(Session *, sql_var_t)
1854
srv_purge_batch_size= innodb_purge_batch_size.get();
1857
static void purge_threads_update(Session *, sql_var_t)
1859
srv_n_purge_threads= innodb_n_purge_threads.get();
1862
static void innodb_adaptive_hash_index_update(Session *, sql_var_t)
1864
if (btr_search_enabled)
1866
btr_search_enable();
1868
btr_search_disable();
1872
static void innodb_old_blocks_pct_update(Session *, sql_var_t)
1874
innobase_old_blocks_pct= buf_LRU_old_ratio_update(innobase_old_blocks_pct.get(), TRUE);
1877
static void innodb_thread_concurrency_update(Session *, sql_var_t)
1879
srv_thread_concurrency= innobase_thread_concurrency.get();
1882
static void innodb_sync_spin_loops_update(Session *, sql_var_t)
1884
srv_n_spin_wait_rounds= innodb_sync_spin_loops.get();
1887
static void innodb_spin_wait_delay_update(Session *, sql_var_t)
1889
srv_spin_wait_delay= innodb_spin_wait_delay.get();
1892
static void innodb_thread_sleep_delay_update(Session *, sql_var_t)
1894
srv_thread_sleep_delay= innodb_thread_sleep_delay.get();
1897
static void innodb_read_ahead_threshold_update(Session *, sql_var_t)
1899
srv_read_ahead_threshold= innodb_read_ahead_threshold.get();
1903
static int innodb_commit_concurrency_validate(Session *session, set_var *var)
1905
uint32_t new_value= var->save_result.uint32_t_value;
1907
if ((innobase_commit_concurrency.get() == 0 && new_value != 0) ||
1908
(innobase_commit_concurrency.get() != 0 && new_value == 0))
1910
push_warning_printf(session,
1911
DRIZZLE_ERROR::WARN_LEVEL_WARN,
1913
_("Once InnoDB is running, innodb_commit_concurrency "
1914
"must not change between zero and nonzero."));
1920
/*************************************************************//**
1921
Check if it is a valid file format. This function is registered as
1922
a callback with MySQL.
1923
@return 0 for valid file format */
1926
innodb_file_format_name_validate(
1927
/*=============================*/
1928
Session* , /*!< in: thread handle */
1931
const char *file_format_input = var->value->str_value.ptr();
1932
if (file_format_input == NULL)
1935
if (file_format_input != NULL) {
1938
format_id = innobase_file_format_name_lookup(
1941
if (format_id <= DICT_TF_FORMAT_MAX) {
1942
innobase_file_format_name =
1943
trx_sys_file_format_id_to_name(format_id);
1952
/*************************************************************//**
1953
Check if it is a valid value of innodb_change_buffering. This function is
1954
registered as a callback with MySQL.
1955
@return 0 for valid innodb_change_buffering */
1958
innodb_change_buffering_validate(
1959
/*=============================*/
1960
Session* , /*!< in: thread handle */
1963
const char *change_buffering_input = var->value->str_value.ptr();
1965
if (change_buffering_input == NULL)
1971
use < UT_ARR_SIZE(innobase_change_buffering_values);
1973
if (!innobase_strcasecmp(change_buffering_input,
1974
innobase_change_buffering_values[use]))
1976
ibuf_use= static_cast<ibuf_use_t>(use);
1985
/*************************************************************//**
1986
Check if valid argument to innodb_file_format_max. This function
1987
is registered as a callback with MySQL.
1988
@return 0 for valid file format */
1991
innodb_file_format_max_validate(
1992
/*==============================*/
1993
Session* session, /*!< in: thread handle */
1996
const char *file_format_input = var->value->str_value.ptr();
1997
if (file_format_input == NULL)
2000
if (file_format_input != NULL) {
2001
int format_id = innobase_file_format_validate_and_set(file_format_input);
2003
if (format_id > DICT_TF_FORMAT_MAX) {
2004
/* DEFAULT is "on", which is invalid at runtime. */
2008
if (format_id >= 0) {
2009
innobase_file_format_max=
2010
trx_sys_file_format_id_to_name((uint)format_id);
2012
/* Update the max format id in the system tablespace. */
2013
char name_buff[100];
2014
strcpy(name_buff, innobase_file_format_max.c_str());
2015
if (trx_sys_file_format_max_set(format_id, (const char **)&name_buff))
2017
errmsg_printf(ERRMSG_LVL_WARN,
2018
" [Info] InnoDB: the file format in the system "
2019
"tablespace is now set to %s.\n", name_buff);
2020
innobase_file_format_max= name_buff;
2025
push_warning_printf(session,
2026
DRIZZLE_ERROR::WARN_LEVEL_WARN,
2028
"InnoDB: invalid innodb_file_format_max "
2029
"value; can be any format up to %s "
2030
"or equivalent id of %d",
2031
trx_sys_file_format_id_to_name(DICT_TF_FORMAT_MAX),
2032
DICT_TF_FORMAT_MAX);
1660
row_prebuilt_t* prebuilt) /*!< in/out: prebuilt struct */
1662
prebuilt->keep_other_fields_on_keyread = 0;
1663
prebuilt->read_just_key = 0;
1666
/*****************************************************************//**
1667
Call this when you have opened a new table handle in HANDLER, before you
1668
call index_read_idx() etc. Actually, we can let the cursor stay open even
1669
over a transaction commit! Then you should call this before every operation,
1670
fetch next etc. This function inits the necessary things even after a
1671
transaction commit. */
1674
ha_innobase::init_table_handle_for_HANDLER(void)
1675
/*============================================*/
1677
/* If current session does not yet have a trx struct, create one.
1678
If the current handle does not yet have a prebuilt struct, create
1679
one. Update the trx pointers in the prebuilt struct. Normally
1680
this operation is done in external_lock. */
1682
update_session(ha_session());
1684
/* Initialize the prebuilt struct much like it would be inited in
1687
innobase_release_stat_resources(prebuilt->trx);
1689
/* If the transaction is not started yet, start it */
1691
trx_start_if_not_started(prebuilt->trx);
1693
/* Assign a read view if the transaction does not have it yet */
1695
trx_assign_read_view(prebuilt->trx);
1697
/* Set the MySQL flag to mark that there is an active transaction */
1699
if (prebuilt->trx->active_trans == 0) {
1701
innobase_register_trx_and_stmt(engine, user_session);
1703
prebuilt->trx->active_trans = 1;
1706
/* We did the necessary inits in this function, no need to repeat them
1707
in row_search_for_mysql */
1709
prebuilt->sql_stat_start = FALSE;
1711
/* We let HANDLER always to do the reads as consistent reads, even
1712
if the trx isolation level would have been specified as SERIALIZABLE */
1714
prebuilt->select_lock_type = LOCK_NONE;
1715
prebuilt->stored_select_lock_type = LOCK_NONE;
1717
/* Always fetch all columns in the index record */
1719
prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
1721
/* We want always to fetch all columns in the whole row? Or do
1724
prebuilt->used_in_HANDLER = TRUE;
1725
reset_template(prebuilt);
2040
1728
/*********************************************************************//**
2041
1729
Opens an InnoDB database.
2042
@return 0 on success, error code on failure */
1730
@return 0 on success, error code on failure */
2047
module::Context &context) /*!< in: Drizzle Plugin Context */
1735
plugin::Registry ®istry) /*!< in: Drizzle Plugin Registry */
2052
InnobaseEngine *actuall_engine_ptr;
2053
const module::option_map &vm= context.getOptions();
2055
srv_auto_extend_increment= innodb_auto_extend_increment.get();
2056
srv_io_capacity= innodb_io_capacity.get();
2057
srv_purge_batch_size= innodb_purge_batch_size.get();
2058
srv_n_purge_threads= innodb_n_purge_threads.get();
2059
srv_flush_log_at_trx_commit= innodb_flush_log_at_trx_commit.get();
2060
srv_max_buf_pool_modified_pct= innodb_max_dirty_pages_pct.get();
2061
srv_max_purge_lag= innodb_max_purge_lag.get();
2062
srv_stats_sample_pages= innodb_stats_sample_pages.get();
2063
srv_n_free_tickets_to_enter= innodb_concurrency_tickets.get();
2064
srv_replication_delay= innodb_replication_delay.get();
2065
srv_thread_concurrency= innobase_thread_concurrency.get();
2066
srv_n_spin_wait_rounds= innodb_sync_spin_loops.get();
2067
srv_spin_wait_delay= innodb_spin_wait_delay.get();
2068
srv_thread_sleep_delay= innodb_thread_sleep_delay.get();
2069
srv_read_ahead_threshold= innodb_read_ahead_threshold.get();
2071
/* Inverted Booleans */
2073
innobase_use_checksums= (vm.count("disable-checksums")) ? false : true;
2074
innobase_use_doublewrite= (vm.count("disable-doublewrite")) ? false : true;
2075
srv_adaptive_flushing= (vm.count("disable-adaptive-flushing")) ? false : true;
2076
srv_use_sys_malloc= (vm.count("use-internal-malloc")) ? false : true;
2077
support_xa= (vm.count("disable-xa")) ? false : true;
2078
btr_search_enabled= (vm.count("disable-adaptive-hash-index")) ? false : true;
2081
/* Hafta do this here because we need to late-bind the default value */
2082
if (vm.count("data-home-dir"))
2084
innobase_data_home_dir= vm["data-home-dir"].as<string>();
2088
innobase_data_home_dir= getDataHome().file_string();
2092
if (vm.count("data-file-path"))
2094
innobase_data_file_path= vm["data-file-path"].as<string>();
2098
innodb_engine_ptr= actuall_engine_ptr= new InnobaseEngine(innobase_engine_name);
2100
ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)DRIZZLE_TYPE_VARCHAR);
1737
static char current_dir[3]; /*!< Set if using current lib */
1743
innodb_engine_ptr= new InnobaseEngine(innobase_engine_name);
1746
ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)DRIZZLE_TYPE_VARCHAR);
2102
1748
#ifdef UNIV_DEBUG
2103
static const char test_filename[] = "-@";
2104
char test_tablename[sizeof test_filename
2105
+ sizeof srv_mysql50_table_name_prefix];
2106
if ((sizeof test_tablename) - 1
2107
!= filename_to_tablename(test_filename, test_tablename,
2108
sizeof test_tablename)
2109
|| strncmp(test_tablename,
2110
srv_mysql50_table_name_prefix,
2111
sizeof srv_mysql50_table_name_prefix)
2112
|| strcmp(test_tablename
2113
+ sizeof srv_mysql50_table_name_prefix,
2115
errmsg_printf(ERRMSG_LVL_ERROR, "tablename encoding has been changed");
1749
static const char test_filename[] = "-@";
1750
char test_tablename[sizeof test_filename
1751
+ sizeof srv_mysql50_table_name_prefix];
1752
if ((sizeof test_tablename) - 1
1753
!= filename_to_tablename(test_filename, test_tablename,
1754
sizeof test_tablename)
1755
|| strncmp(test_tablename,
1756
srv_mysql50_table_name_prefix,
1757
sizeof srv_mysql50_table_name_prefix)
1758
|| strcmp(test_tablename
1759
+ sizeof srv_mysql50_table_name_prefix,
1761
errmsg_printf(ERRMSG_LVL_ERROR, "tablename encoding has been changed");
2118
1764
#endif /* UNIV_DEBUG */
2120
os_innodb_umask = (ulint)internal::my_umask;
2123
/* Set InnoDB initialization parameters according to the values
2124
read from MySQL .cnf file */
2126
/*--------------- Data files -------------------------*/
2128
/* The default dir for data files is the datadir of MySQL */
2130
srv_data_home = (char *)innobase_data_home_dir.c_str();
2132
/* Set default InnoDB data file size to 10 MB and let it be
2133
auto-extending. Thus users can use InnoDB in >= 4.0 without having
2134
to specify any startup options. */
2136
if (innobase_data_file_path.empty())
2138
innobase_data_file_path= std::string("ibdata1:10M:autoextend");
2141
/* Since InnoDB edits the argument in the next call, we make another
2144
internal_innobase_data_file_path = strdup(innobase_data_file_path.c_str());
2146
ret = (bool) srv_parse_data_file_paths_and_sizes(
2147
internal_innobase_data_file_path);
2149
errmsg_printf(ERRMSG_LVL_ERROR,
2150
"InnoDB: syntax error in innodb_data_file_path");
1766
/* Check that values don't overflow on 32-bit systems. */
1767
if (sizeof(ulint) == 4) {
1768
if (innobase_buffer_pool_size > UINT32_MAX) {
1769
errmsg_printf(ERRMSG_LVL_ERROR,
1770
"innobase_buffer_pool_size can't be over 4GB"
1771
" on 32-bit systems");
1776
if (innobase_log_file_size > UINT32_MAX) {
1777
errmsg_printf(ERRMSG_LVL_ERROR,
1778
"innobase_log_file_size can't be over 4GB"
1779
" on 32-bit systems");
1785
os_innodb_umask = (ulint)internal::my_umask;
1787
/* First calculate the default path for innodb_data_home_dir etc.,
1788
in case the user has not given any value.
1790
Note that when using the embedded server, the datadirectory is not
1791
necessarily the current directory of this program. */
1793
/* It's better to use current lib, to keep paths short */
1794
current_dir[0] = FN_CURLIB;
1795
current_dir[1] = FN_LIBCHAR;
1797
default_path = current_dir;
1801
srv_set_thread_priorities = TRUE;
1802
srv_query_thread_priority = QUERY_PRIOR;
1804
/* Set InnoDB initialization parameters according to the values
1805
read from MySQL .cnf file */
1807
/*--------------- Data files -------------------------*/
1809
/* The default dir for data files is the datadir of MySQL */
1811
srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
1814
/* Set default InnoDB data file size to 10 MB and let it be
1815
auto-extending. Thus users can use InnoDB in >= 4.0 without having
1816
to specify any startup options. */
1818
if (!innobase_data_file_path) {
1819
innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
1822
/* Since InnoDB edits the argument in the next call, we make another
1825
internal_innobase_data_file_path = strdup(innobase_data_file_path);
1827
ret = (bool) srv_parse_data_file_paths_and_sizes(
1828
internal_innobase_data_file_path);
1830
errmsg_printf(ERRMSG_LVL_ERROR,
1831
"InnoDB: syntax error in innodb_data_file_path");
2151
1832
mem_free_and_error:
2152
srv_free_paths_and_sizes();
2153
if (internal_innobase_data_file_path)
2154
free(internal_innobase_data_file_path);
2158
/* -------------- Log files ---------------------------*/
2160
/* The default dir for log files is the datadir of MySQL */
2162
if (vm.count("log-group-home-dir"))
2164
innobase_log_group_home_dir= vm["log-group-home-dir"].as<string>();
2168
innobase_log_group_home_dir= getDataHome().file_string();
2172
srv_parse_log_group_home_dirs((char *)innobase_log_group_home_dir.c_str());
2174
if (ret == FALSE || innobase_mirrored_log_groups.get() != 1) {
2175
errmsg_printf(ERRMSG_LVL_ERROR,
2176
_("syntax error in innodb_log_group_home_dir, or a "
2177
"wrong number of mirrored log groups"));
2179
goto mem_free_and_error;
2183
/* Validate the file format by animal name */
2184
if (vm.count("file-format"))
2186
format_id = innobase_file_format_name_lookup(
2187
vm["file-format"].as<string>().c_str());
2189
if (format_id > DICT_TF_FORMAT_MAX) {
2191
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: wrong innodb_file_format.");
2193
goto mem_free_and_error;
2196
/* Set it to the default file format id.*/
2200
srv_file_format = format_id;
2202
innobase_file_format_name =
2203
trx_sys_file_format_id_to_name(format_id);
2205
/* Check innobase_file_format_check variable */
2206
if (!innobase_file_format_check)
2208
/* Set the value to disable checking. */
2209
srv_max_file_format_at_startup = DICT_TF_FORMAT_MAX + 1;
2211
/* Set the value to the lowest supported format. */
2212
srv_max_file_format_at_startup = DICT_TF_FORMAT_MIN;
2215
/* Did the user specify a format name that we support?
2216
As a side effect it will update the variable
2217
srv_max_file_format_at_startup */
2218
if (innobase_file_format_validate_and_set(innobase_file_format_max.c_str()) < 0)
2220
errmsg_printf(ERRMSG_LVL_ERROR, _("InnoDB: invalid "
2221
"innodb_file_format_max value: "
2222
"should be any value up to %s or its "
2223
"equivalent numeric id"),
2224
trx_sys_file_format_id_to_name(DICT_TF_FORMAT_MAX));
2225
goto mem_free_and_error;
2228
if (vm.count("change-buffering"))
2233
use < UT_ARR_SIZE(innobase_change_buffering_values);
2235
if (!innobase_strcasecmp(
2236
innobase_change_buffering.c_str(),
2237
innobase_change_buffering_values[use])) {
2238
ibuf_use = static_cast<ibuf_use_t>(use);
2239
goto innobase_change_buffering_inited_ok;
2243
errmsg_printf(ERRMSG_LVL_ERROR,
2244
"InnoDB: invalid value "
2245
"innodb_change_buffering=%s",
2246
vm["change-buffering"].as<string>().c_str());
2247
goto mem_free_and_error;
1833
srv_free_paths_and_sizes();
1834
if (internal_innobase_data_file_path)
1835
free(internal_innobase_data_file_path);
1839
/* -------------- Log files ---------------------------*/
1841
/* The default dir for log files is the datadir of MySQL */
1843
if (!innobase_log_group_home_dir) {
1844
innobase_log_group_home_dir = default_path;
1847
#ifdef UNIV_LOG_ARCHIVE
1848
/* Since innodb_log_arch_dir has no relevance under MySQL,
1849
starting from 4.0.6 we always set it the same as
1850
innodb_log_group_home_dir: */
1852
innobase_log_arch_dir = innobase_log_group_home_dir;
1854
srv_arch_dir = innobase_log_arch_dir;
1855
#endif /* UNIG_LOG_ARCHIVE */
1858
srv_parse_log_group_home_dirs(innobase_log_group_home_dir);
1860
if (ret == FALSE || innobase_mirrored_log_groups != 1) {
1861
errmsg_printf(ERRMSG_LVL_ERROR, "syntax error in innodb_log_group_home_dir, or a "
1862
"wrong number of mirrored log groups");
1864
goto mem_free_and_error;
1867
/* Validate the file format by animal name */
1868
if (innobase_file_format_name != NULL) {
1870
format_id = innobase_file_format_name_lookup(
1871
innobase_file_format_name);
1873
if (format_id > DICT_TF_FORMAT_MAX) {
1875
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: wrong innodb_file_format.");
1877
goto mem_free_and_error;
1880
/* Set it to the default file format id. Though this
1881
should never happen. */
1885
srv_file_format = format_id;
1887
/* Given the type of innobase_file_format_name we have little
1888
choice but to cast away the constness from the returned name.
1889
innobase_file_format_name is used in the MySQL set variable
1890
interface and so can't be const. */
1892
innobase_file_format_name =
1893
(char*) trx_sys_file_format_id_to_name(format_id);
1895
/* Process innobase_file_format_check variable */
1896
ut_a(innobase_file_format_check != NULL);
1898
/* As a side effect it will set srv_check_file_format_at_startup
1899
on valid input. First we check for "on"/"off". */
1900
if (!innobase_file_format_check_on_off(innobase_file_format_check)) {
1902
/* Did the user specify a format name that we support ?
1903
As a side effect it will update the variable
1904
srv_check_file_format_at_startup */
1905
if (!innobase_file_format_check_validate(
1906
innobase_file_format_check)) {
1908
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: invalid "
1909
"innodb_file_format_check value: "
1910
"should be either 'on' or 'off' or "
1911
"any value up to %s or its "
1912
"equivalent numeric id",
1913
trx_sys_file_format_id_to_name(
1914
DICT_TF_FORMAT_MAX));
1916
goto mem_free_and_error;
1920
if (innobase_change_buffering) {
1924
use < UT_ARR_SIZE(innobase_change_buffering_values);
1926
if (!innobase_strcasecmp(
1927
innobase_change_buffering,
1928
innobase_change_buffering_values[use])) {
1929
ibuf_use = (ibuf_use_t) use;
1930
goto innobase_change_buffering_inited_ok;
1934
errmsg_printf(ERRMSG_LVL_ERROR,
1935
"InnoDB: invalid value "
1936
"innodb_file_format_check=%s",
1937
innobase_change_buffering);
1938
goto mem_free_and_error;
2250
1941
innobase_change_buffering_inited_ok:
2251
ut_a((ulint) ibuf_use < UT_ARR_SIZE(innobase_change_buffering_values));
2252
innobase_change_buffering = innobase_change_buffering_values[ibuf_use];
2254
/* --------------------------------------------------*/
2256
if (vm.count("flush-method") != 0)
2258
srv_file_flush_method_str = (char *)vm["flush-method"].as<string>().c_str();
2261
srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
2262
srv_n_log_files = (ulint) innobase_log_files_in_group;
2263
srv_log_file_size = (ulint) innobase_log_file_size;
2265
srv_log_buffer_size = (ulint) innobase_log_buffer_size;
2267
srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
2268
srv_buf_pool_instances = (ulint) innobase_buffer_pool_instances;
2270
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
2272
srv_n_read_io_threads = (ulint) innobase_read_io_threads;
2273
srv_n_write_io_threads = (ulint) innobase_write_io_threads;
2275
srv_force_recovery = (ulint) innobase_force_recovery;
2277
srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
2278
srv_use_checksums = (ibool) innobase_use_checksums;
1942
ut_a((ulint) ibuf_use < UT_ARR_SIZE(innobase_change_buffering_values));
1943
innobase_change_buffering = (char*)
1944
innobase_change_buffering_values[ibuf_use];
1946
/* --------------------------------------------------*/
1948
srv_file_flush_method_str = innobase_unix_file_flush_method;
1950
srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
1951
srv_n_log_files = (ulint) innobase_log_files_in_group;
1952
srv_log_file_size = (ulint) innobase_log_file_size;
1954
#ifdef UNIV_LOG_ARCHIVE
1955
srv_log_archive_on = (ulint) innobase_log_archive;
1956
#endif /* UNIV_LOG_ARCHIVE */
1957
srv_log_buffer_size = (ulint) innobase_log_buffer_size;
1959
srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
1961
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
1963
srv_n_file_io_threads = (ulint) innobase_file_io_threads;
1964
srv_n_read_io_threads = (ulint) innobase_read_io_threads;
1965
srv_n_write_io_threads = (ulint) innobase_write_io_threads;
1967
srv_force_recovery = (ulint) innobase_force_recovery;
1969
srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
1970
srv_use_checksums = (ibool) innobase_use_checksums;
2280
1972
#ifdef HAVE_LARGE_PAGES
2281
if ((os_use_large_pages = (ibool) my_use_large_pages))
2282
os_large_page_size = (ulint) opt_large_page_size;
1973
if ((os_use_large_pages = (ibool) my_use_large_pages))
1974
os_large_page_size = (ulint) opt_large_page_size;
2285
row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
2287
srv_locks_unsafe_for_binlog = (ibool) TRUE;
2289
srv_max_n_open_files = (ulint) innobase_open_files;
2290
srv_innodb_status = (ibool) innobase_create_status_file;
2292
srv_print_verbose_log = true;
2294
/* Store the default charset-collation number of this MySQL
2297
data_mysql_default_charset_coll = (ulint)default_charset_info->number;
2299
/* Since we in this module access directly the fields of a trx
2300
struct, and due to different headers and flags it might happen that
2301
mutex_t has a different size in this module and in InnoDB
2302
modules, we check at run time that the size is the same in
2303
these compilation modules. */
2305
err = innobase_start_or_create_for_mysql();
2307
if (err != DB_SUCCESS)
2309
goto mem_free_and_error;
2312
err = dict_create_sys_replication_log();
2314
if (err != DB_SUCCESS) {
2315
goto mem_free_and_error;
2319
innobase_old_blocks_pct = buf_LRU_old_ratio_update(innobase_old_blocks_pct.get(),
2322
innobase_open_tables = hash_create(200);
2323
pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
2324
pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
2325
pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
2326
pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
2327
pthread_cond_init(&commit_cond, NULL);
2330
actuall_engine_ptr->dropTemporarySchema();
2332
status_table_function_ptr= new InnodbStatusTool;
2334
context.add(innodb_engine_ptr);
2336
context.add(status_table_function_ptr);
2338
cmp_tool= new(std::nothrow)CmpTool(false);
2339
context.add(cmp_tool);
2341
cmp_reset_tool= new(std::nothrow)CmpTool(true);
2342
context.add(cmp_reset_tool);
2344
cmp_mem_tool= new(std::nothrow)CmpmemTool(false);
2345
context.add(cmp_mem_tool);
2347
cmp_mem_reset_tool= new(std::nothrow)CmpmemTool(true);
2348
context.add(cmp_mem_reset_tool);
2350
innodb_trx_tool= new(std::nothrow)InnodbTrxTool("INNODB_TRX");
2351
context.add(innodb_trx_tool);
2353
innodb_locks_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCKS");
2354
context.add(innodb_locks_tool);
2356
innodb_lock_waits_tool= new(std::nothrow)InnodbTrxTool("INNODB_LOCK_WAITS");
2357
context.add(innodb_lock_waits_tool);
2359
innodb_sys_tables_tool= new(std::nothrow)InnodbSysTablesTool();
2360
context.add(innodb_sys_tables_tool);
2362
innodb_sys_tablestats_tool= new(std::nothrow)InnodbSysTableStatsTool();
2363
context.add(innodb_sys_tablestats_tool);
2365
innodb_sys_indexes_tool= new(std::nothrow)InnodbSysIndexesTool();
2366
context.add(innodb_sys_indexes_tool);
2368
innodb_sys_columns_tool= new(std::nothrow)InnodbSysColumnsTool();
2369
context.add(innodb_sys_columns_tool);
2371
innodb_sys_fields_tool= new(std::nothrow)InnodbSysFieldsTool();
2372
context.add(innodb_sys_fields_tool);
2374
innodb_sys_foreign_tool= new(std::nothrow)InnodbSysForeignTool();
2375
context.add(innodb_sys_foreign_tool);
2377
innodb_sys_foreign_cols_tool= new(std::nothrow)InnodbSysForeignColsTool();
2378
context.add(innodb_sys_foreign_cols_tool);
2380
context.add(new(std::nothrow)InnodbInternalTables());
2381
context.add(new(std::nothrow)InnodbReplicationTable());
2383
if (innobase_use_replication_log)
2385
replication_logger= new(std::nothrow)ReplicationLog();
2386
context.add(replication_logger);
2387
ReplicationLog::setup(replication_logger);
2390
context.registerVariable(new sys_var_const_string_val("data-home-dir", innobase_data_home_dir));
2391
context.registerVariable(new sys_var_const_string_val("flush-method",
2392
vm.count("flush-method") ? vm["flush-method"].as<string>() : ""));
2393
context.registerVariable(new sys_var_const_string_val("log-group-home-dir", innobase_log_group_home_dir));
2394
context.registerVariable(new sys_var_const_string_val("data-file-path", innobase_data_file_path));
2395
context.registerVariable(new sys_var_const_string_val("version", vm["version"].as<string>()));
2398
context.registerVariable(new sys_var_bool_ptr_readonly("replication_log", &innobase_use_replication_log));
2399
context.registerVariable(new sys_var_bool_ptr_readonly("checksums", &innobase_use_checksums));
2400
context.registerVariable(new sys_var_bool_ptr_readonly("doublewrite", &innobase_use_doublewrite));
2401
context.registerVariable(new sys_var_bool_ptr("file-per-table", &srv_file_per_table));
2402
context.registerVariable(new sys_var_bool_ptr_readonly("file-format-check", &innobase_file_format_check));
2403
context.registerVariable(new sys_var_bool_ptr("adaptive-flushing", &srv_adaptive_flushing));
2404
context.registerVariable(new sys_var_bool_ptr("status-file", &innobase_create_status_file));
2405
context.registerVariable(new sys_var_bool_ptr_readonly("use-sys-malloc", &srv_use_sys_malloc));
2406
context.registerVariable(new sys_var_bool_ptr_readonly("use-native-aio", &srv_use_native_aio));
2408
context.registerVariable(new sys_var_bool_ptr("support-xa", &support_xa));
2409
context.registerVariable(new sys_var_bool_ptr("strict_mode", &strict_mode));
2410
context.registerVariable(new sys_var_constrained_value<uint32_t>("lock_wait_timeout", lock_wait_timeout));
2412
context.registerVariable(new sys_var_constrained_value_readonly<size_t>("additional_mem_pool_size",innobase_additional_mem_pool_size));
2413
context.registerVariable(new sys_var_constrained_value<uint32_t>("autoextend_increment",
2414
innodb_auto_extend_increment,
2415
auto_extend_update));
2416
context.registerVariable(new sys_var_constrained_value<uint32_t>("io_capacity",
2418
io_capacity_update));
2419
context.registerVariable(new sys_var_constrained_value<uint32_t>("purge_batch_size",
2420
innodb_purge_batch_size,
2421
purge_batch_update));
2422
context.registerVariable(new sys_var_constrained_value<uint32_t>("purge_threads",
2423
innodb_n_purge_threads,
2424
purge_threads_update));
2425
context.registerVariable(new sys_var_constrained_value<uint16_t>("fast_shutdown", innobase_fast_shutdown));
2426
context.registerVariable(new sys_var_std_string("file_format",
2427
innobase_file_format_name,
2428
innodb_file_format_name_validate));
2429
context.registerVariable(new sys_var_std_string("change_buffering",
2430
innobase_change_buffering,
2431
innodb_change_buffering_validate));
2432
context.registerVariable(new sys_var_std_string("file_format_max",
2433
innobase_file_format_max,
2434
innodb_file_format_max_validate));
2435
context.registerVariable(new sys_var_constrained_value_readonly<size_t>("buffer_pool_size", innobase_buffer_pool_size));
2436
context.registerVariable(new sys_var_constrained_value_readonly<int64_t>("log_file_size", innobase_log_file_size));
2437
context.registerVariable(new sys_var_constrained_value_readonly<uint16_t>("flush_log_at_trx_commit",
2438
innodb_flush_log_at_trx_commit));
2439
context.registerVariable(new sys_var_constrained_value_readonly<unsigned int>("max_dirty_pages_pct",
2440
innodb_max_dirty_pages_pct));
2441
context.registerVariable(new sys_var_constrained_value_readonly<uint64_t>("max_purge_lag", innodb_max_purge_lag));
2442
context.registerVariable(new sys_var_constrained_value_readonly<uint64_t>("stats_sample_pages", innodb_stats_sample_pages));
2443
context.registerVariable(new sys_var_bool_ptr("adaptive_hash_index", &btr_search_enabled, innodb_adaptive_hash_index_update));
2445
context.registerVariable(new sys_var_constrained_value<uint32_t>("commit_concurrency",
2446
innobase_commit_concurrency,
2447
innodb_commit_concurrency_validate));
2448
context.registerVariable(new sys_var_constrained_value<uint32_t>("concurrency_tickets",
2449
innodb_concurrency_tickets));
2450
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("read_io_threads", innobase_read_io_threads));
2451
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("write_io_threads", innobase_write_io_threads));
2452
context.registerVariable(new sys_var_constrained_value_readonly<uint64_t>("replication_delay", innodb_replication_delay));
2453
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("force_recovery", innobase_force_recovery));
2454
context.registerVariable(new sys_var_constrained_value_readonly<size_t>("log_buffer_size", innobase_log_buffer_size));
2455
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("log_files_in_group", innobase_log_files_in_group));
2456
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("mirrored_log_groups", innobase_mirrored_log_groups));
2457
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("open_files", innobase_open_files));
2458
context.registerVariable(new sys_var_constrained_value<uint32_t>("old_blocks_pct",
2459
innobase_old_blocks_pct,
2460
innodb_old_blocks_pct_update));
2461
context.registerVariable(new sys_var_uint32_t_ptr("old_blocks_time", &buf_LRU_old_threshold_ms));
2462
context.registerVariable(new sys_var_constrained_value<uint32_t>("sync_spin_loops", innodb_sync_spin_loops, innodb_sync_spin_loops_update));
2463
context.registerVariable(new sys_var_constrained_value<uint32_t>("spin_wait_delay", innodb_spin_wait_delay, innodb_spin_wait_delay_update));
2464
context.registerVariable(new sys_var_constrained_value<uint32_t>("thread_sleep_delay", innodb_thread_sleep_delay, innodb_thread_sleep_delay_update));
2465
context.registerVariable(new sys_var_constrained_value<uint32_t>("thread_concurrency",
2466
innobase_thread_concurrency,
2467
innodb_thread_concurrency_update));
2468
context.registerVariable(new sys_var_constrained_value<uint32_t>("read_ahead_threshold",
2469
innodb_read_ahead_threshold,
2470
innodb_read_ahead_threshold_update));
2471
/* Get the current high water mark format. */
2472
innobase_file_format_max = trx_sys_file_format_max_get();
2473
btr_search_fully_disabled = (!btr_search_enabled);
1977
row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
1979
srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;
1981
srv_max_n_open_files = (ulint) innobase_open_files;
1982
srv_innodb_status = (ibool) innobase_create_status_file;
1984
srv_print_verbose_log = true;
1986
/* Store the default charset-collation number of this MySQL
1989
data_mysql_default_charset_coll = (ulint)default_charset_info->number;
1992
innobase_commit_concurrency_init_default();
1994
/* Since we in this module access directly the fields of a trx
1995
struct, and due to different headers and flags it might happen that
1996
mutex_t has a different size in this module and in InnoDB
1997
modules, we check at run time that the size is the same in
1998
these compilation modules. */
2000
err = innobase_start_or_create_for_mysql();
2002
if (err != DB_SUCCESS) {
2003
goto mem_free_and_error;
2006
innobase_open_tables = hash_create(200);
2007
pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
2008
pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
2009
pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
2010
pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
2011
pthread_cond_init(&commit_cond, NULL);
2014
if (innodb_locks_init() ||
2015
innodb_trx_init() ||
2016
innodb_lock_waits_init() ||
2018
i_s_cmp_reset_init() ||
2019
i_s_cmpmem_init() ||
2020
i_s_cmpmem_reset_init())
2023
registry.add(innodb_engine_ptr);
2025
registry.add(innodb_trx_schema_table);
2026
registry.add(innodb_locks_schema_table);
2027
registry.add(innodb_lock_waits_schema_table);
2028
registry.add(innodb_cmp_schema_table);
2029
registry.add(innodb_cmp_reset_schema_table);
2030
registry.add(innodb_cmpmem_schema_table);
2031
registry.add(innodb_cmpmem_reset_schema_table);
2033
/* Get the current high water mark format. */
2034
innobase_file_format_check = (char*) trx_sys_file_format_max_get();
2041
/*******************************************************************//**
2042
Closes an InnoDB database.
2043
@return TRUE if error */
2046
innobase_deinit(plugin::Registry ®istry)
2049
i_s_common_deinit(registry);
2050
registry.remove(innodb_engine_ptr);
2051
delete innodb_engine_ptr;
2053
if (innodb_inited) {
2055
srv_fast_shutdown = (ulint) innobase_fast_shutdown;
2057
hash_table_free(innobase_open_tables);
2058
innobase_open_tables = NULL;
2059
if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
2062
srv_free_paths_and_sizes();
2063
if (internal_innobase_data_file_path)
2064
free(internal_innobase_data_file_path);
2065
pthread_mutex_destroy(&innobase_share_mutex);
2066
pthread_mutex_destroy(&prepare_commit_mutex);
2067
pthread_mutex_destroy(&commit_threads_m);
2068
pthread_mutex_destroy(&commit_cond_m);
2069
pthread_cond_destroy(&commit_cond);
2481
2075
/****************************************************************//**
2482
2076
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
2483
2077
the logs, and the name of this function should be innobase_checkpoint.
2484
@return TRUE if error */
2078
@return TRUE if error */
2486
2080
InnobaseEngine::flush_logs()
2487
2081
/*=====================*/
2491
assert(this == innodb_engine_ptr);
2493
log_buffer_flush_to_disk();
2085
assert(this == innodb_engine_ptr);
2087
log_buffer_flush_to_disk();
2498
2092
/*****************************************************************//**
2516
2110
Starts a new InnoDB transaction if a transaction is not yet started. And
2517
2111
assigns a new snapshot for a consistent read if the transaction does not yet
2521
InnobaseEngine::doStartTransaction(
2115
InnobaseEngine::start_consistent_snapshot(
2522
2116
/*====================================*/
2523
Session* session, /*!< in: MySQL thread handle of the user for whom
2524
the transaction should be committed */
2525
start_transaction_option_t options)
2117
Session* session) /*!< in: MySQL thread handle of the user for whom
2118
the transaction should be committed */
2527
assert(this == innodb_engine_ptr);
2529
/* Create a new trx struct for session, if it does not yet have one */
2530
trx_t *trx = check_trx_exists(session);
2532
/* This is just to play safe: release a possible FIFO ticket and
2533
search latch. Since we will reserve the kernel mutex, we have to
2534
release the search system latch first to obey the latching order. */
2535
innobase_release_stat_resources(trx);
2537
/* If the transaction is not started yet, start it */
2538
trx_start_if_not_started(trx);
2540
/* Assign a read view if the transaction does not have it yet */
2541
if (options == START_TRANS_OPT_WITH_CONS_SNAPSHOT)
2542
trx_assign_read_view(trx);
2122
assert(this == innodb_engine_ptr);
2124
/* Create a new trx struct for session, if it does not yet have one */
2126
trx = check_trx_exists(session);
2128
/* This is just to play safe: release a possible FIFO ticket and
2129
search latch. Since we will reserve the kernel mutex, we have to
2130
release the search system latch first to obey the latching order. */
2132
innobase_release_stat_resources(trx);
2134
/* If the transaction is not started yet, start it */
2136
trx_start_if_not_started(trx);
2138
/* Assign a read view if the transaction does not have it yet */
2140
trx_assign_read_view(trx);
2142
/* Set the MySQL flag to mark that there is an active transaction */
2144
if (trx->active_trans == 0) {
2145
innobase_register_trx_and_stmt(this, current_session);
2146
trx->active_trans = 1;
2547
2152
/*****************************************************************//**
2548
2153
Commits a transaction in an InnoDB database or marks an SQL statement
2552
InnobaseEngine::doCommit(
2157
InnobaseEngine::commit(
2553
2158
/*============*/
2554
Session* session, /*!< in: MySQL thread handle of the user for whom
2555
the transaction should be committed */
2556
bool all) /*!< in: TRUE - commit transaction
2557
FALSE - the current SQL statement ended */
2159
Session* session, /*!< in: MySQL thread handle of the user for whom
2160
the transaction should be committed */
2161
bool all) /*!< in: TRUE - commit transaction
2162
FALSE - the current SQL statement ended */
2561
assert(this == innodb_engine_ptr);
2563
trx = check_trx_exists(session);
2565
/* Since we will reserve the kernel mutex, we have to release
2566
the search system latch first to obey the latching order. */
2568
if (trx->has_search_latch) {
2569
trx_search_latch_release_if_reserved(trx);
2573
|| (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
2575
/* We were instructed to commit the whole transaction, or
2576
this is an SQL statement end and autocommit is on */
2578
/* We need current binlog position for ibbackup to work.
2579
Note, the position is current because of
2580
prepare_commit_mutex */
2166
assert(this == innodb_engine_ptr);
2168
trx = check_trx_exists(session);
2170
/* Since we will reserve the kernel mutex, we have to release
2171
the search system latch first to obey the latching order. */
2173
if (trx->has_search_latch) {
2174
trx_search_latch_release_if_reserved(trx);
2177
/* The flag trx->active_trans is set to 1 in
2179
1. ::external_lock(),
2181
3. innobase_query_caching_of_table_permitted(),
2182
4. InnobaseEngine::savepoint_set(),
2183
5. ::init_table_handle_for_HANDLER(),
2184
6. InnobaseEngine::start_consistent_snapshot(),
2186
and it is only set to 0 in a commit or a rollback. If it is 0 we know
2187
there cannot be resources to be freed and we could return immediately.
2188
For the time being, we play safe and do the cleanup though there should
2189
be nothing to clean up. */
2191
if (trx->active_trans == 0
2192
&& trx->conc_state != TRX_NOT_STARTED) {
2194
errmsg_printf(ERRMSG_LVL_ERROR, "trx->active_trans == 0, but"
2195
" trx->conc_state != TRX_NOT_STARTED");
2198
|| (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
2200
/* We were instructed to commit the whole transaction, or
2201
this is an SQL statement end and autocommit is on */
2203
/* We need current binlog position for ibbackup to work.
2204
Note, the position is current because of
2205
prepare_commit_mutex */
2582
if (innobase_commit_concurrency.get() > 0) {
2583
pthread_mutex_lock(&commit_cond_m);
2207
if (innobase_commit_concurrency > 0) {
2208
pthread_mutex_lock(&commit_cond_m);
2586
if (commit_threads > innobase_commit_concurrency.get()) {
2588
pthread_cond_wait(&commit_cond,
2590
pthread_mutex_unlock(&commit_cond_m);
2594
pthread_mutex_unlock(&commit_cond_m);
2211
if (commit_threads > innobase_commit_concurrency) {
2213
pthread_cond_wait(&commit_cond,
2215
pthread_mutex_unlock(&commit_cond_m);
2219
pthread_mutex_unlock(&commit_cond_m);
2598
2223
/* Store transaction point for binlog
2599
Later logic tests that this is set to _something_. We need
2600
that logic to fire, even though we do not have a real name. */
2601
trx->mysql_log_file_name = "UNUSED";
2602
trx->mysql_log_offset = 0;
2604
/* Don't do write + flush right now. For group commit
2605
to work we want to do the flush after releasing the
2606
prepare_commit_mutex. */
2607
trx->flush_log_later = TRUE;
2608
innobase_commit_low(trx);
2609
trx->flush_log_later = FALSE;
2611
if (innobase_commit_concurrency.get() > 0) {
2612
pthread_mutex_lock(&commit_cond_m);
2614
pthread_cond_signal(&commit_cond);
2615
pthread_mutex_unlock(&commit_cond_m);
2618
/* Now do a write + flush of logs. */
2619
trx_commit_complete_for_mysql(trx);
2622
/* We just mark the SQL statement ended and do not do a
2623
transaction commit */
2625
/* If we had reserved the auto-inc lock for some
2626
table in this SQL statement we release it now */
2628
row_unlock_table_autoinc_for_mysql(trx);
2630
/* Store the current undo_no of the transaction so that we
2631
know where to roll back if we have to roll back the next
2634
trx_mark_sql_stat_end(trx);
2636
if (! session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
2638
if (trx->conc_state != TRX_NOT_STARTED)
2640
commit(session, TRUE);
2645
trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
2647
if (trx->declared_to_be_inside_innodb) {
2648
/* Release our possible ticket in the FIFO */
2650
srv_conc_force_exit_innodb(trx);
2653
/* Tell the InnoDB server that there might be work for utility
2655
srv_active_wake_master_thread();
2657
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
2658
trx->global_read_view)
2660
/* At low transaction isolation levels we let
2661
each consistent read set its own snapshot */
2662
read_view_close_for_mysql(trx);
2224
Later logic tests that this is set to _something_. We need
2225
that logic to fire, even though we do not have a real name. */
2226
trx->mysql_log_file_name = "UNUSED";
2227
trx->mysql_log_offset = 0;
2229
/* Don't do write + flush right now. For group commit
2230
to work we want to do the flush after releasing the
2231
prepare_commit_mutex. */
2232
trx->flush_log_later = TRUE;
2233
innobase_commit_low(trx);
2234
trx->flush_log_later = FALSE;
2236
if (innobase_commit_concurrency > 0) {
2237
pthread_mutex_lock(&commit_cond_m);
2239
pthread_cond_signal(&commit_cond);
2240
pthread_mutex_unlock(&commit_cond_m);
2243
if (trx->active_trans == 2) {
2245
pthread_mutex_unlock(&prepare_commit_mutex);
2248
/* Now do a write + flush of logs. */
2249
trx_commit_complete_for_mysql(trx);
2250
trx->active_trans = 0;
2253
/* We just mark the SQL statement ended and do not do a
2254
transaction commit */
2256
/* If we had reserved the auto-inc lock for some
2257
table in this SQL statement we release it now */
2259
row_unlock_table_autoinc_for_mysql(trx);
2261
/* Store the current undo_no of the transaction so that we
2262
know where to roll back if we have to roll back the next
2265
trx_mark_sql_stat_end(trx);
2268
trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
2270
if (trx->declared_to_be_inside_innodb) {
2271
/* Release our possible ticket in the FIFO */
2273
srv_conc_force_exit_innodb(trx);
2276
/* Tell the InnoDB server that there might be work for utility
2278
srv_active_wake_master_thread();
2668
2283
/*****************************************************************//**
2669
2284
Rolls back a transaction or the latest SQL statement.
2670
@return 0 or error number */
2285
@return 0 or error number */
2672
InnobaseEngine::doRollback(
2287
InnobaseEngine::rollback(
2673
2288
/*==============*/
2674
Session* session,/*!< in: handle to the MySQL thread of the user
2675
whose transaction should be rolled back */
2676
bool all) /*!< in: TRUE - commit transaction
2677
FALSE - the current SQL statement ended */
2289
Session* session,/*!< in: handle to the MySQL thread of the user
2290
whose transaction should be rolled back */
2291
bool all) /*!< in: TRUE - commit transaction
2292
FALSE - the current SQL statement ended */
2682
assert(this == innodb_engine_ptr);
2684
trx = check_trx_exists(session);
2686
/* Release a possible FIFO ticket and search latch. Since we will
2687
reserve the kernel mutex, we have to release the search system latch
2688
first to obey the latching order. */
2690
innobase_release_stat_resources(trx);
2692
trx->n_autoinc_rows = 0;
2694
/* If we had reserved the auto-inc lock for some table (if
2695
we come here to roll back the latest SQL statement) we
2696
release it now before a possibly lengthy rollback */
2698
row_unlock_table_autoinc_for_mysql(trx);
2701
|| !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
2703
error = trx_rollback_for_mysql(trx);
2705
error = trx_rollback_last_sql_stat_for_mysql(trx);
2708
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
2709
trx->global_read_view)
2711
/* At low transaction isolation levels we let
2712
each consistent read set its own snapshot */
2713
read_view_close_for_mysql(trx);
2716
return(convert_error_code_to_mysql(error, 0, NULL));
2297
assert(this == innodb_engine_ptr);
2299
trx = check_trx_exists(session);
2301
/* Release a possible FIFO ticket and search latch. Since we will
2302
reserve the kernel mutex, we have to release the search system latch
2303
first to obey the latching order. */
2305
innobase_release_stat_resources(trx);
2307
/* If we had reserved the auto-inc lock for some table (if
2308
we come here to roll back the latest SQL statement) we
2309
release it now before a possibly lengthy rollback */
2311
row_unlock_table_autoinc_for_mysql(trx);
2314
|| !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
2316
error = trx_rollback_for_mysql(trx);
2317
trx->active_trans = 0;
2319
error = trx_rollback_last_sql_stat_for_mysql(trx);
2322
return(convert_error_code_to_mysql(error, 0, NULL));
2719
2325
/*****************************************************************//**
2720
2326
Rolls back a transaction
2721
@return 0 or error number */
2327
@return 0 or error number */
2724
2330
innobase_rollback_trx(
2725
2331
/*==================*/
2726
trx_t* trx) /*!< in: transaction */
2332
trx_t* trx) /*!< in: transaction */
2730
/* Release a possible FIFO ticket and search latch. Since we will
2731
reserve the kernel mutex, we have to release the search system latch
2732
first to obey the latching order. */
2734
innobase_release_stat_resources(trx);
2736
/* If we had reserved the auto-inc lock for some table (if
2737
we come here to roll back the latest SQL statement) we
2738
release it now before a possibly lengthy rollback */
2740
row_unlock_table_autoinc_for_mysql(trx);
2742
error = trx_rollback_for_mysql(trx);
2744
return(convert_error_code_to_mysql(error, 0, NULL));
2336
/* Release a possible FIFO ticket and search latch. Since we will
2337
reserve the kernel mutex, we have to release the search system latch
2338
first to obey the latching order. */
2340
innobase_release_stat_resources(trx);
2342
/* If we had reserved the auto-inc lock for some table (if
2343
we come here to roll back the latest SQL statement) we
2344
release it now before a possibly lengthy rollback */
2346
row_unlock_table_autoinc_for_mysql(trx);
2348
error = trx_rollback_for_mysql(trx);
2350
return(convert_error_code_to_mysql(error, 0, NULL));
2747
2353
/*****************************************************************//**
2948
2595
normalize_table_name(
2949
2596
/*=================*/
2950
char* norm_name, /*!< out: normalized name as a
2951
null-terminated string */
2952
const char* name) /*!< in: table name string */
2597
char* norm_name, /*!< out: normalized name as a
2598
null-terminated string */
2599
const char* name) /*!< in: table name string */
2954
const char* name_ptr;
2958
/* Scan name from the end */
2960
ptr = strchr(name, '\0')-1;
2962
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2972
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2978
memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
2980
norm_name[name_ptr - db_ptr - 1] = '/';
2601
const char* name_ptr;
2605
/* Scan name from the end */
2607
ptr = strchr(name, '\0')-1;
2609
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2619
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
2625
memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
2627
norm_name[name_ptr - db_ptr - 1] = '/';
2983
innobase_casedn_str(norm_name);
2630
innobase_casedn_str(norm_name);
2987
2634
/********************************************************************//**
2988
Get the upper limit of the MySQL integral and floating-point type.
2989
@return maximum allowed value for the field */
2992
innobase_get_int_col_max_value(
2993
/*===========================*/
2994
const Field* field) /*!< in: MySQL field */
2996
uint64_t max_value = 0;
2998
switch(field->key_type()) {
3000
case HA_KEYTYPE_BINARY:
3001
max_value = 0xFFULL;
3004
case HA_KEYTYPE_ULONG_INT:
3005
max_value = 0xFFFFFFFFULL;
3007
case HA_KEYTYPE_LONG_INT:
3008
max_value = 0x7FFFFFFFULL;
3011
case HA_KEYTYPE_ULONGLONG:
3012
max_value = 0xFFFFFFFFFFFFFFFFULL;
3014
case HA_KEYTYPE_LONGLONG:
3015
max_value = 0x7FFFFFFFFFFFFFFFULL;
3017
case HA_KEYTYPE_DOUBLE:
3018
/* We use the maximum as per IEEE754-2008 standard, 2^53 */
3019
max_value = 0x20000000000000ULL;
3028
/*******************************************************************//**
3029
This function checks whether the index column information
3030
is consistent between KEY info from mysql and that from innodb index.
3031
@return TRUE if all column types match. */
3034
innobase_match_index_columns(
3035
/*=========================*/
3036
const KeyInfo* key_info, /*!< in: Index info
3038
const dict_index_t* index_info) /*!< in: Index info
3041
const KeyPartInfo* key_part;
3042
const KeyPartInfo* key_end;
3043
const dict_field_t* innodb_idx_fld;
3044
const dict_field_t* innodb_idx_fld_end;
3046
/* Check whether user defined index column count matches */
3047
if (key_info->key_parts != index_info->n_user_defined_cols) {
3051
key_part = key_info->key_part;
3052
key_end = key_part + key_info->key_parts;
3053
innodb_idx_fld = index_info->fields;
3054
innodb_idx_fld_end = index_info->fields + index_info->n_fields;
3056
/* Check each index column's datatype. We do not check
3057
column name because there exists case that index
3058
column name got modified in mysql but such change does not
3059
propagate to InnoDB.
3060
One hidden assumption here is that the index column sequences
3061
are matched up between those in mysql and Innodb. */
3062
for (; key_part != key_end; ++key_part) {
3065
ulint mtype = innodb_idx_fld->col->mtype;
3067
/* Need to translate to InnoDB column type before
3069
col_type = get_innobase_type_from_mysql_type(&is_unsigned,
3072
/* Ignore Innodb specific system columns. */
3073
while (mtype == DATA_SYS) {
3076
if (innodb_idx_fld >= innodb_idx_fld_end) {
3081
if (col_type != mtype) {
3082
/* Column Type mismatches */
3092
/*******************************************************************//**
3093
This function builds a translation table in INNOBASE_SHARE
3094
structure for fast index location with mysql array number from its
3095
table->key_info structure. This also provides the necessary translation
3096
between the key order in mysql key_info and Innodb ib_table->indexes if
3097
they are not fully matched with each other.
3098
Note we do not have any mutex protecting the translation table
3099
building based on the assumption that there is no concurrent
3100
index creation/drop and DMLs that requires index lookup. All table
3101
handle will be closed before the index creation/drop.
3102
@return TRUE if index translation table built successfully */
3105
innobase_build_index_translation(
3106
/*=============================*/
3107
const Table* table, /*!< in: table in MySQL data
3109
dict_table_t* ib_table, /*!< in: table in Innodb data
3111
INNOBASE_SHARE* share) /*!< in/out: share structure
3112
where index translation table
3113
will be constructed in. */
3115
ulint mysql_num_index;
3117
dict_index_t** index_mapping;
3120
mutex_enter(&dict_sys->mutex);
3122
mysql_num_index = table->getShare()->keys;
3123
ib_num_index = UT_LIST_GET_LEN(ib_table->indexes);
3125
index_mapping = share->idx_trans_tbl.index_mapping;
3127
/* If there exists inconsistency between MySQL and InnoDB dictionary
3128
(metadata) information, the number of index defined in MySQL
3129
could exceed that in InnoDB, do not build index translation
3130
table in such case */
3131
if (UNIV_UNLIKELY(ib_num_index < mysql_num_index)) {
3136
/* If index entry count is non-zero, nothing has
3137
changed since last update, directly return TRUE */
3138
if (share->idx_trans_tbl.index_count) {
3139
/* Index entry count should still match mysql_num_index */
3140
ut_a(share->idx_trans_tbl.index_count == mysql_num_index);
3144
/* The number of index increased, rebuild the mapping table */
3145
if (mysql_num_index > share->idx_trans_tbl.array_size) {
3146
index_mapping = (dict_index_t**) realloc(index_mapping,
3148
sizeof(*index_mapping));
3150
if (!index_mapping) {
3151
/* Report an error if index_mapping continues to be
3152
NULL and mysql_num_index is a non-zero value */
3153
errmsg_printf(ERRMSG_LVL_ERROR,
3154
"InnoDB: fail to allocate memory for "
3155
"index translation table. Number of "
3156
"Index:%lu, array size:%lu",
3158
share->idx_trans_tbl.array_size);
3163
share->idx_trans_tbl.array_size = mysql_num_index;
3166
/* For each index in the mysql key_info array, fetch its
3167
corresponding InnoDB index pointer into index_mapping
3169
for (ulint count = 0; count < mysql_num_index; count++) {
3171
/* Fetch index pointers into index_mapping according to mysql
3173
index_mapping[count] = dict_table_get_index_on_name(
3174
ib_table, table->key_info[count].name);
3176
if (!index_mapping[count]) {
3177
errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find index %s in InnoDB "
3178
"index dictionary.",
3179
table->key_info[count].name);
3184
/* Double check fetched index has the same
3185
column info as those in mysql key_info. */
3186
if (!innobase_match_index_columns(&table->key_info[count],
3187
index_mapping[count])) {
3188
errmsg_printf(ERRMSG_LVL_ERROR, "Found index %s whose column info "
3189
"does not match that of MySQL.",
3190
table->key_info[count].name);
3196
/* Successfully built the translation table */
3197
share->idx_trans_tbl.index_count = mysql_num_index;
3201
/* Build translation table failed. */
3202
free(index_mapping);
3204
share->idx_trans_tbl.array_size = 0;
3205
share->idx_trans_tbl.index_count = 0;
3206
index_mapping = NULL;
3209
share->idx_trans_tbl.index_mapping = index_mapping;
3211
mutex_exit(&dict_sys->mutex);
3216
/*******************************************************************//**
3217
This function uses index translation table to quickly locate the
3218
requested index structure.
3219
Note we do not have mutex protection for the index translatoin table
3220
access, it is based on the assumption that there is no concurrent
3221
translation table rebuild (fter create/drop index) and DMLs that
3222
require index lookup.
3223
@return dict_index_t structure for requested index. NULL if
3224
fail to locate the index structure. */
3227
innobase_index_lookup(
3228
/*==================*/
3229
INNOBASE_SHARE* share, /*!< in: share structure for index
3230
translation table. */
3231
uint keynr) /*!< in: index number for the requested
3234
if (!share->idx_trans_tbl.index_mapping
3235
|| keynr >= share->idx_trans_tbl.index_count) {
3239
return(share->idx_trans_tbl.index_mapping[keynr]);
3242
/********************************************************************//**
3243
2635
Set the autoinc column max value. This should only be called once from
3244
ha_innobase::open(). Therefore there's no need for a covering lock. */
2636
ha_innobase::open(). Therefore there's no need for a covering lock.
2637
@return DB_SUCCESS or error code */
3247
2640
ha_innobase::innobase_initialize_autoinc()
3248
2641
/*======================================*/
3251
const Field* field = getTable()->found_next_number_field;
3253
if (field != NULL) {
3254
auto_inc = innobase_get_int_col_max_value(field);
3256
/* We have no idea what's been passed in to us as the
3257
autoinc column. We set it to the 0, effectively disabling
3258
updates to the table. */
3261
ut_print_timestamp(stderr);
3262
fprintf(stderr, " InnoDB: Unable to determine the AUTOINC "
3266
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
3267
/* If the recovery level is set so high that writes
3268
are disabled we force the AUTOINC counter to 0
3269
value effectively disabling writes to the table.
3270
Secondly, we avoid reading the table in case the read
3271
results in failure due to a corrupted table/index.
3273
We will not return an error to the client, so that the
3274
tables can be dumped with minimal hassle. If an error
3275
were returned in this case, the first attempt to read
3276
the table would fail and subsequent SELECTs would succeed. */
3278
} else if (field == NULL) {
3279
/* This is a far more serious error, best to avoid
3280
opening the table and return failure. */
3281
my_error(ER_AUTOINC_READ_FAILED, MYF(0));
3283
dict_index_t* index;
3284
const char* col_name;
3285
uint64_t read_auto_inc;
3288
update_session(getTable()->in_use);
3289
col_name = field->field_name;
3291
ut_a(prebuilt->trx == session_to_trx(user_session));
3293
index = innobase_get_index(getTable()->getShare()->next_number_index);
3295
/* Execute SELECT MAX(col_name) FROM TABLE; */
3296
err = row_search_max_autoinc(index, col_name, &read_auto_inc);
3300
uint64_t col_max_value;
3302
col_max_value = innobase_get_int_col_max_value(field);
3304
/* At the this stage we do not know the increment
3305
nor the offset, so use a default increment of 1. */
3307
auto_inc = innobase_next_autoinc(read_auto_inc, 1, 1, col_max_value);
3311
case DB_RECORD_NOT_FOUND:
3312
ut_print_timestamp(stderr);
3313
fprintf(stderr, " InnoDB: MySQL and InnoDB data "
3314
"dictionaries are out of sync.\n"
3315
"InnoDB: Unable to find the AUTOINC column "
3316
"%s in the InnoDB table %s.\n"
3317
"InnoDB: We set the next AUTOINC column "
3319
"InnoDB: in effect disabling the AUTOINC "
3320
"next value generation.\n"
3321
"InnoDB: You can either set the next "
3322
"AUTOINC value explicitly using ALTER TABLE\n"
3323
"InnoDB: or fix the data dictionary by "
3324
"recreating the table.\n",
3325
col_name, index->table->name);
3327
/* This will disable the AUTOINC generation. */
3330
/* We want the open to succeed, so that the user can
3331
take corrective action. ie. reads should succeed but
3332
updates should fail. */
3336
/* row_search_max_autoinc() should only return
3337
one of DB_SUCCESS or DB_RECORD_NOT_FOUND. */
3342
dict_table_autoinc_initialize(prebuilt->table, auto_inc);
2643
dict_index_t* index;
2645
const char* col_name;
2648
col_name = table->found_next_number_field->field_name;
2649
index = innobase_get_index(table->s->next_number_index);
2651
/* Execute SELECT MAX(col_name) FROM TABLE; */
2652
error = row_search_max_autoinc(index, col_name, &auto_inc);
2657
/* At the this stage we don't know the increment
2658
or the offset, so use default inrement of 1. */
2662
case DB_RECORD_NOT_FOUND:
2663
ut_print_timestamp(stderr);
2664
fprintf(stderr, " InnoDB: MySQL and InnoDB data "
2665
"dictionaries are out of sync.\n"
2666
"InnoDB: Unable to find the AUTOINC column %s in the "
2667
"InnoDB table %s.\n"
2668
"InnoDB: We set the next AUTOINC column value to the "
2669
"maximum possible value,\n"
2670
"InnoDB: in effect disabling the AUTOINC next value "
2672
"InnoDB: You can either set the next AUTOINC value "
2673
"explicitly using ALTER TABLE\n"
2674
"InnoDB: or fix the data dictionary by recreating "
2676
col_name, index->table->name);
2678
auto_inc = 0xFFFFFFFFFFFFFFFFULL;
2685
dict_table_autoinc_initialize(prebuilt->table, auto_inc);
3345
2690
/*****************************************************************//**
3346
2691
Creates and opens a handle to a table which already exists in an InnoDB
3348
@return 1 if error, 0 if success */
2693
@return 1 if error, 0 if success */
3351
ha_innobase::doOpen(const TableIdentifier &identifier,
3352
int mode, /*!< in: not used */
3353
uint test_if_locked) /*!< in: not used */
2698
const char* name, /*!< in: table name */
2699
int mode, /*!< in: not used */
2700
uint test_if_locked) /*!< in: not used */
3355
dict_table_t* ib_table;
3356
char norm_name[FN_REFLEN];
3360
UT_NOT_USED(test_if_locked);
3362
session= getTable()->in_use;
3364
/* Under some cases Drizzle seems to call this function while
3365
holding btr_search_latch. This breaks the latching order as
3366
we acquire dict_sys->mutex below and leads to a deadlock. */
3367
if (session != NULL) {
3368
getTransactionalEngine()->releaseTemporaryLatches(session);
3371
normalize_table_name(norm_name, identifier.getPath().c_str());
3373
user_session = NULL;
3375
if (!(share=get_share(identifier.getPath().c_str()))) {
3380
/* Create buffers for packing the fields of a record. Why
3381
table->stored_rec_length did not work here? Obviously, because char
3382
fields when packed actually became 1 byte longer, when we also
3383
stored the string length as the first byte. */
3385
upd_and_key_val_buff_len =
3386
getTable()->getShare()->stored_rec_length
3387
+ getTable()->getShare()->max_key_length
3388
+ MAX_REF_PARTS * 3;
3390
upd_buff.resize(upd_and_key_val_buff_len);
3392
if (upd_buff.size() < upd_and_key_val_buff_len)
3397
key_val_buff.resize(upd_and_key_val_buff_len);
3398
if (key_val_buff.size() < upd_and_key_val_buff_len)
3403
/* Get pointer to a table object in InnoDB dictionary cache */
3404
ib_table = dict_table_get(norm_name, TRUE);
3406
if (NULL == ib_table) {
3407
errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find or open table %s from\n"
3408
"the internal data dictionary of InnoDB "
3409
"though the .frm file for the\n"
3410
"table exists. Maybe you have deleted and "
3411
"recreated InnoDB data\n"
3412
"files but have forgotten to delete the "
3413
"corresponding .frm files\n"
3414
"of InnoDB tables, or you have moved .frm "
3415
"files to another database?\n"
3416
"or, the table contains indexes that this "
3417
"version of the engine\n"
3418
"doesn't support.\n"
3419
"See " REFMAN "innodb-troubleshooting.html\n"
3420
"how you can resolve the problem.\n",
3424
key_val_buff.resize(0);
3427
return(HA_ERR_NO_SUCH_TABLE);
3430
if (ib_table->ibd_file_missing && !session_tablespace_op(session)) {
3431
errmsg_printf(ERRMSG_LVL_ERROR, "MySQL is trying to open a table handle but "
3432
"the .ibd file for\ntable %s does not exist.\n"
3433
"Have you deleted the .ibd file from the "
3434
"database directory under\nthe MySQL datadir, "
3435
"or have you used DISCARD TABLESPACE?\n"
3436
"See " REFMAN "innodb-troubleshooting.html\n"
3437
"how you can resolve the problem.\n",
3441
key_val_buff.resize(0);
3444
dict_table_decrement_handle_count(ib_table, FALSE);
3445
return(HA_ERR_NO_SUCH_TABLE);
3448
prebuilt = row_create_prebuilt(ib_table);
3450
prebuilt->mysql_row_len = getTable()->getShare()->stored_rec_length;
3451
prebuilt->default_rec = getTable()->getDefaultValues();
3452
ut_ad(prebuilt->default_rec);
3454
/* Looks like MySQL-3.23 sometimes has primary key number != 0 */
3456
primary_key = getTable()->getShare()->getPrimaryKey();
3457
key_used_on_scan = primary_key;
3459
if (!innobase_build_index_translation(getTable(), ib_table, share)) {
3460
errmsg_printf(ERRMSG_LVL_ERROR, "Build InnoDB index translation table for"
3461
" Table %s failed", identifier.getPath().c_str());
3464
/* Allocate a buffer for a 'row reference'. A row reference is
3465
a string of bytes of length ref_length which uniquely specifies
3466
a row in our table. Note that MySQL may also compare two row
3467
references for equality by doing a simple memcmp on the strings
3468
of length ref_length! */
3470
if (!row_table_got_default_clust_index(ib_table)) {
3472
prebuilt->clust_index_was_generated = FALSE;
3474
if (UNIV_UNLIKELY(primary_key >= MAX_KEY)) {
3475
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has a primary key in "
3476
"InnoDB data dictionary, but not "
3477
"in MySQL!", identifier.getTableName().c_str());
3479
/* This mismatch could cause further problems
3480
if not attended, bring this to the user's attention
3481
by printing a warning in addition to log a message
3483
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
3485
"InnoDB: Table %s has a "
3486
"primary key in InnoDB data "
3487
"dictionary, but not in "
3488
"MySQL!", identifier.getTableName().c_str());
3490
/* If primary_key >= MAX_KEY, its (primary_key)
3491
value could be out of bound if continue to index
3492
into key_info[] array. Find InnoDB primary index,
3493
and assign its key_length to ref_length.
3494
In addition, since MySQL indexes are sorted starting
3495
with primary index, unique index etc., initialize
3496
ref_length to the first index key length in
3497
case we fail to find InnoDB cluster index.
3499
Please note, this will not resolve the primary
3500
index mismatch problem, other side effects are
3501
possible if users continue to use the table.
3502
However, we allow this table to be opened so
3503
that user can adopt necessary measures for the
3504
mismatch while still being accessible to the table
3506
ref_length = getTable()->key_info[0].key_length;
3508
/* Find correspoinding cluster index
3509
key length in MySQL's key_info[] array */
3510
for (ulint i = 0; i < getTable()->getShare()->keys; i++) {
3511
dict_index_t* index;
3512
index = innobase_get_index(i);
3513
if (dict_index_is_clust(index)) {
3515
getTable()->key_info[i].key_length;
3519
/* MySQL allocates the buffer for ref.
3520
key_info->key_length includes space for all key
3521
columns + one byte for each column that may be
3522
NULL. ref_length must be as exact as possible to
3523
save space, because all row reference buffers are
3524
allocated based on ref_length. */
3526
ref_length = getTable()->key_info[primary_key].key_length;
3529
if (primary_key != MAX_KEY) {
3530
errmsg_printf(ERRMSG_LVL_ERROR,
3531
"Table %s has no primary key in InnoDB data "
3532
"dictionary, but has one in MySQL! If you "
3533
"created the table with a MySQL version < "
3534
"3.23.54 and did not define a primary key, "
3535
"but defined a unique key with all non-NULL "
3536
"columns, then MySQL internally treats that "
3537
"key as the primary key. You can fix this "
3538
"error by dump + DROP + CREATE + reimport "
3539
"of the table.", identifier.getTableName().c_str());
3541
/* This mismatch could cause further problems
3542
if not attended, bring this to the user attention
3543
by printing a warning in addition to log a message
3545
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
3547
"InnoDB: Table %s has no "
3548
"primary key in InnoDB data "
3549
"dictionary, but has one in "
3550
"MySQL!", identifier.getTableName().c_str());
3553
prebuilt->clust_index_was_generated = TRUE;
3555
ref_length = DATA_ROW_ID_LEN;
3557
/* If we automatically created the clustered index, then
3558
MySQL does not know about it, and MySQL must NOT be aware
3559
of the index used on scan, to make it avoid checking if we
3560
update the column of the index. That is why we assert below
3561
that key_used_on_scan is the undefined value MAX_KEY.
3562
The column is the row id in the automatical generation case,
3563
and it will never be updated anyway. */
3565
if (key_used_on_scan != MAX_KEY) {
3566
errmsg_printf(ERRMSG_LVL_WARN,
3567
"Table %s key_used_on_scan is %lu even "
3568
"though there is no primary key inside "
3569
"InnoDB.", identifier.getTableName().c_str(), (ulong) key_used_on_scan);
3573
/* Index block size in InnoDB: used by MySQL in query optimization */
3574
stats.block_size = 16 * 1024;
3576
/* Init table lock structure */
3577
lock.init(&share->lock);
3579
if (prebuilt->table) {
3580
/* We update the highest file format in the system table
3581
space, if this table has higher file format setting. */
3583
char changed_file_format_max[100];
3584
strcpy(changed_file_format_max, innobase_file_format_max.c_str());
3585
trx_sys_file_format_max_upgrade((const char **)&changed_file_format_max,
3586
dict_table_get_format(prebuilt->table));
3587
innobase_file_format_max= changed_file_format_max;
3590
/* Only if the table has an AUTOINC column. */
3591
if (prebuilt->table != NULL && getTable()->found_next_number_field != NULL) {
3593
dict_table_autoinc_lock(prebuilt->table);
3595
/* Since a table can already be "open" in InnoDB's internal
3596
data dictionary, we only init the autoinc counter once, the
3597
first time the table is loaded. We can safely reuse the
3598
autoinc value from a previous Drizzle open. */
3599
if (dict_table_autoinc_read(prebuilt->table) == 0) {
3601
innobase_initialize_autoinc();
3604
dict_table_autoinc_unlock(prebuilt->table);
3607
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
2702
dict_table_t* ib_table;
2703
char norm_name[1000];
2706
char* is_part = NULL;
2709
UT_NOT_USED(test_if_locked);
2711
session = ha_session();
2713
/* Under some cases Drizzle seems to call this function while
2714
holding btr_search_latch. This breaks the latching order as
2715
we acquire dict_sys->mutex below and leads to a deadlock. */
2716
if (session != NULL) {
2717
engine->release_temporary_latches(session);
2720
normalize_table_name(norm_name, name);
2722
user_session = NULL;
2724
if (!(share=get_share(name))) {
2729
/* Create buffers for packing the fields of a record. Why
2730
table->stored_rec_length did not work here? Obviously, because char
2731
fields when packed actually became 1 byte longer, when we also
2732
stored the string length as the first byte. */
2734
upd_and_key_val_buff_len =
2735
table->s->stored_rec_length
2736
+ table->s->max_key_length
2737
+ MAX_REF_PARTS * 3;
2738
if (!(unsigned char*) memory::multi_malloc(false,
2739
&upd_buff, upd_and_key_val_buff_len,
2740
&key_val_buff, upd_and_key_val_buff_len,
2747
/* We look for pattern #P# to see if the table is partitioned
2748
MySQL table. The retry logic for partitioned tables is a
2749
workaround for http://bugs.mysql.com/bug.php?id=33349. Look
2750
at support issue https://support.mysql.com/view.php?id=21080
2751
for more details. */
2752
is_part = strstr(norm_name, "#P#");
2754
/* Get pointer to a table object in InnoDB dictionary cache */
2755
ib_table = dict_table_get(norm_name, TRUE);
2757
if (NULL == ib_table) {
2758
if (is_part && retries < 10) {
2760
os_thread_sleep(100000);
2765
errmsg_printf(ERRMSG_LVL_ERROR, "Failed to open table %s after "
2766
"%lu attemtps.\n", norm_name,
2770
errmsg_printf(ERRMSG_LVL_ERROR, "Cannot find or open table %s from\n"
2771
"the internal data dictionary of InnoDB "
2772
"though the .frm file for the\n"
2773
"table exists. Maybe you have deleted and "
2774
"recreated InnoDB data\n"
2775
"files but have forgotten to delete the "
2776
"corresponding .frm files\n"
2777
"of InnoDB tables, or you have moved .frm "
2778
"files to another database?\n"
2779
"or, the table contains indexes that this "
2780
"version of the engine\n"
2781
"doesn't support.\n"
2782
"See " REFMAN "innodb-troubleshooting.html\n"
2783
"how you can resolve the problem.\n",
2789
return(HA_ERR_NO_SUCH_TABLE);
2792
if (ib_table->ibd_file_missing && !session_tablespace_op(session)) {
2793
errmsg_printf(ERRMSG_LVL_ERROR, "MySQL is trying to open a table handle but "
2794
"the .ibd file for\ntable %s does not exist.\n"
2795
"Have you deleted the .ibd file from the "
2796
"database directory under\nthe MySQL datadir, "
2797
"or have you used DISCARD TABLESPACE?\n"
2798
"See " REFMAN "innodb-troubleshooting.html\n"
2799
"how you can resolve the problem.\n",
2805
dict_table_decrement_handle_count(ib_table, FALSE);
2806
return(HA_ERR_NO_SUCH_TABLE);
2809
prebuilt = row_create_prebuilt(ib_table);
2811
prebuilt->mysql_row_len = table->s->stored_rec_length;
2812
prebuilt->default_rec = table->s->default_values;
2813
ut_ad(prebuilt->default_rec);
2815
/* Looks like MySQL-3.23 sometimes has primary key number != 0 */
2817
primary_key = table->s->primary_key;
2818
key_used_on_scan = primary_key;
2820
/* Allocate a buffer for a 'row reference'. A row reference is
2821
a string of bytes of length ref_length which uniquely specifies
2822
a row in our table. Note that MySQL may also compare two row
2823
references for equality by doing a simple memcmp on the strings
2824
of length ref_length! */
2826
if (!row_table_got_default_clust_index(ib_table)) {
2827
if (primary_key >= MAX_KEY) {
2828
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has a primary key in InnoDB data "
2829
"dictionary, but not in MySQL!", name);
2832
prebuilt->clust_index_was_generated = FALSE;
2834
/* MySQL allocates the buffer for ref. key_info->key_length
2835
includes space for all key columns + one byte for each column
2836
that may be NULL. ref_length must be as exact as possible to
2837
save space, because all row reference buffers are allocated
2838
based on ref_length. */
2840
ref_length = table->key_info[primary_key].key_length;
2842
if (primary_key != MAX_KEY) {
2843
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s has no primary key in InnoDB data "
2844
"dictionary, but has one in MySQL! If you "
2845
"created the table with a MySQL version < "
2846
"3.23.54 and did not define a primary key, "
2847
"but defined a unique key with all non-NULL "
2848
"columns, then MySQL internally treats that "
2849
"key as the primary key. You can fix this "
2850
"error by dump + DROP + CREATE + reimport "
2851
"of the table.", name);
2854
prebuilt->clust_index_was_generated = TRUE;
2856
ref_length = DATA_ROW_ID_LEN;
2858
/* If we automatically created the clustered index, then
2859
MySQL does not know about it, and MySQL must NOT be aware
2860
of the index used on scan, to make it avoid checking if we
2861
update the column of the index. That is why we assert below
2862
that key_used_on_scan is the undefined value MAX_KEY.
2863
The column is the row id in the automatical generation case,
2864
and it will never be updated anyway. */
2866
if (key_used_on_scan != MAX_KEY) {
2867
errmsg_printf(ERRMSG_LVL_WARN,
2868
"Table %s key_used_on_scan is %lu even "
2869
"though there is no primary key inside "
2870
"InnoDB.", name, (ulong) key_used_on_scan);
2874
/* Index block size in InnoDB: used by MySQL in query optimization */
2875
stats.block_size = 16 * 1024;
2877
/* Init table lock structure */
2878
thr_lock_data_init(&share->lock,&lock,(void*) 0);
2880
if (prebuilt->table) {
2881
/* We update the highest file format in the system table
2882
space, if this table has higher file format setting. */
2884
trx_sys_file_format_max_upgrade(
2885
(const char**) &innobase_file_format_check,
2886
dict_table_get_format(prebuilt->table));
2889
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
2891
/* Only if the table has an AUTOINC column. */
2892
if (prebuilt->table != NULL && table->found_next_number_field != NULL) {
2895
dict_table_autoinc_lock(prebuilt->table);
2897
/* Since a table can already be "open" in InnoDB's internal
2898
data dictionary, we only init the autoinc counter once, the
2899
first time the table is loaded. We can safely reuse the
2900
autoinc value from a previous Drizzle open. */
2901
if (dict_table_autoinc_read(prebuilt->table) == 0) {
2903
error = innobase_initialize_autoinc();
2904
ut_a(error == DB_SUCCESS);
2907
dict_table_autoinc_unlock(prebuilt->table);
3614
2915
InnobaseEngine::max_supported_key_part_length() const
3616
return(DICT_MAX_INDEX_COL_LEN - 1);
2917
return(DICT_MAX_INDEX_COL_LEN - 1);
3619
2920
/******************************************************************//**
3620
2921
Closes a handle to an InnoDB table.
3624
2925
ha_innobase::close(void)
3625
2926
/*====================*/
3629
session= getTable()->in_use;
3630
if (session != NULL) {
3631
getTransactionalEngine()->releaseTemporaryLatches(session);
3634
row_prebuilt_free(prebuilt, FALSE);
3637
key_val_buff.clear();
3640
/* Tell InnoDB server that there might be work for
3643
srv_active_wake_master_thread();
2930
session = ha_session();
2931
if (session != NULL) {
2932
engine->release_temporary_latches(session);
2935
row_prebuilt_free(prebuilt, FALSE);
2940
/* Tell InnoDB server that there might be work for
2943
srv_active_wake_master_thread();
3648
2948
/* The following accessor functions should really be inside MySQL code! */
3650
2950
/**************************************************************//**
3651
2951
Gets field offset for a field in a table.
3655
2955
get_field_offset(
3656
2956
/*=============*/
3657
Table* table, /*!< in: MySQL table object */
3658
Field* field) /*!< in: MySQL field object */
2957
Table* table, /*!< in: MySQL table object */
2958
Field* field) /*!< in: MySQL field object */
3660
return((uint) (field->ptr - table->getInsertRecord()));
2960
return((uint) (field->ptr - table->record[0]));
3663
2963
/**************************************************************//**
3664
2964
Checks if a field in a record is SQL NULL. Uses the record format
3665
2965
information in table to track the null bit in record.
3666
@return 1 if NULL, 0 otherwise */
2966
@return 1 if NULL, 0 otherwise */
3669
2969
field_in_record_is_null(
3670
2970
/*====================*/
3671
Table* table, /*!< in: MySQL table object */
3672
Field* field, /*!< in: MySQL field object */
3673
char* record) /*!< in: a row in MySQL format */
2971
Table* table, /*!< in: MySQL table object */
2972
Field* field, /*!< in: MySQL field object */
2973
char* record) /*!< in: a row in MySQL format */
3677
if (!field->null_ptr) {
3682
null_offset = (uint) ((char*) field->null_ptr
3683
- (char*) table->getInsertRecord());
3685
if (record[null_offset] & field->null_bit) {
2977
if (!field->null_ptr) {
2982
null_offset = (uint) ((char*) field->null_ptr
2983
- (char*) table->record[0]);
2985
if (record[null_offset] & field->null_bit) {
3693
2993
/**************************************************************//**
3876
3176
innobase_write_to_2_little_endian(
3877
3177
/*==============================*/
3878
byte* buf, /*!< in: where to store */
3879
ulint val) /*!< in: value to write, must be < 64k */
3178
byte* buf, /*!< in: where to store */
3179
ulint val) /*!< in: value to write, must be < 64k */
3881
ut_a(val < 256 * 256);
3181
ut_a(val < 256 * 256);
3883
buf[0] = (byte)(val & 0xFF);
3884
buf[1] = (byte)(val / 256);
3183
buf[0] = (byte)(val & 0xFF);
3184
buf[1] = (byte)(val / 256);
3887
3187
/*******************************************************************//**
3888
3188
Reads an unsigned integer value < 64k from 2 bytes, in the little-endian
3889
3189
storage format.
3893
3193
innobase_read_from_2_little_endian(
3894
3194
/*===============================*/
3895
const unsigned char* buf) /*!< in: from where to read */
3195
const unsigned char* buf) /*!< in: from where to read */
3897
return (uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
3197
return (uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
3900
3200
/*******************************************************************//**
3901
3201
Stores a key value for a row to a buffer.
3902
@return key value length as stored in buff */
3202
@return key value length as stored in buff */
3905
3205
ha_innobase::store_key_val_for_row(
3906
3206
/*===============================*/
3907
uint keynr, /*!< in: key number */
3908
char* buff, /*!< in/out: buffer for the key value (in MySQL
3910
uint buff_len,/*!< in: buffer length */
3911
const unsigned char* record)/*!< in: row in MySQL format */
3207
uint keynr, /*!< in: key number */
3208
char* buff, /*!< in/out: buffer for the key value (in MySQL
3210
uint buff_len,/*!< in: buffer length */
3211
const unsigned char* record)/*!< in: row in MySQL format */
3913
KeyInfo* key_info = &getTable()->key_info[keynr];
3914
KeyPartInfo* key_part = key_info->key_part;
3915
KeyPartInfo* end = key_part + key_info->key_parts;
3916
char* buff_start = buff;
3917
enum_field_types mysql_type;
3921
/* The format for storing a key field in MySQL is the following:
3923
1. If the column can be NULL, then in the first byte we put 1 if the
3924
field value is NULL, 0 otherwise.
3926
2. If the column is of a BLOB type (it must be a column prefix field
3927
in this case), then we put the length of the data in the field to the
3928
next 2 bytes, in the little-endian format. If the field is SQL NULL,
3929
then these 2 bytes are set to 0. Note that the length of data in the
3930
field is <= column prefix length.
3932
3. In a column prefix field, prefix_len next bytes are reserved for
3933
data. In a normal field the max field length next bytes are reserved
3934
for data. For a VARCHAR(n) the max field length is n. If the stored
3935
value is the SQL NULL then these data bytes are set to 0.
3937
4. We always use a 2 byte length for a true >= 5.0.3 VARCHAR. Note that
3938
in the MySQL row format, the length is stored in 1 or 2 bytes,
3939
depending on the maximum allowed length. But in the MySQL key value
3940
format, the length always takes 2 bytes.
3942
We have to zero-fill the buffer so that MySQL is able to use a
3943
simple memcmp to compare two key values to determine if they are
3944
equal. MySQL does this to compare contents of two 'ref' values. */
3946
bzero(buff, buff_len);
3948
for (; key_part != end; key_part++) {
3951
if (key_part->null_bit) {
3952
if (record[key_part->null_offset]
3953
& key_part->null_bit) {
3962
field = key_part->field;
3963
mysql_type = field->type();
3965
if (mysql_type == DRIZZLE_TYPE_VARCHAR) {
3966
/* >= 5.0.3 true VARCHAR */
3972
const CHARSET_INFO* cs;
3975
key_len = key_part->length;
3978
buff += key_len + 2;
3982
cs = field->charset();
3985
(((Field_varstring*)field)->pack_length_no_ptr());
3987
data = row_mysql_read_true_varchar(&len,
3989
+ (ulint)get_field_offset(getTable(), field)),
3994
/* For multi byte character sets we need to calculate
3995
the true length of the key */
3997
if (len > 0 && cs->mbmaxlen > 1) {
3998
true_len = (ulint) cs->cset->well_formed_len(cs,
3999
(const char *) data,
4000
(const char *) data + len,
4006
/* In a column prefix index, we may need to truncate
4007
the stored value: */
4009
if (true_len > key_len) {
4013
/* The length in a key value is always stored in 2
4016
row_mysql_store_true_var_len((byte*)buff, true_len, 2);
4019
memcpy(buff, data, true_len);
4021
/* Note that we always reserve the maximum possible
4022
length of the true VARCHAR in the key value, though
4023
only len first bytes after the 2 length bytes contain
4024
actual data. The rest of the space was reset to zero
4025
in the bzero() call above. */
4029
} else if (mysql_type == DRIZZLE_TYPE_BLOB) {
4031
const CHARSET_INFO* cs;
4036
const byte* blob_data;
4038
ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
4040
key_len = key_part->length;
4043
buff += key_len + 2;
4048
cs = field->charset();
4050
blob_data = row_mysql_read_blob_ref(&blob_len,
4052
+ (ulint)get_field_offset(getTable(), field)),
4053
(ulint) field->pack_length());
4055
true_len = blob_len;
4057
ut_a(get_field_offset(getTable(), field)
4058
== key_part->offset);
4060
/* For multi byte character sets we need to calculate
4061
the true length of the key */
4063
if (blob_len > 0 && cs->mbmaxlen > 1) {
4064
true_len = (ulint) cs->cset->well_formed_len(cs,
4065
(const char *) blob_data,
4066
(const char *) blob_data
4073
/* All indexes on BLOB and TEXT are column prefix
4074
indexes, and we may need to truncate the data to be
4075
stored in the key value: */
4077
if (true_len > key_len) {
4081
/* MySQL reserves 2 bytes for the length and the
4082
storage of the number is little-endian */
4084
innobase_write_to_2_little_endian(
4085
(byte*)buff, true_len);
4088
memcpy(buff, blob_data, true_len);
4090
/* Note that we always reserve the maximum possible
4091
length of the BLOB prefix in the key value. */
4095
/* Here we handle all other data types except the
4096
true VARCHAR, BLOB and TEXT. Note that the column
4097
value we store may be also in a column prefix
4102
const unsigned char* src_start;
4103
enum_field_types real_type;
4104
const CHARSET_INFO* cs= field->charset();
4106
key_len = key_part->length;
4114
src_start = record + key_part->offset;
4115
real_type = field->real_type();
4118
/* Character set for the field is defined only
4119
to fields whose type is string and real field
4120
type is not enum or set. For these fields check
4121
if character set is multi byte. */
4123
memcpy(buff, src_start, true_len);
4126
/* Pad the unused space with spaces. */
4128
if (true_len < key_len) {
4129
ulint pad_len = key_len - true_len;
4130
ut_a(!(pad_len % cs->mbminlen));
4132
cs->cset->fill(cs, buff, pad_len,
4139
ut_a(buff <= buff_start + buff_len);
4141
return((uint)(buff - buff_start));
3213
KEY* key_info = table->key_info + keynr;
3214
KEY_PART_INFO* key_part = key_info->key_part;
3215
KEY_PART_INFO* end = key_part + key_info->key_parts;
3216
char* buff_start = buff;
3217
enum_field_types mysql_type;
3221
/* The format for storing a key field in MySQL is the following:
3223
1. If the column can be NULL, then in the first byte we put 1 if the
3224
field value is NULL, 0 otherwise.
3226
2. If the column is of a BLOB type (it must be a column prefix field
3227
in this case), then we put the length of the data in the field to the
3228
next 2 bytes, in the little-endian format. If the field is SQL NULL,
3229
then these 2 bytes are set to 0. Note that the length of data in the
3230
field is <= column prefix length.
3232
3. In a column prefix field, prefix_len next bytes are reserved for
3233
data. In a normal field the max field length next bytes are reserved
3234
for data. For a VARCHAR(n) the max field length is n. If the stored
3235
value is the SQL NULL then these data bytes are set to 0.
3237
4. We always use a 2 byte length for a true >= 5.0.3 VARCHAR. Note that
3238
in the MySQL row format, the length is stored in 1 or 2 bytes,
3239
depending on the maximum allowed length. But in the MySQL key value
3240
format, the length always takes 2 bytes.
3242
We have to zero-fill the buffer so that MySQL is able to use a
3243
simple memcmp to compare two key values to determine if they are
3244
equal. MySQL does this to compare contents of two 'ref' values. */
3246
bzero(buff, buff_len);
3248
for (; key_part != end; key_part++) {
3251
if (key_part->null_bit) {
3252
if (record[key_part->null_offset]
3253
& key_part->null_bit) {
3262
field = key_part->field;
3263
mysql_type = field->type();
3265
if (mysql_type == DRIZZLE_TYPE_VARCHAR) {
3266
/* >= 5.0.3 true VARCHAR */
3272
const CHARSET_INFO* cs;
3275
key_len = key_part->length;
3278
buff += key_len + 2;
3282
cs = field->charset();
3285
(((Field_varstring*)field)->length_bytes);
3287
data = row_mysql_read_true_varchar(&len,
3289
+ (ulint)get_field_offset(table, field)),
3294
/* For multi byte character sets we need to calculate
3295
the true length of the key */
3297
if (len > 0 && cs->mbmaxlen > 1) {
3298
true_len = (ulint) cs->cset->well_formed_len(cs,
3299
(const char *) data,
3300
(const char *) data + len,
3306
/* In a column prefix index, we may need to truncate
3307
the stored value: */
3309
if (true_len > key_len) {
3313
/* The length in a key value is always stored in 2
3316
row_mysql_store_true_var_len((byte*)buff, true_len, 2);
3319
memcpy(buff, data, true_len);
3321
/* Note that we always reserve the maximum possible
3322
length of the true VARCHAR in the key value, though
3323
only len first bytes after the 2 length bytes contain
3324
actual data. The rest of the space was reset to zero
3325
in the bzero() call above. */
3329
} else if (mysql_type == DRIZZLE_TYPE_BLOB) {
3331
const CHARSET_INFO* cs;
3336
const byte* blob_data;
3338
ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
3340
key_len = key_part->length;
3343
buff += key_len + 2;
3348
cs = field->charset();
3350
blob_data = row_mysql_read_blob_ref(&blob_len,
3352
+ (ulint)get_field_offset(table, field)),
3353
(ulint) field->pack_length());
3355
true_len = blob_len;
3357
ut_a(get_field_offset(table, field)
3358
== key_part->offset);
3360
/* For multi byte character sets we need to calculate
3361
the true length of the key */
3363
if (blob_len > 0 && cs->mbmaxlen > 1) {
3364
true_len = (ulint) cs->cset->well_formed_len(cs,
3365
(const char *) blob_data,
3366
(const char *) blob_data
3373
/* All indexes on BLOB and TEXT are column prefix
3374
indexes, and we may need to truncate the data to be
3375
stored in the key value: */
3377
if (true_len > key_len) {
3381
/* MySQL reserves 2 bytes for the length and the
3382
storage of the number is little-endian */
3384
innobase_write_to_2_little_endian(
3385
(byte*)buff, true_len);
3388
memcpy(buff, blob_data, true_len);
3390
/* Note that we always reserve the maximum possible
3391
length of the BLOB prefix in the key value. */
3395
/* Here we handle all other data types except the
3396
true VARCHAR, BLOB and TEXT. Note that the column
3397
value we store may be also in a column prefix
3402
const unsigned char* src_start;
3403
enum_field_types real_type;
3405
key_len = key_part->length;
3413
src_start = record + key_part->offset;
3414
real_type = field->real_type();
3417
/* Character set for the field is defined only
3418
to fields whose type is string and real field
3419
type is not enum or set. For these fields check
3420
if character set is multi byte. */
3422
memcpy(buff, src_start, true_len);
3425
/* Pad the unused space with spaces. Note that no
3426
padding is ever needed for UCS-2 because in MySQL,
3427
all UCS2 characters are 2 bytes, as MySQL does not
3428
support surrogate pairs, which are needed to represent
3429
characters in the range U+10000 to U+10FFFF. */
3431
if (true_len < key_len) {
3432
ulint pad_len = key_len - true_len;
3433
memset(buff, ' ', pad_len);
3439
ut_a(buff <= buff_start + buff_len);
3441
return((uint)(buff - buff_start));
4144
3444
/**************************************************************//**
4149
3449
build_template(
4150
3450
/*===========*/
4151
row_prebuilt_t* prebuilt, /*!< in/out: prebuilt struct */
4152
Session* , /*!< in: current user thread, used
4153
only if templ_type is
4154
ROW_DRIZZLE_REC_FIELDS */
4155
Table* table, /*!< in: MySQL table */
4156
uint templ_type) /*!< in: ROW_MYSQL_WHOLE_ROW or
4157
ROW_DRIZZLE_REC_FIELDS */
3451
row_prebuilt_t* prebuilt, /*!< in/out: prebuilt struct */
3452
Session* , /*!< in: current user thread, used
3453
only if templ_type is
3454
ROW_DRIZZLE_REC_FIELDS */
3455
Table* table, /*!< in: MySQL table */
3456
uint templ_type) /*!< in: ROW_MYSQL_WHOLE_ROW or
3457
ROW_DRIZZLE_REC_FIELDS */
4159
dict_index_t* index;
4160
dict_index_t* clust_index;
4161
mysql_row_templ_t* templ;
4164
ulint n_requested_fields = 0;
4165
ibool fetch_all_in_key = FALSE;
4166
ibool fetch_primary_key_cols = FALSE;
4168
/* byte offset of the end of last requested column */
4169
ulint mysql_prefix_len = 0;
4171
if (prebuilt->select_lock_type == LOCK_X) {
4172
/* We always retrieve the whole clustered index record if we
4173
use exclusive row level locks, for example, if the read is
4174
done in an UPDATE statement. */
4176
templ_type = ROW_MYSQL_WHOLE_ROW;
4179
if (templ_type == ROW_MYSQL_REC_FIELDS) {
4180
if (prebuilt->hint_need_to_fetch_extra_cols
4181
== ROW_RETRIEVE_ALL_COLS) {
4183
/* We know we must at least fetch all columns in the
4184
key, or all columns in the table */
4186
if (prebuilt->read_just_key) {
4187
/* MySQL has instructed us that it is enough
4188
to fetch the columns in the key; looks like
4189
MySQL can set this flag also when there is
4190
only a prefix of the column in the key: in
4191
that case we retrieve the whole column from
4192
the clustered index */
4194
fetch_all_in_key = TRUE;
4196
templ_type = ROW_MYSQL_WHOLE_ROW;
4198
} else if (prebuilt->hint_need_to_fetch_extra_cols
4199
== ROW_RETRIEVE_PRIMARY_KEY) {
4200
/* We must at least fetch all primary key cols. Note
4201
that if the clustered index was internally generated
4202
by InnoDB on the row id (no primary key was
4203
defined), then row_search_for_mysql() will always
4204
retrieve the row id to a special buffer in the
4207
fetch_primary_key_cols = TRUE;
4211
clust_index = dict_table_get_first_index(prebuilt->table);
4213
if (templ_type == ROW_MYSQL_REC_FIELDS) {
4214
index = prebuilt->index;
4216
index = clust_index;
4219
if (index == clust_index) {
4220
prebuilt->need_to_access_clustered = TRUE;
4222
prebuilt->need_to_access_clustered = FALSE;
4223
/* Below we check column by column if we need to access
4224
the clustered index */
4227
n_fields = (ulint)table->getShare()->sizeFields(); /* number of columns */
4229
if (!prebuilt->mysql_template) {
4230
prebuilt->mysql_template = (mysql_row_templ_t*)
4231
mem_alloc(n_fields * sizeof(mysql_row_templ_t));
4234
prebuilt->template_type = templ_type;
4235
prebuilt->null_bitmap_len = table->getShare()->null_bytes;
4237
prebuilt->templ_contains_blob = FALSE;
4239
/* Note that in InnoDB, i is the column number. MySQL calls columns
4241
for (i = 0; i < n_fields; i++)
4243
const dict_col_t *col= &index->table->cols[i];
4244
templ = prebuilt->mysql_template + n_requested_fields;
4245
field = table->getField(i);
4247
if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
4248
/* Decide which columns we should fetch
4249
and which we can skip. */
4250
register const ibool index_contains_field =
4251
dict_index_contains_col_or_prefix(index, i);
4253
if (!index_contains_field && prebuilt->read_just_key) {
4254
/* If this is a 'key read', we do not need
4255
columns that are not in the key */
4260
if (index_contains_field && fetch_all_in_key) {
4261
/* This field is needed in the query */
3459
dict_index_t* index;
3460
dict_index_t* clust_index;
3461
mysql_row_templ_t* templ;
3464
ulint n_requested_fields = 0;
3465
ibool fetch_all_in_key = FALSE;
3466
ibool fetch_primary_key_cols = FALSE;
3468
/* byte offset of the end of last requested column */
3469
ulint mysql_prefix_len = 0;
3471
if (prebuilt->select_lock_type == LOCK_X) {
3472
/* We always retrieve the whole clustered index record if we
3473
use exclusive row level locks, for example, if the read is
3474
done in an UPDATE statement. */
3476
templ_type = ROW_MYSQL_WHOLE_ROW;
3479
if (templ_type == ROW_MYSQL_REC_FIELDS) {
3480
if (prebuilt->hint_need_to_fetch_extra_cols
3481
== ROW_RETRIEVE_ALL_COLS) {
3483
/* We know we must at least fetch all columns in the
3484
key, or all columns in the table */
3486
if (prebuilt->read_just_key) {
3487
/* MySQL has instructed us that it is enough
3488
to fetch the columns in the key; looks like
3489
MySQL can set this flag also when there is
3490
only a prefix of the column in the key: in
3491
that case we retrieve the whole column from
3492
the clustered index */
3494
fetch_all_in_key = TRUE;
3496
templ_type = ROW_MYSQL_WHOLE_ROW;
3498
} else if (prebuilt->hint_need_to_fetch_extra_cols
3499
== ROW_RETRIEVE_PRIMARY_KEY) {
3500
/* We must at least fetch all primary key cols. Note
3501
that if the clustered index was internally generated
3502
by InnoDB on the row id (no primary key was
3503
defined), then row_search_for_mysql() will always
3504
retrieve the row id to a special buffer in the
3507
fetch_primary_key_cols = TRUE;
3511
clust_index = dict_table_get_first_index(prebuilt->table);
3513
if (templ_type == ROW_MYSQL_REC_FIELDS) {
3514
index = prebuilt->index;
3516
index = clust_index;
3519
if (index == clust_index) {
3520
prebuilt->need_to_access_clustered = TRUE;
3522
prebuilt->need_to_access_clustered = FALSE;
3523
/* Below we check column by column if we need to access
3524
the clustered index */
3527
n_fields = (ulint)table->s->fields; /* number of columns */
3529
if (!prebuilt->mysql_template) {
3530
prebuilt->mysql_template = (mysql_row_templ_t*)
3531
mem_alloc(n_fields * sizeof(mysql_row_templ_t));
3534
prebuilt->template_type = templ_type;
3535
prebuilt->null_bitmap_len = table->s->null_bytes;
3537
prebuilt->templ_contains_blob = FALSE;
3539
/* Note that in InnoDB, i is the column number. MySQL calls columns
3541
for (i = 0; i < n_fields; i++) {
3542
templ = prebuilt->mysql_template + n_requested_fields;
3543
field = table->field[i];
3545
if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
3546
/* Decide which columns we should fetch
3547
and which we can skip. */
3548
register const ibool index_contains_field =
3549
dict_index_contains_col_or_prefix(index, i);
3551
if (!index_contains_field && prebuilt->read_just_key) {
3552
/* If this is a 'key read', we do not need
3553
columns that are not in the key */
3558
if (index_contains_field && fetch_all_in_key) {
3559
/* This field is needed in the query */
4266
3564
if (field->isReadSet() || field->isWriteSet())
4267
/* This field is needed in the query */
3565
/* This field is needed in the query */
4270
3568
assert(table->isReadSet(i) == field->isReadSet());
4271
3569
assert(table->isWriteSet(i) == field->isWriteSet());
4273
if (fetch_primary_key_cols
4274
&& dict_table_col_in_clustered_key(
4276
/* This field is needed in the query */
4281
/* This field is not needed in the query, skip it */
3571
if (fetch_primary_key_cols
3572
&& dict_table_col_in_clustered_key(
3574
/* This field is needed in the query */
3579
/* This field is not needed in the query, skip it */
4286
n_requested_fields++;
4290
if (index == clust_index) {
4291
templ->rec_field_no = dict_col_get_clust_pos(col, index);
4293
templ->rec_field_no = dict_index_get_nth_col_pos(
4297
if (templ->rec_field_no == ULINT_UNDEFINED) {
4298
prebuilt->need_to_access_clustered = TRUE;
4301
if (field->null_ptr) {
4302
templ->mysql_null_byte_offset =
4303
(ulint) ((char*) field->null_ptr
4304
- (char*) table->getInsertRecord());
4306
templ->mysql_null_bit_mask = (ulint) field->null_bit;
4308
templ->mysql_null_bit_mask = 0;
4311
templ->mysql_col_offset = (ulint)
4312
get_field_offset(table, field);
4314
templ->mysql_col_len = (ulint) field->pack_length();
4315
if (mysql_prefix_len < templ->mysql_col_offset
4316
+ templ->mysql_col_len) {
4317
mysql_prefix_len = templ->mysql_col_offset
4318
+ templ->mysql_col_len;
4320
templ->type = col->mtype;
4321
templ->mysql_type = (ulint)field->type();
4323
if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
4324
templ->mysql_length_bytes = (ulint)
4325
(((Field_varstring*)field)->pack_length_no_ptr());
4328
templ->charset = dtype_get_charset_coll(col->prtype);
4329
templ->mbminlen = dict_col_get_mbminlen(col);
4330
templ->mbmaxlen = dict_col_get_mbmaxlen(col);
4331
templ->is_unsigned = col->prtype & DATA_UNSIGNED;
4332
if (templ->type == DATA_BLOB) {
4333
prebuilt->templ_contains_blob = TRUE;
3584
n_requested_fields++;
3588
if (index == clust_index) {
3589
templ->rec_field_no = dict_col_get_clust_pos(
3590
&index->table->cols[i], index);
3592
templ->rec_field_no = dict_index_get_nth_col_pos(
3596
if (templ->rec_field_no == ULINT_UNDEFINED) {
3597
prebuilt->need_to_access_clustered = TRUE;
3600
if (field->null_ptr) {
3601
templ->mysql_null_byte_offset =
3602
(ulint) ((char*) field->null_ptr
3603
- (char*) table->record[0]);
3605
templ->mysql_null_bit_mask = (ulint) field->null_bit;
3607
templ->mysql_null_bit_mask = 0;
3610
templ->mysql_col_offset = (ulint)
3611
get_field_offset(table, field);
3613
templ->mysql_col_len = (ulint) field->pack_length();
3614
if (mysql_prefix_len < templ->mysql_col_offset
3615
+ templ->mysql_col_len) {
3616
mysql_prefix_len = templ->mysql_col_offset
3617
+ templ->mysql_col_len;
3619
templ->type = index->table->cols[i].mtype;
3620
templ->mysql_type = (ulint)field->type();
3622
if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
3623
templ->mysql_length_bytes = (ulint)
3624
(((Field_varstring*)field)->length_bytes);
3627
templ->charset = dtype_get_charset_coll(
3628
index->table->cols[i].prtype);
3629
templ->mbminlen = index->table->cols[i].mbminlen;
3630
templ->mbmaxlen = index->table->cols[i].mbmaxlen;
3631
templ->is_unsigned = index->table->cols[i].prtype
3633
if (templ->type == DATA_BLOB) {
3634
prebuilt->templ_contains_blob = TRUE;
4339
prebuilt->n_template = n_requested_fields;
4340
prebuilt->mysql_prefix_len = mysql_prefix_len;
4342
if (index != clust_index && prebuilt->need_to_access_clustered) {
4343
/* Change rec_field_no's to correspond to the clustered index
4345
for (i = 0; i < n_requested_fields; i++) {
4346
templ = prebuilt->mysql_template + i;
4348
templ->rec_field_no = dict_col_get_clust_pos(
4349
&index->table->cols[templ->col_no],
3640
prebuilt->n_template = n_requested_fields;
3641
prebuilt->mysql_prefix_len = mysql_prefix_len;
3643
if (index != clust_index && prebuilt->need_to_access_clustered) {
3644
/* Change rec_field_no's to correspond to the clustered index
3646
for (i = 0; i < n_requested_fields; i++) {
3647
templ = prebuilt->mysql_template + i;
3649
templ->rec_field_no = dict_col_get_clust_pos(
3650
&index->table->cols[templ->col_no],
3656
/********************************************************************//**
3657
Get the upper limit of the MySQL integral and floating-point type. */
3660
ha_innobase::innobase_get_int_col_max_value(
3661
/*========================================*/
3664
uint64_t max_value = 0;
3666
switch(field->key_type()) {
3668
case HA_KEYTYPE_BINARY:
3669
max_value = 0xFFULL;
3672
case HA_KEYTYPE_UINT24:
3673
max_value = 0xFFFFFFULL;
3676
case HA_KEYTYPE_ULONG_INT:
3677
max_value = 0xFFFFFFFFULL;
3679
case HA_KEYTYPE_LONG_INT:
3680
max_value = 0x7FFFFFFFULL;
3683
case HA_KEYTYPE_ULONGLONG:
3684
max_value = 0xFFFFFFFFFFFFFFFFULL;
3686
case HA_KEYTYPE_LONGLONG:
3687
max_value = 0x7FFFFFFFFFFFFFFFULL;
3689
case HA_KEYTYPE_DOUBLE:
3690
/* We use the maximum as per IEEE754-2008 standard, 2^53 */
3691
max_value = 0x20000000000000ULL;
4355
3700
/********************************************************************//**
4358
3703
INSERT ... SELECT type of statements, since MySQL binlog only stores the
4359
3704
min value of the autoinc interval. Once that is fixed we can get rid of
4360
3705
the special lock handling.
4361
@return DB_SUCCESS if all OK else error code */
3706
@return DB_SUCCESS if all OK else error code */
4364
3709
ha_innobase::innobase_lock_autoinc(void)
4365
3710
/*====================================*/
4367
ulint error = DB_SUCCESS;
4369
dict_table_autoinc_lock(prebuilt->table);
4371
return(ulong(error));
3712
ulint error = DB_SUCCESS;
3714
switch (innobase_autoinc_lock_mode) {
3715
case AUTOINC_NO_LOCKING:
3716
/* Acquire only the AUTOINC mutex. */
3717
dict_table_autoinc_lock(prebuilt->table);
3720
case AUTOINC_NEW_STYLE_LOCKING:
3721
/* For simple (single/multi) row INSERTs, we fallback to the
3722
old style only if another transaction has already acquired
3723
the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
3724
etc. type of statement. */
3725
if (session_sql_command(user_session) == SQLCOM_INSERT
3726
|| session_sql_command(user_session) == SQLCOM_REPLACE) {
3727
dict_table_t* d_table = prebuilt->table;
3729
/* Acquire the AUTOINC mutex. */
3730
dict_table_autoinc_lock(d_table);
3732
/* We need to check that another transaction isn't
3733
already holding the AUTOINC lock on the table. */
3734
if (d_table->n_waiting_or_granted_auto_inc_locks) {
3735
/* Release the mutex to avoid deadlocks. */
3736
dict_table_autoinc_unlock(d_table);
3741
/* Fall through to old style locking. */
3743
case AUTOINC_OLD_STYLE_LOCKING:
3744
error = row_lock_table_autoinc_for_mysql(prebuilt);
3746
if (error == DB_SUCCESS) {
3748
/* Acquire the AUTOINC mutex. */
3749
dict_table_autoinc_lock(prebuilt->table);
3757
return(ulong(error));
4374
3760
/********************************************************************//**
4375
3761
Reset the autoinc value in the table.
4376
@return DB_SUCCESS if all went well else error code */
3762
@return DB_SUCCESS if all went well else error code */
4379
3765
ha_innobase::innobase_reset_autoinc(
4380
3766
/*================================*/
4381
uint64_t autoinc) /*!< in: value to store */
3767
uint64_t autoinc) /*!< in: value to store */
4383
dict_table_autoinc_lock(prebuilt->table);
4384
dict_table_autoinc_initialize(prebuilt->table, autoinc);
4385
dict_table_autoinc_unlock(prebuilt->table);
4387
return(ulong(DB_SUCCESS));
3771
error = innobase_lock_autoinc();
3773
if (error == DB_SUCCESS) {
3775
dict_table_autoinc_initialize(prebuilt->table, autoinc);
3777
dict_table_autoinc_unlock(prebuilt->table);
3780
return(ulong(error));
4390
3783
/********************************************************************//**
4391
3784
Store the autoinc value in the table. The autoinc value is only set if
4392
3785
it's greater than the existing autoinc value in the table.
4393
@return DB_SUCCESS if all went well else error code */
3786
@return DB_SUCCESS if all went well else error code */
4396
3789
ha_innobase::innobase_set_max_autoinc(
4397
3790
/*==================================*/
4398
uint64_t auto_inc) /*!< in: value to store */
3791
uint64_t auto_inc) /*!< in: value to store */
4400
dict_table_autoinc_lock(prebuilt->table);
4401
dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
4402
dict_table_autoinc_unlock(prebuilt->table);
4404
return(ulong(DB_SUCCESS));
3795
error = innobase_lock_autoinc();
3797
if (error == DB_SUCCESS) {
3799
dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
3801
dict_table_autoinc_unlock(prebuilt->table);
3804
return(ulong(error));
4407
3807
/********************************************************************//**
4408
3808
Stores a row in an InnoDB database, to the table specified in this
4410
@return error code */
3810
@return error code */
4413
ha_innobase::doInsertRecord(
3813
ha_innobase::write_row(
4414
3814
/*===================*/
4415
unsigned char* record) /*!< in: a row in MySQL format */
3815
unsigned char* record) /*!< in: a row in MySQL format */
4418
3818
int error_result= 0;
4419
ibool auto_inc_used= FALSE;
4421
trx_t* trx = session_to_trx(user_session);
4423
if (prebuilt->trx != trx) {
4424
errmsg_printf(ERRMSG_LVL_ERROR, "The transaction object for the table handle is at "
4425
"%p, but for the current thread it is at %p",
4426
(const void*) prebuilt->trx, (const void*) trx);
4428
fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
4429
ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
4431
"InnoDB: Dump of 200 bytes around ha_data: ",
4433
ut_print_buf(stderr, ((const byte*) trx) - 100, 200);
4438
sql_command = session_sql_command(user_session);
4440
if ((sql_command == SQLCOM_ALTER_TABLE
4441
|| sql_command == SQLCOM_CREATE_INDEX
4442
|| sql_command == SQLCOM_DROP_INDEX)
4443
&& num_write_row >= 10000) {
4444
/* ALTER TABLE is COMMITted at every 10000 copied rows.
4445
The IX table lock for the original table has to be re-issued.
4446
As this method will be called on a temporary table where the
4447
contents of the original table is being copied to, it is
4448
a bit tricky to determine the source table. The cursor
4449
position in the source table need not be adjusted after the
4450
intermediate COMMIT, since writes by other transactions are
4451
being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
4453
dict_table_t* src_table;
4454
enum lock_mode mode;
4458
/* Commit the transaction. This will release the table
4459
locks, so they have to be acquired again. */
4461
/* Altering an InnoDB table */
4462
/* Get the source table. */
4463
src_table = lock_get_src_table(
4464
prebuilt->trx, prebuilt->table, &mode);
3819
ibool auto_inc_used= FALSE;
3821
trx_t* trx = session_to_trx(user_session);
3823
if (prebuilt->trx != trx) {
3824
errmsg_printf(ERRMSG_LVL_ERROR, "The transaction object for the table handle is at "
3825
"%p, but for the current thread it is at %p",
3826
(const void*) prebuilt->trx, (const void*) trx);
3828
fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
3829
ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
3831
"InnoDB: Dump of 200 bytes around ha_data: ",
3833
ut_print_buf(stderr, ((const byte*) trx) - 100, 200);
3838
ha_statistic_increment(&SSV::ha_write_count);
3840
sql_command = session_sql_command(user_session);
3842
if ((sql_command == SQLCOM_ALTER_TABLE
3843
|| sql_command == SQLCOM_CREATE_INDEX
3844
|| sql_command == SQLCOM_DROP_INDEX)
3845
&& num_write_row >= 10000) {
3846
/* ALTER TABLE is COMMITted at every 10000 copied rows.
3847
The IX table lock for the original table has to be re-issued.
3848
As this method will be called on a temporary table where the
3849
contents of the original table is being copied to, it is
3850
a bit tricky to determine the source table. The cursor
3851
position in the source table need not be adjusted after the
3852
intermediate COMMIT, since writes by other transactions are
3853
being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
3855
dict_table_t* src_table;
3856
enum lock_mode mode;
3860
/* Commit the transaction. This will release the table
3861
locks, so they have to be acquired again. */
3863
/* Altering an InnoDB table */
3864
/* Get the source table. */
3865
src_table = lock_get_src_table(
3866
prebuilt->trx, prebuilt->table, &mode);
4467
/* Unknown situation: do not commit */
4469
ut_print_timestamp(stderr);
4471
" InnoDB: ALTER TABLE is holding lock"
4472
" on %lu tables!\n",
4473
prebuilt->trx->mysql_n_tables_locked);
4476
} else if (src_table == prebuilt->table) {
4477
/* Source table is not in InnoDB format:
4478
no need to re-acquire locks on it. */
4480
/* Altering to InnoDB format */
4481
getTransactionalEngine()->commit(user_session, 1);
4482
/* We will need an IX lock on the destination table. */
4483
prebuilt->sql_stat_start = TRUE;
4485
/* Ensure that there are no other table locks than
4486
LOCK_IX and LOCK_AUTO_INC on the destination table. */
4488
if (!lock_is_table_exclusive(prebuilt->table,
4493
/* Commit the transaction. This will release the table
4494
locks, so they have to be acquired again. */
4495
getTransactionalEngine()->commit(user_session, 1);
4496
/* Re-acquire the table lock on the source table. */
4497
row_lock_table_for_mysql(prebuilt, src_table, mode);
4498
/* We will need an IX lock on the destination table. */
4499
prebuilt->sql_stat_start = TRUE;
4505
/* This is the case where the table has an auto-increment column */
4506
if (getTable()->next_number_field && record == getTable()->getInsertRecord()) {
4508
/* Reset the error code before calling
4509
innobase_get_auto_increment(). */
4510
prebuilt->autoinc_error = DB_SUCCESS;
4512
if ((error = update_auto_increment())) {
4513
/* We don't want to mask autoinc overflow errors. */
4515
/* Handle the case where the AUTOINC sub-system
4516
failed during initialization. */
4517
if (prebuilt->autoinc_error == DB_UNSUPPORTED) {
4518
error_result = ER_AUTOINC_READ_FAILED;
4519
/* Set the error message to report too. */
4520
my_error(ER_AUTOINC_READ_FAILED, MYF(0));
4522
} else if (prebuilt->autoinc_error != DB_SUCCESS) {
4523
error = (int) prebuilt->autoinc_error;
4528
/* MySQL errors are passed straight back. */
4529
error_result = (int) error;
4533
auto_inc_used = TRUE;
4536
if (prebuilt->mysql_template == NULL
4537
|| prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
4539
/* Build the template used in converting quickly between
4540
the two database formats */
4542
build_template(prebuilt, NULL, getTable(), ROW_MYSQL_WHOLE_ROW);
4545
innodb_srv_conc_enter_innodb(prebuilt->trx);
4547
error = row_insert_for_mysql((byte*) record, prebuilt);
4549
user_session->setXaId(trx->id);
4551
/* Handle duplicate key errors */
4552
if (auto_inc_used) {
4555
uint64_t col_max_value;
4557
/* Note the number of rows processed for this statement, used
4558
by get_auto_increment() to determine the number of AUTO-INC
4559
values to reserve. This is only useful for a mult-value INSERT
4560
and is a statement level counter.*/
4561
if (trx->n_autoinc_rows > 0) {
4562
--trx->n_autoinc_rows;
4565
/* We need the upper limit of the col type to check for
4566
whether we update the table autoinc counter or not. */
4567
col_max_value = innobase_get_int_col_max_value(
4568
getTable()->next_number_field);
4569
/* Get the value that MySQL attempted to store in the table.*/
4570
auto_inc = getTable()->next_number_field->val_int();
4573
case DB_DUPLICATE_KEY:
4575
/* A REPLACE command and LOAD DATA INFILE REPLACE
4576
handle a duplicate key error themselves, but we
4577
must update the autoinc counter if we are performing
4578
those statements. */
4580
switch (sql_command) {
4582
if ((trx->duplicates
4583
& (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
4585
goto set_max_autoinc;
4589
case SQLCOM_REPLACE:
4590
case SQLCOM_INSERT_SELECT:
4591
case SQLCOM_REPLACE_SELECT:
4592
goto set_max_autoinc;
4601
/* If the actual value inserted is greater than
4602
the upper limit of the interval, then we try and
4603
update the table upper limit. Note: last_value
4604
will be 0 if get_auto_increment() was not called.*/
4606
if (auto_inc >= prebuilt->autoinc_last_value) {
3869
/* Unknown situation: do not commit */
3871
ut_print_timestamp(stderr);
3873
" InnoDB: ALTER TABLE is holding lock"
3874
" on %lu tables!\n",
3875
prebuilt->trx->mysql_n_tables_locked);
3878
} else if (src_table == prebuilt->table) {
3879
/* Source table is not in InnoDB format:
3880
no need to re-acquire locks on it. */
3882
/* Altering to InnoDB format */
3883
engine->commit(user_session, 1);
3884
/* Note that this transaction is still active. */
3885
prebuilt->trx->active_trans = 1;
3886
/* We will need an IX lock on the destination table. */
3887
prebuilt->sql_stat_start = TRUE;
3889
/* Ensure that there are no other table locks than
3890
LOCK_IX and LOCK_AUTO_INC on the destination table. */
3892
if (!lock_is_table_exclusive(prebuilt->table,
3897
/* Commit the transaction. This will release the table
3898
locks, so they have to be acquired again. */
3899
engine->commit(user_session, 1);
3900
/* Note that this transaction is still active. */
3901
prebuilt->trx->active_trans = 1;
3902
/* Re-acquire the table lock on the source table. */
3903
row_lock_table_for_mysql(prebuilt, src_table, mode);
3904
/* We will need an IX lock on the destination table. */
3905
prebuilt->sql_stat_start = TRUE;
3911
/* This is the case where the table has an auto-increment column */
3912
if (table->next_number_field && record == table->record[0]) {
3914
/* Reset the error code before calling
3915
innobase_get_auto_increment(). */
3916
prebuilt->autoinc_error = DB_SUCCESS;
3918
if ((error = update_auto_increment())) {
3920
/* We don't want to mask autoinc overflow errors. */
3921
if (prebuilt->autoinc_error != DB_SUCCESS) {
3922
error = (int) prebuilt->autoinc_error;
3927
/* MySQL errors are passed straight back. */
3928
error_result = (int) error;
3932
auto_inc_used = TRUE;
3935
if (prebuilt->mysql_template == NULL
3936
|| prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
3938
/* Build the template used in converting quickly between
3939
the two database formats */
3941
build_template(prebuilt, NULL, table,
3942
ROW_MYSQL_WHOLE_ROW);
3945
innodb_srv_conc_enter_innodb(prebuilt->trx);
3947
error = row_insert_for_mysql((byte*) record, prebuilt);
3949
/* Handle duplicate key errors */
3950
if (auto_inc_used) {
3953
uint64_t col_max_value;
3955
/* Note the number of rows processed for this statement, used
3956
by get_auto_increment() to determine the number of AUTO-INC
3957
values to reserve. This is only useful for a mult-value INSERT
3958
and is a statement level counter.*/
3959
if (trx->n_autoinc_rows > 0) {
3960
--trx->n_autoinc_rows;
3963
/* We need the upper limit of the col type to check for
3964
whether we update the table autoinc counter or not. */
3965
col_max_value = innobase_get_int_col_max_value(
3966
table->next_number_field);
3968
/* Get the value that MySQL attempted to store in the table.*/
3969
auto_inc = table->next_number_field->val_int();
3972
case DB_DUPLICATE_KEY:
3974
/* A REPLACE command and LOAD DATA INFILE REPLACE
3975
handle a duplicate key error themselves, but we
3976
must update the autoinc counter if we are performing
3977
those statements. */
3979
switch (sql_command) {
3981
if ((trx->duplicates
3982
& (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
3984
goto set_max_autoinc;
3988
case SQLCOM_REPLACE:
3989
case SQLCOM_INSERT_SELECT:
3990
case SQLCOM_REPLACE_SELECT:
3991
goto set_max_autoinc;
4000
/* If the actual value inserted is greater than
4001
the upper limit of the interval, then we try and
4002
update the table upper limit. Note: last_value
4003
will be 0 if get_auto_increment() was not called.*/
4005
if (auto_inc <= col_max_value
4006
&& auto_inc >= prebuilt->autoinc_last_value) {
4607
4007
set_max_autoinc:
4608
/* This should filter out the negative
4609
values set explicitly by the user. */
4610
if (auto_inc <= col_max_value) {
4611
ut_a(prebuilt->autoinc_increment > 0);
4616
offset = prebuilt->autoinc_offset;
4617
need = prebuilt->autoinc_increment;
4619
auto_inc = innobase_next_autoinc(
4621
need, offset, col_max_value);
4623
err = innobase_set_max_autoinc(
4626
if (err != DB_SUCCESS) {
4635
innodb_srv_conc_exit_innodb(prebuilt->trx);
4008
ut_a(prebuilt->autoinc_increment > 0);
4013
offset = prebuilt->autoinc_offset;
4014
need = prebuilt->autoinc_increment;
4016
auto_inc = innobase_next_autoinc(
4017
auto_inc, need, offset, col_max_value);
4019
err = innobase_set_max_autoinc(auto_inc);
4021
if (err != DB_SUCCESS) {
4029
innodb_srv_conc_exit_innodb(prebuilt->trx);
4638
error_result = convert_error_code_to_mysql((int) error,
4639
prebuilt->table->flags,
4032
error_result = convert_error_code_to_mysql((int) error,
4033
prebuilt->table->flags,
4643
innobase_active_small();
4037
innobase_active_small();
4645
return(error_result);
4039
return(error_result);
4648
4042
/**********************************************************************//**
4649
4043
Checks which fields have changed in a row and stores information
4650
4044
of them to an update vector.
4651
@return error number or 0 */
4045
@return error number or 0 */
4654
4048
calc_row_difference(
4655
4049
/*================*/
4656
upd_t* uvect, /*!< in/out: update vector */
4657
unsigned char* old_row, /*!< in: old row in MySQL format */
4658
unsigned char* new_row, /*!< in: new row in MySQL format */
4659
Table* table, /*!< in: table in MySQL data
4661
unsigned char* upd_buff, /*!< in: buffer to use */
4662
ulint buff_len, /*!< in: buffer length */
4663
row_prebuilt_t* prebuilt, /*!< in: InnoDB prebuilt struct */
4664
Session* ) /*!< in: user thread */
4050
upd_t* uvect, /*!< in/out: update vector */
4051
unsigned char* old_row, /*!< in: old row in MySQL format */
4052
unsigned char* new_row, /*!< in: new row in MySQL format */
4053
Table* table, /*!< in: table in MySQL data
4055
unsigned char* upd_buff, /*!< in: buffer to use */
4056
ulint buff_len, /*!< in: buffer length */
4057
row_prebuilt_t* prebuilt, /*!< in: InnoDB prebuilt struct */
4058
Session* ) /*!< in: user thread */
4666
unsigned char* original_upd_buff = upd_buff;
4667
enum_field_types field_mysql_type;
4672
const byte* new_mysql_row_col;
4676
upd_field_t* ufield;
4678
ulint n_changed = 0;
4680
dict_index_t* clust_index;
4683
n_fields = table->getShare()->sizeFields();
4684
clust_index = dict_table_get_first_index(prebuilt->table);
4686
/* We use upd_buff to convert changed fields */
4687
buf = (byte*) upd_buff;
4689
for (i = 0; i < n_fields; i++) {
4690
Field *field= table->getField(i);
4692
o_ptr = (const byte*) old_row + get_field_offset(table, field);
4693
n_ptr = (const byte*) new_row + get_field_offset(table, field);
4695
/* Use new_mysql_row_col and col_pack_len save the values */
4697
new_mysql_row_col = n_ptr;
4698
col_pack_len = field->pack_length();
4700
o_len = col_pack_len;
4701
n_len = col_pack_len;
4703
/* We use o_ptr and n_ptr to dig up the actual data for
4706
field_mysql_type = field->type();
4708
col_type = prebuilt->table->cols[i].mtype;
4713
o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len);
4714
n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len);
4721
if (field_mysql_type == DRIZZLE_TYPE_VARCHAR) {
4722
/* This is a >= 5.0.3 type true VARCHAR where
4723
the real payload data length is stored in
4726
o_ptr = row_mysql_read_true_varchar(
4729
(((Field_varstring*)field)->pack_length_no_ptr()));
4731
n_ptr = row_mysql_read_true_varchar(
4734
(((Field_varstring*)field)->pack_length_no_ptr()));
4742
if (field->null_ptr) {
4743
if (field_in_record_is_null(table, field,
4745
o_len = UNIV_SQL_NULL;
4748
if (field_in_record_is_null(table, field,
4750
n_len = UNIV_SQL_NULL;
4754
if (o_len != n_len || (o_len != UNIV_SQL_NULL &&
4755
0 != memcmp(o_ptr, n_ptr, o_len))) {
4756
/* The field has changed */
4758
ufield = uvect->fields + n_changed;
4760
/* Let us use a dummy dfield to make the conversion
4761
from the MySQL column format to the InnoDB format */
4763
dict_col_copy_type(prebuilt->table->cols + i,
4766
if (n_len != UNIV_SQL_NULL) {
4767
buf = row_mysql_store_col_in_innobase_format(
4773
dict_table_is_comp(prebuilt->table));
4774
dfield_copy_data(&ufield->new_val, &dfield);
4776
dfield_set_null(&ufield->new_val);
4780
ufield->orig_len = 0;
4781
ufield->field_no = dict_col_get_clust_pos(
4782
&prebuilt->table->cols[i], clust_index);
4787
uvect->n_fields = n_changed;
4788
uvect->info_bits = 0;
4790
ut_a(buf <= (byte*)original_upd_buff + buff_len);
4060
unsigned char* original_upd_buff = upd_buff;
4062
enum_field_types field_mysql_type;
4067
const byte* new_mysql_row_col;
4071
upd_field_t* ufield;
4073
ulint n_changed = 0;
4075
dict_index_t* clust_index;
4078
n_fields = table->s->fields;
4079
clust_index = dict_table_get_first_index(prebuilt->table);
4081
/* We use upd_buff to convert changed fields */
4082
buf = (byte*) upd_buff;
4084
for (i = 0; i < n_fields; i++) {
4085
field = table->field[i];
4087
o_ptr = (const byte*) old_row + get_field_offset(table, field);
4088
n_ptr = (const byte*) new_row + get_field_offset(table, field);
4090
/* Use new_mysql_row_col and col_pack_len save the values */
4092
new_mysql_row_col = n_ptr;
4093
col_pack_len = field->pack_length();
4095
o_len = col_pack_len;
4096
n_len = col_pack_len;
4098
/* We use o_ptr and n_ptr to dig up the actual data for
4101
field_mysql_type = field->type();
4103
col_type = prebuilt->table->cols[i].mtype;
4108
o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len);
4109
n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len);
4116
if (field_mysql_type == DRIZZLE_TYPE_VARCHAR) {
4117
/* This is a >= 5.0.3 type true VARCHAR where
4118
the real payload data length is stored in
4121
o_ptr = row_mysql_read_true_varchar(
4124
(((Field_varstring*)field)->length_bytes));
4126
n_ptr = row_mysql_read_true_varchar(
4129
(((Field_varstring*)field)->length_bytes));
4137
if (field->null_ptr) {
4138
if (field_in_record_is_null(table, field,
4140
o_len = UNIV_SQL_NULL;
4143
if (field_in_record_is_null(table, field,
4145
n_len = UNIV_SQL_NULL;
4149
if (o_len != n_len || (o_len != UNIV_SQL_NULL &&
4150
0 != memcmp(o_ptr, n_ptr, o_len))) {
4151
/* The field has changed */
4153
ufield = uvect->fields + n_changed;
4155
/* Let us use a dummy dfield to make the conversion
4156
from the MySQL column format to the InnoDB format */
4158
dict_col_copy_type(prebuilt->table->cols + i,
4161
if (n_len != UNIV_SQL_NULL) {
4162
buf = row_mysql_store_col_in_innobase_format(
4168
dict_table_is_comp(prebuilt->table));
4169
dfield_copy_data(&ufield->new_val, &dfield);
4171
dfield_set_null(&ufield->new_val);
4175
ufield->orig_len = 0;
4176
ufield->field_no = dict_col_get_clust_pos(
4177
&prebuilt->table->cols[i], clust_index);
4182
uvect->n_fields = n_changed;
4183
uvect->info_bits = 0;
4185
ut_a(buf <= (byte*)original_upd_buff + buff_len);
4795
4190
/**********************************************************************//**
5185
4540
/**********************************************************************//**
5186
4541
Positions an index cursor to the index specified in the handle. Fetches the
5188
@return 0, HA_ERR_KEY_NOT_FOUND, or error number */
4543
@return 0, HA_ERR_KEY_NOT_FOUND, or error number */
5191
4546
ha_innobase::index_read(
5192
4547
/*====================*/
5193
unsigned char* buf, /*!< in/out: buffer for the returned
5195
const unsigned char* key_ptr,/*!< in: key value; if this is NULL
5196
we position the cursor at the
5197
start or end of index; this can
5198
also contain an InnoDB row id, in
5199
which case key_len is the InnoDB
5200
row id length; the key value can
5201
also be a prefix of a full key value,
5202
and the last column can be a prefix
5204
uint key_len,/*!< in: key value length */
5205
enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
4548
unsigned char* buf, /*!< in/out: buffer for the returned
4550
const unsigned char* key_ptr,/*!< in: key value; if this is NULL
4551
we position the cursor at the
4552
start or end of index; this can
4553
also contain an InnoDB row id, in
4554
which case key_len is the InnoDB
4555
row id length; the key value can
4556
also be a prefix of a full key value,
4557
and the last column can be a prefix
4559
uint key_len,/*!< in: key value length */
4560
enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
5208
dict_index_t* index;
5209
ulint match_mode = 0;
5213
ut_a(prebuilt->trx == session_to_trx(user_session));
5215
ha_statistic_increment(&system_status_var::ha_read_key_count);
5217
index = prebuilt->index;
5219
if (UNIV_UNLIKELY(index == NULL)) {
5220
prebuilt->index_usable = FALSE;
5221
return(HA_ERR_CRASHED);
5224
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
5225
return(HA_ERR_TABLE_DEF_CHANGED);
5228
/* Note that if the index for which the search template is built is not
5229
necessarily prebuilt->index, but can also be the clustered index */
5231
if (prebuilt->sql_stat_start) {
5232
build_template(prebuilt, user_session, getTable(),
5233
ROW_MYSQL_REC_FIELDS);
5237
/* Convert the search key value to InnoDB format into
5238
prebuilt->search_tuple */
5240
row_sel_convert_mysql_key_to_innobase(
5241
prebuilt->search_tuple,
5242
(byte*) &key_val_buff[0],
5243
(ulint)upd_and_key_val_buff_len,
5249
/* We position the cursor to the last or the first entry
5252
dtuple_set_n_fields(prebuilt->search_tuple, 0);
5255
mode = convert_search_mode_to_innobase(find_flag);
5259
if (find_flag == HA_READ_KEY_EXACT) {
5261
match_mode = ROW_SEL_EXACT;
5263
} else if (find_flag == HA_READ_PREFIX
5264
|| find_flag == HA_READ_PREFIX_LAST) {
5266
match_mode = ROW_SEL_EXACT_PREFIX;
5269
last_match_mode = (uint) match_mode;
5271
if (mode != PAGE_CUR_UNSUPP) {
5273
innodb_srv_conc_enter_innodb(prebuilt->trx);
5275
ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
5278
innodb_srv_conc_exit_innodb(prebuilt->trx);
5281
ret = DB_UNSUPPORTED;
5287
getTable()->status = 0;
5289
case DB_RECORD_NOT_FOUND:
5290
error = HA_ERR_KEY_NOT_FOUND;
5291
getTable()->status = STATUS_NOT_FOUND;
5293
case DB_END_OF_INDEX:
5294
error = HA_ERR_KEY_NOT_FOUND;
5295
getTable()->status = STATUS_NOT_FOUND;
5298
error = convert_error_code_to_mysql((int) ret,
5299
prebuilt->table->flags,
5301
getTable()->status = STATUS_NOT_FOUND;
4563
dict_index_t* index;
4564
ulint match_mode = 0;
4568
ut_a(prebuilt->trx == session_to_trx(user_session));
4570
ha_statistic_increment(&SSV::ha_read_key_count);
4572
index = prebuilt->index;
4574
/* Note that if the index for which the search template is built is not
4575
necessarily prebuilt->index, but can also be the clustered index */
4577
if (prebuilt->sql_stat_start) {
4578
build_template(prebuilt, user_session, table,
4579
ROW_MYSQL_REC_FIELDS);
4583
/* Convert the search key value to InnoDB format into
4584
prebuilt->search_tuple */
4586
row_sel_convert_mysql_key_to_innobase(
4587
prebuilt->search_tuple,
4588
(byte*) key_val_buff,
4589
(ulint)upd_and_key_val_buff_len,
4595
/* We position the cursor to the last or the first entry
4598
dtuple_set_n_fields(prebuilt->search_tuple, 0);
4601
mode = convert_search_mode_to_innobase(find_flag);
4605
if (find_flag == HA_READ_KEY_EXACT) {
4607
match_mode = ROW_SEL_EXACT;
4609
} else if (find_flag == HA_READ_PREFIX
4610
|| find_flag == HA_READ_PREFIX_LAST) {
4612
match_mode = ROW_SEL_EXACT_PREFIX;
4615
last_match_mode = (uint) match_mode;
4617
if (mode != PAGE_CUR_UNSUPP) {
4619
innodb_srv_conc_enter_innodb(prebuilt->trx);
4621
ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
4624
innodb_srv_conc_exit_innodb(prebuilt->trx);
4627
ret = DB_UNSUPPORTED;
4635
case DB_RECORD_NOT_FOUND:
4636
error = HA_ERR_KEY_NOT_FOUND;
4637
table->status = STATUS_NOT_FOUND;
4639
case DB_END_OF_INDEX:
4640
error = HA_ERR_KEY_NOT_FOUND;
4641
table->status = STATUS_NOT_FOUND;
4644
error = convert_error_code_to_mysql((int) ret,
4645
prebuilt->table->flags,
4647
table->status = STATUS_NOT_FOUND;
5308
4654
/*******************************************************************//**
5309
4655
The following functions works like index_read, but it find the last
5310
4656
row with the current key value or prefix.
5311
@return 0, HA_ERR_KEY_NOT_FOUND, or an error code */
4657
@return 0, HA_ERR_KEY_NOT_FOUND, or an error code */
5314
4660
ha_innobase::index_read_last(
5315
4661
/*=========================*/
5316
unsigned char* buf, /*!< out: fetched row */
5317
const unsigned char* key_ptr,/*!< in: key value, or a prefix of a full
5319
uint key_len)/*!< in: length of the key val or prefix
4662
unsigned char* buf, /*!< out: fetched row */
4663
const unsigned char* key_ptr,/*!< in: key value, or a prefix of a full
4665
uint key_len)/*!< in: length of the key val or prefix
5322
return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
4668
return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
5325
4671
/********************************************************************//**
5326
4672
Get the index for a handle. Does not change active index.
5327
@return NULL or index instance. */
4673
@return NULL or index instance. */
5330
4676
ha_innobase::innobase_get_index(
5331
4677
/*============================*/
5332
uint keynr) /*!< in: use this index; MAX_KEY means always
5333
clustered index, even if it was internally
5334
generated by InnoDB */
4678
uint keynr) /*!< in: use this index; MAX_KEY means always
4679
clustered index, even if it was internally
4680
generated by InnoDB */
5336
dict_index_t* index = 0;
5338
ha_statistic_increment(&system_status_var::ha_read_key_count);
5340
if (keynr != MAX_KEY && getTable()->getShare()->sizeKeys() > 0)
5342
KeyInfo *key = getTable()->key_info + keynr;
5343
index = innobase_index_lookup(share, keynr);
5346
ut_a(ut_strcmp(index->name, key->name) == 0);
5348
/* Can't find index with keynr in the translation
5349
table. Only print message if the index translation
5351
if (share->idx_trans_tbl.index_mapping) {
5352
errmsg_printf(ERRMSG_LVL_ERROR,
5353
"InnoDB could not find "
5354
"index %s key no %u for "
5355
"table %s through its "
5356
"index translation table",
5357
key ? key->name : "NULL",
5359
prebuilt->table->name);
5362
index = dict_table_get_index_on_name(prebuilt->table,
5366
index = dict_table_get_first_index(prebuilt->table);
5370
errmsg_printf(ERRMSG_LVL_ERROR,
5371
"Innodb could not find key n:o %u with name %s "
5372
"from dict cache for table %s",
5373
keynr, getTable()->getShare()->getTableProto()->indexes(keynr).name().c_str(),
5374
prebuilt->table->name);
4683
dict_index_t* index = 0;
4685
ha_statistic_increment(&SSV::ha_read_key_count);
4687
ut_ad(user_session == ha_session());
4688
ut_a(prebuilt->trx == session_to_trx(user_session));
4690
if (keynr != MAX_KEY && table->s->keys > 0) {
4691
key = table->key_info + keynr;
4693
index = dict_table_get_index_on_name(prebuilt->table,
4696
index = dict_table_get_first_index(prebuilt->table);
4700
errmsg_printf(ERRMSG_LVL_ERROR,
4701
"Innodb could not find key n:o %u with name %s "
4702
"from dict cache for table %s",
4703
keynr, key ? key->name : "NULL",
4704
prebuilt->table->name);
5380
4710
/********************************************************************//**
5381
4711
Changes the active index of a handle.
5382
@return 0 or error code */
4712
@return 0 or error code */
5385
4715
ha_innobase::change_active_index(
5386
4716
/*=============================*/
5387
uint keynr) /*!< in: use this index; MAX_KEY means always clustered
5388
index, even if it was internally generated by
4717
uint keynr) /*!< in: use this index; MAX_KEY means always clustered
4718
index, even if it was internally generated by
5391
ut_ad(user_session == table->in_use);
5392
ut_a(prebuilt->trx == session_to_trx(user_session));
5394
active_index = keynr;
5396
prebuilt->index = innobase_get_index(keynr);
5398
if (UNIV_UNLIKELY(!prebuilt->index)) {
5399
errmsg_printf(ERRMSG_LVL_WARN, "InnoDB: change_active_index(%u) failed",
5401
prebuilt->index_usable = FALSE;
5405
prebuilt->index_usable = row_merge_is_index_usable(prebuilt->trx,
5408
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
5409
push_warning_printf(user_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5410
HA_ERR_TABLE_DEF_CHANGED,
5411
"InnoDB: insufficient history for index %u",
5413
/* The caller seems to ignore this. Thus, we must check
5414
this again in row_search_for_mysql(). */
5418
ut_a(prebuilt->search_tuple != 0);
5420
dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields);
5422
dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
5423
prebuilt->index->n_fields);
5425
/* MySQL changes the active index for a handle also during some
5426
queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
5427
and then calculates the sum. Previously we played safe and used
5428
the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
5429
copying. Starting from MySQL-4.1 we use a more efficient flag here. */
5431
build_template(prebuilt, user_session, getTable(), ROW_MYSQL_REC_FIELDS);
4721
ut_ad(user_session == ha_session());
4722
ut_a(prebuilt->trx == session_to_trx(user_session));
4724
active_index = keynr;
4726
prebuilt->index = innobase_get_index(keynr);
4728
if (UNIV_UNLIKELY(!prebuilt->index)) {
4729
errmsg_printf(ERRMSG_LVL_WARN, "InnoDB: change_active_index(%u) failed",
4734
prebuilt->index_usable = row_merge_is_index_usable(prebuilt->trx,
4737
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
4738
errmsg_printf(ERRMSG_LVL_WARN,
4739
"InnoDB: insufficient history for index %u",
4741
/* The caller seems to ignore this. Thus, we must check
4742
this again in row_search_for_mysql(). */
4746
ut_a(prebuilt->search_tuple != 0);
4748
dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields);
4750
dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
4751
prebuilt->index->n_fields);
4753
/* MySQL changes the active index for a handle also during some
4754
queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
4755
and then calculates the sum. Previously we played safe and used
4756
the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
4757
copying. Starting from MySQL-4.1 we use a more efficient flag here. */
4759
build_template(prebuilt, user_session, table, ROW_MYSQL_REC_FIELDS);
5436
4764
/**********************************************************************//**
5437
4765
Positions an index cursor to the index specified in keynr. Fetches the
5439
4767
??? This is only used to read whole keys ???
5440
@return error number or 0 */
4768
@return error number or 0 */
5443
4771
ha_innobase::index_read_idx(
5444
4772
/*========================*/
5445
unsigned char* buf, /*!< in/out: buffer for the returned
5447
uint keynr, /*!< in: use this index */
5448
const unsigned char* key, /*!< in: key value; if this is NULL
5449
we position the cursor at the
5450
start or end of index */
5451
uint key_len, /*!< in: key value length */
5452
enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
4773
unsigned char* buf, /*!< in/out: buffer for the returned
4775
uint keynr, /*!< in: use this index */
4776
const unsigned char* key, /*!< in: key value; if this is NULL
4777
we position the cursor at the
4778
start or end of index */
4779
uint key_len, /*!< in: key value length */
4780
enum ha_rkey_function find_flag)/*!< in: search flags from my_base.h */
5454
if (change_active_index(keynr)) {
5459
return(index_read(buf, key, key_len, find_flag));
4782
if (change_active_index(keynr)) {
4787
return(index_read(buf, key, key_len, find_flag));
5462
4790
/***********************************************************************//**
5463
4791
Reads the next or previous row from a cursor, which must have previously been
5464
4792
positioned using index_read.
5465
@return 0, HA_ERR_END_OF_FILE, or error number */
4793
@return 0, HA_ERR_END_OF_FILE, or error number */
5468
4796
ha_innobase::general_fetch(
5469
4797
/*=======================*/
5470
unsigned char* buf, /*!< in/out: buffer for next row in MySQL
5472
uint direction, /*!< in: ROW_SEL_NEXT or ROW_SEL_PREV */
5473
uint match_mode) /*!< in: 0, ROW_SEL_EXACT, or
5474
ROW_SEL_EXACT_PREFIX */
4798
unsigned char* buf, /*!< in/out: buffer for next row in MySQL
4800
uint direction, /*!< in: ROW_SEL_NEXT or ROW_SEL_PREV */
4801
uint match_mode) /*!< in: 0, ROW_SEL_EXACT, or
4802
ROW_SEL_EXACT_PREFIX */
5479
ut_a(prebuilt->trx == session_to_trx(user_session));
5481
innodb_srv_conc_enter_innodb(prebuilt->trx);
5483
ret = row_search_for_mysql(
5484
(byte*)buf, 0, prebuilt, match_mode, direction);
5486
innodb_srv_conc_exit_innodb(prebuilt->trx);
5491
getTable()->status = 0;
5493
case DB_RECORD_NOT_FOUND:
5494
error = HA_ERR_END_OF_FILE;
5495
getTable()->status = STATUS_NOT_FOUND;
5497
case DB_END_OF_INDEX:
5498
error = HA_ERR_END_OF_FILE;
5499
getTable()->status = STATUS_NOT_FOUND;
5502
error = convert_error_code_to_mysql(
5503
(int) ret, prebuilt->table->flags, user_session);
5504
getTable()->status = STATUS_NOT_FOUND;
4807
ut_a(prebuilt->trx == session_to_trx(user_session));
4809
innodb_srv_conc_enter_innodb(prebuilt->trx);
4811
ret = row_search_for_mysql(
4812
(byte*)buf, 0, prebuilt, match_mode, direction);
4814
innodb_srv_conc_exit_innodb(prebuilt->trx);
4821
case DB_RECORD_NOT_FOUND:
4822
error = HA_ERR_END_OF_FILE;
4823
table->status = STATUS_NOT_FOUND;
4825
case DB_END_OF_INDEX:
4826
error = HA_ERR_END_OF_FILE;
4827
table->status = STATUS_NOT_FOUND;
4830
error = convert_error_code_to_mysql(
4831
(int) ret, prebuilt->table->flags, user_session);
4832
table->status = STATUS_NOT_FOUND;
5511
4839
/***********************************************************************//**
5512
4840
Reads the next row from a cursor, which must have previously been
5513
4841
positioned using index_read.
5514
@return 0, HA_ERR_END_OF_FILE, or error number */
4842
@return 0, HA_ERR_END_OF_FILE, or error number */
5517
4845
ha_innobase::index_next(
5518
4846
/*====================*/
5519
unsigned char* buf) /*!< in/out: buffer for next row in MySQL
4847
unsigned char* buf) /*!< in/out: buffer for next row in MySQL
5522
ha_statistic_increment(&system_status_var::ha_read_next_count);
4850
ha_statistic_increment(&SSV::ha_read_next_count);
5524
return(general_fetch(buf, ROW_SEL_NEXT, 0));
4852
return(general_fetch(buf, ROW_SEL_NEXT, 0));
5527
4855
/*******************************************************************//**
5528
4856
Reads the next row matching to the key value given as the parameter.
5529
@return 0, HA_ERR_END_OF_FILE, or error number */
4857
@return 0, HA_ERR_END_OF_FILE, or error number */
5532
4860
ha_innobase::index_next_same(
5533
4861
/*=========================*/
5534
unsigned char* buf, /*!< in/out: buffer for the row */
5535
const unsigned char* , /*!< in: key value */
5536
uint ) /*!< in: key value length */
4862
unsigned char* buf, /*!< in/out: buffer for the row */
4863
const unsigned char* , /*!< in: key value */
4864
uint ) /*!< in: key value length */
5538
ha_statistic_increment(&system_status_var::ha_read_next_count);
4866
ha_statistic_increment(&SSV::ha_read_next_count);
5540
return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
4868
return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
5543
4871
/***********************************************************************//**
5544
4872
Reads the previous row from a cursor, which must have previously been
5545
4873
positioned using index_read.
5546
@return 0, HA_ERR_END_OF_FILE, or error number */
4874
@return 0, HA_ERR_END_OF_FILE, or error number */
5549
4877
ha_innobase::index_prev(
5550
4878
/*====================*/
5551
unsigned char* buf) /*!< in/out: buffer for previous row in MySQL format */
4879
unsigned char* buf) /*!< in/out: buffer for previous row in MySQL format */
5553
ha_statistic_increment(&system_status_var::ha_read_prev_count);
4881
ha_statistic_increment(&SSV::ha_read_prev_count);
5555
return(general_fetch(buf, ROW_SEL_PREV, 0));
4883
return(general_fetch(buf, ROW_SEL_PREV, 0));
5558
4886
/********************************************************************//**
5559
4887
Positions a cursor on the first record in an index and reads the
5560
4888
corresponding row to buf.
5561
@return 0, HA_ERR_END_OF_FILE, or error code */
4889
@return 0, HA_ERR_END_OF_FILE, or error code */
5564
4892
ha_innobase::index_first(
5565
4893
/*=====================*/
5566
unsigned char* buf) /*!< in/out: buffer for the row */
4894
unsigned char* buf) /*!< in/out: buffer for the row */
5570
ha_statistic_increment(&system_status_var::ha_read_first_count);
5572
error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
5574
/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
5576
if (error == HA_ERR_KEY_NOT_FOUND) {
5577
error = HA_ERR_END_OF_FILE;
4898
ha_statistic_increment(&SSV::ha_read_first_count);
4900
error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
4902
/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
4904
if (error == HA_ERR_KEY_NOT_FOUND) {
4905
error = HA_ERR_END_OF_FILE;
5583
4911
/********************************************************************//**
5584
4912
Positions a cursor on the last record in an index and reads the
5585
4913
corresponding row to buf.
5586
@return 0, HA_ERR_END_OF_FILE, or error code */
4914
@return 0, HA_ERR_END_OF_FILE, or error code */
5589
4917
ha_innobase::index_last(
5590
4918
/*====================*/
5591
unsigned char* buf) /*!< in/out: buffer for the row */
4919
unsigned char* buf) /*!< in/out: buffer for the row */
5595
ha_statistic_increment(&system_status_var::ha_read_last_count);
5597
error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
5599
/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
5601
if (error == HA_ERR_KEY_NOT_FOUND) {
5602
error = HA_ERR_END_OF_FILE;
4923
ha_statistic_increment(&SSV::ha_read_last_count);
4925
error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
4927
/* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
4929
if (error == HA_ERR_KEY_NOT_FOUND) {
4930
error = HA_ERR_END_OF_FILE;
5608
4936
/****************************************************************//**
5609
4937
Initialize a table scan.
5610
@return 0 or error number */
4938
@return 0 or error number */
5613
ha_innobase::doStartTableScan(
4941
ha_innobase::rnd_init(
5614
4942
/*==================*/
5615
bool scan) /*!< in: TRUE if table/index scan FALSE otherwise */
4943
bool scan) /*!< in: TRUE if table/index scan FALSE otherwise */
5619
/* Store the active index value so that we can restore the original
5620
value after a scan */
5622
if (prebuilt->clust_index_was_generated) {
5623
err = change_active_index(MAX_KEY);
5625
err = change_active_index(primary_key);
5628
/* Don't use semi-consistent read in random row reads (by position).
5629
This means we must disable semi_consistent_read if scan is false */
5632
try_semi_consistent_read(0);
4947
/* Store the active index value so that we can restore the original
4948
value after a scan */
4950
if (prebuilt->clust_index_was_generated) {
4951
err = change_active_index(MAX_KEY);
4953
err = change_active_index(primary_key);
4956
/* Don't use semi-consistent read in random row reads (by position).
4957
This means we must disable semi_consistent_read if scan is false */
4960
try_semi_consistent_read(0);
5640
4968
/*****************************************************************//**
5641
4969
Ends a table scan.
5642
@return 0 or error number */
4970
@return 0 or error number */
5645
ha_innobase::doEndTableScan(void)
4973
ha_innobase::rnd_end(void)
5646
4974
/*======================*/
5648
return(doEndIndexScan());
4976
return(index_end());
5651
4979
/*****************************************************************//**
5652
4980
Reads the next row in a table scan (also used to read the FIRST row
5653
4981
in a table scan).
5654
@return 0, HA_ERR_END_OF_FILE, or error number */
4982
@return 0, HA_ERR_END_OF_FILE, or error number */
5657
4985
ha_innobase::rnd_next(
5658
4986
/*==================*/
5659
unsigned char* buf) /*!< in/out: returns the row in this buffer,
4987
unsigned char* buf) /*!< in/out: returns the row in this buffer,
5664
ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
5666
if (start_of_scan) {
5667
error = index_first(buf);
5669
if (error == HA_ERR_KEY_NOT_FOUND) {
5670
error = HA_ERR_END_OF_FILE;
5675
error = general_fetch(buf, ROW_SEL_NEXT, 0);
4992
ha_statistic_increment(&SSV::ha_read_rnd_next_count);
4994
if (start_of_scan) {
4995
error = index_first(buf);
4997
if (error == HA_ERR_KEY_NOT_FOUND) {
4998
error = HA_ERR_END_OF_FILE;
5003
error = general_fetch(buf, ROW_SEL_NEXT, 0);
5681
5009
/**********************************************************************//**
5682
5010
Fetches a row from the table based on a row reference.
5683
@return 0, HA_ERR_KEY_NOT_FOUND, or error code */
5011
@return 0, HA_ERR_KEY_NOT_FOUND, or error code */
5686
5014
ha_innobase::rnd_pos(
5687
5015
/*=================*/
5688
unsigned char* buf, /*!< in/out: buffer for the row */
5689
unsigned char* pos) /*!< in: primary key value of the row in the
5690
MySQL format, or the row id if the clustered
5691
index was internally generated by InnoDB; the
5692
length of data in pos has to be ref_length */
5016
unsigned char* buf, /*!< in/out: buffer for the row */
5017
unsigned char* pos) /*!< in: primary key value of the row in the
5018
MySQL format, or the row id if the clustered
5019
index was internally generated by InnoDB; the
5020
length of data in pos has to be ref_length */
5695
uint keynr = active_index;
5697
ha_statistic_increment(&system_status_var::ha_read_rnd_count);
5699
ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
5701
if (prebuilt->clust_index_was_generated) {
5702
/* No primary key was defined for the table and we
5703
generated the clustered index from the row id: the
5704
row reference is the row id, not any key value
5705
that MySQL knows of */
5707
error = change_active_index(MAX_KEY);
5709
error = change_active_index(primary_key);
5716
/* Note that we assume the length of the row reference is fixed
5717
for the table, and it is == ref_length */
5719
error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
5724
change_active_index(keynr);
5023
uint keynr = active_index;
5025
ha_statistic_increment(&SSV::ha_read_rnd_count);
5027
ut_a(prebuilt->trx == session_to_trx(ha_session()));
5029
if (prebuilt->clust_index_was_generated) {
5030
/* No primary key was defined for the table and we
5031
generated the clustered index from the row id: the
5032
row reference is the row id, not any key value
5033
that MySQL knows of */
5035
error = change_active_index(MAX_KEY);
5037
error = change_active_index(primary_key);
5044
/* Note that we assume the length of the row reference is fixed
5045
for the table, and it is == ref_length */
5047
error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
5052
change_active_index(keynr);
5729
5057
/*********************************************************************//**
6120
5534
InnobaseEngine::doCreateTable(
6121
5535
/*================*/
6122
Session &session, /*!< in: Session */
6123
Table& form, /*!< in: information on table columns and indexes */
6124
const TableIdentifier &identifier,
5536
Session* session, /*!< in: Session */
5537
const char* table_name, /*!< in: table name */
5538
Table& form, /*!< in: information on table
5539
columns and indexes */
6125
5540
message::Table& create_proto)
6128
dict_table_t* innobase_table;
6133
char name2[FN_REFLEN];
6134
char norm_name[FN_REFLEN];
6135
ib_int64_t auto_inc_value;
6137
/* Cache the value of innodb_file_format, in case it is
6138
modified by another thread while the table is being created. */
6139
const ulint file_format = srv_file_format;
6140
bool lex_identified_temp_table= (create_proto.type() == message::Table::TEMPORARY);
6144
const char *table_name= identifier.getPath().c_str();
6146
if (form.getShare()->sizeFields() > 1000) {
6147
/* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
6148
but we play safe here */
6150
return(HA_ERR_TO_BIG_ROW);
6153
/* Get the transaction associated with the current session, or create one
6154
if not yet created */
6156
parent_trx = check_trx_exists(&session);
6158
/* In case MySQL calls this in the middle of a SELECT query, release
6159
possible adaptive hash latch to avoid deadlocks of threads */
6161
trx_search_latch_release_if_reserved(parent_trx);
6163
trx = innobase_trx_allocate(&session);
6165
srv_lower_case_table_names = TRUE;
6167
strcpy(name2, table_name);
6169
normalize_table_name(norm_name, name2);
6171
/* Latch the InnoDB data dictionary exclusively so that no deadlocks
6172
or lock waits can happen in it during a table create operation.
6173
Drop table etc. do this latching in row0mysql.c. */
6175
row_mysql_lock_data_dictionary(trx);
6177
/* Create the table definition in InnoDB */
6181
#if 0 // Since we validate the options before this stage, we no longer need to do this.
6182
/* Validate create options if innodb_strict_mode is set. */
6183
if (! create_options_are_valid(&session, form, create_proto)) {
6184
error = ER_ILLEGAL_HA_CREATE_OPTION;
5543
dict_table_t* innobase_table;
5548
char name2[FN_REFLEN];
5549
char norm_name[FN_REFLEN];
5550
ib_int64_t auto_inc_value;
5552
/* Cache the value of innodb_file_format, in case it is
5553
modified by another thread while the table is being created. */
5554
const ulint file_format = srv_file_format;
5555
bool lex_identified_temp_table= (create_proto.type() == message::Table::TEMPORARY);
5557
assert(session != NULL);
5560
/* Names passed in from server are in two formats:
5561
1. <database_name>/<table_name>: for normal table creation
5562
2. full path: for temp table creation, or sym link
5564
When srv_file_per_table is on, check for full path pattern, i.e.
5565
X:\dir\..., X is a driver letter, or
5566
\\dir1\dir2\..., UNC path
5567
returns error if it is in full path format, but not creating a temp.
5568
table. Currently InnoDB does not support symbolic link on Windows. */
5570
if (srv_file_per_table
5571
&& (! lex_identified_temp_table)) {
5573
if ((table_name[1] == ':')
5574
|| (table_name[0] == '\\' && table_name[1] == '\\')) {
5575
errmsg_printf(ERRMSG_LVL_ERROR, "Cannot create table %s\n", table_name);
5576
return(HA_ERR_GENERIC);
6189
// We assume compact format by default
6190
iflags= DICT_TF_COMPACT;
6192
size_t num_engine_options= create_proto.engine().options_size();
6193
for (size_t x= 0; x < num_engine_options; ++x)
6195
if (boost::iequals(create_proto.engine().options(x).name(), "ROW_FORMAT"))
6197
if (boost::iequals(create_proto.engine().options(x).state(), "COMPRESSED"))
6199
iflags= DICT_TF_FORMAT_ZIP;
6201
else if (boost::iequals(create_proto.engine().options(x).state(), "COMPACT"))
6203
iflags= DICT_TF_FORMAT_ZIP;
6205
else if (boost::iequals(create_proto.engine().options(x).state(), "DYNAMIC"))
6207
iflags= DICT_TF_COMPACT;
6209
else if (boost::iequals(create_proto.engine().options(x).state(), "REDUNDANT"))
6211
iflags= DICT_TF_COMPACT;
6216
assert(0); // This should never happen since we have already validated the options.
6220
if (iflags == DICT_TF_FORMAT_ZIP)
6223
ROW_FORMAT=COMPRESSED without KEY_BLOCK_SIZE implies half the maximum KEY_BLOCK_SIZE.
6224
@todo implement KEY_BLOCK_SIZE
6226
iflags= (DICT_TF_ZSSIZE_MAX - 1)
6227
<< DICT_TF_ZSSIZE_SHIFT
6229
| DICT_TF_FORMAT_ZIP
6230
<< DICT_TF_FORMAT_SHIFT;
5581
if (form.s->fields > 1000) {
5582
/* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
5583
but we play safe here */
5585
return(HA_ERR_TO_BIG_ROW);
5588
/* Get the transaction associated with the current session, or create one
5589
if not yet created */
5591
parent_trx = check_trx_exists(session);
5593
/* In case MySQL calls this in the middle of a SELECT query, release
5594
possible adaptive hash latch to avoid deadlocks of threads */
5596
trx_search_latch_release_if_reserved(parent_trx);
5598
trx = innobase_trx_allocate(session);
5600
srv_lower_case_table_names = TRUE;
5602
strcpy(name2, table_name);
5604
normalize_table_name(norm_name, name2);
5606
/* Latch the InnoDB data dictionary exclusively so that no deadlocks
5607
or lock waits can happen in it during a table create operation.
5608
Drop table etc. do this latching in row0mysql.c. */
5610
row_mysql_lock_data_dictionary(trx);
5612
/* Create the table definition in InnoDB */
5616
/* Validate create options if innodb_strict_mode is set. */
5617
if (! create_options_are_valid(session, form, create_proto)) {
5618
error = ER_ILLEGAL_HA_CREATE_OPTION;
5622
if (create_proto.options().has_key_block_size()) {
5623
/* Determine the page_zip.ssize corresponding to the
5624
requested page size (key_block_size) in kilobytes. */
5627
ulint key_block_size = create_proto.options().key_block_size();
5629
for (ssize = ksize = 1; ssize <= DICT_TF_ZSSIZE_MAX;
5630
ssize++, ksize <<= 1) {
5631
if (key_block_size == ksize) {
5632
iflags = ssize << DICT_TF_ZSSIZE_SHIFT
5634
| DICT_TF_FORMAT_ZIP
5635
<< DICT_TF_FORMAT_SHIFT;
5640
if (!srv_file_per_table) {
5641
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5642
ER_ILLEGAL_HA_CREATE_OPTION,
5643
"InnoDB: KEY_BLOCK_SIZE"
5644
" requires innodb_file_per_table.");
5648
if (file_format < DICT_TF_FORMAT_ZIP) {
5649
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5650
ER_ILLEGAL_HA_CREATE_OPTION,
5651
"InnoDB: KEY_BLOCK_SIZE"
5652
" requires innodb_file_format >"
5658
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
5659
ER_ILLEGAL_HA_CREATE_OPTION,
5661
" KEY_BLOCK_SIZE=%lu.",
5662
create_proto.options().key_block_size());
5666
if (create_proto.options().has_row_type()) {
5668
/* KEY_BLOCK_SIZE was specified. */
5669
if (form.s->row_type != ROW_TYPE_COMPRESSED) {
5670
/* ROW_FORMAT other than COMPRESSED
5671
ignores KEY_BLOCK_SIZE. It does not
5672
make sense to reject conflicting
5673
KEY_BLOCK_SIZE and ROW_FORMAT, because
5674
such combinations can be obtained
5675
with ALTER TABLE anyway. */
5676
push_warning_printf(
5678
DRIZZLE_ERROR::WARN_LEVEL_WARN,
5679
ER_ILLEGAL_HA_CREATE_OPTION,
5680
"InnoDB: ignoring KEY_BLOCK_SIZE=%lu"
5681
" unless ROW_FORMAT=COMPRESSED.",
5682
create_proto.options().key_block_size());
5686
/* No KEY_BLOCK_SIZE */
5687
if (form.s->row_type == ROW_TYPE_COMPRESSED) {
5688
/* ROW_FORMAT=COMPRESSED without
5689
KEY_BLOCK_SIZE implies half the
5690
maximum KEY_BLOCK_SIZE. */
5691
iflags = (DICT_TF_ZSSIZE_MAX - 1)
5692
<< DICT_TF_ZSSIZE_SHIFT
5694
| DICT_TF_FORMAT_ZIP
5695
<< DICT_TF_FORMAT_SHIFT;
6231
5696
#if DICT_TF_ZSSIZE_MAX < 1
6232
5697
# error "DICT_TF_ZSSIZE_MAX < 1"
6237
if (! srv_file_per_table)
6239
push_warning_printf(
6241
DRIZZLE_ERROR::WARN_LEVEL_WARN,
6242
ER_ILLEGAL_HA_CREATE_OPTION,
6243
"InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table.");
6245
else if (file_format < DICT_TF_FORMAT_ZIP)
6247
push_warning_printf(
6249
DRIZZLE_ERROR::WARN_LEVEL_WARN,
6250
ER_ILLEGAL_HA_CREATE_OPTION,
6251
"InnoDB: ROW_FORMAT=compressed requires innodb_file_format > Antelope.");
6256
/* Look for a primary key */
6258
primary_key_no= (form.getShare()->hasPrimaryKey() ?
6259
(int) form.getShare()->getPrimaryKey() :
6262
/* Our function innobase_get_mysql_key_number_for_index assumes
6263
the primary key is always number 0, if it exists */
6265
assert(primary_key_no == -1 || primary_key_no == 0);
6267
/* Check for name conflicts (with reserved name) for
6268
any user indices to be created. */
6269
if (innobase_index_name_is_reserved(trx, form.key_info,
6270
form.getShare()->keys)) {
6275
if (lex_identified_temp_table)
6276
iflags |= DICT_TF2_TEMPORARY << DICT_TF2_SHIFT;
6278
error= create_table_def(trx, &form, norm_name,
6279
lex_identified_temp_table ? name2 : NULL,
6282
session.setXaId(trx->id);
6288
/* Create the keys */
6290
if (form.getShare()->sizeKeys() == 0 || primary_key_no == -1) {
6291
/* Create an index which is used as the clustered index;
6292
order the rows by their row id which is internally generated
6295
error = create_clustered_index_when_no_primary(trx, iflags, norm_name);
6301
if (primary_key_no != -1) {
6302
/* In InnoDB the clustered index must always be created first */
6303
if ((error = create_index(trx, &form, iflags, norm_name,
6304
(uint) primary_key_no))) {
6309
for (i = 0; i < form.getShare()->sizeKeys(); i++) {
6310
if (i != (uint) primary_key_no) {
6312
if ((error = create_index(trx, &form, iflags, norm_name,
6319
stmt = innobase_get_stmt(&session, &stmt_len);
6322
string generated_create_table;
6323
const char *query= stmt;
6325
if (session_sql_command(&session) == SQLCOM_CREATE_TABLE)
6327
message::transformTableDefinitionToSql(create_proto,
6328
generated_create_table,
6329
message::DRIZZLE, true);
6330
query= generated_create_table.c_str();
6333
error = row_table_add_foreign_constraints(trx,
6334
query, strlen(query),
6336
lex_identified_temp_table);
6338
error = convert_error_code_to_mysql(error, iflags, NULL);
6345
innobase_commit_low(trx);
6347
row_mysql_unlock_data_dictionary(trx);
6349
/* Flush the log to reduce probability that the .frm files and
6350
the InnoDB data dictionary get out-of-sync if the user runs
6351
with innodb_flush_log_at_trx_commit = 0 */
6353
log_buffer_flush_to_disk();
6355
innobase_table = dict_table_get(norm_name, FALSE);
6357
assert(innobase_table != 0);
6359
if (innobase_table) {
6360
/* We update the highest file format in the system table
6361
space, if this table has higher file format setting. */
6363
char changed_file_format_max[100];
6364
strcpy(changed_file_format_max, innobase_file_format_max.c_str());
6365
trx_sys_file_format_max_upgrade((const char **)&changed_file_format_max,
6366
dict_table_get_format(innobase_table));
6367
innobase_file_format_max= changed_file_format_max;
6370
/* Note: We can't call update_session() as prebuilt will not be
6371
setup at this stage and so we use session. */
6373
/* We need to copy the AUTOINC value from the old table if
6374
this is an ALTER TABLE or CREATE INDEX because CREATE INDEX
6375
does a table copy too. */
6377
if ((create_proto.options().has_auto_increment_value()
6378
|| session_sql_command(&session) == SQLCOM_ALTER_TABLE
6379
|| session_sql_command(&session) == SQLCOM_CREATE_INDEX)
6380
&& create_proto.options().auto_increment_value() != 0) {
6382
/* Query was one of :
6383
CREATE TABLE ...AUTO_INCREMENT = x; or
6384
ALTER TABLE...AUTO_INCREMENT = x; or
6385
CREATE INDEX x on t(...);
6386
Find out a table definition from the dictionary and get
6387
the current value of the auto increment field. Set a new
6388
value to the auto increment field if the value is greater
6389
than the maximum value in the column. */
6391
auto_inc_value = create_proto.options().auto_increment_value();
6393
dict_table_autoinc_lock(innobase_table);
6394
dict_table_autoinc_initialize(innobase_table, auto_inc_value);
6395
dict_table_autoinc_unlock(innobase_table);
6398
/* Tell the InnoDB server that there might be work for
6401
srv_active_wake_master_thread();
6403
trx_free_for_mysql(trx);
6405
if (lex_identified_temp_table)
6407
session.getMessageCache().storeTableMessage(identifier, create_proto);
6411
StorageEngine::writeDefinitionFromPath(identifier, create_proto);
5702
switch (form.s->row_type) {
5703
const char* row_format_name;
5704
case ROW_TYPE_REDUNDANT:
5706
case ROW_TYPE_COMPRESSED:
5707
case ROW_TYPE_DYNAMIC:
5709
= form.s->row_type == ROW_TYPE_COMPRESSED
5713
if (!srv_file_per_table) {
5714
push_warning_printf(
5716
DRIZZLE_ERROR::WARN_LEVEL_WARN,
5717
ER_ILLEGAL_HA_CREATE_OPTION,
5718
"InnoDB: ROW_FORMAT=%s"
5719
" requires innodb_file_per_table.",
5721
} else if (file_format < DICT_TF_FORMAT_ZIP) {
5722
push_warning_printf(
5724
DRIZZLE_ERROR::WARN_LEVEL_WARN,
5725
ER_ILLEGAL_HA_CREATE_OPTION,
5726
"InnoDB: ROW_FORMAT=%s"
5727
" requires innodb_file_format >"
5731
iflags |= DICT_TF_COMPACT
5732
| (DICT_TF_FORMAT_ZIP
5733
<< DICT_TF_FORMAT_SHIFT);
5738
case ROW_TYPE_NOT_USED:
5739
case ROW_TYPE_FIXED:
5741
error = ER_ILLEGAL_HA_CREATE_OPTION;
5743
case ROW_TYPE_DEFAULT:
5744
case ROW_TYPE_COMPACT:
5745
iflags = DICT_TF_COMPACT;
5748
} else if (!iflags) {
5749
/* No KEY_BLOCK_SIZE or ROW_FORMAT specified:
5750
use ROW_FORMAT=COMPACT by default. */
5751
iflags = DICT_TF_COMPACT;
5754
error = create_table_def(trx, &form, norm_name,
5755
lex_identified_temp_table ? name2 : NULL,
5762
/* Look for a primary key */
5764
primary_key_no= (form.s->primary_key != MAX_KEY ?
5765
(int) form.s->primary_key :
5768
/* Our function row_get_mysql_key_number_for_index assumes
5769
the primary key is always number 0, if it exists */
5771
assert(primary_key_no == -1 || primary_key_no == 0);
5773
/* Create the keys */
5775
if (form.s->keys == 0 || primary_key_no == -1) {
5776
/* Create an index which is used as the clustered index;
5777
order the rows by their row id which is internally generated
5780
error = create_clustered_index_when_no_primary(
5781
trx, iflags, norm_name);
5787
if (primary_key_no != -1) {
5788
/* In InnoDB the clustered index must always be created
5790
if ((error = create_index(trx, &form, iflags, norm_name,
5791
(uint) primary_key_no))) {
5796
for (i = 0; i < form.s->keys; i++) {
5798
if (i != (uint) primary_key_no) {
5800
if ((error = create_index(trx, &form, iflags, norm_name,
5807
if (*trx->mysql_query_str) {
5808
error = row_table_add_foreign_constraints(trx,
5809
*trx->mysql_query_str, norm_name,
5810
lex_identified_temp_table);
5812
error = convert_error_code_to_mysql(error, iflags, NULL);
5819
innobase_commit_low(trx);
5821
row_mysql_unlock_data_dictionary(trx);
5823
/* Flush the log to reduce probability that the .frm files and
5824
the InnoDB data dictionary get out-of-sync if the user runs
5825
with innodb_flush_log_at_trx_commit = 0 */
5827
log_buffer_flush_to_disk();
5829
innobase_table = dict_table_get(norm_name, FALSE);
5831
assert(innobase_table != 0);
5833
if (innobase_table) {
5834
/* We update the highest file format in the system table
5835
space, if this table has higher file format setting. */
5837
trx_sys_file_format_max_upgrade(
5838
(const char**) &innobase_file_format_check,
5839
dict_table_get_format(innobase_table));
5842
/* Note: We can't call update_session() as prebuilt will not be
5843
setup at this stage and so we use session. */
5845
/* We need to copy the AUTOINC value from the old table if
5846
this is an ALTER TABLE. */
5848
if ((create_proto.options().has_auto_increment_value()
5849
|| session_sql_command(session) == SQLCOM_ALTER_TABLE)
5850
&& create_proto.options().auto_increment_value() != 0) {
5852
/* Query was ALTER TABLE...AUTO_INCREMENT = x; or
5853
CREATE TABLE ...AUTO_INCREMENT = x; Find out a table
5854
definition from the dictionary and get the current value
5855
of the auto increment field. Set a new value to the
5856
auto increment field if the value is greater than the
5857
maximum value in the column. */
5859
auto_inc_value = create_proto.options().auto_increment_value();
5861
dict_table_autoinc_lock(innobase_table);
5862
dict_table_autoinc_initialize(innobase_table, auto_inc_value);
5863
dict_table_autoinc_unlock(innobase_table);
5866
/* Tell the InnoDB server that there might be work for
5869
srv_active_wake_master_thread();
5871
trx_free_for_mysql(trx);
6417
innobase_commit_low(trx);
6419
row_mysql_unlock_data_dictionary(trx);
6421
trx_free_for_mysql(trx);
5876
innobase_commit_low(trx);
5878
row_mysql_unlock_data_dictionary(trx);
5880
trx_free_for_mysql(trx);
6426
5885
/*****************************************************************//**
6427
5886
Discards or imports an InnoDB tablespace.
6428
@return 0 == success, -1 == error */
5887
@return 0 == success, -1 == error */
6431
5890
ha_innobase::discard_or_import_tablespace(
6432
5891
/*======================================*/
6433
my_bool discard) /*!< in: TRUE if discard, else import */
5892
my_bool discard) /*!< in: TRUE if discard, else import */
6435
dict_table_t* dict_table;
6439
ut_a(prebuilt->trx);
6440
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6441
ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
6443
dict_table = prebuilt->table;
6444
trx = prebuilt->trx;
6447
err = row_discard_tablespace_for_mysql(dict_table->name, trx);
6449
err = row_import_tablespace_for_mysql(dict_table->name, trx);
6452
err = convert_error_code_to_mysql(err, dict_table->flags, NULL);
5894
dict_table_t* dict_table;
5898
ut_a(prebuilt->trx);
5899
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
5900
ut_a(prebuilt->trx == session_to_trx(ha_session()));
5902
dict_table = prebuilt->table;
5903
trx = prebuilt->trx;
5906
err = row_discard_tablespace_for_mysql(dict_table->name, trx);
5908
err = row_import_tablespace_for_mysql(dict_table->name, trx);
5911
err = convert_error_code_to_mysql(err, dict_table->flags, NULL);
6457
5916
/*****************************************************************//**
6458
5917
Deletes all rows of an InnoDB table.
6459
@return error number */
5918
@return error number */
6462
5921
ha_innobase::delete_all_rows(void)
6463
5922
/*==============================*/
6467
/* Get the transaction associated with the current session, or create one
6468
if not yet created, and update prebuilt->trx */
6470
update_session(getTable()->in_use);
6472
if (session_sql_command(user_session) != SQLCOM_TRUNCATE) {
6474
/* We only handle TRUNCATE TABLE t as a special case.
6475
DELETE FROM t will have to use ha_innobase::doDeleteRecord(),
6476
because DELETE is transactional while TRUNCATE is not. */
6477
return(errno=HA_ERR_WRONG_COMMAND);
6480
/* Truncate the table in InnoDB */
6482
error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
6483
if (error == DB_ERROR) {
6484
/* Cannot truncate; resort to ha_innobase::doDeleteRecord() */
6488
error = convert_error_code_to_mysql(error, prebuilt->table->flags,
5926
/* Get the transaction associated with the current session, or create one
5927
if not yet created, and update prebuilt->trx */
5929
update_session(ha_session());
5931
if (session_sql_command(user_session) != SQLCOM_TRUNCATE) {
5933
/* We only handle TRUNCATE TABLE t as a special case.
5934
DELETE FROM t will have to use ha_innobase::delete_row(),
5935
because DELETE is transactional while TRUNCATE is not. */
5936
return(errno=HA_ERR_WRONG_COMMAND);
5939
/* Truncate the table in InnoDB */
5941
error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
5942
if (error == DB_ERROR) {
5943
/* Cannot truncate; resort to ha_innobase::delete_row() */
5947
error = convert_error_code_to_mysql(error, prebuilt->table->flags,
6494
5953
/*****************************************************************//**
6497
5956
Then the current user cannot have locks set on the table. Drop table
6498
5957
operation inside InnoDB will remove all locks any user has on the table
6500
@return error number */
5959
@return error number */
6503
5962
InnobaseEngine::doDropTable(
6504
5963
/*======================*/
6506
const TableIdentifier &identifier)
5965
const string table_path) /* in: table name */
6511
char norm_name[1000];
6513
ut_a(identifier.getPath().length() < 1000);
6515
/* Strangely, MySQL passes the table name without the '.frm'
6516
extension, in contrast to ::create */
6517
normalize_table_name(norm_name, identifier.getPath().c_str());
6519
/* Get the transaction associated with the current session, or create one
6520
if not yet created */
6522
parent_trx = check_trx_exists(&session);
6524
/* In case MySQL calls this in the middle of a SELECT query, release
6525
possible adaptive hash latch to avoid deadlocks of threads */
6527
trx_search_latch_release_if_reserved(parent_trx);
6529
trx = innobase_trx_allocate(&session);
6531
srv_lower_case_table_names = TRUE;
6533
/* Drop the table in InnoDB */
6535
error = row_drop_table_for_mysql(norm_name, trx,
6536
session_sql_command(&session)
6539
session.setXaId(trx->id);
6541
/* Flush the log to reduce probability that the .frm files and
6542
the InnoDB data dictionary get out-of-sync if the user runs
6543
with innodb_flush_log_at_trx_commit = 0 */
6545
log_buffer_flush_to_disk();
6547
/* Tell the InnoDB server that there might be work for
6550
srv_active_wake_master_thread();
6552
innobase_commit_low(trx);
6554
trx_free_for_mysql(trx);
6556
if (error != ENOENT)
6557
error = convert_error_code_to_mysql(error, 0, NULL);
6559
if (error == 0 || error == ENOENT)
6561
if (identifier.getType() == message::Table::TEMPORARY)
6563
session.getMessageCache().removeTableMessage(identifier);
6564
ulint sql_command = session_sql_command(&session);
6566
// If this was the final removal to an alter table then we will need
6567
// to remove the .dfe that was left behind.
6568
if ((sql_command == SQLCOM_ALTER_TABLE
6569
|| sql_command == SQLCOM_CREATE_INDEX
6570
|| sql_command == SQLCOM_DROP_INDEX))
6572
string path(identifier.getPath());
6574
path.append(DEFAULT_FILE_EXTENSION);
6576
(void)internal::my_delete(path.c_str(), MYF(0));
6581
string path(identifier.getPath());
6583
path.append(DEFAULT_FILE_EXTENSION);
6585
(void)internal::my_delete(path.c_str(), MYF(0));
5970
char norm_name[1000];
5972
ut_a(table_path.length() < 1000);
5974
/* Strangely, MySQL passes the table name without the '.frm'
5975
extension, in contrast to ::create */
5976
normalize_table_name(norm_name, table_path.c_str());
5978
/* Get the transaction associated with the current session, or create one
5979
if not yet created */
5981
parent_trx = check_trx_exists(&session);
5983
/* In case MySQL calls this in the middle of a SELECT query, release
5984
possible adaptive hash latch to avoid deadlocks of threads */
5986
trx_search_latch_release_if_reserved(parent_trx);
5988
trx = innobase_trx_allocate(&session);
5990
srv_lower_case_table_names = TRUE;
5992
/* Drop the table in InnoDB */
5994
error = row_drop_table_for_mysql(norm_name, trx,
5995
session_sql_command(&session)
5998
/* Flush the log to reduce probability that the .frm files and
5999
the InnoDB data dictionary get out-of-sync if the user runs
6000
with innodb_flush_log_at_trx_commit = 0 */
6002
log_buffer_flush_to_disk();
6004
/* Tell the InnoDB server that there might be work for
6007
srv_active_wake_master_thread();
6009
innobase_commit_low(trx);
6011
trx_free_for_mysql(trx);
6014
error = convert_error_code_to_mysql(error, 0, NULL);
6592
6019
/*****************************************************************//**
6593
6020
Removes all tables in the named database inside InnoDB. */
6595
InnobaseEngine::doDropSchema(
6022
InnobaseEngine::drop_database(
6596
6023
/*===================*/
6597
const SchemaIdentifier &identifier)
6598
/*!< in: database path; inside InnoDB the name
6599
of the last directory in the path is used as
6600
the database name: for example, in 'mysql/data/test'
6601
the database name is 'test' */
6605
string schema_path(identifier.getPath());
6606
Session* session = current_session;
6608
/* Get the transaction associated with the current session, or create one
6609
if not yet created */
6611
assert(this == innodb_engine_ptr);
6613
/* In the Windows plugin, session = current_session is always NULL */
6615
trx_t* parent_trx = check_trx_exists(session);
6617
/* In case Drizzle calls this in the middle of a SELECT
6618
query, release possible adaptive hash latch to avoid
6619
deadlocks of threads */
6621
trx_search_latch_release_if_reserved(parent_trx);
6624
schema_path.append("/");
6625
trx = innobase_trx_allocate(session);
6626
error = row_drop_database_for_mysql(schema_path.c_str(), trx);
6628
/* Flush the log to reduce probability that the .frm files and
6629
the InnoDB data dictionary get out-of-sync if the user runs
6630
with innodb_flush_log_at_trx_commit = 0 */
6632
log_buffer_flush_to_disk();
6634
/* Tell the InnoDB server that there might be work for
6637
srv_active_wake_master_thread();
6639
innobase_commit_low(trx);
6640
trx_free_for_mysql(trx);
6642
return false; // We are just a listener since we lack control over DDL, so we give no positive acknowledgement.
6645
void InnobaseEngine::dropTemporarySchema()
6647
SchemaIdentifier schema_identifier(GLOBAL_TEMPORARY_EXT);
6649
string schema_path(GLOBAL_TEMPORARY_EXT);
6651
schema_path.append("/");
6653
trx = trx_allocate_for_mysql();
6655
trx->mysql_thd = NULL;
6657
trx->check_foreigns = false;
6658
trx->check_unique_secondary = false;
6660
(void)row_drop_database_for_mysql(schema_path.c_str(), trx);
6662
/* Flush the log to reduce probability that the .frm files and
6663
the InnoDB data dictionary get out-of-sync if the user runs
6664
with innodb_flush_log_at_trx_commit = 0 */
6666
log_buffer_flush_to_disk();
6668
/* Tell the InnoDB server that there might be work for
6671
srv_active_wake_master_thread();
6673
innobase_commit_low(trx);
6674
trx_free_for_mysql(trx);
6024
char* path) /*!< in: database path; inside InnoDB the name
6025
of the last directory in the path is used as
6026
the database name: for example, in 'mysql/data/test'
6027
the database name is 'test' */
6034
Session* session = current_session;
6036
/* Get the transaction associated with the current session, or create one
6037
if not yet created */
6039
assert(this == innodb_engine_ptr);
6041
/* In the Windows plugin, session = current_session is always NULL */
6043
trx_t* parent_trx = check_trx_exists(session);
6045
/* In case Drizzle calls this in the middle of a SELECT
6046
query, release possible adaptive hash latch to avoid
6047
deadlocks of threads */
6049
trx_search_latch_release_if_reserved(parent_trx);
6052
ptr = strchr(path, '\0') - 2;
6054
while (ptr >= path && *ptr != '\\' && *ptr != '/') {
6060
namebuf = (char*) malloc((uint) len + 2);
6062
memcpy(namebuf, ptr, len);
6064
namebuf[len + 1] = '\0';
6066
innobase_casedn_str(namebuf);
6068
#if defined __WIN__ && !defined MYSQL_SERVER
6069
/* In the Windows plugin, thd = current_thd is always NULL */
6070
trx = trx_allocate_for_mysql();
6071
trx->mysql_thd = NULL;
6072
trx->mysql_query_str = NULL;
6074
trx = innobase_trx_allocate(session);
6076
error = row_drop_database_for_mysql(namebuf, trx);
6079
/* Flush the log to reduce probability that the .frm files and
6080
the InnoDB data dictionary get out-of-sync if the user runs
6081
with innodb_flush_log_at_trx_commit = 0 */
6083
log_buffer_flush_to_disk();
6085
/* Tell the InnoDB server that there might be work for
6088
srv_active_wake_master_thread();
6090
innobase_commit_low(trx);
6091
trx_free_for_mysql(trx);
6676
6093
/*********************************************************************//**
6677
6094
Renames an InnoDB table.
6678
@return 0 or error code */
6095
@return 0 or error code */
6681
6098
innobase_rename_table(
6682
6099
/*==================*/
6683
trx_t* trx, /*!< in: transaction */
6684
const char* from, /*!< in: old name of the table */
6685
const char* to, /*!< in: new name of the table */
6686
ibool lock_and_commit)
6687
/*!< in: TRUE=lock data dictionary and commit */
6100
trx_t* trx, /*!< in: transaction */
6101
const char* from, /*!< in: old name of the table */
6102
const char* to, /*!< in: new name of the table */
6103
ibool lock_and_commit)
6104
/*!< in: TRUE=lock data dictionary and commit */
6690
char norm_to[FN_REFLEN];
6691
char norm_from[FN_REFLEN];
6693
srv_lower_case_table_names = TRUE;
6695
normalize_table_name(norm_to, to);
6696
normalize_table_name(norm_from, from);
6698
/* Serialize data dictionary operations with dictionary mutex:
6699
no deadlocks can occur then in these operations */
6701
if (lock_and_commit) {
6702
row_mysql_lock_data_dictionary(trx);
6705
error = row_rename_table_for_mysql(
6706
norm_from, norm_to, trx, lock_and_commit);
6708
if (error != DB_SUCCESS) {
6709
FILE* ef = dict_foreign_err_file;
6711
fputs("InnoDB: Renaming table ", ef);
6712
ut_print_name(ef, trx, TRUE, norm_from);
6714
ut_print_name(ef, trx, TRUE, norm_to);
6715
fputs(" failed!\n", ef);
6718
if (lock_and_commit) {
6719
row_mysql_unlock_data_dictionary(trx);
6721
/* Flush the log to reduce probability that the .frm
6722
files and the InnoDB data dictionary get out-of-sync
6723
if the user runs with innodb_flush_log_at_trx_commit = 0 */
6725
log_buffer_flush_to_disk();
6110
srv_lower_case_table_names = TRUE;
6112
// Magic number 64 arbitrary
6113
norm_to = (char*) malloc(strlen(to) + 64);
6114
norm_from = (char*) malloc(strlen(from) + 64);
6116
normalize_table_name(norm_to, to);
6117
normalize_table_name(norm_from, from);
6119
/* Serialize data dictionary operations with dictionary mutex:
6120
no deadlocks can occur then in these operations */
6122
if (lock_and_commit) {
6123
row_mysql_lock_data_dictionary(trx);
6126
error = row_rename_table_for_mysql(
6127
norm_from, norm_to, trx, lock_and_commit);
6129
if (error != DB_SUCCESS) {
6130
FILE* ef = dict_foreign_err_file;
6132
fputs("InnoDB: Renaming table ", ef);
6133
ut_print_name(ef, trx, TRUE, norm_from);
6135
ut_print_name(ef, trx, TRUE, norm_to);
6136
fputs(" failed!\n", ef);
6139
if (lock_and_commit) {
6140
row_mysql_unlock_data_dictionary(trx);
6142
/* Flush the log to reduce probability that the .frm
6143
files and the InnoDB data dictionary get out-of-sync
6144
if the user runs with innodb_flush_log_at_trx_commit = 0 */
6146
log_buffer_flush_to_disk();
6730
6154
/*********************************************************************//**
6731
6155
Renames an InnoDB table.
6732
@return 0 or error code */
6733
UNIV_INTERN int InnobaseEngine::doRenameTable(Session &session, const TableIdentifier &from, const TableIdentifier &to)
6156
@return 0 or error code */
6159
InnobaseEngine::doRenameTable(
6160
/*======================*/
6162
const char* from, /*!< in: old name of the table */
6163
const char* to) /*!< in: new name of the table */
6735
// A temp table alter table/rename is a shallow rename and only the
6736
// definition needs to be updated.
6737
if (to.getType() == message::Table::TEMPORARY && from.getType() == message::Table::TEMPORARY)
6739
session.getMessageCache().renameTableMessage(from, to);
6747
/* Get the transaction associated with the current session, or create one
6748
if not yet created */
6750
parent_trx = check_trx_exists(&session);
6752
/* In case MySQL calls this in the middle of a SELECT query, release
6753
possible adaptive hash latch to avoid deadlocks of threads */
6755
trx_search_latch_release_if_reserved(parent_trx);
6757
trx = innobase_trx_allocate(&session);
6759
error = innobase_rename_table(trx, from.getPath().c_str(), to.getPath().c_str(), TRUE);
6761
session.setXaId(trx->id);
6763
/* Tell the InnoDB server that there might be work for
6766
srv_active_wake_master_thread();
6768
innobase_commit_low(trx);
6769
trx_free_for_mysql(trx);
6771
/* Add a special case to handle the Duplicated Key error
6772
and return DB_ERROR instead.
6773
This is to avoid a possible SIGSEGV error from mysql error
6774
handling code. Currently, mysql handles the Duplicated Key
6775
error by re-entering the storage layer and getting dup key
6776
info by calling get_dup_key(). This operation requires a valid
6777
table handle ('row_prebuilt_t' structure) which could no
6778
longer be available in the error handling stage. The suggested
6779
solution is to report a 'table exists' error message (since
6780
the dup key error here is due to an existing table whose name
6781
is the one we are trying to rename to) and return the generic
6783
if (error == (int) DB_DUPLICATE_KEY) {
6784
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), to.getPath().c_str());
6788
error = convert_error_code_to_mysql(error, 0, NULL);
6792
// If this fails, we are in trouble
6793
plugin::StorageEngine::renameDefinitionFromPath(to, from);
6169
/* Get the transaction associated with the current session, or create one
6170
if not yet created */
6172
parent_trx = check_trx_exists(session);
6174
/* In case MySQL calls this in the middle of a SELECT query, release
6175
possible adaptive hash latch to avoid deadlocks of threads */
6177
trx_search_latch_release_if_reserved(parent_trx);
6179
trx = innobase_trx_allocate(session);
6181
error = innobase_rename_table(trx, from, to, TRUE);
6183
/* Tell the InnoDB server that there might be work for
6186
srv_active_wake_master_thread();
6188
innobase_commit_low(trx);
6189
trx_free_for_mysql(trx);
6191
error = convert_error_code_to_mysql(error, 0, NULL);
6799
6196
/*********************************************************************//**
6800
6197
Estimates the number of index records in a range.
6801
@return estimated number of rows */
6198
@return estimated number of rows */
6804
6201
ha_innobase::records_in_range(
6805
6202
/*==========================*/
6806
uint keynr, /*!< in: index number */
6807
key_range *min_key, /*!< in: start key value of the
6808
range, may also be 0 */
6809
key_range *max_key) /*!< in: range end key val, may
6203
uint keynr, /*!< in: index number */
6204
key_range *min_key, /*!< in: start key value of the
6205
range, may also be 0 */
6206
key_range *max_key) /*!< in: range end key val, may
6813
dict_index_t* index;
6814
unsigned char* key_val_buff2 = (unsigned char*) malloc(
6815
getTable()->getShare()->stored_rec_length
6816
+ getTable()->getShare()->max_key_length + 100);
6817
ulint buff2_len = getTable()->getShare()->stored_rec_length
6818
+ getTable()->getShare()->max_key_length + 100;
6819
dtuple_t* range_start;
6820
dtuple_t* range_end;
6826
ut_a(prebuilt->trx == session_to_trx(getTable()->in_use));
6828
prebuilt->trx->op_info = (char*)"estimating records in index range";
6830
/* In case MySQL calls this in the middle of a SELECT query, release
6831
possible adaptive hash latch to avoid deadlocks of threads */
6833
trx_search_latch_release_if_reserved(prebuilt->trx);
6835
active_index = keynr;
6837
key = &getTable()->key_info[active_index];
6839
index = innobase_get_index(keynr);
6841
/* There exists possibility of not being able to find requested
6842
index due to inconsistency between MySQL and InoDB dictionary info.
6843
Necessary message should have been printed in innobase_get_index() */
6844
if (UNIV_UNLIKELY(!index)) {
6845
n_rows = HA_POS_ERROR;
6849
if (UNIV_UNLIKELY(!row_merge_is_index_usable(prebuilt->trx, index))) {
6850
n_rows = HA_ERR_TABLE_DEF_CHANGED;
6854
heap = mem_heap_create(2 * (key->key_parts * sizeof(dfield_t)
6855
+ sizeof(dtuple_t)));
6857
range_start = dtuple_create(heap, key->key_parts);
6858
dict_index_copy_types(range_start, index, key->key_parts);
6860
range_end = dtuple_create(heap, key->key_parts);
6861
dict_index_copy_types(range_end, index, key->key_parts);
6863
row_sel_convert_mysql_key_to_innobase(
6864
range_start, (byte*) &key_val_buff[0],
6865
(ulint)upd_and_key_val_buff_len,
6867
(byte*) (min_key ? min_key->key :
6868
(const unsigned char*) 0),
6869
(ulint) (min_key ? min_key->length : 0),
6872
row_sel_convert_mysql_key_to_innobase(
6873
range_end, (byte*) key_val_buff2,
6875
(byte*) (max_key ? max_key->key :
6876
(const unsigned char*) 0),
6877
(ulint) (max_key ? max_key->length : 0),
6880
mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
6882
mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag :
6885
if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) {
6887
n_rows = btr_estimate_n_rows_in_range(index, range_start,
6892
n_rows = HA_POS_ERROR;
6895
mem_heap_free(heap);
6898
free(key_val_buff2);
6900
prebuilt->trx->op_info = (char*)"";
6902
/* The MySQL optimizer seems to believe an estimate of 0 rows is
6903
always accurate and may return the result 'Empty set' based on that.
6904
The accuracy is not guaranteed, and even if it were, for a locking
6905
read we should anyway perform the search to set the next-key lock.
6906
Add 1 to the value to make sure MySQL does not make the assumption! */
6912
return((ha_rows) n_rows);
6210
dict_index_t* index;
6211
unsigned char* key_val_buff2 = (unsigned char*) malloc(
6212
table->s->stored_rec_length
6213
+ table->s->max_key_length + 100);
6214
ulint buff2_len = table->s->stored_rec_length
6215
+ table->s->max_key_length + 100;
6216
dtuple_t* range_start;
6217
dtuple_t* range_end;
6223
ut_a(prebuilt->trx == session_to_trx(ha_session()));
6225
prebuilt->trx->op_info = (char*)"estimating records in index range";
6227
/* In case MySQL calls this in the middle of a SELECT query, release
6228
possible adaptive hash latch to avoid deadlocks of threads */
6230
trx_search_latch_release_if_reserved(prebuilt->trx);
6232
active_index = keynr;
6234
key = table->key_info + active_index;
6236
index = dict_table_get_index_on_name(prebuilt->table, key->name);
6238
/* MySQL knows about this index and so we must be able to find it.*/
6241
heap = mem_heap_create(2 * (key->key_parts * sizeof(dfield_t)
6242
+ sizeof(dtuple_t)));
6244
range_start = dtuple_create(heap, key->key_parts);
6245
dict_index_copy_types(range_start, index, key->key_parts);
6247
range_end = dtuple_create(heap, key->key_parts);
6248
dict_index_copy_types(range_end, index, key->key_parts);
6250
row_sel_convert_mysql_key_to_innobase(
6251
range_start, (byte*) key_val_buff,
6252
(ulint)upd_and_key_val_buff_len,
6254
(byte*) (min_key ? min_key->key :
6255
(const unsigned char*) 0),
6256
(ulint) (min_key ? min_key->length : 0),
6259
row_sel_convert_mysql_key_to_innobase(
6260
range_end, (byte*) key_val_buff2,
6262
(byte*) (max_key ? max_key->key :
6263
(const unsigned char*) 0),
6264
(ulint) (max_key ? max_key->length : 0),
6267
mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
6269
mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag :
6272
if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) {
6274
n_rows = btr_estimate_n_rows_in_range(index, range_start,
6279
n_rows = HA_POS_ERROR;
6282
mem_heap_free(heap);
6284
free(key_val_buff2);
6286
prebuilt->trx->op_info = (char*)"";
6288
/* The MySQL optimizer seems to believe an estimate of 0 rows is
6289
always accurate and may return the result 'Empty set' based on that.
6290
The accuracy is not guaranteed, and even if it were, for a locking
6291
read we should anyway perform the search to set the next-key lock.
6292
Add 1 to the value to make sure MySQL does not make the assumption! */
6298
return((ha_rows) n_rows);
6915
6301
/*********************************************************************//**
6916
6302
Gives an UPPER BOUND to the number of rows in a table. This is used in
6918
@return upper bound of rows */
6304
@return upper bound of rows */
6921
6307
ha_innobase::estimate_rows_upper_bound(void)
6922
6308
/*======================================*/
6924
dict_index_t* index;
6926
uint64_t local_data_file_length;
6928
/* We do not know if MySQL can call this function before calling
6929
external_lock(). To be safe, update the session of the current table
6932
update_session(getTable()->in_use);
6934
prebuilt->trx->op_info = (char*)
6935
"calculating upper bound for table rows";
6937
/* In case MySQL calls this in the middle of a SELECT query, release
6938
possible adaptive hash latch to avoid deadlocks of threads */
6940
trx_search_latch_release_if_reserved(prebuilt->trx);
6942
index = dict_table_get_first_index(prebuilt->table);
6944
ut_a(index->stat_n_leaf_pages > 0);
6946
local_data_file_length =
6947
((uint64_t) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE;
6950
/* Calculate a minimum length for a clustered index record and from
6951
that an upper bound for the number of rows. Since we only calculate
6952
new statistics in row0mysql.c when a table has grown by a threshold
6953
factor, we must add a safety factor 2 in front of the formula below. */
6955
estimate = 2 * local_data_file_length /
6956
dict_index_calc_min_rec_len(index);
6958
prebuilt->trx->op_info = (char*)"";
6960
return((ha_rows) estimate);
6310
dict_index_t* index;
6312
uint64_t local_data_file_length;
6314
/* We do not know if MySQL can call this function before calling
6315
external_lock(). To be safe, update the session of the current table
6318
update_session(ha_session());
6320
prebuilt->trx->op_info = (char*)
6321
"calculating upper bound for table rows";
6323
/* In case MySQL calls this in the middle of a SELECT query, release
6324
possible adaptive hash latch to avoid deadlocks of threads */
6326
trx_search_latch_release_if_reserved(prebuilt->trx);
6328
index = dict_table_get_first_index(prebuilt->table);
6330
ut_a(index->stat_n_leaf_pages > 0);
6332
local_data_file_length =
6333
((uint64_t) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE;
6336
/* Calculate a minimum length for a clustered index record and from
6337
that an upper bound for the number of rows. Since we only calculate
6338
new statistics in row0mysql.c when a table has grown by a threshold
6339
factor, we must add a safety factor 2 in front of the formula below. */
6341
estimate = 2 * local_data_file_length /
6342
dict_index_calc_min_rec_len(index);
6344
prebuilt->trx->op_info = (char*)"";
6346
return((ha_rows) estimate);
6963
6349
/*********************************************************************//**
6964
6350
How many seeks it will take to read through the table. This is to be
6965
6351
comparable to the number returned by records_in_range so that we can
6966
6352
decide if we should scan the table or use keys.
6967
@return estimated time measured in disk seeks */
6353
@return estimated time measured in disk seeks */
6970
6356
ha_innobase::scan_time()
6971
6357
/*====================*/
6973
/* Since MySQL seems to favor table scans too much over index
6974
searches, we pretend that a sequential read takes the same time
6975
as a random disk read, that is, we do not divide the following
6976
by 10, which would be physically realistic. */
6359
/* Since MySQL seems to favor table scans too much over index
6360
searches, we pretend that a sequential read takes the same time
6361
as a random disk read, that is, we do not divide the following
6362
by 10, which would be physically realistic. */
6978
return((double) (prebuilt->table->stat_clustered_index_size));
6364
return((double) (prebuilt->table->stat_clustered_index_size));
6981
6367
/******************************************************************//**
6982
6368
Calculate the time it takes to read a set of ranges through an index
6983
6369
This enables us to optimise reads for clustered indexes.
6984
@return estimated time measured in disk seeks */
6370
@return estimated time measured in disk seeks */
6987
6373
ha_innobase::read_time(
6988
6374
/*===================*/
6989
uint index, /*!< in: key number */
6990
uint ranges, /*!< in: how many ranges */
6991
ha_rows rows) /*!< in: estimated number of rows in the ranges */
6994
double time_for_scan;
6996
if (index != getTable()->getShare()->getPrimaryKey()) {
6998
return(Cursor::read_time(index, ranges, rows));
7003
return((double) rows);
7006
/* Assume that the read time is proportional to the scan time for all
7007
rows + at most one seek per range. */
7009
time_for_scan = scan_time();
7011
if ((total_rows = estimate_rows_upper_bound()) < rows) {
7013
return(time_for_scan);
7016
return(ranges + (double) rows / (double) total_rows * time_for_scan);
7019
/*********************************************************************//**
7020
Calculates the key number used inside MySQL for an Innobase index. We will
7021
first check the "index translation table" for a match of the index to get
7022
the index number. If there does not exist an "index translation table",
7023
or not able to find the index in the translation table, then we will fall back
7024
to the traditional way of looping through dict_index_t list to find a
7025
match. In this case, we have to take into account if we generated a
7026
default clustered index for the table
7027
@return the key number used inside MySQL */
7030
innobase_get_mysql_key_number_for_index(
7031
/*====================================*/
7032
INNOBASE_SHARE* share, /*!< in: share structure for index
7033
translation table. */
7034
const drizzled::Table* table, /*!< in: table in MySQL data
7036
dict_table_t* ib_table,/*!< in: table in Innodb data
7038
const dict_index_t* index) /*!< in: index */
7040
const dict_index_t* ind;
7048
/* If index does not belong to the table of share structure. Search
7049
index->table instead */
7050
if (index->table != ib_table) {
7052
ind = dict_table_get_first_index(index->table);
7054
while (index != ind) {
7055
ind = dict_table_get_next_index(ind);
7059
if (row_table_got_default_clust_index(index->table)) {
7067
/* If index does not belong to the table of share structure. Search
7068
index->table instead */
7069
if (index->table != ib_table) {
7071
ind = dict_table_get_first_index(index->table);
7073
while (index != ind) {
7074
ind = dict_table_get_next_index(ind);
7078
if (row_table_got_default_clust_index(index->table)) {
7086
/* If index translation table exists, we will first check
7087
the index through index translation table for a match. */
7088
if (share->idx_trans_tbl.index_mapping) {
7089
for (i = 0; i < share->idx_trans_tbl.index_count; i++) {
7090
if (share->idx_trans_tbl.index_mapping[i] == index) {
7095
/* Print an error message if we cannot find the index
7096
** in the "index translation table". */
7097
errmsg_printf(ERRMSG_LVL_ERROR,
7098
"Cannot find index %s in InnoDB index "
7099
"translation table.", index->name);
7102
/* If we do not have an "index translation table", or not able
7103
to find the index in the translation table, we'll directly find
7104
matching index in the dict_index_t list */
7105
for (i = 0; i < table->getShare()->keys; i++) {
7106
ind = dict_table_get_index_on_name(
7107
ib_table, table->key_info[i].name);
7114
errmsg_printf(ERRMSG_LVL_ERROR,
7115
"Cannot find matching index number for index %s "
7116
"in InnoDB index list.", index->name);
6375
uint index, /*!< in: key number */
6376
uint ranges, /*!< in: how many ranges */
6377
ha_rows rows) /*!< in: estimated number of rows in the ranges */
6380
double time_for_scan;
6382
if (index != table->s->primary_key) {
6384
return(Cursor::read_time(index, ranges, rows));
6389
return((double) rows);
6392
/* Assume that the read time is proportional to the scan time for all
6393
rows + at most one seek per range. */
6395
time_for_scan = scan_time();
6397
if ((total_rows = estimate_rows_upper_bound()) < rows) {
6399
return(time_for_scan);
6402
return(ranges + (double) rows / (double) total_rows * time_for_scan);
7120
6405
/*********************************************************************//**
7121
6406
Returns statistics information of the table to the MySQL interpreter,
7122
6407
in various fields of the handle object. */
7125
6410
ha_innobase::info(
7126
6411
/*==============*/
7127
uint flag) /*!< in: what information MySQL requests */
6412
uint flag) /*!< in: what information MySQL requests */
7129
dict_table_t* ib_table;
7130
dict_index_t* index;
7131
ha_rows rec_per_key;
7133
os_file_stat_t stat_info;
7135
/* If we are forcing recovery at a high level, we will suppress
7136
statistics calculation on tables, because that may crash the
7137
server if an index is badly corrupted. */
7139
/* We do not know if MySQL can call this function before calling
7140
external_lock(). To be safe, update the session of the current table
7143
update_session(getTable()->in_use);
7145
/* In case MySQL calls this in the middle of a SELECT query, release
7146
possible adaptive hash latch to avoid deadlocks of threads */
7148
prebuilt->trx->op_info = (char*)"returning various info to MySQL";
7150
trx_search_latch_release_if_reserved(prebuilt->trx);
7152
ib_table = prebuilt->table;
7154
if (flag & HA_STATUS_TIME) {
7155
/* In Analyze we call with this flag: update
7156
then statistics so that they are up-to-date */
7158
prebuilt->trx->op_info = "updating table statistics";
7160
dict_update_statistics(ib_table);
7162
prebuilt->trx->op_info = "returning various info to MySQL";
7164
fs::path get_status_path(getDataHomeCatalog());
7165
get_status_path /= ib_table->name;
7166
fs::change_extension(get_status_path, "dfe");
7168
/* Note that we do not know the access time of the table,
7169
nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
7171
if (os_file_get_status(get_status_path.file_string().c_str(), &stat_info)) {
7172
stats.create_time = (ulong) stat_info.ctime;
7176
if (flag & HA_STATUS_VARIABLE) {
7177
n_rows = ib_table->stat_n_rows;
7179
/* Because we do not protect stat_n_rows by any mutex in a
7180
delete, it is theoretically possible that the value can be
7181
smaller than zero! TODO: fix this race.
7183
The MySQL optimizer seems to assume in a left join that n_rows
7184
is an accurate estimate if it is zero. Of course, it is not,
7185
since we do not have any locks on the rows yet at this phase.
7186
Since SHOW TABLE STATUS seems to call this function with the
7187
HA_STATUS_TIME flag set, while the left join optimizer does not
7188
set that flag, we add one to a zero value if the flag is not
7189
set. That way SHOW TABLE STATUS will show the best estimate,
7190
while the optimizer never sees the table empty. */
7196
if (n_rows == 0 && !(flag & HA_STATUS_TIME)) {
7200
/* Fix bug#40386: Not flushing query cache after truncate.
7201
n_rows can not be 0 unless the table is empty, set to 1
7202
instead. The original problem of bug#29507 is actually
7203
fixed in the server code. */
7204
if (session_sql_command(user_session) == SQLCOM_TRUNCATE) {
7208
/* We need to reset the prebuilt value too, otherwise
7209
checks for values greater than the last value written
7210
to the table will fail and the autoinc counter will
7211
not be updated. This will force doInsertRecord() into
7212
attempting an update of the table's AUTOINC counter. */
7214
prebuilt->autoinc_last_value = 0;
7217
stats.records = (ha_rows)n_rows;
7219
stats.data_file_length = ((uint64_t)
7220
ib_table->stat_clustered_index_size)
7222
stats.index_file_length = ((uint64_t)
7223
ib_table->stat_sum_of_other_index_sizes)
7226
/* Since fsp_get_available_space_in_free_extents() is
7227
acquiring latches inside InnoDB, we do not call it if we
7228
are asked by MySQL to avoid locking. Another reason to
7229
avoid the call is that it uses quite a lot of CPU.
7231
if (flag & HA_STATUS_NO_LOCK) {
7232
/* We do not update delete_length if no
7233
locking is requested so the "old" value can
7234
remain. delete_length is initialized to 0 in
7235
the ha_statistics' constructor. */
7236
} else if (UNIV_UNLIKELY
7237
(srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE)) {
7238
/* Avoid accessing the tablespace if
7239
innodb_crash_recovery is set to a high value. */
7240
stats.delete_length = 0;
7242
/* lock the data dictionary to avoid races with
7243
ibd_file_missing and tablespace_discarded */
7244
row_mysql_lock_data_dictionary(prebuilt->trx);
7246
/* ib_table->space must be an existent tablespace */
7247
if (!ib_table->ibd_file_missing
7248
&& !ib_table->tablespace_discarded) {
7250
stats.delete_length =
7251
fsp_get_available_space_in_free_extents(
7252
ib_table->space) * 1024;
7257
session= getTable()->in_use;
7260
push_warning_printf(
7262
DRIZZLE_ERROR::WARN_LEVEL_WARN,
7264
"InnoDB: Trying to get the free "
7265
"space for table %s but its "
7266
"tablespace has been discarded or "
7267
"the .ibd file is missing. Setting "
7268
"the free space to zero.",
7271
stats.delete_length = 0;
7274
row_mysql_unlock_data_dictionary(prebuilt->trx);
7277
stats.check_time = 0;
7279
if (stats.records == 0) {
7280
stats.mean_rec_length = 0;
7282
stats.mean_rec_length = (ulong) (stats.data_file_length / stats.records);
7286
if (flag & HA_STATUS_CONST) {
7288
/* Verify the number of index in InnoDB and MySQL
7289
matches up. If prebuilt->clust_index_was_generated
7290
holds, InnoDB defines GEN_CLUST_INDEX internally */
7291
ulint num_innodb_index = UT_LIST_GET_LEN(ib_table->indexes) - prebuilt->clust_index_was_generated;
7293
if (getTable()->getShare()->keys != num_innodb_index) {
7294
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains %lu "
7295
"indexes inside InnoDB, which "
7296
"is different from the number of "
7297
"indexes %u defined in the MySQL ",
7298
ib_table->name, num_innodb_index,
7299
getTable()->getShare()->keys);
7302
for (i = 0; i < getTable()->getShare()->sizeKeys(); i++) {
7304
/* We could get index quickly through internal
7305
index mapping with the index translation table.
7306
The identity of index (match up index name with
7307
that of table->key_info[i]) is already verified in
7308
innobase_get_index(). */
7309
index = innobase_get_index(i);
7311
if (index == NULL) {
7312
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains fewer "
7313
"indexes inside InnoDB than "
7314
"are defined in the MySQL "
7315
".frm file. Have you mixed up "
7316
".frm files from different "
7317
"installations? See "
7319
"innodb-troubleshooting.html\n",
7324
for (j = 0; j < getTable()->key_info[i].key_parts; j++) {
7326
if (j + 1 > index->n_uniq) {
7327
errmsg_printf(ERRMSG_LVL_ERROR,
6414
dict_table_t* ib_table;
6415
dict_index_t* index;
6416
ha_rows rec_per_key;
6420
char path[FN_REFLEN];
6421
os_file_stat_t stat_info;
6423
/* If we are forcing recovery at a high level, we will suppress
6424
statistics calculation on tables, because that may crash the
6425
server if an index is badly corrupted. */
6427
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
6429
/* We return success (0) instead of HA_ERR_CRASHED,
6430
because we want MySQL to process this query and not
6431
stop, like it would do if it received the error code
6437
/* We do not know if MySQL can call this function before calling
6438
external_lock(). To be safe, update the session of the current table
6441
update_session(ha_session());
6443
/* In case MySQL calls this in the middle of a SELECT query, release
6444
possible adaptive hash latch to avoid deadlocks of threads */
6446
prebuilt->trx->op_info = (char*)"returning various info to MySQL";
6448
trx_search_latch_release_if_reserved(prebuilt->trx);
6450
ib_table = prebuilt->table;
6452
if (flag & HA_STATUS_TIME) {
6453
if (innobase_stats_on_metadata) {
6454
/* In sql_show we call with this flag: update
6455
then statistics so that they are up-to-date */
6457
prebuilt->trx->op_info = "updating table statistics";
6459
dict_update_statistics(ib_table);
6461
prebuilt->trx->op_info = "returning various info to MySQL";
6464
snprintf(path, sizeof(path), "%s/%s%s",
6465
drizzle_data_home, ib_table->name, ".dfe");
6467
internal::unpack_filename(path,path);
6469
/* Note that we do not know the access time of the table,
6470
nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
6472
if (os_file_get_status(path,&stat_info)) {
6473
stats.create_time = (ulong) stat_info.ctime;
6477
if (flag & HA_STATUS_VARIABLE) {
6478
n_rows = ib_table->stat_n_rows;
6480
/* Because we do not protect stat_n_rows by any mutex in a
6481
delete, it is theoretically possible that the value can be
6482
smaller than zero! TODO: fix this race.
6484
The MySQL optimizer seems to assume in a left join that n_rows
6485
is an accurate estimate if it is zero. Of course, it is not,
6486
since we do not have any locks on the rows yet at this phase.
6487
Since SHOW TABLE STATUS seems to call this function with the
6488
HA_STATUS_TIME flag set, while the left join optimizer does not
6489
set that flag, we add one to a zero value if the flag is not
6490
set. That way SHOW TABLE STATUS will show the best estimate,
6491
while the optimizer never sees the table empty. */
6497
if (n_rows == 0 && !(flag & HA_STATUS_TIME)) {
6501
/* Fix bug#40386: Not flushing query cache after truncate.
6502
n_rows can not be 0 unless the table is empty, set to 1
6503
instead. The original problem of bug#29507 is actually
6504
fixed in the server code. */
6505
if (session_sql_command(user_session) == SQLCOM_TRUNCATE) {
6509
/* We need to reset the prebuilt value too, otherwise
6510
checks for values greater than the last value written
6511
to the table will fail and the autoinc counter will
6512
not be updated. This will force write_row() into
6513
attempting an update of the table's AUTOINC counter. */
6515
prebuilt->autoinc_last_value = 0;
6518
stats.records = (ha_rows)n_rows;
6520
stats.data_file_length = ((uint64_t)
6521
ib_table->stat_clustered_index_size)
6523
stats.index_file_length = ((uint64_t)
6524
ib_table->stat_sum_of_other_index_sizes)
6527
/* Since fsp_get_available_space_in_free_extents() is
6528
acquiring latches inside InnoDB, we do not call it if we
6529
are asked by MySQL to avoid locking. Another reason to
6530
avoid the call is that it uses quite a lot of CPU.
6532
We do not update delete_length if no locking is requested
6533
so the "old" value can remain. delete_length is initialized
6534
to 0 in the ha_statistics' constructor. */
6535
if (!(flag & HA_STATUS_NO_LOCK)) {
6537
/* lock the data dictionary to avoid races with
6538
ibd_file_missing and tablespace_discarded */
6539
row_mysql_lock_data_dictionary(prebuilt->trx);
6541
/* ib_table->space must be an existent tablespace */
6542
if (!ib_table->ibd_file_missing
6543
&& !ib_table->tablespace_discarded) {
6545
stats.delete_length =
6546
fsp_get_available_space_in_free_extents(
6547
ib_table->space) * 1024;
6552
session = ha_session();
6554
push_warning_printf(
6556
DRIZZLE_ERROR::WARN_LEVEL_WARN,
6558
"InnoDB: Trying to get the free "
6559
"space for table %s but its "
6560
"tablespace has been discarded or "
6561
"the .ibd file is missing. Setting "
6562
"the free space to zero.",
6565
stats.delete_length = 0;
6568
row_mysql_unlock_data_dictionary(prebuilt->trx);
6571
stats.check_time = 0;
6573
if (stats.records == 0) {
6574
stats.mean_rec_length = 0;
6576
stats.mean_rec_length = (ulong) (stats.data_file_length / stats.records);
6580
if (flag & HA_STATUS_CONST) {
6581
index = dict_table_get_first_index(ib_table);
6583
if (prebuilt->clust_index_was_generated) {
6584
index = dict_table_get_next_index(index);
6587
for (i = 0; i < table->s->keys; i++) {
6588
if (index == NULL) {
6589
errmsg_printf(ERRMSG_LVL_ERROR, "Table %s contains fewer "
6590
"indexes inside InnoDB than "
6591
"are defined in the MySQL "
6592
".frm file. Have you mixed up "
6593
".frm files from different "
6594
"installations? See "
6596
"innodb-troubleshooting.html\n",
6601
for (j = 0; j < table->key_info[i].key_parts; j++) {
6603
if (j + 1 > index->n_uniq) {
6604
errmsg_printf(ERRMSG_LVL_ERROR,
7328
6605
"Index %s of %s has %lu columns unique inside InnoDB, but MySQL is asking "
7329
6606
"statistics for %lu columns. Have you mixed up .frm files from different "
7330
6607
"installations? "
7331
6608
"See " REFMAN "innodb-troubleshooting.html\n",
7335
index->n_uniq, j + 1);
7339
dict_index_stat_mutex_enter(index);
7341
if (index->stat_n_diff_key_vals[j + 1] == 0) {
7343
rec_per_key = stats.records;
7345
rec_per_key = (ha_rows)(stats.records /
7346
index->stat_n_diff_key_vals[j + 1]);
7349
dict_index_stat_mutex_exit(index);
7351
/* Since MySQL seems to favor table scans
7352
too much over index searches, we pretend
7353
index selectivity is 2 times better than
7356
rec_per_key = rec_per_key / 2;
7358
if (rec_per_key == 0) {
7362
getTable()->key_info[i].rec_per_key[j]=
7363
rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
7364
(ulong) rec_per_key;
7369
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
7373
if (flag & HA_STATUS_ERRKEY) {
7374
const dict_index_t* err_index;
7376
ut_a(prebuilt->trx);
7377
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
7379
err_index = trx_get_error_info(prebuilt->trx);
7382
errkey = (unsigned int)
7383
innobase_get_mysql_key_number_for_index(share, getTable(), ib_table,
7386
errkey = (unsigned int) prebuilt->trx->error_key_num;
7390
if ((flag & HA_STATUS_AUTO) && getTable()->found_next_number_field) {
7391
stats.auto_increment_value = innobase_peek_autoinc();
7395
prebuilt->trx->op_info = (char*)"";
6612
index->n_uniq, j + 1);
6616
if (index->stat_n_diff_key_vals[j + 1] == 0) {
6618
rec_per_key = stats.records;
6620
rec_per_key = (ha_rows)(stats.records /
6621
index->stat_n_diff_key_vals[j + 1]);
6624
/* Since MySQL seems to favor table scans
6625
too much over index searches, we pretend
6626
index selectivity is 2 times better than
6629
rec_per_key = rec_per_key / 2;
6631
if (rec_per_key == 0) {
6635
table->key_info[i].rec_per_key[j]=
6636
rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
6637
(ulong) rec_per_key;
6640
index = dict_table_get_next_index(index);
6644
if (flag & HA_STATUS_ERRKEY) {
6645
const dict_index_t* err_index;
6647
ut_a(prebuilt->trx);
6648
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6650
err_index = trx_get_error_info(prebuilt->trx);
6653
errkey = (unsigned int)
6654
row_get_mysql_key_number_for_index(err_index);
6656
errkey = (unsigned int) prebuilt->trx->error_key_num;
6660
if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) {
6661
stats.auto_increment_value = innobase_peek_autoinc();
6664
prebuilt->trx->op_info = (char*)"";
7400
6669
/**********************************************************************//**
7401
6670
Updates index cardinalities of the table, based on 8 random dives into
7402
6671
each index tree. This does NOT calculate exact statistics on the table.
7403
@return returns always 0 (success) */
6672
@return returns always 0 (success) */
7406
6675
ha_innobase::analyze(
7407
6676
/*=================*/
7408
Session*) /*!< in: connection thread handle */
6677
Session*) /*!< in: connection thread handle */
7410
/* Simply call ::info() with all the flags */
7411
info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
6679
/* Simply call ::info() with all the flags */
6680
info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
7416
6685
/*******************************************************************//**
7417
6686
Tries to check that an InnoDB table is not corrupted. If corruption is
7418
6687
noticed, prints to stderr information about it. In case of corruption
7419
6688
may also assert a failure and crash the server.
7420
@return HA_ADMIN_CORRUPT or HA_ADMIN_OK */
6689
@return HA_ADMIN_CORRUPT or HA_ADMIN_OK */
7423
6692
ha_innobase::check(
7424
6693
/*===============*/
7425
Session* session) /*!< in: user thread handle */
6694
Session* session) /*!< in: user thread handle */
7427
dict_index_t* index;
7429
ulint n_rows_in_table = ULINT_UNDEFINED;
7431
ulint old_isolation_level;
7433
assert(session == getTable()->in_use);
7434
ut_a(prebuilt->trx);
7435
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
7436
ut_a(prebuilt->trx == session_to_trx(session));
7438
if (prebuilt->mysql_template == NULL) {
7439
/* Build the template; we will use a dummy template
7440
in index scans done in checking */
7442
build_template(prebuilt, NULL, getTable(), ROW_MYSQL_WHOLE_ROW);
7445
if (prebuilt->table->ibd_file_missing) {
7446
errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: Error:\n"
7447
"InnoDB: MySQL is trying to use a table handle"
7448
" but the .ibd file for\n"
7449
"InnoDB: table %s does not exist.\n"
7450
"InnoDB: Have you deleted the .ibd file"
7451
" from the database directory under\n"
7452
"InnoDB: the MySQL datadir, or have you"
7453
" used DISCARD TABLESPACE?\n"
7454
"InnoDB: Please refer to\n"
7455
"InnoDB: " REFMAN "innodb-troubleshooting.html\n"
7456
"InnoDB: how you can resolve the problem.\n",
7457
prebuilt->table->name);
7458
return(HA_ADMIN_CORRUPT);
7461
prebuilt->trx->op_info = "checking table";
7463
old_isolation_level = prebuilt->trx->isolation_level;
7465
/* We must run the index record counts at an isolation level
7466
>= READ COMMITTED, because a dirty read can see a wrong number
7467
of records in some index; to play safe, we use always
7468
REPEATABLE READ here */
7470
prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
7472
/* Enlarge the fatal lock wait timeout during CHECK TABLE. */
7473
mutex_enter(&kernel_mutex);
7474
srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
7475
mutex_exit(&kernel_mutex);
7477
for (index = dict_table_get_first_index(prebuilt->table);
7479
index = dict_table_get_next_index(index)) {
7481
fputs("Validating index ", stderr);
7482
ut_print_name(stderr, trx, FALSE, index->name);
7486
if (!btr_validate_index(index, prebuilt->trx)) {
7488
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7490
"InnoDB: The B-tree of"
7491
" index '%-.200s' is corrupted.",
7496
/* Instead of invoking change_active_index(), set up
7497
a dummy template for non-locking reads, disabling
7498
access to the clustered index. */
7499
prebuilt->index = index;
7501
prebuilt->index_usable = row_merge_is_index_usable(
7502
prebuilt->trx, prebuilt->index);
7504
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
7505
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7506
HA_ERR_TABLE_DEF_CHANGED,
7507
"InnoDB: Insufficient history for"
7513
prebuilt->sql_stat_start = TRUE;
7514
prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE;
7515
prebuilt->n_template = 0;
7516
prebuilt->need_to_access_clustered = FALSE;
7518
dtuple_set_n_fields(prebuilt->search_tuple, 0);
7520
prebuilt->select_lock_type = LOCK_NONE;
7522
if (!row_check_index_for_mysql(prebuilt, index, &n_rows)) {
7523
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7525
"InnoDB: The B-tree of"
7526
" index '%-.200s' is corrupted.",
7531
if (user_session->getKilled()) {
7536
fprintf(stderr, "%lu entries in index %s\n", n_rows,
7540
if (index == dict_table_get_first_index(prebuilt->table)) {
7541
n_rows_in_table = n_rows;
7542
} else if (n_rows != n_rows_in_table) {
7543
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7545
"InnoDB: Index '%-.200s'"
7546
" contains %lu entries,"
7550
(ulong) n_rows_in_table);
7555
/* Restore the original isolation level */
7556
prebuilt->trx->isolation_level = old_isolation_level;
7558
/* We validate also the whole adaptive hash index for all tables
7559
at every CHECK TABLE */
7561
if (!btr_search_validate()) {
7562
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
7564
"InnoDB: The adaptive hash index is corrupted.");
7568
/* Restore the fatal lock wait timeout after CHECK TABLE. */
7569
mutex_enter(&kernel_mutex);
7570
srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
7571
mutex_exit(&kernel_mutex);
7573
prebuilt->trx->op_info = "";
7574
if (user_session->getKilled()) {
7575
my_error(ER_QUERY_INTERRUPTED, MYF(0));
7578
return(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT);
6698
assert(session == ha_session());
6699
ut_a(prebuilt->trx);
6700
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
6701
ut_a(prebuilt->trx == session_to_trx(session));
6703
if (prebuilt->mysql_template == NULL) {
6704
/* Build the template; we will use a dummy template
6705
in index scans done in checking */
6707
build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
6710
ret = row_check_table_for_mysql(prebuilt);
6712
if (ret == DB_SUCCESS) {
6713
return(HA_ADMIN_OK);
6716
return(HA_ADMIN_CORRUPT);
7581
6719
/*************************************************************//**
7582
6720
Adds information about free space in the InnoDB tablespace to a table comment
7583
6721
which is printed out when a user calls SHOW TABLE STATUS. Adds also info on
7585
@return table comment + InnoDB free space + info on foreign keys */
6723
@return table comment + InnoDB free space + info on foreign keys */
7588
6726
ha_innobase::update_table_comment(
7589
6727
/*==============================*/
7590
const char* comment)/*!< in: table comment defined by user */
6728
const char* comment)/*!< in: table comment defined by user */
7592
uint length = (uint) strlen(comment);
7596
/* We do not know if MySQL can call this function before calling
7597
external_lock(). To be safe, update the session of the current table
7600
if (length > 64000 - 3) {
7601
return((char*)comment); /* string too long */
7604
update_session(getTable()->in_use);
7606
prebuilt->trx->op_info = (char*)"returning table comment";
7608
/* In case MySQL calls this in the middle of a SELECT query, release
7609
possible adaptive hash latch to avoid deadlocks of threads */
7611
trx_search_latch_release_if_reserved(prebuilt->trx);
7614
/* output the data to a temporary file */
7616
mutex_enter(&srv_dict_tmpfile_mutex);
7617
rewind(srv_dict_tmpfile);
7619
fprintf(srv_dict_tmpfile, "InnoDB free: %llu kB",
7620
fsp_get_available_space_in_free_extents(
7621
prebuilt->table->space));
7623
dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile,
7624
prebuilt->trx, prebuilt->table);
7625
flen = ftell(srv_dict_tmpfile);
7628
} else if (length + flen + 3 > 64000) {
7629
flen = 64000 - 3 - length;
7632
/* allocate buffer for the full string, and
7633
read the contents of the temporary file */
7635
str = (char*) malloc(length + flen + 3);
7638
char* pos = str + length;
7640
memcpy(str, comment, length);
7644
rewind(srv_dict_tmpfile);
7645
flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile);
7649
mutex_exit(&srv_dict_tmpfile_mutex);
7651
prebuilt->trx->op_info = (char*)"";
7653
return(str ? str : (char*) comment);
6730
uint length = (uint) strlen(comment);
6734
/* We do not know if MySQL can call this function before calling
6735
external_lock(). To be safe, update the session of the current table
6738
if (length > 64000 - 3) {
6739
return((char*)comment); /* string too long */
6742
update_session(ha_session());
6744
prebuilt->trx->op_info = (char*)"returning table comment";
6746
/* In case MySQL calls this in the middle of a SELECT query, release
6747
possible adaptive hash latch to avoid deadlocks of threads */
6749
trx_search_latch_release_if_reserved(prebuilt->trx);
6752
/* output the data to a temporary file */
6754
mutex_enter(&srv_dict_tmpfile_mutex);
6755
rewind(srv_dict_tmpfile);
6757
fprintf(srv_dict_tmpfile, "InnoDB free: %llu kB",
6758
fsp_get_available_space_in_free_extents(
6759
prebuilt->table->space));
6761
dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile,
6762
prebuilt->trx, prebuilt->table);
6763
flen = ftell(srv_dict_tmpfile);
6766
} else if (length + flen + 3 > 64000) {
6767
flen = 64000 - 3 - length;
6770
/* allocate buffer for the full string, and
6771
read the contents of the temporary file */
6773
str = (char*) malloc(length + flen + 3);
6776
char* pos = str + length;
6778
memcpy(str, comment, length);
6782
rewind(srv_dict_tmpfile);
6783
flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile);
6787
mutex_exit(&srv_dict_tmpfile_mutex);
6789
prebuilt->trx->op_info = (char*)"";
6791
return(str ? str : (char*) comment);
7656
6794
/*******************************************************************//**
7901
7032
ha_innobase::free_foreign_key_create_info(
7902
7033
/*======================================*/
7903
char* str) /*!< in, own: create info string to free */
7034
char* str) /*!< in, own: create info string to free */
7910
7041
/*******************************************************************//**
7911
7042
Tells something additional to the Cursor about how to do things.
7912
@return 0 or error number */
7043
@return 0 or error number */
7915
7046
ha_innobase::extra(
7916
7047
/*===============*/
7917
enum ha_extra_function operation)
7918
/*!< in: HA_EXTRA_FLUSH or some other flag */
7048
enum ha_extra_function operation)
7049
/*!< in: HA_EXTRA_FLUSH or some other flag */
7920
/* Warning: since it is not sure that MySQL calls external_lock
7921
before calling this function, the trx field in prebuilt can be
7924
switch (operation) {
7925
case HA_EXTRA_FLUSH:
7926
if (prebuilt->blob_heap) {
7927
row_mysql_prebuilt_free_blob_heap(prebuilt);
7930
case HA_EXTRA_RESET_STATE:
7931
reset_template(prebuilt);
7933
case HA_EXTRA_NO_KEYREAD:
7934
prebuilt->read_just_key = 0;
7936
case HA_EXTRA_KEYREAD:
7937
prebuilt->read_just_key = 1;
7939
case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
7940
prebuilt->keep_other_fields_on_keyread = 1;
7943
/* IMPORTANT: prebuilt->trx can be obsolete in
7944
this method, because it is not sure that MySQL
7945
calls external_lock before this method with the
7946
parameters below. We must not invoke update_session()
7947
either, because the calling threads may change.
7948
CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
7949
case HA_EXTRA_IGNORE_DUP_KEY:
7950
session_to_trx(getTable()->in_use)->duplicates |= TRX_DUP_IGNORE;
7952
case HA_EXTRA_WRITE_CAN_REPLACE:
7953
session_to_trx(getTable()->in_use)->duplicates |= TRX_DUP_REPLACE;
7955
case HA_EXTRA_WRITE_CANNOT_REPLACE:
7956
session_to_trx(getTable()->in_use)->duplicates &= ~TRX_DUP_REPLACE;
7958
case HA_EXTRA_NO_IGNORE_DUP_KEY:
7959
session_to_trx(getTable()->in_use)->duplicates &=
7960
~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
7962
default:/* Do nothing */
7051
/* Warning: since it is not sure that MySQL calls external_lock
7052
before calling this function, the trx field in prebuilt can be
7055
switch (operation) {
7056
case HA_EXTRA_FLUSH:
7057
if (prebuilt->blob_heap) {
7058
row_mysql_prebuilt_free_blob_heap(prebuilt);
7061
case HA_EXTRA_RESET_STATE:
7062
reset_template(prebuilt);
7064
case HA_EXTRA_NO_KEYREAD:
7065
prebuilt->read_just_key = 0;
7067
case HA_EXTRA_KEYREAD:
7068
prebuilt->read_just_key = 1;
7070
case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
7071
prebuilt->keep_other_fields_on_keyread = 1;
7074
/* IMPORTANT: prebuilt->trx can be obsolete in
7075
this method, because it is not sure that MySQL
7076
calls external_lock before this method with the
7077
parameters below. We must not invoke update_session()
7078
either, because the calling threads may change.
7079
CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
7080
case HA_EXTRA_IGNORE_DUP_KEY:
7081
session_to_trx(ha_session())->duplicates |= TRX_DUP_IGNORE;
7083
case HA_EXTRA_WRITE_CAN_REPLACE:
7084
session_to_trx(ha_session())->duplicates |= TRX_DUP_REPLACE;
7086
case HA_EXTRA_WRITE_CANNOT_REPLACE:
7087
session_to_trx(ha_session())->duplicates &= ~TRX_DUP_REPLACE;
7089
case HA_EXTRA_NO_IGNORE_DUP_KEY:
7090
session_to_trx(ha_session())->duplicates &=
7091
~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
7093
default:/* Do nothing */
7971
7102
ha_innobase::reset()
7973
if (prebuilt->blob_heap) {
7974
row_mysql_prebuilt_free_blob_heap(prebuilt);
7977
reset_template(prebuilt);
7979
/* TODO: This should really be reset in reset_template() but for now
7980
it's safer to do it explicitly here. */
7982
/* This is a statement level counter. */
7983
prebuilt->autoinc_last_value = 0;
7104
if (prebuilt->blob_heap) {
7105
row_mysql_prebuilt_free_blob_heap(prebuilt);
7108
reset_template(prebuilt);
7110
/* TODO: This should really be reset in reset_template() but for now
7111
it's safer to do it explicitly here. */
7113
/* This is a statement level counter. */
7114
prebuilt->autoinc_last_value = 0;
7119
/******************************************************************//**
7120
MySQL calls this function at the start of each SQL statement inside LOCK
7121
TABLES. Inside LOCK TABLES the ::external_lock method does not work to
7122
mark SQL statement borders. Note also a special case: if a temporary table
7123
is created inside LOCK TABLES, MySQL has not called external_lock() at all
7125
MySQL-5.0 also calls this before each statement in an execution of a stored
7126
procedure. To make the execution more deterministic for binlogging, MySQL-5.0
7127
locks all tables involved in a stored procedure with full explicit table
7128
locks (session_in_lock_tables(session) holds in store_lock()) before executing
7130
@return 0 or error code */
7133
ha_innobase::start_stmt(
7134
/*====================*/
7135
Session* session, /*!< in: handle to the user thread */
7136
thr_lock_type lock_type)
7140
update_session(session);
7142
trx = prebuilt->trx;
7144
/* Here we release the search latch and the InnoDB thread FIFO ticket
7145
if they were reserved. They should have been released already at the
7146
end of the previous statement, but because inside LOCK TABLES the
7147
lock count method does not work to mark the end of a SELECT statement,
7148
that may not be the case. We MUST release the search latch before an
7149
INSERT, for example. */
7151
innobase_release_stat_resources(trx);
7153
/* Reset the AUTOINC statement level counter for multi-row INSERTs. */
7154
trx->n_autoinc_rows = 0;
7156
prebuilt->sql_stat_start = TRUE;
7157
prebuilt->hint_need_to_fetch_extra_cols = 0;
7158
reset_template(prebuilt);
7160
if (!prebuilt->mysql_has_locked) {
7161
/* This handle is for a temporary table created inside
7162
this same LOCK TABLES; since MySQL does NOT call external_lock
7163
in this case, we must use x-row locks inside InnoDB to be
7164
prepared for an update of a row */
7166
prebuilt->select_lock_type = LOCK_X;
7168
if (trx->isolation_level != TRX_ISO_SERIALIZABLE
7169
&& session_sql_command(session) == SQLCOM_SELECT
7170
&& lock_type == TL_READ) {
7172
/* For other than temporary tables, we obtain
7173
no lock for consistent read (plain SELECT). */
7175
prebuilt->select_lock_type = LOCK_NONE;
7177
/* Not a consistent read: restore the
7178
select_lock_type value. The value of
7179
stored_select_lock_type was decided in:
7181
2) ::external_lock(),
7182
3) ::init_table_handle_for_HANDLER(), and
7185
prebuilt->select_lock_type =
7186
prebuilt->stored_select_lock_type;
7190
trx->detailed_error[0] = '\0';
7192
/* Set the MySQL flag to mark that there is an active transaction */
7193
if (trx->active_trans == 0) {
7195
innobase_register_trx_and_stmt(engine, session);
7196
trx->active_trans = 1;
7198
innobase_register_stmt(engine, session);
7988
7204
/******************************************************************//**
7989
7205
Maps a MySQL trx isolation level code to the InnoDB isolation level code
7990
@return InnoDB isolation level */
7206
@return InnoDB isolation level */
7993
7209
innobase_map_isolation_level(
7994
7210
/*=========================*/
7995
enum_tx_isolation iso) /*!< in: MySQL isolation level code */
7211
enum_tx_isolation iso) /*!< in: MySQL isolation level code */
7998
case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
7999
case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
8000
case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
8001
case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
8002
default: ut_a(0); return(0);
7214
case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
7215
case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
7216
case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
7217
case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
7218
default: ut_a(0); return(0);
8006
7222
/******************************************************************//**
8007
7223
As MySQL will execute an external lock for every new table it uses when it
8008
starts to process an SQL statement. We can use this function to store the pointer to
8009
the Session in the handle.
7224
starts to process an SQL statement (an exception is when MySQL calls
7225
start_stmt for the handle) we can use this function to store the pointer to
7226
the Session in the handle. We will also use this function to communicate
7227
to InnoDB that a new SQL statement has started and that we must store a
7228
savepoint to our transaction handle, so that we are able to roll back
7229
the SQL statement in case of an error.
8013
7233
ha_innobase::external_lock(
8014
7234
/*=======================*/
8015
Session* session, /*!< in: handle to the user thread */
8016
int lock_type) /*!< in: lock type */
8018
update_session(session);
8020
trx_t *trx= prebuilt->trx;
8022
prebuilt->sql_stat_start = TRUE;
8023
prebuilt->hint_need_to_fetch_extra_cols = 0;
8025
reset_template(prebuilt);
8027
if (lock_type == F_WRLCK) {
8029
/* If this is a SELECT, then it is in UPDATE TABLE ...
8030
or SELECT ... FOR UPDATE */
8031
prebuilt->select_lock_type = LOCK_X;
8032
prebuilt->stored_select_lock_type = LOCK_X;
8035
if (lock_type != F_UNLCK) {
8036
/* MySQL is setting a new table lock */
8038
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
8039
&& prebuilt->select_lock_type == LOCK_NONE
8040
&& session_test_options(session,
8041
OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
8043
/* To get serializable execution, we let InnoDB
8044
conceptually add 'LOCK IN SHARE MODE' to all SELECTs
8045
which otherwise would have been consistent reads. An
8046
exception is consistent reads in the AUTOCOMMIT=1 mode:
8047
we know that they are read-only transactions, and they
8048
can be serialized also if performed as consistent
8051
prebuilt->select_lock_type = LOCK_S;
8052
prebuilt->stored_select_lock_type = LOCK_S;
8055
/* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
8056
TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
8057
an InnoDB table lock if it is released immediately at the end
8058
of LOCK TABLES, and InnoDB's table locks in that case cause
8059
VERY easily deadlocks.
8061
We do not set InnoDB table locks if user has not explicitly
8062
requested a table lock. Note that session_in_lock_tables(session)
8063
can hold in some cases, e.g., at the start of a stored
8064
procedure call (SQLCOM_CALL). */
8066
if (prebuilt->select_lock_type != LOCK_NONE) {
8067
trx->mysql_n_tables_locked++;
8070
prebuilt->mysql_has_locked = TRUE;
8075
/* MySQL is releasing a table lock */
8076
prebuilt->mysql_has_locked = FALSE;
8077
trx->mysql_n_tables_locked= 0;
7235
Session* session, /*!< in: handle to the user thread */
7236
int lock_type) /*!< in: lock type */
7241
update_session(session);
7243
trx = prebuilt->trx;
7245
prebuilt->sql_stat_start = TRUE;
7246
prebuilt->hint_need_to_fetch_extra_cols = 0;
7248
reset_template(prebuilt);
7250
if (lock_type == F_WRLCK) {
7252
/* If this is a SELECT, then it is in UPDATE TABLE ...
7253
or SELECT ... FOR UPDATE */
7254
prebuilt->select_lock_type = LOCK_X;
7255
prebuilt->stored_select_lock_type = LOCK_X;
7258
if (lock_type != F_UNLCK) {
7259
/* MySQL is setting a new table lock */
7261
trx->detailed_error[0] = '\0';
7263
/* Set the MySQL flag to mark that there is an active
7265
if (trx->active_trans == 0) {
7267
innobase_register_trx_and_stmt(engine, session);
7268
trx->active_trans = 1;
7269
} else if (trx->n_mysql_tables_in_use == 0) {
7270
innobase_register_stmt(engine, session);
7273
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
7274
&& prebuilt->select_lock_type == LOCK_NONE
7275
&& session_test_options(session,
7276
OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
7278
/* To get serializable execution, we let InnoDB
7279
conceptually add 'LOCK IN SHARE MODE' to all SELECTs
7280
which otherwise would have been consistent reads. An
7281
exception is consistent reads in the AUTOCOMMIT=1 mode:
7282
we know that they are read-only transactions, and they
7283
can be serialized also if performed as consistent
7286
prebuilt->select_lock_type = LOCK_S;
7287
prebuilt->stored_select_lock_type = LOCK_S;
7290
/* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
7291
TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
7292
an InnoDB table lock if it is released immediately at the end
7293
of LOCK TABLES, and InnoDB's table locks in that case cause
7294
VERY easily deadlocks.
7296
We do not set InnoDB table locks if user has not explicitly
7297
requested a table lock. Note that session_in_lock_tables(session)
7298
can hold in some cases, e.g., at the start of a stored
7299
procedure call (SQLCOM_CALL). */
7301
if (prebuilt->select_lock_type != LOCK_NONE) {
7302
trx->mysql_n_tables_locked++;
7305
trx->n_mysql_tables_in_use++;
7306
prebuilt->mysql_has_locked = TRUE;
7311
/* MySQL is releasing a table lock */
7313
trx->n_mysql_tables_in_use--;
7314
prebuilt->mysql_has_locked = FALSE;
7316
/* Release a possible FIFO ticket and search latch. Since we
7317
may reserve the kernel mutex, we have to release the search
7318
system latch first to obey the latching order. */
7320
innobase_release_stat_resources(trx);
7322
/* If the MySQL lock count drops to zero we know that the current SQL
7323
statement has ended */
7325
if (trx->n_mysql_tables_in_use == 0) {
7327
trx->mysql_n_tables_locked = 0;
7328
prebuilt->used_in_HANDLER = FALSE;
7330
if (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
7331
if (trx->active_trans != 0) {
7332
engine->commit(session, TRUE);
7335
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
7336
&& trx->global_read_view) {
7338
/* At low transaction isolation levels we let
7339
each consistent read set its own snapshot */
7341
read_view_close_for_mysql(trx);
7349
/************************************************************************//**
7350
Here we export InnoDB status variables to MySQL. */
7353
innodb_export_status(void)
7354
/*======================*/
7356
if (innodb_inited) {
7357
srv_export_innodb_status();
8082
7361
/************************************************************************//**
8087
7366
innodb_show_status(
8088
7367
/*===============*/
8089
plugin::StorageEngine* engine, /*!< in: the innodb StorageEngine */
8090
Session* session,/*!< in: the MySQL query thread of the caller */
8091
stat_print_fn *stat_print)
7368
plugin::StorageEngine* engine, /*!< in: the innodb StorageEngine */
7369
Session* session,/*!< in: the MySQL query thread of the caller */
7370
stat_print_fn *stat_print)
8094
static const char truncated_msg[] = "... truncated...\n";
8095
const long MAX_STATUS_SIZE = 1048576;
8096
ulint trx_list_start = ULINT_UNDEFINED;
8097
ulint trx_list_end = ULINT_UNDEFINED;
8099
assert(engine == innodb_engine_ptr);
8101
trx = check_trx_exists(session);
8103
innobase_release_stat_resources(trx);
8105
/* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
8108
long flen, usable_len;
8111
mutex_enter(&srv_monitor_file_mutex);
8112
rewind(srv_monitor_file);
8113
srv_printf_innodb_monitor(srv_monitor_file, FALSE,
8114
&trx_list_start, &trx_list_end);
8115
flen = ftell(srv_monitor_file);
8116
os_file_set_eof(srv_monitor_file);
8122
if (flen > MAX_STATUS_SIZE) {
8123
usable_len = MAX_STATUS_SIZE;
8124
srv_truncated_status_writes++;
8129
/* allocate buffer for the string, and
8130
read the contents of the temporary file */
8132
if (!(str = (char*) malloc(usable_len + 1))) {
8133
mutex_exit(&srv_monitor_file_mutex);
8137
rewind(srv_monitor_file);
8138
if (flen < MAX_STATUS_SIZE) {
8139
/* Display the entire output. */
8140
flen = (long) fread(str, 1, flen, srv_monitor_file);
8141
} else if (trx_list_end < (ulint) flen
8142
&& trx_list_start < trx_list_end
8143
&& trx_list_start + (flen - trx_list_end)
8144
< MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
8145
/* Omit the beginning of the list of active transactions. */
8146
long len = (long) fread(str, 1, trx_list_start, srv_monitor_file);
8147
memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
8148
len += sizeof truncated_msg - 1;
8149
usable_len = (MAX_STATUS_SIZE - 1) - len;
8150
fseek(srv_monitor_file, flen - usable_len, SEEK_SET);
8151
len += (long) fread(str + len, 1, usable_len, srv_monitor_file);
8154
/* Omit the end of the output. */
8155
flen = (long) fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
8158
mutex_exit(&srv_monitor_file_mutex);
8160
stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
8161
STRING_WITH_LEN(""), str, flen);
7373
static const char truncated_msg[] = "... truncated...\n";
7374
const long MAX_STATUS_SIZE = 64000;
7375
ulint trx_list_start = ULINT_UNDEFINED;
7376
ulint trx_list_end = ULINT_UNDEFINED;
7378
assert(engine == innodb_engine_ptr);
7380
trx = check_trx_exists(session);
7382
innobase_release_stat_resources(trx);
7384
/* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
7387
long flen, usable_len;
7390
mutex_enter(&srv_monitor_file_mutex);
7391
rewind(srv_monitor_file);
7392
srv_printf_innodb_monitor(srv_monitor_file,
7393
&trx_list_start, &trx_list_end);
7394
flen = ftell(srv_monitor_file);
7395
os_file_set_eof(srv_monitor_file);
7401
if (flen > MAX_STATUS_SIZE) {
7402
usable_len = MAX_STATUS_SIZE;
7407
/* allocate buffer for the string, and
7408
read the contents of the temporary file */
7410
if (!(str = (char*) malloc(usable_len + 1))) {
7411
mutex_exit(&srv_monitor_file_mutex);
7415
rewind(srv_monitor_file);
7416
if (flen < MAX_STATUS_SIZE) {
7417
/* Display the entire output. */
7418
flen = (long) fread(str, 1, flen, srv_monitor_file);
7419
} else if (trx_list_end < (ulint) flen
7420
&& trx_list_start < trx_list_end
7421
&& trx_list_start + (flen - trx_list_end)
7422
< MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
7423
/* Omit the beginning of the list of active transactions. */
7424
long len = (long) fread(str, 1, trx_list_start, srv_monitor_file);
7425
memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
7426
len += sizeof truncated_msg - 1;
7427
usable_len = (MAX_STATUS_SIZE - 1) - len;
7428
fseek(srv_monitor_file, flen - usable_len, SEEK_SET);
7429
len += (long) fread(str + len, 1, usable_len, srv_monitor_file);
7432
/* Omit the end of the output. */
7433
flen = (long) fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
7436
mutex_exit(&srv_monitor_file_mutex);
7438
bool result = FALSE;
7440
if (stat_print(session, innobase_engine_name, strlen(innobase_engine_name),
7441
STRING_WITH_LEN(""), str, flen)) {
8168
7449
/************************************************************************//**
8169
Implements the SHOW MUTEX STATUS command.
8170
@return true on failure false on success*/
7450
Implements the SHOW MUTEX STATUS command. . */
8173
7453
innodb_mutex_show_status(
8174
7454
/*=====================*/
8175
plugin::StorageEngine* engine, /*!< in: the innodb StorageEngine */
8176
Session* session, /*!< in: the MySQL query thread of the
8178
stat_print_fn* stat_print) /*!< in: function for printing
7455
plugin::StorageEngine* engine, /*!< in: the innodb StorageEngine */
7456
Session* session, /*!< in: the MySQL query thread of the
7458
stat_print_fn* stat_print)
8181
char buf1[IO_SIZE], buf2[IO_SIZE];
8184
ulint block_mutex_oswait_count = 0;
8185
ulint block_lock_oswait_count = 0;
8186
mutex_t* block_mutex = NULL;
8187
rw_lock_t* block_lock = NULL;
7460
char buf1[IO_SIZE], buf2[IO_SIZE];
8188
7463
#ifdef UNIV_DEBUG
8189
ulint rw_lock_count= 0;
8190
ulint rw_lock_count_spin_loop= 0;
8191
ulint rw_lock_count_spin_rounds= 0;
8192
ulint rw_lock_count_os_wait= 0;
8193
ulint rw_lock_count_os_yield= 0;
8194
uint64_t rw_lock_wait_time= 0;
7464
ulint rw_lock_count= 0;
7465
ulint rw_lock_count_spin_loop= 0;
7466
ulint rw_lock_count_spin_rounds= 0;
7467
ulint rw_lock_count_os_wait= 0;
7468
ulint rw_lock_count_os_yield= 0;
7469
uint64_t rw_lock_wait_time= 0;
8195
7470
#endif /* UNIV_DEBUG */
8196
uint engine_name_len= strlen(innobase_engine_name), buf1len, buf2len;
8197
assert(engine == innodb_engine_ptr);
8199
mutex_enter(&mutex_list_mutex);
8201
for (mutex = UT_LIST_GET_FIRST(mutex_list); mutex != NULL;
8202
mutex = UT_LIST_GET_NEXT(list, mutex)) {
8203
if (mutex->count_os_wait == 0) {
8208
if (buf_pool_is_block_mutex(mutex)) {
8209
block_mutex = mutex;
8210
block_mutex_oswait_count += mutex->count_os_wait;
7471
uint engine_name_len= strlen(innobase_engine_name), buf1len, buf2len;
7472
assert(engine == innodb_engine_ptr);
7474
mutex_enter(&mutex_list_mutex);
7476
mutex = UT_LIST_GET_FIRST(mutex_list);
7478
while (mutex != NULL) {
7479
if (mutex->count_os_wait == 0
7480
|| buf_pool_is_block_mutex(mutex)) {
8213
7483
#ifdef UNIV_DEBUG
8214
if (mutex->mutex_type != 1) {
8215
if (mutex->count_using > 0) {
8216
buf1len= my_snprintf(buf1, sizeof(buf1),
8218
mutex->cmutex_name, mutex->cfile_name);
8219
buf2len= my_snprintf(buf2, sizeof(buf2),
8220
"count=%lu, spin_waits=%lu,"
8221
" spin_rounds=%lu, "
8222
"os_waits=%lu, os_yields=%lu,"
8223
" os_wait_times=%lu",
8225
mutex->count_spin_loop,
8226
mutex->count_spin_rounds,
8227
mutex->count_os_wait,
8228
mutex->count_os_yield,
8229
(ulong) (mutex->lspent_time/1000));
7484
if (mutex->mutex_type != 1) {
7485
if (mutex->count_using > 0) {
7486
buf1len= my_snprintf(buf1, sizeof(buf1),
7488
mutex->cmutex_name, mutex->cfile_name);
7489
buf2len= my_snprintf(buf2, sizeof(buf2),
7490
"count=%lu, spin_waits=%lu,"
7491
" spin_rounds=%lu, "
7492
"os_waits=%lu, os_yields=%lu,"
7493
" os_wait_times=%lu",
7495
mutex->count_spin_loop,
7496
mutex->count_spin_rounds,
7497
mutex->count_os_wait,
7498
mutex->count_os_yield,
7499
(ulong) (mutex->lspent_time/1000));
8231
if (stat_print(session, innobase_engine_name,
8232
engine_name_len, buf1, buf1len,
8234
mutex_exit(&mutex_list_mutex);
8239
rw_lock_count += mutex->count_using;
8240
rw_lock_count_spin_loop += mutex->count_spin_loop;
8241
rw_lock_count_spin_rounds += mutex->count_spin_rounds;
8242
rw_lock_count_os_wait += mutex->count_os_wait;
8243
rw_lock_count_os_yield += mutex->count_os_yield;
8244
rw_lock_wait_time += mutex->lspent_time;
7501
if (stat_print(session, innobase_engine_name,
7502
engine_name_len, buf1, buf1len,
7504
mutex_exit(&mutex_list_mutex);
7510
rw_lock_count += mutex->count_using;
7511
rw_lock_count_spin_loop += mutex->count_spin_loop;
7512
rw_lock_count_spin_rounds += mutex->count_spin_rounds;
7513
rw_lock_count_os_wait += mutex->count_os_wait;
7514
rw_lock_count_os_yield += mutex->count_os_yield;
7515
rw_lock_wait_time += mutex->lspent_time;
8246
7517
#else /* UNIV_DEBUG */
8247
buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
8248
mutex->cfile_name, (ulong) mutex->cline);
8249
buf2len= snprintf(buf2, sizeof(buf2), "os_waits=%lu",
8250
(ulong) mutex->count_os_wait);
7518
buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
7519
mutex->cfile_name, (ulong) mutex->cline);
7520
buf2len= snprintf(buf2, sizeof(buf2), "os_waits=%lu",
7521
mutex->count_os_wait);
8252
if (stat_print(session, innobase_engine_name,
8253
engine_name_len, buf1, buf1len,
8255
mutex_exit(&mutex_list_mutex);
7523
if (stat_print(session, innobase_engine_name,
7524
engine_name_len, buf1, buf1len,
7526
mutex_exit(&mutex_list_mutex);
8258
7529
#endif /* UNIV_DEBUG */
8262
buf1len = snprintf(buf1, sizeof buf1,
8264
block_mutex->cfile_name,
8265
(ulong) block_mutex->cline);
8266
buf2len = snprintf(buf2, sizeof buf2,
8268
(ulong) block_mutex_oswait_count);
8270
if (stat_print(session, innobase_engine_name,
8271
strlen(innobase_engine_name), buf1, buf1len,
8273
mutex_exit(&mutex_list_mutex);
8278
mutex_exit(&mutex_list_mutex);
8280
mutex_enter(&rw_lock_list_mutex);
8282
for (lock = UT_LIST_GET_FIRST(rw_lock_list); lock != NULL;
8283
lock = UT_LIST_GET_NEXT(list, lock)) {
8284
if (lock->count_os_wait == 0) {
8288
if (buf_pool_is_block_lock(lock)) {
8290
block_lock_oswait_count += lock->count_os_wait;
8294
buf1len = snprintf(buf1, sizeof buf1, "%s:%lu",
8295
lock->cfile_name, (ulong) lock->cline);
8296
buf2len = snprintf(buf2, sizeof buf2, "os_waits=%lu",
8297
(ulong) lock->count_os_wait);
8299
if (stat_print(session, innobase_engine_name,
8300
strlen(innobase_engine_name), buf1, buf1len,
8302
mutex_exit(&rw_lock_list_mutex);
8308
buf1len = snprintf(buf1, sizeof buf1,
8310
block_lock->cfile_name,
8311
(ulong) block_lock->cline);
8312
buf2len = snprintf(buf2, sizeof buf2,
8314
(ulong) block_lock_oswait_count);
8316
if (stat_print(session, innobase_engine_name,
8317
strlen(innobase_engine_name), buf1, buf1len,
8319
mutex_exit(&rw_lock_list_mutex);
8324
mutex_exit(&rw_lock_list_mutex);
7532
mutex = UT_LIST_GET_NEXT(list, mutex);
7535
mutex_exit(&mutex_list_mutex);
7537
mutex_enter(&rw_lock_list_mutex);
7539
lock = UT_LIST_GET_FIRST(rw_lock_list);
7541
while (lock != NULL) {
7542
if (lock->count_os_wait
7543
&& !buf_pool_is_block_lock(lock)) {
7544
buf1len= snprintf(buf1, sizeof(buf1), "%s:%lu",
7545
lock->cfile_name, (unsigned long) lock->cline);
7546
buf2len= snprintf(buf2, sizeof(buf2),
7547
"os_waits=%lu", lock->count_os_wait);
7549
if (stat_print(session, innobase_engine_name,
7550
engine_name_len, buf1, buf1len,
7552
mutex_exit(&rw_lock_list_mutex);
7556
lock = UT_LIST_GET_NEXT(list, lock);
7559
mutex_exit(&rw_lock_list_mutex);
8326
7561
#ifdef UNIV_DEBUG
8327
buf2len = snprintf(buf2, sizeof buf2,
8328
"count=%lu, spin_waits=%lu, spin_rounds=%lu, "
8329
"os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
8330
(ulong) rw_lock_count,
8331
(ulong) rw_lock_count_spin_loop,
8332
(ulong) rw_lock_count_spin_rounds,
8333
(ulong) rw_lock_count_os_wait,
8334
(ulong) rw_lock_count_os_yield,
8335
(ulong) (rw_lock_wait_time / 1000));
7562
buf2len= my_snprintf(buf2, sizeof(buf2),
7563
"count=%lu, spin_waits=%lu, spin_rounds=%lu, "
7564
"os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
7565
rw_lock_count, rw_lock_count_spin_loop,
7566
rw_lock_count_spin_rounds,
7567
rw_lock_count_os_wait, rw_lock_count_os_yield,
7568
(ulong) (rw_lock_wait_time/1000));
8337
if (stat_print(session, innobase_engine_name, engine_name_len,
8338
STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
7570
if (stat_print(session, innobase_engine_name, engine_name_len,
7571
STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) {
8341
7574
#endif /* UNIV_DEBUG */
8346
7579
bool InnobaseEngine::show_status(Session* session,
8347
7580
stat_print_fn* stat_print,
8348
7581
enum ha_stat_type stat_type)
8350
assert(this == innodb_engine_ptr);
7583
assert(this == innodb_engine_ptr);
8352
switch (stat_type) {
8353
case HA_ENGINE_STATUS:
8354
return innodb_show_status(this, session, stat_print);
8355
case HA_ENGINE_MUTEX:
8356
return innodb_mutex_show_status(this, session, stat_print);
7585
switch (stat_type) {
7586
case HA_ENGINE_STATUS:
7587
return innodb_show_status(this, session, stat_print);
7588
case HA_ENGINE_MUTEX:
7589
return innodb_mutex_show_status(this, session, stat_print);
8362
7595
/************************************************************************//**
8442
7673
SELECT the read lock is released early on the 'const' tables where we only
8443
7674
fetch one row. MySQL does not call this when it releases all locks at the
8444
7675
end of an SQL statement.
8445
@return pointer to the next element in the 'to' array */
7676
@return pointer to the next element in the 'to' array */
8447
7678
THR_LOCK_DATA**
8448
7679
ha_innobase::store_lock(
8449
7680
/*====================*/
8450
Session* session, /*!< in: user thread handle */
8451
THR_LOCK_DATA** to, /*!< in: pointer to an array
8452
of pointers to lock structs;
8453
pointer to the 'lock' field
8454
of current handle is stored
8455
next to this array */
8456
enum thr_lock_type lock_type) /*!< in: lock type to store in
8457
'lock'; this may also be
7681
Session* session, /*!< in: user thread handle */
7682
THR_LOCK_DATA** to, /*!< in: pointer to an array
7683
of pointers to lock structs;
7684
pointer to the 'lock' field
7685
of current handle is stored
7686
next to this array */
7687
enum thr_lock_type lock_type) /*!< in: lock type to store in
7688
'lock'; this may also be
8462
/* Note that trx in this function is NOT necessarily prebuilt->trx
8463
because we call update_session() later, in ::external_lock()! Failure to
8464
understand this caused a serious memory corruption bug in 5.1.11. */
8466
trx = check_trx_exists(session);
8468
assert(EQ_CURRENT_SESSION(session));
8469
const uint32_t sql_command = session_sql_command(session);
8471
if (sql_command == SQLCOM_DROP_TABLE) {
8473
/* MySQL calls this function in DROP Table though this table
8474
handle may belong to another session that is running a query.
8475
Let us in that case skip any changes to the prebuilt struct. */
8477
} else if (lock_type == TL_READ_WITH_SHARED_LOCKS
8478
|| lock_type == TL_READ_NO_INSERT
8479
|| (lock_type != TL_IGNORE
8480
&& sql_command != SQLCOM_SELECT)) {
8482
/* The OR cases above are in this order:
8483
1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
8484
are processing a stored procedure or function, or
8485
2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
8486
3) this is a SELECT ... IN SHARE MODE, or
8487
4) we are doing a complex SQL statement like
8488
INSERT INTO ... SELECT ... and the logical logging (MySQL
8489
binlog) requires the use of a locking read, or
8490
MySQL is doing LOCK TABLES ... READ.
8491
5) we let InnoDB do locking reads for all SQL statements that
8492
are not simple SELECTs; note that select_lock_type in this
8493
case may get strengthened in ::external_lock() to LOCK_X.
8494
Note that we MUST use a locking read in all data modifying
8495
SQL statements, because otherwise the execution would not be
8496
serializable, and also the results from the update could be
8497
unexpected if an obsolete consistent read view would be
8500
ulint isolation_level;
8502
isolation_level = trx->isolation_level;
8504
if ((srv_locks_unsafe_for_binlog
8505
|| isolation_level <= TRX_ISO_READ_COMMITTED)
8506
&& isolation_level != TRX_ISO_SERIALIZABLE
8507
&& (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
8508
&& (sql_command == SQLCOM_INSERT_SELECT
8509
|| sql_command == SQLCOM_REPLACE_SELECT
8510
|| sql_command == SQLCOM_UPDATE
8511
|| sql_command == SQLCOM_CREATE_TABLE
8512
|| sql_command == SQLCOM_SET_OPTION)) {
8514
/* If we either have innobase_locks_unsafe_for_binlog
8515
option set or this session is using READ COMMITTED
8516
isolation level and isolation level of the transaction
8517
is not set to serializable and MySQL is doing
8518
INSERT INTO...SELECT or REPLACE INTO...SELECT
8519
or UPDATE ... = (SELECT ...) or CREATE ...
8520
SELECT... or SET ... = (SELECT ...) without
8521
FOR UPDATE or IN SHARE MODE in select,
8522
then we use consistent read for select. */
8524
prebuilt->select_lock_type = LOCK_NONE;
8525
prebuilt->stored_select_lock_type = LOCK_NONE;
8526
} else if (sql_command == SQLCOM_CHECKSUM) {
8527
/* Use consistent read for checksum table */
8529
prebuilt->select_lock_type = LOCK_NONE;
8530
prebuilt->stored_select_lock_type = LOCK_NONE;
8532
prebuilt->select_lock_type = LOCK_S;
8533
prebuilt->stored_select_lock_type = LOCK_S;
8536
} else if (lock_type != TL_IGNORE) {
8538
/* We set possible LOCK_X value in external_lock, not yet
8539
here even if this would be SELECT ... FOR UPDATE */
8541
prebuilt->select_lock_type = LOCK_NONE;
8542
prebuilt->stored_select_lock_type = LOCK_NONE;
8545
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
8547
/* If we are not doing a LOCK TABLE, DISCARD/IMPORT
8548
TABLESPACE or TRUNCATE TABLE then allow multiple
8549
writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
8550
< TL_WRITE_CONCURRENT_INSERT.
8553
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
8554
&& lock_type <= TL_WRITE)
8555
&& !session_tablespace_op(session)
8556
&& sql_command != SQLCOM_TRUNCATE
8557
&& sql_command != SQLCOM_CREATE_TABLE) {
8559
lock_type = TL_WRITE_ALLOW_WRITE;
8562
/* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
8563
MySQL would use the lock TL_READ_NO_INSERT on t2, and that
8564
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
8565
to t2. Convert the lock to a normal read lock to allow
8566
concurrent inserts to t2.
8569
if (lock_type == TL_READ_NO_INSERT) {
8571
lock_type = TL_READ;
8574
lock.type = lock_type;
7693
/* Note that trx in this function is NOT necessarily prebuilt->trx
7694
because we call update_session() later, in ::external_lock()! Failure to
7695
understand this caused a serious memory corruption bug in 5.1.11. */
7697
trx = check_trx_exists(session);
7699
/* NOTE: MySQL can call this function with lock 'type' TL_IGNORE!
7700
Be careful to ignore TL_IGNORE if we are going to do something with
7701
only 'real' locks! */
7703
/* If no MySQL table is in use, we need to set the isolation level
7704
of the transaction. */
7706
if (lock_type != TL_IGNORE
7707
&& trx->n_mysql_tables_in_use == 0) {
7708
trx->isolation_level = innobase_map_isolation_level(
7709
(enum_tx_isolation) session_tx_isolation(session));
7711
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
7712
&& trx->global_read_view) {
7714
/* At low transaction isolation levels we let
7715
each consistent read set its own snapshot */
7717
read_view_close_for_mysql(trx);
7721
assert(EQ_CURRENT_SESSION(session));
7722
const uint32_t sql_command = session_sql_command(session);
7724
if (sql_command == SQLCOM_DROP_TABLE) {
7726
/* MySQL calls this function in DROP Table though this table
7727
handle may belong to another session that is running a query.
7728
Let us in that case skip any changes to the prebuilt struct. */
7730
} else if (lock_type == TL_READ_WITH_SHARED_LOCKS
7731
|| lock_type == TL_READ_NO_INSERT
7732
|| (lock_type != TL_IGNORE
7733
&& sql_command != SQLCOM_SELECT)) {
7735
/* The OR cases above are in this order:
7736
1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
7737
are processing a stored procedure or function, or
7738
2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
7739
3) this is a SELECT ... IN SHARE MODE, or
7740
4) we are doing a complex SQL statement like
7741
INSERT INTO ... SELECT ... and the logical logging (MySQL
7742
binlog) requires the use of a locking read, or
7743
MySQL is doing LOCK TABLES ... READ.
7744
5) we let InnoDB do locking reads for all SQL statements that
7745
are not simple SELECTs; note that select_lock_type in this
7746
case may get strengthened in ::external_lock() to LOCK_X.
7747
Note that we MUST use a locking read in all data modifying
7748
SQL statements, because otherwise the execution would not be
7749
serializable, and also the results from the update could be
7750
unexpected if an obsolete consistent read view would be
7753
ulint isolation_level;
7755
isolation_level = trx->isolation_level;
7757
if ((srv_locks_unsafe_for_binlog
7758
|| isolation_level == TRX_ISO_READ_COMMITTED)
7759
&& isolation_level != TRX_ISO_SERIALIZABLE
7760
&& (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
7761
&& (sql_command == SQLCOM_INSERT_SELECT
7762
|| sql_command == SQLCOM_UPDATE
7763
|| sql_command == SQLCOM_CREATE_TABLE)) {
7765
/* If we either have innobase_locks_unsafe_for_binlog
7766
option set or this session is using READ COMMITTED
7767
isolation level and isolation level of the transaction
7768
is not set to serializable and MySQL is doing
7769
INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
7770
CREATE ... SELECT... without FOR UPDATE or
7771
IN SHARE MODE in select, then we use consistent
7774
prebuilt->select_lock_type = LOCK_NONE;
7775
prebuilt->stored_select_lock_type = LOCK_NONE;
7776
} else if (sql_command == SQLCOM_CHECKSUM) {
7777
/* Use consistent read for checksum table */
7779
prebuilt->select_lock_type = LOCK_NONE;
7780
prebuilt->stored_select_lock_type = LOCK_NONE;
7782
prebuilt->select_lock_type = LOCK_S;
7783
prebuilt->stored_select_lock_type = LOCK_S;
7786
} else if (lock_type != TL_IGNORE) {
7788
/* We set possible LOCK_X value in external_lock, not yet
7789
here even if this would be SELECT ... FOR UPDATE */
7791
prebuilt->select_lock_type = LOCK_NONE;
7792
prebuilt->stored_select_lock_type = LOCK_NONE;
7795
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
7797
/* If we are not doing a LOCK TABLE, DISCARD/IMPORT
7798
TABLESPACE or TRUNCATE TABLE then allow multiple
7799
writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
7800
< TL_WRITE_CONCURRENT_INSERT.
7802
We especially allow multiple writers if MySQL is at the
7803
start of a stored procedure call (SQLCOM_CALL) or a
7804
stored function call (MySQL does have in_lock_tables
7807
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
7808
&& lock_type <= TL_WRITE)
7809
&& !session_tablespace_op(session)
7810
&& sql_command != SQLCOM_TRUNCATE
7811
&& sql_command != SQLCOM_CREATE_TABLE) {
7813
lock_type = TL_WRITE_ALLOW_WRITE;
7816
/* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
7817
MySQL would use the lock TL_READ_NO_INSERT on t2, and that
7818
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
7819
to t2. Convert the lock to a normal read lock to allow
7820
concurrent inserts to t2.
7822
We especially allow concurrent inserts if MySQL is at the
7823
start of a stored procedure call (SQLCOM_CALL)
7824
(MySQL does have session_in_lock_tables() TRUE there). */
7826
if (lock_type == TL_READ_NO_INSERT) {
7828
lock_type = TL_READ;
7831
lock.type = lock_type;
8582
7839
/*********************************************************************//**
8583
7840
Read the next autoinc value. Acquire the relevant locks before reading
8584
7841
the AUTOINC value. If SUCCESS then the table AUTOINC mutex will be locked
8585
7842
on return and all relevant locks acquired.
8586
@return DB_SUCCESS or error code */
7843
@return DB_SUCCESS or error code */
8589
7846
ha_innobase::innobase_get_autoinc(
8590
7847
/*==============================*/
8591
uint64_t* value) /*!< out: autoinc value */
7848
uint64_t* value) /*!< out: autoinc value */
8595
dict_table_autoinc_lock(prebuilt->table);
8596
prebuilt->autoinc_error= DB_SUCCESS;
8597
/* Determine the first value of the interval */
8598
*value = dict_table_autoinc_read(prebuilt->table);
8600
/* It should have been initialized during open. */
8602
prebuilt->autoinc_error = DB_UNSUPPORTED;
8603
dict_table_autoinc_unlock(prebuilt->table);
7852
prebuilt->autoinc_error = innobase_lock_autoinc();
7854
if (prebuilt->autoinc_error == DB_SUCCESS) {
7856
/* Determine the first value of the interval */
7857
*value = dict_table_autoinc_read(prebuilt->table);
7859
/* It should have been initialized during open. */
7863
return(prebuilt->autoinc_error);
8609
7866
/*******************************************************************//**
8610
This function reads the global auto-inc counter. It doesn't use the
7867
This function reads the global auto-inc counter. It doesn't use the
8611
7868
AUTOINC lock even if the lock mode is set to TRADITIONAL.
8612
@return the autoinc value */
7869
@return the autoinc value */
8615
7872
ha_innobase::innobase_peek_autoinc(void)
8616
7873
/*====================================*/
8619
dict_table_t* innodb_table;
8621
ut_a(prebuilt != NULL);
8622
ut_a(prebuilt->table != NULL);
8624
innodb_table = prebuilt->table;
8626
dict_table_autoinc_lock(innodb_table);
8628
auto_inc = dict_table_autoinc_read(innodb_table);
8630
if (auto_inc == 0) {
8631
ut_print_timestamp(stderr);
8632
fprintf(stderr, " InnoDB: AUTOINC next value generation "
8633
"is disabled for '%s'\n", innodb_table->name);
8636
dict_table_autoinc_unlock(innodb_table);
7876
dict_table_t* innodb_table;
7878
ut_a(prebuilt != NULL);
7879
ut_a(prebuilt->table != NULL);
7881
innodb_table = prebuilt->table;
7883
dict_table_autoinc_lock(innodb_table);
7885
auto_inc = dict_table_autoinc_read(innodb_table);
7889
dict_table_autoinc_unlock(innodb_table);
8641
7894
/*********************************************************************//**
8868
8122
characters for prefix indexes using a multibyte character set. The function
8869
8123
finds charset information and returns length of prefix_len characters in the
8870
8124
index field in bytes.
8871
@return number of bytes occupied by the first n characters */
8125
@return number of bytes occupied by the first n characters */
8872
8126
extern "C" UNIV_INTERN
8874
8128
innobase_get_at_most_n_mbchars(
8875
8129
/*===========================*/
8876
ulint charset_id, /*!< in: character set id */
8877
ulint prefix_len, /*!< in: prefix length in bytes of the index
8878
(this has to be divided by mbmaxlen to get the
8879
number of CHARACTERS n in the prefix) */
8880
ulint data_len, /*!< in: length of the string in bytes */
8881
const char* str); /*!< in: character string */
8130
ulint charset_id, /*!< in: character set id */
8131
ulint prefix_len, /*!< in: prefix length in bytes of the index
8132
(this has to be divided by mbmaxlen to get the
8133
number of CHARACTERS n in the prefix) */
8134
ulint data_len, /*!< in: length of the string in bytes */
8135
const char* str); /*!< in: character string */
8884
8138
innobase_get_at_most_n_mbchars(
8885
8139
/*===========================*/
8886
ulint charset_id, /*!< in: character set id */
8887
ulint prefix_len, /*!< in: prefix length in bytes of the index
8888
(this has to be divided by mbmaxlen to get the
8889
number of CHARACTERS n in the prefix) */
8890
ulint data_len, /*!< in: length of the string in bytes */
8891
const char* str) /*!< in: character string */
8893
ulint char_length; /*!< character length in bytes */
8894
ulint n_chars; /*!< number of characters in prefix */
8895
const CHARSET_INFO* charset; /*!< charset used in the field */
8897
charset = get_charset((uint) charset_id);
8900
ut_ad(charset->mbmaxlen);
8902
/* Calculate how many characters at most the prefix index contains */
8904
n_chars = prefix_len / charset->mbmaxlen;
8906
/* If the charset is multi-byte, then we must find the length of the
8907
first at most n chars in the string. If the string contains less
8908
characters than n, then we return the length to the end of the last
8911
if (charset->mbmaxlen > 1) {
8912
/* my_charpos() returns the byte length of the first n_chars
8913
characters, or a value bigger than the length of str, if
8914
there were not enough full characters in str.
8916
Why does the code below work:
8917
Suppose that we are looking for n UTF-8 characters.
8919
1) If the string is long enough, then the prefix contains at
8920
least n complete UTF-8 characters + maybe some extra
8921
characters + an incomplete UTF-8 character. No problem in
8922
this case. The function returns the pointer to the
8923
end of the nth character.
8925
2) If the string is not long enough, then the string contains
8926
the complete value of a column, that is, only complete UTF-8
8927
characters, and we can store in the column prefix index the
8930
char_length = my_charpos(charset, str,
8931
str + data_len, (int) n_chars);
8932
if (char_length > data_len) {
8933
char_length = data_len;
8936
if (data_len < prefix_len) {
8937
char_length = data_len;
8939
char_length = prefix_len;
8943
return(char_length);
8946
* We will also use this function to communicate
8947
* to InnoDB that a new SQL statement has started and that we must store a
8948
* savepoint to our transaction handle, so that we are able to roll back
8949
* the SQL statement in case of an error.
8952
InnobaseEngine::doStartStatement(
8953
Session *session) /*!< in: handle to the Drizzle session */
8956
* Create the InnoDB transaction structure
8959
trx_t *trx= check_trx_exists(session);
8961
/* "reset" the error message for the transaction */
8962
trx->detailed_error[0]= '\0';
8964
/* Set the isolation level of the transaction. */
8965
trx->isolation_level= innobase_map_isolation_level(session_tx_isolation(session));
8969
InnobaseEngine::doEndStatement(
8972
trx_t *trx= check_trx_exists(session);
8974
/* Release a possible FIFO ticket and search latch. Since we
8975
may reserve the kernel mutex, we have to release the search
8976
system latch first to obey the latching order. */
8978
innobase_release_stat_resources(trx);
8140
ulint charset_id, /*!< in: character set id */
8141
ulint prefix_len, /*!< in: prefix length in bytes of the index
8142
(this has to be divided by mbmaxlen to get the
8143
number of CHARACTERS n in the prefix) */
8144
ulint data_len, /*!< in: length of the string in bytes */
8145
const char* str) /*!< in: character string */
8147
ulint char_length; /*!< character length in bytes */
8148
ulint n_chars; /*!< number of characters in prefix */
8149
const CHARSET_INFO* charset; /*!< charset used in the field */
8151
charset = get_charset((uint) charset_id);
8154
ut_ad(charset->mbmaxlen);
8156
/* Calculate how many characters at most the prefix index contains */
8158
n_chars = prefix_len / charset->mbmaxlen;
8160
/* If the charset is multi-byte, then we must find the length of the
8161
first at most n chars in the string. If the string contains less
8162
characters than n, then we return the length to the end of the last
8165
if (charset->mbmaxlen > 1) {
8166
/* my_charpos() returns the byte length of the first n_chars
8167
characters, or a value bigger than the length of str, if
8168
there were not enough full characters in str.
8170
Why does the code below work:
8171
Suppose that we are looking for n UTF-8 characters.
8173
1) If the string is long enough, then the prefix contains at
8174
least n complete UTF-8 characters + maybe some extra
8175
characters + an incomplete UTF-8 character. No problem in
8176
this case. The function returns the pointer to the
8177
end of the nth character.
8179
2) If the string is not long enough, then the string contains
8180
the complete value of a column, that is, only complete UTF-8
8181
characters, and we can store in the column prefix index the
8184
char_length = my_charpos(charset, str,
8185
str + data_len, (int) n_chars);
8186
if (char_length > data_len) {
8187
char_length = data_len;
8190
if (data_len < prefix_len) {
8191
char_length = data_len;
8193
char_length = prefix_len;
8197
return(char_length);
8982
8200
/*******************************************************************//**
8983
8201
This function is used to prepare an X/Open XA distributed transaction.
8984
@return 0 or error number */
8202
@return 0 or error number */
8986
InnobaseEngine::doXaPrepare(
8204
InnobaseEngine::prepare(
8987
8205
/*================*/
8988
Session* session,/*!< in: handle to the MySQL thread of
8989
the user whose XA transaction should
8991
bool all) /*!< in: TRUE - commit transaction
8992
FALSE - the current SQL statement
8996
trx_t* trx = check_trx_exists(session);
8998
assert(this == innodb_engine_ptr);
9000
/* we use support_xa value as it was seen at transaction start
9001
time, not the current session variable value. Any possible changes
9002
to the session variable take effect only in the next transaction */
9003
if (!trx->support_xa) {
9008
session->get_xid(reinterpret_cast<DRIZZLE_XID*>(&trx->xid));
9010
/* Release a possible FIFO ticket and search latch. Since we will
9011
reserve the kernel mutex, we have to release the search system latch
9012
first to obey the latching order. */
9014
innobase_release_stat_resources(trx);
9017
|| (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
9019
/* We were instructed to prepare the whole transaction, or
9020
this is an SQL statement end and autocommit is on */
9022
ut_ad(trx->conc_state != TRX_NOT_STARTED);
9024
error = (int) trx_prepare_for_mysql(trx);
9026
/* We just mark the SQL statement ended and do not do a
9027
transaction prepare */
9029
/* If we had reserved the auto-inc lock for some
9030
table in this SQL statement we release it now */
9032
row_unlock_table_autoinc_for_mysql(trx);
9034
/* Store the current undo_no of the transaction so that we
9035
know where to roll back if we have to roll back the next
9038
trx_mark_sql_stat_end(trx);
9041
/* Tell the InnoDB server that there might be work for utility
9044
srv_active_wake_master_thread();
9049
uint64_t InnobaseEngine::doGetCurrentTransactionId(Session *session)
9051
trx_t *trx= session_to_trx(session);
9055
uint64_t InnobaseEngine::doGetNewTransactionId(Session *session)
9057
trx_t*& trx = session_to_trx(session);
9061
trx = innobase_trx_allocate(session);
9063
innobase_trx_init(session, trx);
9066
mutex_enter(&kernel_mutex);
9067
trx->id= trx_sys_get_new_trx_id();
9068
mutex_exit(&kernel_mutex);
9070
uint64_t transaction_id= trx->id;
9072
return transaction_id;
8206
Session* session,/*!< in: handle to the MySQL thread of
8207
the user whose XA transaction should
8209
bool all) /*!< in: TRUE - commit transaction
8210
FALSE - the current SQL statement
8214
trx_t* trx = check_trx_exists(session);
8216
assert(this == innodb_engine_ptr);
8218
/* we use support_xa value as it was seen at transaction start
8219
time, not the current session variable value. Any possible changes
8220
to the session variable take effect only in the next transaction */
8221
if (!trx->support_xa) {
8226
session_get_xid(session, reinterpret_cast<DRIZZLE_XID*>(&trx->xid));
8228
/* Release a possible FIFO ticket and search latch. Since we will
8229
reserve the kernel mutex, we have to release the search system latch
8230
first to obey the latching order. */
8232
innobase_release_stat_resources(trx);
8234
if (trx->active_trans == 0 && trx->conc_state != TRX_NOT_STARTED) {
8236
errmsg_printf(ERRMSG_LVL_ERROR,
8237
"trx->active_trans == 0, but trx->conc_state != "
8242
|| (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
8244
/* We were instructed to prepare the whole transaction, or
8245
this is an SQL statement end and autocommit is on */
8247
ut_ad(trx->active_trans);
8249
error = (int) trx_prepare_for_mysql(trx);
8251
/* We just mark the SQL statement ended and do not do a
8252
transaction prepare */
8254
/* If we had reserved the auto-inc lock for some
8255
table in this SQL statement we release it now */
8257
row_unlock_table_autoinc_for_mysql(trx);
8259
/* Store the current undo_no of the transaction so that we
8260
know where to roll back if we have to roll back the next
8263
trx_mark_sql_stat_end(trx);
8266
/* Tell the InnoDB server that there might be work for utility
8269
srv_active_wake_master_thread();
8271
if (all || !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
8274
/* For ibbackup to work the order of transactions in binlog
8275
and InnoDB must be the same. Consider the situation
8277
thread1> prepare; write to binlog; ...
8279
thread2> prepare; write to binlog; commit
8282
To ensure this will not happen we're taking the mutex on
8283
prepare, and releasing it on commit.
8285
Note: only do it for normal commits, done via ha_commit_trans.
8286
If 2pc protocol is executed by external transaction
8287
coordinator, it will be just a regular MySQL client
8288
executing XA PREPARE and XA COMMIT commands.
8289
In this case we cannot know how many minutes or hours
8290
will be between XA PREPARE and XA COMMIT, and we don't want
8291
to block for undefined period of time.
8293
pthread_mutex_lock(&prepare_commit_mutex);
8294
trx->active_trans = 2;
9075
8299
/*******************************************************************//**
9076
8300
This function is used to recover X/Open XA distributed transactions.
9077
@return number of prepared transactions stored in xid_list */
8301
@return number of prepared transactions stored in xid_list */
9079
InnobaseEngine::doXaRecover(
8303
InnobaseEngine::recover(
9080
8304
/*================*/
9081
::drizzled::XID* xid_list,/*!< in/out: prepared transactions */
9082
size_t len) /*!< in: number of slots in xid_list */
8305
::drizzled::XID* xid_list,/*!< in/out: prepared transactions */
8306
uint len) /*!< in: number of slots in xid_list */
9084
assert(this == innodb_engine_ptr);
9086
if (len == 0 || xid_list == NULL) {
9091
return(trx_recover_for_mysql((::XID *)xid_list, len));
8308
assert(this == innodb_engine_ptr);
8310
if (len == 0 || xid_list == NULL) {
8315
return(trx_recover_for_mysql((::XID *)xid_list, len));
9094
8318
/*******************************************************************//**
9095
8319
This function is used to commit one X/Open XA distributed transaction
9096
8320
which is in the prepared state
9097
@return 0 or error number */
8321
@return 0 or error number */
9099
InnobaseEngine::doXaCommitXid(
8323
InnobaseEngine::commit_by_xid(
9100
8324
/*===================*/
9101
::drizzled::XID* xid) /*!< in: X/Open XA transaction identification */
8325
::drizzled::XID* xid) /*!< in: X/Open XA transaction identification */
9105
assert(this == innodb_engine_ptr);
9107
trx = trx_get_trx_by_xid((::XID *)xid);
9110
innobase_commit_low(trx);
8329
assert(this == innodb_engine_ptr);
8331
trx = trx_get_trx_by_xid((::XID *)xid);
8334
innobase_commit_low(trx);
9118
8342
/*******************************************************************//**
9119
8343
This function is used to rollback one X/Open XA distributed transaction
9120
8344
which is in the prepared state
9121
@return 0 or error number */
8345
@return 0 or error number */
9123
InnobaseEngine::doXaRollbackXid(
8347
InnobaseEngine::rollback_by_xid(
9124
8348
/*=====================*/
9125
::drizzled::XID* xid) /*!< in: X/Open XA transaction
8349
::drizzled::XID* xid) /*!< in: X/Open XA transaction
9130
assert(this == innodb_engine_ptr);
9132
trx = trx_get_trx_by_xid((::XID *)xid);
9135
return(innobase_rollback_trx(trx));
8354
assert(this == innodb_engine_ptr);
8356
trx = trx_get_trx_by_xid((::XID *)xid);
8359
return(innobase_rollback_trx(trx));
9142
8366
/************************************************************//**
9143
8367
Validate the file format name and return its corresponding id.
9144
@return valid file format id */
8368
@return valid file format id */
9147
8371
innobase_file_format_name_lookup(
9148
8372
/*=============================*/
9149
const char* format_name) /*!< in: pointer to file format name */
9154
ut_a(format_name != NULL);
9156
/* The format name can contain the format id itself instead of
9157
the name and we check for that. */
9158
format_id = (uint) strtoul(format_name, &endp, 10);
9160
/* Check for valid parse. */
9161
if (*endp == '\0' && *format_name != '\0') {
9163
if (format_id <= DICT_TF_FORMAT_MAX) {
9169
for (format_id = 0; format_id <= DICT_TF_FORMAT_MAX;
9173
name = trx_sys_file_format_id_to_name(format_id);
9175
if (!innobase_strcasecmp(format_name, name)) {
9182
return(DICT_TF_FORMAT_MAX + 1);
8373
const char* format_name) /*!< in: pointer to file format name */
8378
ut_a(format_name != NULL);
8380
/* The format name can contain the format id itself instead of
8381
the name and we check for that. */
8382
format_id = (uint) strtoul(format_name, &endp, 10);
8384
/* Check for valid parse. */
8385
if (*endp == '\0' && *format_name != '\0') {
8387
if (format_id <= DICT_TF_FORMAT_MAX) {
8393
for (format_id = 0; format_id <= DICT_TF_FORMAT_MAX;
8397
name = trx_sys_file_format_id_to_name(format_id);
8399
if (!innobase_strcasecmp(format_name, name)) {
8406
return(DICT_TF_FORMAT_MAX + 1);
8409
/************************************************************//**
8410
Validate the file format check value, is it one of "on" or "off",
8411
as a side effect it sets the srv_check_file_format_at_startup variable.
8412
@return true if config value one of "on" or "off" */
8415
innobase_file_format_check_on_off(
8416
/*==============================*/
8417
const char* format_check) /*!< in: parameter value */
8421
if (!innobase_strcasecmp(format_check, "off")) {
8423
/* Set the value to disable checking. */
8424
srv_check_file_format_at_startup = DICT_TF_FORMAT_MAX + 1;
8426
} else if (!innobase_strcasecmp(format_check, "on")) {
8428
/* Set the value to the lowest supported format. */
8429
srv_check_file_format_at_startup = DICT_TF_FORMAT_51;
9185
8437
/************************************************************//**
9186
8438
Validate the file format check config parameters, as a side effect it
9187
sets the srv_max_file_format_at_startup variable.
9188
@return the format_id if valid config value, otherwise, return -1 */
8439
sets the srv_check_file_format_at_startup variable.
8440
@return true if valid config value */
9191
innobase_file_format_validate_and_set(
8443
innobase_file_format_check_validate(
9192
8444
/*================================*/
9193
const char* format_max) /*!< in: parameter value */
9197
format_id = innobase_file_format_name_lookup(format_max);
9199
if (format_id < DICT_TF_FORMAT_MAX + 1) {
9200
srv_max_file_format_at_startup = format_id;
9201
return((int) format_id);
9209
static void init_options(drizzled::module::option_context &context)
9211
context("disable-checksums",
9212
"Disable InnoDB checksums validation.");
9213
context("data-home-dir",
9214
po::value<string>(),
9215
"The common part for InnoDB table spaces.");
9216
context("disable-doublewrite",
9217
"Disable InnoDB doublewrite buffer.");
9218
context("io-capacity",
9219
po::value<io_capacity_constraint>(&innodb_io_capacity)->default_value(200),
9220
"Number of IOPs the server can do. Tunes the background IO rate");
9221
context("fast-shutdown",
9222
po::value<trinary_constraint>(&innobase_fast_shutdown)->default_value(1),
9223
"Speeds up the shutdown process of the InnoDB storage engine. Possible values are 0, 1 (faster) or 2 (fastest - crash-like).");
9224
context("purge-batch-size",
9225
po::value<purge_batch_constraint>(&innodb_purge_batch_size)->default_value(20),
9226
"Number of UNDO logs to purge in one batch from the history list. "
9228
context("purge-threads",
9229
po::value<purge_threads_constraint>(&innodb_n_purge_threads)->default_value(0),
9230
"Purge threads can be either 0 or 1. Defalut is 0.");
9231
context("file-per-table",
9232
po::value<bool>(&srv_file_per_table)->default_value(false)->zero_tokens(),
9233
"Stores each InnoDB table to an .ibd file in the database dir.");
9234
context("file-format",
9235
po::value<string>(&innobase_file_format_name)->default_value("Antelope"),
9236
"File format to use for new tables in .ibd files.");
9237
context("file-format-max",
9238
po::value<string>(&innobase_file_format_max)->default_value("Antelope"),
9239
"The highest file format in the tablespace.");
9240
context("file-format-check",
9241
po::value<bool>(&innobase_file_format_check)->default_value(true)->zero_tokens(),
9242
"Whether to perform system file format check.");
9243
context("flush-log-at-trx-commit",
9244
po::value<trinary_constraint>(&innodb_flush_log_at_trx_commit)->default_value(1),
9245
"Set to 0 (write and flush once per second), 1 (write and flush at each commit) or 2 (write at commit, flush once per second).");
9246
context("flush-method",
9247
po::value<string>(),
9248
"With which method to flush data.");
9249
context("log-group-home-dir",
9250
po::value<string>(),
9251
"Path to InnoDB log files.");
9252
context("max-dirty-pages-pct",
9253
po::value<max_dirty_pages_constraint>(&innodb_max_dirty_pages_pct)->default_value(75),
9254
"Percentage of dirty pages allowed in bufferpool.");
9255
context("disable-adaptive-flushing",
9256
"Do not attempt flushing dirty pages to avoid IO bursts at checkpoints.");
9257
context("max-purge-lag",
9258
po::value<uint64_constraint>(&innodb_max_purge_lag)->default_value(0),
9259
"Desired maximum length of the purge queue (0 = no limit)");
9260
context("status-file",
9261
po::value<bool>(&innobase_create_status_file)->default_value(false)->zero_tokens(),
9262
"Enable SHOW INNODB STATUS output in the innodb_status.<pid> file");
9263
context("disable-stats-on-metadata",
9264
"Disable statistics gathering for metadata commands such as SHOW TABLE STATUS (on by default)");
9265
context("stats-sample-pages",
9266
po::value<uint64_nonzero_constraint>(&innodb_stats_sample_pages)->default_value(8),
9267
"The number of index pages to sample when calculating statistics (default 8)");
9268
context("disable-adaptive-hash-index",
9269
"Enable InnoDB adaptive hash index (enabled by default)");
9270
context("replication-delay",
9271
po::value<uint64_constraint>(&innodb_replication_delay)->default_value(0),
9272
"Replication thread delay (ms) on the slave server if innodb_thread_concurrency is reached (0 by default)");
9273
context("additional-mem-pool-size",
9274
po::value<additional_mem_pool_constraint>(&innobase_additional_mem_pool_size)->default_value(8*1024*1024L),
9275
"Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.");
9276
context("autoextend-increment",
9277
po::value<autoextend_constraint>(&innodb_auto_extend_increment)->default_value(8L),
9278
"Data file autoextend increment in megabytes");
9279
context("buffer-pool-size",
9280
po::value<buffer_pool_constraint>(&innobase_buffer_pool_size)->default_value(128*1024*1024L),
9281
"The size of the memory buffer InnoDB uses to cache data and indexes of its tables.");
9282
context("buffer-pool-instances",
9283
po::value<buffer_pool_instances_constraint>(&innobase_buffer_pool_instances)->default_value(1),
9284
"Number of buffer pool instances, set to higher value on high-end machines to increase scalability");
9286
context("commit-concurrency",
9287
po::value<concurrency_constraint>(&innobase_commit_concurrency)->default_value(0),
9288
"Helps in performance tuning in heavily concurrent environments.");
9289
context("concurrency-tickets",
9290
po::value<uint32_nonzero_constraint>(&innodb_concurrency_tickets)->default_value(500L),
9291
"Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket");
9292
context("read-io-threads",
9293
po::value<io_threads_constraint>(&innobase_read_io_threads)->default_value(4),
9294
"Number of background read I/O threads in InnoDB.");
9295
context("write-io-threads",
9296
po::value<io_threads_constraint>(&innobase_write_io_threads)->default_value(4),
9297
"Number of background write I/O threads in InnoDB.");
9298
context("force-recovery",
9299
po::value<force_recovery_constraint>(&innobase_force_recovery)->default_value(0),
9300
"Helps to save your data in case the disk image of the database becomes corrupt.");
9301
context("log-buffer-size",
9302
po::value<log_buffer_constraint>(&innobase_log_buffer_size)->default_value(8*1024*1024L),
9303
"The size of the buffer which InnoDB uses to write log to the log files on disk.");
9304
context("log-file-size",
9305
po::value<log_file_constraint>(&innobase_log_file_size)->default_value(20*1024*1024L),
9306
"The size of the buffer which InnoDB uses to write log to the log files on disk.");
9307
context("log-files-in-group",
9308
po::value<log_files_in_group_constraint>(&innobase_log_files_in_group)->default_value(2),
9309
"Number of log files in the log group. InnoDB writes to the files in a circular fashion.");
9310
context("mirrored-log-groups",
9311
po::value<mirrored_log_groups_constraint>(&innobase_mirrored_log_groups)->default_value(1),
9312
"Number of identical copies of log groups we keep for the database. Currently this should be set to 1.");
9313
context("open-files",
9314
po::value<open_files_constraint>(&innobase_open_files)->default_value(300L),
9315
"How many files at the maximum InnoDB keeps open at the same time.");
9316
context("sync-spin-loops",
9317
po::value<uint32_constraint>(&innodb_sync_spin_loops)->default_value(30L),
9318
"Count of spin-loop rounds in InnoDB mutexes (30 by default)");
9319
context("spin-wait-delay",
9320
po::value<uint32_constraint>(&innodb_spin_wait_delay)->default_value(6L),
9321
"Maximum delay between polling for a spin lock (6 by default)");
9322
context("thread-concurrency",
9323
po::value<concurrency_constraint>(&innobase_thread_concurrency)->default_value(0),
9324
"Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.");
9325
context("thread-sleep-delay",
9326
po::value<uint32_constraint>(&innodb_thread_sleep_delay)->default_value(10000L),
9327
"Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep");
9328
context("data-file-path",
9329
po::value<string>(),
9330
"Path to individual files and their sizes.");
9332
po::value<string>()->default_value(INNODB_VERSION_STR),
9334
context("use-internal-malloc",
9335
"Use InnoDB's internal memory allocator instal of the OS memory allocator.");
9336
context("change-buffering",
9337
po::value<string>(&innobase_change_buffering),
9338
"Buffer changes to reduce random access: OFF, ON, inserting, deleting, changing, or purging.");
9339
context("read-ahead-threshold",
9340
po::value<read_ahead_threshold_constraint>(&innodb_read_ahead_threshold)->default_value(56),
9341
"Number of pages that must be accessed sequentially for InnoDB to trigger a readahead.");
9342
context("disable-xa",
9343
"Disable InnoDB support for the XA two-phase commit");
9344
context("disable-table-locks",
9345
"Disable InnoDB locking in LOCK TABLES");
9346
context("strict-mode",
9347
po::value<bool>(&strict_mode)->default_value(false)->zero_tokens(),
9348
"Use strict mode when evaluating create options.");
9349
context("replication-log",
9350
po::value<bool>(&innobase_use_replication_log)->default_value(false),
9351
_("Enable internal replication log."));
9352
context("lock-wait-timeout",
9353
po::value<lock_wait_constraint>(&lock_wait_timeout)->default_value(50),
9354
_("Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back. Values above 100000000 disable the timeout."));
9355
context("old-blocks-pct",
9356
po::value<old_blocks_constraint>(&innobase_old_blocks_pct)->default_value(100 * 3 / 8),
9357
_("Percentage of the buffer pool to reserve for 'old' blocks."));
9358
context("old-blocks-time",
9359
po::value<uint32_t>(&buf_LRU_old_threshold_ms)->default_value(0),
9360
_("ove blocks to the 'new' end of the buffer pool if the first access"
9361
" was at least this many milliseconds ago."
9362
" The timeout is disabled if 0 (the default)."));
8445
const char* format_check) /*!< in: parameter value */
8450
format_id = innobase_file_format_name_lookup(format_check);
8452
if (format_id < DICT_TF_FORMAT_MAX + 1) {
8453
srv_check_file_format_at_startup = format_id;
8461
/*************************************************************//**
8462
Check if it is a valid file format. This function is registered as
8463
a callback with MySQL.
8464
@return 0 for valid file format */
8467
innodb_file_format_name_validate(
8468
/*=============================*/
8469
Session* , /*!< in: thread handle */
8470
drizzle_sys_var* , /*!< in: pointer to system
8472
void* save, /*!< out: immediate result
8473
for update function */
8474
drizzle_value* value) /*!< in: incoming string */
8476
const char* file_format_input;
8477
char buff[STRING_BUFFER_USUAL_SIZE];
8478
int len = sizeof(buff);
8481
ut_a(value != NULL);
8483
file_format_input = value->val_str(value, buff, &len);
8485
if (file_format_input != NULL) {
8488
format_id = innobase_file_format_name_lookup(
8491
if (format_id <= DICT_TF_FORMAT_MAX) {
8493
*static_cast<const char**>(save) = file_format_input;
8498
*static_cast<const char**>(save) = NULL;
8502
/****************************************************************//**
8503
Update the system variable innodb_file_format using the "saved"
8504
value. This function is registered as a callback with MySQL. */
8507
innodb_file_format_name_update(
8508
/*===========================*/
8509
Session* , /*!< in: thread handle */
8510
drizzle_sys_var* , /*!< in: pointer to
8512
void* var_ptr, /*!< out: where the
8513
formal string goes */
8514
const void* save) /*!< in: immediate result
8515
from check function */
8517
const char* format_name;
8519
ut_a(var_ptr != NULL);
8522
format_name = *static_cast<const char*const*>(save);
8527
format_id = innobase_file_format_name_lookup(format_name);
8529
if (format_id <= DICT_TF_FORMAT_MAX) {
8530
srv_file_format = format_id;
8534
*static_cast<const char**>(var_ptr)
8535
= trx_sys_file_format_id_to_name(srv_file_format);
8538
/*************************************************************//**
8539
Check if valid argument to innodb_file_format_check. This
8540
function is registered as a callback with MySQL.
8541
@return 0 for valid file format */
8544
innodb_file_format_check_validate(
8545
/*==============================*/
8546
Session* , /*!< in: thread handle */
8547
drizzle_sys_var* , /*!< in: pointer to system
8549
void* save, /*!< out: immediate result
8550
for update function */
8551
drizzle_value* value) /*!< in: incoming string */
8553
const char* file_format_input;
8554
char buff[STRING_BUFFER_USUAL_SIZE];
8555
int len = sizeof(buff);
8558
ut_a(value != NULL);
8560
file_format_input = value->val_str(value, buff, &len);
8562
if (file_format_input != NULL) {
8564
/* Check if user set on/off, we want to print a suitable
8565
message if they did so. */
8567
if (innobase_file_format_check_on_off(file_format_input)) {
8568
errmsg_printf(ERRMSG_LVL_WARN,
8569
"InnoDB: invalid innodb_file_format_check "
8570
"value; on/off can only be set at startup or "
8571
"in the configuration file");
8572
} else if (innobase_file_format_check_validate(
8573
file_format_input)) {
8575
*static_cast<const char**>(save) = file_format_input;
8580
errmsg_printf(ERRMSG_LVL_WARN,
8581
"InnoDB: invalid innodb_file_format_check "
8582
"value; can be any format up to %s "
8583
"or its equivalent numeric id",
8584
trx_sys_file_format_id_to_name(
8585
DICT_TF_FORMAT_MAX));
8589
*static_cast<const char**>(save) = NULL;
8593
/****************************************************************//**
8594
Update the system variable innodb_file_format_check using the "saved"
8595
value. This function is registered as a callback with MySQL. */
8598
innodb_file_format_check_update(
8599
/*============================*/
8600
Session* session, /*!< in: thread handle */
8601
drizzle_sys_var* , /*!< in: pointer to
8603
void* var_ptr, /*!< out: where the
8604
formal string goes */
8605
const void* save) /*!< in: immediate result
8606
from check function */
8608
const char* format_name_in;
8609
const char** format_name_out;
8613
ut_a(var_ptr != NULL);
8615
format_name_in = *static_cast<const char*const*>(save);
8617
if (!format_name_in) {
8622
format_id = innobase_file_format_name_lookup(format_name_in);
8624
if (format_id > DICT_TF_FORMAT_MAX) {
8625
/* DEFAULT is "on", which is invalid at runtime. */
8626
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
8628
"Ignoring SET innodb_file_format=%s",
8633
format_name_out = static_cast<const char**>(var_ptr);
8635
/* Update the max format id in the system tablespace. */
8636
if (trx_sys_file_format_max_set(format_id, format_name_out)) {
8637
ut_print_timestamp(stderr);
8639
" [Info] InnoDB: the file format in the system "
8640
"tablespace is now set to %s.\n", *format_name_out);
8644
/****************************************************************//**
8645
Update the system variable innodb_adaptive_hash_index using the "saved"
8646
value. This function is registered as a callback with MySQL. */
8649
innodb_adaptive_hash_index_update(
8650
/*==============================*/
8651
Session* , /*!< in: thread handle */
8652
drizzle_sys_var* , /*!< in: pointer to
8654
void* , /*!< out: where the
8655
formal string goes */
8656
const void* save) /*!< in: immediate result
8657
from check function */
8659
if (*(bool*) save) {
8660
btr_search_enable();
8662
btr_search_disable();
8666
/*************************************************************//**
8667
Check if it is a valid value of innodb_change_buffering. This function is
8668
registered as a callback with MySQL.
8669
@return 0 for valid innodb_change_buffering */
8672
innodb_change_buffering_validate(
8673
/*=============================*/
8674
Session* , /*!< in: thread handle */
8675
drizzle_sys_var* , /*!< in: pointer to system
8677
void* save, /*!< out: immediate result
8678
for update function */
8679
drizzle_value* value) /*!< in: incoming string */
8681
const char* change_buffering_input;
8682
char buff[STRING_BUFFER_USUAL_SIZE];
8683
int len = sizeof(buff);
8686
ut_a(value != NULL);
8688
change_buffering_input = value->val_str(value, buff, &len);
8690
if (change_buffering_input != NULL) {
8693
for (use = 0; use < UT_ARR_SIZE(innobase_change_buffering_values);
8695
if (!innobase_strcasecmp(
8696
change_buffering_input,
8697
innobase_change_buffering_values[use])) {
8698
*(ibuf_use_t*) save = (ibuf_use_t) use;
8707
/****************************************************************//**
8708
Update the system variable innodb_change_buffering using the "saved"
8709
value. This function is registered as a callback with MySQL. */
8712
innodb_change_buffering_update(
8713
/*===========================*/
8714
Session* , /*!< in: thread handle */
8715
drizzle_sys_var* , /*!< in: pointer to
8717
void* var_ptr, /*!< out: where the
8718
formal string goes */
8719
const void* save) /*!< in: immediate result
8720
from check function */
8722
ut_a(var_ptr != NULL);
8724
ut_a((*(ibuf_use_t*) save) < IBUF_USE_COUNT);
8726
ibuf_use = *(const ibuf_use_t*) save;
8728
*(const char**) var_ptr = innobase_change_buffering_values[ibuf_use];
8731
static int show_innodb_vars(SHOW_VAR *var, char *)
8733
innodb_export_status();
8734
var->type= SHOW_ARRAY;
8735
var->value= (char *) &innodb_status_variables;
8739
static st_show_var_func_container
8740
show_innodb_vars_cont = { &show_innodb_vars };
8742
static SHOW_VAR innodb_status_variables_export[]= {
8743
{"Innodb", (char*) &show_innodb_vars_cont, SHOW_FUNC},
8744
{NULL, NULL, SHOW_LONG}
8748
/* plugin options */
8749
static DRIZZLE_SYSVAR_BOOL(checksums, innobase_use_checksums,
8750
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
8751
"Enable InnoDB checksums validation (enabled by default). "
8752
"Disable with --skip-innodb-checksums.",
8755
static DRIZZLE_SYSVAR_STR(data_home_dir, innobase_data_home_dir,
8756
PLUGIN_VAR_READONLY,
8757
"The common part for InnoDB table spaces.",
8760
static DRIZZLE_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
8761
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
8762
"Enable InnoDB doublewrite buffer (enabled by default). "
8763
"Disable with --skip-innodb-doublewrite.",
8766
static DRIZZLE_SYSVAR_ULONG(io_capacity, srv_io_capacity,
8767
PLUGIN_VAR_RQCMDARG,
8768
"Number of IOPs the server can do. Tunes the background IO rate",
8769
NULL, NULL, 200, 100, ~0L, 0);
8771
static DRIZZLE_SYSVAR_ULONG(fast_shutdown, innobase_fast_shutdown,
8772
PLUGIN_VAR_OPCMDARG,
8773
"Speeds up the shutdown process of the InnoDB storage engine. Possible "
8774
"values are 0, 1 (faster)"
8775
" or 2 (fastest - crash-like)"
8777
NULL, NULL, 1, 0, 2, 0);
8779
static DRIZZLE_SYSVAR_BOOL(file_per_table, srv_file_per_table,
8780
PLUGIN_VAR_NOCMDARG,
8781
"Stores each InnoDB table to an .ibd file in the database dir.",
8784
static DRIZZLE_SYSVAR_STR(file_format, innobase_file_format_name,
8785
PLUGIN_VAR_RQCMDARG,
8786
"File format to use for new tables in .ibd files.",
8787
innodb_file_format_name_validate,
8788
innodb_file_format_name_update, "Antelope");
8790
static DRIZZLE_SYSVAR_STR(file_format_check, innobase_file_format_check,
8791
PLUGIN_VAR_OPCMDARG,
8792
"The highest file format in the tablespace.",
8793
innodb_file_format_check_validate,
8794
innodb_file_format_check_update,
8797
static DRIZZLE_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit,
8798
PLUGIN_VAR_OPCMDARG,
8799
"Set to 0 (write and flush once per second),"
8800
" 1 (write and flush at each commit)"
8801
" or 2 (write at commit, flush once per second).",
8802
NULL, NULL, 1, 0, 2, 0);
8804
static DRIZZLE_SYSVAR_STR(flush_method, innobase_unix_file_flush_method,
8805
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8806
"With which method to flush data.", NULL, NULL, NULL);
8808
static DRIZZLE_SYSVAR_BOOL(locks_unsafe_for_binlog, innobase_locks_unsafe_for_binlog,
8809
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
8810
"Force InnoDB to not use next-key locking, to use only row-level locking.",
8813
#ifdef UNIV_LOG_ARCHIVE
8814
static DRIZZLE_SYSVAR_STR(log_arch_dir, innobase_log_arch_dir,
8815
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8816
"Where full logs should be archived.", NULL, NULL, NULL);
8818
static DRIZZLE_SYSVAR_BOOL(log_archive, innobase_log_archive,
8819
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
8820
"Set to 1 if you want to have logs archived.", NULL, NULL, FALSE);
8821
#endif /* UNIV_LOG_ARCHIVE */
8823
static DRIZZLE_SYSVAR_STR(log_group_home_dir, innobase_log_group_home_dir,
8824
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8825
"Path to InnoDB log files.", NULL, NULL, NULL);
8827
static DRIZZLE_SYSVAR_ULONG(max_dirty_pages_pct, srv_max_buf_pool_modified_pct,
8828
PLUGIN_VAR_RQCMDARG,
8829
"Percentage of dirty pages allowed in bufferpool.",
8830
NULL, NULL, 75, 0, 99, 0);
8832
static DRIZZLE_SYSVAR_BOOL(adaptive_flushing, srv_adaptive_flushing,
8833
PLUGIN_VAR_NOCMDARG,
8834
"Attempt flushing dirty pages to avoid IO bursts at checkpoints.",
8837
static DRIZZLE_SYSVAR_ULONG(max_purge_lag, srv_max_purge_lag,
8838
PLUGIN_VAR_RQCMDARG,
8839
"Desired maximum length of the purge queue (0 = no limit)",
8840
NULL, NULL, 0, 0, ~0L, 0);
8842
static DRIZZLE_SYSVAR_BOOL(rollback_on_timeout, innobase_rollback_on_timeout,
8843
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
8844
"Roll back the complete transaction on lock wait timeout, for 4.x compatibility (disabled by default)",
8847
static DRIZZLE_SYSVAR_BOOL(status_file, innobase_create_status_file,
8848
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOSYSVAR,
8849
"Enable SHOW INNODB STATUS output in the innodb_status.<pid> file",
8852
static DRIZZLE_SYSVAR_BOOL(stats_on_metadata, innobase_stats_on_metadata,
8853
PLUGIN_VAR_OPCMDARG,
8854
"Enable statistics gathering for metadata commands such as SHOW TABLE STATUS (on by default)",
8857
static DRIZZLE_SYSVAR_ULONGLONG(stats_sample_pages, srv_stats_sample_pages,
8858
PLUGIN_VAR_RQCMDARG,
8859
"The number of index pages to sample when calculating statistics (default 8)",
8860
NULL, NULL, 8, 1, ~0ULL, 0);
8862
static DRIZZLE_SYSVAR_BOOL(adaptive_hash_index, btr_search_enabled,
8863
PLUGIN_VAR_OPCMDARG,
8864
"Enable InnoDB adaptive hash index (enabled by default). "
8865
"Disable with --skip-innodb-adaptive-hash-index.",
8866
NULL, innodb_adaptive_hash_index_update, TRUE);
8868
static DRIZZLE_SYSVAR_ULONG(replication_delay, srv_replication_delay,
8869
PLUGIN_VAR_RQCMDARG,
8870
"Replication thread delay (ms) on the slave server if "
8871
"innodb_thread_concurrency is reached (0 by default)",
8872
NULL, NULL, 0, 0, ~0UL, 0);
8874
static DRIZZLE_SYSVAR_LONG(additional_mem_pool_size, innobase_additional_mem_pool_size,
8875
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8876
"Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.",
8877
NULL, NULL, 8*1024*1024L, 512*1024L, LONG_MAX, 1024);
8879
static DRIZZLE_SYSVAR_UINT(autoextend_increment, srv_auto_extend_increment,
8880
PLUGIN_VAR_RQCMDARG,
8881
"Data file autoextend increment in megabytes",
8882
NULL, NULL, 8L, 1L, 1000L, 0);
8884
static DRIZZLE_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size,
8885
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8886
"The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
8887
NULL, NULL, 128*1024*1024L, 5*1024*1024L, INT64_MAX, 1024*1024L);
8889
static DRIZZLE_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency,
8890
PLUGIN_VAR_RQCMDARG,
8891
"Helps in performance tuning in heavily concurrent environments.",
8892
innobase_commit_concurrency_validate, NULL, 0, 0, 1000, 0);
8894
static DRIZZLE_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
8895
PLUGIN_VAR_RQCMDARG,
8896
"Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
8897
NULL, NULL, 500L, 1L, ~0L, 0);
8899
static DRIZZLE_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
8900
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8901
"Number of file I/O threads in InnoDB.",
8902
NULL, NULL, 4, 4, 64, 0);
8904
static DRIZZLE_SYSVAR_ULONG(read_io_threads, innobase_read_io_threads,
8905
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8906
"Number of background read I/O threads in InnoDB.",
8907
NULL, NULL, 4, 1, 64, 0);
8909
static DRIZZLE_SYSVAR_ULONG(write_io_threads, innobase_write_io_threads,
8910
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8911
"Number of background write I/O threads in InnoDB.",
8912
NULL, NULL, 4, 1, 64, 0);
8914
static DRIZZLE_SYSVAR_LONG(force_recovery, innobase_force_recovery,
8915
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8916
"Helps to save your data in case the disk image of the database becomes corrupt.",
8917
NULL, NULL, 0, 0, 6, 0);
8919
static DRIZZLE_SYSVAR_LONG(log_buffer_size, innobase_log_buffer_size,
8920
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8921
"The size of the buffer which InnoDB uses to write log to the log files on disk.",
8922
NULL, NULL, 8*1024*1024L, 256*1024L, LONG_MAX, 1024);
8924
static DRIZZLE_SYSVAR_LONGLONG(log_file_size, innobase_log_file_size,
8925
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8926
"Size of each log file in a log group.",
8927
NULL, NULL, 5*1024*1024L, 1*1024*1024L, INT64_MAX, 1024*1024L);
8929
static DRIZZLE_SYSVAR_LONG(log_files_in_group, innobase_log_files_in_group,
8930
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8931
"Number of log files in the log group. InnoDB writes to the files in a circular fashion. Value 3 is recommended here.",
8932
NULL, NULL, 2, 2, 100, 0);
8934
static DRIZZLE_SYSVAR_LONG(mirrored_log_groups, innobase_mirrored_log_groups,
8935
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8936
"Number of identical copies of log groups we keep for the database. Currently this should be set to 1.",
8937
NULL, NULL, 1, 1, 10, 0);
8939
static DRIZZLE_SYSVAR_LONG(open_files, innobase_open_files,
8940
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8941
"How many files at the maximum InnoDB keeps open at the same time.",
8942
NULL, NULL, 300L, 10L, LONG_MAX, 0);
8944
static DRIZZLE_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds,
8945
PLUGIN_VAR_RQCMDARG,
8946
"Count of spin-loop rounds in InnoDB mutexes (30 by default)",
8947
NULL, NULL, 30L, 0L, ~0L, 0);
8949
static DRIZZLE_SYSVAR_ULONG(spin_wait_delay, srv_spin_wait_delay,
8950
PLUGIN_VAR_OPCMDARG,
8951
"Maximum delay between polling for a spin lock (6 by default)",
8952
NULL, NULL, 6L, 0L, ~0L, 0);
8954
static DRIZZLE_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
8955
PLUGIN_VAR_RQCMDARG,
8956
"Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.",
8957
NULL, NULL, 0, 0, 1000, 0);
8959
static DRIZZLE_SYSVAR_ULONG(thread_sleep_delay, srv_thread_sleep_delay,
8960
PLUGIN_VAR_RQCMDARG,
8961
"Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep",
8962
NULL, NULL, 10000L, 0L, ~0L, 0);
8964
static DRIZZLE_SYSVAR_STR(data_file_path, innobase_data_file_path,
8965
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8966
"Path to individual files and their sizes.",
8969
static DRIZZLE_SYSVAR_LONG(autoinc_lock_mode, innobase_autoinc_lock_mode,
8970
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
8971
"The AUTOINC lock modes supported by InnoDB: "
8972
"0 => Old style AUTOINC locking (for backward"
8974
"1 => New style AUTOINC locking "
8975
"2 => No AUTOINC locking (unsafe for SBR)",
8977
AUTOINC_NO_LOCKING, /* Default setting */
8978
AUTOINC_OLD_STYLE_LOCKING, /* Minimum value */
8979
AUTOINC_NO_LOCKING, 0); /* Maximum value */
8981
static DRIZZLE_SYSVAR_STR(version, innodb_version_str,
8982
PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY,
8983
"InnoDB version", NULL, NULL, INNODB_VERSION_STR);
8985
static DRIZZLE_SYSVAR_BOOL(use_sys_malloc, srv_use_sys_malloc,
8986
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
8987
"Use OS memory allocator instead of InnoDB's internal memory allocator",
8990
static DRIZZLE_SYSVAR_STR(change_buffering, innobase_change_buffering,
8991
PLUGIN_VAR_RQCMDARG,
8992
"Buffer changes to reduce random access: "
8993
"OFF, ON, inserting, deleting, changing, or purging.",
8994
innodb_change_buffering_validate,
8995
innodb_change_buffering_update, NULL);
8997
static DRIZZLE_SYSVAR_ULONG(read_ahead_threshold, srv_read_ahead_threshold,
8998
PLUGIN_VAR_RQCMDARG,
8999
"Number of pages that must be accessed sequentially for InnoDB to"
9000
"trigger a readahead.",
9001
NULL, NULL, 56, 0, 64, 0);
9003
static drizzle_sys_var* innobase_system_variables[]= {
9004
DRIZZLE_SYSVAR(additional_mem_pool_size),
9005
DRIZZLE_SYSVAR(autoextend_increment),
9006
DRIZZLE_SYSVAR(buffer_pool_size),
9007
DRIZZLE_SYSVAR(checksums),
9008
DRIZZLE_SYSVAR(commit_concurrency),
9009
DRIZZLE_SYSVAR(concurrency_tickets),
9010
DRIZZLE_SYSVAR(data_file_path),
9011
DRIZZLE_SYSVAR(data_home_dir),
9012
DRIZZLE_SYSVAR(doublewrite),
9013
DRIZZLE_SYSVAR(fast_shutdown),
9014
DRIZZLE_SYSVAR(file_io_threads),
9015
DRIZZLE_SYSVAR(read_io_threads),
9016
DRIZZLE_SYSVAR(write_io_threads),
9017
DRIZZLE_SYSVAR(file_per_table),
9018
DRIZZLE_SYSVAR(file_format),
9019
DRIZZLE_SYSVAR(file_format_check),
9020
DRIZZLE_SYSVAR(flush_log_at_trx_commit),
9021
DRIZZLE_SYSVAR(flush_method),
9022
DRIZZLE_SYSVAR(force_recovery),
9023
DRIZZLE_SYSVAR(locks_unsafe_for_binlog),
9024
DRIZZLE_SYSVAR(lock_wait_timeout),
9025
#ifdef UNIV_LOG_ARCHIVE
9026
DRIZZLE_SYSVAR(log_arch_dir),
9027
DRIZZLE_SYSVAR(log_archive),
9028
#endif /* UNIV_LOG_ARCHIVE */
9029
DRIZZLE_SYSVAR(log_buffer_size),
9030
DRIZZLE_SYSVAR(log_file_size),
9031
DRIZZLE_SYSVAR(log_files_in_group),
9032
DRIZZLE_SYSVAR(log_group_home_dir),
9033
DRIZZLE_SYSVAR(max_dirty_pages_pct),
9034
DRIZZLE_SYSVAR(max_purge_lag),
9035
DRIZZLE_SYSVAR(adaptive_flushing),
9036
DRIZZLE_SYSVAR(mirrored_log_groups),
9037
DRIZZLE_SYSVAR(open_files),
9038
DRIZZLE_SYSVAR(rollback_on_timeout),
9039
DRIZZLE_SYSVAR(stats_on_metadata),
9040
DRIZZLE_SYSVAR(stats_sample_pages),
9041
DRIZZLE_SYSVAR(adaptive_hash_index),
9042
DRIZZLE_SYSVAR(replication_delay),
9043
DRIZZLE_SYSVAR(status_file),
9044
DRIZZLE_SYSVAR(strict_mode),
9045
DRIZZLE_SYSVAR(support_xa),
9046
DRIZZLE_SYSVAR(sync_spin_loops),
9047
DRIZZLE_SYSVAR(spin_wait_delay),
9048
DRIZZLE_SYSVAR(table_locks),
9049
DRIZZLE_SYSVAR(thread_concurrency),
9050
DRIZZLE_SYSVAR(thread_sleep_delay),
9051
DRIZZLE_SYSVAR(autoinc_lock_mode),
9052
DRIZZLE_SYSVAR(version),
9053
DRIZZLE_SYSVAR(use_sys_malloc),
9054
DRIZZLE_SYSVAR(change_buffering),
9055
DRIZZLE_SYSVAR(read_ahead_threshold),
9056
DRIZZLE_SYSVAR(io_capacity),
9367
9060
DRIZZLE_DECLARE_PLUGIN
9404
/***********************************************************************
9405
This function checks each index name for a table against reserved
9406
system default primary index name 'GEN_CLUST_INDEX'. If a name matches,
9407
this function pushes an warning message to the client, and returns true. */
9408
extern "C" UNIV_INTERN
9410
innobase_index_name_is_reserved(
9411
/*============================*/
9412
/* out: true if an index name
9413
matches the reserved name */
9414
const trx_t* trx, /* in: InnoDB transaction handle */
9415
const KeyInfo* key_info, /* in: Indexes to be created */
9416
ulint num_of_keys) /* in: Number of indexes to
9099
/** @brief Initialize the default value of innodb_commit_concurrency.
9101
Once InnoDB is running, the innodb_commit_concurrency must not change
9102
from zero to nonzero. (Bug #42101)
9104
The initial default value is 0, and without this extra initialization,
9105
SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter
9106
to 0, even if it was initially set to nonzero at the command line
9107
or configuration file. */
9110
innobase_commit_concurrency_init_default(void)
9111
/*==========================================*/
9420
uint key_num; /* index number */
9422
for (key_num = 0; key_num < num_of_keys; key_num++) {
9423
key = &key_info[key_num];
9425
if (innobase_strcasecmp(key->name,
9426
innobase_index_reserve_name) == 0) {
9427
/* Push warning to drizzle */
9428
push_warning_printf((Session*)trx->mysql_thd,
9429
DRIZZLE_ERROR::WARN_LEVEL_WARN,
9430
ER_WRONG_NAME_FOR_INDEX,
9431
"Cannot Create Index with name "
9432
"'%s'. The name is reserved "
9433
"for the system default primary "
9435
innobase_index_reserve_name);
9437
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
9438
innobase_index_reserve_name);
9113
DRIZZLE_SYSVAR_NAME(commit_concurrency).def_val
9114
= innobase_commit_concurrency;
9447
9117
#ifdef UNIV_COMPILE_TEST_FUNCS
9449
9119
typedef struct innobase_convert_name_test_struct {
9457
const char* expected;
9127
const char* expected;
9458
9128
} innobase_convert_name_test_t;
9461
9131
test_innobase_convert_name()
9466
innobase_convert_name_test_t test_input[] = {
9467
{buf, sizeof(buf), "abcd", 4, NULL, TRUE, "\"abcd\""},
9468
{buf, 7, "abcd", 4, NULL, TRUE, "\"abcd\""},
9469
{buf, 6, "abcd", 4, NULL, TRUE, "\"abcd\""},
9470
{buf, 5, "abcd", 4, NULL, TRUE, "\"abc\""},
9471
{buf, 4, "abcd", 4, NULL, TRUE, "\"ab\""},
9473
{buf, sizeof(buf), "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
9474
{buf, 9, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
9475
{buf, 8, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
9476
{buf, 7, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
9477
{buf, 6, "ab@0060cd", 9, NULL, TRUE, "\"ab`c\""},
9478
{buf, 5, "ab@0060cd", 9, NULL, TRUE, "\"ab`\""},
9479
{buf, 4, "ab@0060cd", 9, NULL, TRUE, "\"ab\""},
9481
{buf, sizeof(buf), "ab\"cd", 5, NULL, TRUE,
9482
"\"#mysql50#ab\"\"cd\""},
9483
{buf, 17, "ab\"cd", 5, NULL, TRUE,
9484
"\"#mysql50#ab\"\"cd\""},
9485
{buf, 16, "ab\"cd", 5, NULL, TRUE,
9486
"\"#mysql50#ab\"\"c\""},
9487
{buf, 15, "ab\"cd", 5, NULL, TRUE,
9488
"\"#mysql50#ab\"\"\""},
9489
{buf, 14, "ab\"cd", 5, NULL, TRUE,
9491
{buf, 13, "ab\"cd", 5, NULL, TRUE,
9493
{buf, 12, "ab\"cd", 5, NULL, TRUE,
9495
{buf, 11, "ab\"cd", 5, NULL, TRUE,
9497
{buf, 10, "ab\"cd", 5, NULL, TRUE,
9500
{buf, sizeof(buf), "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
9501
{buf, 9, "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
9502
{buf, 8, "ab/cd", 5, NULL, TRUE, "\"ab\".\"c\""},
9503
{buf, 7, "ab/cd", 5, NULL, TRUE, "\"ab\".\"\""},
9504
{buf, 6, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
9505
{buf, 5, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
9506
{buf, 4, "ab/cd", 5, NULL, TRUE, "\"ab\""},
9507
{buf, 3, "ab/cd", 5, NULL, TRUE, "\"a\""},
9508
{buf, 2, "ab/cd", 5, NULL, TRUE, "\"\""},
9509
/* XXX probably "" is a better result in this case
9510
{buf, 1, "ab/cd", 5, NULL, TRUE, "."},
9512
{buf, 0, "ab/cd", 5, NULL, TRUE, ""},
9515
for (i = 0; i < sizeof(test_input) / sizeof(test_input[0]); i++) {
9521
fprintf(stderr, "TESTING %lu, %s, %lu, %s\n",
9522
test_input[i].buflen,
9524
test_input[i].idlen,
9525
test_input[i].expected);
9527
end = innobase_convert_name(
9529
test_input[i].buflen,
9531
test_input[i].idlen,
9532
test_input[i].session,
9533
test_input[i].file_id);
9535
res_len = (size_t) (end - test_input[i].buf);
9537
if (res_len != strlen(test_input[i].expected)) {
9539
fprintf(stderr, "unexpected len of the result: %u, "
9540
"expected: %u\n", (unsigned) res_len,
9541
(unsigned) strlen(test_input[i].expected));
9545
if (memcmp(test_input[i].buf,
9546
test_input[i].expected,
9547
strlen(test_input[i].expected)) != 0
9550
fprintf(stderr, "unexpected result: %.*s, "
9551
"expected: %s\n", (int) res_len,
9553
test_input[i].expected);
9558
fprintf(stderr, "OK: res: %.*s\n\n", (int) res_len,
9561
fprintf(stderr, "FAILED\n\n");
9136
innobase_convert_name_test_t test_input[] = {
9137
{buf, sizeof(buf), "abcd", 4, NULL, TRUE, "\"abcd\""},
9138
{buf, 7, "abcd", 4, NULL, TRUE, "\"abcd\""},
9139
{buf, 6, "abcd", 4, NULL, TRUE, "\"abcd\""},
9140
{buf, 5, "abcd", 4, NULL, TRUE, "\"abc\""},
9141
{buf, 4, "abcd", 4, NULL, TRUE, "\"ab\""},
9143
{buf, sizeof(buf), "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
9144
{buf, 9, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
9145
{buf, 8, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
9146
{buf, 7, "ab@0060cd", 9, NULL, TRUE, "\"ab`cd\""},
9147
{buf, 6, "ab@0060cd", 9, NULL, TRUE, "\"ab`c\""},
9148
{buf, 5, "ab@0060cd", 9, NULL, TRUE, "\"ab`\""},
9149
{buf, 4, "ab@0060cd", 9, NULL, TRUE, "\"ab\""},
9151
{buf, sizeof(buf), "ab\"cd", 5, NULL, TRUE,
9152
"\"#mysql50#ab\"\"cd\""},
9153
{buf, 17, "ab\"cd", 5, NULL, TRUE,
9154
"\"#mysql50#ab\"\"cd\""},
9155
{buf, 16, "ab\"cd", 5, NULL, TRUE,
9156
"\"#mysql50#ab\"\"c\""},
9157
{buf, 15, "ab\"cd", 5, NULL, TRUE,
9158
"\"#mysql50#ab\"\"\""},
9159
{buf, 14, "ab\"cd", 5, NULL, TRUE,
9161
{buf, 13, "ab\"cd", 5, NULL, TRUE,
9163
{buf, 12, "ab\"cd", 5, NULL, TRUE,
9165
{buf, 11, "ab\"cd", 5, NULL, TRUE,
9167
{buf, 10, "ab\"cd", 5, NULL, TRUE,
9170
{buf, sizeof(buf), "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
9171
{buf, 9, "ab/cd", 5, NULL, TRUE, "\"ab\".\"cd\""},
9172
{buf, 8, "ab/cd", 5, NULL, TRUE, "\"ab\".\"c\""},
9173
{buf, 7, "ab/cd", 5, NULL, TRUE, "\"ab\".\"\""},
9174
{buf, 6, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
9175
{buf, 5, "ab/cd", 5, NULL, TRUE, "\"ab\"."},
9176
{buf, 4, "ab/cd", 5, NULL, TRUE, "\"ab\""},
9177
{buf, 3, "ab/cd", 5, NULL, TRUE, "\"a\""},
9178
{buf, 2, "ab/cd", 5, NULL, TRUE, "\"\""},
9179
/* XXX probably "" is a better result in this case
9180
{buf, 1, "ab/cd", 5, NULL, TRUE, "."},
9182
{buf, 0, "ab/cd", 5, NULL, TRUE, ""},
9185
for (i = 0; i < sizeof(test_input) / sizeof(test_input[0]); i++) {
9191
fprintf(stderr, "TESTING %lu, %s, %lu, %s\n",
9192
test_input[i].buflen,
9194
test_input[i].idlen,
9195
test_input[i].expected);
9197
end = innobase_convert_name(
9199
test_input[i].buflen,
9201
test_input[i].idlen,
9202
test_input[i].session,
9203
test_input[i].file_id);
9205
res_len = (size_t) (end - test_input[i].buf);
9207
if (res_len != strlen(test_input[i].expected)) {
9209
fprintf(stderr, "unexpected len of the result: %u, "
9210
"expected: %u\n", (unsigned) res_len,
9211
(unsigned) strlen(test_input[i].expected));
9215
if (memcmp(test_input[i].buf,
9216
test_input[i].expected,
9217
strlen(test_input[i].expected)) != 0
9220
fprintf(stderr, "unexpected result: %.*s, "
9221
"expected: %s\n", (int) res_len,
9223
test_input[i].expected);
9228
fprintf(stderr, "OK: res: %.*s\n\n", (int) res_len,
9231
fprintf(stderr, "FAILED\n\n");
9567
9237
#endif /* UNIV_COMPILE_TEST_FUNCS */