3946 Marko Mäkelä 2012-06-06
WL#6255 cleanup and fix for ADD COLUMN b, ADD PRIMARY KEY (a, c)
row_log_t: Add add_cols, col_map.
row_log_allocate(): Add the parameters add_cols, col_map.
row_log_table_apply(), row_log_table_apply_ops(): Remove the
parameters add_cols, col_map.
row_log_table_apply_convert_mrec(), row_log_table_apply_insert(),
row_log_table_apply_update(): Replace the parameters add_cols,
col_map, new_table with row_log_t log.
row_log_table_apply_op(): Remove the parameters new_table, add_cols,
col_map.
row_log_table_get_pk(): Map added and reordered columns.
ha_innobase::check_if_supported_inplace_alter(): Initialize key_part->field
to table->field[], or to altered_table->field[] for ADD COLUMN.
modified:
mysql-test/suite/innodb/r/innodb-table-online.result
mysql-test/suite/innodb/t/innodb-table-online.test
storage/innobase/handler/handler0alter.cc
storage/innobase/include/row0log.h
storage/innobase/row/row0log.cc
3945 Marko Mäkelä 2012-06-05
Adjust main.alter_table for ADD COLUMN.
modified:
mysql-test/r/alter_table.result
mysql-test/t/alter_table.test
3944 Marko Mäkelä 2012-06-05
WL#6255 ALTER_ADD_COLUMN (ALTER TABLE ... ADD COLUMN)
innobase_build_col_map_add(): Convert a default value of an ADD COLUMN
to the InnoDB format.
ha_innobase_inplace_ctx(): Add add_cols.
innobase_build_col_map(), row_merge_build_indexes(),
row_log_table_apply(), row_build(), row_log_table_apply_convert_mrec(),
row_log_table_apply_insert(), row_log_table_apply_update(),
row_log_table_apply_op(), row_log_table_apply_ops(),
row_merge_read_clustered_index(): Add the parameter add_cols.
prepare_inplace_alter_table_dict(): When rebuilding a table, make it a
*.ibd file if the original table was in an *.ibd file, or if
innodb_file_per_table=1.
modified:
mysql-test/suite/innodb/r/innodb-create-options.result
mysql-test/suite/innodb/r/innodb.result
mysql-test/suite/innodb/t/innodb-create-options.test
storage/innobase/handler/handler0alter.cc
storage/innobase/include/row0log.h
storage/innobase/include/row0merge.h
storage/innobase/include/row0row.h
storage/innobase/row/row0log.cc
storage/innobase/row/row0merge.cc
storage/innobase/row/row0row.cc
storage/innobase/row/row0undo.cc
storage/innobase/row/row0upd.cc
storage/innobase/row/row0vers.cc
=== modified file 'mysql-test/r/alter_table.result'
--- a/mysql-test/r/alter_table.result revid:marko.makela@stripped
+++ b/mysql-test/r/alter_table.result revid:marko.makela@oracle.com-20120605213921-w1upm6qwwud13rsc
@@ -1543,8 +1543,7 @@ ALTER TABLE t1 ADD COLUMN (c1 INT);
ALTER TABLE t1 ADD COLUMN (c2 INT), ALGORITHM= DEFAULT;
ALTER TABLE t1 ADD COLUMN (c3 INT), ALGORITHM= COPY;
ALTER TABLE t1 ADD COLUMN (c4 INT), ALGORITHM= INPLACE;
-ERROR 42000: This version of MySQL doesn't yet support 'ALTER TABLE t1 ADD COLUMN (c4 INT), ALGORITHM= INPLACE'
-ALTER TABLE t1 DROP COLUMN c1, DROP COLUMN c2, DROP COLUMN c3;
+ALTER TABLE t1 DROP COLUMN c1, DROP COLUMN c2, DROP COLUMN c3, DROP COLUMN c4;
#
# 4: Test LOCK keyword
#
@@ -1646,26 +1645,26 @@ affected rows: 0
ALTER TABLE tm1;
affected rows: 0
ALTER TABLE ti1 ADD COLUMN d VARCHAR(200);
-affected rows: 2
-info: Records: 2 Duplicates: 0 Warnings: 0
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
ALTER TABLE tm1 ADD COLUMN d VARCHAR(200);
affected rows: 2
info: Records: 2 Duplicates: 0 Warnings: 0
ALTER TABLE ti1 ADD COLUMN d2 VARCHAR(200);
-affected rows: 2
-info: Records: 2 Duplicates: 0 Warnings: 0
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
ALTER TABLE tm1 ADD COLUMN d2 VARCHAR(200);
affected rows: 2
info: Records: 2 Duplicates: 0 Warnings: 0
ALTER TABLE ti1 ADD COLUMN e ENUM('a', 'b') FIRST;
-affected rows: 2
-info: Records: 2 Duplicates: 0 Warnings: 0
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
ALTER TABLE tm1 ADD COLUMN e ENUM('a', 'b') FIRST;
affected rows: 2
info: Records: 2 Duplicates: 0 Warnings: 0
ALTER TABLE ti1 ADD COLUMN f INT AFTER a;
-affected rows: 2
-info: Records: 2 Duplicates: 0 Warnings: 0
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
ALTER TABLE tm1 ADD COLUMN f INT AFTER a;
affected rows: 2
info: Records: 2 Duplicates: 0 Warnings: 0
=== modified file 'mysql-test/suite/innodb/r/innodb-table-online.result'
--- a/mysql-test/suite/innodb/r/innodb-table-online.result revid:marko.makela@stripped43232-ned9z2rxx931s91t
+++ b/mysql-test/suite/innodb/r/innodb-table-online.result revid:marko.makela@stripped120605213921-w1upm6qwwud13rsc
@@ -214,8 +214,9 @@ ALTER TABLE t1 ADD PRIMARY KEY(c22f), CH
ERROR 42000: Multiple primary key defined
ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(c22f), CHANGE c2 c22f INT;
ERROR 23000: Duplicate entry '5' for key 'PRIMARY'
-ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(c1,c22f), CHANGE c2 c22f INT,
-CHANGE c3 c3 TEXT NULL, CHANGE c1 c1 INT AFTER c22f;
+ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(c1,c22f,c4(5)),
+CHANGE c2 c22f INT, CHANGE c3 c3 TEXT NULL, CHANGE c1 c1 INT AFTER c22f,
+ADD COLUMN c4 VARCHAR(6) DEFAULT 'Online';
SET DEBUG_SYNC = 'now WAIT_FOR rebuilt3';
SELECT name, count FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE subsystem = 'ddl';
name count
@@ -263,22 +264,26 @@ ALTER TABLE t1 MODIFY c3 TEXT NOT NULL;
ERROR 22004: Invalid use of NULL value
UPDATE t1 SET c3=CONCAT(c1,REPEAT('foo',c1)) WHERE c3 IS NULL;
SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL c3p5_created0 WAIT_FOR ins_done0';
-ALTER TABLE t1 MODIFY c3 TEXT NOT NULL, DROP COLUMN c22f;
+ALTER TABLE t1 MODIFY c3 TEXT NOT NULL, DROP COLUMN c22f,
+ADD COLUMN c5 CHAR(5) DEFAULT 'tired' FIRST;
SET DEBUG_SYNC = 'now WAIT_FOR c3p5_created0';
BEGIN;
-INSERT INTO t1 VALUES(347,33101,'Pikku kakkosen posti');
-INSERT INTO t1 VALUES(33101,347,NULL);
+INSERT INTO t1 VALUES(347,33101,'Pikku kakkosen posti','YLETV2');
+INSERT INTO t1 VALUES(33101,347,NULL,'');
SET DEBUG_SYNC = 'now SIGNAL ins_done0';
ERROR 22004: Invalid use of NULL value
ROLLBACK;
ALTER TABLE t1 MODIFY c3 TEXT NOT NULL;
SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL c3p5_created WAIT_FOR ins_done';
-ALTER TABLE t1 DROP PRIMARY KEY, DROP COLUMN c22f, ADD PRIMARY KEY c3p5(c3(5));
+ALTER TABLE t1 DROP PRIMARY KEY, DROP COLUMN c22f,
+ADD COLUMN c6 VARCHAR(1000) DEFAULT
+'I love tracking down hard-to-reproduce bugs.',
+ADD PRIMARY KEY c3p5(c3(5), c6(2));
SET DEBUG_SYNC = 'now WAIT_FOR c3p5_created';
SET DEBUG_SYNC = 'ib_after_row_insert SIGNAL ins_done WAIT_FOR ddl_timed_out';
-INSERT INTO t1 VALUES(347,33101,NULL);
+INSERT INTO t1 VALUES(347,33101,NULL,'');
ERROR 23000: Column 'c3' cannot be null
-INSERT INTO t1 VALUES(347,33101,'Pikku kakkosen posti');
+INSERT INTO t1 VALUES(347,33101,'Pikku kakkosen posti','');
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
SET DEBUG_SYNC = 'now SIGNAL ddl_timed_out';
SELECT name, count FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE subsystem = 'ddl';
@@ -294,6 +299,18 @@ SET DEBUG_SYNC = 'row_log_table_apply1_b
SET lock_wait_timeout = 1;
ALTER TABLE t1 ROW_FORMAT=REDUNDANT;
SET DEBUG_SYNC = 'now WAIT_FOR rebuilt4';
+SELECT * FROM t1 LIMIT 10;
+c22f c1 c3 c4
+5 1 1foo Online
+6 2 2foofoo Online
+7 3 3foofoofoo Online
+8 4 4foofoofoofoo Online
+9 5 5foofoofoofoofoo Online
+5 6 6foofoofoofoofoofoo Online
+6 7 7foofoofoofoofoofoofoo Online
+7 8 8foofoofoofoofoofoofoofoo Online
+8 9 9foofoofoofoofoofoofoofoofoo Online
+9 10 10foofoofoofoofoofoofoofoofoofoo Online
SET lock_wait_timeout = 10;
ALTER TABLE t1 DISCARD TABLESPACE;
SET DEBUG_SYNC = 'now SIGNAL dml4_done';
@@ -304,11 +321,12 @@ t1 CREATE TABLE `t1` (
`c22f` int(11) NOT NULL DEFAULT '0',
`c1` int(11) NOT NULL DEFAULT '0',
`c3` text NOT NULL,
- PRIMARY KEY (`c1`,`c22f`)
+ `c4` varchar(6) NOT NULL DEFAULT 'Online',
+ PRIMARY KEY (`c1`,`c22f`,`c4`(5))
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT
ALTER TABLE t1 DROP COLUMN c3, ROW_FORMAT=REDUNDANT, ALGORITHM = INPLACE;
SELECT * FROM t1;
-c22f c1
+c22f c1 c4
SET DEBUG_SYNC = 'RESET';
SET DEBUG = '';
SET GLOBAL innodb_monitor_disable = module_ddl;
=== modified file 'mysql-test/suite/innodb/t/innodb-table-online.test'
--- a/mysql-test/suite/innodb/t/innodb-table-online.test revid:marko.makela@stripped0120605143232-ned9z2rxx931s91t
+++ b/mysql-test/suite/innodb/t/innodb-table-online.test revid:marko.makela@oracle.com-20120605213921-w1upm6qwwud13rsc
@@ -220,8 +220,9 @@ ALTER TABLE t1 ADD PRIMARY KEY(c22f), CH
--error ER_DUP_ENTRY
ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(c22f), CHANGE c2 c22f INT;
--send
-ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(c1,c22f), CHANGE c2 c22f INT,
-CHANGE c3 c3 TEXT NULL, CHANGE c1 c1 INT AFTER c22f;
+ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(c1,c22f,c4(5)),
+CHANGE c2 c22f INT, CHANGE c3 c3 TEXT NULL, CHANGE c1 c1 INT AFTER c22f,
+ADD COLUMN c4 VARCHAR(6) DEFAULT 'Online';
connection default;
SET DEBUG_SYNC = 'now WAIT_FOR rebuilt3';
@@ -262,14 +263,15 @@ UPDATE t1 SET c3=CONCAT(c1,REPEAT('foo',
SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL c3p5_created0 WAIT_FOR ins_done0';
--send
-ALTER TABLE t1 MODIFY c3 TEXT NOT NULL, DROP COLUMN c22f;
+ALTER TABLE t1 MODIFY c3 TEXT NOT NULL, DROP COLUMN c22f,
+ADD COLUMN c5 CHAR(5) DEFAULT 'tired' FIRST;
connection default;
SET DEBUG_SYNC = 'now WAIT_FOR c3p5_created0';
BEGIN;
-INSERT INTO t1 VALUES(347,33101,'Pikku kakkosen posti');
-INSERT INTO t1 VALUES(33101,347,NULL);
+INSERT INTO t1 VALUES(347,33101,'Pikku kakkosen posti','YLETV2');
+INSERT INTO t1 VALUES(33101,347,NULL,'');
SET DEBUG_SYNC = 'now SIGNAL ins_done0';
connection con1;
@@ -284,16 +286,19 @@ ALTER TABLE t1 MODIFY c3 TEXT NOT NULL;
SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL c3p5_created WAIT_FOR ins_done';
--send
-ALTER TABLE t1 DROP PRIMARY KEY, DROP COLUMN c22f, ADD PRIMARY KEY c3p5(c3(5));
+ALTER TABLE t1 DROP PRIMARY KEY, DROP COLUMN c22f,
+ADD COLUMN c6 VARCHAR(1000) DEFAULT
+'I love tracking down hard-to-reproduce bugs.',
+ADD PRIMARY KEY c3p5(c3(5), c6(2));
connection default;
SET DEBUG_SYNC = 'now WAIT_FOR c3p5_created';
SET DEBUG_SYNC = 'ib_after_row_insert SIGNAL ins_done WAIT_FOR ddl_timed_out';
--error ER_BAD_NULL_ERROR
-INSERT INTO t1 VALUES(347,33101,NULL);
+INSERT INTO t1 VALUES(347,33101,NULL,'');
--send
-INSERT INTO t1 VALUES(347,33101,'Pikku kakkosen posti');
+INSERT INTO t1 VALUES(347,33101,'Pikku kakkosen posti','');
connection con1;
--error ER_LOCK_WAIT_TIMEOUT
@@ -314,6 +319,7 @@ ALTER TABLE t1 ROW_FORMAT=REDUNDANT;
connection con1;
SET DEBUG_SYNC = 'now WAIT_FOR rebuilt4';
+SELECT * FROM t1 LIMIT 10;
connect (con2,localhost,root,,);
connection con2;
=== modified file 'mysql-test/t/alter_table.test'
--- a/mysql-test/t/alter_table.test revid:marko.makela@stripped2-ned9z2rxx931s91t
+++ b/mysql-test/t/alter_table.test revid:marko.makela@strippedsc
@@ -1317,10 +1317,9 @@ ALTER TABLE t1 DROP INDEX i1, DROP INDEX
ALTER TABLE t1 ADD COLUMN (c1 INT);
ALTER TABLE t1 ADD COLUMN (c2 INT), ALGORITHM= DEFAULT;
ALTER TABLE t1 ADD COLUMN (c3 INT), ALGORITHM= COPY;
---error ER_NOT_SUPPORTED_YET
ALTER TABLE t1 ADD COLUMN (c4 INT), ALGORITHM= INPLACE;
-ALTER TABLE t1 DROP COLUMN c1, DROP COLUMN c2, DROP COLUMN c3;
+ALTER TABLE t1 DROP COLUMN c1, DROP COLUMN c2, DROP COLUMN c3, DROP COLUMN c4;
--echo #
--echo # 4: Test LOCK keyword
=== modified file 'storage/innobase/handler/handler0alter.cc'
--- a/storage/innobase/handler/handler0alter.cc revid:marko.makela@oracle.com-20120605143232-ned9z2rxx931s91t
+++ b/storage/innobase/handler/handler0alter.cc revid:marko.makela@stripped-20120605213921-w1upm6qwwud13rsc
@@ -247,6 +247,9 @@ ha_innobase::check_if_supported_inplace_
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
}
+ List_iterator_fast<Create_field> cf_it(
+ ha_alter_info->alter_info->create_list);
+
/* Fix the key parts. */
for (KEY* new_key = ha_alter_info->key_info_buffer;
new_key < ha_alter_info->key_info_buffer
@@ -255,44 +258,28 @@ ha_innobase::check_if_supported_inplace_
for (KEY_PART_INFO* key_part = new_key->key_part;
key_part < new_key->key_part + new_key->key_parts;
key_part++) {
- key_part->field = table->field[key_part->fieldnr];
- /* TODO: Use altered_table for ADD_COLUMN.
- What to do with ADD_COLUMN|DROP_COLUMN? */
-
- if (dict_table_get_n_user_cols(prebuilt->table)
- <= key_part->fieldnr) {
- /* This should never occur, unless
- the .frm file gets out of sync with
- the InnoDB data dictionary. */
- sql_print_warning(
- "InnoDB table '%s' has %u columns, "
- "MySQL table '%s' has %u.",
- prebuilt->table->name,
- (unsigned) dict_table_get_n_user_cols(
- prebuilt->table),
- table->s->table_name.str,
- table->s->fields);
- ut_ad(0);
- DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
- }
-
- dict_col_t* col = dict_table_get_nth_col(
- prebuilt->table, key_part->fieldnr);
-
- if (!(col->prtype & DATA_NOT_NULL)
- != !!key_part->field->null_ptr) {
- sql_print_warning(
- "InnoDB table '%s' column '%s' "
- "attributes differ from "
- "MySQL '%s'.'%s'.",
- prebuilt->table->name,
- dict_table_get_col_name(
- prebuilt->table,
- key_part->fieldnr),
- table->s->table_name.str,
- key_part->field->field_name);
- ut_ad(0);
- DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
+ const Create_field* new_field;
+
+ DBUG_ASSERT(key_part->fieldnr
+ < altered_table->s->fields);
+
+ cf_it.rewind();
+ for (uint fieldnr = 0; (new_field = cf_it++);
+ fieldnr++) {
+ if (fieldnr == key_part->fieldnr) {
+ break;
+ }
+ }
+
+ DBUG_ASSERT(new_field);
+
+ key_part->field = new_field->field;
+
+ if (!new_field->field) {
+ DBUG_ASSERT(ha_alter_info->handler_flags
+ & Alter_inplace_info::ADD_COLUMN);
+ key_part->field = altered_table->field[
+ key_part->fieldnr];
}
}
}
@@ -2022,10 +2009,11 @@ innobase_check_foreigns(
dict_foreign_t** drop_fk,
ulint n_drop_fk)
{
- List_iterator_fast<Create_field> cf_it;
+ List_iterator_fast<Create_field> cf_it(
+ ha_alter_info->alter_info->create_list);
for (Field** fp = old_table->field; *fp; fp++) {
- cf_it.init(ha_alter_info->alter_info->create_list);
+ cf_it.rewind();
const Create_field* new_field;
ut_ad(!(*fp)->null_ptr == !!((*fp)->flags & NOT_NULL_FLAG));
@@ -2116,8 +2104,8 @@ innobase_build_col_map(
ulint* col_map = static_cast<ulint*>(
mem_heap_alloc(heap, old_table->n_cols * sizeof *col_map));
- List_iterator_fast<Create_field> cf_it;
- cf_it.init(ha_alter_info->alter_info->create_list);
+ List_iterator_fast<Create_field> cf_it(
+ ha_alter_info->alter_info->create_list);
uint i = 0;
/* Any dropped columns will map to ULINT_UNDEFINED. */
@@ -2588,7 +2576,7 @@ col_fail:
goto error_handling;);
rw_lock_x_lock(&add_index[num_created]->lock);
bool ok = row_log_allocate(add_index[num_created],
- NULL, true);
+ NULL, true, NULL, NULL);
rw_lock_x_unlock(&add_index[num_created]->lock);
if (!ok) {
@@ -2612,7 +2600,8 @@ col_fail:
bool ok = row_log_allocate(
clust_index, indexed_table,
!(ha_alter_info->handler_flags
- & Alter_inplace_info::ADD_PK_INDEX));
+ & Alter_inplace_info::ADD_PK_INDEX),
+ add_cols, col_map);
rw_lock_x_unlock(&clust_index->lock);
if (!ok) {
@@ -2907,7 +2896,8 @@ err_exit_no_heap:
already contains. */
if (ha_alter_info->handler_flags
& Alter_inplace_info::ALTER_COLUMN_NAME) {
- List_iterator_fast<Create_field> cf_it;
+ List_iterator_fast<Create_field> cf_it(
+ ha_alter_info->alter_info->create_list);
for (Field** fp = table->field; *fp; fp++) {
if (!((*fp)->flags & FIELD_IS_RENAMED)) {
@@ -2916,7 +2906,7 @@ err_exit_no_heap:
const char* name = 0;
- cf_it.init(ha_alter_info->alter_info->create_list);
+ cf_it.rewind();
while (Create_field* cf = cf_it++) {
if (cf->field == *fp) {
name = cf->field_name;
@@ -3003,7 +2993,7 @@ check_if_ok_to_rename:
List_iterator<Alter_drop> drop_it(
ha_alter_info->alter_info->drop_list);
- drop_it.rewind();
+
while (Alter_drop* drop = drop_it++) {
if (drop->type != Alter_drop::FOREIGN_KEY) {
continue;
@@ -3414,8 +3404,7 @@ oom:
&& ctx->indexed_table != prebuilt->table) {
DEBUG_SYNC_C("row_log_table_apply1_before");
error = row_log_table_apply(
- ctx->thr, prebuilt->table, table,
- ctx->add_cols, ctx->col_map);
+ ctx->thr, prebuilt->table, table);
}
/* After an error, remove all those index definitions
@@ -3869,7 +3858,8 @@ innobase_rename_columns(
row_prebuilt_t* prebuilt,
trx_t* trx)
{
- List_iterator_fast<Create_field> cf_it;
+ List_iterator_fast<Create_field> cf_it(
+ ha_alter_info->alter_info->create_list);
uint i = 0;
for (Field** fp = table->field; *fp; fp++, i++) {
@@ -3877,7 +3867,7 @@ innobase_rename_columns(
continue;
}
- cf_it.init(ha_alter_info->alter_info->create_list);
+ cf_it.rewind();
while (Create_field* cf = cf_it++) {
if (cf->field == *fp) {
if (innobase_rename_column(
@@ -4000,8 +3990,7 @@ ha_innobase::commit_inplace_alter_table(
if (ctx->online) {
DEBUG_SYNC_C("row_log_table_apply2_before");
error = row_log_table_apply(
- ctx->thr, prebuilt->table, table,
- ctx->add_cols, ctx->col_map);
+ ctx->thr, prebuilt->table, table);
switch (error) {
KEY* dup_key;
=== modified file 'storage/innobase/include/row0log.h'
--- a/storage/innobase/include/row0log.h revid:marko.makela@stripped3232-ned9z2rxx931s91t
+++ b/storage/innobase/include/row0log.h revid:marko.makela@strippedqwwud13rsc
@@ -45,8 +45,13 @@ row_log_allocate(
dict_index_t* index, /*!< in/out: index */
dict_table_t* table, /*!< in/out: new table being rebuilt,
or NULL when creating a secondary index */
- bool same_pk)/*!< in: whether the definition of the
+ bool same_pk,/*!< in: whether the definition of the
PRIMARY KEY has remained the same */
+ const dtuple_t* add_cols,
+ /*!< in: default values of
+ added columns, or NULL */
+ const ulint* col_map)/*!< in: mapping of old column
+ numbers to new ones, or NULL if !table */
__attribute__((nonnull(1), warn_unused_result));
/******************************************************//**
Free the row log for an index on which online creation was aborted. */
@@ -176,14 +181,9 @@ row_log_table_apply(
que_thr_t* thr, /*!< in: query graph */
dict_table_t* old_table,
/*!< in: old table */
- struct TABLE* table, /*!< in/out: MySQL table
+ struct TABLE* table) /*!< in/out: MySQL table
(for reporting duplicates) */
- const dtuple_t* add_cols,
- /*!< in: default values of
- added columns, or NULL */
- const ulint* col_map)/*!< in: mapping of old column
- numbers to new ones, or NULL */
- __attribute__((nonnull(1,2,3,5), warn_unused_result));
+ __attribute__((nonnull, warn_unused_result));
/******************************************************//**
Get the latest transaction ID that has invoked row_log_online_op()
=== modified file 'storage/innobase/row/row0log.cc'
--- a/storage/innobase/row/row0log.cc revid:marko.makela@stripped0120605143232-ned9z2rxx931s91t
+++ b/storage/innobase/row/row0log.cc revid:marko.makela@strippedw1upm6qwwud13rsc
@@ -95,6 +95,10 @@ struct row_log_t {
index that is being created online */
bool same_pk;/*!< whether the definition of the PRIMARY KEY
has remained the same */
+ const dtuple_t* add_cols;
+ /*!< default values of added columns, or NULL */
+ const ulint* col_map;/*!< mapping of old column numbers to
+ new ones, or NULL if !table */
dberr_t error; /*!< error that occurred during online
table rebuild */
trx_id_t max_trx;/*!< biggest observed trx_id in
@@ -796,8 +800,8 @@ row_log_table_get_pk(
/* index->online_log->error is protected by the above mutex. */
if (index->online_log->error == DB_SUCCESS) {
- dict_table_t* new_table
- = index->online_log->table;
+ row_log_t* log = index->online_log;
+ dict_table_t* new_table = log->table;
dict_index_t* new_index
= dict_table_get_first_index(new_table);
const ulint new_n_uniq
@@ -835,18 +839,35 @@ row_log_table_get_pk(
dfield_t* dfield;
const dict_col_t* new_col;
const dict_col_t* col;
+ ulint col_no;
ulint i;
ulint len;
const byte* field;
- dfield = dtuple_get_nth_field(tuple, new_i);
ifield = dict_index_get_nth_field(new_index, new_i);
+ dfield = dtuple_get_nth_field(tuple, new_i);
new_col = dict_field_get_col(ifield);
+ col_no = new_col->ind;
+
+ for (ulint old_i = 0; old_i < index->table->n_cols;
+ old_i++) {
+ if (col_no == log->col_map[old_i]) {
+ col_no = old_i;
+ goto copy_col;
+ }
+ }
+
+ /* No matching column was found in the old
+ table, so this must be an added column.
+ Copy the default value. */
+ ut_ad(log->add_cols);
+ dfield_copy(dfield,
+ dtuple_get_nth_field(
+ log->add_cols, col_no));
+ continue;
- /* TODO: support ADD COLUMN, DROP COLUMN,
- reordering columns */
- col = dict_table_get_nth_col(
- index->table, new_col->ind);
+copy_col:
+ col = dict_table_get_nth_col(index->table, col_no);
i = dict_col_get_clust_pos(col, index);
@@ -1002,37 +1023,32 @@ row_log_table_is_rollback(
/******************************************************//**
Converts a log record to a table row.
@return converted row, or NULL if the conversion fails */
-static __attribute__((nonnull(1,2,3,5,6,7,8), warn_unused_result))
+static __attribute__((nonnull, warn_unused_result))
const dtuple_t*
row_log_table_apply_convert_mrec(
/*=============================*/
const mrec_t* mrec, /*!< in: merge record */
const dict_index_t* index, /*!< in: index of mrec */
const ulint* offsets, /*!< in: offsets of mrec */
- const dtuple_t* add_cols, /*!< in: default values of
- added columns, or NULL */
- const ulint* col_map, /*!< in: mapping of old column
- numbers to new ones, or NULL */
+ const row_log_t* log, /*!< in: rebuild context */
mem_heap_t* heap, /*!< in/out: memory heap */
- dict_table_t* new_table, /*!< in/out: table
- being rebuilt */
dberr_t* error) /*!< out: DB_SUCCESS or
reason of failure */
{
dtuple_t* row;
/* This is based on row_build(). */
- if (add_cols) {
- row = dtuple_copy(add_cols, heap);
+ if (log->add_cols) {
+ row = dtuple_copy(log->add_cols, heap);
/* dict_table_copy_types() would set the fields to NULL */
- for (ulint i = 0; i < dict_table_get_n_cols(new_table); i++) {
+ for (ulint i = 0; i < dict_table_get_n_cols(log->table); i++) {
dict_col_copy_type(
- dict_table_get_nth_col(new_table, i),
+ dict_table_get_nth_col(log->table, i),
dfield_get_type(dtuple_get_nth_field(row, i)));
}
} else {
- row = dtuple_create(heap, dict_table_get_n_cols(new_table));
- dict_table_copy_types(row, new_table);
+ row = dtuple_create(heap, dict_table_get_n_cols(log->table));
+ dict_table_copy_types(row, log->table);
}
for (ulint i = 0; i < rec_offs_n_fields(offsets); i++) {
@@ -1052,7 +1068,7 @@ row_log_table_apply_convert_mrec(
const dict_col_t* col
= dict_field_get_col(ind_field);
ulint col_no
- = col_map[dict_col_get_no(col)];
+ = log->col_map[dict_col_get_no(col)];
if (col_no == ULINT_UNDEFINED) {
/* dropped column */
@@ -1078,7 +1094,7 @@ row_log_table_apply_convert_mrec(
/* See if any columns were changed to NULL or NOT NULL. */
const dict_col_t* new_col
- = dict_table_get_nth_col(new_table, col_no);
+ = dict_table_get_nth_col(log->table, col_no);
ut_ad(new_col->mtype == col->mtype);
/* Assert that prtype matches except for nullability. */
@@ -1131,6 +1147,7 @@ row_log_table_apply_insert_low(
dict_index_t* index = dict_table_get_first_index(new_table);
ut_ad(dtuple_validate(row));
+ ut_ad(new_table == dup->index->online_log->table);
#ifdef ROW_LOG_APPLY_PRINT
if (row_log_apply_print) {
@@ -1178,7 +1195,7 @@ row_log_table_apply_insert_low(
/******************************************************//**
Replays an insert operation on a table that was rebuilt.
@return DB_SUCCESS or error code */
-static __attribute__((nonnull(1,2,3,4,6,7,8,9), warn_unused_result))
+static __attribute__((nonnull, warn_unused_result))
dberr_t
row_log_table_apply_insert(
/*=======================*/
@@ -1187,26 +1204,20 @@ row_log_table_apply_insert(
const ulint* offsets, /*!< in: offsets of mrec */
mem_heap_t* offsets_heap, /*!< in/out: memory heap
that can be emptied */
- const dtuple_t* add_cols, /*!< in: default values of
- added columns, or NULL */
- const ulint* col_map, /*!< in: mapping of old column
- numbers to new ones, or NULL */
mem_heap_t* heap, /*!< in/out: memory heap */
- dict_table_t* new_table, /*!< in/out: table
- being rebuilt */
row_merge_dup_t* dup) /*!< in/out: for reporting
duplicate key errors */
{
+ const row_log_t*log = dup->index->online_log;
dberr_t error;
const dtuple_t* row = row_log_table_apply_convert_mrec(
- mrec, dup->index, offsets, add_cols, col_map, heap, new_table,
- &error);
+ mrec, dup->index, offsets, log, heap, &error);
ut_ad(!row == (error != DB_SUCCESS));
if (row) {
error = row_log_table_apply_insert_low(
- thr, row, offsets_heap, heap, new_table, dup);
+ thr, row, offsets_heap, heap, log->table, dup);
}
if (error != DB_SUCCESS) {
@@ -1403,7 +1414,7 @@ all_done:
/******************************************************//**
Replays an update operation on a table that was rebuilt.
@return DB_SUCCESS or error code */
-static __attribute__((nonnull(1,4,5,6,8,9,10,11,12), warn_unused_result))
+static __attribute__((nonnull, warn_unused_result))
dberr_t
row_log_table_apply_update(
/*=======================*/
@@ -1418,13 +1429,7 @@ row_log_table_apply_update(
const ulint* offsets, /*!< in: offsets of mrec */
mem_heap_t* offsets_heap, /*!< in/out: memory heap
that can be emptied */
- const dtuple_t* add_cols, /*!< in: default values of
- added columns, or NULL */
- const ulint* col_map, /*!< in: mapping of old column
- numbers to new ones, or NULL */
mem_heap_t* heap, /*!< in/out: memory heap */
- dict_table_t* new_table, /*!< in/out: table
- being rebuilt */
row_merge_dup_t* dup, /*!< in/out: for reporting
duplicate key errors */
const dtuple_t* old_pk) /*!< in: PRIMARY KEY and
@@ -1432,8 +1437,9 @@ row_log_table_apply_update(
of the old value,
or PRIMARY KEY if same_pk */
{
+ const row_log_t*log = dup->index->online_log;
const dtuple_t* row;
- dict_index_t* index = dict_table_get_first_index(new_table);
+ dict_index_t* index = dict_table_get_first_index(log->table);
mtr_t mtr;
btr_pcur_t pcur;
dberr_t error;
@@ -1445,8 +1451,7 @@ row_log_table_apply_update(
+ (dup->index->online_log->same_pk ? 0 : 2));
row = row_log_table_apply_convert_mrec(
- mrec, dup->index, offsets, add_cols, col_map,
- heap, new_table, &error);
+ mrec, dup->index, offsets, log, heap, &error);
ut_ad(!row == (error != DB_SUCCESS));
@@ -1477,7 +1482,7 @@ row_log_table_apply_update(
insert:
/* The row was not found. Insert it. */
error = row_log_table_apply_insert_low(
- thr, row, offsets_heap, heap, new_table, dup);
+ thr, row, offsets_heap, heap, log->table, dup);
if (error != DB_SUCCESS) {
err_exit:
@@ -1576,8 +1581,9 @@ delete_insert:
the record. */
old_row = row_build(ROW_COPY_DATA, index,
btr_pcur_get_rec(&pcur),
- cur_offsets, new_table,
- add_cols, col_map, &old_ext, heap);
+ cur_offsets, log->table,
+ log->add_cols, log->col_map,
+ &old_ext, heap);
ut_ad(old_row);
} else {
old_row = NULL;
@@ -1667,7 +1673,7 @@ func_exit:
Applies an operation to a table that was rebuilt.
@return NULL on failure (mrec corruption) or when out of data;
pointer to next record on success */
-static __attribute__((nonnull(1,4,6,7,8,9,10,11,12,13), warn_unused_result))
+static __attribute__((nonnull, warn_unused_result))
const mrec_t*
row_log_table_apply_op(
/*===================*/
@@ -1676,12 +1682,6 @@ row_log_table_apply_op(
DB_TRX_ID in old index */
ulint new_trx_id_col, /*!< in: position of
DB_TRX_ID in new index */
- dict_table_t* new_table, /*!< in/out: table
- being rebuilt */
- const dtuple_t* add_cols, /*!< in: default values of
- added columns, or NULL */
- const ulint* col_map, /*!< in: mapping of old column
- numbers to new ones, or NULL */
row_merge_dup_t* dup, /*!< in/out: for reporting
duplicate key errors */
dberr_t* error, /*!< out: DB_SUCCESS
@@ -1694,13 +1694,14 @@ row_log_table_apply_op(
ulint* offsets) /*!< in/out: work area
for parsing mrec */
{
- dict_index_t* new_index = dict_table_get_first_index(new_table);
+ const row_log_t*log = dup->index->online_log;
+ dict_index_t* new_index = dict_table_get_first_index(log->table);
ulint extra_size;
const mrec_t* next_mrec;
dtuple_t* old_pk;
ut_ad(dict_index_is_clust(dup->index));
- ut_ad(dup->index->table != new_table);
+ ut_ad(dup->index->table != log->table);
*error = DB_SUCCESS;
@@ -1747,8 +1748,7 @@ row_log_table_apply_op(
trx_read_trx_id(db_trx_id))) {
*error = row_log_table_apply_insert(
thr, mrec, offsets, offsets_heap,
- add_cols, col_map,
- heap, new_table, dup);
+ heap, dup);
}
}
break;
@@ -1772,7 +1772,7 @@ row_log_table_apply_op(
*error = row_log_table_apply_delete(
thr, trx_id_col, new_trx_id_col,
mrec, offsets, offsets_heap, heap,
- new_table);
+ log->table);
break;
case ROW_T_UPDATE:
/* Logically, the log entry consists of the
@@ -1918,8 +1918,7 @@ row_log_table_apply_op(
*error = row_log_table_apply_update(
thr, trx_id_col, new_trx_id_col,
mrec, offsets, offsets_heap,
- add_cols, col_map,
- heap, new_table, dup, old_pk);
+ heap, dup, old_pk);
}
}
@@ -1934,16 +1933,11 @@ row_log_table_apply_op(
/******************************************************//**
Applies operations to a table was rebuilt.
@return DB_SUCCESS, or error code on failure */
-static __attribute__((nonnull(1,3,4), warn_unused_result))
+static __attribute__((nonnull, warn_unused_result))
dberr_t
row_log_table_apply_ops(
/*====================*/
que_thr_t* thr, /*!< in: query graph */
- const dtuple_t* add_cols,
- /*!< in: default values of
- added columns, or NULL */
- const ulint* col_map,/*!< in: mapping of old column
- numbers to new ones, or NULL */
row_merge_dup_t*dup) /*!< in/out: for reporting duplicate key
errors */
{
@@ -2118,7 +2112,6 @@ all_done:
(&index->online_log->head.buf)[1] - mrec_end);
mrec = row_log_table_apply_op(
thr, trx_id_col, new_trx_id_col,
- index->online_log->table, add_cols, col_map,
dup, &error, offsets_heap, heap,
index->online_log->head.buf,
(&index->online_log->head.buf)[1], offsets);
@@ -2217,7 +2210,6 @@ all_done:
next_mrec = row_log_table_apply_op(
thr, trx_id_col, new_trx_id_col,
- index->online_log->table, add_cols, col_map,
dup, &error, offsets_heap, heap,
mrec, mrec_end, offsets);
@@ -2284,13 +2276,8 @@ row_log_table_apply(
que_thr_t* thr, /*!< in: query graph */
dict_table_t* old_table,
/*!< in: old table */
- struct TABLE* table, /*!< in/out: MySQL table
+ struct TABLE* table) /*!< in/out: MySQL table
(for reporting duplicates) */
- const dtuple_t* add_cols,
- /*!< in: default values of
- added columns, or NULL */
- const ulint* col_map)/*!< in: mapping of old column
- numbers to new ones, or NULL */
{
dberr_t error;
dict_index_t* clust_index;
@@ -2317,7 +2304,7 @@ row_log_table_apply(
ut_ad(0);
error = DB_ERROR;
} else {
- error = row_log_table_apply_ops(thr, add_cols, col_map, &dup);
+ error = row_log_table_apply_ops(thr, &dup);
}
rw_lock_x_unlock(dict_index_get_lock(clust_index));
@@ -2335,8 +2322,13 @@ row_log_allocate(
dict_index_t* index, /*!< in/out: index */
dict_table_t* table, /*!< in/out: new table being rebuilt,
or NULL when creating a secondary index */
- bool same_pk)/*!< in: whether the definition of the
+ bool same_pk,/*!< in: whether the definition of the
PRIMARY KEY has remained the same */
+ const dtuple_t* add_cols,
+ /*!< in: default values of
+ added columns, or NULL */
+ const ulint* col_map)/*!< in: mapping of old column
+ numbers to new ones, or NULL if !table */
{
byte* buf;
row_log_t* log;
@@ -2346,6 +2338,8 @@ row_log_allocate(
ut_ad(dict_index_is_clust(index) == !!table);
ut_ad(!table || index->table != table);
ut_ad(same_pk || table);
+ ut_ad(!table || col_map);
+ ut_ad(!add_cols || col_map);
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(dict_index_get_lock(index), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
@@ -2363,6 +2357,8 @@ row_log_allocate(
log->trx_rb = NULL;
log->table = table;
log->same_pk = same_pk;
+ log->add_cols = add_cols;
+ log->col_map = col_map;
log->error = DB_SUCCESS;
log->max_trx = 0;
log->head.block = buf;
No bundle (reason: useless for push emails).| Thread |
|---|
| • bzr push into mysql-trunk-wl6255 branch (marko.makela:3944 to 3946) WL#6255 | marko.makela | 6 Jun |