summaryrefslogtreecommitdiff
path: root/storage/innobase/handler/handler0alter.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/handler/handler0alter.cc')
-rw-r--r--storage/innobase/handler/handler0alter.cc95
1 files changed, 60 insertions, 35 deletions
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 1eec22874d1..24bfb31b1fb 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -1011,6 +1011,7 @@ ha_innobase::check_if_supported_inplace_alter(
constant DEFAULT expression. */
cf_it.rewind();
Field **af = altered_table->field;
+
while (Create_field* cf = cf_it++) {
DBUG_ASSERT(cf->field
|| (ha_alter_info->handler_flags
@@ -1018,49 +1019,71 @@ ha_innobase::check_if_supported_inplace_alter(
if (const Field* f = cf->field) {
/* This could be changing an existing column
- from NULL to NOT NULL. For now, ensure that
- the DEFAULT is a constant. */
- if (~ha_alter_info->handler_flags
- & (Alter_inplace_info::ALTER_COLUMN_NOT_NULLABLE
- | Alter_inplace_info::ALTER_COLUMN_DEFAULT)
- || (*af)->real_maybe_null()) {
- /* This ALTER TABLE is not both changing
- a column to NOT NULL and changing the
- DEFAULT value of a column, or this column
- does allow NULL after the ALTER TABLE. */
- goto next_column;
- }
-
- /* Find the matching column in the old table. */
- Field** fp;
- for (fp = table->field; *fp; fp++) {
- if (f != *fp) {
- continue;
+ from NULL to NOT NULL. */
+ switch ((*af)->type()) {
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_TIMESTAMP2:
+ /* Inserting NULL into a TIMESTAMP column
+ would cause the DEFAULT value to be
+ replaced. Ensure that the DEFAULT
+ expression is not changing during
+ ALTER TABLE. */
+ if (!f->real_maybe_null()
+ || (*af)->real_maybe_null()) {
+ /* The column was NOT NULL, or it
+ will allow NULL after ALTER TABLE. */
+ goto next_column;
}
- if (!f->real_maybe_null()) {
- /* The column already is NOT NULL. */
+
+ if (!(*af)->default_value
+ && (*af)->is_real_null()) {
+ /* No DEFAULT value is
+ specified. We can report
+ errors for any NULL values for
+ 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:
+ /* For any other data type, NULL
+ values are not converted.
+ (An AUTO_INCREMENT attribute cannot
+ be introduced to a column with
+ ALGORITHM=INPLACE.) */
+ ut_ad((MTYP_TYPENR((*af)->unireg_check)
+ == Field::NEXT_NUMBER)
+ == (MTYP_TYPENR(f->unireg_check)
+ == Field::NEXT_NUMBER));
+ goto next_column;
}
- /* The column must be found in the old table. */
- DBUG_ASSERT(fp < &table->field[table->s->fields]);
- }
-
- if (!(*af)->default_value
- || (*af)->default_value->flags == 0) {
- /* The NOT NULL column is not
- carrying a non-constant DEFAULT. */
- goto next_column;
- }
-
- /* TODO: Allow NULL column values to
- be replaced with a non-constant DEFAULT. */
- if (cf->field) {
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))) {
+ /* 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). */
+ (*af)->set_default();
+ goto next_column;
}
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
@@ -4471,11 +4494,13 @@ prepare_inplace_alter_table_dict(
|| !innobase_fulltext_exist(altered_table))) {
/* InnoDB can perform an online operation (LOCK=NONE). */
} else {
+ size_t query_length;
/* This should have been blocked in
check_if_supported_inplace_alter(). */
ut_ad(0);
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
- thd_query(ctx->prebuilt->trx->mysql_thd));
+ innobase_get_stmt_unsafe(ctx->prebuilt->trx->mysql_thd,
+ &query_length));
goto error_handled;
}