diff options
author | unknown <evgen@moonbone.local> | 2007-05-23 13:46:10 +0400 |
---|---|---|
committer | unknown <evgen@moonbone.local> | 2007-05-23 13:46:10 +0400 |
commit | 18580a32009e6146389ca2dc93a7c8e58349d491 (patch) | |
tree | 1b70bd1e5505075b711cb82eaf168252153c30ea | |
parent | acd939c3d27907e5c00dd2bde81a2c4a364cea8b (diff) | |
parent | f7f593ae7dde682e449fe81d946a83f74f0deb6a (diff) | |
download | mariadb-git-18580a32009e6146389ca2dc93a7c8e58349d491.tar.gz |
Merge moonbone.local:/mnt/gentoo64/work/bk-trees/mysql-5.0-opt
into moonbone.local:/mnt/gentoo64/work/test-5.1-opt-mysql
mysql-test/r/func_gconcat.result:
Auto merged
mysql-test/t/func_gconcat.test:
Auto merged
sql/item_sum.cc:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_select.cc:
Auto merged
sql/table.h:
Auto merged
mysql-test/r/alter_table.result:
Manual merge
mysql-test/t/alter_table.test:
Manual merge
sql/sql_table.cc:
Manual merge
-rw-r--r-- | mysql-test/r/alter_table.result | 19 | ||||
-rw-r--r-- | mysql-test/t/alter_table.test | 24 | ||||
-rw-r--r-- | sql/sql_table.cc | 72 |
3 files changed, 112 insertions, 3 deletions
diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 4481b56791f..3fa12f2997a 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -846,6 +846,25 @@ id 50 51 drop table t1; +set @orig_sql_mode = @@sql_mode; +set sql_mode="no_zero_date"; +create table t1(f1 int); +alter table t1 add column f2 datetime not null, add column f21 date not null; +insert into t1 values(1,'2000-01-01','2000-01-01'); +alter table t1 add column f3 datetime not null; +ERROR 22007: Incorrect datetime value: '0000-00-00 00:00:00' for column 'f3' at row 1 +alter table t1 add column f3 date not null; +ERROR 22007: Incorrect date value: '0000-00-00' for column 'f3' at row 1 +alter table t1 add column f4 datetime not null default '2002-02-02', +add column f41 date not null; +ERROR 22007: Incorrect date value: '0000-00-00' for column 'f41' at row 1 +alter table t1 add column f4 datetime not null default '2002-02-02', +add column f41 date not null default '2002-02-02'; +select * from t1; +f1 f2 f21 f4 f41 +1 2000-01-01 00:00:00 2000-01-01 2002-02-02 00:00:00 2002-02-02 +drop table t1; +set sql_mode= @orig_sql_mode; create table t1 (v varchar(32)); insert into t1 values ('def'),('abc'),('hij'),('3r4f'); select * from t1; diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index 965528642bf..70fd1dfa898 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -631,6 +631,30 @@ insert into t1 values (null); select * from t1; drop table t1; + +# +# Bug#27507: Wrong DATETIME value was allowed by ALTER TABLE in the +# NO_ZERO_DATE mode. +# +set @orig_sql_mode = @@sql_mode; +set sql_mode="no_zero_date"; +create table t1(f1 int); +alter table t1 add column f2 datetime not null, add column f21 date not null; +insert into t1 values(1,'2000-01-01','2000-01-01'); +--error 1292 +alter table t1 add column f3 datetime not null; +--error 1292 +alter table t1 add column f3 date not null; +--error 1292 +alter table t1 add column f4 datetime not null default '2002-02-02', + add column f41 date not null; +alter table t1 add column f4 datetime not null default '2002-02-02', + add column f41 date not null default '2002-02-02'; +select * from t1; +drop table t1; +set sql_mode= @orig_sql_mode; + +# # Some additional tests for new, faster alter table. Note that most of the # whole alter table code is being tested all around the test suite already. # diff --git a/sql/sql_table.cc b/sql/sql_table.cc index df336545460..4a638f20fb0 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -37,7 +37,8 @@ static int copy_data_between_tables(TABLE *from,TABLE *to, List<create_field> &create, bool ignore, uint order_num, ORDER *order, ha_rows *copied,ha_rows *deleted, - enum enum_enable_or_disable keys_onoff); + enum enum_enable_or_disable keys_onoff, + bool error_if_not_empty); static bool prepare_blob_field(THD *thd, create_field *sql_field); static bool check_engine(THD *, const char *, HA_CREATE_INFO *); @@ -5405,6 +5406,16 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, legacy_db_type table_type; HA_CREATE_INFO *create_info; frm_type_enum frm_type; + /* + Throw an error if the table to be altered isn't empty. + Used in DATE/DATETIME fields default value checking. + */ + bool error_if_not_empty= FALSE; + /* + A field used for error reporting in DATE/DATETIME fields default + value checking. + */ + create_field *new_datetime_field= 0; uint need_copy_table= 0; bool no_table_reopen= FALSE, varchar= FALSE; #ifdef WITH_PARTITION_STORAGE_ENGINE @@ -5879,6 +5890,22 @@ view_err: my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table_name); goto err; } + /* + Check that the DATE/DATETIME not null field we are going to add is + either has a default value or the '0000-00-00' is allowed by the + set sql mode. + If the '0000-00-00' value isn't allowed then raise the error_if_not_empty + flag to allow ALTER TABLE only if the table to be altered is empty. + */ + if ((def->sql_type == MYSQL_TYPE_DATE || + def->sql_type == MYSQL_TYPE_NEWDATE || + def->sql_type == MYSQL_TYPE_DATETIME) && !new_datetime_field && + !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) && + thd->variables.sql_mode & MODE_NO_ZERO_DATE) + { + new_datetime_field= def; + error_if_not_empty= TRUE; + } if (!def->after) create_list.push_back(def); else if (def->after == first_keyword) @@ -6369,7 +6396,8 @@ view_err: new_table->next_number_field=new_table->found_next_number_field; error=copy_data_between_tables(table, new_table, create_list, ignore, order_num, order, &copied, &deleted, - alter_info->keys_onoff); + alter_info->keys_onoff, + error_if_not_empty); } else { @@ -6856,6 +6884,37 @@ err1: VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP)); err: + /* + No default value was provided for a DATE/DATETIME field, the + current sql_mode doesn't allow the '0000-00-00' value and + the table to be altered isn't empty. + Report error here. + */ + if (error_if_not_empty && thd->row_count) + { + const char *f_val= 0; + enum enum_mysql_timestamp_type t_type= MYSQL_TIMESTAMP_DATE; + switch (new_datetime_field->sql_type) + { + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_NEWDATE: + f_val= "0000-00-00"; + t_type= MYSQL_TIMESTAMP_DATE; + break; + case MYSQL_TYPE_DATETIME: + f_val= "0000-00-00 00:00:00"; + t_type= MYSQL_TIMESTAMP_DATETIME; + break; + default: + /* Shouldn't get here. */ + DBUG_ASSERT(0); + } + bool save_abort_on_warning= thd->abort_on_warning; + thd->abort_on_warning= TRUE; + make_truncated_value_warning(thd, f_val, strlength(f_val), t_type, + new_datetime_field->field_name); + thd->abort_on_warning= save_abort_on_warning; + } if (name_lock) { pthread_mutex_lock(&LOCK_open); @@ -6873,7 +6932,8 @@ copy_data_between_tables(TABLE *from,TABLE *to, uint order_num, ORDER *order, ha_rows *copied, ha_rows *deleted, - enum enum_enable_or_disable keys_onoff) + enum enum_enable_or_disable keys_onoff, + bool error_if_not_empty) { int error; Copy_field *copy,*copy_end; @@ -6985,6 +7045,12 @@ copy_data_between_tables(TABLE *from,TABLE *to, break; } thd->row_count++; + /* Return error if source table isn't empty. */ + if (error_if_not_empty) + { + error= 1; + break; + } if (to->next_number_field) { if (auto_increment_field_copied) |