Commit f21eadfc authored by svoj@april.(none)'s avatar svoj@april.(none)

Merge svojtovich@bk-internal.mysql.com:/home/bk/mysql-5.0

into  april.(none):/home/svoj/devel/mysql/merge/mysql-5.0-engines
parents d8e27606 b92f68d4
...@@ -357,8 +357,10 @@ enum ha_base_keytype { ...@@ -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_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_NEEDS_UPGRADE 160 /* The table changed in storage engine */
#define HA_ERR_TABLE_READONLY 161 /* The table is not writable */ #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. */ /* Add error numbers before HA_ERR_LAST and change it accordingly. */
#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) #define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1)
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
/* Functions to compressed records */ /* Functions to compressed records */
#include "myisamdef.h" #include "fulltext.h"
#define IS_CHAR ((uint) 32768) /* Bit if char (not offset) in tree */ #define IS_CHAR ((uint) 32768) /* Bit if char (not offset) in tree */
...@@ -230,11 +230,19 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys) ...@@ -230,11 +230,19 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys)
{ {
for (i=0 ; i < share->base.keys ; i++) for (i=0 ; i < share->base.keys ; i++)
{ {
share->keyinfo[i].keylength+=(uint16) diff_length; MI_KEYDEF *keyinfo= &share->keyinfo[i];
share->keyinfo[i].minlength+=(uint16) diff_length; keyinfo->keylength+= (uint16) diff_length;
share->keyinfo[i].maxlength+=(uint16) diff_length; keyinfo->minlength+= (uint16) diff_length;
share->keyinfo[i].seg[share->keyinfo[i].keysegs].length= keyinfo->maxlength+= (uint16) diff_length;
(uint16) rec_reflength; keyinfo->seg[keyinfo->flag & HA_FULLTEXT ?
FT_SEGS : keyinfo->keysegs].length= (uint16) rec_reflength;
}
if (share->ft2_keyinfo.seg)
{
MI_KEYDEF *ft2_keyinfo= &share->ft2_keyinfo;
ft2_keyinfo->keylength+= (uint16) diff_length;
ft2_keyinfo->minlength+= (uint16) diff_length;
ft2_keyinfo->maxlength+= (uint16) diff_length;
} }
} }
......
...@@ -94,28 +94,42 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, ...@@ -94,28 +94,42 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
myisam_read_vec[search_flag], info->s->state.key_root[inx])) myisam_read_vec[search_flag], info->s->state.key_root[inx]))
{ {
/* /*
If we are searching for an exact key (including the data pointer) If we searching for a partial key (or using >, >=, < or <=) and
and this was added by an concurrent insert, the data is outside of the data file, we need to continue searching
then the result is "key not found". for the first key inside the data file
*/ */
if ((search_flag == HA_READ_KEY_EXACT) && if (info->lastpos >= info->state->data_file_length &&
(info->lastpos >= info->state->data_file_length)) (search_flag != HA_READ_KEY_EXACT ||
last_used_keyseg != keyinfo->seg + keyinfo->keysegs))
{ {
my_errno= HA_ERR_KEY_NOT_FOUND; do
info->lastpos= HA_OFFSET_ERROR; {
} uint not_used[2];
else while (info->lastpos >= info->state->data_file_length) /*
{ Skip rows that are inserted by other threads since we got a lock
/* Note that this can only happen if we are not searching after an
Skip rows that are inserted by other threads since we got a lock full length exact key, because the keys are sorted
Note that this can only happen if we are not searching after an according to position
exact key, because the keys are sorted according to position */
*/ if (_mi_search_next(info, keyinfo, info->lastkey,
if (_mi_search_next(info, keyinfo, info->lastkey, info->lastkey_length,
info->lastkey_length, myisam_readnext_vec[search_flag],
myisam_readnext_vec[search_flag], info->s->state.key_root[inx]))
info->s->state.key_root[inx])) break;
break; /*
Check that the found key does still match the search.
_mi_search_next() delivers the next key regardless of its
value.
*/
if (search_flag == HA_READ_KEY_EXACT &&
ha_key_cmp(keyinfo->seg, key_buff, info->lastkey, use_key_length,
SEARCH_FIND, not_used))
{
my_errno= HA_ERR_KEY_NOT_FOUND;
info->lastpos= HA_OFFSET_ERROR;
break;
}
} while (info->lastpos >= info->state->data_file_length);
} }
} }
} }
......
#
# 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
...@@ -424,3 +424,34 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -424,3 +424,34 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 index_merge a,b a,b 5,5 NULL # Using intersect(a,b); Using where 1 SIMPLE t3 index_merge a,b a,b 5,5 NULL # Using intersect(a,b); Using where
drop table t3; drop table t3;
drop table t0, t1, t2; drop table t0, t1, t2;
CREATE TABLE t1(a INT);
INSERT INTO t1 VALUES(1);
CREATE TABLE t2(a INT, b INT, dummy CHAR(16) DEFAULT '', KEY(a), KEY(b));
INSERT INTO t2(a,b) VALUES
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(1,2);
LOCK TABLES t1 WRITE, t2 WRITE;
INSERT INTO t2(a,b) VALUES(1,2);
SELECT t2.a FROM t1,t2 WHERE t2.b=2 AND t2.a=1;
a
1
1
UNLOCK TABLES;
DROP TABLE t1, t2;
...@@ -515,6 +515,34 @@ select c1 from t1 order by c1 limit 1; ...@@ -515,6 +515,34 @@ select c1 from t1 order by c1 limit 1;
c1 c1
a a
drop table t1; drop table t1;
create table t1 (a int not null, primary key(a));
create table t2 (a int not null, b int not null, primary key(a,b));
insert into t1 values (1),(2),(3),(4),(5),(6);
insert into t2 values (1,1),(2,1);
lock tables t1 read local, t2 read local;
select straight_join * from t1,t2 force index (primary) where t1.a=t2.a;
a a b
1 1 1
2 2 1
insert into t2 values(2,0);
select straight_join * from t1,t2 force index (primary) where t1.a=t2.a;
a a b
1 1 1
2 2 1
drop table t1,t2;
CREATE TABLE t1 (c1 varchar(250) NOT NULL);
CREATE TABLE t2 (c1 varchar(250) NOT NULL, PRIMARY KEY (c1));
INSERT INTO t1 VALUES ('test000001'), ('test000002'), ('test000003');
INSERT INTO t2 VALUES ('test000002'), ('test000003'), ('test000004');
LOCK TABLES t1 READ LOCAL, t2 READ LOCAL;
SELECT t1.c1 AS t1c1, t2.c1 AS t2c1 FROM t1, t2
WHERE t1.c1 = t2.c1 HAVING t1c1 != t2c1;
t1c1 t2c1
INSERT INTO t2 VALUES ('test000001'), ('test000005');
SELECT t1.c1 AS t1c1, t2.c1 AS t2c1 FROM t1, t2
WHERE t1.c1 = t2.c1 HAVING t1c1 != t2c1;
t1c1 t2c1
DROP TABLE t1,t2;
CREATE TABLE t1 (`a` int(11) NOT NULL default '0', `b` int(11) NOT NULL default '0', UNIQUE KEY `a` USING RTREE (`a`,`b`)) ENGINE=MyISAM; CREATE TABLE t1 (`a` int(11) NOT NULL default '0', `b` int(11) NOT NULL default '0', UNIQUE KEY `a` USING RTREE (`a`,`b`)) ENGINE=MyISAM;
Got one of the listed errors Got one of the listed errors
create table t1 (a int, b varchar(200), c text not null) checksum=1; create table t1 (a int, b varchar(200), c text not null) checksum=1;
......
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;
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;
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;
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;
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;
...@@ -383,3 +383,35 @@ explain select * from t3 where a=1 and b=1; ...@@ -383,3 +383,35 @@ explain select * from t3 where a=1 and b=1;
drop table t3; drop table t3;
drop table t0, t1, t2; drop table t0, t1, t2;
#
# BUG#20256 - LOCK WRITE - MyISAM
#
CREATE TABLE t1(a INT);
INSERT INTO t1 VALUES(1);
CREATE TABLE t2(a INT, b INT, dummy CHAR(16) DEFAULT '', KEY(a), KEY(b));
INSERT INTO t2(a,b) VALUES
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
(1,2);
LOCK TABLES t1 WRITE, t2 WRITE;
INSERT INTO t2(a,b) VALUES(1,2);
SELECT t2.a FROM t1,t2 WHERE t2.b=2 AND t2.a=1;
UNLOCK TABLES;
DROP TABLE t1, t2;
...@@ -488,6 +488,42 @@ insert into t1 values ('a'), ('b'); ...@@ -488,6 +488,42 @@ insert into t1 values ('a'), ('b');
select c1 from t1 order by c1 limit 1; select c1 from t1 order by c1 limit 1;
drop table t1; drop table t1;
#
# Bug #14400 Join could miss concurrently inserted row
#
# Partial key.
create table t1 (a int not null, primary key(a));
create table t2 (a int not null, b int not null, primary key(a,b));
insert into t1 values (1),(2),(3),(4),(5),(6);
insert into t2 values (1,1),(2,1);
lock tables t1 read local, t2 read local;
select straight_join * from t1,t2 force index (primary) where t1.a=t2.a;
connect (root,localhost,root,,test,$MASTER_MYPORT,master.sock);
insert into t2 values(2,0);
disconnect root;
connection default;
select straight_join * from t1,t2 force index (primary) where t1.a=t2.a;
drop table t1,t2;
#
# Full key.
CREATE TABLE t1 (c1 varchar(250) NOT NULL);
CREATE TABLE t2 (c1 varchar(250) NOT NULL, PRIMARY KEY (c1));
INSERT INTO t1 VALUES ('test000001'), ('test000002'), ('test000003');
INSERT INTO t2 VALUES ('test000002'), ('test000003'), ('test000004');
LOCK TABLES t1 READ LOCAL, t2 READ LOCAL;
SELECT t1.c1 AS t1c1, t2.c1 AS t2c1 FROM t1, t2
WHERE t1.c1 = t2.c1 HAVING t1c1 != t2c1;
connect (con1,localhost,root,,);
connection con1;
INSERT INTO t2 VALUES ('test000001'), ('test000005');
disconnect con1;
connection default;
SELECT t1.c1 AS t1c1, t2.c1 AS t2c1 FROM t1, t2
WHERE t1.c1 = t2.c1 HAVING t1c1 != t2c1;
DROP TABLE t1,t2;
# End of 4.0 tests
# #
# Test RTREE index # Test RTREE index
# #
......
#
# Bug#20573 Strict mode auto-increment
#
let $type= 'MYISAM' ;
--source include/strict_autoinc.inc
# end of test
-- source include/have_innodb.inc
#
# Bug#20573 Strict mode auto-increment
#
let $type= 'InnoDB' ;
--source include/strict_autoinc.inc
# end of test
#
# Bug#20573 Strict mode auto-increment
#
let $type= 'MEMORY' ;
--source include/strict_autoinc.inc
# end of test
-- source include/have_bdb.inc
#
# Bug#20573 Strict mode auto-increment
#
let $type= 'BDB' ;
--source include/strict_autoinc.inc
# end of test
-- source include/have_ndb.inc
#
# Bug#20573 Strict mode auto-increment
#
let $type= 'NDB' ;
--source include/strict_autoinc.inc
# end of test
...@@ -953,7 +953,10 @@ int ha_berkeley::write_row(byte * record) ...@@ -953,7 +953,10 @@ int ha_berkeley::write_row(byte * record)
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time(); table->timestamp_field->set_time();
if (table->next_number_field && record == table->record[0]) 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))) if ((error=pack_row(&row, record,1)))
DBUG_RETURN(error); /* purecov: inspected */ DBUG_RETURN(error); /* purecov: inspected */
......
...@@ -176,7 +176,10 @@ int ha_heap::write_row(byte * buf) ...@@ -176,7 +176,10 @@ int ha_heap::write_row(byte * buf)
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time(); table->timestamp_field->set_time();
if (table->next_number_field && buf == table->record[0]) if (table->next_number_field && buf == table->record[0])
update_auto_increment(); {
if ((res= update_auto_increment()))
return res;
}
res= heap_write(file,buf); res= heap_write(file,buf);
if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD > if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
file->s->records)) file->s->records))
......
...@@ -3252,7 +3252,8 @@ no_commit: ...@@ -3252,7 +3252,8 @@ no_commit:
/* We must use the handler code to update the auto-increment /* We must use the handler code to update the auto-increment
value to be sure that we increment it correctly. */ value to be sure that we increment it correctly. */
update_auto_increment(); if ((error= update_auto_increment()))
goto func_exit;
auto_inc_used = 1; auto_inc_used = 1;
} }
......
...@@ -169,6 +169,14 @@ ha_myisam::ha_myisam(TABLE *table_arg) ...@@ -169,6 +169,14 @@ ha_myisam::ha_myisam(TABLE *table_arg)
can_enable_indexes(1) can_enable_indexes(1)
{} {}
handler *ha_myisam::clone(MEM_ROOT *mem_root)
{
ha_myisam *new_handler= static_cast <ha_myisam *>(handler::clone(mem_root));
if (new_handler)
new_handler->file->state= file->state;
return new_handler;
}
static const char *ha_myisam_exts[] = { static const char *ha_myisam_exts[] = {
".MYI", ".MYI",
...@@ -316,7 +324,11 @@ int ha_myisam::write_row(byte * buf) ...@@ -316,7 +324,11 @@ int ha_myisam::write_row(byte * buf)
or a new row, then update the auto_increment value in the record. or a new row, then update the auto_increment value in the record.
*/ */
if (table->next_number_field && buf == table->record[0]) 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); return mi_write(file,buf);
} }
......
...@@ -45,6 +45,7 @@ class ha_myisam: public handler ...@@ -45,6 +45,7 @@ class ha_myisam: public handler
public: public:
ha_myisam(TABLE *table_arg); ha_myisam(TABLE *table_arg);
~ha_myisam() {} ~ha_myisam() {}
handler *clone(MEM_ROOT *mem_root);
const char *table_type() const { return "MyISAM"; } const char *table_type() const { return "MyISAM"; }
const char *index_type(uint key_number); const char *index_type(uint key_number);
const char **bas_ext() const; const char **bas_ext() const;
......
...@@ -139,7 +139,11 @@ int ha_myisammrg::write_row(byte * buf) ...@@ -139,7 +139,11 @@ int ha_myisammrg::write_row(byte * buf)
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time(); table->timestamp_field->set_time();
if (table->next_number_field && buf == table->record[0]) 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); return myrg_write(file,buf);
} }
......
...@@ -2131,9 +2131,11 @@ int ha_ndbcluster::write_row(byte *record) ...@@ -2131,9 +2131,11 @@ int ha_ndbcluster::write_row(byte *record)
if (has_auto_increment) if (has_auto_increment)
{ {
THD *thd= table->in_use; THD *thd= table->in_use;
int error;
m_skip_auto_increment= FALSE; 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 */ /* Ensure that handler is always called for auto_increment values */
thd->next_insert_id= 0; thd->next_insert_id= 0;
m_skip_auto_increment= !auto_increment_column_changed; m_skip_auto_increment= !auto_increment_column_changed;
......
...@@ -429,6 +429,8 @@ static int ha_init_errors(void) ...@@ -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_DEF_CHANGED, ER(ER_TABLE_DEF_CHANGED));
SETMSG(HA_ERR_TABLE_NEEDS_UPGRADE, ER(ER_TABLE_NEEDS_UPGRADE)); SETMSG(HA_ERR_TABLE_NEEDS_UPGRADE, ER(ER_TABLE_NEEDS_UPGRADE));
SETMSG(HA_ERR_TABLE_READONLY, ER(ER_OPEN_AS_READONLY)); 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(). */ /* Register the error messages for use with my_error(). */
return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST); return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
...@@ -1374,6 +1376,15 @@ int ha_delete_table(THD *thd, enum db_type table_type, const char *path, ...@@ -1374,6 +1376,15 @@ int ha_delete_table(THD *thd, enum db_type table_type, const char *path,
/**************************************************************************** /****************************************************************************
** General handler functions ** General handler functions
****************************************************************************/ ****************************************************************************/
handler *handler::clone(MEM_ROOT *mem_root)
{
handler *new_handler= get_new_handler(table, mem_root, table->s->db_type);
if (new_handler && !new_handler->ha_open(table->s->path, table->db_stat,
HA_OPEN_IGNORE_IF_LOCKED))
return new_handler;
return NULL;
}
/* Open database-handler. Try O_RDONLY if can't open as O_RDWR */ /* Open database-handler. Try O_RDONLY if can't open as O_RDWR */
/* Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set */ /* Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set */
...@@ -1542,7 +1553,10 @@ prev_insert_id(ulonglong nr, struct system_variables *variables) ...@@ -1542,7 +1553,10 @@ prev_insert_id(ulonglong nr, struct system_variables *variables)
RETURN RETURN
0 ok 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 IMPLEMENTATION
...@@ -1586,13 +1600,12 @@ prev_insert_id(ulonglong nr, struct system_variables *variables) ...@@ -1586,13 +1600,12 @@ prev_insert_id(ulonglong nr, struct system_variables *variables)
thd->next_insert_id is cleared after it's been used for a statement. 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; ulonglong nr;
THD *thd= table->in_use; THD *thd= table->in_use;
struct system_variables *variables= &thd->variables; struct system_variables *variables= &thd->variables;
bool auto_increment_field_not_null; bool auto_increment_field_not_null;
bool result= 0;
DBUG_ENTER("handler::update_auto_increment"); DBUG_ENTER("handler::update_auto_increment");
/* /*
...@@ -1616,7 +1629,7 @@ bool handler::update_auto_increment() ...@@ -1616,7 +1629,7 @@ bool handler::update_auto_increment()
if (!(nr= thd->next_insert_id)) if (!(nr= thd->next_insert_id))
{ {
if ((nr= get_auto_increment()) == ~(ulonglong) 0) 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) if (variables->auto_increment_increment != 1)
nr= next_insert_id(nr-1, variables); nr= next_insert_id(nr-1, variables);
...@@ -1636,6 +1649,7 @@ bool handler::update_auto_increment() ...@@ -1636,6 +1649,7 @@ bool handler::update_auto_increment()
if (likely(!table->next_number_field->store((longlong) nr, TRUE))) if (likely(!table->next_number_field->store((longlong) nr, TRUE)))
thd->insert_id((ulonglong) nr); thd->insert_id((ulonglong) nr);
else 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 overflow of the field; we'll use the max value, however we try to
...@@ -1646,6 +1660,8 @@ bool handler::update_auto_increment() ...@@ -1646,6 +1660,8 @@ bool handler::update_auto_increment()
if (unlikely(table->next_number_field->store((longlong) nr, TRUE))) if (unlikely(table->next_number_field->store((longlong) nr, TRUE)))
thd->insert_id(nr= table->next_number_field->val_int()); 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 We can't set next_insert_id if the auto-increment key is not the
...@@ -1666,7 +1682,7 @@ bool handler::update_auto_increment() ...@@ -1666,7 +1682,7 @@ bool handler::update_auto_increment()
/* Mark that we generated a new value */ /* Mark that we generated a new value */
auto_increment_column_changed=1; auto_increment_column_changed=1;
DBUG_RETURN(result); DBUG_RETURN(0);
} }
/* /*
...@@ -1864,6 +1880,12 @@ void handler::print_error(int error, myf errflag) ...@@ -1864,6 +1880,12 @@ void handler::print_error(int error, myf errflag)
case HA_ERR_TABLE_READONLY: case HA_ERR_TABLE_READONLY:
textno= ER_OPEN_AS_READONLY; textno= ER_OPEN_AS_READONLY;
break; 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: default:
{ {
/* The error was "unknown" to this function. /* The error was "unknown" to this function.
......
...@@ -563,9 +563,10 @@ public: ...@@ -563,9 +563,10 @@ public:
pushed_cond(NULL) pushed_cond(NULL)
{} {}
virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ } virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ }
virtual handler *clone(MEM_ROOT *mem_root);
int ha_open(const char *name, int mode, int test_if_locked); int ha_open(const char *name, int mode, int test_if_locked);
void adjust_next_insert_id_after_explicit_value(ulonglong nr); 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 void print_error(int error, myf errflag);
virtual bool get_error_message(int error, String *buf); virtual bool get_error_message(int error, String *buf);
uint get_dup_key(int error); uint get_dup_key(int error);
......
...@@ -1034,10 +1034,7 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler) ...@@ -1034,10 +1034,7 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
} }
THD *thd= current_thd; THD *thd= current_thd;
if (!(file= get_new_handler(head, thd->mem_root, head->s->db_type))) if (!(file= head->file->clone(thd->mem_root)))
goto failure;
DBUG_PRINT("info", ("Allocated new handler %p", file));
if (file->ha_open(head->s->path, head->db_stat, HA_OPEN_IGNORE_IF_LOCKED))
{ {
/* Caller will free the memory */ /* Caller will free the memory */
goto failure; goto failure;
......
...@@ -5623,6 +5623,8 @@ ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA ...@@ -5623,6 +5623,8 @@ ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA
eng "Triggers can not be created on system tables" eng "Triggers can not be created on system tables"
ER_REMOVED_SPACES ER_REMOVED_SPACES
eng "Leading spaces are removed from name '%s'" eng "Leading spaces are removed from name '%s'"
ER_AUTOINC_READ_FAILED
eng "Failed to read auto-increment value from storage engine"
ER_USERNAME ER_USERNAME
eng "user name" eng "user name"
ER_HOSTNAME ER_HOSTNAME
......
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