summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <evgen@moonbone.local>2007-05-23 13:46:10 +0400
committerunknown <evgen@moonbone.local>2007-05-23 13:46:10 +0400
commit18580a32009e6146389ca2dc93a7c8e58349d491 (patch)
tree1b70bd1e5505075b711cb82eaf168252153c30ea
parentacd939c3d27907e5c00dd2bde81a2c4a364cea8b (diff)
parentf7f593ae7dde682e449fe81d946a83f74f0deb6a (diff)
downloadmariadb-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.result19
-rw-r--r--mysql-test/t/alter_table.test24
-rw-r--r--sql/sql_table.cc72
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)