Commit f79c5a65 authored by Oleksandr Byelkin's avatar Oleksandr Byelkin

Merge branch '10.3' into bb-10.3-MDEV-10814

parents 47ac7252 4f9977d8
......@@ -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"
......
This diff is collapsed.
......@@ -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 @@ row_log_table_get_pk(
/* 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 @@ row_log_table_apply_convert_mrec(
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 @@ row_merge_read_clustered_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.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment