Merge with 5.2

This commit is contained in:
Michael Widenius 2011-03-09 15:47:59 +02:00
commit 139a2b64bf
1617 changed files with 28742 additions and 44152 deletions

View file

@ -6010,6 +6010,16 @@ create_table_def(
DBUG_RETURN(HA_ERR_GENERIC);
}
/* MySQL does the name length check. But we do additional check
on the name length here */
if (strlen(table_name) > MAX_FULL_NAME_LEN) {
push_warning_printf(
(THD*) trx->mysql_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TABLE_NAME,
"InnoDB: Table Name or Database Name is too long");
DBUG_RETURN(ER_TABLE_NAME);
}
n_cols = form->s->fields;
/* We pass 0 as the space id, and determine at a lower level the space
@ -6291,6 +6301,60 @@ create_clustered_index_when_no_primary(
return(error);
}
/*****************************************************************//**
Return a display name for the row format
@return row format name */
UNIV_INTERN
const char*
get_row_format_name(
/*================*/
enum row_type row_format) /*!< in: Row Format */
{
switch (row_format) {
case ROW_TYPE_COMPACT:
return("COMPACT");
case ROW_TYPE_COMPRESSED:
return("COMPRESSED");
case ROW_TYPE_DYNAMIC:
return("DYNAMIC");
case ROW_TYPE_REDUNDANT:
return("REDUNDANT");
case ROW_TYPE_DEFAULT:
return("DEFAULT");
case ROW_TYPE_FIXED:
return("FIXED");
case ROW_TYPE_PAGE:
case ROW_TYPE_NOT_USED:
break;
}
return("NOT USED");
}
/** If file-per-table is missing, issue warning and set ret false */
#define CHECK_ERROR_ROW_TYPE_NEEDS_FILE_PER_TABLE \
if (!srv_file_per_table) { \
push_warning_printf( \
thd, MYSQL_ERROR::WARN_LEVEL_WARN, \
ER_ILLEGAL_HA_CREATE_OPTION, \
"InnoDB: ROW_FORMAT=%s requires" \
" innodb_file_per_table.", \
get_row_format_name(row_format)); \
ret = FALSE; \
}
/** If file-format is Antelope, issue warning and set ret false */
#define CHECK_ERROR_ROW_TYPE_NEEDS_GT_ANTELOPE \
if (srv_file_format < DICT_TF_FORMAT_ZIP) { \
push_warning_printf( \
thd, MYSQL_ERROR::WARN_LEVEL_WARN, \
ER_ILLEGAL_HA_CREATE_OPTION, \
"InnoDB: ROW_FORMAT=%s requires" \
" innodb_file_format > Antelope.", \
get_row_format_name(row_format)); \
ret = FALSE; \
}
/*****************************************************************//**
Validates the create options. We may build on this function
in future. For now, it checks two specifiers:
@ -6306,9 +6370,9 @@ create_options_are_valid(
columns and indexes */
HA_CREATE_INFO* create_info) /*!< in: create info. */
{
ibool kbs_specified = FALSE;
ibool kbs_specified = FALSE;
ibool ret = TRUE;
enum row_type row_format = form->s->row_type;
ut_ad(thd != NULL);
@ -6320,10 +6384,8 @@ create_options_are_valid(
ut_ad(form != NULL);
ut_ad(create_info != NULL);
/* First check if KEY_BLOCK_SIZE was specified. */
if (create_info->key_block_size
|| (create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)) {
/* First check if a non-zero KEY_BLOCK_SIZE was specified. */
if (create_info->key_block_size) {
kbs_specified = TRUE;
switch (create_info->key_block_size) {
case 1:
@ -6331,126 +6393,70 @@ create_options_are_valid(
case 4:
case 8:
case 16:
/* Valid value. */
/* Valid KEY_BLOCK_SIZE, check its dependencies. */
if (!srv_file_per_table) {
push_warning(
thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: KEY_BLOCK_SIZE requires"
" innodb_file_per_table.");
ret = FALSE;
}
if (srv_file_format < DICT_TF_FORMAT_ZIP) {
push_warning(
thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: KEY_BLOCK_SIZE requires"
" innodb_file_format > Antelope.");
ret = FALSE;
}
break;
default:
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: invalid"
" KEY_BLOCK_SIZE = %lu."
" Valid values are"
" [1, 2, 4, 8, 16]",
create_info->key_block_size);
push_warning_printf(
thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: invalid KEY_BLOCK_SIZE = %lu."
" Valid values are [1, 2, 4, 8, 16]",
create_info->key_block_size);
ret = FALSE;
break;
}
}
/* If KEY_BLOCK_SIZE was specified, check for its
dependencies. */
if (kbs_specified && !srv_file_per_table) {
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: KEY_BLOCK_SIZE"
" requires innodb_file_per_table.");
ret = FALSE;
}
if (kbs_specified && srv_file_format < DICT_TF_FORMAT_ZIP) {
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: KEY_BLOCK_SIZE"
" requires innodb_file_format >"
" Antelope.");
ret = FALSE;
}
/* Now check for ROW_FORMAT specifier. */
if (create_info->used_fields & HA_CREATE_USED_ROW_FORMAT) {
switch (form->s->row_type) {
const char* row_format_name;
case ROW_TYPE_COMPRESSED:
case ROW_TYPE_DYNAMIC:
row_format_name
= form->s->row_type == ROW_TYPE_COMPRESSED
? "COMPRESSED"
: "DYNAMIC";
/* These two ROW_FORMATs require srv_file_per_table
and srv_file_format > Antelope */
if (!srv_file_per_table) {
push_warning_printf(
thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: ROW_FORMAT=%s"
" requires innodb_file_per_table.",
row_format_name);
ret = FALSE;
}
if (srv_file_format < DICT_TF_FORMAT_ZIP) {
push_warning_printf(
thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: ROW_FORMAT=%s"
" requires innodb_file_format >"
" Antelope.",
row_format_name);
ret = FALSE;
}
/* Cannot specify KEY_BLOCK_SIZE with
ROW_FORMAT = DYNAMIC.
However, we do allow COMPRESSED to be
specified with KEY_BLOCK_SIZE. */
if (kbs_specified
&& form->s->row_type == ROW_TYPE_DYNAMIC) {
push_warning_printf(
thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: cannot specify"
" ROW_FORMAT = DYNAMIC with"
" KEY_BLOCK_SIZE.");
ret = FALSE;
}
break;
case ROW_TYPE_REDUNDANT:
case ROW_TYPE_COMPACT:
case ROW_TYPE_DEFAULT:
/* Default is COMPACT. */
row_format_name
= form->s->row_type == ROW_TYPE_REDUNDANT
? "REDUNDANT"
: "COMPACT";
/* Cannot specify KEY_BLOCK_SIZE with these
format specifiers. */
if (kbs_specified) {
push_warning_printf(
thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: cannot specify"
" ROW_FORMAT = %s with"
" KEY_BLOCK_SIZE.",
row_format_name);
ret = FALSE;
}
break;
default:
push_warning(thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: invalid ROW_FORMAT specifier.");
/* Check for a valid Innodb ROW_FORMAT specifier and
other incompatibilities. */
switch (row_format) {
case ROW_TYPE_COMPRESSED:
CHECK_ERROR_ROW_TYPE_NEEDS_FILE_PER_TABLE;
CHECK_ERROR_ROW_TYPE_NEEDS_GT_ANTELOPE;
break;
case ROW_TYPE_DYNAMIC:
CHECK_ERROR_ROW_TYPE_NEEDS_FILE_PER_TABLE;
CHECK_ERROR_ROW_TYPE_NEEDS_GT_ANTELOPE;
/* fall through since dynamic also shuns KBS */
case ROW_TYPE_COMPACT:
case ROW_TYPE_REDUNDANT:
if (kbs_specified) {
push_warning_printf(
thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: cannot specify ROW_FORMAT = %s"
" with KEY_BLOCK_SIZE.",
get_row_format_name(row_format));
ret = FALSE;
}
break;
case ROW_TYPE_DEFAULT:
break;
case ROW_TYPE_FIXED:
case ROW_TYPE_PAGE:
case ROW_TYPE_NOT_USED:
push_warning(
thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION, \
"InnoDB: invalid ROW_FORMAT specifier.");
ret = FALSE;
break;
}
return(ret);
@ -6500,7 +6506,7 @@ ha_innobase::create(
const ulint file_format = srv_file_format;
const char* stmt;
size_t stmt_len;
enum row_type row_type;
enum row_type row_format;
DBUG_ENTER("ha_innobase::create");
@ -6576,8 +6582,7 @@ ha_innobase::create(
goto cleanup;
}
if (create_info->key_block_size
|| (create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)) {
if (create_info->key_block_size) {
/* Determine the page_zip.ssize corresponding to the
requested page size (key_block_size) in kilobytes. */
@ -6598,40 +6603,40 @@ ha_innobase::create(
}
if (!srv_file_per_table) {
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: KEY_BLOCK_SIZE"
" requires innodb_file_per_table.");
push_warning(
thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: KEY_BLOCK_SIZE requires"
" innodb_file_per_table.");
flags = 0;
}
if (file_format < DICT_TF_FORMAT_ZIP) {
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: KEY_BLOCK_SIZE"
" requires innodb_file_format >"
" Antelope.");
push_warning(
thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: KEY_BLOCK_SIZE requires"
" innodb_file_format > Antelope.");
flags = 0;
}
if (!flags) {
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: ignoring"
" KEY_BLOCK_SIZE=%lu.",
create_info->key_block_size);
push_warning_printf(
thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: ignoring KEY_BLOCK_SIZE=%lu.",
create_info->key_block_size);
}
}
row_type = form->s->row_type;
row_format = form->s->row_type;
if (flags) {
/* if KEY_BLOCK_SIZE was specified on this statement and
ROW_FORMAT was not, automatically change ROW_FORMAT to COMPRESSED.*/
if ( (create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)
&& !(create_info->used_fields & HA_CREATE_USED_ROW_FORMAT)) {
row_type = ROW_TYPE_COMPRESSED;
} else if (row_type != ROW_TYPE_COMPRESSED) {
/* if ROW_FORMAT is set to default,
automatically change it to COMPRESSED.*/
if (row_format == ROW_TYPE_DEFAULT) {
row_format = ROW_TYPE_COMPRESSED;
} else if (row_format != ROW_TYPE_COMPRESSED) {
/* ROW_FORMAT other than COMPRESSED
ignores KEY_BLOCK_SIZE. It does not
make sense to reject conflicting
@ -6639,8 +6644,7 @@ ha_innobase::create(
such combinations can be obtained
with ALTER TABLE anyway. */
push_warning_printf(
thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: ignoring KEY_BLOCK_SIZE=%lu"
" unless ROW_FORMAT=COMPRESSED.",
@ -6649,7 +6653,7 @@ ha_innobase::create(
}
} else {
/* flags == 0 means no KEY_BLOCK_SIZE.*/
if (row_type == ROW_TYPE_COMPRESSED) {
if (row_format == ROW_TYPE_COMPRESSED) {
/* ROW_FORMAT=COMPRESSED without
KEY_BLOCK_SIZE implies half the
maximum KEY_BLOCK_SIZE. */
@ -6664,49 +6668,40 @@ ha_innobase::create(
}
}
switch (row_type) {
const char* row_format_name;
switch (row_format) {
case ROW_TYPE_REDUNDANT:
break;
case ROW_TYPE_COMPRESSED:
case ROW_TYPE_DYNAMIC:
row_format_name
= row_type == ROW_TYPE_COMPRESSED
? "COMPRESSED"
: "DYNAMIC";
if (!srv_file_per_table) {
push_warning_printf(
thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: ROW_FORMAT=%s"
" requires innodb_file_per_table.",
row_format_name);
"InnoDB: ROW_FORMAT=%s requires"
" innodb_file_per_table.",
get_row_format_name(row_format));
} else if (file_format < DICT_TF_FORMAT_ZIP) {
push_warning_printf(
thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: ROW_FORMAT=%s"
" requires innodb_file_format >"
" Antelope.",
row_format_name);
"InnoDB: ROW_FORMAT=%s requires"
" innodb_file_format > Antelope.",
get_row_format_name(row_format));
} else {
flags |= DICT_TF_COMPACT
| (DICT_TF_FORMAT_ZIP
<< DICT_TF_FORMAT_SHIFT);
| (DICT_TF_FORMAT_ZIP
<< DICT_TF_FORMAT_SHIFT);
break;
}
/* fall through */
case ROW_TYPE_NOT_USED:
case ROW_TYPE_FIXED:
default:
push_warning(thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: assuming ROW_FORMAT=COMPACT.");
case ROW_TYPE_PAGE:
push_warning(
thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: assuming ROW_FORMAT=COMPACT.");
case ROW_TYPE_DEFAULT:
case ROW_TYPE_COMPACT:
flags = DICT_TF_COMPACT;
@ -6820,23 +6815,25 @@ ha_innobase::create(
setup at this stage and so we use thd. */
/* We need to copy the AUTOINC value from the old table if
this is an ALTER TABLE or CREATE INDEX because CREATE INDEX
does a table copy too. */
this is an ALTER|OPTIMIZE TABLE or CREATE INDEX because CREATE INDEX
does a table copy too. If query was one of :
CREATE TABLE ...AUTO_INCREMENT = x; or
ALTER TABLE...AUTO_INCREMENT = x; or
OPTIMIZE TABLE t; or
CREATE INDEX x on t(...);
Find out a table definition from the dictionary and get
the current value of the auto increment field. Set a new
value to the auto increment field if the value is greater
than the maximum value in the column. */
if (((create_info->used_fields & HA_CREATE_USED_AUTO)
|| thd_sql_command(thd) == SQLCOM_ALTER_TABLE
|| thd_sql_command(thd) == SQLCOM_OPTIMIZE
|| thd_sql_command(thd) == SQLCOM_CREATE_INDEX)
&& create_info->auto_increment_value > 0) {
/* Query was one of :
CREATE TABLE ...AUTO_INCREMENT = x; or
ALTER TABLE...AUTO_INCREMENT = x; or
CREATE INDEX x on t(...);
Find out a table definition from the dictionary and get
the current value of the auto increment field. Set a new
value to the auto increment field if the value is greater
than the maximum value in the column. */
auto_inc_value = create_info->auto_increment_value;
dict_table_autoinc_lock(innobase_table);
@ -7344,6 +7341,7 @@ ha_innobase::estimate_rows_upper_bound(void)
dict_index_t* index;
ulonglong estimate;
ulonglong local_data_file_length;
ulint stat_n_leaf_pages;
DBUG_ENTER("estimate_rows_upper_bound");
@ -7363,10 +7361,12 @@ ha_innobase::estimate_rows_upper_bound(void)
index = dict_table_get_first_index(prebuilt->table);
ut_a(index->stat_n_leaf_pages > 0);
stat_n_leaf_pages = index->stat_n_leaf_pages;
ut_a(stat_n_leaf_pages > 0);
local_data_file_length =
((ulonglong) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE;
((ulonglong) stat_n_leaf_pages) * UNIV_PAGE_SIZE;
/* Calculate a minimum length for a clustered index record and from
@ -7565,7 +7565,9 @@ ha_innobase::info_low(
prebuilt->trx->op_info = "updating table statistics";
dict_update_statistics(ib_table);
dict_update_statistics(ib_table,
FALSE /* update even if stats
are initialized */);
prebuilt->trx->op_info = "returning various info to MySQL";
}
@ -7584,6 +7586,9 @@ ha_innobase::info_low(
}
if (flag & HA_STATUS_VARIABLE) {
dict_table_stats_lock(ib_table, RW_S_LATCH);
n_rows = ib_table->stat_n_rows;
/* Because we do not protect stat_n_rows by any mutex in a
@ -7633,6 +7638,8 @@ ha_innobase::info_low(
ib_table->stat_sum_of_other_index_sizes)
* UNIV_PAGE_SIZE;
dict_table_stats_unlock(ib_table, RW_S_LATCH);
/* Since fsp_get_available_space_in_free_extents() is
acquiring latches inside InnoDB, we do not call it if we
are asked by MySQL to avoid locking. Another reason to
@ -7649,19 +7656,12 @@ ha_innobase::info_low(
innodb_crash_recovery is set to a high value. */
stats.delete_length = 0;
} else {
/* lock the data dictionary to avoid races with
ibd_file_missing and tablespace_discarded */
row_mysql_lock_data_dictionary(prebuilt->trx);
ullint avail_space;
/* ib_table->space must be an existent tablespace */
if (!ib_table->ibd_file_missing
&& !ib_table->tablespace_discarded) {
stats.delete_length =
fsp_get_available_space_in_free_extents(
ib_table->space) * 1024;
} else {
avail_space = fsp_get_available_space_in_free_extents(
ib_table->space);
if (avail_space == ULLINT_UNDEFINED) {
THD* thd;
thd = ha_thd();
@ -7678,9 +7678,9 @@ ha_innobase::info_low(
ib_table->name);
stats.delete_length = 0;
} else {
stats.delete_length = avail_space * 1024;
}
row_mysql_unlock_data_dictionary(prebuilt->trx);
}
stats.check_time = 0;
@ -7711,6 +7711,8 @@ ha_innobase::info_low(
table->s->keys);
}
dict_table_stats_lock(ib_table, RW_S_LATCH);
for (i = 0; i < table->s->keys; i++) {
ulong j;
/* We could get index quickly through internal
@ -7748,8 +7750,6 @@ ha_innobase::info_low(
break;
}
dict_index_stat_mutex_enter(index);
if (index->stat_n_diff_key_vals[j + 1] == 0) {
rec_per_key = stats.records;
@ -7758,8 +7758,6 @@ ha_innobase::info_low(
index->stat_n_diff_key_vals[j + 1]);
}
dict_index_stat_mutex_exit(index);
/* Since MySQL seems to favor table scans
too much over index searches, we pretend
index selectivity is 2 times better than
@ -7776,6 +7774,8 @@ ha_innobase::info_low(
(ulong) rec_per_key;
}
}
dict_table_stats_unlock(ib_table, RW_S_LATCH);
}
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {