summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <acurtis/antony@xiphis.org/ltantony.xiphis.org>2006-08-30 13:20:39 -0700
committerunknown <acurtis/antony@xiphis.org/ltantony.xiphis.org>2006-08-30 13:20:39 -0700
commit2233201ba715bb733af86cddd1305ee389897d4b (patch)
tree8420b990a80a44f9a16ab6d77359c0a179d2893a
parent69a29c1ea143387588367afbc3121fce4d977415 (diff)
downloadmariadb-git-2233201ba715bb733af86cddd1305ee389897d4b.tar.gz
Bug#20573
"strict mode: inserts autogenerated auto_increment value bigger than max" Strict mode should fail if autoincrement value is out of range include/my_base.h: Add new handler error codes sql/ha_berkeley.cc: handle error in update_auto_increment() sql/ha_heap.cc: handle error in update_auto_increment() sql/ha_innodb.cc: handle error in update_auto_increment() sql/ha_myisam.cc: handle error in update_auto_increment() sql/ha_myisammrg.cc: handle error in update_auto_increment() sql/ha_ndbcluster.cc: handle error in update_auto_increment() sql/handler.cc: return error from handler::update_auto_increment() sql/handler.h: change return type of handler::update_auto_increment() to int sql/share/errmsg.txt: new error message for auto-increment mysql-test/include/strict_autoinc.inc: New BitKeeper file ``mysql-test/include/strict_autoinc.inc'' mysql-test/r/strict_autoinc_1myisam.result: New BitKeeper file ``mysql-test/r/strict_autoinc_1myisam.result'' mysql-test/r/strict_autoinc_2innodb.result: New BitKeeper file ``mysql-test/r/strict_autoinc_2innodb.result'' mysql-test/r/strict_autoinc_3heap.result: New BitKeeper file ``mysql-test/r/strict_autoinc_3heap.result'' mysql-test/r/strict_autoinc_4bdb.result: New BitKeeper file ``mysql-test/r/strict_autoinc_4bdb.result'' mysql-test/r/strict_autoinc_5ndb.result: New BitKeeper file ``mysql-test/r/strict_autoinc_5ndb.result'' mysql-test/t/strict_autoinc_1myisam.test: New BitKeeper file ``mysql-test/t/strict_autoinc_1myisam.test'' mysql-test/t/strict_autoinc_2innodb.test: New BitKeeper file ``mysql-test/t/strict_autoinc_2innodb.test'' mysql-test/t/strict_autoinc_3heap.test: New BitKeeper file ``mysql-test/t/strict_autoinc_3heap.test'' mysql-test/t/strict_autoinc_4bdb.test: New BitKeeper file ``mysql-test/t/strict_autoinc_4bdb.test'' mysql-test/t/strict_autoinc_5ndb.test: New BitKeeper file ``mysql-test/t/strict_autoinc_5ndb.test''
-rw-r--r--include/my_base.h4
-rw-r--r--mysql-test/include/strict_autoinc.inc28
-rw-r--r--mysql-test/r/strict_autoinc_1myisam.result27
-rw-r--r--mysql-test/r/strict_autoinc_2innodb.result27
-rw-r--r--mysql-test/r/strict_autoinc_3heap.result27
-rw-r--r--mysql-test/r/strict_autoinc_4bdb.result27
-rw-r--r--mysql-test/r/strict_autoinc_5ndb.result27
-rw-r--r--mysql-test/t/strict_autoinc_1myisam.test8
-rw-r--r--mysql-test/t/strict_autoinc_2innodb.test10
-rw-r--r--mysql-test/t/strict_autoinc_3heap.test8
-rw-r--r--mysql-test/t/strict_autoinc_4bdb.test10
-rw-r--r--mysql-test/t/strict_autoinc_5ndb.test10
-rw-r--r--sql/ha_berkeley.cc5
-rw-r--r--sql/ha_heap.cc5
-rw-r--r--sql/ha_innodb.cc3
-rw-r--r--sql/ha_myisam.cc6
-rw-r--r--sql/ha_myisammrg.cc6
-rw-r--r--sql/ha_ndbcluster.cc4
-rw-r--r--sql/handler.cc23
-rw-r--r--sql/handler.h2
-rw-r--r--sql/share/errmsg.txt2
21 files changed, 256 insertions, 13 deletions
diff --git a/include/my_base.h b/include/my_base.h
index d8a0e15ccbe..cffe1c3caf4 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -357,8 +357,10 @@ enum ha_base_keytype {
#define HA_ERR_TABLE_DEF_CHANGED 159 /* The table changed in storage engine */
#define HA_ERR_TABLE_NEEDS_UPGRADE 160 /* The table changed in storage engine */
#define HA_ERR_TABLE_READONLY 161 /* The table is not writable */
+#define HA_ERR_AUTOINC_READ_FAILED 162/* Failed to get the next autoinc value */
+#define HA_ERR_AUTOINC_ERANGE 163 /* Failed to set the row autoinc value */
-#define HA_ERR_LAST 161 /*Copy last error nr.*/
+#define HA_ERR_LAST 163 /*Copy last error nr.*/
/* Add error numbers before HA_ERR_LAST and change it accordingly. */
#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1)
diff --git a/mysql-test/include/strict_autoinc.inc b/mysql-test/include/strict_autoinc.inc
new file mode 100644
index 00000000000..6960440f3a7
--- /dev/null
+++ b/mysql-test/include/strict_autoinc.inc
@@ -0,0 +1,28 @@
+#
+# Test for strict-mode autoincrement
+#
+
+set @org_mode=@@sql_mode;
+eval create table t1
+(
+ `a` tinyint(4) NOT NULL auto_increment,
+ primary key (`a`)
+) engine = $type ;
+set @@sql_mode='strict_all_tables';
+--error ER_WARN_DATA_OUT_OF_RANGE
+insert into t1 values(1000);
+select count(*) from t1;
+
+set auto_increment_increment=1000;
+set auto_increment_offset=700;
+--error ER_WARN_DATA_OUT_OF_RANGE
+insert into t1 values(null);
+select count(*) from t1;
+
+set @@sql_mode=@org_mode;
+insert into t1 values(null);
+select * from t1;
+
+drop table t1;
+
+# End of test
diff --git a/mysql-test/r/strict_autoinc_1myisam.result b/mysql-test/r/strict_autoinc_1myisam.result
new file mode 100644
index 00000000000..5d3c2698cda
--- /dev/null
+++ b/mysql-test/r/strict_autoinc_1myisam.result
@@ -0,0 +1,27 @@
+set @org_mode=@@sql_mode;
+create table t1
+(
+`a` tinyint(4) NOT NULL auto_increment,
+primary key (`a`)
+) engine = 'MYISAM' ;
+set @@sql_mode='strict_all_tables';
+insert into t1 values(1000);
+ERROR 22003: Out of range value adjusted for column 'a' at row 1
+select count(*) from t1;
+count(*)
+0
+set auto_increment_increment=1000;
+set auto_increment_offset=700;
+insert into t1 values(null);
+ERROR 22003: Out of range value adjusted for column 'a' at row 1
+select count(*) from t1;
+count(*)
+0
+set @@sql_mode=@org_mode;
+insert into t1 values(null);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+select * from t1;
+a
+127
+drop table t1;
diff --git a/mysql-test/r/strict_autoinc_2innodb.result b/mysql-test/r/strict_autoinc_2innodb.result
new file mode 100644
index 00000000000..f1936ff4de3
--- /dev/null
+++ b/mysql-test/r/strict_autoinc_2innodb.result
@@ -0,0 +1,27 @@
+set @org_mode=@@sql_mode;
+create table t1
+(
+`a` tinyint(4) NOT NULL auto_increment,
+primary key (`a`)
+) engine = 'InnoDB' ;
+set @@sql_mode='strict_all_tables';
+insert into t1 values(1000);
+ERROR 22003: Out of range value adjusted for column 'a' at row 1
+select count(*) from t1;
+count(*)
+0
+set auto_increment_increment=1000;
+set auto_increment_offset=700;
+insert into t1 values(null);
+ERROR 22003: Out of range value adjusted for column 'a' at row 1
+select count(*) from t1;
+count(*)
+0
+set @@sql_mode=@org_mode;
+insert into t1 values(null);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+select * from t1;
+a
+127
+drop table t1;
diff --git a/mysql-test/r/strict_autoinc_3heap.result b/mysql-test/r/strict_autoinc_3heap.result
new file mode 100644
index 00000000000..aa0be270ac5
--- /dev/null
+++ b/mysql-test/r/strict_autoinc_3heap.result
@@ -0,0 +1,27 @@
+set @org_mode=@@sql_mode;
+create table t1
+(
+`a` tinyint(4) NOT NULL auto_increment,
+primary key (`a`)
+) engine = 'MEMORY' ;
+set @@sql_mode='strict_all_tables';
+insert into t1 values(1000);
+ERROR 22003: Out of range value adjusted for column 'a' at row 1
+select count(*) from t1;
+count(*)
+0
+set auto_increment_increment=1000;
+set auto_increment_offset=700;
+insert into t1 values(null);
+ERROR 22003: Out of range value adjusted for column 'a' at row 1
+select count(*) from t1;
+count(*)
+0
+set @@sql_mode=@org_mode;
+insert into t1 values(null);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+select * from t1;
+a
+127
+drop table t1;
diff --git a/mysql-test/r/strict_autoinc_4bdb.result b/mysql-test/r/strict_autoinc_4bdb.result
new file mode 100644
index 00000000000..73683b645e2
--- /dev/null
+++ b/mysql-test/r/strict_autoinc_4bdb.result
@@ -0,0 +1,27 @@
+set @org_mode=@@sql_mode;
+create table t1
+(
+`a` tinyint(4) NOT NULL auto_increment,
+primary key (`a`)
+) engine = 'BDB' ;
+set @@sql_mode='strict_all_tables';
+insert into t1 values(1000);
+ERROR 22003: Out of range value adjusted for column 'a' at row 1
+select count(*) from t1;
+count(*)
+0
+set auto_increment_increment=1000;
+set auto_increment_offset=700;
+insert into t1 values(null);
+ERROR 22003: Out of range value adjusted for column 'a' at row 1
+select count(*) from t1;
+count(*)
+0
+set @@sql_mode=@org_mode;
+insert into t1 values(null);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+select * from t1;
+a
+127
+drop table t1;
diff --git a/mysql-test/r/strict_autoinc_5ndb.result b/mysql-test/r/strict_autoinc_5ndb.result
new file mode 100644
index 00000000000..d0d62d05b32
--- /dev/null
+++ b/mysql-test/r/strict_autoinc_5ndb.result
@@ -0,0 +1,27 @@
+set @org_mode=@@sql_mode;
+create table t1
+(
+`a` tinyint(4) NOT NULL auto_increment,
+primary key (`a`)
+) engine = 'NDB' ;
+set @@sql_mode='strict_all_tables';
+insert into t1 values(1000);
+ERROR 22003: Out of range value adjusted for column 'a' at row 1
+select count(*) from t1;
+count(*)
+0
+set auto_increment_increment=1000;
+set auto_increment_offset=700;
+insert into t1 values(null);
+ERROR 22003: Out of range value adjusted for column 'a' at row 1
+select count(*) from t1;
+count(*)
+0
+set @@sql_mode=@org_mode;
+insert into t1 values(null);
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 1
+select * from t1;
+a
+127
+drop table t1;
diff --git a/mysql-test/t/strict_autoinc_1myisam.test b/mysql-test/t/strict_autoinc_1myisam.test
new file mode 100644
index 00000000000..d9ecce30974
--- /dev/null
+++ b/mysql-test/t/strict_autoinc_1myisam.test
@@ -0,0 +1,8 @@
+#
+# Bug#20573 Strict mode auto-increment
+#
+
+let $type= 'MYISAM' ;
+--source include/strict_autoinc.inc
+
+# end of test
diff --git a/mysql-test/t/strict_autoinc_2innodb.test b/mysql-test/t/strict_autoinc_2innodb.test
new file mode 100644
index 00000000000..83dfe950938
--- /dev/null
+++ b/mysql-test/t/strict_autoinc_2innodb.test
@@ -0,0 +1,10 @@
+-- source include/have_innodb.inc
+
+#
+# Bug#20573 Strict mode auto-increment
+#
+
+let $type= 'InnoDB' ;
+--source include/strict_autoinc.inc
+
+# end of test
diff --git a/mysql-test/t/strict_autoinc_3heap.test b/mysql-test/t/strict_autoinc_3heap.test
new file mode 100644
index 00000000000..f266ecdfda2
--- /dev/null
+++ b/mysql-test/t/strict_autoinc_3heap.test
@@ -0,0 +1,8 @@
+#
+# Bug#20573 Strict mode auto-increment
+#
+
+let $type= 'MEMORY' ;
+--source include/strict_autoinc.inc
+
+# end of test
diff --git a/mysql-test/t/strict_autoinc_4bdb.test b/mysql-test/t/strict_autoinc_4bdb.test
new file mode 100644
index 00000000000..10d6bfd41e7
--- /dev/null
+++ b/mysql-test/t/strict_autoinc_4bdb.test
@@ -0,0 +1,10 @@
+-- source include/have_bdb.inc
+
+#
+# Bug#20573 Strict mode auto-increment
+#
+
+let $type= 'BDB' ;
+--source include/strict_autoinc.inc
+
+# end of test
diff --git a/mysql-test/t/strict_autoinc_5ndb.test b/mysql-test/t/strict_autoinc_5ndb.test
new file mode 100644
index 00000000000..9e2090fddef
--- /dev/null
+++ b/mysql-test/t/strict_autoinc_5ndb.test
@@ -0,0 +1,10 @@
+-- source include/have_ndb.inc
+
+#
+# Bug#20573 Strict mode auto-increment
+#
+
+let $type= 'NDB' ;
+--source include/strict_autoinc.inc
+
+# end of test
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index 72af402a0dc..4209bc93d30 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -953,7 +953,10 @@ int ha_berkeley::write_row(byte * record)
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
if (table->next_number_field && record == table->record[0])
- update_auto_increment();
+ {
+ if ((error= update_auto_increment()))
+ DBUG_RETURN(error);
+ }
if ((error=pack_row(&row, record,1)))
DBUG_RETURN(error); /* purecov: inspected */
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index 79d4575ff1b..3aaa0287098 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -176,7 +176,10 @@ int ha_heap::write_row(byte * buf)
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
if (table->next_number_field && buf == table->record[0])
- update_auto_increment();
+ {
+ if ((res= update_auto_increment()))
+ return res;
+ }
res= heap_write(file,buf);
if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
file->s->records))
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index c56be6376d0..4e73d4fb285 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -3252,7 +3252,8 @@ no_commit:
/* We must use the handler code to update the auto-increment
value to be sure that we increment it correctly. */
- update_auto_increment();
+ if ((error= update_auto_increment()))
+ goto func_exit;
auto_inc_used = 1;
}
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 128cc191434..f35d7efce0b 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -316,7 +316,11 @@ int ha_myisam::write_row(byte * buf)
or a new row, then update the auto_increment value in the record.
*/
if (table->next_number_field && buf == table->record[0])
- update_auto_increment();
+ {
+ int error;
+ if ((error= update_auto_increment()))
+ return error;
+ }
return mi_write(file,buf);
}
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index 0b6e05fcbd4..cb11d9b0452 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -139,7 +139,11 @@ int ha_myisammrg::write_row(byte * buf)
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
if (table->next_number_field && buf == table->record[0])
- update_auto_increment();
+ {
+ int error;
+ if ((error= update_auto_increment()))
+ return error;
+ }
return myrg_write(file,buf);
}
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 5d6fe5f984f..d8f33394e1a 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -2130,9 +2130,11 @@ int ha_ndbcluster::write_row(byte *record)
if (has_auto_increment)
{
THD *thd= table->in_use;
+ int error;
m_skip_auto_increment= FALSE;
- update_auto_increment();
+ if ((error= update_auto_increment()))
+ DBUG_RETURN(error);
/* Ensure that handler is always called for auto_increment values */
thd->next_insert_id= 0;
m_skip_auto_increment= !auto_increment_column_changed;
diff --git a/sql/handler.cc b/sql/handler.cc
index b0051b02d91..d29ae5e4026 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -429,6 +429,8 @@ static int ha_init_errors(void)
SETMSG(HA_ERR_TABLE_DEF_CHANGED, ER(ER_TABLE_DEF_CHANGED));
SETMSG(HA_ERR_TABLE_NEEDS_UPGRADE, ER(ER_TABLE_NEEDS_UPGRADE));
SETMSG(HA_ERR_TABLE_READONLY, ER(ER_OPEN_AS_READONLY));
+ SETMSG(HA_ERR_AUTOINC_READ_FAILED, ER(ER_AUTOINC_READ_FAILED));
+ SETMSG(HA_ERR_AUTOINC_ERANGE, ER(ER_WARN_DATA_OUT_OF_RANGE));
/* Register the error messages for use with my_error(). */
return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
@@ -1542,7 +1544,10 @@ prev_insert_id(ulonglong nr, struct system_variables *variables)
RETURN
0 ok
- 1 get_auto_increment() was called and returned ~(ulonglong) 0
+ HA_ERR_AUTOINC_READ_FAILED
+ get_auto_increment() was called and returned ~(ulonglong) 0
+ HA_ERR_AUTOINC_ERANGE
+ storing value in field caused strict mode failure.
IMPLEMENTATION
@@ -1586,13 +1591,12 @@ prev_insert_id(ulonglong nr, struct system_variables *variables)
thd->next_insert_id is cleared after it's been used for a statement.
*/
-bool handler::update_auto_increment()
+int handler::update_auto_increment()
{
ulonglong nr;
THD *thd= table->in_use;
struct system_variables *variables= &thd->variables;
bool auto_increment_field_not_null;
- bool result= 0;
DBUG_ENTER("handler::update_auto_increment");
/*
@@ -1616,7 +1620,7 @@ bool handler::update_auto_increment()
if (!(nr= thd->next_insert_id))
{
if ((nr= get_auto_increment()) == ~(ulonglong) 0)
- result= 1; // Mark failure
+ DBUG_RETURN(HA_ERR_AUTOINC_READ_FAILED); // Mark failure
if (variables->auto_increment_increment != 1)
nr= next_insert_id(nr-1, variables);
@@ -1636,6 +1640,7 @@ bool handler::update_auto_increment()
if (likely(!table->next_number_field->store((longlong) nr, TRUE)))
thd->insert_id((ulonglong) nr);
else
+ if (thd->killed != THD::KILL_BAD_DATA) /* did we fail strict mode? */
{
/*
overflow of the field; we'll use the max value, however we try to
@@ -1646,6 +1651,8 @@ bool handler::update_auto_increment()
if (unlikely(table->next_number_field->store((longlong) nr, TRUE)))
thd->insert_id(nr= table->next_number_field->val_int());
}
+ else
+ DBUG_RETURN(HA_ERR_AUTOINC_ERANGE);
/*
We can't set next_insert_id if the auto-increment key is not the
@@ -1666,7 +1673,7 @@ bool handler::update_auto_increment()
/* Mark that we generated a new value */
auto_increment_column_changed=1;
- DBUG_RETURN(result);
+ DBUG_RETURN(0);
}
/*
@@ -1864,6 +1871,12 @@ void handler::print_error(int error, myf errflag)
case HA_ERR_TABLE_READONLY:
textno= ER_OPEN_AS_READONLY;
break;
+ case HA_ERR_AUTOINC_READ_FAILED:
+ textno= ER_AUTOINC_READ_FAILED;
+ break;
+ case HA_ERR_AUTOINC_ERANGE:
+ textno= ER_WARN_DATA_OUT_OF_RANGE;
+ break;
default:
{
/* The error was "unknown" to this function.
diff --git a/sql/handler.h b/sql/handler.h
index 44de0cc715a..051f5bd31bf 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -565,7 +565,7 @@ public:
virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ }
int ha_open(const char *name, int mode, int test_if_locked);
void adjust_next_insert_id_after_explicit_value(ulonglong nr);
- bool update_auto_increment();
+ int update_auto_increment();
virtual void print_error(int error, myf errflag);
virtual bool get_error_message(int error, String *buf);
uint get_dup_key(int error);
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index e90f54608e1..94e0d6e0db5 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -5623,3 +5623,5 @@ ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA
eng "Triggers can not be created on system tables"
ER_REMOVED_SPACES
eng "Leading spaces are removed from name '%s'"
+ER_AUTOINC_READ_FAILED
+ eng "Failed to read auto-increment value from storage engine"