3833 Marko Mäkelä 2012-05-15
WL#6255 preparation: Split row_ins_index_entry(), row_ins_index_entry_low().
row_ins_clust_index_entry(): Insert a clustered index entry.
row_ins_sec_index_entry(): Insert a secondary index entry.
row_ins_clust_index_entry_low(): Insert a clustered index entry.
row_ins_sec_index_entry_low(): Insert a secondary index entry.
Remove the parameter foreign=TRUE from all functions and n_ext=0
from the insert into secondary index.
modified:
storage/innobase/ibuf/ibuf0ibuf.cc
storage/innobase/include/row0ins.h
storage/innobase/row/row0ins.cc
storage/innobase/row/row0upd.cc
3832 Marko Mäkelä 2012-05-15
Add function attributes.
modified:
storage/innobase/include/btr0cur.h
3831 Marko Mäkelä 2012-05-14
WL#6255: Allow ROW_FORMAT and KEY_BLOCK_SIZE to be changed in-place.
create_options_are_valid(): Rename to create_options_are_invalid(), and
change the return type from ibool to const char*.
INNOBASE_ONLINE_CREATE, INNOBASE_INPLACE_REBUILD: New sets of
supported in-place ALTER TABLE operations.
innobase_need_rebuild(): Determine if ALTER TABLE needs to rebuild the
table. We ignore other CHANGE_CREATE_OPTION flags than KEY_BLOCK_SIZE
and ROW_FORMAT.
ha_innobase::check_if_supported_inplace_alter(): Allow all
INNOBASE_INPLACE_REBUILD operations. Replace ADD_PK_INDEX with
INNOBASE_INPLACE_REBUILD.
innobase_create_key_defs(): Rebuild the clustered index for
INNOBASE_INPLACE_REBUILD.
ha_innobase::prepare_inplace_alter_table(): Call
create_options_are_invalid().
ha_innobase::inplace_alter_table(): If no other operations than
CHANGE_CREATE_OPTION are being performed and !innobase_need_rebuild(),
do nothing.
modified:
mysql-test/suite/innodb/r/innodb-create-options.result
mysql-test/suite/innodb/t/innodb-create-options.test
storage/innobase/handler/ha_innodb.cc
storage/innobase/handler/ha_innodb.h
storage/innobase/handler/handler0alter.cc
3830 Marko Mäkelä 2012-05-14
Branch mysql-trunk-wl6255 from mysql-trunk.
modified:
.bzr-mysql/default.conf
3829 Jorgen Loland 2012-05-14
Bug#11754168 list bug-id from new bug system instead of old bug
system in default.experimental
modified:
mysql-test/collections/default.experimental
=== modified file '.bzr-mysql/default.conf'
--- a/.bzr-mysql/default.conf revid:jorgen.loland@stripped20120514093058-4vd4gc1iosh2n6ba
+++ b/.bzr-mysql/default.conf revid:marko.makela@strippedpemt6kzrn
@@ -1,4 +1,4 @@
[MYSQL]
post_commit_to = "commits@stripped"
post_push_to = "commits@strippedl.com"
-tree_name = "mysql-trunk"
+tree_name = "mysql-trunk-wl6255"
=== modified file 'mysql-test/suite/innodb/r/innodb-create-options.result'
--- a/mysql-test/suite/innodb/r/innodb-create-options.result revid:jorgen.loland@oracle.com-20120514093058-4vd4gc1iosh2n6ba
+++ b/mysql-test/suite/innodb/r/innodb-create-options.result revid:marko.makela@stripped
@@ -46,11 +46,11 @@ SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTI
TABLE_NAME ROW_FORMAT CREATE_OPTIONS
t1 Compact
ALTER TABLE t1 ROW_FORMAT=FIXED KEY_BLOCK_SIZE=0;
-ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ROW_TYPE'
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: invalid ROW_FORMAT specifier.
-Error 1005 Can't create table '#sql-temporary' (errno: 1478)
+Error 1478 Table storage engine 'InnoDB' does not support the create option 'ROW_TYPE'
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1';
TABLE_NAME ROW_FORMAT CREATE_OPTIONS
t1 Compact
@@ -104,29 +104,29 @@ t1 Compressed KEY_BLOCK_SIZE=1
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 ( i INT );
ALTER TABLE t1 ROW_FORMAT=FIXED KEY_BLOCK_SIZE=1;
-ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ROW_TYPE'
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: invalid ROW_FORMAT specifier.
-Error 1005 Can't create table '#sql-temporary' (errno: 1478)
+Error 1478 Table storage engine 'InnoDB' does not support the create option 'ROW_TYPE'
ALTER TABLE t1 ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=2;
-ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE.
-Error 1005 Can't create table '#sql-temporary' (errno: 1478)
+Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
ALTER TABLE t1 ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=4;
-ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE.
-Error 1005 Can't create table '#sql-temporary' (errno: 1478)
+Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
ALTER TABLE t1 ROW_FORMAT=REDUNDANT KEY_BLOCK_SIZE=2;
-ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE.
-Error 1005 Can't create table '#sql-temporary' (errno: 1478)
+Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=1;
SHOW WARNINGS;
Level Code Message
@@ -146,11 +146,11 @@ SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTI
TABLE_NAME ROW_FORMAT CREATE_OPTIONS
t1 Compact row_format=COMPACT
ALTER TABLE t1 KEY_BLOCK_SIZE=2;
-ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE.
-Error 1005 Can't create table '#sql-temporary' (errno: 1478)
+Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
ALTER TABLE t1 ROW_FORMAT=REDUNDANT;
SHOW WARNINGS;
Level Code Message
@@ -158,11 +158,11 @@ SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTI
TABLE_NAME ROW_FORMAT CREATE_OPTIONS
t1 Redundant row_format=REDUNDANT
ALTER TABLE t1 KEY_BLOCK_SIZE=4;
-ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE.
-Error 1005 Can't create table '#sql-temporary' (errno: 1478)
+Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
ALTER TABLE t1 ROW_FORMAT=DYNAMIC;
SHOW WARNINGS;
Level Code Message
@@ -170,11 +170,11 @@ SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTI
TABLE_NAME ROW_FORMAT CREATE_OPTIONS
t1 Dynamic row_format=DYNAMIC
ALTER TABLE t1 KEY_BLOCK_SIZE=2;
-ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE.
-Error 1005 Can't create table '#sql-temporary' (errno: 1478)
+Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
ALTER TABLE t1 ROW_FORMAT=COMPRESSED;
SHOW WARNINGS;
Level Code Message
@@ -212,23 +212,23 @@ t1 CREATE TABLE `t1` (
`f1` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=2
ALTER TABLE t1 ROW_FORMAT=COMPACT;
-ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE.
-Error 1005 Can't create table '#sql-temporary' (errno: 1478)
+Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
ALTER TABLE t1 ROW_FORMAT=REDUNDANT;
-ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE.
-Error 1005 Can't create table '#sql-temporary' (errno: 1478)
+Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
ALTER TABLE t1 ROW_FORMAT=DYNAMIC;
-ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE.
-Error 1005 Can't create table '#sql-temporary' (errno: 1478)
+Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
ALTER TABLE t1 ROW_FORMAT=COMPRESSED;
SHOW WARNINGS;
Level Code Message
@@ -298,23 +298,23 @@ CREATE TABLE t1 ( i INT ) ROW_FORMAT=DEF
SHOW WARNINGS;
Level Code Message
ALTER TABLE t1 KEY_BLOCK_SIZE=2;
-ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
-Error 1005 Can't create table '#sql-temporary' (errno: 1478)
+Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
ALTER TABLE t1 ROW_FORMAT=COMPRESSED;
-ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT'
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_format > Antelope.
-Error 1005 Can't create table '#sql-temporary' (errno: 1478)
+Error 1478 Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT'
ALTER TABLE t1 ROW_FORMAT=DYNAMIC;
-ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT'
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope.
-Error 1005 Can't create table '#sql-temporary' (errno: 1478)
+Error 1478 Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT'
SET GLOBAL innodb_file_format=Barracuda;
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4;
@@ -375,23 +375,23 @@ CREATE TABLE t1 ( i INT ) ROW_FORMAT=DEF
SHOW WARNINGS;
Level Code Message
ALTER TABLE t1 KEY_BLOCK_SIZE=1;
-ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
-Error 1005 Can't create table '#sql-temporary' (errno: 1478)
+Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE'
ALTER TABLE t1 ROW_FORMAT=COMPRESSED;
-ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT'
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table.
-Error 1005 Can't create table '#sql-temporary' (errno: 1478)
+Error 1478 Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT'
ALTER TABLE t1 ROW_FORMAT=DYNAMIC;
-ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT'
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table.
-Error 1005 Can't create table '#sql-temporary' (errno: 1478)
+Error 1478 Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT'
ALTER TABLE t1 ROW_FORMAT=COMPACT;
SHOW WARNINGS;
Level Code Message
=== modified file 'mysql-test/suite/innodb/t/innodb-create-options.test'
--- a/mysql-test/suite/innodb/t/innodb-create-options.test revid:jorgen.loland@strippedom-20120514093058-4vd4gc1iosh2n6ba
+++ b/mysql-test/suite/innodb/t/innodb-create-options.test revid:marko.makela@oracle.com-20120515071932-5h01ee6pemt6kzrn
@@ -98,7 +98,7 @@ ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BL
SHOW WARNINGS;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1';
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
+--error ER_ILLEGAL_HA_CREATE_OPTION
ALTER TABLE t1 ROW_FORMAT=FIXED KEY_BLOCK_SIZE=0;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW WARNINGS;
@@ -137,22 +137,22 @@ SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTI
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 ( i INT );
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
+--error ER_ILLEGAL_HA_CREATE_OPTION
ALTER TABLE t1 ROW_FORMAT=FIXED KEY_BLOCK_SIZE=1;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW WARNINGS;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
+--error ER_ILLEGAL_HA_CREATE_OPTION
ALTER TABLE t1 ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=2;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW WARNINGS;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
+--error ER_ILLEGAL_HA_CREATE_OPTION
ALTER TABLE t1 ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=4;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW WARNINGS;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
+--error ER_ILLEGAL_HA_CREATE_OPTION
ALTER TABLE t1 ROW_FORMAT=REDUNDANT KEY_BLOCK_SIZE=2;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW WARNINGS;
@@ -169,7 +169,7 @@ DROP TABLE IF EXISTS t1;
CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPACT;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1';
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
+--error ER_ILLEGAL_HA_CREATE_OPTION
ALTER TABLE t1 KEY_BLOCK_SIZE=2;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW WARNINGS;
@@ -177,7 +177,7 @@ ALTER TABLE t1 ROW_FORMAT=REDUNDANT;
SHOW WARNINGS;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1';
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
+--error ER_ILLEGAL_HA_CREATE_OPTION
ALTER TABLE t1 KEY_BLOCK_SIZE=4;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW WARNINGS;
@@ -185,7 +185,7 @@ ALTER TABLE t1 ROW_FORMAT=DYNAMIC;
SHOW WARNINGS;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1';
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
+--error ER_ILLEGAL_HA_CREATE_OPTION
ALTER TABLE t1 KEY_BLOCK_SIZE=2;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW WARNINGS;
@@ -209,17 +209,17 @@ SHOW CREATE TABLE t1;
ALTER TABLE t1 ADD COLUMN f1 INT;
SHOW CREATE TABLE t1;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
+--error ER_ILLEGAL_HA_CREATE_OPTION
ALTER TABLE t1 ROW_FORMAT=COMPACT;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW WARNINGS;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
+--error ER_ILLEGAL_HA_CREATE_OPTION
ALTER TABLE t1 ROW_FORMAT=REDUNDANT;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW WARNINGS;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
+--error ER_ILLEGAL_HA_CREATE_OPTION
ALTER TABLE t1 ROW_FORMAT=DYNAMIC;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW WARNINGS;
@@ -264,17 +264,17 @@ DROP TABLE IF EXISTS t1;
CREATE TABLE t1 ( i INT ) ROW_FORMAT=DEFAULT;
SHOW WARNINGS;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
+--error ER_ILLEGAL_HA_CREATE_OPTION
ALTER TABLE t1 KEY_BLOCK_SIZE=2;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW WARNINGS;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
+--error ER_ILLEGAL_HA_CREATE_OPTION
ALTER TABLE t1 ROW_FORMAT=COMPRESSED;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW WARNINGS;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
+--error ER_ILLEGAL_HA_CREATE_OPTION
ALTER TABLE t1 ROW_FORMAT=DYNAMIC;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW WARNINGS;
@@ -319,17 +319,17 @@ DROP TABLE IF EXISTS t1;
CREATE TABLE t1 ( i INT ) ROW_FORMAT=DEFAULT;
SHOW WARNINGS;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
+--error ER_ILLEGAL_HA_CREATE_OPTION
ALTER TABLE t1 KEY_BLOCK_SIZE=1;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW WARNINGS;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
+--error ER_ILLEGAL_HA_CREATE_OPTION
ALTER TABLE t1 ROW_FORMAT=COMPRESSED;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW WARNINGS;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
+--error ER_ILLEGAL_HA_CREATE_OPTION
ALTER TABLE t1 ROW_FORMAT=DYNAMIC;
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW WARNINGS;
=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc revid:jorgen.loland@stripped-20120514093058-4vd4gc1iosh2n6ba
+++ b/storage/innobase/handler/ha_innodb.cc revid:marko.makela@stripped5071932-5h01ee6pemt6kzrn
@@ -8519,7 +8519,7 @@ get_row_format_name(
"InnoDB: ROW_FORMAT=%s requires" \
" innodb_file_per_table.", \
get_row_format_name(row_format)); \
- ret = FALSE; \
+ ret = "ROW_FORMAT"; \
}
/** If file-format is Antelope, issue warning and set ret false */
@@ -8531,7 +8531,7 @@ get_row_format_name(
"InnoDB: ROW_FORMAT=%s requires" \
" innodb_file_format > Antelope.", \
get_row_format_name(row_format)); \
- ret = FALSE; \
+ ret = "ROW_FORMAT"; \
}
@@ -8540,11 +8540,11 @@ Validates the create options. We may bui
in future. For now, it checks two specifiers:
KEY_BLOCK_SIZE and ROW_FORMAT
If innodb_strict_mode is not set then this function is a no-op
-@return TRUE if valid. */
-static
-ibool
-create_options_are_valid(
-/*=====================*/
+@return NULL if valid, string if not. */
+UNIV_INTERN
+const char*
+create_options_are_invalid(
+/*=======================*/
THD* thd, /*!< in: connection thread. */
TABLE* form, /*!< in: information on table
columns and indexes */
@@ -8552,14 +8552,14 @@ create_options_are_valid(
bool use_tablespace) /*!< in: srv_file_per_table */
{
ibool kbs_specified = FALSE;
- ibool ret = TRUE;
+ const char* ret = NULL;
enum row_type row_format = form->s->row_type;
ut_ad(thd != NULL);
/* If innodb_strict_mode is not set don't do any validation. */
if (!(THDVAR(thd, strict_mode))) {
- return(TRUE);
+ return(NULL);
}
ut_ad(form != NULL);
@@ -8582,7 +8582,7 @@ create_options_are_valid(
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: KEY_BLOCK_SIZE requires"
" innodb_file_per_table.");
- ret = FALSE;
+ ret = "KEY_BLOCK_SIZE";
}
if (srv_file_format < UNIV_FORMAT_B) {
push_warning(
@@ -8590,7 +8590,7 @@ create_options_are_valid(
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: KEY_BLOCK_SIZE requires"
" innodb_file_format > Antelope.");
- ret = FALSE;
+ ret = "KEY_BLOCK_SIZE";
}
/* The maximum KEY_BLOCK_SIZE (KBS) is 16. But if
@@ -8607,7 +8607,7 @@ create_options_are_valid(
" cannot be larger than %ld.",
create_info->key_block_size,
kbs_max);
- ret = FALSE;
+ ret = "KEY_BLOCK_SIZE";
}
break;
default:
@@ -8617,7 +8617,7 @@ create_options_are_valid(
"InnoDB: invalid KEY_BLOCK_SIZE = %lu."
" Valid values are [1, 2, 4, 8, 16]",
create_info->key_block_size);
- ret = FALSE;
+ ret = "KEY_BLOCK_SIZE";
break;
}
}
@@ -8642,7 +8642,7 @@ create_options_are_valid(
"InnoDB: cannot specify ROW_FORMAT = %s"
" with KEY_BLOCK_SIZE.",
get_row_format_name(row_format));
- ret = FALSE;
+ ret = "KEY_BLOCK_SIZE";
}
break;
case ROW_TYPE_DEFAULT:
@@ -8654,7 +8654,7 @@ create_options_are_valid(
thd, Sql_condition::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION, \
"InnoDB: invalid ROW_FORMAT specifier.");
- ret = FALSE;
+ ret = "ROW_TYPE";
break;
}
@@ -8991,7 +8991,7 @@ ha_innobase::create(
/* Create the table definition in InnoDB */
/* Validate create options if innodb_strict_mode is set. */
- if (!create_options_are_valid(
+ if (create_options_are_invalid(
thd, form, create_info, use_tablespace)) {
DBUG_RETURN(ER_ILLEGAL_HA_CREATE_OPTION);
}
=== modified file 'storage/innobase/handler/ha_innodb.h'
--- a/storage/innobase/handler/ha_innodb.h revid:jorgen.loland@stripped20514093058-4vd4gc1iosh2n6ba
+++ b/storage/innobase/handler/ha_innodb.h revid:marko.makela@stripped32-5h01ee6pemt6kzrn
@@ -492,6 +492,23 @@ innobase_table_flags(
ulint* flags2) /*!< out: DICT_TF2 flags */
__attribute__((nonnull, warn_unused_result));
+/*****************************************************************//**
+Validates the create options. We may build on this function
+in future. For now, it checks two specifiers:
+KEY_BLOCK_SIZE and ROW_FORMAT
+If innodb_strict_mode is not set then this function is a no-op
+@return NULL if valid, string if not. */
+UNIV_INTERN
+const char*
+create_options_are_invalid(
+/*=======================*/
+ THD* thd, /*!< in: connection thread. */
+ TABLE* form, /*!< in: information on table
+ columns and indexes */
+ HA_CREATE_INFO* create_info, /*!< in: create info. */
+ bool use_tablespace) /*!< in: srv_file_per_table */
+ __attribute__((nonnull, warn_unused_result));
+
/*********************************************************************//**
Retrieve the FTS Relevance Ranking result for doc with doc_id
of prebuilt->fts_doc_id
=== modified file 'storage/innobase/handler/handler0alter.cc'
--- a/storage/innobase/handler/handler0alter.cc revid:jorgen.loland@oracle.com-20120514093058-4vd4gc1iosh2n6ba
+++ b/storage/innobase/handler/handler0alter.cc revid:marko.makela@oracle.com-20120515071932-5h01ee6pemt6kzrn
@@ -44,16 +44,35 @@ Smart ALTER TABLE
#include "ha_innodb.h"
/** Operations for creating an index in place */
-static const Alter_inplace_info::HA_ALTER_FLAGS INNOBASE_INPLACE_CREATE
+static const Alter_inplace_info::HA_ALTER_FLAGS INNOBASE_ONLINE_CREATE
= Alter_inplace_info::ADD_INDEX
- | Alter_inplace_info::ADD_UNIQUE_INDEX
- | Alter_inplace_info::ADD_PK_INDEX;// not online
+ | Alter_inplace_info::ADD_UNIQUE_INDEX;
+
+/** Operations for rebuilding a table in place */
+static const Alter_inplace_info::HA_ALTER_FLAGS INNOBASE_INPLACE_REBUILD
+ = Alter_inplace_info::ADD_PK_INDEX
+ | Alter_inplace_info::CHANGE_CREATE_OPTION
+ /*
+ | Alter_inplace_info::ALTER_COLUMN_NULLABLE
+ | Alter_inplace_info::ALTER_COLUMN_NOT_NULLABLE
+ | Alter_inplace_info::ALTER_COLUMN_TYPE
+ | Alter_inplace_info::ALTER_COLUMN_EQUAL_PACK_LENGTH,
+ | Alter_inplace_info::ALTER_COLUMN_ORDER
+ | Alter_inplace_info::ADD_COLUMN
+ | Alter_inplace_info::DROP_COLUMN
+ */
+ ;
+
+/** Operations for creating indexes or rebuilding a table */
+static const Alter_inplace_info::HA_ALTER_FLAGS INNOBASE_INPLACE_CREATE
+ = INNOBASE_ONLINE_CREATE | INNOBASE_INPLACE_REBUILD;
/** Operations for altering a table that InnoDB does not care about */
static const Alter_inplace_info::HA_ALTER_FLAGS INNOBASE_INPLACE_IGNORE
= Alter_inplace_info::ALTER_COLUMN_DEFAULT
- | Alter_inplace_info::ALTER_RENAME
- | Alter_inplace_info::CHANGE_CREATE_OPTION;
+ | Alter_inplace_info::ALTER_COLUMN_COLUMN_FORMAT
+ | Alter_inplace_info::ALTER_COLUMN_STORAGE_TYPE
+ | Alter_inplace_info::ALTER_RENAME;
/** Operations that InnoDB can perform online */
static const Alter_inplace_info::HA_ALTER_FLAGS INNOBASE_ONLINE_OPERATIONS
@@ -135,6 +154,29 @@ my_error_innodb(
}
}
+/*******************************************************************//**
+Determine if ALTER TABLE needs to rebuild the table.
+@param ha_alter_info the DDL operation
+@return whether it is necessary to rebuild the table */
+static __attribute__((nonnull, warn_unused_result))
+bool
+innobase_need_rebuild(
+/*==================*/
+ const Alter_inplace_info* ha_alter_info)
+{
+ if (ha_alter_info->handler_flags
+ == Alter_inplace_info::CHANGE_CREATE_OPTION
+ && !(ha_alter_info->create_info->used_fields
+ & (HA_CREATE_USED_ROW_FORMAT
+ | HA_CREATE_USED_KEY_BLOCK_SIZE))) {
+ /* Any other CHANGE_CREATE_OPTION than changing
+ ROW_FORMAT or KEY_BLOCK_SIZE is ignored. */
+ return(false);
+ }
+
+ return(!!(ha_alter_info->handler_flags & INNOBASE_INPLACE_REBUILD));
+}
+
/** Check if InnoDB supports a particular alter table in-place
@param altered_table TABLE object for new version of table.
@param ha_alter_info Structure describing changes to be done
@@ -161,30 +203,11 @@ ha_innobase::check_if_supported_inplace_
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
}
- HA_CREATE_INFO* create_info = ha_alter_info->create_info;
-
if (ha_alter_info->handler_flags
- & ~(INNOBASE_ONLINE_OPERATIONS
- | Alter_inplace_info::ADD_PK_INDEX)) {
+ & ~(INNOBASE_ONLINE_OPERATIONS | INNOBASE_INPLACE_REBUILD)) {
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
}
- if (ha_alter_info->handler_flags
- & Alter_inplace_info::CHANGE_CREATE_OPTION) {
- /* Changing ROW_FORMAT or KEY_BLOCK_SIZE should
- rebuild the table. TODO: copy index-by-index instead
- of row-by-row. */
-
- if (create_info->used_fields & HA_CREATE_USED_ROW_FORMAT
- && create_info->row_type != get_row_type()) {
- DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
- }
-
- if (create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE) {
- DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
- }
- }
-
if (!(ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE)) {
DBUG_RETURN(HA_ALTER_INPLACE_NO_LOCK);
}
@@ -254,14 +277,9 @@ ha_innobase::check_if_supported_inplace_
prebuilt->trx->will_lock++;
- /* TODO: Reject if creating a fulltext index and there is an
- incompatible FTS_DOC_ID or FTS_DOC_ID_INDEX, either in the table
- or in the ha_alter_info. We can and should reject this before
- locking the data dictionary. */
-
- /* Creating the primary key requires an exclusive lock on the
+ /* Rebuilding the clustered index requires an exclusive lock on the
table during the whole copying operation. */
- if (ha_alter_info->handler_flags & Alter_inplace_info::ADD_PK_INDEX) {
+ if (innobase_need_rebuild(ha_alter_info)) {
DBUG_RETURN(HA_ALTER_INPLACE_EXCLUSIVE_LOCK);
}
@@ -934,7 +952,7 @@ innobase_create_key_defs(
definitions are allocated */
const Alter_inplace_info* ha_alter_info,
/*!< in: alter operation */
- const TABLE* altered_table,
+ const TABLE* altered_table,
/*!< in: MySQL table that is being altered */
ulint& n_add,
/*!< in/out: number of indexes to be created */
@@ -970,20 +988,21 @@ innobase_create_key_defs(
/* If there is a primary key, it is always the first index
defined for the innodb_table. */
- new_primary = !my_strcasecmp(system_charset_info,
- key_info[*add].name, "PRIMARY");
+ new_primary = n_add > 0
+ && !my_strcasecmp(system_charset_info,
+ key_info[*add].name, "PRIMARY");
/* If there is a UNIQUE INDEX consisting entirely of NOT NULL
columns and if the index does not contain column prefix(es)
(only prefix/part of the column is indexed), MySQL will treat the
index as a PRIMARY KEY unless the table already has one. */
- if (!new_primary && got_default_clust
+ if (n_add > 0 && !new_primary && got_default_clust
&& (key_info[*add].flags & HA_NOSAME)
&& !(key_info[*add].flags & HA_KEY_HAS_PART_KEY_SEG)) {
uint key_part = key_info[*add].key_parts;
- new_primary = TRUE;
+ new_primary = true;
while (key_part--) {
const uint maybe_null
@@ -994,38 +1013,33 @@ innobase_create_key_defs(
field->null_ptr);
if (maybe_null) {
- new_primary = FALSE;
+ new_primary = false;
break;
}
}
}
- if (new_primary || add_fts_doc_id) {
+ if (new_primary || add_fts_doc_id
+ || innobase_need_rebuild(ha_alter_info)) {
ulint primary_key_number;
if (new_primary) {
+ DBUG_ASSERT(n_add > 0);
primary_key_number = *add;
- } else if (add_fts_doc_id) {
- /* If DICT_TF2_FTS_ADD_DOC_ID is set, we will need to
- rebuild the table to add the unique Doc ID column for
- FTS index. And thus the clustered index would required
- to be rebuilt. */
-
- if (got_default_clust) {
- /* Create the GEN_CLUST_INDEX */
- merge_index_def_t* index = indexdef++;
-
- index->fields = NULL;
- index->n_fields = 0;
- index->ind_type = DICT_CLUSTERED;
- index->name = mem_heap_strdup(
- heap, innobase_index_reserve_name);
- index->key_number = ~0;
- primary_key_number = ULINT_UNDEFINED;
- goto created_clustered;
- } else {
- primary_key_number = 0;
- }
+ } else if (got_default_clust) {
+ /* Create the GEN_CLUST_INDEX */
+ merge_index_def_t* index = indexdef++;
+
+ index->fields = NULL;
+ index->n_fields = 0;
+ index->ind_type = DICT_CLUSTERED;
+ index->name = mem_heap_strdup(
+ heap, innobase_index_reserve_name);
+ index->key_number = ~0;
+ primary_key_number = ULINT_UNDEFINED;
+ goto created_clustered;
+ } else {
+ primary_key_number = 0;
}
/* Create the PRIMARY key index definition */
@@ -1433,7 +1447,7 @@ prepare_inplace_alter_table_dict(
be exclusively locked when a full-text index is being created. */
DBUG_ASSERT(!!new_clustered
== ((ha_alter_info->handler_flags
- & Alter_inplace_info::ADD_PK_INDEX)
+ & INNOBASE_INPLACE_REBUILD)
|| add_fts_doc_id));
/* Allocate memory for dictionary index definitions */
@@ -1674,8 +1688,7 @@ col_fail:
will be exclusively locked anyway, the modification
log is unnecessary. */
if (!exclusive && !num_fts_index
- && !(ha_alter_info->handler_flags
- & ~INNOBASE_ONLINE_OPERATIONS)
+ && !innobase_need_rebuild(ha_alter_info)
&& !user_table->ibd_file_missing
&& !user_table->tablespace_discarded) {
DBUG_EXECUTE_IF("innodb_OOM_prepare_inplace_alter",
@@ -1924,19 +1937,33 @@ ha_innobase::prepare_inplace_alter_table
}
#endif /* UNIV_DEBUG */
+ ut_d(mutex_enter(&dict_sys->mutex));
+ ut_d(dict_table_check_for_dup_indexes(
+ prebuilt->table, CHECK_ABORTED_OK));
+ ut_d(mutex_exit(&dict_sys->mutex));
+
if (!(ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE)) {
/* Nothing to do */
goto func_exit;
}
- ut_d(mutex_enter(&dict_sys->mutex));
- ut_d(dict_table_check_for_dup_indexes(
- prebuilt->table, CHECK_ABORTED_OK));
- ut_d(mutex_exit(&dict_sys->mutex));
+ if (ha_alter_info->handler_flags
+ == Alter_inplace_info::CHANGE_CREATE_OPTION
+ && !innobase_need_rebuild(ha_alter_info)) {
+ goto func_exit;
+ }
- /* In case MySQL calls this in the middle of a SELECT query, release
- possible adaptive hash latch to avoid deadlocks of threads. */
- trx_search_latch_release_if_reserved(prebuilt->trx);
+ if (ha_alter_info->handler_flags
+ & Alter_inplace_info::CHANGE_CREATE_OPTION) {
+ if (const char* invalid_opt = create_options_are_invalid(
+ user_thd, altered_table,
+ ha_alter_info->create_info,
+ prebuilt->table->space != 0)) {
+ my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
+ table_type(), invalid_opt);
+ DBUG_RETURN(true);
+ }
+ }
/* Check if any index name is reserved. */
if (innobase_index_name_is_reserved(
@@ -2385,6 +2412,12 @@ ok_exit:
DBUG_RETURN(false);
}
+ if (ha_alter_info->handler_flags
+ == Alter_inplace_info::CHANGE_CREATE_OPTION
+ && !innobase_need_rebuild(ha_alter_info)) {
+ goto ok_exit;
+ }
+
class ha_innobase_inplace_ctx* ctx
= static_cast<class ha_innobase_inplace_ctx*>
(ha_alter_info->handler_ctx);
=== modified file 'storage/innobase/ibuf/ibuf0ibuf.cc'
--- a/storage/innobase/ibuf/ibuf0ibuf.cc revid:jorgen.loland@stripped093058-4vd4gc1iosh2n6ba
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc revid:marko.makela@strippedee6pemt6kzrn
@@ -3939,7 +3939,7 @@ ibuf_set_del_mark(
/* Delete mark the old index record. According to a
comment in row_upd_sec_index_entry(), it can already
have been delete marked if a lock wait occurred in
- row_ins_index_entry() in a previous invocation of
+ row_ins_sec_index_entry() in a previous invocation of
row_upd_sec_index_entry(). */
if (UNIV_LIKELY
=== modified file 'storage/innobase/include/btr0cur.h'
--- a/storage/innobase/include/btr0cur.h revid:jorgen.loland@stripped120514093058-4vd4gc1iosh2n6ba
+++ b/storage/innobase/include/btr0cur.h revid:marko.makela@stripped2-5h01ee6pemt6kzrn
@@ -220,11 +220,12 @@ btr_cur_optimistic_insert(
NULL */
ulint n_ext, /*!< in: number of externally stored columns */
que_thr_t* thr, /*!< in: query thread or NULL */
- mtr_t* mtr); /*!< in: mtr; if this function returns
+ mtr_t* mtr) /*!< in: mtr; if this function returns
DB_SUCCESS on a leaf page of a secondary
index in a compressed tablespace, the
mtr must be committed before latching
any further pages */
+ __attribute__((nonnull(2,3,4,5,8), warn_unused_result));
/*************************************************************//**
Performs an insert on a page of an index tree. It is assumed that mtr
holds an x-latch on the tree and on the cursor page. If the insert is
@@ -251,7 +252,8 @@ btr_cur_pessimistic_insert(
NULL */
ulint n_ext, /*!< in: number of externally stored columns */
que_thr_t* thr, /*!< in: query thread or NULL */
- mtr_t* mtr); /*!< in: mtr */
+ mtr_t* mtr) /*!< in: mtr */
+ __attribute__((nonnull(2,3,4,5,8), warn_unused_result));
/*************************************************************//**
See if there is enough place in the page modification log to log
an update-in-place.
=== modified file 'storage/innobase/include/row0ins.h'
--- a/storage/innobase/include/row0ins.h revid:jorgen.loland@strippedm-20120514093058-4vd4gc1iosh2n6ba
+++ b/storage/innobase/include/row0ins.h revid:marko.makela@stripped71932-5h01ee6pemt6kzrn
@@ -75,20 +75,32 @@ ins_node_set_new_row(
ins_node_t* node, /*!< in: insert node */
dtuple_t* row); /*!< in: new row (or first row) for the node */
/***************************************************************//**
-Inserts an index entry to index. Tries first optimistic, then pessimistic
-descent down the tree. If the entry matches enough to a delete marked record,
-performs the insert by updating or delete unmarking the delete marked
-record.
+Inserts an entry into a clustered index. Tries first optimistic,
+then pessimistic descent down the tree. If the entry matches enough
+to a delete marked record, performs the insert by updating or delete
+unmarking the delete marked record.
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DUPLICATE_KEY, or some other error code */
UNIV_INTERN
dberr_t
-row_ins_index_entry(
-/*================*/
- dict_index_t* index, /*!< in: index */
+row_ins_clust_index_entry(
+/*======================*/
+ dict_index_t* index, /*!< in: clustered index */
+ dtuple_t* entry, /*!< in/out: index entry to insert */
+ que_thr_t* thr, /*!< in: query thread */
+ ulint n_ext) /*!< in: number of externally stored columns */
+ __attribute__((nonnull, warn_unused_result));
+/***************************************************************//**
+Inserts an entry into a secondary index. Tries first optimistic,
+then pessimistic descent down the tree. If the entry matches enough
+to a delete marked record, performs the insert by updating or delete
+unmarking the delete marked record.
+@return DB_SUCCESS, DB_LOCK_WAIT, DB_DUPLICATE_KEY, or some other error code */
+UNIV_INTERN
+dberr_t
+row_ins_sec_index_entry(
+/*====================*/
+ dict_index_t* index, /*!< in: secondary index */
dtuple_t* entry, /*!< in/out: index entry to insert */
- ulint n_ext, /*!< in: number of externally stored columns */
- ibool foreign,/*!< in: TRUE=check foreign key constraints
- (foreign=FALSE only during CREATE INDEX) */
que_thr_t* thr) /*!< in: query thread */
__attribute__((nonnull, warn_unused_result));
/***************************************************************//**
=== modified file 'storage/innobase/row/row0ins.cc'
--- a/storage/innobase/row/row0ins.cc revid:jorgen.loland@strippedc1iosh2n6ba
+++ b/storage/innobase/row/row0ins.cc revid:marko.makela@stripped
@@ -2120,32 +2120,27 @@ row_ins_must_modify_rec(
}
/***************************************************************//**
-Tries to insert an index entry to an index. If the index is clustered
-and a record with the same unique key is found, the other record is
-necessarily marked deleted by a committed transaction, or a unique key
-violation error occurs. The delete marked record is then updated to an
-existing record, and we must write an undo log record on the delete
-marked record. If the index is secondary, and a record with exactly the
-same fields is found, the other record is necessarily marked deleted.
-It is then unmarked. Otherwise, the entry is just inserted to the index.
-@return DB_SUCCESS, DB_LOCK_WAIT, DB_FAIL if pessimistic retry needed,
-or error code */
+Tries to insert an entry into a clustered index. If a record with the
+same unique key is found, the other record is necessarily marked
+deleted by a committed transaction, or a unique key violation error
+occurs. The delete marked record is then updated to an existing
+record, and we must write an undo log record on the delete marked
+record.
+@return DB_SUCCESS, DB_LOCK_WAIT, DB_FAIL if pessimistic
+retry needed, or error code */
static __attribute__((nonnull, warn_unused_result))
dberr_t
-row_ins_index_entry_low(
-/*====================*/
+row_ins_clust_index_entry_low(
+/*==========================*/
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
depending on whether we wish optimistic or
pessimistic descent down the index tree */
- dict_index_t* index, /*!< in: index */
+ dict_index_t* index, /*!< in: clustered index */
dtuple_t* entry, /*!< in/out: index entry to insert */
ulint n_ext, /*!< in: number of externally stored columns */
que_thr_t* thr) /*!< in: query thread */
{
btr_cur_t cursor;
- ulint search_mode;
- ibool modify = FALSE;
- rec_t* insert_rec;
rec_t* rec;
ulint* offsets;
dberr_t err;
@@ -2154,6 +2149,8 @@ row_ins_index_entry_low(
mtr_t mtr;
mem_heap_t* heap = NULL;
+ ut_ad(dict_index_is_clust(index));
+
log_free_check();
mtr_start(&mtr);
@@ -2164,28 +2161,9 @@ row_ins_index_entry_low(
the function will return in both low_match and up_match of the
cursor sensible values */
- if (dict_index_is_clust(index)) {
- search_mode = mode;
- } else if (!(thr_get_trx(thr)->check_unique_secondary)) {
- search_mode = mode | BTR_INSERT | BTR_IGNORE_SEC_UNIQUE;
- } else {
- search_mode = mode | BTR_INSERT;
- }
-
- btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
- search_mode,
+ btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, mode,
&cursor, 0, __FILE__, __LINE__, &mtr);
- if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) {
- /* The insertion was made to the insert buffer already during
- the search: we are done */
-
- ut_ad(search_mode & BTR_INSERT);
- err = DB_SUCCESS;
-
- goto function_exit;
- }
-
#ifdef UNIV_DEBUG
{
page_t* page = btr_cur_get_page(&cursor);
@@ -2203,126 +2181,98 @@ row_ins_index_entry_low(
if (dict_index_is_unique(index) && (cursor.up_match >= n_unique
|| cursor.low_match >= n_unique)) {
- if (dict_index_is_clust(index)) {
- /* Note that the following may return also
- DB_LOCK_WAIT */
-
- err = row_ins_duplicate_error_in_clust(
- &cursor, entry, thr, &mtr);
- if (err != DB_SUCCESS) {
-
- goto function_exit;
- }
- } else {
- mtr_commit(&mtr);
- err = row_ins_scan_sec_index_for_duplicate(
- index, entry, thr);
- mtr_start(&mtr);
+ /* Note that the following may return also
+ DB_LOCK_WAIT */
- if (err != DB_SUCCESS) {
- goto function_exit;
- }
+ err = row_ins_duplicate_error_in_clust(
+ &cursor, entry, thr, &mtr);
+ if (err != DB_SUCCESS) {
- /* We did not find a duplicate and we have now
- locked with s-locks the necessary records to
- prevent any insertion of a duplicate by another
- transaction. Let us now reposition the cursor and
- continue the insertion. */
-
- btr_cur_search_to_nth_level(index, 0, entry,
- PAGE_CUR_LE,
- mode | BTR_INSERT,
- &cursor, 0,
- __FILE__, __LINE__, &mtr);
+ goto function_exit;
}
}
- modify = row_ins_must_modify_rec(&cursor);
-
- if (modify) {
+ if (row_ins_must_modify_rec(&cursor)) {
/* There is already an index entry with a long enough common
prefix, we must convert the insert into a modify of an
existing record */
- if (dict_index_is_clust(index)) {
- err = row_ins_clust_index_entry_by_modify(
- mode, &cursor, &heap, &big_rec, entry,
- thr, &mtr);
-
- if (big_rec) {
- ut_a(err == DB_SUCCESS);
- /* Write out the externally stored
- columns while still x-latching
- index->lock and block->lock. Allocate
- pages for big_rec in the mtr that
- modified the B-tree, but be sure to skip
- any pages that were freed in mtr. We will
- write out the big_rec pages before
- committing the B-tree mini-transaction. If
- the system crashes so that crash recovery
- will not replay the mtr_commit(&mtr), the
- big_rec pages will be left orphaned until
- the pages are allocated for something else.
-
- TODO: If the allocation extends the
- tablespace, it will not be redo
- logged, in either mini-transaction.
- Tablespace extension should be
- redo-logged in the big_rec
- mini-transaction, so that recovery
- will not fail when the big_rec was
- written to the extended portion of the
- file, in case the file was somehow
- truncated in the crash. */
-
- rec = btr_cur_get_rec(&cursor);
- offsets = rec_get_offsets(
- rec, index, NULL,
- ULINT_UNDEFINED, &heap);
-
- DEBUG_SYNC_C_IF_THD(
- thr_get_trx(thr)->mysql_thd,
- "before_row_ins_upd_extern");
- err = btr_store_big_rec_extern_fields(
- index, btr_cur_get_block(&cursor),
- rec, offsets, big_rec, &mtr,
- BTR_STORE_INSERT_UPDATE);
- DEBUG_SYNC_C_IF_THD(
- thr_get_trx(thr)->mysql_thd,
- "after_row_ins_upd_extern");
- /* If writing big_rec fails (for
- example, because of DB_OUT_OF_FILE_SPACE),
- the record will be corrupted. Even if
- we did not update any externally
- stored columns, our update could cause
- the record to grow so that a
- non-updated column was selected for
- external storage. This non-update
- would not have been written to the
- undo log, and thus the record cannot
- be rolled back.
-
- However, because we have not executed
- mtr_commit(mtr) yet, the update will
- not be replayed in crash recovery, and
- the following assertion failure will
- effectively "roll back" the operation. */
- ut_a(err == DB_SUCCESS);
- mtr_commit(&mtr);
- goto stored_big_rec;
- }
- } else {
- ut_ad(!n_ext);
- err = row_ins_sec_index_entry_by_modify(
- mode, &cursor, entry, thr, &mtr);
+ err = row_ins_clust_index_entry_by_modify(
+ mode, &cursor, &heap, &big_rec, entry,
+ thr, &mtr);
+
+ if (big_rec) {
+ ut_a(err == DB_SUCCESS);
+ /* Write out the externally stored
+ columns while still x-latching
+ index->lock and block->lock. Allocate
+ pages for big_rec in the mtr that
+ modified the B-tree, but be sure to skip
+ any pages that were freed in mtr. We will
+ write out the big_rec pages before
+ committing the B-tree mini-transaction. If
+ the system crashes so that crash recovery
+ will not replay the mtr_commit(&mtr), the
+ big_rec pages will be left orphaned until
+ the pages are allocated for something else.
+
+ TODO: If the allocation extends the
+ tablespace, it will not be redo
+ logged, in either mini-transaction.
+ Tablespace extension should be
+ redo-logged in the big_rec
+ mini-transaction, so that recovery
+ will not fail when the big_rec was
+ written to the extended portion of the
+ file, in case the file was somehow
+ truncated in the crash. */
+
+ rec = btr_cur_get_rec(&cursor);
+ offsets = rec_get_offsets(
+ rec, index, NULL,
+ ULINT_UNDEFINED, &heap);
+
+ DEBUG_SYNC_C_IF_THD(
+ thr_get_trx(thr)->mysql_thd,
+ "before_row_ins_upd_extern");
+ err = btr_store_big_rec_extern_fields(
+ index, btr_cur_get_block(&cursor),
+ rec, offsets, big_rec, &mtr,
+ BTR_STORE_INSERT_UPDATE);
+ DEBUG_SYNC_C_IF_THD(
+ thr_get_trx(thr)->mysql_thd,
+ "after_row_ins_upd_extern");
+ /* If writing big_rec fails (for
+ example, because of DB_OUT_OF_FILE_SPACE),
+ the record will be corrupted. Even if
+ we did not update any externally
+ stored columns, our update could cause
+ the record to grow so that a
+ non-updated column was selected for
+ external storage. This non-update
+ would not have been written to the
+ undo log, and thus the record cannot
+ be rolled back.
+
+ However, because we have not executed
+ mtr_commit(mtr) yet, the update will
+ not be replayed in crash recovery, and
+ the following assertion failure will
+ effectively "roll back" the operation. */
+ ut_a(err == DB_SUCCESS);
+ mtr_commit(&mtr);
+ dtuple_big_rec_free(big_rec);
+ goto stored_big_rec;
}
} else {
+ rec_t* insert_rec;
+
if (mode == BTR_MODIFY_LEAF) {
err = btr_cur_optimistic_insert(
0, &cursor, entry, &insert_rec, &big_rec,
n_ext, thr, &mtr);
} else {
- ut_a(mode == BTR_MODIFY_TREE);
+ ut_ad(mode == BTR_MODIFY_TREE);
if (buf_LRU_buf_pool_running_out()) {
err = DB_LOCK_TABLE_FULL;
@@ -2345,17 +2295,139 @@ function_exit:
err = row_ins_index_entry_big_rec(
entry, big_rec, NULL, &heap, index,
thr_get_trx(thr)->mysql_thd, __FILE__, __LINE__);
+ dtuple_convert_back_big_rec(index, entry, big_rec);
+ }
stored_big_rec:
- if (modify) {
- dtuple_big_rec_free(big_rec);
- } else {
- dtuple_convert_back_big_rec(index, entry, big_rec);
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+ return(err);
+}
+
+/***************************************************************//**
+Tries to insert an entry into a secondary index. If a record with exactly the
+same fields is found, the other record is necessarily marked deleted.
+It is then unmarked. Otherwise, the entry is just inserted to the index.
+@return DB_SUCCESS, DB_LOCK_WAIT, DB_FAIL if pessimistic retry needed,
+or error code */
+static __attribute__((nonnull, warn_unused_result))
+dberr_t
+row_ins_sec_index_entry_low(
+/*========================*/
+ ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
+ depending on whether we wish optimistic or
+ pessimistic descent down the index tree */
+ dict_index_t* index, /*!< in: secondary index */
+ dtuple_t* entry, /*!< in/out: index entry to insert */
+ que_thr_t* thr) /*!< in: query thread */
+{
+ btr_cur_t cursor;
+ ulint search_mode;
+ dberr_t err;
+ ulint n_unique;
+ mtr_t mtr;
+
+ ut_ad(!dict_index_is_clust(index));
+ ut_ad(!dict_index_is_online_ddl(index));
+
+ log_free_check();
+
+ mtr_start(&mtr);
+
+ cursor.thr = thr;
+
+ /* Note that we use PAGE_CUR_LE as the search mode, because then
+ the function will return in both low_match and up_match of the
+ cursor sensible values */
+
+ if (!thr_get_trx(thr)->check_unique_secondary) {
+ search_mode = mode | BTR_INSERT | BTR_IGNORE_SEC_UNIQUE;
+ } else {
+ search_mode = mode | BTR_INSERT;
+ }
+
+ btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
+ search_mode,
+ &cursor, 0, __FILE__, __LINE__, &mtr);
+
+ if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) {
+ /* The insert was buffered during the search: we are done */
+
+ err = DB_SUCCESS;
+
+ goto function_exit;
+ }
+
+#ifdef UNIV_DEBUG
+ {
+ page_t* page = btr_cur_get_page(&cursor);
+ rec_t* first_rec = page_rec_get_next(
+ page_get_infimum_rec(page));
+
+ ut_ad(page_rec_is_supremum(first_rec)
+ || rec_get_n_fields(first_rec, index)
+ == dtuple_get_n_fields(entry));
+ }
+#endif
+
+ n_unique = dict_index_get_n_unique(index);
+
+ if (dict_index_is_unique(index) && (cursor.up_match >= n_unique
+ || cursor.low_match >= n_unique)) {
+
+ mtr_commit(&mtr);
+ err = row_ins_scan_sec_index_for_duplicate(index, entry, thr);
+ mtr_start(&mtr);
+
+ if (err != DB_SUCCESS) {
+ goto function_exit;
}
+
+ /* We did not find a duplicate and we have now
+ locked with s-locks the necessary records to
+ prevent any insertion of a duplicate by another
+ transaction. Let us now reposition the cursor and
+ continue the insertion. */
+
+ btr_cur_search_to_nth_level(index, 0, entry,
+ PAGE_CUR_LE,
+ mode | BTR_INSERT,
+ &cursor, 0,
+ __FILE__, __LINE__, &mtr);
}
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
+ if (row_ins_must_modify_rec(&cursor)) {
+ /* There is already an index entry with a long enough common
+ prefix, we must convert the insert into a modify of an
+ existing record */
+
+ err = row_ins_sec_index_entry_by_modify(
+ mode, &cursor, entry, thr, &mtr);
+ } else {
+ rec_t* insert_rec;
+ big_rec_t* big_rec;
+
+ if (mode == BTR_MODIFY_LEAF) {
+ err = btr_cur_optimistic_insert(
+ 0, &cursor, entry, &insert_rec,
+ &big_rec, 0, thr, &mtr);
+ } else {
+ ut_ad(mode == BTR_MODIFY_TREE);
+ if (buf_LRU_buf_pool_running_out()) {
+
+ err = DB_LOCK_TABLE_FULL;
+ } else {
+ err = btr_cur_pessimistic_insert(
+ 0, &cursor, entry, &insert_rec,
+ &big_rec, 0, thr, &mtr);
+ }
+ }
+
+ ut_ad(!big_rec);
}
+
+function_exit:
+ mtr_commit(&mtr);
return(err);
}
@@ -2407,28 +2479,63 @@ row_ins_index_entry_big_rec_func(
}
/***************************************************************//**
-Inserts an index entry to index. Tries first optimistic, then pessimistic
-descent down the tree. If the entry matches enough to a delete marked record,
-performs the insert by updating or delete unmarking the delete marked
-record.
+Inserts an entry into a clustered index. Tries first optimistic,
+then pessimistic descent down the tree. If the entry matches enough
+to a delete marked record, performs the insert by updating or delete
+unmarking the delete marked record.
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DUPLICATE_KEY, or some other error code */
UNIV_INTERN
dberr_t
-row_ins_index_entry(
-/*================*/
- dict_index_t* index, /*!< in: index */
+row_ins_clust_index_entry(
+/*======================*/
+ dict_index_t* index, /*!< in: clustered index */
dtuple_t* entry, /*!< in/out: index entry to insert */
- ulint n_ext, /*!< in: number of externally stored columns */
- ibool foreign,/*!< in: TRUE=check foreign key constraints
- (foreign=FALSE only during CREATE INDEX) */
- que_thr_t* thr) /*!< in: query thread */
+ que_thr_t* thr, /*!< in: query thread */
+ ulint n_ext) /*!< in: number of externally stored columns */
{
dberr_t err;
- /* Only clustered indexes may contain externally stored columns. */
- ut_ad(dict_index_is_clust(index) || !n_ext);
+ if (UT_LIST_GET_FIRST(index->table->foreign_list)) {
+ err = row_ins_check_foreign_constraints(
+ index->table, index, entry, thr);
+ if (err != DB_SUCCESS) {
+
+ return(err);
+ }
+ }
+
+ /* Try first optimistic descent to the B-tree */
+
+ err = row_ins_clust_index_entry_low(BTR_MODIFY_LEAF, index, entry,
+ n_ext, thr);
+ if (err != DB_FAIL) {
+
+ return(err);
+ }
- if (foreign && UT_LIST_GET_FIRST(index->table->foreign_list)) {
+ /* Try then pessimistic descent to the B-tree */
+
+ return(row_ins_clust_index_entry_low(BTR_MODIFY_TREE, index, entry,
+ n_ext, thr));
+}
+
+/***************************************************************//**
+Inserts an entry into a secondary index. Tries first optimistic,
+then pessimistic descent down the tree. If the entry matches enough
+to a delete marked record, performs the insert by updating or delete
+unmarking the delete marked record.
+@return DB_SUCCESS, DB_LOCK_WAIT, DB_DUPLICATE_KEY, or some other error code */
+UNIV_INTERN
+dberr_t
+row_ins_sec_index_entry(
+/*====================*/
+ dict_index_t* index, /*!< in: secondary index */
+ dtuple_t* entry, /*!< in/out: index entry to insert */
+ que_thr_t* thr) /*!< in: query thread */
+{
+ dberr_t err;
+
+ if (UT_LIST_GET_FIRST(index->table->foreign_list)) {
err = row_ins_check_foreign_constraints(index->table, index,
entry, thr);
if (err != DB_SUCCESS) {
@@ -2439,14 +2546,12 @@ row_ins_index_entry(
if (dict_index_online_trylog(index, entry, thr_get_trx(thr)->id,
ROW_OP_INSERT)) {
-
return(DB_SUCCESS);
}
/* Try first optimistic descent to the B-tree */
- err = row_ins_index_entry_low(BTR_MODIFY_LEAF, index, entry,
- n_ext, thr);
+ err = row_ins_sec_index_entry_low(BTR_MODIFY_LEAF, index, entry, thr);
if (err != DB_FAIL) {
return(err);
@@ -2454,9 +2559,29 @@ row_ins_index_entry(
/* Try then pessimistic descent to the B-tree */
- err = row_ins_index_entry_low(BTR_MODIFY_TREE, index, entry,
- n_ext, thr);
- return(err);
+ return(row_ins_sec_index_entry_low(
+ BTR_MODIFY_TREE, index, entry, thr));
+}
+
+/***************************************************************//**
+Inserts an index entry to index. Tries first optimistic, then pessimistic
+descent down the tree. If the entry matches enough to a delete marked record,
+performs the insert by updating or delete unmarking the delete marked
+record.
+@return DB_SUCCESS, DB_LOCK_WAIT, DB_DUPLICATE_KEY, or some other error code */
+static
+dberr_t
+row_ins_index_entry(
+/*================*/
+ dict_index_t* index, /*!< in: index */
+ dtuple_t* entry, /*!< in/out: index entry to insert */
+ que_thr_t* thr) /*!< in: query thread */
+{
+ if (dict_index_is_clust(index)) {
+ return(row_ins_clust_index_entry(index, entry, thr, 0));
+ } else {
+ return(row_ins_sec_index_entry(index, entry, thr));
+ }
}
/***********************************************************//**
@@ -2533,7 +2658,7 @@ row_ins_index_entry_step(
ut_ad(dtuple_check_typed(node->entry));
- err = row_ins_index_entry(node->index, node->entry, 0, TRUE, thr);
+ err = row_ins_index_entry(node->index, node->entry, thr);
return(err);
}
=== modified file 'storage/innobase/row/row0upd.cc'
--- a/storage/innobase/row/row0upd.cc revid:jorgen.loland@stripped-4vd4gc1iosh2n6ba
+++ b/storage/innobase/row/row0upd.cc revid:marko.makela@strippedzrn
@@ -1734,7 +1734,7 @@ row_upd_sec_index_entry(
case ROW_FOUND:
/* Delete mark the old index record; it can already be
delete marked if we return after a lock wait in
- row_ins_index_entry below */
+ row_ins_sec_index_entry() below */
if (!rec_get_deleted_flag(
rec, dict_table_is_comp(index->table))) {
@@ -1774,7 +1774,7 @@ row_upd_sec_index_entry(
ut_a(entry);
/* Insert new index entry */
- err = row_ins_index_entry(index, entry, 0, TRUE, thr);
+ err = row_ins_sec_index_entry(index, entry, thr);
func_exit:
mem_heap_free(heap);
@@ -2005,7 +2005,7 @@ row_upd_clust_rec_by_insert(
default:
ut_error;
case UPD_NODE_INSERT_BLOB:
- /* A lock wait occurred in row_ins_index_entry() in
+ /* A lock wait occurred in row_ins_clust_index_entry() in
the previous invocation of this function. Mark the
off-page columns in the entry inherited. */
@@ -2014,7 +2014,7 @@ row_upd_clust_rec_by_insert(
ut_a(change_ownership);
/* fall through */
case UPD_NODE_INSERT_CLUSTERED:
- /* A lock wait occurred in row_ins_index_entry() in
+ /* A lock wait occurred in row_ins_clust_index_entry() in
the previous invocation of this function. */
break;
case UPD_NODE_UPDATE_CLUSTERED:
@@ -2065,9 +2065,9 @@ err_exit:
mtr_commit(mtr);
- err = row_ins_index_entry(index, entry,
- node->upd_ext ? node->upd_ext->n_ext : 0,
- TRUE, thr);
+ err = row_ins_clust_index_entry(
+ index, entry, thr,
+ node->upd_ext ? node->upd_ext->n_ext : 0);
node->state = change_ownership
? UPD_NODE_INSERT_BLOB
: UPD_NODE_INSERT_CLUSTERED;
No bundle (reason: useless for push emails).| Thread |
|---|
| • bzr push into mysql-trunk-wl6255 branch (marko.makela:3829 to 3833) WL#6255 | marko.makela | 15 May |