3937 Marko Mäkelä 2012-06-05
WL#6255 ALTER_COLUMN_ORDER and DROP_COLUMN (DROP COLUMN and column reorder)
ha_innobase_inplace_ctx(): Add col_map for mapping old column numbers
to new ones when rebuilding a table.
innobase_build_col_map(): Map old column numbers to new ones. Dropped
columns are indicated by ULINT_UNDEFINED.
prepare_inplace_alter_table_dict(): Invoke innobase_build_col_map()
whenever rebuilding the table.
row_log_table_apply(), row_merge_build_indexes(), 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_build_indexes(): Add the
parameter col_map.
row_merge_buf_add(): Remove the tweaks for FTS_DOC_ID. They will now
be handled by the col_map.
row_merge_read_clustered_index(): Add the parameter col_map. Remove
the array nullable[]. No longer tweak the DATA_NOT_NULL field of the
row tuple, because it will have been set up in row_build().
modified:
mysql-test/r/alter_table.result
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/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
3936 Marko Mäkelä 2012-06-04
fts_get_doc_id_from_rec(): Remove an unnecessary cast and add assertions.
modified:
storage/innobase/fts/fts0fts.cc
3935 Marko Mäkelä 2012-06-04
Crank up Valgrind instrumentation.
dtuple_create_from_mem(): Add Valgrind instrumentation for tuple->fields.
dtuple_create(): Remove the Valgrind instrumentation.
modified:
storage/innobase/include/data0data.ic
3934 Marko Mäkelä 2012-06-04
WL#6255 bug fix: Disallow online addition of a hidden FTS_DOC_ID.
If FTS_DOC_ID is being explicitly added or renamed by the user,
that is OK, because the column is supposed to be unique already.
modified:
mysql-test/suite/innodb/r/innodb-alter.result
mysql-test/suite/innodb/t/innodb-alter.test
storage/innobase/handler/ha_innodb.h
storage/innobase/handler/handler0alter.cc
=== modified file 'mysql-test/r/alter_table.result'
--- a/mysql-test/r/alter_table.result revid:marko.makela@stripped105343-n95ug4qqgn787nea
+++ b/mysql-test/r/alter_table.result revid:marko.makela@stripped75k2gp2kp
@@ -1704,8 +1704,8 @@ ALTER TABLE tm1 ADD PRIMARY KEY(a);
affected rows: 2
info: Records: 2 Duplicates: 0 Warnings: 0
ALTER TABLE ti1 DROP COLUMN d2;
-affected rows: 2
-info: Records: 2 Duplicates: 0 Warnings: 0
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
ALTER TABLE tm1 DROP COLUMN d2;
affected rows: 2
info: Records: 2 Duplicates: 0 Warnings: 0
@@ -1752,14 +1752,14 @@ ALTER TABLE tm1 MODIFY COLUMN e INT;
affected rows: 2
info: Records: 2 Duplicates: 0 Warnings: 0
ALTER TABLE ti1 MODIFY COLUMN e INT AFTER h;
-affected rows: 2
-info: Records: 2 Duplicates: 0 Warnings: 0
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
ALTER TABLE tm1 MODIFY COLUMN e INT AFTER h;
affected rows: 2
info: Records: 2 Duplicates: 0 Warnings: 0
ALTER TABLE ti1 MODIFY COLUMN e INT FIRST;
-affected rows: 2
-info: Records: 2 Duplicates: 0 Warnings: 0
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
ALTER TABLE tm1 MODIFY COLUMN e INT FIRST;
affected rows: 2
info: Records: 2 Duplicates: 0 Warnings: 0
@@ -1782,14 +1782,14 @@ ALTER TABLE tm1 MODIFY COLUMN h VARCHAR(
affected rows: 2
info: Records: 2 Duplicates: 0 Warnings: 0
ALTER TABLE ti1 MODIFY COLUMN h VARCHAR(30) AFTER d;
-affected rows: 2
-info: Records: 2 Duplicates: 0 Warnings: 0
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
ALTER TABLE tm1 MODIFY COLUMN h VARCHAR(30) AFTER d;
affected rows: 2
info: Records: 2 Duplicates: 0 Warnings: 0
ALTER TABLE ti1 DROP COLUMN h;
-affected rows: 2
-info: Records: 2 Duplicates: 0 Warnings: 0
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
ALTER TABLE tm1 DROP COLUMN h;
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@stripped343-n95ug4qqgn787nea
+++ b/mysql-test/suite/innodb/r/innodb-table-online.result revid:marko.makela@stripped0604214744-29tpakp75k2gp2kp
@@ -215,7 +215,7 @@ ERROR 42000: Multiple primary key define
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 c3 c3 TEXT NULL, CHANGE c1 c1 INT AFTER c22f;
SET DEBUG_SYNC = 'now WAIT_FOR rebuilt3';
SELECT name, count FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE subsystem = 'ddl';
name count
@@ -254,16 +254,16 @@ ALTER TABLE t1 DROP PRIMARY KEY, ADD PRI
ERROR 23000: Duplicate entry '' for key 'PRIMARY'
UPDATE t1 SET c3 = NULL WHERE c3 = '';
SET lock_wait_timeout = 1;
-ALTER TABLE t1 ADD PRIMARY KEY c3p5(c3(5));
+ALTER TABLE t1 DROP COLUMN c22f, ADD PRIMARY KEY c3p5(c3(5));
ERROR 42000: Multiple primary key defined
-ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY c3p5(c3(5)),
+ALTER TABLE t1 DROP COLUMN c22f, DROP PRIMARY KEY, ADD PRIMARY KEY c3p5(c3(5)),
ALGORITHM = INPLACE;
ERROR 22004: Invalid use of NULL value
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;
+ALTER TABLE t1 MODIFY c3 TEXT NOT NULL, DROP COLUMN c22f;
SET DEBUG_SYNC = 'now WAIT_FOR c3p5_created0';
BEGIN;
INSERT INTO t1 VALUES(347,33101,'Pikku kakkosen posti');
@@ -273,7 +273,7 @@ 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, ADD PRIMARY KEY c3p5(c3(5));
+ALTER TABLE t1 DROP PRIMARY KEY, DROP COLUMN c22f, ADD PRIMARY KEY c3p5(c3(5));
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);
@@ -301,14 +301,14 @@ ERROR HY000: Lock wait timeout exceeded;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` int(11) NOT NULL,
`c22f` int(11) NOT NULL DEFAULT '0',
+ `c1` int(11) NOT NULL DEFAULT '0',
`c3` text NOT NULL,
PRIMARY KEY (`c1`,`c22f`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT
-ALTER TABLE t1 ROW_FORMAT=REDUNDANT, ALGORITHM = INPLACE;
+ALTER TABLE t1 DROP COLUMN c3, ROW_FORMAT=REDUNDANT, ALGORITHM = INPLACE;
SELECT * FROM t1;
-c1 c22f c3
+c22f c1
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@stripped5343-n95ug4qqgn787nea
+++ b/mysql-test/suite/innodb/t/innodb-table-online.test revid:marko.makela@stripped604214744-29tpakp75k2gp2kp
@@ -221,7 +221,7 @@ ALTER TABLE t1 ADD PRIMARY KEY(c22f), CH
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 c3 c3 TEXT NULL, CHANGE c1 c1 INT AFTER c22f;
connection default;
SET DEBUG_SYNC = 'now WAIT_FOR rebuilt3';
@@ -251,9 +251,9 @@ ALTER TABLE t1 DROP PRIMARY KEY, ADD PRI
UPDATE t1 SET c3 = NULL WHERE c3 = '';
SET lock_wait_timeout = 1;
--error ER_MULTIPLE_PRI_KEY
-ALTER TABLE t1 ADD PRIMARY KEY c3p5(c3(5));
+ALTER TABLE t1 DROP COLUMN c22f, ADD PRIMARY KEY c3p5(c3(5));
--error ER_INVALID_USE_OF_NULL
-ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY c3p5(c3(5)),
+ALTER TABLE t1 DROP COLUMN c22f, DROP PRIMARY KEY, ADD PRIMARY KEY c3p5(c3(5)),
ALGORITHM = INPLACE;
--error ER_INVALID_USE_OF_NULL
@@ -262,7 +262,7 @@ 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;
+ALTER TABLE t1 MODIFY c3 TEXT NOT NULL, DROP COLUMN c22f;
connection default;
@@ -284,7 +284,7 @@ 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, ADD PRIMARY KEY c3p5(c3(5));
+ALTER TABLE t1 DROP PRIMARY KEY, DROP COLUMN c22f, ADD PRIMARY KEY c3p5(c3(5));
connection default;
SET DEBUG_SYNC = 'now WAIT_FOR c3p5_created';
@@ -342,7 +342,7 @@ reap;
SHOW CREATE TABLE t1;
# The source tablespace was discarded during the previous online rebuild.
# The rebuild will re-create t1 as an empty table.
-ALTER TABLE t1 ROW_FORMAT=REDUNDANT, ALGORITHM = INPLACE;
+ALTER TABLE t1 DROP COLUMN c3, ROW_FORMAT=REDUNDANT, ALGORITHM = INPLACE;
SELECT * FROM t1;
SET DEBUG_SYNC = 'RESET';
=== modified file 'storage/innobase/fts/fts0fts.cc'
--- a/storage/innobase/fts/fts0fts.cc revid:marko.makela@strippedqqgn787nea
+++ b/storage/innobase/fts/fts0fts.cc revid:marko.makela@stripped
@@ -4853,13 +4853,13 @@ fts_get_doc_id_from_rec(
col_no = dict_col_get_clust_pos(
&table->cols[table->fts->doc_col], clust_index);
+ ut_ad(col_no != ULINT_UNDEFINED);
- /* We have no choice but to cast rec here :-( */
- data = rec_get_nth_field((rec_t*) rec, offsets, col_no, &len);
+ data = rec_get_nth_field(rec, offsets, col_no, &len);
ut_a(len == 8);
- ut_a(len == sizeof(doc_id));
- doc_id = (doc_id_t) mach_read_from_8(data);
+ ut_ad(8 == sizeof(doc_id));
+ doc_id = static_cast<doc_id_t>(mach_read_from_8(data));
return(doc_id);
}
=== modified file 'storage/innobase/handler/handler0alter.cc'
--- a/storage/innobase/handler/handler0alter.cc revid:marko.makela@oracle.com-20120604105343-n95ug4qqgn787nea
+++ b/storage/innobase/handler/handler0alter.cc revid:marko.makela@oracle.com-20120604214744-29tpakp75k2gp2kp
@@ -59,12 +59,12 @@ static const Alter_inplace_info::HA_ALTE
| Alter_inplace_info::CHANGE_CREATE_OPTION
| Alter_inplace_info::ALTER_COLUMN_NULLABLE
| Alter_inplace_info::ALTER_COLUMN_NOT_NULLABLE
+ | Alter_inplace_info::ALTER_COLUMN_ORDER
+ | Alter_inplace_info::DROP_COLUMN
/*
| Alter_inplace_info::ALTER_COLUMN_TYPE
- | Alter_inplace_info::ALTER_COLUMN_EQUAL_PACK_LENGTH,
- | Alter_inplace_info::ALTER_COLUMN_ORDER
+ | Alter_inplace_info::ALTER_COLUMN_EQUAL_PACK_LENGTH
| Alter_inplace_info::ADD_COLUMN
- | Alter_inplace_info::DROP_COLUMN
*/
;
@@ -1759,6 +1759,8 @@ public:
trx_t* trx;
/** table where the indexes are being created or dropped */
dict_table_t* indexed_table;
+ /** mapping of old column numbers to new ones, or NULL */
+ const ulint* col_map;
ha_innobase_inplace_ctx(trx_t* user_trx,
dict_index_t** add_arg,
const ulint* add_key_numbers_arg,
@@ -1772,7 +1774,8 @@ public:
bool online_arg,
mem_heap_t* heap_arg,
trx_t* trx_arg,
- dict_table_t* indexed_table_arg) :
+ dict_table_t* indexed_table_arg,
+ const ulint* col_map_arg) :
inplace_alter_handler_ctx(),
add (add_arg), add_key_numbers (add_key_numbers_arg),
num_to_add (num_to_add_arg),
@@ -1780,7 +1783,8 @@ public:
drop_fk (drop_fk_arg), num_to_drop_fk (num_to_drop_fk_arg),
add_fk (add_fk_arg), num_to_add_fk (num_to_add_fk_arg),
online (online_arg), heap (heap_arg), trx (trx_arg),
- indexed_table (indexed_table_arg) {
+ indexed_table (indexed_table_arg),
+ col_map (col_map_arg) {
#ifdef UNIV_DEBUG
for (ulint i = 0; i < num_to_add; i++) {
ut_ad(!add[i]->to_be_dropped);
@@ -2041,6 +2045,106 @@ innobase_check_foreigns(
return(false);
}
+/** Construct the translation table for reordering, dropping or
+adding columns.
+
+@param ha_alter_info Data used during in-place alter
+@param altered_table MySQL table that is being altered
+@param table MySQL table as it is before the ALTER operation
+@param new_table InnoDB table corresponding to MySQL altered_table
+@param old_table InnoDB table corresponding to MYSQL table
+@param heap Memory heap where allocated
+@return array of integers, mapping column numbers in the table
+to column numbers in altered_table */
+static __attribute__((nonnull, warn_unused_result))
+const ulint*
+innobase_build_col_map(
+/*===================*/
+ Alter_inplace_info* ha_alter_info,
+ const TABLE* altered_table,
+ const TABLE* table,
+ const dict_table_t* new_table,
+ const dict_table_t* old_table,
+ mem_heap_t* heap)
+{
+ DBUG_ENTER("innobase_build_col_map");
+ DBUG_ASSERT(altered_table != table);
+ DBUG_ASSERT(new_table != old_table);
+ DBUG_ASSERT(dict_table_get_n_cols(new_table)
+ >= altered_table->s->fields + DATA_N_SYS_COLS);
+ DBUG_ASSERT(dict_table_get_n_cols(old_table)
+ >= table->s->fields + DATA_N_SYS_COLS);
+
+ 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);
+ uint i = 0;
+
+ /* Any dropped columns will map to ULINT_UNDEFINED. */
+ for (uint old_i = 0; old_i + DATA_N_SYS_COLS < old_table->n_cols;
+ old_i++) {
+ col_map[old_i] = ULINT_UNDEFINED;
+ }
+
+ while (const Create_field* new_field = cf_it++) {
+ for (uint old_i = 0; table->field[old_i]; old_i++) {
+ const Field* field = table->field[old_i];
+ if (new_field->field == field) {
+ col_map[old_i] = i;
+ goto found_col;
+ }
+ }
+ /* ALTER_ADD_COLUMN */
+ ut_ad(0);//TODO
+found_col:
+ i++;
+ continue;
+ }
+
+ DBUG_ASSERT(i == altered_table->s->fields);
+
+ i = table->s->fields;
+
+ /* Add the InnoDB hidden FTS_DOC_ID column, if any. */
+ if (i + DATA_N_SYS_COLS < old_table->n_cols) {
+ /* There should be exactly one extra field,
+ the FTS_DOC_ID. */
+ DBUG_ASSERT(DICT_TF2_FLAG_IS_SET(old_table,
+ DICT_TF2_FTS_HAS_DOC_ID));
+ DBUG_ASSERT(i + DATA_N_SYS_COLS + 1 == old_table->n_cols);
+ DBUG_ASSERT(!strcmp(dict_table_get_col_name(
+ old_table, table->s->fields),
+ FTS_DOC_ID_COL_NAME));
+ if (altered_table->s->fields + DATA_N_SYS_COLS
+ < new_table->n_cols) {
+ DBUG_ASSERT(DICT_TF2_FLAG_IS_SET(
+ new_table,
+ DICT_TF2_FTS_HAS_DOC_ID));
+ DBUG_ASSERT(altered_table->s->fields
+ + DATA_N_SYS_COLS + 1
+ == new_table->n_cols);
+ col_map[i] = altered_table->s->fields;
+ } else {
+ DBUG_ASSERT(!DICT_TF2_FLAG_IS_SET(
+ new_table,
+ DICT_TF2_FTS_HAS_DOC_ID));
+ col_map[i] = ULINT_UNDEFINED;
+ }
+ } else {
+ DBUG_ASSERT(!DICT_TF2_FLAG_IS_SET(
+ old_table,
+ DICT_TF2_FTS_HAS_DOC_ID));
+ }
+
+ for (; i < old_table->n_cols; i++) {
+ col_map[i] = i + new_table->n_cols - old_table->n_cols;
+ }
+
+ DBUG_RETURN(col_map);
+}
+
/** Update internal structures with concurrent writes blocked,
while preparing ALTER TABLE.
@@ -2096,6 +2200,7 @@ prepare_inplace_alter_table_dict(
ulint new_clustered = 0;
dberr_t error;
THD* user_thd = user_trx->mysql_thd;
+ const ulint* col_map;
const bool locked =
add_fts_doc_id
@@ -2157,10 +2262,9 @@ prepare_inplace_alter_table_dict(
column is to be added, and the primary index definition
is just copied from old table and stored in indexdefs[0] */
DBUG_ASSERT(!add_fts_doc_id || new_clustered);
- DBUG_ASSERT(!!new_clustered
- == ((ha_alter_info->handler_flags
- & INNOBASE_INPLACE_REBUILD)
- || add_fts_doc_id));
+ DBUG_ASSERT(!!new_clustered ==
+ (innobase_need_rebuild(ha_alter_info)
+ || add_fts_doc_id));
/* Allocate memory for dictionary index definitions */
@@ -2242,9 +2346,7 @@ prepare_inplace_alter_table_dict(
| DICT_TF2_FTS;
}
- if (add_fts_doc_id_idx) {
- DBUG_ASSERT(flags2 & DICT_TF2_FTS);
- }
+ DBUG_ASSERT(!add_fts_doc_id_idx || (flags2 & DICT_TF2_FTS));
/* Create the table. */
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
@@ -2335,6 +2437,8 @@ col_fail:
fts_add_doc_id_column(indexed_table, heap);
indexed_table->fts->doc_col = fts_doc_id_col;
ut_ad(fts_doc_id_col == altered_table->s->fields);
+ } else if (indexed_table->fts) {
+ indexed_table->fts->doc_col = fts_doc_id_col;
}
error = row_create_table_for_mysql(indexed_table, trx);
@@ -2379,6 +2483,13 @@ col_fail:
trx_commit_for_mysql(user_trx);
DBUG_RETURN(true);
}
+
+ col_map = innobase_build_col_map(
+ ha_alter_info, altered_table, old_table,
+ indexed_table, user_table, heap);
+ } else {
+ DBUG_ASSERT(!innobase_need_rebuild(ha_alter_info));
+ col_map = NULL;
}
/* Assign table_id, so that no table id of
@@ -2516,11 +2627,6 @@ op_ok:
}
}
- if (indexed_table != user_table && user_table->fts) {
- indexed_table->fts->doc_col
- = user_table->fts->doc_col;
- }
-
ut_ad(trx_get_dict_operation(trx) == op);
}
@@ -2556,7 +2662,7 @@ error_handling:
drop_index, n_drop_index,
drop_foreign, n_drop_foreign,
add_foreign, n_add_foreign,
- !locked, heap, trx, indexed_table);
+ !locked, heap, trx, indexed_table, col_map);
DBUG_RETURN(false);
case DB_TABLESPACE_ALREADY_EXISTS:
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), "(unknown)");
@@ -3076,7 +3182,7 @@ index_needed:
drop_index, n_drop_index,
drop_fk, n_drop_fk,
add_fk, n_add_fk, !locked,
- heap, NULL, indexed_table);
+ heap, NULL, indexed_table, NULL);
}
func_exit:
@@ -3224,7 +3330,8 @@ ok_exit:
prebuilt->trx,
prebuilt->table, ctx->indexed_table,
ctx->online,
- ctx->add, ctx->add_key_numbers, ctx->num_to_add, table);
+ ctx->add, ctx->add_key_numbers, ctx->num_to_add, table,
+ ctx->col_map);
#ifndef DBUG_OFF
oom:
#endif /* !DBUG_OFF */
@@ -3232,7 +3339,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->thr, prebuilt->table, table, ctx->col_map);
}
/* After an error, remove all those index definitions
@@ -3811,8 +3918,8 @@ 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->thr, prebuilt->table, table,
+ ctx->col_map);
switch (error) {
KEY* dup_key;
=== modified file 'storage/innobase/include/data0data.ic'
--- a/storage/innobase/include/data0data.ic revid:marko.makela@stripped
+++ b/storage/innobase/include/data0data.ic revid:marko.makela@oracle.com-20120604214744-29tpakp75k2gp2kp
@@ -407,6 +407,8 @@ dtuple_create_from_mem(
}
}
#endif
+ UNIV_MEM_ASSERT_W(tuple->fields, n_fields * sizeof *tuple->fields);
+ UNIV_MEM_INVALID(tuple->fields, n_fields * sizeof *tuple->fields);
return(tuple);
}
@@ -434,10 +436,6 @@ dtuple_create(
tuple = dtuple_create_from_mem(buf, buf_size, n_fields);
-#ifdef UNIV_DEBUG
- UNIV_MEM_INVALID(tuple->fields, n_fields * sizeof *tuple->fields);
-#endif
-
return(tuple);
}
=== modified file 'storage/innobase/include/row0log.h'
--- a/storage/innobase/include/row0log.h revid:marko.makela@strippedg4qqgn787nea
+++ b/storage/innobase/include/row0log.h revid:marko.makela@strippedp
@@ -176,8 +176,10 @@ 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 ulint* col_map)/*!< in: mapping of old column
+ numbers to new ones, or NULL */
__attribute__((nonnull, warn_unused_result));
/******************************************************//**
=== modified file 'storage/innobase/include/row0merge.h'
--- a/storage/innobase/include/row0merge.h revid:marko.makela@strippedgn787nea
+++ b/storage/innobase/include/row0merge.h revid:marko.makela@stripped
@@ -290,10 +290,13 @@ row_merge_build_indexes(
dict_index_t** indexes, /*!< in: indexes to be created */
const ulint* key_numbers, /*!< in: MySQL key numbers */
ulint n_indexes, /*!< in: size of indexes[] */
- struct TABLE* table) /*!< in/out: MySQL table, for
+ struct TABLE* table, /*!< in/out: MySQL table, for
reporting erroneous key value
if applicable */
- __attribute__((nonnull, warn_unused_result));
+ const ulint* col_map) /*!< in: mapping of old column
+ numbers to new ones, or NULL
+ if old_table == new_table */
+ __attribute__((nonnull(1,2,3,5,6,8), warn_unused_result));
/********************************************************************//**
Write a buffer to a block. */
UNIV_INTERN
=== modified file 'storage/innobase/include/row0row.h'
--- a/storage/innobase/include/row0row.h revid:marko.makela@oracle.com-20120604105343-n95ug4qqgn787nea
+++ b/storage/innobase/include/row0row.h revid:marko.makela@stripped0604214744-29tpakp75k2gp2kp
@@ -143,12 +143,14 @@ row_build(
consulted instead; the user
columns in this table should be
the same columns as in index->table */
+ const ulint* col_map,/*!< in: mapping of old column
+ numbers to new ones, or NULL */
row_ext_t** ext, /*!< out, own: cache of
externally stored column
prefixes, or NULL */
mem_heap_t* heap) /*!< in: memory heap from which
the memory needed is allocated */
- __attribute__((nonnull(2,3,7), warn_unused_result));
+ __attribute__((nonnull(2,3,8), warn_unused_result));
/*******************************************************************//**
Converts an index record to a typed data tuple.
@return index entry built; does not set info_bits, and the data fields
=== modified file 'storage/innobase/row/row0log.cc'
--- a/storage/innobase/row/row0log.cc revid:marko.makela@stripped4qqgn787nea
+++ b/storage/innobase/row/row0log.cc revid:marko.makela@stripped
@@ -1009,6 +1009,8 @@ 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 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 */
@@ -1018,16 +1020,33 @@ row_log_table_apply_convert_mrec(
dtuple_t* row;
/* This is based on row_build(). */
- row = dtuple_create(heap, dict_table_get_n_cols(index->table));
- dict_table_copy_types(row, index->table);
+ row = dtuple_create(heap, dict_table_get_n_cols(new_table));
+ dict_table_copy_types(row, new_table);
for (ulint i = 0; i < rec_offs_n_fields(offsets); i++) {
const dict_field_t* ind_field
= dict_index_get_nth_field(index, i);
+
+ if (ind_field->prefix_len) {
+ /* Column prefixes can only occur in key
+ fields, which cannot be stored externally. For
+ a column prefix, there should also be the full
+ field in the clustered index tuple. The row
+ tuple comprises full fields, not prefixes. */
+ ut_ad(!rec_offs_nth_extern(offsets, i));
+ continue;
+ }
+
const dict_col_t* col
= dict_field_get_col(ind_field);
ulint col_no
- = dict_col_get_no(col);
+ = col_map[dict_col_get_no(col)];
+
+ if (col_no == ULINT_UNDEFINED) {
+ /* dropped column */
+ continue;
+ }
+
dfield_t* dfield
= dtuple_get_nth_field(row, col_no);
ulint len;
@@ -1039,24 +1058,17 @@ row_log_table_apply_convert_mrec(
dict_table_zip_size(index->table),
i, &len, heap);
ut_a(data);
- dfield_set_data(dfield, data, len);
- } else if (ind_field->prefix_len == 0) {
+ } else {
data = rec_get_nth_field(mrec, offsets, i, &len);
- dfield_set_data(dfield, data, len);
}
- ut_ad(dict_col_type_assert_equal(col,
- dfield_get_type(dfield)));
+ dfield_set_data(dfield, data, len);
/* See if any columns were changed to NULL or NOT NULL. */
- /* TODO: adjust for ADD COLUMN, DROP COLUMN */
- if (col_no >= dict_table_get_n_cols(new_table)) {
- continue;
- }
-
const dict_col_t* new_col
= dict_table_get_nth_col(new_table, col_no);
ut_ad(new_col->mtype == col->mtype);
+
/* Assert that prtype matches except for nullability. */
ut_ad(!((new_col->prtype ^ col->prtype) & ~DATA_NOT_NULL));
ut_ad(!((new_col->prtype ^ dfield_get_type(dfield)->prtype)
@@ -1080,9 +1092,6 @@ row_log_table_apply_convert_mrec(
dfield_get_type(dfield)));
}
- /* TODO: convert row to new_table->cols, in case columns are
- added or dropped or reordered */
-
*error = DB_SUCCESS;
return(row);
}
@@ -1166,6 +1175,8 @@ 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 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 */
@@ -1174,7 +1185,7 @@ row_log_table_apply_insert(
{
dberr_t error;
const dtuple_t* row = row_log_table_apply_convert_mrec(
- mrec, dup->index, offsets, heap, new_table,
+ mrec, dup->index, offsets, col_map, heap, new_table,
&error);
ut_ad(!row == (error != DB_SUCCESS));
@@ -1217,7 +1228,7 @@ row_log_table_apply_delete_low(
/* Build a row template for purging secondary index entries. */
row = row_build(
ROW_COPY_DATA, index, btr_pcur_get_rec(pcur),
- offsets, NULL, &ext, heap);
+ offsets, NULL, NULL, &ext, heap);
} else {
row = NULL;
}
@@ -1393,6 +1404,8 @@ 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 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 */
@@ -1416,7 +1429,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, heap, new_table, &error);
+ mrec, dup->index, offsets, col_map, heap, new_table, &error);
ut_ad(!row == (error != DB_SUCCESS));
@@ -1546,7 +1559,8 @@ delete_insert:
the record. */
old_row = row_build(ROW_COPY_DATA, index,
btr_pcur_get_rec(&pcur),
- cur_offsets, NULL, &old_ext, heap);
+ cur_offsets, new_table,
+ col_map, &old_ext, heap);
ut_ad(old_row);
} else {
old_row = NULL;
@@ -1647,6 +1661,8 @@ row_log_table_apply_op(
DB_TRX_ID in new index */
dict_table_t* new_table, /*!< in/out: table
being rebuilt */
+ 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
@@ -1712,7 +1728,7 @@ row_log_table_apply_op(
trx_read_trx_id(db_trx_id))) {
*error = row_log_table_apply_insert(
thr, mrec, offsets, offsets_heap,
- heap, new_table, dup);
+ col_map, heap, new_table, dup);
}
}
break;
@@ -1881,8 +1897,9 @@ row_log_table_apply_op(
trx_read_trx_id(db_trx_id))) {
*error = row_log_table_apply_update(
thr, trx_id_col, new_trx_id_col,
- mrec, offsets, offsets_heap, heap,
- new_table, dup, old_pk);
+ mrec, offsets, offsets_heap,
+ col_map,
+ heap, new_table, dup, old_pk);
}
}
@@ -1902,6 +1919,8 @@ dberr_t
row_log_table_apply_ops(
/*====================*/
que_thr_t* thr, /*!< in: query graph */
+ 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 */
{
@@ -2076,7 +2095,7 @@ 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,
+ index->online_log->table, col_map,
dup, &error, offsets_heap, heap,
index->online_log->head.buf,
(&index->online_log->head.buf)[1], offsets);
@@ -2175,7 +2194,7 @@ all_done:
next_mrec = row_log_table_apply_op(
thr, trx_id_col, new_trx_id_col,
- index->online_log->table,
+ index->online_log->table, col_map,
dup, &error, offsets_heap, heap,
mrec, mrec_end, offsets);
@@ -2242,8 +2261,10 @@ 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 ulint* col_map)/*!< in: mapping of old column
+ numbers to new ones, or NULL */
{
dberr_t error;
dict_index_t* clust_index;
@@ -2270,7 +2291,7 @@ row_log_table_apply(
ut_ad(0);
error = DB_ERROR;
} else {
- error = row_log_table_apply_ops(thr, &dup);
+ error = row_log_table_apply_ops(thr, col_map, &dup);
}
rw_lock_x_unlock(dict_index_get_lock(clust_index));
=== modified file 'storage/innobase/row/row0merge.cc'
--- a/storage/innobase/row/row0merge.cc revid:marko.makela@oracle.com-20120604105343-n95ug4qqgn787nea
+++ b/storage/innobase/row/row0merge.cc revid:marko.makela@stripped0604214744-29tpakp75k2gp2kp
@@ -284,7 +284,7 @@ row_merge_buf_add(
dict_index_t* fts_index,/*!< in: fts index to be created */
const dict_table_t* old_table,/*!< in: original table */
fts_psort_t* psort_info, /*!< in: parallel sort info */
- const dtuple_t* row, /*!< in: row in clustered index */
+ const dtuple_t* row, /*!< in: table row */
const row_ext_t* ext, /*!< in: cache of externally stored
column prefixes, or NULL */
doc_id_t* doc_id) /*!< in/out: Doc ID if we are
@@ -338,35 +338,13 @@ row_merge_buf_add(
const dict_col_t* col;
ulint col_no;
const dfield_t* row_field;
- ibool col_adjusted;
col = ifield->col;
col_no = dict_col_get_no(col);
- col_adjusted = FALSE;
-
- /* If we are creating a FTS index, a new Doc
- ID column is being added, so we need to adjust
- any column number positioned after this Doc ID.
- However, if we are rebuilding the table for adding
- new primary, and if the old table already has
- FTS_DOC_ID, such adjustment is not needed */
- if (*doc_id > 0
- && DICT_TF2_FLAG_IS_SET(index->table,
- DICT_TF2_FTS_ADD_DOC_ID)
- && !DICT_TF2_FLAG_IS_SET(old_table,
- DICT_TF2_FTS_HAS_DOC_ID)
- && col_no > index->table->fts->doc_col) {
-
- ut_ad(index->table->fts);
-
- col_no--;
- col_adjusted = TRUE;
- }
/* Process the Doc ID column */
if (*doc_id > 0
- && col_no == index->table->fts->doc_col
- && !col_adjusted) {
+ && col_no == index->table->fts->doc_col) {
fts_write_doc_id((byte*) &write_doc_id, *doc_id);
/* Note: field->data now points to a value on the
@@ -1235,7 +1213,7 @@ row_merge_skip_rec(
Reads clustered index of the table and create temporary files
containing the index entries for the indexes to be built.
@return DB_SUCCESS or error */
-static __attribute__((nonnull))
+static __attribute__((nonnull(1,2,3,4,6,9,10,13),warn_unused_result))
dberr_t
row_merge_read_clustered_index(
/*===========================*/
@@ -1251,12 +1229,18 @@ row_merge_read_clustered_index(
online */
dict_index_t** index, /*!< in: indexes to be created */
dict_index_t* fts_sort_idx,
- /*!< in: indexes to be created */
- fts_psort_t* psort_info, /*!< in: parallel sort info */
+ /*!< in: full-text index to be created,
+ or NULL */
+ fts_psort_t* psort_info,
+ /*!< in: parallel sort info for
+ fts_sort_idx creation, or NULL */
merge_file_t* files, /*!< in: temporary files */
const ulint* key_numbers,
/*!< in: MySQL key numbers to create */
ulint n_index,/*!< in: number of indexes to create */
+ const ulint* col_map,/*!< in: mapping of old column
+ numbers to new ones, or NULL
+ if old_table == new_table */
row_merge_block_t* block) /*!< in/out: file buffer */
{
dict_index_t* clust_index; /* Clustered index */
@@ -1270,9 +1254,6 @@ row_merge_read_clustered_index(
ulint n_nonnull = 0; /* number of columns
changed to NOT NULL */
ulint* nonnull = NULL; /* NOT NULL columns */
- ulint n_nullable = 0; /* number of columns
- changed to NULL */
- ulint* nullable = NULL;/* NULLable columns */
dict_index_t* fts_index = NULL;/* FTS index */
doc_id_t doc_id = 0;
doc_id_t max_doc_id = 0;
@@ -1281,6 +1262,8 @@ row_merge_read_clustered_index(
ibool fts_pll_sort = FALSE;
ib_int64_t sig_count = 0;
+ ut_ad(old_table == new_table || col_map);
+
trx->op_info = "reading clustered index";
#ifdef FTS_INTERNAL_DIAG_PRINT
@@ -1292,7 +1275,6 @@ row_merge_read_clustered_index(
merge_buf = static_cast<row_merge_buf_t**>(
mem_alloc(n_index * sizeof *merge_buf));
-
for (ulint i = 0; i < n_index; i++) {
if (index[i]->type & DICT_FTS) {
@@ -1335,44 +1317,38 @@ row_merge_read_clustered_index(
btr_pcur_open_at_index_side(
TRUE, clust_index, BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
- if (UNIV_UNLIKELY(old_table != new_table)) {
- ulint n_cols = dict_table_get_n_cols(old_table);
-
- /* A primary key will be created. Identify the
- columns that were flagged NOT NULL in the new table,
- so that we can quickly check that the records in the
- (old) clustered index do not violate the added NOT
- NULL constraints. */
-
- if (!fts_sort_idx) {
- ut_a(n_cols == dict_table_get_n_cols(new_table));
- }
+ if (old_table != new_table) {
+ /* The table is being rebuilt. Identify the columns
+ that were flagged NOT NULL in the new table, so that
+ we can quickly check that the records in the old table
+ do not violate the added NOT NULL constraints. */
nonnull = static_cast<ulint*>(
- mem_alloc(2 * n_cols * sizeof *nonnull));
- nullable = nonnull + n_cols;
+ mem_alloc(dict_table_get_n_cols(new_table)
+ * sizeof *nonnull));
+
+ for (ulint i = 0; i < dict_table_get_n_cols(old_table); i++) {
+ if (dict_table_get_nth_col(old_table, i)->prtype
+ & DATA_NOT_NULL) {
+ continue;
+ }
- for (ulint i = 0; i < n_cols; i++) {
- /* TODO: adjust for ADD COLUMN, DROP COLUMN */
- ulint old_nonnull = DATA_NOT_NULL
- & dict_table_get_nth_col(old_table, i)->prtype;
- ulint new_nonnull = DATA_NOT_NULL
- & dict_table_get_nth_col(new_table, i)->prtype;
+ const ulint j = col_map[i];
- if (old_nonnull == new_nonnull) {
+ if (j == ULINT_UNDEFINED) {
+ /* The column was dropped. */
continue;
}
- if (old_nonnull) {
- nullable[n_nullable++] = i;
- } else {
- nonnull[n_nonnull++] = i;
+ if (dict_table_get_nth_col(new_table, j)->prtype
+ & DATA_NOT_NULL) {
+ nonnull[n_nonnull++] = j;
}
}
- if (!n_nonnull && !n_nullable) {
+ if (!n_nonnull) {
mem_free(nonnull);
- nonnull = nullable = NULL;
+ nonnull = NULL;
}
}
@@ -1535,31 +1511,20 @@ row_merge_read_clustered_index(
/* Build a row based on the clustered index. */
row = row_build(ROW_COPY_POINTERS, clust_index,
- rec, offsets, new_table, &ext, row_heap);
+ rec, offsets, new_table,
+ col_map, &ext, row_heap);
ut_ad(row);
for (ulint i = 0; i < n_nonnull; i++) {
- dfield_t* field
- = &row->fields[nonnull[i]];
- dtype_t* field_type
- = dfield_get_type(field);
+ const dfield_t* field = &row->fields[nonnull[i]];
- ut_ad(!(field_type->prtype & DATA_NOT_NULL));
+ ut_ad(dfield_get_type(field)->prtype & DATA_NOT_NULL);
if (dfield_is_null(field)) {
err = DB_INVALID_NULL;
trx->error_key_num = 0;
goto func_exit;
}
-
- field_type->prtype |= DATA_NOT_NULL;
- }
-
- for (ulint i = 0; i < n_nullable; i++) {
- dtype_t* field_type
- = dfield_get_type(&row->fields[nullable[i]]);
- ut_ad((field_type->prtype & DATA_NOT_NULL));
- field_type->prtype &= ~DATA_NOT_NULL;
}
/* Get the next Doc ID */
@@ -3231,9 +3196,12 @@ row_merge_build_indexes(
dict_index_t** indexes, /*!< in: indexes to be created */
const ulint* key_numbers, /*!< in: MySQL key numbers */
ulint n_indexes, /*!< in: size of indexes[] */
- struct TABLE* table) /*!< in/out: MySQL table, for
+ struct TABLE* table, /*!< in/out: MySQL table, for
reporting erroneous key value
if applicable */
+ const ulint* col_map) /*!< in: mapping of old column
+ numbers to new ones, or NULL
+ if old_table == new_table */
{
merge_file_t* merge_files;
row_merge_block_t* block;
@@ -3247,6 +3215,8 @@ row_merge_build_indexes(
fts_psort_t* merge_info = NULL;
ib_int64_t sig_count = 0;
+ ut_ad(old_table == new_table || col_map);
+
/* Allocate memory for merge file data structure and initialize
fields */
@@ -3294,7 +3264,7 @@ row_merge_build_indexes(
error = row_merge_read_clustered_index(
trx, table, old_table, new_table, online, indexes,
fts_sort_idx, psort_info, merge_files, key_numbers,
- n_indexes, block);
+ n_indexes, col_map, block);
if (error != DB_SUCCESS) {
=== modified file 'storage/innobase/row/row0row.cc'
--- a/storage/innobase/row/row0row.cc revid:marko.makela@stripped
+++ b/storage/innobase/row/row0row.cc revid:marko.makela@stripped-20120604214744-29tpakp75k2gp2kp
@@ -217,6 +217,8 @@ row_build(
of an index, or NULL if
index->table should be
consulted instead */
+ const ulint* col_map,/*!< in: mapping of old column
+ numbers to new ones, or NULL */
row_ext_t** ext, /*!< out, own: cache of
externally stored column
prefixes, or NULL */
@@ -225,14 +227,10 @@ row_build(
{
const byte* copy;
dtuple_t* row;
- const dict_table_t* table;
- ulint n_fields;
ulint n_ext_cols;
ulint* ext_cols = NULL; /* remove warning */
ulint len;
- ulint row_len;
byte* buf;
- ulint i;
ulint j;
mem_heap_t* tmp_heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
@@ -241,6 +239,7 @@ row_build(
ut_ad(index && rec && heap);
ut_ad(dict_index_is_clust(index));
ut_ad(!mutex_own(&trx_sys->mutex));
+ ut_ad(!col_map || col_table);
if (!offsets) {
offsets = rec_get_offsets(rec, index, offsets_,
@@ -272,17 +271,6 @@ row_build(
copy = rec;
}
- table = index->table;
- row_len = dict_table_get_n_cols(table);
-
- row = dtuple_create(heap, row_len);
-
- dict_table_copy_types(row, table);
-
- dtuple_set_info_bits(row, rec_get_info_bits(
- rec, dict_table_is_comp(table)));
-
- n_fields = rec_offs_n_fields(offsets);
n_ext_cols = rec_offs_n_extern(offsets);
if (n_ext_cols) {
ext_cols = static_cast<ulint*>(
@@ -292,33 +280,62 @@ row_build(
/* Avoid a debug assertion in rec_offs_validate(). */
rec_offs_make_valid(copy, index, const_cast<ulint*>(offsets));
- for (i = j = 0; i < n_fields; i++) {
- dict_field_t* ind_field
+ if (!col_table) {
+ ut_ad(!col_map);
+ col_table = index->table;
+ }
+
+ //row = dtuple_copy(heap, default_row);// todo: ADD_COLUMN
+ row = dtuple_create(heap, dict_table_get_n_cols(col_table));
+
+ dict_table_copy_types(row, col_table);
+ dtuple_set_info_bits(row, rec_get_info_bits(
+ copy, rec_offs_comp(offsets)));
+
+ j = 0;
+
+ for (ulint i = 0; i < rec_offs_n_fields(offsets); i++) {
+ const dict_field_t* ind_field
= dict_index_get_nth_field(index, i);
+
+ if (ind_field->prefix_len) {
+ /* Column prefixes can only occur in key
+ fields, which cannot be stored externally. For
+ a column prefix, there should also be the full
+ field in the clustered index tuple. The row
+ tuple comprises full fields, not prefixes. */
+ ut_ad(!rec_offs_nth_extern(offsets, i));
+ continue;
+ }
+
const dict_col_t* col
= dict_field_get_col(ind_field);
ulint col_no
= dict_col_get_no(col);
- dfield_t* dfield
- = dtuple_get_nth_field(row, col_no);
-
- if (ind_field->prefix_len == 0) {
- const byte* field = rec_get_nth_field(
- copy, offsets, i, &len);
+ if (col_map) {
+ col_no = col_map[col_no];
- dfield_set_data(dfield, field, len);
+ if (col_no == ULINT_UNDEFINED) {
+ /* dropped column */
+ continue;
+ }
+ } else if (col_no >= dict_table_get_n_cols(col_table)) {
+ /* dropped last columns */
+ continue;
}
+ dfield_t* dfield = dtuple_get_nth_field(row, col_no);
+
+ const byte* field = rec_get_nth_field(
+ copy, offsets, i, &len);
+
+ dfield_set_data(dfield, field, len);
+
if (rec_offs_nth_extern(offsets, i)) {
dfield_set_ext(dfield);
- if (UNIV_LIKELY_NULL(col_table)) {
- ut_a(col_no
- < dict_table_get_n_cols(col_table));
- col = dict_table_get_nth_col(
- col_table, col_no);
- }
+ col = dict_table_get_nth_col(col_table, col_no);
if (col->ord_part) {
/* We will have to fetch prefixes of
=== modified file 'storage/innobase/row/row0undo.cc'
--- a/storage/innobase/row/row0undo.cc revid:marko.makela@stripped05343-n95ug4qqgn787nea
+++ b/storage/innobase/row/row0undo.cc revid:marko.makela@stripped75k2gp2kp
@@ -216,7 +216,8 @@ row_undo_search_clust_to_pcur(
}
node->row = row_build(ROW_COPY_DATA, clust_index, rec,
- offsets, NULL, ext, node->heap);
+ offsets, NULL,
+ NULL, ext, node->heap);
if (node->update) {
node->undo_row = dtuple_copy(node->row, node->heap);
row_upd_replace(node->undo_row, &node->undo_ext,
=== modified file 'storage/innobase/row/row0upd.cc'
--- a/storage/innobase/row/row0upd.cc revid:marko.makela@strippednea
+++ b/storage/innobase/row/row0upd.cc revid:marko.makela@stripped
@@ -1584,7 +1584,7 @@ row_upd_store_row(
}
node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets,
- NULL, ext, node->heap);
+ NULL, NULL, ext, node->heap);
if (node->is_delete) {
node->upd_row = NULL;
node->upd_ext = NULL;
=== modified file 'storage/innobase/row/row0vers.cc'
--- a/storage/innobase/row/row0vers.cc revid:marko.makela@strippedn787nea
+++ b/storage/innobase/row/row0vers.cc revid:marko.makela@stripped
@@ -163,7 +163,8 @@ row_vers_impl_x_locked_low(
columns. */
row = row_build(ROW_COPY_POINTERS, clust_index, prev_version,
- clust_offsets, NULL, &ext, heap);
+ clust_offsets,
+ NULL, NULL, &ext, heap);
entry = row_build_index_entry(row, ext, index, heap);
@@ -383,7 +384,8 @@ row_vers_old_has_index_entry(
Thus, it is safe to fetch the prefixes for
externally stored columns. */
row = row_build(ROW_COPY_POINTERS, clust_index,
- rec, clust_offsets, NULL, &ext, heap);
+ rec, clust_offsets,
+ NULL, NULL, &ext, heap);
entry = row_build_index_entry(row, ext, index, heap);
/* If entry == NULL, the record contains unset BLOB
@@ -444,7 +446,7 @@ row_vers_old_has_index_entry(
externally stored columns. */
row = row_build(ROW_COPY_POINTERS, clust_index,
prev_version, clust_offsets,
- NULL, &ext, heap);
+ NULL, NULL, &ext, heap);
entry = row_build_index_entry(row, ext, index, heap);
/* If entry == NULL, the record contains unset
No bundle (reason: useless for push emails).| Thread |
|---|
| • bzr push into mysql-trunk-wl6255 branch (marko.makela:3934 to 3937) WL#6255 | marko.makela | 4 Jun |