mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-16330 Allow instant change of WITH SYSTEM VERSIONING column attribute
Changing columns WITH/WITHOUT SYSTEM VERSIONING doens't require to read data at all. Thus it should be an instant operation. Patch also fixes a bug when ALTER_COLUMN_UNVERSIONED wasn't passed to InnoDB to change its internal structures. change_field_versioning_try(): apply WITH/WITHOUT SYSTEM VERSIONING change in SYS_COLUMNS for one field. change_fields_versioning_try(): apply WITH/WITHOUT SYSTEM VERSIONING change in SYS_COLUMNS for every changed field in a table. change_fields_versioning_cache(): update cache for versioning property of columns.
This commit is contained in:
committed by
Marko Mäkelä
parent
ff09512e07
commit
9dc81f7d38
@@ -379,3 +379,99 @@ DROP TABLE tts;
|
||||
DROP TABLE ttx;
|
||||
DROP FUNCTION fts;
|
||||
DROP FUNCTION ftx;
|
||||
#
|
||||
# MDEV-16330 Allow instant change of WITH SYSTEM VERSIONING column attribute
|
||||
#
|
||||
SET @@SYSTEM_VERSIONING_ALTER_HISTORY=KEEP;
|
||||
CREATE TABLE t (
|
||||
a INT,
|
||||
b INT,
|
||||
row_start BIGINT UNSIGNED AS ROW START INVISIBLE,
|
||||
row_end BIGINT UNSIGNED AS ROW END INVISIBLE,
|
||||
PERIOD FOR SYSTEM_TIME(row_start, row_end)
|
||||
) WITH SYSTEM VERSIONING ENGINE=INNODB;
|
||||
INSERT INTO t VALUES (1,1);
|
||||
# without table rebuild
|
||||
SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c
|
||||
INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t
|
||||
ON c.table_id=t.table_id
|
||||
WHERE t.name='test/t' AND c.name='a';
|
||||
prtype
|
||||
50179
|
||||
ALTER TABLE t
|
||||
CHANGE a a INT WITHOUT SYSTEM VERSIONING;
|
||||
affected rows: 0
|
||||
info: Records: 0 Duplicates: 0 Warnings: 0
|
||||
SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c
|
||||
INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t
|
||||
ON c.table_id=t.table_id
|
||||
WHERE t.name='test/t' AND c.name='a';
|
||||
prtype
|
||||
1027
|
||||
UPDATE t SET a=11;
|
||||
SELECT COUNT(*) FROM t FOR SYSTEM_TIME ALL;
|
||||
COUNT(*)
|
||||
1
|
||||
# with table rebuild
|
||||
SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c
|
||||
INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t
|
||||
ON c.table_id=t.table_id
|
||||
WHERE t.name='test/t' AND c.name='a';
|
||||
prtype
|
||||
1027
|
||||
ALTER TABLE t
|
||||
CHANGE a a INT WITH SYSTEM VERSIONING,
|
||||
ADD PRIMARY KEY pk(a);
|
||||
affected rows: 0
|
||||
info: Records: 0 Duplicates: 0 Warnings: 0
|
||||
SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c
|
||||
INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t
|
||||
ON c.table_id=t.table_id
|
||||
WHERE t.name='test/t' AND c.name='a';
|
||||
prtype
|
||||
50435
|
||||
UPDATE t SET a=1;
|
||||
SELECT COUNT(*) FROM t FOR SYSTEM_TIME ALL;
|
||||
COUNT(*)
|
||||
2
|
||||
SHOW CREATE TABLE t;
|
||||
Table Create Table
|
||||
t CREATE TABLE `t` (
|
||||
`a` int(11) NOT NULL,
|
||||
`b` int(11) DEFAULT NULL,
|
||||
`row_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START INVISIBLE,
|
||||
`row_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END INVISIBLE,
|
||||
PRIMARY KEY (`a`,`row_end`),
|
||||
PERIOD FOR SYSTEM_TIME (`row_start`, `row_end`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
|
||||
# handles VIRTUAL columns too
|
||||
CREATE OR REPLACE TABLE t (
|
||||
a INT AS (b + 1),
|
||||
b INT,
|
||||
row_start BIGINT UNSIGNED AS ROW START INVISIBLE,
|
||||
row_end BIGINT UNSIGNED AS ROW END INVISIBLE,
|
||||
PERIOD FOR SYSTEM_TIME(row_start, row_end)
|
||||
) WITH SYSTEM VERSIONING ENGINE=INNODB;
|
||||
INSERT INTO t VALUES (DEFAULT, 1);
|
||||
SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c
|
||||
INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t
|
||||
ON c.table_id=t.table_id
|
||||
WHERE t.name='test/t' AND c.name='b';
|
||||
prtype
|
||||
50179
|
||||
ALTER TABLE t
|
||||
CHANGE b b INT WITHOUT SYSTEM VERSIONING;
|
||||
affected rows: 0
|
||||
info: Records: 0 Duplicates: 0 Warnings: 0
|
||||
SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c
|
||||
INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t
|
||||
ON c.table_id=t.table_id
|
||||
WHERE t.name='test/t' AND c.name='b';
|
||||
prtype
|
||||
1027
|
||||
UPDATE t SET b=11;
|
||||
SELECT COUNT(*) FROM t FOR SYSTEM_TIME ALL;
|
||||
COUNT(*)
|
||||
1
|
||||
DROP TABLE t;
|
||||
SET @@SYSTEM_VERSIONING_ALTER_HISTORY=ERROR;
|
||||
|
@@ -0,0 +1,86 @@
|
||||
CREATE OR REPLACE TABLE t1 (
|
||||
a INT,
|
||||
b INT,
|
||||
row_start BIGINT UNSIGNED AS ROW START INVISIBLE,
|
||||
row_end BIGINT UNSIGNED AS ROW END INVISIBLE,
|
||||
PERIOD FOR SYSTEM_TIME(row_start, row_end)
|
||||
) WITH SYSTEM VERSIONING ENGINE=INNODB;
|
||||
CREATE OR REPLACE TABLE t2 (
|
||||
a INT WITHOUT SYSTEM VERSIONING,
|
||||
b INT,
|
||||
row_start BIGINT UNSIGNED AS ROW START INVISIBLE,
|
||||
row_end BIGINT UNSIGNED AS ROW END INVISIBLE,
|
||||
PERIOD FOR SYSTEM_TIME(row_start, row_end)
|
||||
) WITH SYSTEM VERSIONING ENGINE=INNODB;
|
||||
INSERT INTO t1 VALUES (1,1);
|
||||
INSERT INTO t2 VALUES (1,1);
|
||||
SET @@SYSTEM_VERSIONING_ALTER_HISTORY=KEEP;
|
||||
# without rebuild
|
||||
ALTER TABLE t1
|
||||
CHANGE a a INT WITHOUT SYSTEM VERSIONING,
|
||||
ALGORITHM=INSTANT;
|
||||
affected rows: 0
|
||||
info: Records: 0 Duplicates: 0 Warnings: 0
|
||||
ALTER TABLE t2
|
||||
CHANGE a a INT WITH SYSTEM VERSIONING,
|
||||
ADD PRIMARY KEY pk (a),
|
||||
ALGORITHM=INSTANT;
|
||||
ERROR 0A000: ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=INPLACE
|
||||
# with rebuild
|
||||
ALTER TABLE t2
|
||||
CHANGE a a INT WITH SYSTEM VERSIONING,
|
||||
ADD PRIMARY KEY pk (a);
|
||||
affected rows: 0
|
||||
info: Records: 0 Duplicates: 0 Warnings: 0
|
||||
UPDATE t1 SET a=2;
|
||||
SELECT COUNT(*) FROM t1 FOR SYSTEM_TIME ALL;
|
||||
COUNT(*)
|
||||
1
|
||||
UPDATE t2 SET a=2;
|
||||
SELECT COUNT(*) FROM t2 FOR SYSTEM_TIME ALL;
|
||||
COUNT(*)
|
||||
2
|
||||
DROP TABLE t1, t2;
|
||||
# rollback ALTER TABLE: nothing should change
|
||||
CREATE TABLE t (
|
||||
a INT,
|
||||
b INT,
|
||||
row_start BIGINT UNSIGNED AS ROW START INVISIBLE,
|
||||
row_end BIGINT UNSIGNED AS ROW END INVISIBLE,
|
||||
PERIOD FOR SYSTEM_TIME(row_start, row_end)
|
||||
) WITH SYSTEM VERSIONING ENGINE=INNODB;
|
||||
INSERT INTO t VALUES (1, 1);
|
||||
SELECT C.PRTYPE FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS C
|
||||
JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t ON C.TABLE_ID=t.TABLE_ID
|
||||
WHERE t.NAME='test/t' AND C.NAME='b';
|
||||
PRTYPE
|
||||
50179
|
||||
SET @@SYSTEM_VERSIONING_ALTER_HISTORY=KEEP;
|
||||
SET @SAVED_DEBUG_DBUG = @@SESSION.DEBUG_DBUG;
|
||||
SET DEBUG_DBUG='+d,ib_commit_inplace_fail_1';
|
||||
ALTER TABLE t
|
||||
CHANGE b b INT WITHOUT SYSTEM VERSIONING;
|
||||
ERROR HY000: Internal error: Injected error!
|
||||
SET DEBUG_DBUG = @SAVED_DEBUG_DBUG;
|
||||
SELECT C.PRTYPE FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS C
|
||||
JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t ON C.TABLE_ID=t.TABLE_ID
|
||||
WHERE t.NAME='test/t' AND C.NAME='b';
|
||||
PRTYPE
|
||||
50179
|
||||
SHOW CREATE TABLE t;
|
||||
Table Create Table
|
||||
t CREATE TABLE `t` (
|
||||
`a` int(11) DEFAULT NULL,
|
||||
`b` int(11) DEFAULT NULL,
|
||||
`row_start` bigint(20) unsigned GENERATED ALWAYS AS ROW START INVISIBLE,
|
||||
`row_end` bigint(20) unsigned GENERATED ALWAYS AS ROW END INVISIBLE,
|
||||
PERIOD FOR SYSTEM_TIME (`row_start`, `row_end`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
|
||||
SELECT COUNT(*) FROM t FOR SYSTEM_TIME ALL;
|
||||
COUNT(*)
|
||||
1
|
||||
UPDATE t SET b=11;
|
||||
SELECT COUNT(*) FROM t FOR SYSTEM_TIME ALL;
|
||||
COUNT(*)
|
||||
2
|
||||
DROP TABLE t;
|
@@ -1,5 +1,4 @@
|
||||
-- source include/have_innodb.inc
|
||||
-- source include/not_embedded.inc
|
||||
|
||||
set default_storage_engine= innodb;
|
||||
|
||||
@@ -411,3 +410,85 @@ DROP TABLE tts;
|
||||
DROP TABLE ttx;
|
||||
DROP FUNCTION fts;
|
||||
DROP FUNCTION ftx;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-16330 Allow instant change of WITH SYSTEM VERSIONING column attribute
|
||||
--echo #
|
||||
|
||||
SET @@SYSTEM_VERSIONING_ALTER_HISTORY=KEEP;
|
||||
CREATE TABLE t (
|
||||
a INT,
|
||||
b INT,
|
||||
row_start BIGINT UNSIGNED AS ROW START INVISIBLE,
|
||||
row_end BIGINT UNSIGNED AS ROW END INVISIBLE,
|
||||
PERIOD FOR SYSTEM_TIME(row_start, row_end)
|
||||
) WITH SYSTEM VERSIONING ENGINE=INNODB;
|
||||
|
||||
INSERT INTO t VALUES (1,1);
|
||||
|
||||
--echo # without table rebuild
|
||||
SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c
|
||||
INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t
|
||||
ON c.table_id=t.table_id
|
||||
WHERE t.name='test/t' AND c.name='a';
|
||||
--enable_info
|
||||
ALTER TABLE t
|
||||
CHANGE a a INT WITHOUT SYSTEM VERSIONING;
|
||||
--disable_info
|
||||
SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c
|
||||
INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t
|
||||
ON c.table_id=t.table_id
|
||||
WHERE t.name='test/t' AND c.name='a';
|
||||
|
||||
UPDATE t SET a=11;
|
||||
SELECT COUNT(*) FROM t FOR SYSTEM_TIME ALL;
|
||||
|
||||
--echo # with table rebuild
|
||||
SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c
|
||||
INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t
|
||||
ON c.table_id=t.table_id
|
||||
WHERE t.name='test/t' AND c.name='a';
|
||||
--enable_info
|
||||
ALTER TABLE t
|
||||
CHANGE a a INT WITH SYSTEM VERSIONING,
|
||||
ADD PRIMARY KEY pk(a);
|
||||
--disable_info
|
||||
SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c
|
||||
INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t
|
||||
ON c.table_id=t.table_id
|
||||
WHERE t.name='test/t' AND c.name='a';
|
||||
|
||||
UPDATE t SET a=1;
|
||||
SELECT COUNT(*) FROM t FOR SYSTEM_TIME ALL;
|
||||
|
||||
SHOW CREATE TABLE t;
|
||||
|
||||
-- echo # handles VIRTUAL columns too
|
||||
CREATE OR REPLACE TABLE t (
|
||||
a INT AS (b + 1),
|
||||
b INT,
|
||||
row_start BIGINT UNSIGNED AS ROW START INVISIBLE,
|
||||
row_end BIGINT UNSIGNED AS ROW END INVISIBLE,
|
||||
PERIOD FOR SYSTEM_TIME(row_start, row_end)
|
||||
) WITH SYSTEM VERSIONING ENGINE=INNODB;
|
||||
|
||||
INSERT INTO t VALUES (DEFAULT, 1);
|
||||
|
||||
SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c
|
||||
INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t
|
||||
ON c.table_id=t.table_id
|
||||
WHERE t.name='test/t' AND c.name='b';
|
||||
--enable_info
|
||||
ALTER TABLE t
|
||||
CHANGE b b INT WITHOUT SYSTEM VERSIONING;
|
||||
--disable_info
|
||||
SELECT c.prtype FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS c
|
||||
INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t
|
||||
ON c.table_id=t.table_id
|
||||
WHERE t.name='test/t' AND c.name='b';
|
||||
|
||||
UPDATE t SET b=11;
|
||||
SELECT COUNT(*) FROM t FOR SYSTEM_TIME ALL;
|
||||
|
||||
DROP TABLE t;
|
||||
SET @@SYSTEM_VERSIONING_ALTER_HISTORY=ERROR;
|
||||
|
@@ -0,0 +1,87 @@
|
||||
-- source include/have_innodb.inc
|
||||
-- source include/have_debug.inc
|
||||
|
||||
CREATE OR REPLACE TABLE t1 (
|
||||
a INT,
|
||||
b INT,
|
||||
row_start BIGINT UNSIGNED AS ROW START INVISIBLE,
|
||||
row_end BIGINT UNSIGNED AS ROW END INVISIBLE,
|
||||
PERIOD FOR SYSTEM_TIME(row_start, row_end)
|
||||
) WITH SYSTEM VERSIONING ENGINE=INNODB;
|
||||
|
||||
CREATE OR REPLACE TABLE t2 (
|
||||
a INT WITHOUT SYSTEM VERSIONING,
|
||||
b INT,
|
||||
row_start BIGINT UNSIGNED AS ROW START INVISIBLE,
|
||||
row_end BIGINT UNSIGNED AS ROW END INVISIBLE,
|
||||
PERIOD FOR SYSTEM_TIME(row_start, row_end)
|
||||
) WITH SYSTEM VERSIONING ENGINE=INNODB;
|
||||
|
||||
INSERT INTO t1 VALUES (1,1);
|
||||
INSERT INTO t2 VALUES (1,1);
|
||||
|
||||
SET @@SYSTEM_VERSIONING_ALTER_HISTORY=KEEP;
|
||||
|
||||
--enable_info
|
||||
--echo # without rebuild
|
||||
ALTER TABLE t1
|
||||
CHANGE a a INT WITHOUT SYSTEM VERSIONING,
|
||||
ALGORITHM=INSTANT;
|
||||
|
||||
--error ER_ALTER_OPERATION_NOT_SUPPORTED
|
||||
ALTER TABLE t2
|
||||
CHANGE a a INT WITH SYSTEM VERSIONING,
|
||||
ADD PRIMARY KEY pk (a),
|
||||
ALGORITHM=INSTANT;
|
||||
|
||||
--echo # with rebuild
|
||||
ALTER TABLE t2
|
||||
CHANGE a a INT WITH SYSTEM VERSIONING,
|
||||
ADD PRIMARY KEY pk (a);
|
||||
--disable_info
|
||||
|
||||
--source include/restart_mysqld.inc
|
||||
|
||||
UPDATE t1 SET a=2;
|
||||
SELECT COUNT(*) FROM t1 FOR SYSTEM_TIME ALL;
|
||||
|
||||
UPDATE t2 SET a=2;
|
||||
SELECT COUNT(*) FROM t2 FOR SYSTEM_TIME ALL;
|
||||
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
--echo # rollback ALTER TABLE: nothing should change
|
||||
CREATE TABLE t (
|
||||
a INT,
|
||||
b INT,
|
||||
row_start BIGINT UNSIGNED AS ROW START INVISIBLE,
|
||||
row_end BIGINT UNSIGNED AS ROW END INVISIBLE,
|
||||
PERIOD FOR SYSTEM_TIME(row_start, row_end)
|
||||
) WITH SYSTEM VERSIONING ENGINE=INNODB;
|
||||
|
||||
INSERT INTO t VALUES (1, 1);
|
||||
|
||||
SELECT C.PRTYPE FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS C
|
||||
JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t ON C.TABLE_ID=t.TABLE_ID
|
||||
WHERE t.NAME='test/t' AND C.NAME='b';
|
||||
|
||||
SET @@SYSTEM_VERSIONING_ALTER_HISTORY=KEEP;
|
||||
|
||||
SET @SAVED_DEBUG_DBUG = @@SESSION.DEBUG_DBUG;
|
||||
SET DEBUG_DBUG='+d,ib_commit_inplace_fail_1';
|
||||
--error ER_INTERNAL_ERROR
|
||||
ALTER TABLE t
|
||||
CHANGE b b INT WITHOUT SYSTEM VERSIONING;
|
||||
SET DEBUG_DBUG = @SAVED_DEBUG_DBUG;
|
||||
|
||||
SELECT C.PRTYPE FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS AS C
|
||||
JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES AS t ON C.TABLE_ID=t.TABLE_ID
|
||||
WHERE t.NAME='test/t' AND C.NAME='b';
|
||||
|
||||
SHOW CREATE TABLE t;
|
||||
|
||||
SELECT COUNT(*) FROM t FOR SYSTEM_TIME ALL;
|
||||
UPDATE t SET b=11;
|
||||
SELECT COUNT(*) FROM t FOR SYSTEM_TIME ALL;
|
||||
|
||||
DROP TABLE t;
|
@@ -6535,15 +6535,15 @@ static bool fill_alter_inplace_info(THD *thd,
|
||||
ALTER_DROP_INDEX are replaced with versions that have higher granuality.
|
||||
*/
|
||||
|
||||
ha_alter_info->handler_flags|= (alter_info->flags &
|
||||
~(ALTER_ADD_INDEX |
|
||||
ALTER_DROP_INDEX |
|
||||
ALTER_PARSER_ADD_COLUMN |
|
||||
ALTER_PARSER_DROP_COLUMN |
|
||||
ALTER_COLUMN_ORDER |
|
||||
ALTER_RENAME_COLUMN |
|
||||
ALTER_CHANGE_COLUMN |
|
||||
ALTER_COLUMN_UNVERSIONED));
|
||||
alter_table_operations flags_to_remove=
|
||||
ALTER_ADD_INDEX | ALTER_DROP_INDEX | ALTER_PARSER_ADD_COLUMN |
|
||||
ALTER_PARSER_DROP_COLUMN | ALTER_COLUMN_ORDER | ALTER_RENAME_COLUMN |
|
||||
ALTER_CHANGE_COLUMN;
|
||||
|
||||
if (!table->file->native_versioned())
|
||||
flags_to_remove|= ALTER_COLUMN_UNVERSIONED;
|
||||
|
||||
ha_alter_info->handler_flags|= (alter_info->flags & ~flags_to_remove);
|
||||
/*
|
||||
Comparing new and old default values of column is cumbersome.
|
||||
So instead of using such a comparison for detecting if default
|
||||
|
@@ -87,7 +87,6 @@ static const alter_table_operations INNOBASE_ALTER_REBUILD
|
||||
/*
|
||||
| ALTER_STORED_COLUMN_TYPE
|
||||
*/
|
||||
| ALTER_COLUMN_UNVERSIONED
|
||||
| ALTER_ADD_SYSTEM_VERSIONING
|
||||
| ALTER_DROP_SYSTEM_VERSIONING
|
||||
;
|
||||
@@ -128,6 +127,7 @@ static const alter_table_operations INNOBASE_ALTER_INSTANT
|
||||
| ALTER_ADD_VIRTUAL_COLUMN
|
||||
| INNOBASE_FOREIGN_OPERATIONS
|
||||
| ALTER_COLUMN_EQUAL_PACK_LENGTH
|
||||
| ALTER_COLUMN_UNVERSIONED
|
||||
| ALTER_DROP_VIRTUAL_COLUMN;
|
||||
|
||||
struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
|
||||
@@ -8433,6 +8433,188 @@ innobase_update_foreign_cache(
|
||||
DBUG_RETURN(err);
|
||||
}
|
||||
|
||||
/** Changes SYS_COLUMNS.PRTYPE for one column.
|
||||
@param[in,out] trx transaction
|
||||
@param[in] table_name table name
|
||||
@param[in] tableid table ID as in SYS_TABLES
|
||||
@param[in] pos column position
|
||||
@param[in] prtype new precise type
|
||||
@return boolean flag
|
||||
@retval true on failure
|
||||
@retval false on success */
|
||||
static
|
||||
bool
|
||||
change_field_versioning_try(
|
||||
trx_t* trx,
|
||||
const char* table_name,
|
||||
const table_id_t tableid,
|
||||
const ulint pos,
|
||||
const ulint prtype)
|
||||
{
|
||||
DBUG_ENTER("change_field_versioning_try");
|
||||
|
||||
pars_info_t* info = pars_info_create();
|
||||
|
||||
pars_info_add_int4_literal(info, "prtype", prtype);
|
||||
pars_info_add_ull_literal(info,"tableid", tableid);
|
||||
pars_info_add_int4_literal(info, "pos", pos);
|
||||
|
||||
dberr_t error = que_eval_sql(info,
|
||||
"PROCEDURE CHANGE_COLUMN_MTYPE () IS\n"
|
||||
"BEGIN\n"
|
||||
"UPDATE SYS_COLUMNS SET PRTYPE=:prtype\n"
|
||||
"WHERE TABLE_ID=:tableid AND POS=:pos;\n"
|
||||
"END;\n",
|
||||
false, trx);
|
||||
|
||||
if (error != DB_SUCCESS) {
|
||||
my_error_innodb(error, table_name, 0);
|
||||
trx->error_state = DB_SUCCESS;
|
||||
trx->op_info = "";
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
/** Changes fields WITH/WITHOUT SYSTEM VERSIONING property in SYS_COLUMNS.
|
||||
@param[in] ha_alter_info alter info
|
||||
@param[in] ctx alter inplace context
|
||||
@param[in] trx transaction
|
||||
@param[in] table old table
|
||||
@return boolean flag
|
||||
@retval true on failure
|
||||
@retval false on success */
|
||||
static
|
||||
bool
|
||||
change_fields_versioning_try(
|
||||
const Alter_inplace_info* ha_alter_info,
|
||||
const ha_innobase_inplace_ctx* ctx,
|
||||
trx_t* trx,
|
||||
const TABLE* table)
|
||||
{
|
||||
DBUG_ENTER("change_fields_versioning_try");
|
||||
|
||||
DBUG_ASSERT(ha_alter_info);
|
||||
DBUG_ASSERT(ctx);
|
||||
|
||||
if (!(ha_alter_info->handler_flags & ALTER_COLUMN_UNVERSIONED)){
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
uint virtual_count = 0;
|
||||
|
||||
List_iterator_fast<Create_field> it(
|
||||
ha_alter_info->alter_info->create_list);
|
||||
|
||||
for (uint i = 0; i < table->s->fields; i++) {
|
||||
const Field* field = table->field[i];
|
||||
|
||||
if (innobase_is_v_fld(field)) {
|
||||
virtual_count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
const Create_field* create_field = NULL;
|
||||
while (const Create_field* cf = it++) {
|
||||
if (cf->field == field) {
|
||||
create_field = cf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
it.rewind();
|
||||
DBUG_ASSERT(create_field);
|
||||
|
||||
if (create_field->versioning
|
||||
== Column_definition::VERSIONING_NOT_SET) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const dict_table_t* new_table = ctx->new_table;
|
||||
ulint pos = i - virtual_count;
|
||||
const dict_col_t* col = dict_table_get_nth_col(new_table, pos);
|
||||
|
||||
DBUG_ASSERT(!col->vers_sys_start());
|
||||
DBUG_ASSERT(!col->vers_sys_end());
|
||||
|
||||
ulint new_prtype
|
||||
= create_field->versioning
|
||||
== Column_definition::WITHOUT_VERSIONING
|
||||
? col->prtype & ~DATA_VERSIONED
|
||||
: col->prtype | DATA_VERSIONED;
|
||||
|
||||
if (change_field_versioning_try(trx, table->s->table_name.str,
|
||||
new_table->id, pos,
|
||||
new_prtype)) {
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
}
|
||||
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
/** Changes WITH/WITHOUT SYSTEM VERSIONING for fields
|
||||
in the data dictionary cache.
|
||||
@param ha_alter_info Data used during in-place alter
|
||||
@param ctx In-place ALTER TABLE context
|
||||
@param table MySQL table as it is before the ALTER operation */
|
||||
static
|
||||
void
|
||||
change_fields_versioning_cache(
|
||||
Alter_inplace_info* ha_alter_info,
|
||||
const ha_innobase_inplace_ctx* ctx,
|
||||
const TABLE* table)
|
||||
{
|
||||
DBUG_ENTER("change_fields_versioning");
|
||||
|
||||
DBUG_ASSERT(ha_alter_info);
|
||||
DBUG_ASSERT(ctx);
|
||||
DBUG_ASSERT(ha_alter_info->handler_flags & ALTER_COLUMN_UNVERSIONED);
|
||||
|
||||
uint virtual_count = 0;
|
||||
|
||||
List_iterator_fast<Create_field> it(
|
||||
ha_alter_info->alter_info->create_list);
|
||||
|
||||
for (uint i = 0; i < table->s->fields; i++) {
|
||||
const Field* field = table->field[i];
|
||||
|
||||
if (innobase_is_v_fld(field)) {
|
||||
virtual_count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
const Create_field* create_field = NULL;
|
||||
while (const Create_field* cf = it++) {
|
||||
if (cf->field == field) {
|
||||
create_field = cf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
it.rewind();
|
||||
DBUG_ASSERT(create_field);
|
||||
|
||||
dict_col_t* col
|
||||
= dict_table_get_nth_col(ctx->new_table, i - virtual_count);
|
||||
|
||||
if (create_field->versioning
|
||||
== Column_definition::WITHOUT_VERSIONING) {
|
||||
|
||||
DBUG_ASSERT(!col->vers_sys_start());
|
||||
DBUG_ASSERT(!col->vers_sys_end());
|
||||
col->prtype &= ~DATA_VERSIONED;
|
||||
} else if (create_field->versioning
|
||||
== Column_definition::WITH_VERSIONING) {
|
||||
|
||||
DBUG_ASSERT(!col->vers_sys_start());
|
||||
DBUG_ASSERT(!col->vers_sys_end());
|
||||
col->prtype |= DATA_VERSIONED;
|
||||
}
|
||||
}
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
/** Commit the changes made during prepare_inplace_alter_table()
|
||||
and inplace_alter_table() inside the data dictionary tables,
|
||||
when rebuilding the table.
|
||||
@@ -8742,6 +8924,10 @@ commit_try_norebuild(
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
if (change_fields_versioning_try(ha_alter_info, ctx, trx, old_table)) {
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
dberr_t error;
|
||||
|
||||
/* We altered the table in place. Mark the indexes as committed. */
|
||||
@@ -8947,6 +9133,10 @@ commit_cache_norebuild(
|
||||
ha_alter_info, table, ctx->new_table);
|
||||
}
|
||||
|
||||
if (ha_alter_info->handler_flags & ALTER_COLUMN_UNVERSIONED) {
|
||||
change_fields_versioning_cache(ha_alter_info, ctx, table);
|
||||
}
|
||||
|
||||
#ifdef MYSQL_RENAME_INDEX
|
||||
rename_indexes_in_cache(ctx, ha_alter_info);
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user