Merge shellback.(none):/home/msvensson/mysql/mysql-5.0
into shellback.(none):/home/msvensson/mysql/mysql-5.0-maint BitKeeper/etc/ignore: auto-union sql/item_func.h: Auto merged sql/set_var.cc: Auto merged sql/sql_class.h: Auto merged
This commit is contained in:
commit
5d5ef8469a
@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc)
|
||||
AC_CANONICAL_SYSTEM
|
||||
# The Docs Makefile.am parses this line!
|
||||
# remember to also change ndb version below and update version.c in ndb
|
||||
AM_INIT_AUTOMAKE(mysql, 5.0.26)
|
||||
AM_INIT_AUTOMAKE(mysql, 5.0.27)
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
PROTOCOL_VERSION=10
|
||||
@ -19,7 +19,7 @@ SHARED_LIB_VERSION=$SHARED_LIB_MAJOR_VERSION:0:0
|
||||
# ndb version
|
||||
NDB_VERSION_MAJOR=5
|
||||
NDB_VERSION_MINOR=0
|
||||
NDB_VERSION_BUILD=26
|
||||
NDB_VERSION_BUILD=27
|
||||
NDB_VERSION_STATUS=""
|
||||
|
||||
# Set all version vars based on $VERSION. How do we do this more elegant ?
|
||||
|
@ -446,7 +446,7 @@ static int del(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *key,
|
||||
else
|
||||
{
|
||||
DBUG_PRINT("test",("Inserting of key when deleting"));
|
||||
if (_mi_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos,
|
||||
if (!_mi_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos,
|
||||
&tmp))
|
||||
goto err;
|
||||
ret_value=_mi_insert(info,keyinfo,key,leaf_buff,endpos,keybuff,
|
||||
|
@ -126,7 +126,6 @@ int main(int argc,char *argv[])
|
||||
|
||||
if (count || stats)
|
||||
{
|
||||
doc_cnt++;
|
||||
if (strcmp(buf, buf2))
|
||||
{
|
||||
if (*buf2)
|
||||
@ -151,6 +150,7 @@ int main(int argc,char *argv[])
|
||||
keylen2=keylen;
|
||||
doc_cnt=0;
|
||||
}
|
||||
doc_cnt+= (subkeys >= 0 ? 1 : -subkeys);
|
||||
}
|
||||
if (dump)
|
||||
{
|
||||
@ -166,7 +166,6 @@ int main(int argc,char *argv[])
|
||||
|
||||
if (count || stats)
|
||||
{
|
||||
doc_cnt++;
|
||||
if (*buf2)
|
||||
{
|
||||
uniq++;
|
||||
|
@ -33,7 +33,7 @@
|
||||
MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
|
||||
{
|
||||
int save_errno,errpos=0;
|
||||
uint files=0,i,dir_length,length,key_parts;
|
||||
uint files= 0, i, dir_length, length, key_parts, min_keys= 0;
|
||||
ulonglong file_offset=0;
|
||||
char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end;
|
||||
MYRG_INFO *m_info=0;
|
||||
@ -89,7 +89,10 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
|
||||
else
|
||||
fn_format(buff, buff, "", "", 0);
|
||||
if (!(isam=mi_open(buff,mode,(handle_locking?HA_OPEN_WAIT_IF_LOCKED:0))))
|
||||
{
|
||||
my_errno= HA_ERR_WRONG_MRG_TABLE_DEF;
|
||||
goto err;
|
||||
}
|
||||
if (!m_info) /* First file */
|
||||
{
|
||||
key_parts=isam->s->base.key_parts;
|
||||
@ -106,6 +109,7 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
|
||||
files= 0;
|
||||
}
|
||||
m_info->reclength=isam->s->base.reclength;
|
||||
min_keys= isam->s->base.keys;
|
||||
errpos=3;
|
||||
}
|
||||
m_info->open_tables[files].table= isam;
|
||||
@ -121,6 +125,8 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
|
||||
m_info->records+= isam->state->records;
|
||||
m_info->del+= isam->state->del;
|
||||
m_info->data_file_length+= isam->state->data_file_length;
|
||||
if (min_keys > isam->s->base.keys)
|
||||
min_keys= isam->s->base.keys;
|
||||
for (i=0; i < key_parts; i++)
|
||||
m_info->rec_per_key_part[i]+= (isam->s->state.rec_per_key_part[i] /
|
||||
m_info->tables);
|
||||
@ -138,7 +144,7 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
|
||||
my_errno=HA_ERR_RECORD_FILE_FULL;
|
||||
goto err;
|
||||
}
|
||||
m_info->keys= files ? isam->s->base.keys : 0;
|
||||
m_info->keys= min_keys;
|
||||
bzero((char*) &m_info->by_key,sizeof(m_info->by_key));
|
||||
|
||||
/* this works ok if the table list is empty */
|
||||
|
@ -65,6 +65,8 @@ int _myrg_init_queue(MYRG_INFO *info,int inx,enum ha_rkey_function search_flag)
|
||||
error=my_errno;
|
||||
}
|
||||
}
|
||||
else
|
||||
my_errno= error= HA_ERR_WRONG_INDEX;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ insert delayed into t1 set a = 4;
|
||||
insert delayed into t1 set a = 5, tmsp = 19711006010203;
|
||||
insert delayed into t1 (a, tmsp) values (6, 19711006010203);
|
||||
insert delayed into t1 (a, tmsp) values (7, NULL);
|
||||
FLUSH TABLE t1;
|
||||
insert into t1 set a = 8,tmsp=19711006010203;
|
||||
select * from t1 where tmsp=0;
|
||||
a tmsp
|
||||
@ -22,6 +23,7 @@ insert delayed into t1 values (null,"c");
|
||||
insert delayed into t1 values (3,"d"),(null,"e");
|
||||
insert delayed into t1 values (3,"this will give an","error");
|
||||
ERROR 21S01: Column count doesn't match value count at row 1
|
||||
FLUSH TABLE t1;
|
||||
show status like 'not_flushed_delayed_rows';
|
||||
Variable_name Value
|
||||
Not_flushed_delayed_rows 0
|
||||
@ -54,6 +56,7 @@ insert delayed into t1 values(null);
|
||||
insert delayed into t1 values(null);
|
||||
insert delayed into t1 values(null);
|
||||
insert delayed into t1 values(null);
|
||||
FLUSH TABLE t1;
|
||||
select * from t1 order by a;
|
||||
a
|
||||
1
|
||||
@ -69,3 +72,174 @@ a
|
||||
12
|
||||
13
|
||||
DROP TABLE t1;
|
||||
SET @bug20627_old_auto_increment_offset=
|
||||
@@auto_increment_offset= 2;
|
||||
SET @bug20627_old_auto_increment_increment=
|
||||
@@auto_increment_increment= 3;
|
||||
SET @bug20627_old_session_auto_increment_offset=
|
||||
@@session.auto_increment_offset= 4;
|
||||
SET @bug20627_old_session_auto_increment_increment=
|
||||
@@session.auto_increment_increment= 5;
|
||||
SET @@auto_increment_offset= 2;
|
||||
SET @@auto_increment_increment= 3;
|
||||
SET @@session.auto_increment_offset= 4;
|
||||
SET @@session.auto_increment_increment= 5;
|
||||
CREATE TABLE t1 (
|
||||
c1 INT NOT NULL AUTO_INCREMENT,
|
||||
PRIMARY KEY (c1)
|
||||
);
|
||||
INSERT INTO t1 VALUES (NULL),(NULL),(NULL);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
4
|
||||
9
|
||||
14
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (
|
||||
c1 INT NOT NULL AUTO_INCREMENT,
|
||||
PRIMARY KEY (c1)
|
||||
);
|
||||
INSERT DELAYED INTO t1 VALUES (NULL),(NULL),(NULL);
|
||||
FLUSH TABLE t1;
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
4
|
||||
9
|
||||
14
|
||||
DROP TABLE t1;
|
||||
SET @@auto_increment_offset=
|
||||
@bug20627_old_auto_increment_offset;
|
||||
SET @@auto_increment_increment=
|
||||
@bug20627_old_auto_increment_increment;
|
||||
SET @@session.auto_increment_offset=
|
||||
@bug20627_old_session_auto_increment_offset;
|
||||
SET @@session.auto_increment_increment=
|
||||
@bug20627_old_session_auto_increment_increment;
|
||||
SET @bug20830_old_auto_increment_offset=
|
||||
@@auto_increment_offset= 2;
|
||||
SET @bug20830_old_auto_increment_increment=
|
||||
@@auto_increment_increment= 3;
|
||||
SET @bug20830_old_session_auto_increment_offset=
|
||||
@@session.auto_increment_offset= 4;
|
||||
SET @bug20830_old_session_auto_increment_increment=
|
||||
@@session.auto_increment_increment= 5;
|
||||
SET @@auto_increment_offset= 2;
|
||||
SET @@auto_increment_increment= 3;
|
||||
SET @@session.auto_increment_offset= 4;
|
||||
SET @@session.auto_increment_increment= 5;
|
||||
CREATE TABLE t1 (
|
||||
c1 INT(11) NOT NULL AUTO_INCREMENT,
|
||||
c2 INT(11) DEFAULT NULL,
|
||||
PRIMARY KEY (c1)
|
||||
);
|
||||
SET insert_id= 14;
|
||||
INSERT INTO t1 VALUES(NULL, 11), (NULL, 12), (NULL, 13);
|
||||
INSERT INTO t1 VALUES(NULL, 21), (NULL, 22), (NULL, 23);
|
||||
INSERT INTO t1 VALUES( 69, 31), (NULL, 32), (NULL, 33);
|
||||
INSERT INTO t1 VALUES(NULL, 41), (NULL, 42), (NULL, 43);
|
||||
SET insert_id= 114;
|
||||
INSERT INTO t1 VALUES(NULL, 51), (NULL, 52), (NULL, 53);
|
||||
INSERT INTO t1 VALUES(NULL, 61), (NULL, 62), (NULL, 63);
|
||||
INSERT INTO t1 VALUES( 49, 71), (NULL, 72), (NULL, 73);
|
||||
INSERT INTO t1 VALUES(NULL, 81), (NULL, 82), (NULL, 83);
|
||||
SET insert_id= 114;
|
||||
INSERT INTO t1 VALUES(NULL, 91);
|
||||
ERROR 23000: Duplicate entry '114' for key 1
|
||||
INSERT INTO t1 VALUES (NULL, 92), (NULL, 93);
|
||||
SELECT * FROM t1;
|
||||
c1 c2
|
||||
14 11
|
||||
19 12
|
||||
24 13
|
||||
29 21
|
||||
34 22
|
||||
39 23
|
||||
69 31
|
||||
74 32
|
||||
79 33
|
||||
84 41
|
||||
89 42
|
||||
94 43
|
||||
114 51
|
||||
119 52
|
||||
124 53
|
||||
129 61
|
||||
134 62
|
||||
139 63
|
||||
49 71
|
||||
144 72
|
||||
149 73
|
||||
154 81
|
||||
159 82
|
||||
164 83
|
||||
169 92
|
||||
174 93
|
||||
SELECT COUNT(*) FROM t1;
|
||||
COUNT(*)
|
||||
26
|
||||
SELECT SUM(c1) FROM t1;
|
||||
SUM(c1)
|
||||
2569
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (
|
||||
c1 INT(11) NOT NULL AUTO_INCREMENT,
|
||||
c2 INT(11) DEFAULT NULL,
|
||||
PRIMARY KEY (c1)
|
||||
);
|
||||
SET insert_id= 14;
|
||||
INSERT DELAYED INTO t1 VALUES(NULL, 11), (NULL, 12), (NULL, 13);
|
||||
INSERT DELAYED INTO t1 VALUES(NULL, 21), (NULL, 22), (NULL, 23);
|
||||
INSERT DELAYED INTO t1 VALUES( 69, 31), (NULL, 32), (NULL, 33);
|
||||
INSERT DELAYED INTO t1 VALUES(NULL, 41), (NULL, 42), (NULL, 43);
|
||||
SET insert_id= 114;
|
||||
INSERT DELAYED INTO t1 VALUES(NULL, 51), (NULL, 52), (NULL, 53);
|
||||
INSERT DELAYED INTO t1 VALUES(NULL, 61), (NULL, 62), (NULL, 63);
|
||||
INSERT DELAYED INTO t1 VALUES( 49, 71), (NULL, 72), (NULL, 73);
|
||||
INSERT DELAYED INTO t1 VALUES(NULL, 81), (NULL, 82), (NULL, 83);
|
||||
SET insert_id= 114;
|
||||
INSERT DELAYED INTO t1 VALUES(NULL, 91);
|
||||
INSERT DELAYED INTO t1 VALUES (NULL, 92), (NULL, 93);
|
||||
FLUSH TABLE t1;
|
||||
SELECT * FROM t1;
|
||||
c1 c2
|
||||
14 11
|
||||
19 12
|
||||
24 13
|
||||
29 21
|
||||
34 22
|
||||
39 23
|
||||
69 31
|
||||
74 32
|
||||
79 33
|
||||
84 41
|
||||
89 42
|
||||
94 43
|
||||
114 51
|
||||
119 52
|
||||
124 53
|
||||
129 61
|
||||
134 62
|
||||
139 63
|
||||
49 71
|
||||
144 72
|
||||
149 73
|
||||
154 81
|
||||
159 82
|
||||
164 83
|
||||
169 92
|
||||
174 93
|
||||
SELECT COUNT(*) FROM t1;
|
||||
COUNT(*)
|
||||
26
|
||||
SELECT SUM(c1) FROM t1;
|
||||
SUM(c1)
|
||||
2569
|
||||
DROP TABLE t1;
|
||||
SET @@auto_increment_offset=
|
||||
@bug20830_old_auto_increment_offset;
|
||||
SET @@auto_increment_increment=
|
||||
@bug20830_old_auto_increment_increment;
|
||||
SET @@session.auto_increment_offset=
|
||||
@bug20830_old_session_auto_increment_offset;
|
||||
SET @@session.auto_increment_increment=
|
||||
@bug20830_old_session_auto_increment_increment;
|
||||
|
@ -178,9 +178,9 @@ t3 CREATE TABLE `t3` (
|
||||
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`,`t2`)
|
||||
create table t4 (a int not null, b char(10), key(a)) engine=MERGE UNION=(t1,t2);
|
||||
select * from t4;
|
||||
ERROR HY000: All tables in the MERGE table are not identically defined
|
||||
ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists
|
||||
alter table t4 add column c int;
|
||||
ERROR HY000: All tables in the MERGE table are not identically defined
|
||||
ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists
|
||||
create database mysqltest;
|
||||
create table mysqltest.t6 (a int not null primary key auto_increment, message char(20));
|
||||
create table t5 (a int not null, b char(20), key(a)) engine=MERGE UNION=(test.t1,mysqltest.t6);
|
||||
@ -768,6 +768,21 @@ Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
test.t2 check status OK
|
||||
drop table t1, t2, t3;
|
||||
CREATE TABLE t1(a INT);
|
||||
INSERT INTO t1 VALUES(2),(1);
|
||||
CREATE TABLE t2(a INT, KEY(a)) ENGINE=MERGE UNION=(t1);
|
||||
SELECT * FROM t2 WHERE a=2;
|
||||
ERROR HY000: Got error 124 from storage engine
|
||||
DROP TABLE t1, t2;
|
||||
CREATE TABLE t1(a INT) ENGINE=MEMORY;
|
||||
CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t1);
|
||||
SELECT * FROM t2;
|
||||
ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists
|
||||
DROP TABLE t1, t2;
|
||||
CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t3);
|
||||
SELECT * FROM t2;
|
||||
ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists
|
||||
DROP TABLE t2;
|
||||
create table t1 (b bit(1));
|
||||
create table t2 (b bit(1));
|
||||
create table tm (b bit(1)) engine = merge union = (t1,t2);
|
||||
|
@ -234,6 +234,135 @@ n b
|
||||
2 100
|
||||
3 350
|
||||
drop table t1;
|
||||
DROP PROCEDURE IF EXISTS p1;
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
SELECT LAST_INSERT_ID(0);
|
||||
LAST_INSERT_ID(0)
|
||||
0
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL DEFAULT 0,
|
||||
last_id INT,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
CREATE TABLE t2 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
last_id INT,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
INSERT INTO t2 (last_id) VALUES (LAST_INSERT_ID());
|
||||
INSERT INTO t1 (last_id) VALUES (LAST_INSERT_ID());
|
||||
END|
|
||||
CALL p1();
|
||||
SELECT * FROM t1;
|
||||
id last_id
|
||||
0 1
|
||||
SELECT * FROM t2;
|
||||
id last_id
|
||||
1 0
|
||||
SELECT * FROM t1;
|
||||
id last_id
|
||||
0 1
|
||||
SELECT * FROM t2;
|
||||
id last_id
|
||||
1 0
|
||||
DROP PROCEDURE p1;
|
||||
DROP TABLE t1, t2;
|
||||
DROP PROCEDURE IF EXISTS p1;
|
||||
DROP FUNCTION IF EXISTS f1;
|
||||
DROP FUNCTION IF EXISTS f2;
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
CREATE TABLE t1 (
|
||||
i INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
j INT DEFAULT 0
|
||||
);
|
||||
CREATE TABLE t2 (i INT);
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
INSERT INTO t1 (i) VALUES (NULL);
|
||||
INSERT INTO t2 (i) VALUES (LAST_INSERT_ID());
|
||||
INSERT INTO t1 (i) VALUES (NULL), (NULL);
|
||||
INSERT INTO t2 (i) VALUES (LAST_INSERT_ID());
|
||||
END |
|
||||
CREATE FUNCTION f1() RETURNS INT MODIFIES SQL DATA
|
||||
BEGIN
|
||||
INSERT INTO t1 (i) VALUES (NULL);
|
||||
INSERT INTO t2 (i) VALUES (LAST_INSERT_ID());
|
||||
INSERT INTO t1 (i) VALUES (NULL), (NULL);
|
||||
INSERT INTO t2 (i) VALUES (LAST_INSERT_ID());
|
||||
RETURN 0;
|
||||
END |
|
||||
CREATE FUNCTION f2() RETURNS INT NOT DETERMINISTIC
|
||||
RETURN LAST_INSERT_ID() |
|
||||
INSERT INTO t1 VALUES (NULL, -1);
|
||||
CALL p1();
|
||||
SELECT f1();
|
||||
f1()
|
||||
0
|
||||
INSERT INTO t1 VALUES (NULL, f2()), (NULL, LAST_INSERT_ID()),
|
||||
(NULL, LAST_INSERT_ID()), (NULL, f2()), (NULL, f2());
|
||||
INSERT INTO t1 VALUES (NULL, f2());
|
||||
INSERT INTO t1 VALUES (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID(5)),
|
||||
(NULL, @@LAST_INSERT_ID);
|
||||
INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID());
|
||||
UPDATE t1 SET j= -1 WHERE i IS NULL;
|
||||
SELECT * FROM t1;
|
||||
i j
|
||||
1 -1
|
||||
2 0
|
||||
3 0
|
||||
4 0
|
||||
5 0
|
||||
6 0
|
||||
7 0
|
||||
8 3
|
||||
9 3
|
||||
10 3
|
||||
11 3
|
||||
12 3
|
||||
13 8
|
||||
14 13
|
||||
15 5
|
||||
16 13
|
||||
17 -1
|
||||
18 14
|
||||
SELECT * FROM t2;
|
||||
i
|
||||
2
|
||||
3
|
||||
5
|
||||
6
|
||||
SELECT * FROM t1;
|
||||
i j
|
||||
1 -1
|
||||
2 0
|
||||
3 0
|
||||
4 0
|
||||
5 0
|
||||
6 0
|
||||
7 0
|
||||
8 3
|
||||
9 3
|
||||
10 3
|
||||
11 3
|
||||
12 3
|
||||
13 8
|
||||
14 13
|
||||
15 5
|
||||
16 13
|
||||
17 -1
|
||||
18 14
|
||||
SELECT * FROM t2;
|
||||
i
|
||||
2
|
||||
3
|
||||
5
|
||||
6
|
||||
DROP PROCEDURE p1;
|
||||
DROP FUNCTION f1;
|
||||
DROP FUNCTION f2;
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
# End of 5.0 tests
|
||||
|
||||
|
@ -17,7 +17,8 @@ insert delayed into t1 set a = 4;
|
||||
insert delayed into t1 set a = 5, tmsp = 19711006010203;
|
||||
insert delayed into t1 (a, tmsp) values (6, 19711006010203);
|
||||
insert delayed into t1 (a, tmsp) values (7, NULL);
|
||||
--sleep 2
|
||||
# Wait until the rows are flushed to the table files.
|
||||
FLUSH TABLE t1;
|
||||
insert into t1 set a = 8,tmsp=19711006010203;
|
||||
select * from t1 where tmsp=0;
|
||||
select * from t1 where tmsp=19711006010203;
|
||||
@ -34,8 +35,8 @@ insert delayed into t1 values (null,"c");
|
||||
insert delayed into t1 values (3,"d"),(null,"e");
|
||||
--error 1136
|
||||
insert delayed into t1 values (3,"this will give an","error");
|
||||
# 2 was not enough for --ps-protocol
|
||||
--sleep 4
|
||||
# Wait until the rows are flushed to the table files.
|
||||
FLUSH TABLE t1;
|
||||
show status like 'not_flushed_delayed_rows';
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
@ -92,10 +93,145 @@ insert delayed into t1 values(null);
|
||||
# Works, since the delayed-counter is 8, which is unused
|
||||
insert delayed into t1 values(null);
|
||||
|
||||
# Wait until the rows are flushed to the table files.
|
||||
FLUSH TABLE t1;
|
||||
# Check what we have now
|
||||
# must wait so that the delayed thread finishes
|
||||
# Note: this must be increased if the test fails
|
||||
--sleep 1
|
||||
select * from t1 order by a;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Bug#20627 - INSERT DELAYED does not honour auto_increment_* variables
|
||||
#
|
||||
SET @bug20627_old_auto_increment_offset=
|
||||
@@auto_increment_offset= 2;
|
||||
SET @bug20627_old_auto_increment_increment=
|
||||
@@auto_increment_increment= 3;
|
||||
SET @bug20627_old_session_auto_increment_offset=
|
||||
@@session.auto_increment_offset= 4;
|
||||
SET @bug20627_old_session_auto_increment_increment=
|
||||
@@session.auto_increment_increment= 5;
|
||||
SET @@auto_increment_offset= 2;
|
||||
SET @@auto_increment_increment= 3;
|
||||
SET @@session.auto_increment_offset= 4;
|
||||
SET @@session.auto_increment_increment= 5;
|
||||
#
|
||||
# Normal insert as reference.
|
||||
CREATE TABLE t1 (
|
||||
c1 INT NOT NULL AUTO_INCREMENT,
|
||||
PRIMARY KEY (c1)
|
||||
);
|
||||
INSERT INTO t1 VALUES (NULL),(NULL),(NULL);
|
||||
# Check what we have now
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Delayed insert.
|
||||
CREATE TABLE t1 (
|
||||
c1 INT NOT NULL AUTO_INCREMENT,
|
||||
PRIMARY KEY (c1)
|
||||
);
|
||||
INSERT DELAYED INTO t1 VALUES (NULL),(NULL),(NULL);
|
||||
# Wait until the rows are flushed to the table files.
|
||||
FLUSH TABLE t1;
|
||||
# Check what we have now
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Cleanup
|
||||
SET @@auto_increment_offset=
|
||||
@bug20627_old_auto_increment_offset;
|
||||
SET @@auto_increment_increment=
|
||||
@bug20627_old_auto_increment_increment;
|
||||
SET @@session.auto_increment_offset=
|
||||
@bug20627_old_session_auto_increment_offset;
|
||||
SET @@session.auto_increment_increment=
|
||||
@bug20627_old_session_auto_increment_increment;
|
||||
|
||||
#
|
||||
# Bug#20830 - INSERT DELAYED does not honour SET INSERT_ID
|
||||
#
|
||||
SET @bug20830_old_auto_increment_offset=
|
||||
@@auto_increment_offset= 2;
|
||||
SET @bug20830_old_auto_increment_increment=
|
||||
@@auto_increment_increment= 3;
|
||||
SET @bug20830_old_session_auto_increment_offset=
|
||||
@@session.auto_increment_offset= 4;
|
||||
SET @bug20830_old_session_auto_increment_increment=
|
||||
@@session.auto_increment_increment= 5;
|
||||
SET @@auto_increment_offset= 2;
|
||||
SET @@auto_increment_increment= 3;
|
||||
SET @@session.auto_increment_offset= 4;
|
||||
SET @@session.auto_increment_increment= 5;
|
||||
#
|
||||
# Normal insert as reference.
|
||||
CREATE TABLE t1 (
|
||||
c1 INT(11) NOT NULL AUTO_INCREMENT,
|
||||
c2 INT(11) DEFAULT NULL,
|
||||
PRIMARY KEY (c1)
|
||||
);
|
||||
SET insert_id= 14;
|
||||
INSERT INTO t1 VALUES(NULL, 11), (NULL, 12), (NULL, 13);
|
||||
INSERT INTO t1 VALUES(NULL, 21), (NULL, 22), (NULL, 23);
|
||||
# Restart sequence at a different value.
|
||||
INSERT INTO t1 VALUES( 69, 31), (NULL, 32), (NULL, 33);
|
||||
INSERT INTO t1 VALUES(NULL, 41), (NULL, 42), (NULL, 43);
|
||||
# Restart sequence at a different value.
|
||||
SET insert_id= 114;
|
||||
INSERT INTO t1 VALUES(NULL, 51), (NULL, 52), (NULL, 53);
|
||||
INSERT INTO t1 VALUES(NULL, 61), (NULL, 62), (NULL, 63);
|
||||
# Set one value below the maximum value.
|
||||
INSERT INTO t1 VALUES( 49, 71), (NULL, 72), (NULL, 73);
|
||||
INSERT INTO t1 VALUES(NULL, 81), (NULL, 82), (NULL, 83);
|
||||
# Create a duplicate value.
|
||||
SET insert_id= 114;
|
||||
--error 1062
|
||||
INSERT INTO t1 VALUES(NULL, 91);
|
||||
INSERT INTO t1 VALUES (NULL, 92), (NULL, 93);
|
||||
# Check what we have now
|
||||
SELECT * FROM t1;
|
||||
SELECT COUNT(*) FROM t1;
|
||||
SELECT SUM(c1) FROM t1;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Delayed insert.
|
||||
CREATE TABLE t1 (
|
||||
c1 INT(11) NOT NULL AUTO_INCREMENT,
|
||||
c2 INT(11) DEFAULT NULL,
|
||||
PRIMARY KEY (c1)
|
||||
);
|
||||
SET insert_id= 14;
|
||||
INSERT DELAYED INTO t1 VALUES(NULL, 11), (NULL, 12), (NULL, 13);
|
||||
INSERT DELAYED INTO t1 VALUES(NULL, 21), (NULL, 22), (NULL, 23);
|
||||
# Restart sequence at a different value.
|
||||
INSERT DELAYED INTO t1 VALUES( 69, 31), (NULL, 32), (NULL, 33);
|
||||
INSERT DELAYED INTO t1 VALUES(NULL, 41), (NULL, 42), (NULL, 43);
|
||||
# Restart sequence at a different value.
|
||||
SET insert_id= 114;
|
||||
INSERT DELAYED INTO t1 VALUES(NULL, 51), (NULL, 52), (NULL, 53);
|
||||
INSERT DELAYED INTO t1 VALUES(NULL, 61), (NULL, 62), (NULL, 63);
|
||||
# Set one value below the maximum value.
|
||||
INSERT DELAYED INTO t1 VALUES( 49, 71), (NULL, 72), (NULL, 73);
|
||||
INSERT DELAYED INTO t1 VALUES(NULL, 81), (NULL, 82), (NULL, 83);
|
||||
# Create a duplicate value.
|
||||
SET insert_id= 114;
|
||||
INSERT DELAYED INTO t1 VALUES(NULL, 91);
|
||||
INSERT DELAYED INTO t1 VALUES (NULL, 92), (NULL, 93);
|
||||
# Wait until the rows are flushed to the table files.
|
||||
FLUSH TABLE t1;
|
||||
# Check what we have now
|
||||
SELECT * FROM t1;
|
||||
SELECT COUNT(*) FROM t1;
|
||||
SELECT SUM(c1) FROM t1;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Cleanup
|
||||
SET @@auto_increment_offset=
|
||||
@bug20830_old_auto_increment_offset;
|
||||
SET @@auto_increment_increment=
|
||||
@bug20830_old_auto_increment_increment;
|
||||
SET @@session.auto_increment_offset=
|
||||
@bug20830_old_session_auto_increment_offset;
|
||||
SET @@session.auto_increment_increment=
|
||||
@bug20830_old_session_auto_increment_increment;
|
||||
|
||||
|
@ -378,6 +378,31 @@ select * from t3;
|
||||
check table t1, t2;
|
||||
drop table t1, t2, t3;
|
||||
|
||||
#
|
||||
# BUG#21617 - crash when selecting from merge table with inconsistent
|
||||
# indexes
|
||||
#
|
||||
CREATE TABLE t1(a INT);
|
||||
INSERT INTO t1 VALUES(2),(1);
|
||||
CREATE TABLE t2(a INT, KEY(a)) ENGINE=MERGE UNION=(t1);
|
||||
--error 1030
|
||||
SELECT * FROM t2 WHERE a=2;
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
#
|
||||
# BUG#10974 - No error message if merge table based on union of innodb,
|
||||
# memory
|
||||
#
|
||||
CREATE TABLE t1(a INT) ENGINE=MEMORY;
|
||||
CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t1);
|
||||
--error 1168
|
||||
SELECT * FROM t2;
|
||||
DROP TABLE t1, t2;
|
||||
CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t3);
|
||||
--error 1168
|
||||
SELECT * FROM t2;
|
||||
DROP TABLE t2;
|
||||
|
||||
# End of 4.1 tests
|
||||
|
||||
#
|
||||
|
@ -244,6 +244,118 @@ select * from t1 order by n;
|
||||
|
||||
connection master;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# BUG#20339: stored procedure using LAST_INSERT_ID() does not
|
||||
# replicate statement-based
|
||||
#
|
||||
--disable_warnings
|
||||
DROP PROCEDURE IF EXISTS p1;
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
--enable_warnings
|
||||
|
||||
# Reset result of LAST_INSERT_ID().
|
||||
SELECT LAST_INSERT_ID(0);
|
||||
|
||||
CREATE TABLE t1 (
|
||||
id INT NOT NULL DEFAULT 0,
|
||||
last_id INT,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE t2 (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
last_id INT,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
delimiter |;
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
INSERT INTO t2 (last_id) VALUES (LAST_INSERT_ID());
|
||||
INSERT INTO t1 (last_id) VALUES (LAST_INSERT_ID());
|
||||
END|
|
||||
delimiter ;|
|
||||
|
||||
CALL p1();
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
|
||||
sync_slave_with_master;
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
|
||||
connection master;
|
||||
|
||||
DROP PROCEDURE p1;
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
|
||||
#
|
||||
# BUG#21726: Incorrect result with multiple invocations of
|
||||
# LAST_INSERT_ID
|
||||
#
|
||||
--disable_warnings
|
||||
DROP PROCEDURE IF EXISTS p1;
|
||||
DROP FUNCTION IF EXISTS f1;
|
||||
DROP FUNCTION IF EXISTS f2;
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
--enable_warnings
|
||||
|
||||
CREATE TABLE t1 (
|
||||
i INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
j INT DEFAULT 0
|
||||
);
|
||||
CREATE TABLE t2 (i INT);
|
||||
|
||||
delimiter |;
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
INSERT INTO t1 (i) VALUES (NULL);
|
||||
INSERT INTO t2 (i) VALUES (LAST_INSERT_ID());
|
||||
INSERT INTO t1 (i) VALUES (NULL), (NULL);
|
||||
INSERT INTO t2 (i) VALUES (LAST_INSERT_ID());
|
||||
END |
|
||||
|
||||
CREATE FUNCTION f1() RETURNS INT MODIFIES SQL DATA
|
||||
BEGIN
|
||||
INSERT INTO t1 (i) VALUES (NULL);
|
||||
INSERT INTO t2 (i) VALUES (LAST_INSERT_ID());
|
||||
INSERT INTO t1 (i) VALUES (NULL), (NULL);
|
||||
INSERT INTO t2 (i) VALUES (LAST_INSERT_ID());
|
||||
RETURN 0;
|
||||
END |
|
||||
|
||||
CREATE FUNCTION f2() RETURNS INT NOT DETERMINISTIC
|
||||
RETURN LAST_INSERT_ID() |
|
||||
delimiter ;|
|
||||
|
||||
INSERT INTO t1 VALUES (NULL, -1);
|
||||
CALL p1();
|
||||
SELECT f1();
|
||||
INSERT INTO t1 VALUES (NULL, f2()), (NULL, LAST_INSERT_ID()),
|
||||
(NULL, LAST_INSERT_ID()), (NULL, f2()), (NULL, f2());
|
||||
INSERT INTO t1 VALUES (NULL, f2());
|
||||
INSERT INTO t1 VALUES (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID(5)),
|
||||
(NULL, @@LAST_INSERT_ID);
|
||||
# Test replication of substitution "IS NULL" -> "= LAST_INSERT_ID".
|
||||
INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID());
|
||||
UPDATE t1 SET j= -1 WHERE i IS NULL;
|
||||
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
|
||||
sync_slave_with_master;
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
|
||||
connection master;
|
||||
DROP PROCEDURE p1;
|
||||
DROP FUNCTION f1;
|
||||
DROP FUNCTION f2;
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
|
||||
sync_slave_with_master;
|
||||
|
||||
--echo
|
||||
|
@ -164,28 +164,22 @@ void delete_queue(QUEUE *queue)
|
||||
|
||||
void queue_insert(register QUEUE *queue, byte *element)
|
||||
{
|
||||
reg2 uint idx,next;
|
||||
reg2 uint idx, next;
|
||||
int cmp;
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
if (queue->elements < queue->max_elements)
|
||||
#endif
|
||||
DBUG_ASSERT(queue->elements < queue->max_elements);
|
||||
queue->root[0]= element;
|
||||
idx= ++queue->elements;
|
||||
/* max_at_top swaps the comparison if we want to order by desc */
|
||||
while ((cmp= queue->compare(queue->first_cmp_arg,
|
||||
element + queue->offset_to_key,
|
||||
queue->root[(next= idx >> 1)] +
|
||||
queue->offset_to_key)) &&
|
||||
(cmp ^ queue->max_at_top) < 0)
|
||||
{
|
||||
queue->root[0]=element;
|
||||
idx= ++queue->elements;
|
||||
|
||||
/* max_at_top swaps the comparison if we want to order by desc */
|
||||
while ((cmp=queue->compare(queue->first_cmp_arg,
|
||||
element+queue->offset_to_key,
|
||||
queue->root[(next=idx >> 1)] +
|
||||
queue->offset_to_key)) &&
|
||||
(cmp ^ queue->max_at_top) < 0)
|
||||
{
|
||||
queue->root[idx]=queue->root[next];
|
||||
idx=next;
|
||||
}
|
||||
queue->root[idx]=element;
|
||||
queue->root[idx]= queue->root[next];
|
||||
idx= next;
|
||||
}
|
||||
queue->root[idx]= element;
|
||||
}
|
||||
|
||||
/* Remove item from queue */
|
||||
@ -193,16 +187,12 @@ void queue_insert(register QUEUE *queue, byte *element)
|
||||
|
||||
byte *queue_remove(register QUEUE *queue, uint idx)
|
||||
{
|
||||
#ifndef DBUG_OFF
|
||||
if (idx >= queue->max_elements)
|
||||
return 0;
|
||||
#endif
|
||||
{
|
||||
byte *element=queue->root[++idx]; /* Intern index starts from 1 */
|
||||
queue->root[idx]=queue->root[queue->elements--];
|
||||
_downheap(queue,idx);
|
||||
return element;
|
||||
}
|
||||
byte *element;
|
||||
DBUG_ASSERT(idx < queue->max_elements);
|
||||
element= queue->root[++idx]; /* Intern index starts from 1 */
|
||||
queue->root[idx]= queue->root[queue->elements--];
|
||||
_downheap(queue, idx);
|
||||
return element;
|
||||
}
|
||||
|
||||
/* Fix when element on top has been replaced */
|
||||
|
@ -120,6 +120,8 @@ static bool archive_inited= FALSE;
|
||||
/* Variables for archive share methods */
|
||||
pthread_mutex_t archive_mutex;
|
||||
static HASH archive_open_tables;
|
||||
static z_off_t max_zfile_size;
|
||||
static int zoffset_size;
|
||||
|
||||
/* The file extension */
|
||||
#define ARZ ".ARZ" // The data file
|
||||
@ -203,6 +205,18 @@ bool archive_db_init()
|
||||
}
|
||||
else
|
||||
{
|
||||
zoffset_size= 2 << ((zlibCompileFlags() >> 6) & 3);
|
||||
switch (sizeof(z_off_t)) {
|
||||
case 2:
|
||||
max_zfile_size= INT_MAX16;
|
||||
break;
|
||||
case 8:
|
||||
max_zfile_size= LONGLONG_MAX;
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
max_zfile_size= INT_MAX32;
|
||||
}
|
||||
archive_inited= TRUE;
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
@ -240,7 +254,7 @@ ha_archive::ha_archive(TABLE *table_arg)
|
||||
buffer.set((char *)byte_buffer, IO_SIZE, system_charset_info);
|
||||
|
||||
/* The size of the offset value we will use for position() */
|
||||
ref_length = 2 << ((zlibCompileFlags() >> 6) & 3);
|
||||
ref_length = zoffset_size;
|
||||
DBUG_ASSERT(ref_length <= sizeof(z_off_t));
|
||||
}
|
||||
|
||||
@ -480,7 +494,8 @@ int ha_archive::init_archive_writer()
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
share->archive_write_open= TRUE;
|
||||
|
||||
info(HA_STATUS_TIME);
|
||||
share->approx_file_size= data_file_length;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
@ -651,10 +666,21 @@ error:
|
||||
*/
|
||||
int ha_archive::real_write_row(byte *buf, gzFile writer)
|
||||
{
|
||||
z_off_t written;
|
||||
z_off_t written, total_row_length;
|
||||
uint *ptr, *end;
|
||||
DBUG_ENTER("ha_archive::real_write_row");
|
||||
|
||||
total_row_length= table->s->reclength;
|
||||
for (ptr= table->s->blob_field, end= ptr + table->s->blob_fields;
|
||||
ptr != end; ptr++)
|
||||
total_row_length+= ((Field_blob*) table->field[*ptr])->get_length();
|
||||
if (share->approx_file_size > max_zfile_size - total_row_length)
|
||||
{
|
||||
info(HA_STATUS_TIME);
|
||||
share->approx_file_size= data_file_length;
|
||||
if (share->approx_file_size > max_zfile_size - total_row_length)
|
||||
DBUG_RETURN(HA_ERR_RECORD_FILE_FULL);
|
||||
}
|
||||
share->approx_file_size+= total_row_length;
|
||||
written= gzwrite(writer, buf, table->s->reclength);
|
||||
DBUG_PRINT("ha_archive::real_write_row", ("Wrote %d bytes expected %d", written, table->s->reclength));
|
||||
if (!delayed_insert || !bulk_insert)
|
||||
|
@ -38,6 +38,7 @@ typedef struct st_archive_share {
|
||||
bool dirty; /* Flag for if a flush should occur */
|
||||
bool crashed; /* Meta file is crashed */
|
||||
ha_rows rows_recorded; /* Number of rows in tables */
|
||||
z_off_t approx_file_size; /* Approximate archive data file size */
|
||||
} ARCHIVE_SHARE;
|
||||
|
||||
/*
|
||||
|
@ -3345,6 +3345,34 @@ longlong Item_func_release_lock::val_int()
|
||||
}
|
||||
|
||||
|
||||
bool Item_func_last_insert_id::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
|
||||
if (Item_int_func::fix_fields(thd, ref))
|
||||
return TRUE;
|
||||
|
||||
if (arg_count == 0)
|
||||
{
|
||||
if (!thd->last_insert_id_used)
|
||||
{
|
||||
/*
|
||||
As this statement calls LAST_INSERT_ID(), set
|
||||
THD::last_insert_id_used and remember first generated insert
|
||||
id of the previous statement in THD::current_insert_id.
|
||||
*/
|
||||
thd->last_insert_id_used= TRUE;
|
||||
thd->current_insert_id= thd->last_insert_id;
|
||||
}
|
||||
null_value= FALSE;
|
||||
}
|
||||
|
||||
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
longlong Item_func_last_insert_id::val_int()
|
||||
{
|
||||
THD *thd= current_thd;
|
||||
@ -3354,12 +3382,13 @@ longlong Item_func_last_insert_id::val_int()
|
||||
longlong value= args[0]->val_int();
|
||||
thd->insert_id(value);
|
||||
null_value= args[0]->null_value;
|
||||
return value; // Avoid side effect of insert_id()
|
||||
return value;
|
||||
}
|
||||
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
||||
return thd->last_insert_id_used ? thd->current_insert_id : thd->insert_id();
|
||||
|
||||
return thd->current_insert_id;
|
||||
}
|
||||
|
||||
|
||||
/* This function is just used to test speed of different functions */
|
||||
|
||||
longlong Item_func_benchmark::val_int()
|
||||
|
@ -891,6 +891,7 @@ public:
|
||||
if (arg_count)
|
||||
max_length= args[0]->max_length;
|
||||
}
|
||||
bool fix_fields(THD *thd, Item **ref);
|
||||
};
|
||||
|
||||
|
||||
|
@ -3365,7 +3365,6 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli)
|
||||
{
|
||||
switch (type) {
|
||||
case LAST_INSERT_ID_EVENT:
|
||||
thd->last_insert_id_used = 1;
|
||||
thd->last_insert_id = val;
|
||||
break;
|
||||
case INSERT_ID_EVENT:
|
||||
|
@ -2571,8 +2571,17 @@ bool sys_var_last_insert_id::update(THD *thd, set_var *var)
|
||||
byte *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type,
|
||||
LEX_STRING *base)
|
||||
{
|
||||
thd->sys_var_tmp.long_value= (long) thd->insert_id();
|
||||
return (byte*) &thd->last_insert_id;
|
||||
if (!thd->last_insert_id_used)
|
||||
{
|
||||
/*
|
||||
As this statement reads @@LAST_INSERT_ID, set
|
||||
THD::last_insert_id_used and remember first generated insert id
|
||||
of the previous statement in THD::current_insert_id.
|
||||
*/
|
||||
thd->last_insert_id_used= TRUE;
|
||||
thd->current_insert_id= thd->last_insert_id;
|
||||
}
|
||||
return (byte*) &thd->current_insert_id;
|
||||
}
|
||||
|
||||
|
||||
|
@ -3813,7 +3813,7 @@ ER_WRONG_MRG_TABLE
|
||||
cze "V-B¹echny tabulky v MERGE tabulce nejsou definovány stejnì"
|
||||
dan "Tabellerne i MERGE er ikke defineret ens"
|
||||
nla "Niet alle tabellen in de MERGE tabel hebben identieke gedefinities"
|
||||
eng "All tables in the MERGE table are not identically defined"
|
||||
eng "Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists"
|
||||
est "Kõik tabelid MERGE tabeli määratluses ei ole identsed"
|
||||
fre "Toutes les tables de la table de type MERGE n'ont pas la même définition"
|
||||
ger "Nicht alle Tabellen in der MERGE-Tabelle sind gleich definiert"
|
||||
|
@ -553,10 +553,24 @@ bool THD::store_globals()
|
||||
}
|
||||
|
||||
|
||||
/* Cleanup after a query */
|
||||
/*
|
||||
Cleanup after query.
|
||||
|
||||
SYNOPSIS
|
||||
THD::cleanup_after_query()
|
||||
|
||||
DESCRIPTION
|
||||
This function is used to reset thread data to it's default state.
|
||||
|
||||
NOTE
|
||||
This function is not suitable for setting thread data to some
|
||||
non-default values, as there is only one replication thread, so
|
||||
different master threads may overwrite data of each other on
|
||||
slave.
|
||||
*/
|
||||
void THD::cleanup_after_query()
|
||||
{
|
||||
last_insert_id_used= FALSE;
|
||||
if (clear_next_insert_id)
|
||||
{
|
||||
clear_next_insert_id= 0;
|
||||
|
@ -1252,17 +1252,29 @@ public:
|
||||
ulonglong next_insert_id;
|
||||
/* Remember last next_insert_id to reset it if something went wrong */
|
||||
ulonglong prev_insert_id;
|
||||
|
||||
/*
|
||||
The insert_id used for the last statement or set by SET LAST_INSERT_ID=#
|
||||
or SELECT LAST_INSERT_ID(#). Used for binary log and returned by
|
||||
LAST_INSERT_ID()
|
||||
At the beginning of the statement last_insert_id holds the first
|
||||
generated value of the previous statement. During statement
|
||||
execution it is updated to the value just generated, but then
|
||||
restored to the value that was generated first, so for the next
|
||||
statement it will again be "the first generated value of the
|
||||
previous statement".
|
||||
|
||||
It may also be set with "LAST_INSERT_ID(expr)" or
|
||||
"@@LAST_INSERT_ID= expr", but the effect of such setting will be
|
||||
seen only in the next statement.
|
||||
*/
|
||||
ulonglong last_insert_id;
|
||||
|
||||
/*
|
||||
Set to the first value that LAST_INSERT_ID() returned for the last
|
||||
statement. When this is set, last_insert_id_used is set to true.
|
||||
current_insert_id remembers the first generated value of the
|
||||
previous statement, and does not change during statement
|
||||
execution. Its value returned from LAST_INSERT_ID() and
|
||||
@@LAST_INSERT_ID.
|
||||
*/
|
||||
ulonglong current_insert_id;
|
||||
|
||||
ulonglong limit_found_rows;
|
||||
ulonglong options; /* Bitmap of states */
|
||||
longlong row_count_func; /* For the ROW_COUNT() function */
|
||||
@ -1325,7 +1337,22 @@ public:
|
||||
bool last_cuted_field;
|
||||
bool no_errors, password, is_fatal_error;
|
||||
bool query_start_used, rand_used, time_zone_used;
|
||||
bool last_insert_id_used,insert_id_used, clear_next_insert_id;
|
||||
|
||||
/*
|
||||
last_insert_id_used is set when current statement calls
|
||||
LAST_INSERT_ID() or reads @@LAST_INSERT_ID, so that binary log
|
||||
LAST_INSERT_ID_EVENT be generated.
|
||||
*/
|
||||
bool last_insert_id_used;
|
||||
|
||||
/*
|
||||
insert_id_used is set when current statement updates
|
||||
THD::last_insert_id, so that binary log INSERT_ID_EVENT be
|
||||
generated.
|
||||
*/
|
||||
bool insert_id_used;
|
||||
|
||||
bool clear_next_insert_id;
|
||||
/* for IS NULL => = last_insert_id() fix in remove_eq_conds() */
|
||||
bool substitute_null_with_insert_id;
|
||||
bool in_lock_tables;
|
||||
@ -1461,15 +1488,6 @@ public:
|
||||
insert_id_used=1;
|
||||
substitute_null_with_insert_id= TRUE;
|
||||
}
|
||||
inline ulonglong insert_id(void)
|
||||
{
|
||||
if (!last_insert_id_used)
|
||||
{
|
||||
last_insert_id_used=1;
|
||||
current_insert_id=last_insert_id;
|
||||
}
|
||||
return last_insert_id;
|
||||
}
|
||||
inline ulonglong found_rows(void)
|
||||
{
|
||||
return limit_found_rows;
|
||||
|
@ -590,10 +590,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
#endif
|
||||
error=write_record(thd, table ,&info);
|
||||
/*
|
||||
If auto_increment values are used, save the first one
|
||||
for LAST_INSERT_ID() and for the update log.
|
||||
We can't use insert_id() as we don't want to touch the
|
||||
last_insert_id_used flag.
|
||||
If auto_increment values are used, save the first one for
|
||||
LAST_INSERT_ID() and for the update log.
|
||||
*/
|
||||
if (! id && thd->insert_id_used)
|
||||
{ // Get auto increment value
|
||||
@ -1303,6 +1301,9 @@ public:
|
||||
time_t start_time;
|
||||
bool query_start_used,last_insert_id_used,insert_id_used, ignore, log_query;
|
||||
ulonglong last_insert_id;
|
||||
ulonglong next_insert_id;
|
||||
ulong auto_increment_increment;
|
||||
ulong auto_increment_offset;
|
||||
timestamp_auto_set_type timestamp_field_type;
|
||||
uint query_length;
|
||||
|
||||
@ -1684,6 +1685,22 @@ static int write_delayed(THD *thd,TABLE *table,enum_duplicates duplic, bool igno
|
||||
row->last_insert_id= thd->last_insert_id;
|
||||
row->timestamp_field_type= table->timestamp_field_type;
|
||||
|
||||
/* The session variable settings can always be copied. */
|
||||
row->auto_increment_increment= thd->variables.auto_increment_increment;
|
||||
row->auto_increment_offset= thd->variables.auto_increment_offset;
|
||||
/*
|
||||
Next insert id must be set for the first value in a multi-row insert
|
||||
only. So clear it after the first use. Assume a multi-row insert.
|
||||
Since the user thread doesn't really execute the insert,
|
||||
thd->next_insert_id is left untouched between the rows. If we copy
|
||||
the same insert id to every row of the multi-row insert, the delayed
|
||||
insert thread would copy this before inserting every row. Thus it
|
||||
tries to insert all rows with the same insert id. This fails on the
|
||||
unique constraint. So just the first row would be really inserted.
|
||||
*/
|
||||
row->next_insert_id= thd->next_insert_id;
|
||||
thd->next_insert_id= 0;
|
||||
|
||||
di->rows.push_back(row);
|
||||
di->stacked_inserts++;
|
||||
di->status=1;
|
||||
@ -2055,6 +2072,14 @@ bool delayed_insert::handle_inserts(void)
|
||||
thd.insert_id_used=row->insert_id_used;
|
||||
table->timestamp_field_type= row->timestamp_field_type;
|
||||
|
||||
/* The session variable settings can always be copied. */
|
||||
thd.variables.auto_increment_increment= row->auto_increment_increment;
|
||||
thd.variables.auto_increment_offset= row->auto_increment_offset;
|
||||
/* Next insert id must be used only if non-zero. */
|
||||
if (row->next_insert_id)
|
||||
thd.next_insert_id= row->next_insert_id;
|
||||
DBUG_PRINT("loop", ("next_insert_id: %lu", (ulong) thd.next_insert_id));
|
||||
|
||||
info.ignore= row->ignore;
|
||||
info.handle_duplicates= row->dup;
|
||||
if (info.ignore ||
|
||||
@ -2076,6 +2101,20 @@ bool delayed_insert::handle_inserts(void)
|
||||
info.error_count++; // Ignore errors
|
||||
thread_safe_increment(delayed_insert_errors,&LOCK_delayed_status);
|
||||
row->log_query = 0;
|
||||
/*
|
||||
We must reset next_insert_id. Otherwise all following rows may
|
||||
become duplicates. If write_record() failed on a duplicate and
|
||||
next_insert_id would be left unchanged, the next rows would also
|
||||
be tried with the same insert id and would fail. Since the end
|
||||
of a multi-row statement is unknown here, all following rows in
|
||||
the queue would be dropped, regardless which thread added them.
|
||||
After the queue is used up, next_insert_id is cleared and the
|
||||
next run will succeed. This could even happen if these come from
|
||||
the same multi-row statement as the current queue contents. That
|
||||
way it would look somewhat random which rows are rejected after
|
||||
a duplicate.
|
||||
*/
|
||||
thd.next_insert_id= 0;
|
||||
}
|
||||
if (using_ignore)
|
||||
{
|
||||
@ -2121,6 +2160,7 @@ bool delayed_insert::handle_inserts(void)
|
||||
/* This should never happen */
|
||||
table->file->print_error(error,MYF(0));
|
||||
sql_print_error("%s",thd.net.last_error);
|
||||
DBUG_PRINT("error", ("HA_EXTRA_NO_CACHE failed in loop"));
|
||||
goto err;
|
||||
}
|
||||
query_cache_invalidate3(&thd, table, 1);
|
||||
@ -2146,6 +2186,7 @@ bool delayed_insert::handle_inserts(void)
|
||||
{ // This shouldn't happen
|
||||
table->file->print_error(error,MYF(0));
|
||||
sql_print_error("%s",thd.net.last_error);
|
||||
DBUG_PRINT("error", ("HA_EXTRA_NO_CACHE failed after loop"));
|
||||
goto err;
|
||||
}
|
||||
query_cache_invalidate3(&thd, table, 1);
|
||||
@ -2153,13 +2194,16 @@ bool delayed_insert::handle_inserts(void)
|
||||
DBUG_RETURN(0);
|
||||
|
||||
err:
|
||||
DBUG_EXECUTE("error", max_rows= 0;);
|
||||
/* Remove all not used rows */
|
||||
while ((row=rows.get()))
|
||||
{
|
||||
delete row;
|
||||
thread_safe_increment(delayed_insert_errors,&LOCK_delayed_status);
|
||||
stacked_inserts--;
|
||||
DBUG_EXECUTE("error", max_rows++;);
|
||||
}
|
||||
DBUG_PRINT("error", ("dropped %lu rows after an error", max_rows));
|
||||
thread_safe_increment(delayed_insert_errors, &LOCK_delayed_status);
|
||||
pthread_mutex_lock(&mutex);
|
||||
DBUG_RETURN(1);
|
||||
@ -2447,7 +2491,7 @@ bool select_insert::send_data(List<Item> &values)
|
||||
*/
|
||||
table->next_number_field->reset();
|
||||
if (!last_insert_id && thd->insert_id_used)
|
||||
last_insert_id= thd->insert_id();
|
||||
last_insert_id= thd->last_insert_id;
|
||||
}
|
||||
}
|
||||
DBUG_RETURN(error);
|
||||
|
@ -616,10 +616,8 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
thd->no_trans_update= no_trans_update;
|
||||
|
||||
/*
|
||||
If auto_increment values are used, save the first one
|
||||
for LAST_INSERT_ID() and for the binary/update log.
|
||||
We can't use insert_id() as we don't want to touch the
|
||||
last_insert_id_used flag.
|
||||
If auto_increment values are used, save the first one for
|
||||
LAST_INSERT_ID() and for the binary/update log.
|
||||
*/
|
||||
if (!id && thd->insert_id_used)
|
||||
id= thd->last_insert_id;
|
||||
@ -784,10 +782,8 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
if (write_record(thd, table, &info))
|
||||
DBUG_RETURN(1);
|
||||
/*
|
||||
If auto_increment values are used, save the first one
|
||||
for LAST_INSERT_ID() and for the binary/update log.
|
||||
We can't use insert_id() as we don't want to touch the
|
||||
last_insert_id_used flag.
|
||||
If auto_increment values are used, save the first one for
|
||||
LAST_INSERT_ID() and for the binary/update log.
|
||||
*/
|
||||
if (!id && thd->insert_id_used)
|
||||
id= thd->last_insert_id;
|
||||
|
@ -2421,6 +2421,20 @@ mysql_execute_command(THD *thd)
|
||||
DBUG_ENTER("mysql_execute_command");
|
||||
thd->net.no_send_error= 0;
|
||||
|
||||
/*
|
||||
Remember first generated insert id value of the previous
|
||||
statement. We remember it here at the beginning of the statement,
|
||||
and also in Item_func_last_insert_id::fix_fields() and
|
||||
sys_var_last_insert_id::value_ptr(). Last two places are required
|
||||
because LAST_INSERT_ID() and @@LAST_INSERT_ID may also be used in
|
||||
expression that is not executed with mysql_execute_command().
|
||||
|
||||
And we remember it here because some statements read
|
||||
@@LAST_INSERT_ID indirectly, like "SELECT * FROM t1 WHERE id IS
|
||||
NULL", that may replace "id IS NULL" with "id = <LAST_INSERT_ID>".
|
||||
*/
|
||||
thd->current_insert_id= thd->last_insert_id;
|
||||
|
||||
/*
|
||||
In many cases first table of main SELECT_LEX have special meaning =>
|
||||
check that it is first table in global list and relink it first in
|
||||
@ -5636,7 +5650,7 @@ void mysql_reset_thd_for_next_command(THD *thd)
|
||||
DBUG_ENTER("mysql_reset_thd_for_next_command");
|
||||
thd->free_list= 0;
|
||||
thd->select_number= 1;
|
||||
thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
|
||||
thd->query_start_used= thd->insert_id_used=0;
|
||||
thd->is_fatal_error= thd->time_zone_used= 0;
|
||||
thd->server_status&= ~ (SERVER_MORE_RESULTS_EXISTS |
|
||||
SERVER_QUERY_NO_INDEX_USED |
|
||||
|
@ -8142,7 +8142,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
||||
Field *field=((Item_field*) args[0])->field;
|
||||
if (field->flags & AUTO_INCREMENT_FLAG && !field->table->maybe_null &&
|
||||
(thd->options & OPTION_AUTO_IS_NULL) &&
|
||||
thd->insert_id() && thd->substitute_null_with_insert_id)
|
||||
thd->current_insert_id && thd->substitute_null_with_insert_id)
|
||||
{
|
||||
#ifdef HAVE_QUERY_CACHE
|
||||
query_cache_abort(&thd->net);
|
||||
@ -8150,9 +8150,16 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
||||
COND *new_cond;
|
||||
if ((new_cond= new Item_func_eq(args[0],
|
||||
new Item_int("last_insert_id()",
|
||||
thd->insert_id(),
|
||||
thd->current_insert_id,
|
||||
21))))
|
||||
{
|
||||
/*
|
||||
Set THD::last_insert_id_used manually, as this statement
|
||||
uses LAST_INSERT_ID() in a sense, and should issue
|
||||
LAST_INSERT_ID_EVENT.
|
||||
*/
|
||||
thd->last_insert_id_used= TRUE;
|
||||
|
||||
cond=new_cond;
|
||||
/*
|
||||
Item_func_eq can't be fixed after creation so we do not check
|
||||
|
@ -568,7 +568,7 @@ int mysql_update(THD *thd,
|
||||
thd->row_count_func=
|
||||
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
|
||||
send_ok(thd, (ulong) thd->row_count_func,
|
||||
thd->insert_id_used ? thd->insert_id() : 0L,buff);
|
||||
thd->insert_id_used ? thd->last_insert_id : 0L,buff);
|
||||
DBUG_PRINT("info",("%d records updated",updated));
|
||||
}
|
||||
thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */
|
||||
@ -1567,6 +1567,6 @@ bool multi_update::send_eof()
|
||||
thd->row_count_func=
|
||||
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
|
||||
::send_ok(thd, (ulong) thd->row_count_func,
|
||||
thd->insert_id_used ? thd->insert_id() : 0L,buff);
|
||||
thd->insert_id_used ? thd->last_insert_id : 0L,buff);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -15237,6 +15237,43 @@ static void test_bug21206()
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
/*
|
||||
Bug#21726: Incorrect result with multiple invocations of
|
||||
LAST_INSERT_ID
|
||||
|
||||
Test that client gets updated value of insert_id on UPDATE that uses
|
||||
LAST_INSERT_ID(expr).
|
||||
*/
|
||||
static void test_bug21726()
|
||||
{
|
||||
const char *create_table[]=
|
||||
{
|
||||
"DROP TABLE IF EXISTS t1",
|
||||
"CREATE TABLE t1 (i INT)",
|
||||
"INSERT INTO t1 VALUES (1)",
|
||||
};
|
||||
const char *update_query= "UPDATE t1 SET i= LAST_INSERT_ID(i + 1)";
|
||||
int rc;
|
||||
my_ulonglong insert_id;
|
||||
|
||||
DBUG_ENTER("test_bug21726");
|
||||
myheader("test_bug21726");
|
||||
|
||||
fill_tables(create_table, sizeof(create_table) / sizeof(*create_table));
|
||||
|
||||
rc= mysql_query(mysql, update_query);
|
||||
myquery(rc);
|
||||
insert_id= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(insert_id == 2);
|
||||
|
||||
rc= mysql_query(mysql, update_query);
|
||||
myquery(rc);
|
||||
insert_id= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(insert_id == 3);
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Read and parse arguments and MySQL options from my.cnf
|
||||
@ -15511,7 +15548,8 @@ static struct my_tests_st my_tests[]= {
|
||||
{ "test_bug17667", test_bug17667 },
|
||||
{ "test_bug19671", test_bug19671 },
|
||||
{ "test_bug15752", test_bug15752 },
|
||||
{ "test_bug21206", test_bug21206},
|
||||
{ "test_bug21206", test_bug21206 },
|
||||
{ "test_bug21726", test_bug21726 },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user