Merge branch '10.3' into bb-10.3-MDEV-10814
This commit is contained in:
commit
f79c5a658c
@ -2,7 +2,7 @@ CREATE TABLE t1 (i1 INT UNSIGNED NULL DEFAULT 42) ENGINE=innodb;
|
||||
INSERT INTO t1 VALUES(NULL);
|
||||
ALTER TABLE t1 CHANGE i1 i1 INT UNSIGNED NOT NULL DEFAULT rand(),
|
||||
ALGORITHM=INPLACE;
|
||||
ERROR 22004: Invalid use of NULL value
|
||||
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: cannot convert NULL to non-constant DEFAULT. Try ALGORITHM=COPY
|
||||
ALTER TABLE t1 CHANGE i1 i1 INT UNSIGNED NOT NULL DEFAULT rand(),
|
||||
ALGORITHM=COPY;
|
||||
ERROR 01000: Data truncated for column 'i1' at row 1
|
||||
@ -10,20 +10,20 @@ ALTER TABLE t1 CHANGE i1 id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
ADD PRIMARY KEY(id), ALGORITHM=INPLACE;
|
||||
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY
|
||||
ALTER TABLE t1 ADD PRIMARY KEY(i1), ALGORITHM=INPLACE;
|
||||
ERROR 22004: Invalid use of NULL value
|
||||
ALTER TABLE t1 CHANGE i1 id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
ADD PRIMARY KEY(id);
|
||||
affected rows: 0
|
||||
info: Records: 0 Duplicates: 0 Warnings: 0
|
||||
ALTER TABLE t1 CHANGE i1 id INT UNSIGNED NOT NULL AUTO_INCREMENT;
|
||||
affected rows: 1
|
||||
info: Records: 1 Duplicates: 0 Warnings: 0
|
||||
SELECT * FROM t1;
|
||||
id
|
||||
1
|
||||
42
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=43 DEFAULT CHARSET=latin1
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (i1 INT UNSIGNED NOT NULL, d1 TIMESTAMP NULL) ENGINE=InnoDB;
|
||||
SHOW CREATE TABLE t1;
|
||||
|
@ -411,9 +411,7 @@ SET @old_sql_mode = @@sql_mode;
|
||||
SET @@sql_mode = 'STRICT_TRANS_TABLES';
|
||||
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 CHAR(255) NOT NULL;
|
||||
ERROR 22004: Invalid use of NULL value
|
||||
ERROR 23000: Duplicate entry '' for key 'PRIMARY'
|
||||
SET @@sql_mode = @old_sql_mode;
|
||||
UPDATE t1 SET c3=LEFT(CONCAT(c1,REPEAT('foo',c1)),255) WHERE c3 IS NULL;
|
||||
SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL c3p5_created0 WAIT_FOR ins_done0';
|
||||
|
@ -3,7 +3,7 @@
|
||||
CREATE TABLE t1 (i1 INT UNSIGNED NULL DEFAULT 42) ENGINE=innodb;
|
||||
INSERT INTO t1 VALUES(NULL);
|
||||
--enable_info
|
||||
--error ER_INVALID_USE_OF_NULL
|
||||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||
ALTER TABLE t1 CHANGE i1 i1 INT UNSIGNED NOT NULL DEFAULT rand(),
|
||||
ALGORITHM=INPLACE;
|
||||
--error WARN_DATA_TRUNCATED
|
||||
@ -12,10 +12,8 @@ ALGORITHM=COPY;
|
||||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||
ALTER TABLE t1 CHANGE i1 id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
ADD PRIMARY KEY(id), ALGORITHM=INPLACE;
|
||||
--error ER_INVALID_USE_OF_NULL
|
||||
ALTER TABLE t1 ADD PRIMARY KEY(i1), ALGORITHM=INPLACE;
|
||||
ALTER TABLE t1 CHANGE i1 id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
ADD PRIMARY KEY(id);
|
||||
ALTER TABLE t1 CHANGE i1 id INT UNSIGNED NOT NULL AUTO_INCREMENT;
|
||||
--disable_info
|
||||
SELECT * FROM t1;
|
||||
SHOW CREATE TABLE t1;
|
||||
|
@ -358,12 +358,10 @@ SET @old_sql_mode = @@sql_mode;
|
||||
# NULL -> NOT NULL only allowed INPLACE if strict sql_mode is on.
|
||||
# And adding a PRIMARY KEY will also add NOT NULL implicitly!
|
||||
SET @@sql_mode = 'STRICT_TRANS_TABLES';
|
||||
--error ER_INVALID_USE_OF_NULL
|
||||
--error ER_DUP_ENTRY
|
||||
ALTER TABLE t1 DROP COLUMN c22f, DROP PRIMARY KEY, ADD PRIMARY KEY c3p5(c3(5)),
|
||||
ALGORITHM = INPLACE;
|
||||
|
||||
--error ER_INVALID_USE_OF_NULL
|
||||
ALTER TABLE t1 MODIFY c3 CHAR(255) NOT NULL;
|
||||
SET @@sql_mode = @old_sql_mode;
|
||||
UPDATE t1 SET c3=LEFT(CONCAT(c1,REPEAT('foo',c1)),255) WHERE c3 IS NULL;
|
||||
|
||||
@ -397,6 +395,7 @@ ROLLBACK;
|
||||
--echo # session con1
|
||||
connection con1;
|
||||
ALTER TABLE t1 MODIFY c3 CHAR(255) 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,
|
||||
|
@ -7089,7 +7089,7 @@ ER_IDENT_CAUSES_TOO_LONG_PATH
|
||||
eng "Long database name and identifier for object resulted in path length exceeding %d characters. Path: '%s'"
|
||||
|
||||
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOT_NULL
|
||||
eng "cannot silently convert NULL values, as required in this SQL_MODE"
|
||||
eng "cannot convert NULL to non-constant DEFAULT"
|
||||
|
||||
ER_MUST_CHANGE_PASSWORD_LOGIN
|
||||
eng "Your password has expired. To log in you must change it using a client that supports expired passwords"
|
||||
|
@ -127,6 +127,10 @@ static const alter_table_operations INNOBASE_ALTER_NOREBUILD
|
||||
| ALTER_DROP_VIRTUAL_COLUMN
|
||||
| ALTER_VIRTUAL_COLUMN_ORDER;
|
||||
|
||||
static const alter_table_operations INNOBASE_DEFAULTS
|
||||
= ALTER_COLUMN_NOT_NULLABLE
|
||||
| ALTER_ADD_COLUMN;
|
||||
|
||||
struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
|
||||
{
|
||||
/** Dummy query graph */
|
||||
@ -173,8 +177,8 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
|
||||
const char** col_names;
|
||||
/** added AUTO_INCREMENT column position, or ULINT_UNDEFINED */
|
||||
const ulint add_autoinc;
|
||||
/** default values of ADD COLUMN, or NULL */
|
||||
const dtuple_t* add_cols;
|
||||
/** default values of ADD and CHANGE COLUMN, or NULL */
|
||||
const dtuple_t* defaults;
|
||||
/** autoinc sequence to use */
|
||||
ib_sequence_t sequence;
|
||||
/** temporary table name to use for old table when renaming tables */
|
||||
@ -200,6 +204,9 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
|
||||
/** original column names of the table */
|
||||
const char* const old_col_names;
|
||||
|
||||
/** Whether alter ignore issued. */
|
||||
const bool ignore;
|
||||
|
||||
ha_innobase_inplace_ctx(row_prebuilt_t*& prebuilt_arg,
|
||||
dict_index_t** drop_arg,
|
||||
ulint num_to_drop_arg,
|
||||
@ -216,7 +223,8 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
|
||||
ulint add_autoinc_arg,
|
||||
ulonglong autoinc_col_min_value_arg,
|
||||
ulonglong autoinc_col_max_value_arg,
|
||||
ulint num_to_drop_vcol_arg) :
|
||||
ulint num_to_drop_vcol_arg,
|
||||
bool ignore_flag) :
|
||||
inplace_alter_handler_ctx(),
|
||||
prebuilt (prebuilt_arg),
|
||||
add_index (0), add_key_numbers (0), num_to_add_index (0),
|
||||
@ -229,7 +237,7 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
|
||||
new_table (new_table_arg), instant_table (0),
|
||||
col_map (0), col_names (col_names_arg),
|
||||
add_autoinc (add_autoinc_arg),
|
||||
add_cols (0),
|
||||
defaults (0),
|
||||
sequence(prebuilt->trx->mysql_thd,
|
||||
autoinc_col_min_value_arg, autoinc_col_max_value_arg),
|
||||
tmp_name (0),
|
||||
@ -243,7 +251,8 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
|
||||
m_stage(NULL),
|
||||
old_n_cols(prebuilt_arg->table->n_cols),
|
||||
old_cols(prebuilt_arg->table->cols),
|
||||
old_col_names(prebuilt_arg->table->col_names)
|
||||
old_col_names(prebuilt_arg->table->col_names),
|
||||
ignore(ignore_flag)
|
||||
{
|
||||
ut_ad(old_n_cols >= DATA_N_SYS_COLS);
|
||||
#ifdef UNIV_DEBUG
|
||||
@ -674,6 +683,46 @@ instant_alter_column_possible(
|
||||
|| !create_option_need_rebuild(ha_alter_info, table);
|
||||
}
|
||||
|
||||
/** Check whether the non-const default value for the field
|
||||
@param[in] field field which could be added or changed
|
||||
@return true if the non-const default is present. */
|
||||
static bool is_non_const_value(Field* field)
|
||||
{
|
||||
return field->default_value
|
||||
&& field->default_value->flags & ~(VCOL_SESSION_FUNC
|
||||
| VCOL_TIME_FUNC);
|
||||
}
|
||||
|
||||
/** Set default value for the field.
|
||||
@param[in] field field which could be added or changed
|
||||
@return true if the default value is set. */
|
||||
static bool set_default_value(Field* field)
|
||||
{
|
||||
/* The added/changed NOT NULL column lacks a DEFAULT value,
|
||||
or the DEFAULT is the same for all rows.
|
||||
(Time functions, such as CURRENT_TIMESTAMP(),
|
||||
are evaluated from a timestamp that is assigned
|
||||
at the start of the statement. Session
|
||||
functions, such as USER(), always evaluate the
|
||||
same within a statement.) */
|
||||
|
||||
ut_ad(!is_non_const_value(field));
|
||||
|
||||
/* Compute the DEFAULT values of non-constant columns
|
||||
(VCOL_SESSION_FUNC | VCOL_TIME_FUNC). */
|
||||
switch (field->set_default()) {
|
||||
case 0: /* OK */
|
||||
case 3: /* DATETIME to TIME or DATE conversion */
|
||||
return true;
|
||||
case -1: /* OOM, or GEOMETRY type mismatch */
|
||||
case 1: /* A number adjusted to the min/max value */
|
||||
case 2: /* String truncation, or conversion problem */
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Check if InnoDB supports a particular alter table in-place
|
||||
@param altered_table TABLE object for new version of table.
|
||||
@param ha_alter_info Structure describing changes to be done
|
||||
@ -1080,20 +1129,26 @@ ha_innobase::check_if_supported_inplace_alter(
|
||||
/* No DEFAULT value is
|
||||
specified. We can report
|
||||
errors for any NULL values for
|
||||
the TIMESTAMP.
|
||||
the TIMESTAMP. */
|
||||
|
||||
FIXME: Allow any DEFAULT
|
||||
expression whose value does
|
||||
not change during ALTER TABLE.
|
||||
This would require a fix in
|
||||
row_merge_read_clustered_index()
|
||||
to try to replace the DEFAULT
|
||||
value before reporting
|
||||
DB_INVALID_NULL. */
|
||||
goto next_column;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Changing from NULL to NOT NULL and
|
||||
set the default constant values. */
|
||||
if (f->real_maybe_null()
|
||||
&& !(*af)->real_maybe_null()) {
|
||||
|
||||
if (is_non_const_value(*af)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!set_default_value(*af)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* For any other data type, NULL
|
||||
values are not converted.
|
||||
(An AUTO_INCREMENT attribute cannot
|
||||
@ -1109,32 +1164,16 @@ ha_innobase::check_if_supported_inplace_alter(
|
||||
ha_alter_info->unsupported_reason
|
||||
= innobase_get_err_msg(
|
||||
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOT_NULL);
|
||||
} else if (!(*af)->default_value
|
||||
|| !((*af)->default_value->flags
|
||||
& ~(VCOL_SESSION_FUNC | VCOL_TIME_FUNC))) {
|
||||
} else if (!is_non_const_value(*af)) {
|
||||
|
||||
n_add_cols++;
|
||||
|
||||
if (af < &altered_table->field[table_share->fields]) {
|
||||
add_column_not_last = true;
|
||||
}
|
||||
/* The added NOT NULL column lacks a DEFAULT value,
|
||||
or the DEFAULT is the same for all rows.
|
||||
(Time functions, such as CURRENT_TIMESTAMP(),
|
||||
are evaluated from a timestamp that is assigned
|
||||
at the start of the statement. Session
|
||||
functions, such as USER(), always evaluate the
|
||||
same within a statement.) */
|
||||
|
||||
/* Compute the DEFAULT values of non-constant columns
|
||||
(VCOL_SESSION_FUNC | VCOL_TIME_FUNC). */
|
||||
switch ((*af)->set_default()) {
|
||||
case 0: /* OK */
|
||||
case 3: /* DATETIME to TIME or DATE conversion */
|
||||
if (set_default_value(*af)) {
|
||||
goto next_column;
|
||||
case -1: /* OOM, or GEOMETRY type mismatch */
|
||||
case 1: /* A number adjusted to the min/max value */
|
||||
case 2: /* String truncation, or conversion problem */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3181,7 +3220,7 @@ adding columns.
|
||||
@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 add_cols Default values for ADD COLUMN, or NULL if no ADD COLUMN
|
||||
@param defaults Default values for ADD COLUMN, or NULL if no ADD COLUMN
|
||||
@param heap Memory heap where allocated
|
||||
@return array of integers, mapping column numbers in the table
|
||||
to column numbers in altered_table */
|
||||
@ -3194,7 +3233,7 @@ innobase_build_col_map(
|
||||
const TABLE* table,
|
||||
const dict_table_t* new_table,
|
||||
const dict_table_t* old_table,
|
||||
dtuple_t* add_cols,
|
||||
dtuple_t* defaults,
|
||||
mem_heap_t* heap)
|
||||
{
|
||||
DBUG_ENTER("innobase_build_col_map");
|
||||
@ -3206,9 +3245,10 @@ innobase_build_col_map(
|
||||
DBUG_ASSERT(dict_table_get_n_cols(old_table)
|
||||
+ dict_table_get_n_v_cols(old_table)
|
||||
>= table->s->fields + DATA_N_SYS_COLS);
|
||||
DBUG_ASSERT(!!add_cols == !!(ha_alter_info->handler_flags
|
||||
& ALTER_ADD_COLUMN));
|
||||
DBUG_ASSERT(!add_cols || dtuple_get_n_fields(add_cols)
|
||||
DBUG_ASSERT(!!defaults == !!(ha_alter_info->handler_flags
|
||||
& (ALTER_ADD_COLUMN
|
||||
| ALTER_COLUMN_NOT_NULLABLE)));
|
||||
DBUG_ASSERT(!defaults || dtuple_get_n_fields(defaults)
|
||||
== dict_table_get_n_cols(new_table));
|
||||
|
||||
ulint* col_map = static_cast<ulint*>(
|
||||
@ -3250,6 +3290,19 @@ innobase_build_col_map(
|
||||
}
|
||||
|
||||
if (new_field->field == field) {
|
||||
|
||||
const Field* altered_field =
|
||||
altered_table->field[i];
|
||||
|
||||
if (field->real_maybe_null()
|
||||
&& !altered_field->real_maybe_null()) {
|
||||
innobase_build_col_map_add(
|
||||
heap, dtuple_get_nth_field(
|
||||
defaults, i),
|
||||
altered_field,
|
||||
dict_table_is_comp(new_table));
|
||||
}
|
||||
|
||||
col_map[old_i - num_old_v] = i;
|
||||
goto found_col;
|
||||
}
|
||||
@ -3257,7 +3310,7 @@ innobase_build_col_map(
|
||||
|
||||
ut_ad(!is_v);
|
||||
innobase_build_col_map_add(
|
||||
heap, dtuple_get_nth_field(add_cols, i),
|
||||
heap, dtuple_get_nth_field(defaults, i),
|
||||
altered_table->field[i + num_v],
|
||||
dict_table_is_comp(new_table));
|
||||
found_col:
|
||||
@ -4765,7 +4818,7 @@ prepare_inplace_alter_table_dict(
|
||||
DBUG_ASSERT(!add_fts_doc_id || add_fts_doc_id_idx);
|
||||
DBUG_ASSERT(!add_fts_doc_id_idx
|
||||
|| innobase_fulltext_exist(altered_table));
|
||||
DBUG_ASSERT(!ctx->add_cols);
|
||||
DBUG_ASSERT(!ctx->defaults);
|
||||
DBUG_ASSERT(!ctx->add_index);
|
||||
DBUG_ASSERT(!ctx->add_key_numbers);
|
||||
DBUG_ASSERT(!ctx->num_to_add_index);
|
||||
@ -4933,7 +4986,7 @@ new_clustered_failed:
|
||||
part ? part : "", partlen + 1);
|
||||
ulint n_cols = 0;
|
||||
ulint n_v_cols = 0;
|
||||
dtuple_t* add_cols;
|
||||
dtuple_t* defaults;
|
||||
ulint z = 0;
|
||||
|
||||
for (uint i = 0; i < altered_table->s->fields; i++) {
|
||||
@ -5101,23 +5154,21 @@ new_clustered_failed:
|
||||
|
||||
dict_table_add_system_columns(ctx->new_table, ctx->heap);
|
||||
|
||||
if (ha_alter_info->handler_flags
|
||||
& ALTER_ADD_COLUMN) {
|
||||
add_cols = dtuple_create_with_vcol(
|
||||
if (ha_alter_info->handler_flags & INNOBASE_DEFAULTS) {
|
||||
defaults = dtuple_create_with_vcol(
|
||||
ctx->heap,
|
||||
dict_table_get_n_cols(ctx->new_table),
|
||||
dict_table_get_n_v_cols(ctx->new_table));
|
||||
|
||||
dict_table_copy_types(add_cols, ctx->new_table);
|
||||
dict_table_copy_types(defaults, ctx->new_table);
|
||||
} else {
|
||||
add_cols = NULL;
|
||||
defaults = NULL;
|
||||
}
|
||||
|
||||
ctx->col_map = innobase_build_col_map(
|
||||
ha_alter_info, altered_table, old_table,
|
||||
ctx->new_table, user_table,
|
||||
add_cols, ctx->heap);
|
||||
ctx->add_cols = add_cols;
|
||||
ctx->new_table, user_table, defaults, ctx->heap);
|
||||
ctx->defaults = defaults;
|
||||
} else {
|
||||
DBUG_ASSERT(!innobase_need_rebuild(ha_alter_info, old_table));
|
||||
DBUG_ASSERT(old_table->s->primary_key
|
||||
@ -5490,7 +5541,8 @@ new_table_failed:
|
||||
clust_index, ctx->new_table,
|
||||
!(ha_alter_info->handler_flags
|
||||
& ALTER_ADD_PK_INDEX),
|
||||
ctx->add_cols, ctx->col_map, path);
|
||||
ctx->defaults, ctx->col_map, path,
|
||||
ctx->ignore);
|
||||
rw_lock_x_unlock(&clust_index->lock);
|
||||
|
||||
if (!ok) {
|
||||
@ -5548,7 +5600,7 @@ error_handling_drop_uncached:
|
||||
ctx->prebuilt->trx,
|
||||
index,
|
||||
NULL, true, NULL, NULL,
|
||||
path);
|
||||
path, ctx->ignore);
|
||||
rw_lock_x_unlock(&index->lock);
|
||||
|
||||
if (!ok) {
|
||||
@ -6720,7 +6772,8 @@ err_exit:
|
||||
add_fk, n_add_fk,
|
||||
ha_alter_info->online,
|
||||
heap, indexed_table,
|
||||
col_names, ULINT_UNDEFINED, 0, 0, 0);
|
||||
col_names, ULINT_UNDEFINED, 0, 0, 0,
|
||||
ha_alter_info->ignore);
|
||||
}
|
||||
|
||||
DBUG_ASSERT(m_prebuilt->trx->dict_operation_lock_mode == 0);
|
||||
@ -6855,7 +6908,7 @@ found_col:
|
||||
heap, m_prebuilt->table, col_names,
|
||||
add_autoinc_col_no,
|
||||
ha_alter_info->create_info->auto_increment_value,
|
||||
autoinc_col_max_value, 0);
|
||||
autoinc_col_max_value, 0, ha_alter_info->ignore);
|
||||
|
||||
DBUG_RETURN(prepare_inplace_alter_table_dict(
|
||||
ha_alter_info, altered_table, table,
|
||||
@ -7086,7 +7139,7 @@ ok_exit:
|
||||
m_prebuilt->table, ctx->new_table,
|
||||
ctx->online,
|
||||
ctx->add_index, ctx->add_key_numbers, ctx->num_to_add_index,
|
||||
altered_table, ctx->add_cols, ctx->col_map,
|
||||
altered_table, ctx->defaults, ctx->col_map,
|
||||
ctx->add_autoinc, ctx->sequence, ctx->skip_pk_sort,
|
||||
ctx->m_stage, add_v, eval_table,
|
||||
ha_alter_info->handler_flags & ALTER_DROP_HISTORICAL);
|
||||
|
@ -55,12 +55,13 @@ row_log_allocate(
|
||||
or NULL when creating a secondary index */
|
||||
bool same_pk,/*!< in: whether the definition of the
|
||||
PRIMARY KEY has remained the same */
|
||||
const dtuple_t* add_cols,
|
||||
const dtuple_t* defaults,
|
||||
/*!< in: default values of
|
||||
added columns, or NULL */
|
||||
added, changed columns, or NULL */
|
||||
const ulint* col_map,/*!< in: mapping of old column
|
||||
numbers to new ones, or NULL if !table */
|
||||
const char* path) /*!< in: where to create temporary file */
|
||||
const char* path, /*!< in: where to create temporary file */
|
||||
bool ignore) /*!< in: Whether alter ignore issued */
|
||||
MY_ATTRIBUTE((nonnull(1), warn_unused_result));
|
||||
|
||||
/******************************************************//**
|
||||
|
@ -308,7 +308,7 @@ old_table unless creating a PRIMARY KEY
|
||||
@param[in] n_indexes size of indexes[]
|
||||
@param[in,out] table MySQL table, for reporting erroneous key value
|
||||
if applicable
|
||||
@param[in] add_cols default values of added columns, or NULL
|
||||
@param[in] defaults default values of added, changed columns, or NULL
|
||||
@param[in] col_map mapping of old column numbers to new ones, or
|
||||
NULL if old_table == new_table
|
||||
@param[in] add_autoinc number of added AUTO_INCREMENT columns, or
|
||||
@ -334,7 +334,7 @@ row_merge_build_indexes(
|
||||
const ulint* key_numbers,
|
||||
ulint n_indexes,
|
||||
struct TABLE* table,
|
||||
const dtuple_t* add_cols,
|
||||
const dtuple_t* defaults,
|
||||
const ulint* col_map,
|
||||
ulint add_autoinc,
|
||||
ib_sequence_t& sequence,
|
||||
|
@ -153,9 +153,9 @@ row_build(
|
||||
consulted instead; the user
|
||||
columns in this table should be
|
||||
the same columns as in index->table */
|
||||
const dtuple_t* add_cols,
|
||||
const dtuple_t* defaults,
|
||||
/*!< in: default values of
|
||||
added columns, or NULL */
|
||||
added, changed columns, or NULL */
|
||||
const ulint* col_map,/*!< in: mapping of old column
|
||||
numbers to new ones, or NULL */
|
||||
row_ext_t** ext, /*!< out, own: cache of
|
||||
@ -177,7 +177,7 @@ addition of new virtual columns.
|
||||
of an index, or NULL if
|
||||
index->table should be
|
||||
consulted instead
|
||||
@param[in] add_cols default values of added columns, or NULL
|
||||
@param[in] defaults default values of added, changed columns, or NULL
|
||||
@param[in] add_v new virtual columns added
|
||||
along with new indexes
|
||||
@param[in] col_map mapping of old column
|
||||
@ -194,7 +194,7 @@ row_build_w_add_vcol(
|
||||
const rec_t* rec,
|
||||
const ulint* offsets,
|
||||
const dict_table_t* col_table,
|
||||
const dtuple_t* add_cols,
|
||||
const dtuple_t* defaults,
|
||||
const dict_add_v_col_t* add_v,
|
||||
const ulint* col_map,
|
||||
row_ext_t** ext,
|
||||
|
@ -183,8 +183,9 @@ 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 dtuple_t* defaults;
|
||||
/*!< default values of added, changed 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
|
||||
@ -220,6 +221,9 @@ struct row_log_t {
|
||||
decryption or NULL */
|
||||
const char* path; /*!< where to create temporary file during
|
||||
log operation */
|
||||
bool ignore; /*!< Whether the alter ignore is being used;
|
||||
if not, NULL values will not be converted to
|
||||
defaults */
|
||||
};
|
||||
|
||||
/** Create the file or online log if it does not exist.
|
||||
@ -1151,7 +1155,9 @@ row_log_table_get_pk_col(
|
||||
const ulint* offsets,
|
||||
ulint i,
|
||||
const page_size_t& page_size,
|
||||
ulint max_len)
|
||||
ulint max_len,
|
||||
bool ignore,
|
||||
const dtuple_t* defaults)
|
||||
{
|
||||
const byte* field;
|
||||
ulint len;
|
||||
@ -1159,7 +1165,12 @@ row_log_table_get_pk_col(
|
||||
field = rec_get_nth_field(rec, offsets, i, &len);
|
||||
|
||||
if (len == UNIV_SQL_NULL) {
|
||||
return(DB_INVALID_NULL);
|
||||
if (!ignore || !defaults->fields[i].data) {
|
||||
return(DB_INVALID_NULL);
|
||||
}
|
||||
|
||||
field = static_cast<const byte*>(defaults->fields[i].data);
|
||||
len = defaults->fields[i].len;
|
||||
}
|
||||
|
||||
if (rec_offs_nth_extern(offsets, i)) {
|
||||
@ -1323,7 +1334,8 @@ row_log_table_get_pk(
|
||||
|
||||
log->error = row_log_table_get_pk_col(
|
||||
col, ifield, dfield, *heap,
|
||||
rec, offsets, i, page_size, max_len);
|
||||
rec, offsets, i, page_size, max_len,
|
||||
log->ignore, log->defaults);
|
||||
|
||||
if (log->error != DB_SUCCESS) {
|
||||
err_exit:
|
||||
@ -1338,10 +1350,10 @@ err_exit:
|
||||
/* 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);
|
||||
ut_ad(log->defaults);
|
||||
|
||||
dfield_copy(dfield, dtuple_get_nth_field(
|
||||
log->add_cols, col_no));
|
||||
log->defaults, col_no));
|
||||
mbminlen = dfield->type.mbminlen;
|
||||
mbmaxlen = dfield->type.mbmaxlen;
|
||||
prtype = dfield->type.prtype;
|
||||
@ -1512,8 +1524,8 @@ row_log_table_apply_convert_mrec(
|
||||
*error = DB_SUCCESS;
|
||||
|
||||
/* This is based on row_build(). */
|
||||
if (log->add_cols) {
|
||||
row = dtuple_copy(log->add_cols, heap);
|
||||
if (log->defaults) {
|
||||
row = dtuple_copy(log->defaults, heap);
|
||||
/* dict_table_copy_types() would set the fields to NULL */
|
||||
for (ulint i = 0; i < dict_table_get_n_cols(log->table); i++) {
|
||||
dict_col_copy_type(
|
||||
@ -1634,9 +1646,17 @@ blob_done:
|
||||
|
||||
if ((new_col->prtype & DATA_NOT_NULL)
|
||||
&& dfield_is_null(dfield)) {
|
||||
/* We got a NULL value for a NOT NULL column. */
|
||||
*error = DB_INVALID_NULL;
|
||||
return(NULL);
|
||||
|
||||
const dfield_t& default_field
|
||||
= log->defaults->fields[col_no];
|
||||
|
||||
if (!log->ignore || !default_field.data) {
|
||||
/* We got a NULL value for a NOT NULL column. */
|
||||
*error = DB_INVALID_NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*dfield = default_field;
|
||||
}
|
||||
|
||||
/* Adjust the DATA_NOT_NULL flag in the parsed row. */
|
||||
@ -3147,12 +3167,13 @@ row_log_allocate(
|
||||
or NULL when creating a secondary index */
|
||||
bool same_pk,/*!< in: whether the definition of the
|
||||
PRIMARY KEY has remained the same */
|
||||
const dtuple_t* add_cols,
|
||||
const dtuple_t* defaults,
|
||||
/*!< in: default values of
|
||||
added columns, or NULL */
|
||||
added, changed columns, or NULL */
|
||||
const ulint* col_map,/*!< in: mapping of old column
|
||||
numbers to new ones, or NULL if !table */
|
||||
const char* path) /*!< in: where to create temporary file */
|
||||
const char* path, /*!< in: where to create temporary file */
|
||||
const bool ignore) /*!< in: alter ignore issued */
|
||||
{
|
||||
row_log_t* log;
|
||||
DBUG_ENTER("row_log_allocate");
|
||||
@ -3162,7 +3183,7 @@ row_log_allocate(
|
||||
ut_ad(!table || index->table != table);
|
||||
ut_ad(same_pk || table);
|
||||
ut_ad(!table || col_map);
|
||||
ut_ad(!add_cols || col_map);
|
||||
ut_ad(!defaults || col_map);
|
||||
ut_ad(rw_lock_own(dict_index_get_lock(index), RW_LOCK_X));
|
||||
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
|
||||
ut_ad(trx->id);
|
||||
@ -3179,7 +3200,7 @@ row_log_allocate(
|
||||
log->blobs = NULL;
|
||||
log->table = table;
|
||||
log->same_pk = same_pk;
|
||||
log->add_cols = add_cols;
|
||||
log->defaults = defaults;
|
||||
log->col_map = col_map;
|
||||
log->error = DB_SUCCESS;
|
||||
log->min_trx = trx->id;
|
||||
@ -3191,6 +3212,7 @@ row_log_allocate(
|
||||
log->head.blocks = log->head.bytes = 0;
|
||||
log->head.total = 0;
|
||||
log->path = path;
|
||||
log->ignore=ignore;
|
||||
|
||||
dict_index_set_online_status(index, ONLINE_INDEX_CREATION);
|
||||
index->online_log = log;
|
||||
|
@ -1656,7 +1656,7 @@ containing the index entries for the indexes to be built.
|
||||
@param[in] files temporary files
|
||||
@param[in] key_numbers MySQL key numbers to create
|
||||
@param[in] n_index number of indexes to create
|
||||
@param[in] add_cols default values of added columns, or NULL
|
||||
@param[in] defaults default values of added, changed columns, or NULL
|
||||
@param[in] add_v newly added virtual columns along with indexes
|
||||
@param[in] col_map mapping of old column numbers to new ones, or
|
||||
NULL if old_table == new_table
|
||||
@ -1689,7 +1689,7 @@ row_merge_read_clustered_index(
|
||||
merge_file_t* files,
|
||||
const ulint* key_numbers,
|
||||
ulint n_index,
|
||||
const dtuple_t* add_cols,
|
||||
const dtuple_t* defaults,
|
||||
const dict_add_v_col_t* add_v,
|
||||
const ulint* col_map,
|
||||
ulint add_autoinc,
|
||||
@ -1743,7 +1743,7 @@ row_merge_read_clustered_index(
|
||||
DBUG_ENTER("row_merge_read_clustered_index");
|
||||
|
||||
ut_ad((old_table == new_table) == !col_map);
|
||||
ut_ad(!add_cols || col_map);
|
||||
ut_ad(!defaults || col_map);
|
||||
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
|
||||
ut_ad(trx->id);
|
||||
|
||||
@ -2187,19 +2187,26 @@ end_of_index:
|
||||
|
||||
row = row_build_w_add_vcol(ROW_COPY_POINTERS, clust_index,
|
||||
rec, offsets, new_table,
|
||||
add_cols, add_v, col_map, &ext,
|
||||
defaults, add_v, col_map, &ext,
|
||||
row_heap);
|
||||
ut_ad(row);
|
||||
|
||||
for (ulint i = 0; i < n_nonnull; i++) {
|
||||
const dfield_t* field = &row->fields[nonnull[i]];
|
||||
dfield_t* field = &row->fields[nonnull[i]];
|
||||
|
||||
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;
|
||||
const dfield_t& default_field
|
||||
= defaults->fields[nonnull[i]];
|
||||
|
||||
if (default_field.data == NULL) {
|
||||
err = DB_INVALID_NULL;
|
||||
trx->error_key_num = 0;
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
*field = default_field;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4548,7 +4555,7 @@ old_table unless creating a PRIMARY KEY
|
||||
@param[in] n_indexes size of indexes[]
|
||||
@param[in,out] table MySQL table, for reporting erroneous key value
|
||||
if applicable
|
||||
@param[in] add_cols default values of added columns, or NULL
|
||||
@param[in] defaults default values of added, changed columns, or NULL
|
||||
@param[in] col_map mapping of old column numbers to new ones, or
|
||||
NULL if old_table == new_table
|
||||
@param[in] add_autoinc number of added AUTO_INCREMENT columns, or
|
||||
@ -4574,7 +4581,7 @@ row_merge_build_indexes(
|
||||
const ulint* key_numbers,
|
||||
ulint n_indexes,
|
||||
struct TABLE* table,
|
||||
const dtuple_t* add_cols,
|
||||
const dtuple_t* defaults,
|
||||
const ulint* col_map,
|
||||
ulint add_autoinc,
|
||||
ib_sequence_t& sequence,
|
||||
@ -4610,7 +4617,7 @@ row_merge_build_indexes(
|
||||
|
||||
ut_ad(!srv_read_only_mode);
|
||||
ut_ad((old_table == new_table) == !col_map);
|
||||
ut_ad(!add_cols || col_map);
|
||||
ut_ad(!defaults || col_map);
|
||||
|
||||
stage->begin_phase_read_pk(skip_pk_sort && new_table != old_table
|
||||
? n_indexes - 1
|
||||
@ -4744,7 +4751,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, add_cols, add_v, col_map, add_autoinc,
|
||||
n_indexes, defaults, add_v, col_map, add_autoinc,
|
||||
sequence, block, skip_pk_sort, &tmpfd, stage,
|
||||
pct_cost, crypt_block, eval_table, drop_historical);
|
||||
|
||||
|
@ -357,7 +357,7 @@ addition of new virtual columns.
|
||||
of an index, or NULL if
|
||||
index->table should be
|
||||
consulted instead
|
||||
@param[in] add_cols default values of added columns, or NULL
|
||||
@param[in] defaults default values of added/changed columns, or NULL
|
||||
@param[in] add_v new virtual columns added
|
||||
along with new indexes
|
||||
@param[in] col_map mapping of old column
|
||||
@ -375,7 +375,7 @@ row_build_low(
|
||||
const rec_t* rec,
|
||||
const ulint* offsets,
|
||||
const dict_table_t* col_table,
|
||||
const dtuple_t* add_cols,
|
||||
const dtuple_t* defaults,
|
||||
const dict_add_v_col_t* add_v,
|
||||
const ulint* col_map,
|
||||
row_ext_t** ext,
|
||||
@ -441,13 +441,13 @@ row_build_low(
|
||||
|
||||
if (!col_table) {
|
||||
ut_ad(!col_map);
|
||||
ut_ad(!add_cols);
|
||||
ut_ad(!defaults);
|
||||
col_table = index->table;
|
||||
}
|
||||
|
||||
if (add_cols) {
|
||||
if (defaults) {
|
||||
ut_ad(col_map);
|
||||
row = dtuple_copy(add_cols, heap);
|
||||
row = dtuple_copy(defaults, heap);
|
||||
/* dict_table_copy_types() would set the fields to NULL */
|
||||
for (ulint i = 0; i < dict_table_get_n_cols(col_table); i++) {
|
||||
dict_col_copy_type(
|
||||
@ -594,9 +594,9 @@ row_build(
|
||||
of an index, or NULL if
|
||||
index->table should be
|
||||
consulted instead */
|
||||
const dtuple_t* add_cols,
|
||||
const dtuple_t* defaults,
|
||||
/*!< in: default values of
|
||||
added columns, or NULL */
|
||||
added and changed columns, or NULL */
|
||||
const ulint* col_map,/*!< in: mapping of old column
|
||||
numbers to new ones, or NULL */
|
||||
row_ext_t** ext, /*!< out, own: cache of
|
||||
@ -606,7 +606,7 @@ row_build(
|
||||
the memory needed is allocated */
|
||||
{
|
||||
return(row_build_low(type, index, rec, offsets, col_table,
|
||||
add_cols, NULL, col_map, ext, heap));
|
||||
defaults, NULL, col_map, ext, heap));
|
||||
}
|
||||
|
||||
/** An inverse function to row_build_index_entry. Builds a row from a
|
||||
@ -622,7 +622,7 @@ addition of new virtual columns.
|
||||
of an index, or NULL if
|
||||
index->table should be
|
||||
consulted instead
|
||||
@param[in] add_cols default values of added columns, or NULL
|
||||
@param[in] defaults default values of added, changed columns, or NULL
|
||||
@param[in] add_v new virtual columns added
|
||||
along with new indexes
|
||||
@param[in] col_map mapping of old column
|
||||
@ -639,14 +639,14 @@ row_build_w_add_vcol(
|
||||
const rec_t* rec,
|
||||
const ulint* offsets,
|
||||
const dict_table_t* col_table,
|
||||
const dtuple_t* add_cols,
|
||||
const dtuple_t* defaults,
|
||||
const dict_add_v_col_t* add_v,
|
||||
const ulint* col_map,
|
||||
row_ext_t** ext,
|
||||
mem_heap_t* heap)
|
||||
{
|
||||
return(row_build_low(type, index, rec, offsets, col_table,
|
||||
add_cols, add_v, col_map, ext, heap));
|
||||
defaults, add_v, col_map, ext, heap));
|
||||
}
|
||||
|
||||
/** Convert an index record to a data tuple.
|
||||
|
Loading…
x
Reference in New Issue
Block a user