summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.in4
-rw-r--r--myisam/mi_check.c9
-rw-r--r--myisam/mi_delete.c2
-rw-r--r--myisam/myisam_ftdump.c3
-rw-r--r--myisammrg/myrg_open.c10
-rw-r--r--myisammrg/myrg_queue.c2
-rw-r--r--mysql-test/r/ctype_ucs.result21
-rw-r--r--mysql-test/r/delayed.result174
-rw-r--r--mysql-test/r/func_gconcat.result9
-rw-r--r--mysql-test/r/func_group.result4
-rw-r--r--mysql-test/r/group_by.result9
-rw-r--r--mysql-test/r/merge.result19
-rw-r--r--mysql-test/r/ps.result47
-rw-r--r--mysql-test/r/rpl_insert_id.result129
-rw-r--r--mysql-test/r/subselect.result101
-rw-r--r--mysql-test/r/view.result41
-rw-r--r--mysql-test/t/ctype_ucs.test21
-rw-r--r--mysql-test/t/delayed.test148
-rw-r--r--mysql-test/t/func_gconcat.test15
-rw-r--r--mysql-test/t/group_by.test12
-rw-r--r--mysql-test/t/merge.test25
-rw-r--r--mysql-test/t/ps.test52
-rw-r--r--mysql-test/t/rpl_insert_id.test112
-rw-r--r--mysql-test/t/subselect.test72
-rw-r--r--mysql-test/t/view.test49
-rw-r--r--mysys/my_chsize.c4
-rw-r--r--mysys/queues.c48
-rw-r--r--sql/field.h2
-rw-r--r--sql/filesort.cc1
-rw-r--r--sql/ha_archive.cc34
-rw-r--r--sql/ha_archive.h1
-rw-r--r--sql/item.cc1
-rw-r--r--sql/item_func.cc35
-rw-r--r--sql/item_func.h1
-rw-r--r--sql/item_sum.cc22
-rw-r--r--sql/log_event.cc1
-rw-r--r--sql/mysql_priv.h3
-rw-r--r--sql/set_var.cc13
-rw-r--r--sql/share/errmsg.txt5
-rw-r--r--sql/sql_base.cc5
-rw-r--r--sql/sql_class.cc16
-rw-r--r--sql/sql_class.h48
-rw-r--r--sql/sql_insert.cc58
-rw-r--r--sql/sql_lex.cc3
-rw-r--r--sql/sql_load.cc12
-rw-r--r--sql/sql_parse.cc16
-rw-r--r--sql/sql_select.cc13
-rw-r--r--sql/sql_update.cc4
-rw-r--r--sql/sql_view.cc2
-rw-r--r--sql/sql_yacc.yy8
-rw-r--r--sql/unireg.cc39
-rw-r--r--tests/mysql_client_test.c40
52 files changed, 1368 insertions, 157 deletions
diff --git a/configure.in b/configure.in
index 7bc4fe77675..55da1dfb241 100644
--- a/configure.in
+++ b/configure.in
@@ -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 ?
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index a3195ebce7f..5a81d221d2a 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -1370,7 +1370,8 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
param->temp_filename);
goto err;
}
- if (filecopy(param,new_file,info->dfile,0L,new_header_length,
+ if (new_header_length &&
+ filecopy(param,new_file,info->dfile,0L,new_header_length,
"datafile-header"))
goto err;
info->s->state.dellink= HA_OFFSET_ERROR;
@@ -2072,7 +2073,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
param->temp_filename);
goto err;
}
- if (filecopy(param, new_file,info->dfile,0L,new_header_length,
+ if (new_header_length &&
+ filecopy(param, new_file,info->dfile,0L,new_header_length,
"datafile-header"))
goto err;
if (param->testflag & T_UNPACK)
@@ -2440,7 +2442,8 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
param->temp_filename);
goto err;
}
- if (filecopy(param, new_file,info->dfile,0L,new_header_length,
+ if (new_header_length &&
+ filecopy(param, new_file,info->dfile,0L,new_header_length,
"datafile-header"))
goto err;
if (param->testflag & T_UNPACK)
diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c
index 2bc99d65dd2..85cc60bdd9d 100644
--- a/myisam/mi_delete.c
+++ b/myisam/mi_delete.c
@@ -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,
diff --git a/myisam/myisam_ftdump.c b/myisam/myisam_ftdump.c
index 809d7bcca89..2be95d11714 100644
--- a/myisam/myisam_ftdump.c
+++ b/myisam/myisam_ftdump.c
@@ -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++;
diff --git a/myisammrg/myrg_open.c b/myisammrg/myrg_open.c
index f9cdc2bb205..af10f0da90b 100644
--- a/myisammrg/myrg_open.c
+++ b/myisammrg/myrg_open.c
@@ -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 */
diff --git a/myisammrg/myrg_queue.c b/myisammrg/myrg_queue.c
index 2e600a526c0..74fdddc7748 100644
--- a/myisammrg/myrg_queue.c
+++ b/myisammrg/myrg_queue.c
@@ -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;
}
diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
index 3b6bfa6d776..76fcbbeb9f8 100644
--- a/mysql-test/r/ctype_ucs.result
+++ b/mysql-test/r/ctype_ucs.result
@@ -755,6 +755,27 @@ select export_set(5, name, upper(name), ",", 5) from bug20536;
export_set(5, name, upper(name), ",", 5)
test1,TEST1,test1,TEST1,TEST1
'test\_2','TEST\_2','test\_2','TEST\_2','TEST\_2'
+CREATE TABLE t1 (
+status enum('active','passive') collate latin1_general_ci
+NOT NULL default 'passive'
+);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `status` enum('active','passive') character set latin1 collate latin1_general_ci NOT NULL default 'passive'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+ALTER TABLE t1 ADD a int NOT NULL AFTER status;
+CREATE TABLE t2 (
+status enum('active','passive') collate ucs2_turkish_ci
+NOT NULL default 'passive'
+);
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `status` enum('active','passive') character set ucs2 collate ucs2_turkish_ci NOT NULL default 'passive'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+ALTER TABLE t2 ADD a int NOT NULL AFTER status;
+DROP TABLE t1,t2;
select password(name) from bug20536;
password(name)
????????????????????
diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result
index a336f3b4108..6295fceec2b 100644
--- a/mysql-test/r/delayed.result
+++ b/mysql-test/r/delayed.result
@@ -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;
diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result
index 6617ccc671e..93925670d01 100644
--- a/mysql-test/r/func_gconcat.result
+++ b/mysql-test/r/func_gconcat.result
@@ -654,3 +654,12 @@ CHAR_LENGTH( GROUP_CONCAT(b) )
240001
SET GROUP_CONCAT_MAX_LEN = 1024;
DROP TABLE t1;
+CREATE TABLE t1 (a int, b int);
+INSERT INTO t1 VALUES (2,1), (1,2), (2,2), (1,3);
+SELECT GROUP_CONCAT(a), x
+FROM (SELECT a, GROUP_CONCAT(b) x FROM t1 GROUP BY a) AS s
+GROUP BY x;
+GROUP_CONCAT(a) x
+2 1,2
+1 2,3
+DROP TABLE t1;
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result
index 98eb9e9e2b3..c6117053a60 100644
--- a/mysql-test/r/func_group.result
+++ b/mysql-test/r/func_group.result
@@ -860,8 +860,8 @@ CREATE TABLE t1 (a INT, b INT);
INSERT INTO t1 VALUES (1,1),(1,2),(2,3);
SELECT (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a;
(SELECT COUNT(DISTINCT t1.b))
-0
2
+1
SELECT (SELECT COUNT(DISTINCT 12)) FROM t1 GROUP BY t1.a;
(SELECT COUNT(DISTINCT 12))
1
@@ -1013,7 +1013,7 @@ SELECT SQL_NO_CACHE
WHERE ttt.a = ccc.b AND ttt.a = t.a GROUP BY ttt.a) AS minid
FROM t1 t, t2 c WHERE t.a = c.b;
minid
-NULL
+1
DROP TABLE t1,t2;
create table t1 select variance(0);
show create table t1;
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index ef057e04d1a..5eb2e5744c1 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -821,12 +821,3 @@ a b real_b
68 France France
DROP VIEW v1;
DROP TABLE t1,t2;
-CREATE TABLE t1 (a INT, b INT, KEY(a));
-INSERT INTO t1 VALUES (1, 1), (2, 2), (3,3), (4,4);
-EXPLAIN SELECT a, SUM(b) FROM t1 GROUP BY a LIMIT 2;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL a 5 NULL 4
-EXPLAIN SELECT a, SUM(b) FROM t1 IGNORE INDEX (a) GROUP BY a LIMIT 2;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using temporary; Using filesort
-DROP TABLE t1;
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index b8fdd24be74..d7eb7da939d 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -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);
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index 059a8fe6aa2..048c3ae46d3 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -909,6 +909,53 @@ create temporary table if not exists t1 (a1 int);
execute stmt;
drop temporary table t1;
deallocate prepare stmt;
+CREATE TABLE t1(
+ID int(10) unsigned NOT NULL auto_increment,
+Member_ID varchar(15) NOT NULL default '',
+Action varchar(12) NOT NULL,
+Action_Date datetime NOT NULL,
+Track varchar(15) default NULL,
+User varchar(12) default NULL,
+Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update
+CURRENT_TIMESTAMP,
+PRIMARY KEY (ID),
+KEY Action (Action),
+KEY Action_Date (Action_Date)
+);
+INSERT INTO t1(Member_ID, Action, Action_Date, Track) VALUES
+('111111', 'Disenrolled', '2006-03-01', 'CAD' ),
+('111111', 'Enrolled', '2006-03-01', 'CAD' ),
+('111111', 'Disenrolled', '2006-07-03', 'CAD' ),
+('222222', 'Enrolled', '2006-03-07', 'CAD' ),
+('222222', 'Enrolled', '2006-03-07', 'CHF' ),
+('222222', 'Disenrolled', '2006-08-02', 'CHF' ),
+('333333', 'Enrolled', '2006-03-01', 'CAD' ),
+('333333', 'Disenrolled', '2006-03-01', 'CAD' ),
+('444444', 'Enrolled', '2006-03-01', 'CAD' ),
+('555555', 'Disenrolled', '2006-03-01', 'CAD' ),
+('555555', 'Enrolled', '2006-07-21', 'CAD' ),
+('555555', 'Disenrolled', '2006-03-01', 'CHF' ),
+('666666', 'Enrolled', '2006-02-09', 'CAD' ),
+('666666', 'Enrolled', '2006-05-12', 'CHF' ),
+('666666', 'Disenrolled', '2006-06-01', 'CAD' );
+PREPARE STMT FROM
+"SELECT GROUP_CONCAT(Track SEPARATOR ', ') FROM t1
+ WHERE Member_ID=? AND Action='Enrolled' AND
+ (Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t1
+ WHERE Member_ID=?
+ GROUP BY Track
+ HAVING Track>='CAD' AND
+ MAX(Action_Date)>'2006-03-01')";
+SET @id='111111';
+EXECUTE STMT USING @id,@id;
+GROUP_CONCAT(Track SEPARATOR ', ')
+NULL
+SET @id='222222';
+EXECUTE STMT USING @id,@id;
+GROUP_CONCAT(Track SEPARATOR ', ')
+CAD
+DEALLOCATE PREPARE STMT;
+DROP TABLE t1;
End of 4.1 tests
create table t1 (a varchar(20));
insert into t1 values ('foo');
diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result
index e425cce9508..d0360c8b9a3 100644
--- a/mysql-test/r/rpl_insert_id.result
+++ b/mysql-test/r/rpl_insert_id.result
@@ -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
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index c6a31856a24..6bf85979002 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -1160,7 +1160,7 @@ Code2 char(2) NOT NULL default '',
PRIMARY KEY (Code)
) ENGINE=MyISAM;
INSERT INTO t2 VALUES ('AUS','Australia','Oceania','Australia and New Zealand',7741220.00,1901,18886000,79.8,351182.00,392911.00,'Australia','Constitutional Monarchy, Federation','Elisabeth II',135,'AU');
-INSERT INTO t2 VALUES ('AZE','Azerbaijan','Asia','Middle East',86600.00,1991,7734000,62.9,4127.00,4100.00,'Azärbaycan','Federal Republic','Heydär Äliyev',144,'AZ');
+INSERT INTO t2 VALUES ('AZE','Azerbaijan','Asia','Middle East',86600.00,1991,7734000,62.9,4127.00,4100.00,'Azärbaycan','Federal Republic','Heydär Äliyev',144,'AZ');
select t2.Continent, t1.Name, t1.Population from t2 LEFT JOIN t1 ON t2.Code = t1.t2 where t1.Population IN (select max(t1.Population) AS Population from t1, t2 where t1.t2 = t2.Code group by Continent);
Continent Name Population
Oceania Sydney 3276207
@@ -2512,7 +2512,7 @@ Code2 char(2) NOT NULL default ''
) ENGINE=MyISAM;
INSERT INTO t1 VALUES ('XXX','Xxxxx','Oceania','Xxxxxx',26.00,0,0,0,0,0,'Xxxxx','Xxxxx','Xxxxx',NULL,'XX');
INSERT INTO t1 VALUES ('ASM','American Samoa','Oceania','Polynesia',199.00,0,68000,75.1,334.00,NULL,'Amerika Samoa','US Territory','George W. Bush',54,'AS');
-INSERT INTO t1 VALUES ('ATF','French Southern territories','Antarctica','Antarctica',7780.00,0,0,NULL,0.00,NULL,'Terres australes françaises','Nonmetropolitan Territory of France','Jacques Chirac',NULL,'TF');
+INSERT INTO t1 VALUES ('ATF','French Southern territories','Antarctica','Antarctica',7780.00,0,0,NULL,0.00,NULL,'Terres australes françaises','Nonmetropolitan Territory of France','Jacques Chirac',NULL,'TF');
INSERT INTO t1 VALUES ('UMI','United States Minor Outlying Islands','Oceania','Micronesia/Caribbean',16.00,0,0,NULL,0.00,NULL,'United States Minor Outlying Islands','Dependent Territory of the US','George W. Bush',NULL,'UM');
/*!40000 ALTER TABLE t1 ENABLE KEYS */;
SELECT DISTINCT Continent AS c FROM t1 WHERE Code <> SOME ( SELECT Code FROM t1 WHERE Continent = c AND Population < 200);
@@ -2966,6 +2966,42 @@ ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10;
a a b
10 1 359
drop table t1,t2;
+CREATE TABLE t1 (
+field1 int NOT NULL,
+field2 int NOT NULL,
+field3 int NOT NULL,
+PRIMARY KEY (field1,field2,field3)
+);
+CREATE TABLE t2 (
+fieldA int NOT NULL,
+fieldB int NOT NULL,
+PRIMARY KEY (fieldA,fieldB)
+);
+INSERT INTO t1 VALUES
+(1,1,1), (1,1,2), (1,2,1), (1,2,2), (1,2,3), (1,3,1);
+INSERT INTO t2 VALUES (1,1), (1,2), (1,3);
+SELECT field1, field2, COUNT(*)
+FROM t1 GROUP BY field1, field2;
+field1 field2 COUNT(*)
+1 1 2
+1 2 3
+1 3 1
+SELECT field1, field2
+FROM t1
+GROUP BY field1, field2
+HAVING COUNT(*) >= ALL (SELECT fieldB
+FROM t2 WHERE fieldA = field1);
+field1 field2
+1 2
+SELECT field1, field2
+FROM t1
+GROUP BY field1, field2
+HAVING COUNT(*) < ANY (SELECT fieldB
+FROM t2 WHERE fieldA = field1);
+field1 field2
+1 1
+1 3
+DROP TABLE t1, t2;
create table t1 (df decimal(5,1));
insert into t1 values(1.1);
insert into t1 values(2.2);
@@ -3422,3 +3458,64 @@ id select_type table type possible_keys key key_len ref rows Extra
4 UNION t12 system NULL NULL NULL NULL 0 const row not found
NULL UNION RESULT <union2,4> ALL NULL NULL NULL NULL NULL
DROP TABLE t1;
+CREATE TABLE t1 (a INT, b INT);
+CREATE TABLE t2 (a INT);
+INSERT INTO t2 values (1);
+INSERT INTO t1 VALUES (1,1),(1,2),(2,3),(3,4);
+SELECT (SELECT COUNT(DISTINCT t1.b) from t2) FROM t1 GROUP BY t1.a;
+(SELECT COUNT(DISTINCT t1.b) from t2)
+2
+1
+1
+SELECT (SELECT COUNT(DISTINCT t1.b) from t2 union select 1 from t2 where 12 < 3)
+FROM t1 GROUP BY t1.a;
+(SELECT COUNT(DISTINCT t1.b) from t2 union select 1 from t2 where 12 < 3)
+2
+1
+1
+SELECT COUNT(DISTINCT t1.b), (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a;
+COUNT(DISTINCT t1.b) (SELECT COUNT(DISTINCT t1.b))
+2 2
+1 1
+1 1
+SELECT COUNT(DISTINCT t1.b),
+(SELECT COUNT(DISTINCT t1.b) union select 1 from DUAL where 12 < 3)
+FROM t1 GROUP BY t1.a;
+COUNT(DISTINCT t1.b) (SELECT COUNT(DISTINCT t1.b) union select 1 from DUAL where 12 < 3)
+2 2
+1 1
+1 1
+SELECT (
+SELECT (
+SELECT COUNT(DISTINCT t1.b)
+)
+)
+FROM t1 GROUP BY t1.a;
+(
+SELECT (
+SELECT COUNT(DISTINCT t1.b)
+)
+)
+2
+1
+1
+SELECT (
+SELECT (
+SELECT (
+SELECT COUNT(DISTINCT t1.b)
+)
+)
+FROM t1 GROUP BY t1.a LIMIT 1)
+FROM t1 t2
+GROUP BY t2.a;
+(
+SELECT (
+SELECT (
+SELECT COUNT(DISTINCT t1.b)
+)
+)
+FROM t1 GROUP BY t1.a LIMIT 1)
+2
+2
+2
+DROP TABLE t1,t2;
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index 9c05aba168c..6364002993f 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -472,11 +472,11 @@ create view v3 (x,y,z) as select b, a, b from t1;
create view v4 (x,y,z) as select c+1, b, a from t1;
create algorithm=temptable view v5 (x,y,z) as select c, b, a from t1;
insert into v3 values (-60,4,30);
-ERROR HY000: The target table v3 of the INSERT is not updatable
+ERROR HY000: The target table v3 of the INSERT is not insertable-into
insert into v4 values (-60,4,30);
-ERROR HY000: The target table v4 of the INSERT is not updatable
+ERROR HY000: The target table v4 of the INSERT is not insertable-into
insert into v5 values (-60,4,30);
-ERROR HY000: The target table v5 of the INSERT is not updatable
+ERROR HY000: The target table v5 of the INSERT is not insertable-into
insert into v1 values (-60,4,30);
insert into v1 (z,y,x) values (50,6,-100);
insert into v2 values (5,40);
@@ -499,11 +499,11 @@ create view v3 (x,y,z) as select b, a, b from t1;
create view v4 (x,y,z) as select c+1, b, a from t1;
create algorithm=temptable view v5 (x,y,z) as select c, b, a from t1;
insert into v3 select c, b, a from t2;
-ERROR HY000: The target table v3 of the INSERT is not updatable
+ERROR HY000: The target table v3 of the INSERT is not insertable-into
insert into v4 select c, b, a from t2;
-ERROR HY000: The target table v4 of the INSERT is not updatable
+ERROR HY000: The target table v4 of the INSERT is not insertable-into
insert into v5 select c, b, a from t2;
-ERROR HY000: The target table v5 of the INSERT is not updatable
+ERROR HY000: The target table v5 of the INSERT is not insertable-into
insert into v1 select c, b, a from t2;
insert into v1 (z,y,x) select a+20,b+2,-100 from t2;
insert into v2 select b+1, a+10 from t2;
@@ -1352,14 +1352,14 @@ drop table t1;
create table t1 (s1 smallint);
create view v1 as select * from t1 where 20 < (select (s1) from t1);
insert into v1 values (30);
-ERROR HY000: The target table v1 of the INSERT is not updatable
+ERROR HY000: The target table v1 of the INSERT is not insertable-into
create view v2 as select * from t1;
create view v3 as select * from t1 where 20 < (select (s1) from v2);
insert into v3 values (30);
-ERROR HY000: The target table v3 of the INSERT is not updatable
+ERROR HY000: The target table v3 of the INSERT is not insertable-into
create view v4 as select * from v2 where 20 < (select (s1) from t1);
insert into v4 values (30);
-ERROR HY000: The target table v4 of the INSERT is not updatable
+ERROR HY000: The target table v4 of the INSERT is not insertable-into
drop view v4, v3, v2, v1;
drop table t1;
create table t1 (a int);
@@ -2911,7 +2911,7 @@ INSERT INTO v2 VALUES (0);
RETURN 0;
END |
SELECT f2();
-ERROR HY000: The target table v2 of the INSERT is not updatable
+ERROR HY000: The target table v2 of the INSERT is not insertable-into
DROP FUNCTION f1;
DROP FUNCTION f2;
DROP VIEW v1, v2;
@@ -2935,4 +2935,25 @@ id select_type table type possible_keys key key_len ref rows Extra
2 SUBQUERY t1 ALL NULL NULL NULL NULL 3
DROP VIEW v1;
DROP TABLE t1;
+create table t1 (s1 int);
+create view v1 as select s1 as a, s1 as b from t1;
+insert into v1 values (1,1);
+ERROR HY000: The target table v1 of the INSERT is not insertable-into
+update v1 set a = 5;
+drop view v1;
+drop table t1;
+CREATE TABLE t1(pk int PRIMARY KEY);
+CREATE TABLE t2(pk int PRIMARY KEY, fk int, ver int, org int);
+CREATE ALGORITHM=MERGE VIEW v1 AS
+SELECT t1.*
+FROM t1 JOIN t2
+ON t2.fk = t1.pk AND
+t2.ver = (SELECT MAX(t.ver) FROM t2 t WHERE t.org = t2.org);
+SHOW WARNINGS;
+Level Code Message
+SHOW CREATE VIEW v1;
+View Create View
+v1 CREATE ALGORITHM=MERGE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`pk` AS `pk` from (`t1` join `t2` on(((`t2`.`fk` = `t1`.`pk`) and (`t2`.`ver` = (select max(`t`.`ver`) AS `MAX(t.ver)` from `t2` `t` where (`t`.`org` = `t2`.`org`))))))
+DROP VIEW v1;
+DROP TABLE t1, t2;
End of 5.0 tests.
diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test
index 8116d39e3db..6c814368c88 100644
--- a/mysql-test/t/ctype_ucs.test
+++ b/mysql-test/t/ctype_ucs.test
@@ -484,6 +484,27 @@ select make_set(3, name, upper(name)) from bug20536;
select export_set(5, name, upper(name)) from bug20536;
select export_set(5, name, upper(name), ",", 5) from bug20536;
+#
+# Bug #20108: corrupted default enum value for a ucs2 field
+#
+
+CREATE TABLE t1 (
+ status enum('active','passive') collate latin1_general_ci
+ NOT NULL default 'passive'
+);
+SHOW CREATE TABLE t1;
+ALTER TABLE t1 ADD a int NOT NULL AFTER status;
+
+CREATE TABLE t2 (
+ status enum('active','passive') collate ucs2_turkish_ci
+ NOT NULL default 'passive'
+);
+SHOW CREATE TABLE t2;
+ALTER TABLE t2 ADD a int NOT NULL AFTER status;
+
+DROP TABLE t1,t2;
+
+
# Some broken functions: add these tests just to document current behavior.
# PASSWORD and OLD_PASSWORD don't work with UCS2 strings, but to fix it would
diff --git a/mysql-test/t/delayed.test b/mysql-test/t/delayed.test
index 55e8f81f763..03d8e20dd8f 100644
--- a/mysql-test/t/delayed.test
+++ b/mysql-test/t/delayed.test
@@ -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;
+
diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test
index 98c21986aa9..b5c468e1638 100644
--- a/mysql-test/t/func_gconcat.test
+++ b/mysql-test/t/func_gconcat.test
@@ -447,3 +447,18 @@ SELECT a, CHAR_LENGTH(b) FROM t1;
SELECT CHAR_LENGTH( GROUP_CONCAT(b) ) FROM t1;
SET GROUP_CONCAT_MAX_LEN = 1024;
DROP TABLE t1;
+
+#
+# Bug #22015: crash with GROUP_CONCAT over a derived table that
+# returns the results of aggregation by GROUP_CONCAT
+#
+
+CREATE TABLE t1 (a int, b int);
+
+INSERT INTO t1 VALUES (2,1), (1,2), (2,2), (1,3);
+
+SELECT GROUP_CONCAT(a), x
+ FROM (SELECT a, GROUP_CONCAT(b) x FROM t1 GROUP BY a) AS s
+ GROUP BY x;
+
+DROP TABLE t1;
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index 8a514108dc3..ce1e4e59600 100644
--- a/mysql-test/t/group_by.test
+++ b/mysql-test/t/group_by.test
@@ -655,15 +655,3 @@ where t2.b=v1.a GROUP BY t2.b;
DROP VIEW v1;
DROP TABLE t1,t2;
-
-#
-# Bug #21174: Index degrades sort performance and
-# optimizer does not honor IGNORE INDEX
-#
-CREATE TABLE t1 (a INT, b INT, KEY(a));
-INSERT INTO t1 VALUES (1, 1), (2, 2), (3,3), (4,4);
-
-EXPLAIN SELECT a, SUM(b) FROM t1 GROUP BY a LIMIT 2;
-EXPLAIN SELECT a, SUM(b) FROM t1 IGNORE INDEX (a) GROUP BY a LIMIT 2;
-
-DROP TABLE t1;
diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test
index 93fbc631680..1308b0b83a4 100644
--- a/mysql-test/t/merge.test
+++ b/mysql-test/t/merge.test
@@ -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
#
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index 692db191cf7..f1e8e77d94e 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -988,6 +988,58 @@ execute stmt;
drop temporary table t1;
deallocate prepare stmt;
+#
+# BUG#22085: Crash on the execution of a prepared statement that
+# uses an IN subquery with aggregate functions in HAVING
+#
+
+CREATE TABLE t1(
+ ID int(10) unsigned NOT NULL auto_increment,
+ Member_ID varchar(15) NOT NULL default '',
+ Action varchar(12) NOT NULL,
+ Action_Date datetime NOT NULL,
+ Track varchar(15) default NULL,
+ User varchar(12) default NULL,
+ Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update
+ CURRENT_TIMESTAMP,
+ PRIMARY KEY (ID),
+ KEY Action (Action),
+ KEY Action_Date (Action_Date)
+);
+
+INSERT INTO t1(Member_ID, Action, Action_Date, Track) VALUES
+ ('111111', 'Disenrolled', '2006-03-01', 'CAD' ),
+ ('111111', 'Enrolled', '2006-03-01', 'CAD' ),
+ ('111111', 'Disenrolled', '2006-07-03', 'CAD' ),
+ ('222222', 'Enrolled', '2006-03-07', 'CAD' ),
+ ('222222', 'Enrolled', '2006-03-07', 'CHF' ),
+ ('222222', 'Disenrolled', '2006-08-02', 'CHF' ),
+ ('333333', 'Enrolled', '2006-03-01', 'CAD' ),
+ ('333333', 'Disenrolled', '2006-03-01', 'CAD' ),
+ ('444444', 'Enrolled', '2006-03-01', 'CAD' ),
+ ('555555', 'Disenrolled', '2006-03-01', 'CAD' ),
+ ('555555', 'Enrolled', '2006-07-21', 'CAD' ),
+ ('555555', 'Disenrolled', '2006-03-01', 'CHF' ),
+ ('666666', 'Enrolled', '2006-02-09', 'CAD' ),
+ ('666666', 'Enrolled', '2006-05-12', 'CHF' ),
+ ('666666', 'Disenrolled', '2006-06-01', 'CAD' );
+
+PREPARE STMT FROM
+"SELECT GROUP_CONCAT(Track SEPARATOR ', ') FROM t1
+ WHERE Member_ID=? AND Action='Enrolled' AND
+ (Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t1
+ WHERE Member_ID=?
+ GROUP BY Track
+ HAVING Track>='CAD' AND
+ MAX(Action_Date)>'2006-03-01')";
+SET @id='111111';
+EXECUTE STMT USING @id,@id;
+SET @id='222222';
+EXECUTE STMT USING @id,@id;
+
+DEALLOCATE PREPARE STMT;
+DROP TABLE t1;
+
--echo End of 4.1 tests
############################# 5.0 tests start ################################
#
diff --git a/mysql-test/t/rpl_insert_id.test b/mysql-test/t/rpl_insert_id.test
index 3c46a5b4ca1..126aad68df4 100644
--- a/mysql-test/t/rpl_insert_id.test
+++ b/mysql-test/t/rpl_insert_id.test
@@ -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
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index a4e535ac418..7811301a9bc 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -665,7 +665,7 @@ CREATE TABLE t2 (
) ENGINE=MyISAM;
INSERT INTO t2 VALUES ('AUS','Australia','Oceania','Australia and New Zealand',7741220.00,1901,18886000,79.8,351182.00,392911.00,'Australia','Constitutional Monarchy, Federation','Elisabeth II',135,'AU');
-INSERT INTO t2 VALUES ('AZE','Azerbaijan','Asia','Middle East',86600.00,1991,7734000,62.9,4127.00,4100.00,'Azärbaycan','Federal Republic','Heydär Äliyev',144,'AZ');
+INSERT INTO t2 VALUES ('AZE','Azerbaijan','Asia','Middle East',86600.00,1991,7734000,62.9,4127.00,4100.00,'Azärbaycan','Federal Republic','Heydär Äliyev',144,'AZ');
select t2.Continent, t1.Name, t1.Population from t2 LEFT JOIN t1 ON t2.Code = t1.t2 where t1.Population IN (select max(t1.Population) AS Population from t1, t2 where t1.t2 = t2.Code group by Continent);
@@ -1526,7 +1526,7 @@ CREATE TABLE t1 (
) ENGINE=MyISAM;
INSERT INTO t1 VALUES ('XXX','Xxxxx','Oceania','Xxxxxx',26.00,0,0,0,0,0,'Xxxxx','Xxxxx','Xxxxx',NULL,'XX');
INSERT INTO t1 VALUES ('ASM','American Samoa','Oceania','Polynesia',199.00,0,68000,75.1,334.00,NULL,'Amerika Samoa','US Territory','George W. Bush',54,'AS');
-INSERT INTO t1 VALUES ('ATF','French Southern territories','Antarctica','Antarctica',7780.00,0,0,NULL,0.00,NULL,'Terres australes françaises','Nonmetropolitan Territory of France','Jacques Chirac',NULL,'TF');
+INSERT INTO t1 VALUES ('ATF','French Southern territories','Antarctica','Antarctica',7780.00,0,0,NULL,0.00,NULL,'Terres australes françaises','Nonmetropolitan Territory of France','Jacques Chirac',NULL,'TF');
INSERT INTO t1 VALUES ('UMI','United States Minor Outlying Islands','Oceania','Micronesia/Caribbean',16.00,0,0,NULL,0.00,NULL,'United States Minor Outlying Islands','Dependent Territory of the US','George W. Bush',NULL,'UM');
/*!40000 ALTER TABLE t1 ENABLE KEYS */;
SELECT DISTINCT Continent AS c FROM t1 WHERE Code <> SOME ( SELECT Code FROM t1 WHERE Continent = c AND Population < 200);
@@ -1918,6 +1918,43 @@ SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r
drop table t1,t2;
+#
+# Bug #21853: assert failure for a grouping query with
+# an ALL/ANY quantified subquery in HAVING
+#
+
+CREATE TABLE t1 (
+ field1 int NOT NULL,
+ field2 int NOT NULL,
+ field3 int NOT NULL,
+ PRIMARY KEY (field1,field2,field3)
+);
+CREATE TABLE t2 (
+ fieldA int NOT NULL,
+ fieldB int NOT NULL,
+ PRIMARY KEY (fieldA,fieldB)
+);
+
+INSERT INTO t1 VALUES
+ (1,1,1), (1,1,2), (1,2,1), (1,2,2), (1,2,3), (1,3,1);
+INSERT INTO t2 VALUES (1,1), (1,2), (1,3);
+
+SELECT field1, field2, COUNT(*)
+ FROM t1 GROUP BY field1, field2;
+
+SELECT field1, field2
+ FROM t1
+ GROUP BY field1, field2
+ HAVING COUNT(*) >= ALL (SELECT fieldB
+ FROM t2 WHERE fieldA = field1);
+SELECT field1, field2
+ FROM t1
+ GROUP BY field1, field2
+ HAVING COUNT(*) < ANY (SELECT fieldB
+ FROM t2 WHERE fieldA = field1);
+
+DROP TABLE t1, t2;
+
# End of 4.1 tests
#
@@ -2332,3 +2369,34 @@ explain select * from t1 where not exists
((select t11.i from t1 t11) union (select t12.i from t1 t12));
DROP TABLE t1;
+
+#
+# Bug #21540: Subqueries with no from and aggregate functions return
+# wrong results
+CREATE TABLE t1 (a INT, b INT);
+CREATE TABLE t2 (a INT);
+INSERT INTO t2 values (1);
+INSERT INTO t1 VALUES (1,1),(1,2),(2,3),(3,4);
+SELECT (SELECT COUNT(DISTINCT t1.b) from t2) FROM t1 GROUP BY t1.a;
+SELECT (SELECT COUNT(DISTINCT t1.b) from t2 union select 1 from t2 where 12 < 3)
+ FROM t1 GROUP BY t1.a;
+SELECT COUNT(DISTINCT t1.b), (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a;
+SELECT COUNT(DISTINCT t1.b),
+ (SELECT COUNT(DISTINCT t1.b) union select 1 from DUAL where 12 < 3)
+ FROM t1 GROUP BY t1.a;
+SELECT (
+ SELECT (
+ SELECT COUNT(DISTINCT t1.b)
+ )
+)
+FROM t1 GROUP BY t1.a;
+SELECT (
+ SELECT (
+ SELECT (
+ SELECT COUNT(DISTINCT t1.b)
+ )
+ )
+ FROM t1 GROUP BY t1.a LIMIT 1)
+FROM t1 t2
+GROUP BY t2.a;
+DROP TABLE t1,t2;
diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test
index 4745804e847..b631d2032c4 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -347,13 +347,13 @@ create view v3 (x,y,z) as select b, a, b from t1;
create view v4 (x,y,z) as select c+1, b, a from t1;
create algorithm=temptable view v5 (x,y,z) as select c, b, a from t1;
# try insert to VIEW with fields duplicate
--- error 1288
+-- error 1471
insert into v3 values (-60,4,30);
# try insert to VIEW with expression in SELECT list
--- error 1288
+-- error 1471
insert into v4 values (-60,4,30);
# try insert to VIEW using temporary table algorithm
--- error 1288
+-- error 1471
insert into v5 values (-60,4,30);
insert into v1 values (-60,4,30);
insert into v1 (z,y,x) values (50,6,-100);
@@ -375,13 +375,13 @@ create view v3 (x,y,z) as select b, a, b from t1;
create view v4 (x,y,z) as select c+1, b, a from t1;
create algorithm=temptable view v5 (x,y,z) as select c, b, a from t1;
# try insert to VIEW with fields duplicate
--- error 1288
+-- error 1471
insert into v3 select c, b, a from t2;
# try insert to VIEW with expression in SELECT list
--- error 1288
+-- error 1471
insert into v4 select c, b, a from t2;
# try insert to VIEW using temporary table algorithm
--- error 1288
+-- error 1471
insert into v5 select c, b, a from t2;
insert into v1 select c, b, a from t2;
insert into v1 (z,y,x) select a+20,b+2,-100 from t2;
@@ -1249,14 +1249,14 @@ drop table t1;
#
create table t1 (s1 smallint);
create view v1 as select * from t1 where 20 < (select (s1) from t1);
--- error 1288
+-- error 1471
insert into v1 values (30);
create view v2 as select * from t1;
create view v3 as select * from t1 where 20 < (select (s1) from v2);
--- error 1288
+-- error 1471
insert into v3 values (30);
create view v4 as select * from v2 where 20 < (select (s1) from t1);
--- error 1288
+-- error 1471
insert into v4 values (30);
drop view v4, v3, v2, v1;
drop table t1;
@@ -2825,7 +2825,7 @@ BEGIN
END |
delimiter ;|
---error ER_NON_UPDATABLE_TABLE
+--error ER_NON_INSERTABLE_TABLE
SELECT f2();
DROP FUNCTION f1;
@@ -2850,4 +2850,33 @@ EXPLAIN SELECT * FROM v1 t WHERE t.s1+1 < (SELECT MAX(t1.s1) FROM t1);
DROP VIEW v1;
DROP TABLE t1;
+
+#
+# Bug #5505: Wrong error message on INSERT into a view
+#
+create table t1 (s1 int);
+create view v1 as select s1 as a, s1 as b from t1;
+--error 1471
+insert into v1 values (1,1);
+update v1 set a = 5;
+drop view v1;
+drop table t1;
+
+#
+# Bug #21646: view qith a subquery in ON expression
+#
+
+CREATE TABLE t1(pk int PRIMARY KEY);
+CREATE TABLE t2(pk int PRIMARY KEY, fk int, ver int, org int);
+
+CREATE ALGORITHM=MERGE VIEW v1 AS
+SELECT t1.*
+ FROM t1 JOIN t2
+ ON t2.fk = t1.pk AND
+ t2.ver = (SELECT MAX(t.ver) FROM t2 t WHERE t.org = t2.org);
+SHOW WARNINGS;
+SHOW CREATE VIEW v1;
+
+DROP VIEW v1;
+DROP TABLE t1, t2;
--echo End of 5.0 tests.
diff --git a/mysys/my_chsize.c b/mysys/my_chsize.c
index 9760de29a08..fe0d0ffa607 100644
--- a/mysys/my_chsize.c
+++ b/mysys/my_chsize.c
@@ -46,7 +46,9 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags)
DBUG_PRINT("my",("fd: %d length: %lu MyFlags: %d",fd,(ulong) newlength,
MyFlags));
- oldsize = my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE));
+ if ((oldsize = my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE))) == newlength)
+ DBUG_RETURN(0);
+
DBUG_PRINT("info",("old_size: %ld", (ulong) oldsize));
if (oldsize > newlength)
diff --git a/mysys/queues.c b/mysys/queues.c
index ecf1058af41..6a285ce7417 100644
--- a/mysys/queues.c
+++ b/mysys/queues.c
@@ -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 */
diff --git a/sql/field.h b/sql/field.h
index 65e747e9d2f..b79c2bf77a8 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1432,6 +1432,8 @@ public:
uint decimals, flags, pack_length, key_length;
Field::utype unireg_check;
TYPELIB *interval; // Which interval to use
+ TYPELIB *save_interval; // Temporary copy for the above
+ // Used only for UCS2 intervals
List<String> interval_list;
CHARSET_INFO *charset;
Field::geometry_type geom_type;
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 42d25dbbaee..f13354d5c72 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -1268,6 +1268,7 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length,
switch ((sortorder->result_type=sortorder->item->result_type())) {
case STRING_RESULT:
sortorder->length=sortorder->item->max_length;
+ set_if_smaller(sortorder->length, thd->variables.max_sort_length);
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
{
sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
diff --git a/sql/ha_archive.cc b/sql/ha_archive.cc
index bb94a99e700..bc3c819c4ed 100644
--- a/sql/ha_archive.cc
+++ b/sql/ha_archive.cc
@@ -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)
diff --git a/sql/ha_archive.h b/sql/ha_archive.h
index 2bac9fa605e..564b9f03bf5 100644
--- a/sql/ha_archive.h
+++ b/sql/ha_archive.h
@@ -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;
/*
diff --git a/sql/item.cc b/sql/item.cc
index ba13ba985b5..d56ca95093b 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1182,6 +1182,7 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
split_sum_func(thd, ref_pointer_array, fields);
}
else if ((type() == SUM_FUNC_ITEM || (used_tables() & ~PARAM_TABLE_BIT)) &&
+ type() != SUBSELECT_ITEM &&
(type() != REF_ITEM ||
((Item_ref*)this)->ref_type() == Item_ref::VIEW_REF))
{
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 2e594c74031..e395a7a3af5 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -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()
diff --git a/sql/item_func.h b/sql/item_func.h
index 177daf0311f..31adc033034 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -891,6 +891,7 @@ public:
if (arg_count)
max_length= args[0]->max_length;
}
+ bool fix_fields(THD *thd, Item **ref);
};
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index bcd8270e52f..5ca1dbba94b 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -246,7 +246,27 @@ bool Item_sum::register_sum_func(THD *thd, Item **ref)
aggr_sl->inner_sum_func_list->next= this;
}
aggr_sl->inner_sum_func_list= this;
-
+ aggr_sl->with_sum_func= 1;
+
+ /*
+ Mark Item_subselect(s) as containing aggregate function all the way up
+ to aggregate function's calculation context.
+ Note that we must not mark the Item of calculation context itself
+ because with_sum_func on the calculation context st_select_lex is
+ already set above.
+
+ with_sum_func being set for an Item means that this Item refers
+ (somewhere in it, e.g. one of its arguments if it's a function) directly
+ or through intermediate items to an aggregate function that is calculated
+ in a context "outside" of the Item (e.g. in the current or outer select).
+
+ with_sum_func being set for an st_select_lex means that this st_select_lex
+ has aggregate functions directly referenced (i.e. not through a sub-select).
+ */
+ for (sl= thd->lex->current_select;
+ sl && sl != aggr_sl && sl->master_unit()->item;
+ sl= sl->master_unit()->outer_select() )
+ sl->master_unit()->item->with_sum_func= 1;
}
return FALSE;
}
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 219434ab218..271658d8054 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -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:
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 11f6375ebe0..c6cc6519d78 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -446,7 +446,8 @@ enum enum_parsing_place
NO_MATTER,
IN_HAVING,
SELECT_LIST,
- IN_WHERE
+ IN_WHERE,
+ IN_ON
};
struct st_table;
diff --git a/sql/set_var.cc b/sql/set_var.cc
index c667e2f2bcc..d00857a2bc1 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -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;
}
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 05b31b1e8b2..5ed7466b0df 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -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"
@@ -5631,3 +5631,6 @@ ER_HOSTNAME
eng "host name"
ER_WRONG_STRING_LENGTH
eng "String '%-.70s' is too long for %s (should be no longer than %d)"
+ER_NON_INSERTABLE_TABLE
+ eng "The target table %-.100s of the %s is not insertable-into"
+
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index c29c610b200..85be84d1270 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -902,8 +902,11 @@ void update_non_unique_table_error(TABLE_LIST *update,
*/
if (update->view)
{
+ /* Issue the ER_NON_INSERTABLE_TABLE error for an INSERT */
if (update->view == duplicate->view)
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), update->alias, operation);
+ my_error(!strncmp(operation, "INSERT", 6) ?
+ ER_NON_INSERTABLE_TABLE : ER_NON_UPDATABLE_TABLE, MYF(0),
+ update->alias, operation);
else
my_error(ER_VIEW_PREVENT_UPDATE, MYF(0),
(duplicate->view ? duplicate->alias : update->alias),
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 093173ab949..4d47ec338c0 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -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;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 039c133e885..ccc7a661446 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -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;
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index b5dab814d08..2ce83caa369 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -111,7 +111,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
if (!table_list->updatable)
{
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "INSERT");
+ my_error(ER_NON_INSERTABLE_TABLE, MYF(0), table_list->alias, "INSERT");
return -1;
}
@@ -214,7 +214,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
(table_list->view &&
check_view_insertability(thd, table_list)))
{
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "INSERT");
+ my_error(ER_NON_INSERTABLE_TABLE, MYF(0), table_list->alias, "INSERT");
return -1;
}
@@ -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);
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index d0087b14d6a..788276ac654 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1710,7 +1710,8 @@ bool st_lex::can_be_merged()
unit= unit->next_unit())
{
if (unit->first_select()->parent_lex == this &&
- (unit->item == 0 || unit->item->place() != IN_WHERE))
+ (unit->item == 0 ||
+ (unit->item->place() != IN_WHERE && unit->item->place() != IN_ON)))
{
selects_allow_merge= 0;
break;
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index d5faf6ee7e9..bdc08b7bd2d 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -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;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 18d048df393..1b69e266442 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2422,6 +2422,20 @@ mysql_execute_command(THD *thd)
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
queries_tables list if it is necessary (we need such relinking only
@@ -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 |
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index c27bc3b099d..274251f2df3 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -8153,7 +8153,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);
@@ -8161,9 +8161,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
@@ -11740,8 +11747,6 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
We must not try to use disabled keys.
*/
usable_keys= table->s->keys_in_use;
- /* we must not consider keys that are disabled by IGNORE INDEX */
- usable_keys.intersect(table->keys_in_use_for_query);
for (ORDER *tmp_order=order; tmp_order ; tmp_order=tmp_order->next)
{
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 5405a7fd5c3..a4e05a96f9b 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -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 */
@@ -1561,6 +1561,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;
}
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 4e2b48d9faf..94c5ad331dd 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -1574,7 +1574,7 @@ bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view)
list->push_back(fld);
else
{
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), view->alias, "INSERT");
+ my_error(ER_NON_INSERTABLE_TABLE, MYF(0), view->alias, "INSERT");
DBUG_RETURN(TRUE);
}
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 764b6dd53c1..cb105d05332 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -5212,11 +5212,13 @@ join_table:
/* Change the current name resolution context to a local context. */
if (push_new_name_resolution_context(YYTHD, $1, $3))
YYABORT;
+ Select->parsing_place= IN_ON;
}
expr
{
add_join_on($3,$6);
Lex->pop_context();
+ Select->parsing_place= NO_MATTER;
}
| table_ref STRAIGHT_JOIN table_factor
ON
@@ -5225,12 +5227,14 @@ join_table:
/* Change the current name resolution context to a local context. */
if (push_new_name_resolution_context(YYTHD, $1, $3))
YYABORT;
+ Select->parsing_place= IN_ON;
}
expr
{
$3->straight=1;
add_join_on($3,$6);
Lex->pop_context();
+ Select->parsing_place= NO_MATTER;
}
| table_ref normal_join table_ref
USING
@@ -5254,6 +5258,7 @@ join_table:
/* Change the current name resolution context to a local context. */
if (push_new_name_resolution_context(YYTHD, $1, $5))
YYABORT;
+ Select->parsing_place= IN_ON;
}
expr
{
@@ -5261,6 +5266,7 @@ join_table:
Lex->pop_context();
$5->outer_join|=JOIN_TYPE_LEFT;
$$=$5;
+ Select->parsing_place= NO_MATTER;
}
| table_ref LEFT opt_outer JOIN_SYM table_factor
{
@@ -5285,6 +5291,7 @@ join_table:
/* Change the current name resolution context to a local context. */
if (push_new_name_resolution_context(YYTHD, $1, $5))
YYABORT;
+ Select->parsing_place= IN_ON;
}
expr
{
@@ -5293,6 +5300,7 @@ join_table:
YYABORT;
add_join_on($$, $8);
Lex->pop_context();
+ Select->parsing_place= NO_MATTER;
}
| table_ref RIGHT opt_outer JOIN_SYM table_factor
{
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 3a139aea4c7..93afd9c9e4e 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -228,13 +228,19 @@ bool mysql_create_frm(THD *thd, my_string file_name,
goto err3;
{
- /* Unescape all UCS2 intervals: were escaped in pack_headers */
+ /*
+ Restore all UCS2 intervals.
+ HEX representation of them is not needed anymore.
+ */
List_iterator<create_field> it(create_fields);
create_field *field;
while ((field=it++))
{
- if (field->interval && field->charset->mbminlen > 1)
- unhex_type2(field->interval);
+ if (field->save_interval)
+ {
+ field->interval= field->save_interval;
+ field->save_interval= 0;
+ }
}
}
DBUG_RETURN(0);
@@ -514,18 +520,36 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
reclength=(uint) (field->offset+ data_offset + length);
n_length+= (ulong) strlen(field->field_name)+1;
field->interval_id=0;
+ field->save_interval= 0;
if (field->interval)
{
uint old_int_count=int_count;
if (field->charset->mbminlen > 1)
{
- /* Escape UCS2 intervals using HEX notation */
+ /*
+ Escape UCS2 intervals using HEX notation to avoid
+ problems with delimiters between enum elements.
+ As the original representation is still needed in
+ the function make_empty_rec to create a record of
+ filled with default values it is saved in save_interval
+ The HEX representation is created from this copy.
+ */
+ field->save_interval= field->interval;
+ field->interval= (TYPELIB*) sql_alloc(sizeof(TYPELIB));
+ *field->interval= *field->save_interval;
+ field->interval->type_names=
+ (const char **) sql_alloc(sizeof(char*) *
+ (field->interval->count+1));
+ field->interval->type_names[field->interval->count]= 0;
+ field->interval->type_lengths=
+ (uint *) sql_alloc(sizeof(uint) * field->interval->count);
+
for (uint pos= 0; pos < field->interval->count; pos++)
{
char *dst;
- uint length= field->interval->type_lengths[pos], hex_length;
- const char *src= field->interval->type_names[pos];
+ uint length= field->save_interval->type_lengths[pos], hex_length;
+ const char *src= field->save_interval->type_names[pos];
hex_length= length * 2;
field->interval->type_lengths[pos]= hex_length;
field->interval->type_names[pos]= dst= sql_alloc(hex_length + 1);
@@ -777,7 +801,8 @@ static bool make_empty_rec(THD *thd, File file,enum db_type table_type,
field->charset,
field->geom_type,
field->unireg_check,
- field->interval,
+ field->save_interval ? field->save_interval :
+ field->interval,
field->field_name,
&table);
if (!regfield)
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index 8a444590301..d3f39296445 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -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 }
};