mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 20:42:30 +01:00
Merge bk@192.168.21.1:mysql-5.1
into mysql.com:/home/hf/work/mrg/mysql-5.1-opt sql/mysqld.cc: Auto merged sql/sql_parse.cc: Auto merged
This commit is contained in:
commit
cf2842b56d
40 changed files with 1066 additions and 304 deletions
|
@ -881,6 +881,42 @@ create table t1 (t varchar(255) default null, key t (t(80)))
|
||||||
engine=myisam default charset=latin1;
|
engine=myisam default charset=latin1;
|
||||||
alter table t1 change t t text;
|
alter table t1 change t t text;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
CREATE TABLE t1 (a varchar(500));
|
||||||
|
ALTER TABLE t1 ADD b GEOMETRY NOT NULL, ADD SPATIAL INDEX(b);
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` varchar(500) DEFAULT NULL,
|
||||||
|
`b` geometry NOT NULL,
|
||||||
|
SPATIAL KEY `b` (`b`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
ALTER TABLE t1 ADD KEY(b(50));
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` varchar(500) DEFAULT NULL,
|
||||||
|
`b` geometry NOT NULL,
|
||||||
|
SPATIAL KEY `b` (`b`),
|
||||||
|
KEY `b_2` (`b`(50))
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
ALTER TABLE t1 ADD c POINT;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` varchar(500) DEFAULT NULL,
|
||||||
|
`b` geometry NOT NULL,
|
||||||
|
`c` point DEFAULT NULL,
|
||||||
|
SPATIAL KEY `b` (`b`),
|
||||||
|
KEY `b_2` (`b`(50))
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
CREATE TABLE t2 (a INT, KEY (a(20)));
|
||||||
|
ERROR HY000: Incorrect sub part key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique sub keys
|
||||||
|
ALTER TABLE t1 ADD d INT;
|
||||||
|
ALTER TABLE t1 ADD KEY (d(20));
|
||||||
|
ERROR HY000: Incorrect sub part key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique sub keys
|
||||||
|
ALTER TABLE t1 ADD e GEOMETRY NOT NULL, ADD SPATIAL KEY (e(30));
|
||||||
|
ERROR HY000: Incorrect sub part key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique sub keys
|
||||||
|
DROP TABLE t1;
|
||||||
CREATE TABLE t1 (s CHAR(8) BINARY);
|
CREATE TABLE t1 (s CHAR(8) BINARY);
|
||||||
INSERT INTO t1 VALUES ('test');
|
INSERT INTO t1 VALUES ('test');
|
||||||
SELECT LENGTH(s) FROM t1;
|
SELECT LENGTH(s) FROM t1;
|
||||||
|
|
|
@ -25,10 +25,11 @@ insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
|
||||||
check table t1;
|
check table t1;
|
||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 check status OK
|
test.t1 check status OK
|
||||||
select * from t1 ignore key (key1) where text1='teststring' or text1 like 'teststring_%';
|
select * from t1 ignore key (key1) where text1='teststring' or
|
||||||
|
text1 like 'teststring_%' ORDER BY text1;
|
||||||
text1
|
text1
|
||||||
teststring
|
|
||||||
teststring
|
teststring
|
||||||
|
teststring
|
||||||
select * from t1 where text1='teststring' or text1 like 'teststring_%';
|
select * from t1 where text1='teststring' or text1 like 'teststring_%';
|
||||||
text1
|
text1
|
||||||
teststring
|
teststring
|
||||||
|
@ -48,10 +49,11 @@ alter table t1 modify text1 char(32) binary not null;
|
||||||
check table t1;
|
check table t1;
|
||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 check status OK
|
test.t1 check status OK
|
||||||
select * from t1 ignore key (key1) where text1='teststring' or text1 like 'teststring_%';
|
select * from t1 ignore key (key1) where text1='teststring' or
|
||||||
|
text1 like 'teststring_%' ORDER BY text1;
|
||||||
text1
|
text1
|
||||||
teststring
|
|
||||||
teststring
|
teststring
|
||||||
|
teststring
|
||||||
select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
|
select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
|
||||||
concat('|', text1, '|')
|
concat('|', text1, '|')
|
||||||
|teststring |
|
|teststring |
|
||||||
|
@ -132,10 +134,11 @@ concat('|', text1, '|')
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create table t1 (text1 varchar(32) not NULL, KEY key1 using BTREE (text1)) engine=heap;
|
create table t1 (text1 varchar(32) not NULL, KEY key1 using BTREE (text1)) engine=heap;
|
||||||
insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
|
insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
|
||||||
select * from t1 ignore key (key1) where text1='teststring' or text1 like 'teststring_%';
|
select * from t1 ignore key (key1) where text1='teststring' or
|
||||||
|
text1 like 'teststring_%' ORDER BY text1;
|
||||||
text1
|
text1
|
||||||
teststring
|
|
||||||
teststring
|
teststring
|
||||||
|
teststring
|
||||||
select * from t1 where text1='teststring' or text1 like 'teststring_%';
|
select * from t1 where text1='teststring' or text1 like 'teststring_%';
|
||||||
text1
|
text1
|
||||||
teststring
|
teststring
|
||||||
|
|
|
@ -1,26 +1,12 @@
|
||||||
flush logs;
|
flush logs;
|
||||||
set global expire_logs_days = 3;
|
set global expire_logs_days = 3;
|
||||||
show variables like 'log%';
|
show variables like 'log_bin%';
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
log ON
|
|
||||||
log_bin OFF
|
log_bin OFF
|
||||||
log_bin_trust_function_creators ON
|
log_bin_trust_function_creators ON
|
||||||
log_error
|
|
||||||
log_output TABLE
|
|
||||||
log_queries_not_using_indexes OFF
|
|
||||||
log_slave_updates OFF
|
|
||||||
log_slow_queries OFF
|
|
||||||
log_warnings 1
|
|
||||||
flush logs;
|
flush logs;
|
||||||
show variables like 'log%';
|
show variables like 'log_bin%';
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
log ON
|
|
||||||
log_bin OFF
|
log_bin OFF
|
||||||
log_bin_trust_function_creators ON
|
log_bin_trust_function_creators ON
|
||||||
log_error
|
|
||||||
log_output TABLE
|
|
||||||
log_queries_not_using_indexes OFF
|
|
||||||
log_slave_updates OFF
|
|
||||||
log_slow_queries OFF
|
|
||||||
log_warnings 1
|
|
||||||
set global expire_logs_days = 0;
|
set global expire_logs_days = 0;
|
||||||
|
|
|
@ -10,7 +10,7 @@ t1 CREATE TABLE `t1` (
|
||||||
`fid` int(11) NOT NULL AUTO_INCREMENT,
|
`fid` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
`g` geometry NOT NULL,
|
`g` geometry NOT NULL,
|
||||||
PRIMARY KEY (`fid`),
|
PRIMARY KEY (`fid`),
|
||||||
SPATIAL KEY `g` (`g`(32))
|
SPATIAL KEY `g` (`g`)
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(150 150, 150 150)'));
|
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(150 150, 150 150)'));
|
||||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(149 149, 151 151)'));
|
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(149 149, 151 151)'));
|
||||||
|
@ -293,7 +293,7 @@ t2 CREATE TABLE `t2` (
|
||||||
`fid` int(11) NOT NULL AUTO_INCREMENT,
|
`fid` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
`g` geometry NOT NULL,
|
`g` geometry NOT NULL,
|
||||||
PRIMARY KEY (`fid`),
|
PRIMARY KEY (`fid`),
|
||||||
SPATIAL KEY `g` (`g`(32))
|
SPATIAL KEY `g` (`g`)
|
||||||
) ENGINE=MyISAM AUTO_INCREMENT=101 DEFAULT CHARSET=latin1
|
) ENGINE=MyISAM AUTO_INCREMENT=101 DEFAULT CHARSET=latin1
|
||||||
SELECT count(*) FROM t2;
|
SELECT count(*) FROM t2;
|
||||||
count(*)
|
count(*)
|
||||||
|
@ -803,7 +803,7 @@ CREATE TABLE t2 (geom GEOMETRY NOT NULL, SPATIAL KEY gk(geom));
|
||||||
INSERT INTO t2 SELECT GeomFromText(st) FROM t1;
|
INSERT INTO t2 SELECT GeomFromText(st) FROM t1;
|
||||||
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
|
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
|
||||||
drop table t1, t2;
|
drop table t1, t2;
|
||||||
CREATE TABLE t1 (`geometry` geometry NOT NULL default '',SPATIAL KEY `gndx` (`geometry`(32))) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
CREATE TABLE t1 (`geometry` geometry NOT NULL default '',SPATIAL KEY `gndx` (`geometry`)) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||||
Warnings:
|
Warnings:
|
||||||
Warning 1101 BLOB/TEXT column 'geometry' can't have a default value
|
Warning 1101 BLOB/TEXT column 'geometry' can't have a default value
|
||||||
INSERT INTO t1 (geometry) VALUES
|
INSERT INTO t1 (geometry) VALUES
|
||||||
|
@ -820,7 +820,7 @@ test.t1 check status OK
|
||||||
drop table t1;
|
drop table t1;
|
||||||
CREATE TABLE t1 (
|
CREATE TABLE t1 (
|
||||||
c1 geometry NOT NULL default '',
|
c1 geometry NOT NULL default '',
|
||||||
SPATIAL KEY i1 (c1(32))
|
SPATIAL KEY i1 (c1)
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||||
Warnings:
|
Warnings:
|
||||||
Warning 1101 BLOB/TEXT column 'c1' can't have a default value
|
Warning 1101 BLOB/TEXT column 'c1' can't have a default value
|
||||||
|
@ -836,7 +836,7 @@ test.t1 check status OK
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
CREATE TABLE t1 (
|
CREATE TABLE t1 (
|
||||||
c1 geometry NOT NULL default '',
|
c1 geometry NOT NULL default '',
|
||||||
SPATIAL KEY i1 (c1(32))
|
SPATIAL KEY i1 (c1)
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||||
Warnings:
|
Warnings:
|
||||||
Warning 1101 BLOB/TEXT column 'c1' can't have a default value
|
Warning 1101 BLOB/TEXT column 'c1' can't have a default value
|
||||||
|
@ -879,7 +879,7 @@ c1 varchar(15) collate utf8_bin default NULL,
|
||||||
c3 varchar(10) collate utf8_bin default NULL,
|
c3 varchar(10) collate utf8_bin default NULL,
|
||||||
spatial_point point NOT NULL,
|
spatial_point point NOT NULL,
|
||||||
PRIMARY KEY(id),
|
PRIMARY KEY(id),
|
||||||
SPATIAL KEY (spatial_point(32))
|
SPATIAL KEY (spatial_point)
|
||||||
)ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
|
)ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
|
||||||
INSERT INTO t1 (c2, c1, c3, spatial_point) VALUES
|
INSERT INTO t1 (c2, c1, c3, spatial_point) VALUES
|
||||||
('y', 's', 'j', GeomFromText('POINT(167 74)')),
|
('y', 's', 'j', GeomFromText('POINT(167 74)')),
|
||||||
|
|
|
@ -1035,12 +1035,110 @@ HAVING SUM(t1_inner.b)+t1_outer.b > 5);
|
||||||
ERROR 42000: 'test.t1_outer.b' isn't in GROUP BY
|
ERROR 42000: 'test.t1_outer.b' isn't in GROUP BY
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
SET SQL_MODE = '';
|
SET SQL_MODE = '';
|
||||||
CREATE TABLE t1 (a INT, b INT, KEY(a));
|
CREATE TABLE t1 (a INT, b INT,
|
||||||
INSERT INTO t1 VALUES (1, 1), (2, 2), (3,3), (4,4);
|
PRIMARY KEY (a),
|
||||||
EXPLAIN SELECT a, SUM(b) FROM t1 GROUP BY a LIMIT 2;
|
KEY i2(a,b));
|
||||||
|
INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8);
|
||||||
|
INSERT INTO t1 SELECT a + 8,b FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a + 16,b FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a + 32,b FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a + 64,b FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a + 128,b FROM t1;
|
||||||
|
ANALYZE TABLE t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 analyze status OK
|
||||||
|
EXPLAIN SELECT a FROM t1 WHERE a < 2;
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 SIMPLE t1 index NULL a 5 NULL 4
|
1 SIMPLE t1 range PRIMARY,i2 PRIMARY 4 NULL 2 Using where; Using index
|
||||||
EXPLAIN SELECT a, SUM(b) FROM t1 IGNORE INDEX (a) GROUP BY a LIMIT 2;
|
EXPLAIN SELECT a FROM t1 WHERE a < 2 ORDER BY a;
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
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
|
1 SIMPLE t1 range PRIMARY,i2 PRIMARY 4 NULL 2 Using where; Using index
|
||||||
DROP TABLE t1;
|
EXPLAIN SELECT a FROM t1 WHERE a < 2 GROUP BY a;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 range PRIMARY,i2 PRIMARY 4 NULL 2 Using where; Using index
|
||||||
|
EXPLAIN SELECT a FROM t1 IGNORE INDEX (PRIMARY,i2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ALL NULL NULL NULL NULL 256
|
||||||
|
EXPLAIN SELECT a FROM t1 IGNORE INDEX FOR JOIN (PRIMARY,i2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ALL NULL NULL NULL NULL 256
|
||||||
|
EXPLAIN SELECT a FROM t1 IGNORE INDEX FOR GROUP BY (PRIMARY,i2) GROUP BY a;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 index NULL PRIMARY 4 NULL 256 Using index
|
||||||
|
EXPLAIN SELECT a FROM t1 IGNORE INDEX FOR ORDER BY (PRIMARY,i2) ORDER BY a;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 index NULL PRIMARY 4 NULL 256 Using index; Using filesort
|
||||||
|
EXPLAIN SELECT a FROM t1 IGNORE INDEX FOR ORDER BY (PRIMARY)
|
||||||
|
IGNORE INDEX FOR GROUP BY (i2) GROUP BY a;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 index NULL PRIMARY 4 NULL 256 Using index
|
||||||
|
EXPLAIN SELECT a FROM t1 IGNORE INDEX (PRIMARY) IGNORE INDEX FOR ORDER BY (i2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 index NULL i2 9 NULL 256 Using index
|
||||||
|
EXPLAIN SELECT a FROM t1 FORCE INDEX (i2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 index NULL i2 9 NULL 256 Using index
|
||||||
|
EXPLAIN SELECT a FROM t1 USE INDEX ();
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ALL NULL NULL NULL NULL 256
|
||||||
|
EXPLAIN SELECT a FROM t1 USE INDEX () USE INDEX (i2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ALL NULL NULL NULL NULL 256
|
||||||
|
EXPLAIN SELECT a FROM t1
|
||||||
|
FORCE INDEX (PRIMARY)
|
||||||
|
IGNORE INDEX FOR GROUP BY (i2)
|
||||||
|
IGNORE INDEX FOR ORDER BY (i2)
|
||||||
|
USE INDEX (i2);
|
||||||
|
ERROR HY000: Incorrect usage of USE INDEX and FORCE INDEX
|
||||||
|
EXPLAIN SELECT a FROM t1 USE INDEX (i2) USE INDEX ();
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 index NULL i2 9 NULL 256 Using index
|
||||||
|
EXPLAIN SELECT a FROM t1 FORCE INDEX ();
|
||||||
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1
|
||||||
|
EXPLAIN SELECT a FROM t1 IGNORE INDEX ();
|
||||||
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1
|
||||||
|
EXPLAIN SELECT a FROM t1 USE INDEX FOR JOIN (i2)
|
||||||
|
USE INDEX FOR GROUP BY (i2) GROUP BY a;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 index NULL i2 9 NULL 256 Using index
|
||||||
|
EXPLAIN SELECT a FROM t1 FORCE INDEX FOR JOIN (i2)
|
||||||
|
FORCE INDEX FOR GROUP BY (i2) GROUP BY a;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 range NULL i2 4 NULL 257 Using index for group-by
|
||||||
|
EXPLAIN SELECT a FROM t1 USE INDEX () IGNORE INDEX (i2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ALL NULL NULL NULL NULL 256
|
||||||
|
EXPLAIN SELECT a FROM t1 IGNORE INDEX (i2) USE INDEX ();
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ALL NULL NULL NULL NULL 256
|
||||||
|
EXPLAIN SELECT a FROM t1
|
||||||
|
USE INDEX FOR GROUP BY (i2)
|
||||||
|
USE INDEX FOR ORDER BY (i2)
|
||||||
|
USE INDEX FOR JOIN (i2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 index NULL i2 9 NULL 256 Using index
|
||||||
|
EXPLAIN SELECT a FROM t1
|
||||||
|
USE INDEX FOR JOIN (i2)
|
||||||
|
USE INDEX FOR JOIN (i2)
|
||||||
|
USE INDEX FOR JOIN (i2,i2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 index NULL i2 9 NULL 256 Using index
|
||||||
|
EXPLAIN SELECT 1 FROM t1 WHERE a IN
|
||||||
|
(SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 index NULL PRIMARY 4 NULL 256 Using where; Using index
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 256 Using where
|
||||||
|
CREATE TABLE t2 (a INT, b INT, KEY(a));
|
||||||
|
INSERT INTO t2 VALUES (1, 1), (2, 2), (3,3), (4,4);
|
||||||
|
EXPLAIN SELECT a, SUM(b) FROM t2 GROUP BY a LIMIT 2;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t2 index NULL a 5 NULL 4
|
||||||
|
EXPLAIN SELECT a, SUM(b) FROM t2 IGNORE INDEX (a) GROUP BY a LIMIT 2;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t2 ALL NULL NULL NULL NULL 4 Using temporary; Using filesort
|
||||||
|
EXPLAIN SELECT 1 FROM t2 WHERE a IN
|
||||||
|
(SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t2 index NULL a 5 NULL 4 Using where; Using index
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 256 Using where
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
|
|
@ -489,3 +489,44 @@ EXPLAIN SELECT MAX(a) FROM t1 FORCE INDEX(a);
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 SIMPLE t1 system NULL NULL NULL NULL 1
|
1 SIMPLE t1 system NULL NULL NULL NULL 1
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
a INTEGER auto_increment PRIMARY KEY,
|
||||||
|
b INTEGER NOT NULL,
|
||||||
|
c INTEGER NOT NULL,
|
||||||
|
d CHAR(64)
|
||||||
|
);
|
||||||
|
CREATE TABLE t2 (
|
||||||
|
a INTEGER auto_increment PRIMARY KEY,
|
||||||
|
b INTEGER NOT NULL,
|
||||||
|
c SMALLINT NOT NULL,
|
||||||
|
d DATETIME NOT NULL,
|
||||||
|
e SMALLINT NOT NULL,
|
||||||
|
f INTEGER NOT NULL,
|
||||||
|
g INTEGER NOT NULL,
|
||||||
|
h SMALLINT NOT NULL,
|
||||||
|
i INTEGER NOT NULL,
|
||||||
|
j INTEGER NOT NULL,
|
||||||
|
UNIQUE INDEX (b),
|
||||||
|
INDEX (b, d, e, f, g, h, i, j, c),
|
||||||
|
INDEX (c)
|
||||||
|
);
|
||||||
|
INSERT INTO t2 VALUES
|
||||||
|
(NULL, 1, 254, '1000-01-01 00:00:00', 257, 0, 0, 0, 0, 0),
|
||||||
|
(NULL, 2, 1, '2004-11-30 12:00:00', 1, 0, 0, 0, 0, 0),
|
||||||
|
(NULL, 3, 1, '2004-11-30 12:00:00', 1, 0, 0, 2, -21600, 0),
|
||||||
|
(NULL, 4, 1, '2004-11-30 12:00:00', 1, 0, 0, 2, -10800, 0),
|
||||||
|
(NULL, 5, 1, '2004-11-30 12:00:00', 1, 0, 0, 5, -10800, 0),
|
||||||
|
(NULL, 6, 1, '2004-11-30 12:00:00', 102, 0, 0, 0, 0, 0),
|
||||||
|
(NULL, 7, 1, '2004-11-30 12:00:00', 105, 2, 0, 0, 0, 0),
|
||||||
|
(NULL, 8, 1, '2004-11-30 12:00:00', 105, 10, 0, 0, 0, 0);
|
||||||
|
INSERT INTO t1 (b, c, d) VALUES
|
||||||
|
(3388000, -553000, NULL),
|
||||||
|
(3388000, -553000, NULL);
|
||||||
|
SELECT *
|
||||||
|
FROM t2 c JOIN t1 pa ON c.b = pa.a
|
||||||
|
WHERE c.c = 1
|
||||||
|
ORDER BY c.b, c.d
|
||||||
|
;
|
||||||
|
a b c d e f g h i j a b c d
|
||||||
|
2 2 1 2004-11-30 12:00:00 1 0 0 0 0 0 2 3388000 -553000 NULL
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
|
|
@ -958,6 +958,28 @@ a ratio
|
||||||
19 1.3333
|
19 1.3333
|
||||||
9 2.6667
|
9 2.6667
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
CREATE TABLE t1 (a INT UNSIGNED NOT NULL, b TIME);
|
||||||
|
INSERT INTO t1 (a) VALUES (100000), (0), (100), (1000000),(10000), (1000), (10);
|
||||||
|
UPDATE t1 SET b = SEC_TO_TIME(a);
|
||||||
|
SELECT a, b FROM t1 ORDER BY b DESC;
|
||||||
|
a b
|
||||||
|
1000000 277:46:40
|
||||||
|
100000 27:46:40
|
||||||
|
10000 02:46:40
|
||||||
|
1000 00:16:40
|
||||||
|
100 00:01:40
|
||||||
|
10 00:00:10
|
||||||
|
0 00:00:00
|
||||||
|
SELECT a, b FROM t1 ORDER BY SEC_TO_TIME(a) DESC;
|
||||||
|
a b
|
||||||
|
1000000 277:46:40
|
||||||
|
100000 27:46:40
|
||||||
|
10000 02:46:40
|
||||||
|
1000 00:16:40
|
||||||
|
100 00:01:40
|
||||||
|
10 00:00:10
|
||||||
|
0 00:00:00
|
||||||
|
DROP TABLE t1;
|
||||||
CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a), UNIQUE KEY b (b));
|
CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a), UNIQUE KEY b (b));
|
||||||
INSERT INTO t1 VALUES (1,1),(2,2);
|
INSERT INTO t1 VALUES (1,1),(2,2);
|
||||||
CREATE TABLE t2 (a INT, b INT, KEY a (a,b));
|
CREATE TABLE t2 (a INT, b INT, KEY a (a,b));
|
||||||
|
|
|
@ -3933,4 +3933,42 @@ cc cc 7
|
||||||
aa aa 2
|
aa aa 2
|
||||||
aa aa 2
|
aa aa 2
|
||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
access_id int NOT NULL default '0',
|
||||||
|
name varchar(20) default NULL,
|
||||||
|
rank int NOT NULL default '0',
|
||||||
|
KEY idx (access_id)
|
||||||
|
);
|
||||||
|
CREATE TABLE t2 (
|
||||||
|
faq_group_id int NOT NULL default '0',
|
||||||
|
faq_id int NOT NULL default '0',
|
||||||
|
access_id int default NULL,
|
||||||
|
UNIQUE KEY idx1 (faq_id),
|
||||||
|
KEY idx2 (faq_group_id,faq_id)
|
||||||
|
);
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(1,'Everyone',2),(2,'Help',3),(3,'Technical Support',1),(4,'Chat User',4);
|
||||||
|
INSERT INTO t2 VALUES
|
||||||
|
(261,265,1),(490,494,1);
|
||||||
|
SELECT t2.faq_id
|
||||||
|
FROM t1 INNER JOIN t2 IGNORE INDEX (idx1)
|
||||||
|
ON (t1.access_id = t2.access_id)
|
||||||
|
LEFT JOIN t2 t
|
||||||
|
ON (t.faq_group_id = t2.faq_group_id AND
|
||||||
|
find_in_set(t.access_id, '1,4') < find_in_set(t2.access_id, '1,4'))
|
||||||
|
WHERE
|
||||||
|
t2.access_id IN (1,4) AND t.access_id IS NULL AND t2.faq_id in (265);
|
||||||
|
faq_id
|
||||||
|
265
|
||||||
|
SELECT t2.faq_id
|
||||||
|
FROM t1 INNER JOIN t2
|
||||||
|
ON (t1.access_id = t2.access_id)
|
||||||
|
LEFT JOIN t2 t
|
||||||
|
ON (t.faq_group_id = t2.faq_group_id AND
|
||||||
|
find_in_set(t.access_id, '1,4') < find_in_set(t2.access_id, '1,4'))
|
||||||
|
WHERE
|
||||||
|
t2.access_id IN (1,4) AND t.access_id IS NULL AND t2.faq_id in (265);
|
||||||
|
faq_id
|
||||||
|
265
|
||||||
|
DROP TABLE t1,t2;
|
||||||
End of 5.0 tests
|
End of 5.0 tests
|
||||||
|
|
|
@ -3873,3 +3873,16 @@ id_1
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
DROP TABLE t2;
|
DROP TABLE t2;
|
||||||
DROP TABLE t1xt2;
|
DROP TABLE t1xt2;
|
||||||
|
CREATE TABLE t1 (a int);
|
||||||
|
INSERT INTO t1 VALUES (3), (1), (2);
|
||||||
|
SELECT 'this is ' 'a test.' AS col1, a AS col2 FROM t1;
|
||||||
|
col1 col2
|
||||||
|
this is a test. 3
|
||||||
|
this is a test. 1
|
||||||
|
this is a test. 2
|
||||||
|
SELECT * FROM (SELECT 'this is ' 'a test.' AS col1, a AS t2 FROM t1) t;
|
||||||
|
col1 t2
|
||||||
|
this is a test. 3
|
||||||
|
this is a test. 1
|
||||||
|
this is a test. 2
|
||||||
|
DROP table t1;
|
||||||
|
|
|
@ -641,6 +641,33 @@ engine=myisam default charset=latin1;
|
||||||
alter table t1 change t t text;
|
alter table t1 change t t text;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #26794: Adding an index with a prefix on a SPATIAL type breaks ALTER
|
||||||
|
# TABLE
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a varchar(500));
|
||||||
|
|
||||||
|
ALTER TABLE t1 ADD b GEOMETRY NOT NULL, ADD SPATIAL INDEX(b);
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
ALTER TABLE t1 ADD KEY(b(50));
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
|
||||||
|
ALTER TABLE t1 ADD c POINT;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
|
||||||
|
--error ER_WRONG_SUB_KEY
|
||||||
|
CREATE TABLE t2 (a INT, KEY (a(20)));
|
||||||
|
|
||||||
|
ALTER TABLE t1 ADD d INT;
|
||||||
|
--error ER_WRONG_SUB_KEY
|
||||||
|
ALTER TABLE t1 ADD KEY (d(20));
|
||||||
|
|
||||||
|
# the 5.1 part of the test
|
||||||
|
--error ER_WRONG_SUB_KEY
|
||||||
|
ALTER TABLE t1 ADD e GEOMETRY NOT NULL, ADD SPATIAL KEY (e(30));
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
#
|
#
|
||||||
# Bug#18038 MySQL server corrupts binary columns data
|
# Bug#18038 MySQL server corrupts binary columns data
|
||||||
#
|
#
|
||||||
|
|
|
@ -16,7 +16,8 @@ drop table if exists t1;
|
||||||
create table t1 (text1 varchar(32) not NULL, KEY key1 (text1));
|
create table t1 (text1 varchar(32) not NULL, KEY key1 (text1));
|
||||||
insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
|
insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
|
||||||
check table t1;
|
check table t1;
|
||||||
select * from t1 ignore key (key1) where text1='teststring' or text1 like 'teststring_%';
|
select * from t1 ignore key (key1) where text1='teststring' or
|
||||||
|
text1 like 'teststring_%' ORDER BY text1;
|
||||||
select * from t1 where text1='teststring' or text1 like 'teststring_%';
|
select * from t1 where text1='teststring' or text1 like 'teststring_%';
|
||||||
select * from t1 where text1='teststring' or text1 > 'teststring\t';
|
select * from t1 where text1='teststring' or text1 > 'teststring\t';
|
||||||
select * from t1 order by text1;
|
select * from t1 order by text1;
|
||||||
|
@ -24,7 +25,8 @@ explain select * from t1 order by text1;
|
||||||
|
|
||||||
alter table t1 modify text1 char(32) binary not null;
|
alter table t1 modify text1 char(32) binary not null;
|
||||||
check table t1;
|
check table t1;
|
||||||
select * from t1 ignore key (key1) where text1='teststring' or text1 like 'teststring_%';
|
select * from t1 ignore key (key1) where text1='teststring' or
|
||||||
|
text1 like 'teststring_%' ORDER BY text1;
|
||||||
select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
|
select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
|
||||||
select concat('|', text1, '|') from t1 where text1='teststring' or text1 > 'teststring\t';
|
select concat('|', text1, '|') from t1 where text1='teststring' or text1 > 'teststring\t';
|
||||||
select text1, length(text1) from t1 order by text1;
|
select text1, length(text1) from t1 order by text1;
|
||||||
|
@ -57,7 +59,8 @@ drop table t1;
|
||||||
|
|
||||||
create table t1 (text1 varchar(32) not NULL, KEY key1 using BTREE (text1)) engine=heap;
|
create table t1 (text1 varchar(32) not NULL, KEY key1 using BTREE (text1)) engine=heap;
|
||||||
insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
|
insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
|
||||||
select * from t1 ignore key (key1) where text1='teststring' or text1 like 'teststring_%';
|
select * from t1 ignore key (key1) where text1='teststring' or
|
||||||
|
text1 like 'teststring_%' ORDER BY text1;
|
||||||
select * from t1 where text1='teststring' or text1 like 'teststring_%';
|
select * from t1 where text1='teststring' or text1 like 'teststring_%';
|
||||||
select * from t1 where text1='teststring' or text1 >= 'teststring\t';
|
select * from t1 where text1='teststring' or text1 >= 'teststring\t';
|
||||||
select * from t1 order by text1;
|
select * from t1 order by text1;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#
|
#
|
||||||
flush logs;
|
flush logs;
|
||||||
set global expire_logs_days = 3;
|
set global expire_logs_days = 3;
|
||||||
show variables like 'log%';
|
show variables like 'log_bin%';
|
||||||
flush logs;
|
flush logs;
|
||||||
show variables like 'log%';
|
show variables like 'log_bin%';
|
||||||
set global expire_logs_days = 0;
|
set global expire_logs_days = 0;
|
||||||
|
|
|
@ -172,7 +172,7 @@ CREATE TABLE t2 (geom GEOMETRY NOT NULL, SPATIAL KEY gk(geom));
|
||||||
INSERT INTO t2 SELECT GeomFromText(st) FROM t1;
|
INSERT INTO t2 SELECT GeomFromText(st) FROM t1;
|
||||||
drop table t1, t2;
|
drop table t1, t2;
|
||||||
|
|
||||||
CREATE TABLE t1 (`geometry` geometry NOT NULL default '',SPATIAL KEY `gndx` (`geometry`(32))) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
CREATE TABLE t1 (`geometry` geometry NOT NULL default '',SPATIAL KEY `gndx` (`geometry`)) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||||
|
|
||||||
INSERT INTO t1 (geometry) VALUES
|
INSERT INTO t1 (geometry) VALUES
|
||||||
(PolygonFromText('POLYGON((-18.6086111000 -66.9327777000, -18.6055555000
|
(PolygonFromText('POLYGON((-18.6086111000 -66.9327777000, -18.6055555000
|
||||||
|
@ -192,7 +192,7 @@ drop table t1;
|
||||||
#
|
#
|
||||||
CREATE TABLE t1 (
|
CREATE TABLE t1 (
|
||||||
c1 geometry NOT NULL default '',
|
c1 geometry NOT NULL default '',
|
||||||
SPATIAL KEY i1 (c1(32))
|
SPATIAL KEY i1 (c1)
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||||
INSERT INTO t1 (c1) VALUES (
|
INSERT INTO t1 (c1) VALUES (
|
||||||
PolygonFromText('POLYGON((-18.6086111000 -66.9327777000,
|
PolygonFromText('POLYGON((-18.6086111000 -66.9327777000,
|
||||||
|
@ -206,7 +206,7 @@ DROP TABLE t1;
|
||||||
#
|
#
|
||||||
CREATE TABLE t1 (
|
CREATE TABLE t1 (
|
||||||
c1 geometry NOT NULL default '',
|
c1 geometry NOT NULL default '',
|
||||||
SPATIAL KEY i1 (c1(32))
|
SPATIAL KEY i1 (c1)
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||||
INSERT INTO t1 (c1) VALUES (
|
INSERT INTO t1 (c1) VALUES (
|
||||||
PolygonFromText('POLYGON((-18.6086111000 -66.9327777000,
|
PolygonFromText('POLYGON((-18.6086111000 -66.9327777000,
|
||||||
|
@ -251,7 +251,7 @@ CREATE TABLE t1 (id bigint(12) unsigned NOT NULL auto_increment,
|
||||||
c3 varchar(10) collate utf8_bin default NULL,
|
c3 varchar(10) collate utf8_bin default NULL,
|
||||||
spatial_point point NOT NULL,
|
spatial_point point NOT NULL,
|
||||||
PRIMARY KEY(id),
|
PRIMARY KEY(id),
|
||||||
SPATIAL KEY (spatial_point(32))
|
SPATIAL KEY (spatial_point)
|
||||||
)ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
|
)ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
|
||||||
#
|
#
|
||||||
INSERT INTO t1 (c2, c1, c3, spatial_point) VALUES
|
INSERT INTO t1 (c2, c1, c3, spatial_point) VALUES
|
||||||
|
|
|
@ -757,10 +757,66 @@ SET SQL_MODE = '';
|
||||||
# Bug #21174: Index degrades sort performance and
|
# Bug #21174: Index degrades sort performance and
|
||||||
# optimizer does not honor IGNORE INDEX
|
# optimizer does not honor IGNORE INDEX
|
||||||
#
|
#
|
||||||
CREATE TABLE t1 (a INT, b INT, KEY(a));
|
CREATE TABLE t1 (a INT, b INT,
|
||||||
INSERT INTO t1 VALUES (1, 1), (2, 2), (3,3), (4,4);
|
PRIMARY KEY (a),
|
||||||
|
KEY i2(a,b));
|
||||||
|
INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8);
|
||||||
|
INSERT INTO t1 SELECT a + 8,b FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a + 16,b FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a + 32,b FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a + 64,b FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a + 128,b FROM t1;
|
||||||
|
ANALYZE TABLE t1;
|
||||||
|
EXPLAIN SELECT a FROM t1 WHERE a < 2;
|
||||||
|
EXPLAIN SELECT a FROM t1 WHERE a < 2 ORDER BY a;
|
||||||
|
EXPLAIN SELECT a FROM t1 WHERE a < 2 GROUP BY a;
|
||||||
|
EXPLAIN SELECT a FROM t1 IGNORE INDEX (PRIMARY,i2);
|
||||||
|
EXPLAIN SELECT a FROM t1 IGNORE INDEX FOR JOIN (PRIMARY,i2);
|
||||||
|
EXPLAIN SELECT a FROM t1 IGNORE INDEX FOR GROUP BY (PRIMARY,i2) GROUP BY a;
|
||||||
|
EXPLAIN SELECT a FROM t1 IGNORE INDEX FOR ORDER BY (PRIMARY,i2) ORDER BY a;
|
||||||
|
EXPLAIN SELECT a FROM t1 IGNORE INDEX FOR ORDER BY (PRIMARY)
|
||||||
|
IGNORE INDEX FOR GROUP BY (i2) GROUP BY a;
|
||||||
|
EXPLAIN SELECT a FROM t1 IGNORE INDEX (PRIMARY) IGNORE INDEX FOR ORDER BY (i2);
|
||||||
|
EXPLAIN SELECT a FROM t1 FORCE INDEX (i2);
|
||||||
|
EXPLAIN SELECT a FROM t1 USE INDEX ();
|
||||||
|
EXPLAIN SELECT a FROM t1 USE INDEX () USE INDEX (i2);
|
||||||
|
--error ER_WRONG_USAGE
|
||||||
|
EXPLAIN SELECT a FROM t1
|
||||||
|
FORCE INDEX (PRIMARY)
|
||||||
|
IGNORE INDEX FOR GROUP BY (i2)
|
||||||
|
IGNORE INDEX FOR ORDER BY (i2)
|
||||||
|
USE INDEX (i2);
|
||||||
|
EXPLAIN SELECT a FROM t1 USE INDEX (i2) USE INDEX ();
|
||||||
|
--error ER_PARSE_ERROR
|
||||||
|
EXPLAIN SELECT a FROM t1 FORCE INDEX ();
|
||||||
|
--error ER_PARSE_ERROR
|
||||||
|
EXPLAIN SELECT a FROM t1 IGNORE INDEX ();
|
||||||
|
EXPLAIN SELECT a FROM t1 USE INDEX FOR JOIN (i2)
|
||||||
|
USE INDEX FOR GROUP BY (i2) GROUP BY a;
|
||||||
|
EXPLAIN SELECT a FROM t1 FORCE INDEX FOR JOIN (i2)
|
||||||
|
FORCE INDEX FOR GROUP BY (i2) GROUP BY a;
|
||||||
|
EXPLAIN SELECT a FROM t1 USE INDEX () IGNORE INDEX (i2);
|
||||||
|
EXPLAIN SELECT a FROM t1 IGNORE INDEX (i2) USE INDEX ();
|
||||||
|
|
||||||
EXPLAIN SELECT a, SUM(b) FROM t1 GROUP BY a LIMIT 2;
|
EXPLAIN SELECT a FROM t1
|
||||||
EXPLAIN SELECT a, SUM(b) FROM t1 IGNORE INDEX (a) GROUP BY a LIMIT 2;
|
USE INDEX FOR GROUP BY (i2)
|
||||||
|
USE INDEX FOR ORDER BY (i2)
|
||||||
|
USE INDEX FOR JOIN (i2);
|
||||||
|
|
||||||
DROP TABLE t1;
|
EXPLAIN SELECT a FROM t1
|
||||||
|
USE INDEX FOR JOIN (i2)
|
||||||
|
USE INDEX FOR JOIN (i2)
|
||||||
|
USE INDEX FOR JOIN (i2,i2);
|
||||||
|
|
||||||
|
EXPLAIN SELECT 1 FROM t1 WHERE a IN
|
||||||
|
(SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));
|
||||||
|
|
||||||
|
CREATE TABLE t2 (a INT, b INT, KEY(a));
|
||||||
|
INSERT INTO t2 VALUES (1, 1), (2, 2), (3,3), (4,4);
|
||||||
|
EXPLAIN SELECT a, SUM(b) FROM t2 GROUP BY a LIMIT 2;
|
||||||
|
EXPLAIN SELECT a, SUM(b) FROM t2 IGNORE INDEX (a) GROUP BY a LIMIT 2;
|
||||||
|
|
||||||
|
EXPLAIN SELECT 1 FROM t2 WHERE a IN
|
||||||
|
(SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));
|
||||||
|
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
|
|
@ -453,3 +453,51 @@ ALTER TABLE t1 DISABLE KEYS;
|
||||||
EXPLAIN SELECT MAX(a) FROM t1 FORCE INDEX(a);
|
EXPLAIN SELECT MAX(a) FROM t1 FORCE INDEX(a);
|
||||||
|
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #24778: Innodb: No result when using ORDER BY
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
a INTEGER auto_increment PRIMARY KEY,
|
||||||
|
b INTEGER NOT NULL,
|
||||||
|
c INTEGER NOT NULL,
|
||||||
|
d CHAR(64)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE t2 (
|
||||||
|
a INTEGER auto_increment PRIMARY KEY,
|
||||||
|
b INTEGER NOT NULL,
|
||||||
|
c SMALLINT NOT NULL,
|
||||||
|
d DATETIME NOT NULL,
|
||||||
|
e SMALLINT NOT NULL,
|
||||||
|
f INTEGER NOT NULL,
|
||||||
|
g INTEGER NOT NULL,
|
||||||
|
h SMALLINT NOT NULL,
|
||||||
|
i INTEGER NOT NULL,
|
||||||
|
j INTEGER NOT NULL,
|
||||||
|
UNIQUE INDEX (b),
|
||||||
|
INDEX (b, d, e, f, g, h, i, j, c),
|
||||||
|
INDEX (c)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO t2 VALUES
|
||||||
|
(NULL, 1, 254, '1000-01-01 00:00:00', 257, 0, 0, 0, 0, 0),
|
||||||
|
(NULL, 2, 1, '2004-11-30 12:00:00', 1, 0, 0, 0, 0, 0),
|
||||||
|
(NULL, 3, 1, '2004-11-30 12:00:00', 1, 0, 0, 2, -21600, 0),
|
||||||
|
(NULL, 4, 1, '2004-11-30 12:00:00', 1, 0, 0, 2, -10800, 0),
|
||||||
|
(NULL, 5, 1, '2004-11-30 12:00:00', 1, 0, 0, 5, -10800, 0),
|
||||||
|
(NULL, 6, 1, '2004-11-30 12:00:00', 102, 0, 0, 0, 0, 0),
|
||||||
|
(NULL, 7, 1, '2004-11-30 12:00:00', 105, 2, 0, 0, 0, 0),
|
||||||
|
(NULL, 8, 1, '2004-11-30 12:00:00', 105, 10, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
INSERT INTO t1 (b, c, d) VALUES
|
||||||
|
(3388000, -553000, NULL),
|
||||||
|
(3388000, -553000, NULL);
|
||||||
|
|
||||||
|
SELECT *
|
||||||
|
FROM t2 c JOIN t1 pa ON c.b = pa.a
|
||||||
|
WHERE c.c = 1
|
||||||
|
ORDER BY c.b, c.d
|
||||||
|
;
|
||||||
|
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
|
|
@ -678,6 +678,21 @@ insert into t1 values (1,2,3), (9,8,3), (19,4,3), (1,4,9);
|
||||||
select a,(sum(b)/sum(c)) as ratio from t1 group by a order by sum(b)/sum(c) asc;
|
select a,(sum(b)/sum(c)) as ratio from t1 group by a order by sum(b)/sum(c) asc;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#26672: Incorrect SEC_TO_TIME() casting in ORDER BY
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a INT UNSIGNED NOT NULL, b TIME);
|
||||||
|
INSERT INTO t1 (a) VALUES (100000), (0), (100), (1000000),(10000), (1000), (10);
|
||||||
|
UPDATE t1 SET b = SEC_TO_TIME(a);
|
||||||
|
|
||||||
|
-- Correct ORDER
|
||||||
|
SELECT a, b FROM t1 ORDER BY b DESC;
|
||||||
|
|
||||||
|
-- must be ordered as the above
|
||||||
|
SELECT a, b FROM t1 ORDER BY SEC_TO_TIME(a) DESC;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
#
|
#
|
||||||
# BUG#16590: Optimized does not do right "const" table pre-read
|
# BUG#16590: Optimized does not do right "const" table pre-read
|
||||||
#
|
#
|
||||||
|
|
|
@ -3299,4 +3299,51 @@ SELECT * FROM t1 LEFT JOIN t2 ON t1.name=t2.name;
|
||||||
|
|
||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #26963: join with predicates that contain fields from equalities evaluated
|
||||||
|
# to constants after constant table substitution
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
access_id int NOT NULL default '0',
|
||||||
|
name varchar(20) default NULL,
|
||||||
|
rank int NOT NULL default '0',
|
||||||
|
KEY idx (access_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE t2 (
|
||||||
|
faq_group_id int NOT NULL default '0',
|
||||||
|
faq_id int NOT NULL default '0',
|
||||||
|
access_id int default NULL,
|
||||||
|
UNIQUE KEY idx1 (faq_id),
|
||||||
|
KEY idx2 (faq_group_id,faq_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(1,'Everyone',2),(2,'Help',3),(3,'Technical Support',1),(4,'Chat User',4);
|
||||||
|
INSERT INTO t2 VALUES
|
||||||
|
(261,265,1),(490,494,1);
|
||||||
|
|
||||||
|
|
||||||
|
SELECT t2.faq_id
|
||||||
|
FROM t1 INNER JOIN t2 IGNORE INDEX (idx1)
|
||||||
|
ON (t1.access_id = t2.access_id)
|
||||||
|
LEFT JOIN t2 t
|
||||||
|
ON (t.faq_group_id = t2.faq_group_id AND
|
||||||
|
find_in_set(t.access_id, '1,4') < find_in_set(t2.access_id, '1,4'))
|
||||||
|
WHERE
|
||||||
|
t2.access_id IN (1,4) AND t.access_id IS NULL AND t2.faq_id in (265);
|
||||||
|
|
||||||
|
SELECT t2.faq_id
|
||||||
|
FROM t1 INNER JOIN t2
|
||||||
|
ON (t1.access_id = t2.access_id)
|
||||||
|
LEFT JOIN t2 t
|
||||||
|
ON (t.faq_group_id = t2.faq_group_id AND
|
||||||
|
find_in_set(t.access_id, '1,4') < find_in_set(t2.access_id, '1,4'))
|
||||||
|
WHERE
|
||||||
|
t2.access_id IN (1,4) AND t.access_id IS NULL AND t2.faq_id in (265);
|
||||||
|
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
|
||||||
--echo End of 5.0 tests
|
--echo End of 5.0 tests
|
||||||
|
|
|
@ -2736,3 +2736,15 @@ DROP TABLE t1;
|
||||||
DROP TABLE t2;
|
DROP TABLE t2;
|
||||||
DROP TABLE t1xt2;
|
DROP TABLE t1xt2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #26728: derived table with concatanation of literals in select list
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a int);
|
||||||
|
INSERT INTO t1 VALUES (3), (1), (2);
|
||||||
|
|
||||||
|
SELECT 'this is ' 'a test.' AS col1, a AS col2 FROM t1;
|
||||||
|
SELECT * FROM (SELECT 'this is ' 'a test.' AS col1, a AS t2 FROM t1) t;
|
||||||
|
|
||||||
|
DROP table t1;
|
||||||
|
|
||||||
|
|
|
@ -1015,6 +1015,7 @@ bool Field::type_can_have_key_part(enum enum_field_types type)
|
||||||
case MYSQL_TYPE_BLOB:
|
case MYSQL_TYPE_BLOB:
|
||||||
case MYSQL_TYPE_VAR_STRING:
|
case MYSQL_TYPE_VAR_STRING:
|
||||||
case MYSQL_TYPE_STRING:
|
case MYSQL_TYPE_STRING:
|
||||||
|
case MYSQL_TYPE_GEOMETRY:
|
||||||
return TRUE;
|
return TRUE;
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
|
@ -1374,7 +1374,10 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch ((sortorder->result_type=sortorder->item->result_type())) {
|
sortorder->result_type= sortorder->item->result_type();
|
||||||
|
if (sortorder->item->result_as_longlong())
|
||||||
|
sortorder->result_type= INT_RESULT;
|
||||||
|
switch (sortorder->result_type) {
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
sortorder->length=sortorder->item->max_length;
|
sortorder->length=sortorder->item->max_length;
|
||||||
set_if_smaller(sortorder->length, thd->variables.max_sort_length);
|
set_if_smaller(sortorder->length, thd->variables.max_sort_length);
|
||||||
|
|
19
sql/item.cc
19
sql/item.cc
|
@ -3907,7 +3907,9 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
||||||
{
|
{
|
||||||
/* First usage of column */
|
/* First usage of column */
|
||||||
table->used_fields++; // Used to optimize loops
|
table->used_fields++; // Used to optimize loops
|
||||||
table->used_keys.intersect(field->part_of_key);
|
/* purecov: begin inspected */
|
||||||
|
table->covering_keys.intersect(field->part_of_key);
|
||||||
|
/* purecov: end */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4125,7 +4127,9 @@ bool Item_field::set_no_const_sub(byte *arg)
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
The function returns a pointer to an item that is taken from
|
The function returns a pointer to an item that is taken from
|
||||||
the very beginning of the item_equal list which the Item_field
|
the very beginning of the item_equal list which the Item_field
|
||||||
object refers to (belongs to).
|
object refers to (belongs to) unless item_equal contains a constant
|
||||||
|
item. In this case the function returns this constant item,
|
||||||
|
(if the substitution does not require conversion).
|
||||||
If the Item_field object does not refer any Item_equal object
|
If the Item_field object does not refer any Item_equal object
|
||||||
'this' is returned
|
'this' is returned
|
||||||
|
|
||||||
|
@ -4134,7 +4138,8 @@ bool Item_field::set_no_const_sub(byte *arg)
|
||||||
of the thransformer method.
|
of the thransformer method.
|
||||||
|
|
||||||
RETURN VALUES
|
RETURN VALUES
|
||||||
pointer to a replacement Item_field if there is a better equal item;
|
pointer to a replacement Item_field if there is a better equal item or
|
||||||
|
a pointer to a constant equal item;
|
||||||
this - otherwise.
|
this - otherwise.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -4142,6 +4147,14 @@ Item *Item_field::replace_equal_field(byte *arg)
|
||||||
{
|
{
|
||||||
if (item_equal)
|
if (item_equal)
|
||||||
{
|
{
|
||||||
|
Item *const_item= item_equal->get_const();
|
||||||
|
if (const_item)
|
||||||
|
{
|
||||||
|
if (cmp_context != (Item_result)-1 &&
|
||||||
|
const_item->cmp_context != cmp_context)
|
||||||
|
return this;
|
||||||
|
return const_item;
|
||||||
|
}
|
||||||
Item_field *subst= item_equal->get_first();
|
Item_field *subst= item_equal->get_first();
|
||||||
if (subst && !field->eq(subst->field))
|
if (subst && !field->eq(subst->field))
|
||||||
return subst;
|
return subst;
|
||||||
|
|
|
@ -1811,7 +1811,11 @@ public:
|
||||||
str_value.length(), collation.collation);
|
str_value.length(), collation.collation);
|
||||||
}
|
}
|
||||||
Item *safe_charset_converter(CHARSET_INFO *tocs);
|
Item *safe_charset_converter(CHARSET_INFO *tocs);
|
||||||
inline void append(char *str, uint length) { str_value.append(str, length); }
|
inline void append(char *str, uint length)
|
||||||
|
{
|
||||||
|
str_value.append(str, length);
|
||||||
|
max_length= str_value.numchars() * collation.collation->mbmaxlen;
|
||||||
|
}
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
// to prevent drop fixed flag (no need parent cleanup call)
|
// to prevent drop fixed flag (no need parent cleanup call)
|
||||||
void cleanup() {}
|
void cleanup() {}
|
||||||
|
|
|
@ -2021,7 +2021,6 @@ inline void setup_table_map(TABLE *table, TABLE_LIST *table_list, uint tablenr)
|
||||||
table->const_table= 0;
|
table->const_table= 0;
|
||||||
table->null_row= 0;
|
table->null_row= 0;
|
||||||
table->status= STATUS_NO_RECORD;
|
table->status= STATUS_NO_RECORD;
|
||||||
table->keys_in_use_for_query= table->s->keys_in_use;
|
|
||||||
table->maybe_null= table_list->outer_join;
|
table->maybe_null= table_list->outer_join;
|
||||||
TABLE_LIST *embedding= table_list->embedding;
|
TABLE_LIST *embedding= table_list->embedding;
|
||||||
while (!table->maybe_null && embedding)
|
while (!table->maybe_null && embedding)
|
||||||
|
@ -2032,6 +2031,8 @@ inline void setup_table_map(TABLE *table, TABLE_LIST *table_list, uint tablenr)
|
||||||
table->tablenr= tablenr;
|
table->tablenr= tablenr;
|
||||||
table->map= (table_map) 1 << tablenr;
|
table->map= (table_map) 1 << tablenr;
|
||||||
table->force_index= table_list->force_index;
|
table->force_index= table_list->force_index;
|
||||||
|
table->covering_keys= table->s->keys_for_keyread;
|
||||||
|
table->merge_keys.clear_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5031,7 +5031,8 @@ enum options_mysqld
|
||||||
OPT_MERGE,
|
OPT_MERGE,
|
||||||
OPT_THREAD_HANDLING,
|
OPT_THREAD_HANDLING,
|
||||||
OPT_INNODB_ROLLBACK_ON_TIMEOUT,
|
OPT_INNODB_ROLLBACK_ON_TIMEOUT,
|
||||||
OPT_SECURE_FILE_PRIV
|
OPT_SECURE_FILE_PRIV,
|
||||||
|
OPT_OLD_MODE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -6262,6 +6263,10 @@ The minimum value for this variable is 4096.",
|
||||||
(gptr*) &global_system_variables.net_write_timeout,
|
(gptr*) &global_system_variables.net_write_timeout,
|
||||||
(gptr*) &max_system_variables.net_write_timeout, 0, GET_ULONG,
|
(gptr*) &max_system_variables.net_write_timeout, 0, GET_ULONG,
|
||||||
REQUIRED_ARG, NET_WRITE_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
|
REQUIRED_ARG, NET_WRITE_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
|
||||||
|
{ "old_mode", OPT_OLD_MODE, "Use compatible behaviour.",
|
||||||
|
(gptr*) &global_system_variables.old_mode,
|
||||||
|
(gptr*) &max_system_variables.old_mode, 0, GET_BOOL, NO_ARG,
|
||||||
|
0, 0, 0, 0, 0, 0},
|
||||||
{"open_files_limit", OPT_OPEN_FILES_LIMIT,
|
{"open_files_limit", OPT_OPEN_FILES_LIMIT,
|
||||||
"If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of files.",
|
"If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of files.",
|
||||||
(gptr*) &open_files_limit, (gptr*) &open_files_limit, 0, GET_ULONG,
|
(gptr*) &open_files_limit, (gptr*) &open_files_limit, 0, GET_ULONG,
|
||||||
|
|
|
@ -2111,9 +2111,9 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
|
||||||
param.key_parts_end=key_parts;
|
param.key_parts_end=key_parts;
|
||||||
|
|
||||||
/* Calculate cost of full index read for the shortest covering index */
|
/* Calculate cost of full index read for the shortest covering index */
|
||||||
if (!head->used_keys.is_clear_all())
|
if (!head->covering_keys.is_clear_all())
|
||||||
{
|
{
|
||||||
int key_for_use= find_shortest_key(head, &head->used_keys);
|
int key_for_use= find_shortest_key(head, &head->covering_keys);
|
||||||
double key_read_time= (get_index_only_read_time(¶m, records,
|
double key_read_time= (get_index_only_read_time(¶m, records,
|
||||||
key_for_use) +
|
key_for_use) +
|
||||||
(double) records / TIME_FOR_COMPARE);
|
(double) records / TIME_FOR_COMPARE);
|
||||||
|
@ -4646,7 +4646,7 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
|
||||||
param->needed_reg->set_bit(keynr);
|
param->needed_reg->set_bit(keynr);
|
||||||
|
|
||||||
bool read_index_only= index_read_must_be_used ? TRUE :
|
bool read_index_only= index_read_must_be_used ? TRUE :
|
||||||
(bool) param->table->used_keys.is_set(keynr);
|
(bool) param->table->covering_keys.is_set(keynr);
|
||||||
|
|
||||||
found_records= check_quick_select(param, idx, *key, update_tbl_stats);
|
found_records= check_quick_select(param, idx, *key, update_tbl_stats);
|
||||||
if (param->is_ror_scan)
|
if (param->is_ror_scan)
|
||||||
|
@ -9012,7 +9012,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
|
||||||
cur_index_info++, cur_index++)
|
cur_index_info++, cur_index++)
|
||||||
{
|
{
|
||||||
/* Check (B1) - if current index is covering. */
|
/* Check (B1) - if current index is covering. */
|
||||||
if (!table->used_keys.is_set(cur_index))
|
if (!table->covering_keys.is_set(cur_index))
|
||||||
goto next_index;
|
goto next_index;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1851,8 +1851,6 @@ bool reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
|
||||||
table->const_table=0;
|
table->const_table=0;
|
||||||
table->null_row= table->maybe_null= table->force_index= 0;
|
table->null_row= table->maybe_null= table->force_index= 0;
|
||||||
table->status=STATUS_NO_RECORD;
|
table->status=STATUS_NO_RECORD;
|
||||||
table->keys_in_use_for_query= share->keys_in_use;
|
|
||||||
table->used_keys= share->keys_for_keyread;
|
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2271,9 +2269,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||||
table->const_table=0;
|
table->const_table=0;
|
||||||
table->null_row= table->maybe_null= table->force_index= 0;
|
table->null_row= table->maybe_null= table->force_index= 0;
|
||||||
table->status=STATUS_NO_RECORD;
|
table->status=STATUS_NO_RECORD;
|
||||||
table->keys_in_use_for_query= table->s->keys_in_use;
|
|
||||||
table->insert_values= 0;
|
table->insert_values= 0;
|
||||||
table->used_keys= table->s->keys_for_keyread;
|
|
||||||
table->fulltext_searched= 0;
|
table->fulltext_searched= 0;
|
||||||
table->file->ft_handler= 0;
|
table->file->ft_handler= 0;
|
||||||
if (table->timestamp_field)
|
if (table->timestamp_field)
|
||||||
|
@ -2358,8 +2354,6 @@ static bool reopen_table(TABLE *table)
|
||||||
tmp.null_row= table->null_row;
|
tmp.null_row= table->null_row;
|
||||||
tmp.maybe_null= table->maybe_null;
|
tmp.maybe_null= table->maybe_null;
|
||||||
tmp.status= table->status;
|
tmp.status= table->status;
|
||||||
tmp.keys_in_use_for_query= tmp.s->keys_in_use;
|
|
||||||
tmp.used_keys= tmp.s->keys_for_keyread;
|
|
||||||
|
|
||||||
tmp.s->table_map_id= table->s->table_map_id;
|
tmp.s->table_map_id= table->s->table_map_id;
|
||||||
|
|
||||||
|
@ -3820,7 +3814,7 @@ static void update_field_dependencies(THD *thd, Field *field, TABLE *table)
|
||||||
been set for all fields (for example for view).
|
been set for all fields (for example for view).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
table->used_keys.intersect(field->part_of_key);
|
table->covering_keys.intersect(field->part_of_key);
|
||||||
table->merge_keys.merge(field->part_of_key);
|
table->merge_keys.merge(field->part_of_key);
|
||||||
|
|
||||||
if (thd->mark_used_columns == MARK_COLUMNS_READ)
|
if (thd->mark_used_columns == MARK_COLUMNS_READ)
|
||||||
|
@ -5060,7 +5054,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
|
||||||
TABLE *table_1= nj_col_1->table_ref->table;
|
TABLE *table_1= nj_col_1->table_ref->table;
|
||||||
/* Mark field_1 used for table cache. */
|
/* Mark field_1 used for table cache. */
|
||||||
bitmap_set_bit(table_1->read_set, field_1->field_index);
|
bitmap_set_bit(table_1->read_set, field_1->field_index);
|
||||||
table_1->used_keys.intersect(field_1->part_of_key);
|
table_1->covering_keys.intersect(field_1->part_of_key);
|
||||||
table_1->merge_keys.merge(field_1->part_of_key);
|
table_1->merge_keys.merge(field_1->part_of_key);
|
||||||
}
|
}
|
||||||
if (field_2)
|
if (field_2)
|
||||||
|
@ -5068,7 +5062,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
|
||||||
TABLE *table_2= nj_col_2->table_ref->table;
|
TABLE *table_2= nj_col_2->table_ref->table;
|
||||||
/* Mark field_2 used for table cache. */
|
/* Mark field_2 used for table cache. */
|
||||||
bitmap_set_bit(table_2->read_set, field_2->field_index);
|
bitmap_set_bit(table_2->read_set, field_2->field_index);
|
||||||
table_2->used_keys.intersect(field_2->part_of_key);
|
table_2->covering_keys.intersect(field_2->part_of_key);
|
||||||
table_2->merge_keys.merge(field_2->part_of_key);
|
table_2->merge_keys.merge(field_2->part_of_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5704,30 +5698,8 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
|
||||||
tablenr= 0;
|
tablenr= 0;
|
||||||
}
|
}
|
||||||
setup_table_map(table, table_list, tablenr);
|
setup_table_map(table, table_list, tablenr);
|
||||||
table->used_keys= table->s->keys_for_keyread;
|
if (table_list->process_index_hints(table))
|
||||||
table->merge_keys.clear_all();
|
DBUG_RETURN(1);
|
||||||
if (table_list->use_index)
|
|
||||||
{
|
|
||||||
key_map map;
|
|
||||||
get_key_map_from_key_list(&map, table, table_list->use_index);
|
|
||||||
if (map.is_set_all())
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
/*
|
|
||||||
Don't introduce keys in keys_in_use_for_query that weren't there
|
|
||||||
before. FORCE/USE INDEX should not add keys, it should only remove
|
|
||||||
all keys except the key(s) specified in the hint.
|
|
||||||
*/
|
|
||||||
table->keys_in_use_for_query.intersect(map);
|
|
||||||
}
|
|
||||||
if (table_list->ignore_index)
|
|
||||||
{
|
|
||||||
key_map map;
|
|
||||||
get_key_map_from_key_list(&map, table, table_list->ignore_index);
|
|
||||||
if (map.is_set_all())
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
table->keys_in_use_for_query.subtract(map);
|
|
||||||
}
|
|
||||||
table->used_keys.intersect(table->keys_in_use_for_query);
|
|
||||||
}
|
}
|
||||||
if (tablenr > MAX_TABLES)
|
if (tablenr > MAX_TABLES)
|
||||||
{
|
{
|
||||||
|
@ -6009,7 +5981,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
|
||||||
bitmap_set_bit(field->table->read_set, field->field_index);
|
bitmap_set_bit(field->table->read_set, field->field_index);
|
||||||
if (table)
|
if (table)
|
||||||
{
|
{
|
||||||
table->used_keys.intersect(field->part_of_key);
|
table->covering_keys.intersect(field->part_of_key);
|
||||||
table->merge_keys.merge(field->part_of_key);
|
table->merge_keys.merge(field->part_of_key);
|
||||||
}
|
}
|
||||||
if (tables->is_natural_join)
|
if (tables->is_natural_join)
|
||||||
|
@ -6027,7 +5999,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
|
||||||
if (field_table)
|
if (field_table)
|
||||||
{
|
{
|
||||||
thd->used_tables|= field_table->map;
|
thd->used_tables|= field_table->map;
|
||||||
field_table->used_keys.intersect(field->part_of_key);
|
field_table->covering_keys.intersect(field->part_of_key);
|
||||||
field_table->merge_keys.merge(field->part_of_key);
|
field_table->merge_keys.merge(field->part_of_key);
|
||||||
field_table->used_fields++;
|
field_table->used_fields++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,6 +243,11 @@ struct system_variables
|
||||||
|
|
||||||
my_bool low_priority_updates;
|
my_bool low_priority_updates;
|
||||||
my_bool new_mode;
|
my_bool new_mode;
|
||||||
|
/*
|
||||||
|
compatibility option:
|
||||||
|
- index usage hints (USE INDEX without a FOR clause) behave as in 5.0
|
||||||
|
*/
|
||||||
|
my_bool old_mode;
|
||||||
my_bool query_cache_wlock_invalidate;
|
my_bool query_cache_wlock_invalidate;
|
||||||
my_bool engine_condition_pushdown;
|
my_bool engine_condition_pushdown;
|
||||||
my_bool innodb_table_locks;
|
my_bool innodb_table_locks;
|
||||||
|
@ -278,6 +283,7 @@ struct system_variables
|
||||||
DATE_TIME_FORMAT *datetime_format;
|
DATE_TIME_FORMAT *datetime_format;
|
||||||
DATE_TIME_FORMAT *time_format;
|
DATE_TIME_FORMAT *time_format;
|
||||||
my_bool sysdate_is_now;
|
my_bool sysdate_is_now;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
||||||
/* Update the table->file->stats.records number */
|
/* Update the table->file->stats.records number */
|
||||||
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
||||||
|
|
||||||
table->used_keys.clear_all();
|
table->covering_keys.clear_all();
|
||||||
table->quick_keys.clear_all(); // Can't use 'only index'
|
table->quick_keys.clear_all(); // Can't use 'only index'
|
||||||
select=make_select(table, 0, 0, conds, 0, &error);
|
select=make_select(table, 0, 0, conds, 0, &error);
|
||||||
if (error)
|
if (error)
|
||||||
|
@ -553,7 +553,7 @@ multi_delete::initialize_tables(JOIN *join)
|
||||||
tbl->no_keyread=1;
|
tbl->no_keyread=1;
|
||||||
/* Don't use record cache */
|
/* Don't use record cache */
|
||||||
tbl->no_cache= 1;
|
tbl->no_cache= 1;
|
||||||
tbl->used_keys.clear_all();
|
tbl->covering_keys.clear_all();
|
||||||
if (tbl->file->has_transactions())
|
if (tbl->file->has_transactions())
|
||||||
transactional_tables= 1;
|
transactional_tables= 1;
|
||||||
else
|
else
|
||||||
|
|
|
@ -567,7 +567,7 @@ SQL_SELECT *prepare_simple_select(THD *thd, Item *cond,
|
||||||
cond->fix_fields(thd, &cond); // can never fail
|
cond->fix_fields(thd, &cond); // can never fail
|
||||||
|
|
||||||
/* Assume that no indexes cover all required fields */
|
/* Assume that no indexes cover all required fields */
|
||||||
table->used_keys.clear_all();
|
table->covering_keys.clear_all();
|
||||||
|
|
||||||
SQL_SELECT *res= make_select(table, 0, 0, cond, 0, error);
|
SQL_SELECT *res= make_select(table, 0, 0, cond, 0, error);
|
||||||
if (*error || (res && res->check_quick(thd, 0, HA_POS_ERROR)) ||
|
if (*error || (res && res->check_quick(thd, 0, HA_POS_ERROR)) ||
|
||||||
|
|
|
@ -69,6 +69,17 @@ static uchar to_upper_lex[]=
|
||||||
208,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255
|
208,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Names of the index hints (for error messages). Keep in sync with
|
||||||
|
index_hint_type
|
||||||
|
*/
|
||||||
|
|
||||||
|
const char * index_hint_type_name[] =
|
||||||
|
{
|
||||||
|
"IGNORE INDEX",
|
||||||
|
"USE INDEX",
|
||||||
|
"FORCE INDEX"
|
||||||
|
};
|
||||||
|
|
||||||
inline int lex_casecmp(const char *s, const char *t, uint len)
|
inline int lex_casecmp(const char *s, const char *t, uint len)
|
||||||
{
|
{
|
||||||
|
@ -1201,7 +1212,6 @@ void st_select_lex::init_select()
|
||||||
group_list.empty();
|
group_list.empty();
|
||||||
type= db= 0;
|
type= db= 0;
|
||||||
having= 0;
|
having= 0;
|
||||||
use_index_ptr= ignore_index_ptr= 0;
|
|
||||||
table_join_options= 0;
|
table_join_options= 0;
|
||||||
in_sum_expr= with_wild= 0;
|
in_sum_expr= with_wild= 0;
|
||||||
options= 0;
|
options= 0;
|
||||||
|
@ -1209,7 +1219,6 @@ void st_select_lex::init_select()
|
||||||
braces= 0;
|
braces= 0;
|
||||||
expr_list.empty();
|
expr_list.empty();
|
||||||
interval_list.empty();
|
interval_list.empty();
|
||||||
use_index.empty();
|
|
||||||
ftfunc_list_alloc.empty();
|
ftfunc_list_alloc.empty();
|
||||||
inner_sum_func_list= 0;
|
inner_sum_func_list= 0;
|
||||||
ftfunc_list= &ftfunc_list_alloc;
|
ftfunc_list= &ftfunc_list_alloc;
|
||||||
|
@ -1436,14 +1445,11 @@ bool st_select_lex_node::inc_in_sum_expr() { return 1; }
|
||||||
uint st_select_lex_node::get_in_sum_expr() { return 0; }
|
uint st_select_lex_node::get_in_sum_expr() { return 0; }
|
||||||
TABLE_LIST* st_select_lex_node::get_table_list() { return 0; }
|
TABLE_LIST* st_select_lex_node::get_table_list() { return 0; }
|
||||||
List<Item>* st_select_lex_node::get_item_list() { return 0; }
|
List<Item>* st_select_lex_node::get_item_list() { return 0; }
|
||||||
List<String>* st_select_lex_node::get_use_index() { return 0; }
|
TABLE_LIST *st_select_lex_node::add_table_to_list (THD *thd, Table_ident *table,
|
||||||
List<String>* st_select_lex_node::get_ignore_index() { return 0; }
|
|
||||||
TABLE_LIST *st_select_lex_node::add_table_to_list(THD *thd, Table_ident *table,
|
|
||||||
LEX_STRING *alias,
|
LEX_STRING *alias,
|
||||||
ulong table_join_options,
|
ulong table_join_options,
|
||||||
thr_lock_type flags,
|
thr_lock_type flags,
|
||||||
List<String> *use_index,
|
List<index_hint> *hints,
|
||||||
List<String> *ignore_index,
|
|
||||||
LEX_STRING *option)
|
LEX_STRING *option)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1550,19 +1556,6 @@ List<Item>* st_select_lex::get_item_list()
|
||||||
return &item_list;
|
return &item_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
List<String>* st_select_lex::get_use_index()
|
|
||||||
{
|
|
||||||
return use_index_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
List<String>* st_select_lex::get_ignore_index()
|
|
||||||
{
|
|
||||||
return ignore_index_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ulong st_select_lex::get_table_join_options()
|
ulong st_select_lex::get_table_join_options()
|
||||||
{
|
{
|
||||||
return table_join_options;
|
return table_join_options;
|
||||||
|
@ -2328,3 +2321,61 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds,
|
||||||
are in sql_union.cc
|
are in sql_union.cc
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Sets the kind of hints to be added by the calls to add_index_hint().
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
set_index_hint_type()
|
||||||
|
type the kind of hints to be added from now on.
|
||||||
|
clause the clause to use for hints to be added from now on.
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
Used in filling up the tagged hints list.
|
||||||
|
This list is filled by first setting the kind of the hint as a
|
||||||
|
context variable and then adding hints of the current kind.
|
||||||
|
Then the context variable index_hint_type can be reset to the
|
||||||
|
next hint type.
|
||||||
|
*/
|
||||||
|
void st_select_lex::set_index_hint_type(enum index_hint_type type,
|
||||||
|
index_clause_map clause)
|
||||||
|
{
|
||||||
|
current_index_hint_type= type;
|
||||||
|
current_index_hint_clause= clause;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Makes an array to store index usage hints (ADD/FORCE/IGNORE INDEX).
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
alloc_index_hints()
|
||||||
|
thd current thread.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void st_select_lex::alloc_index_hints (THD *thd)
|
||||||
|
{
|
||||||
|
index_hints= new (thd->mem_root) List<index_hint>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
adds an element to the array storing index usage hints
|
||||||
|
(ADD/FORCE/IGNORE INDEX).
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
add_index_hint()
|
||||||
|
thd current thread.
|
||||||
|
str name of the index.
|
||||||
|
length number of characters in str.
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
0 on success, non-zero otherwise
|
||||||
|
*/
|
||||||
|
bool st_select_lex::add_index_hint (THD *thd, char *str, uint length)
|
||||||
|
{
|
||||||
|
return index_hints->push_front (new (thd->mem_root)
|
||||||
|
index_hint(current_index_hint_type,
|
||||||
|
current_index_hint_clause,
|
||||||
|
str, length));
|
||||||
|
}
|
||||||
|
|
|
@ -216,6 +216,47 @@ enum tablespace_op_type
|
||||||
NO_TABLESPACE_OP, DISCARD_TABLESPACE, IMPORT_TABLESPACE
|
NO_TABLESPACE_OP, DISCARD_TABLESPACE, IMPORT_TABLESPACE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
String names used to print a statement with index hints.
|
||||||
|
Keep in sync with index_hint_type.
|
||||||
|
*/
|
||||||
|
extern const char * index_hint_type_name[];
|
||||||
|
typedef byte index_clause_map;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Bits in index_clause_map : one for each possible FOR clause in
|
||||||
|
USE/FORCE/IGNORE INDEX index hint specification
|
||||||
|
*/
|
||||||
|
#define INDEX_HINT_MASK_JOIN (1)
|
||||||
|
#define INDEX_HINT_MASK_GROUP (1 << 1)
|
||||||
|
#define INDEX_HINT_MASK_ORDER (1 << 2)
|
||||||
|
|
||||||
|
#define INDEX_HINT_MASK_ALL (INDEX_HINT_MASK_JOIN | INDEX_HINT_MASK_GROUP | \
|
||||||
|
INDEX_HINT_MASK_ORDER)
|
||||||
|
|
||||||
|
/* Single element of an USE/FORCE/IGNORE INDEX list specified as a SQL hint */
|
||||||
|
class index_hint : public Sql_alloc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/* The type of the hint : USE/FORCE/IGNORE */
|
||||||
|
enum index_hint_type type;
|
||||||
|
/* Where the hit applies to. A bitmask of INDEX_HINT_MASK_<place> values */
|
||||||
|
index_clause_map clause;
|
||||||
|
/*
|
||||||
|
The index name. Empty (str=NULL) name represents an empty list
|
||||||
|
USE INDEX () clause
|
||||||
|
*/
|
||||||
|
LEX_STRING key_name;
|
||||||
|
|
||||||
|
index_hint (enum index_hint_type type_arg, index_clause_map clause_arg,
|
||||||
|
char *str, uint length) :
|
||||||
|
type(type_arg), clause(clause_arg)
|
||||||
|
{
|
||||||
|
key_name.str= str;
|
||||||
|
key_name.length= length;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The state of the lex parsing for selects
|
The state of the lex parsing for selects
|
||||||
|
|
||||||
|
@ -394,15 +435,12 @@ public:
|
||||||
virtual uint get_in_sum_expr();
|
virtual uint get_in_sum_expr();
|
||||||
virtual TABLE_LIST* get_table_list();
|
virtual TABLE_LIST* get_table_list();
|
||||||
virtual List<Item>* get_item_list();
|
virtual List<Item>* get_item_list();
|
||||||
virtual List<String>* get_use_index();
|
|
||||||
virtual List<String>* get_ignore_index();
|
|
||||||
virtual ulong get_table_join_options();
|
virtual ulong get_table_join_options();
|
||||||
virtual TABLE_LIST *add_table_to_list(THD *thd, Table_ident *table,
|
virtual TABLE_LIST *add_table_to_list(THD *thd, Table_ident *table,
|
||||||
LEX_STRING *alias,
|
LEX_STRING *alias,
|
||||||
ulong table_options,
|
ulong table_options,
|
||||||
thr_lock_type flags= TL_UNLOCK,
|
thr_lock_type flags= TL_UNLOCK,
|
||||||
List<String> *use_index= 0,
|
List<index_hint> *hints= 0,
|
||||||
List<String> *ignore_index= 0,
|
|
||||||
LEX_STRING *option= 0);
|
LEX_STRING *option= 0);
|
||||||
virtual void set_lock_for_tables(thr_lock_type lock_type) {}
|
virtual void set_lock_for_tables(thr_lock_type lock_type) {}
|
||||||
|
|
||||||
|
@ -532,8 +570,7 @@ public:
|
||||||
SQL_LIST table_list;
|
SQL_LIST table_list;
|
||||||
SQL_LIST group_list; /* GROUP BY clause. */
|
SQL_LIST group_list; /* GROUP BY clause. */
|
||||||
List<Item> item_list; /* list of fields & expressions */
|
List<Item> item_list; /* list of fields & expressions */
|
||||||
List<String> interval_list, use_index, *use_index_ptr,
|
List<String> interval_list;
|
||||||
ignore_index, *ignore_index_ptr;
|
|
||||||
bool is_item_list_lookup;
|
bool is_item_list_lookup;
|
||||||
/*
|
/*
|
||||||
Usualy it is pointer to ftfunc_list_alloc, but in union used to create fake
|
Usualy it is pointer to ftfunc_list_alloc, but in union used to create fake
|
||||||
|
@ -680,8 +717,7 @@ public:
|
||||||
LEX_STRING *alias,
|
LEX_STRING *alias,
|
||||||
ulong table_options,
|
ulong table_options,
|
||||||
thr_lock_type flags= TL_UNLOCK,
|
thr_lock_type flags= TL_UNLOCK,
|
||||||
List<String> *use_index= 0,
|
List<index_hint> *hints= 0,
|
||||||
List<String> *ignore_index= 0,
|
|
||||||
LEX_STRING *option= 0);
|
LEX_STRING *option= 0);
|
||||||
TABLE_LIST* get_table_list();
|
TABLE_LIST* get_table_list();
|
||||||
bool init_nested_join(THD *thd);
|
bool init_nested_join(THD *thd);
|
||||||
|
@ -690,8 +726,6 @@ public:
|
||||||
void add_joined_table(TABLE_LIST *table);
|
void add_joined_table(TABLE_LIST *table);
|
||||||
TABLE_LIST *convert_right_join();
|
TABLE_LIST *convert_right_join();
|
||||||
List<Item>* get_item_list();
|
List<Item>* get_item_list();
|
||||||
List<String>* get_use_index();
|
|
||||||
List<String>* get_ignore_index();
|
|
||||||
ulong get_table_join_options();
|
ulong get_table_join_options();
|
||||||
void set_lock_for_tables(thr_lock_type lock_type);
|
void set_lock_for_tables(thr_lock_type lock_type);
|
||||||
inline void init_order()
|
inline void init_order()
|
||||||
|
@ -731,6 +765,33 @@ public:
|
||||||
select lexes.
|
select lexes.
|
||||||
*/
|
*/
|
||||||
void cleanup_all_joins(bool full);
|
void cleanup_all_joins(bool full);
|
||||||
|
|
||||||
|
void set_index_hint_type(enum index_hint_type type, index_clause_map clause);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add a index hint to the tagged list of hints. The type and clause of the
|
||||||
|
hint will be the current ones (set by set_index_hint())
|
||||||
|
*/
|
||||||
|
bool add_index_hint (THD *thd, char *str, uint length);
|
||||||
|
|
||||||
|
/* make a list to hold index hints */
|
||||||
|
void alloc_index_hints (THD *thd);
|
||||||
|
/* read and clear the index hints */
|
||||||
|
List<index_hint>* pop_index_hints(void)
|
||||||
|
{
|
||||||
|
List<index_hint> *hints= index_hints;
|
||||||
|
index_hints= NULL;
|
||||||
|
return hints;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_index_hints(void) { index_hints= NULL; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* current index hint kind. used in filling up index_hints */
|
||||||
|
enum index_hint_type current_index_hint_type;
|
||||||
|
index_clause_map current_index_hint_clause;
|
||||||
|
/* a list of USE/FORCE/IGNORE INDEX */
|
||||||
|
List<index_hint> *index_hints;
|
||||||
};
|
};
|
||||||
typedef class st_select_lex SELECT_LEX;
|
typedef class st_select_lex SELECT_LEX;
|
||||||
|
|
||||||
|
|
|
@ -1417,8 +1417,7 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
|
||||||
/* 'parent_lex' is used in init_query() so it must be before it. */
|
/* 'parent_lex' is used in init_query() so it must be before it. */
|
||||||
sel->parent_lex= lex;
|
sel->parent_lex= lex;
|
||||||
sel->init_query();
|
sel->init_query();
|
||||||
if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ,
|
if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ))
|
||||||
(List<String> *) 0, (List<String> *) 0))
|
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
lex->query_tables_last= query_tables_last;
|
lex->query_tables_last= query_tables_last;
|
||||||
TABLE_LIST *table_list= (TABLE_LIST*) sel->table_list.first;
|
TABLE_LIST *table_list= (TABLE_LIST*) sel->table_list.first;
|
||||||
|
@ -4708,7 +4707,7 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
|
||||||
{
|
{
|
||||||
uint found=0;
|
uint found=0;
|
||||||
ulong found_access=0;
|
ulong found_access=0;
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
TABLE_LIST *org_tables= tables;
|
TABLE_LIST *org_tables= tables;
|
||||||
#endif
|
#endif
|
||||||
TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table();
|
TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table();
|
||||||
|
@ -5461,8 +5460,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||||
LEX_STRING *alias,
|
LEX_STRING *alias,
|
||||||
ulong table_options,
|
ulong table_options,
|
||||||
thr_lock_type lock_type,
|
thr_lock_type lock_type,
|
||||||
List<String> *use_index_arg,
|
List<index_hint> *index_hints_arg,
|
||||||
List<String> *ignore_index_arg,
|
|
||||||
LEX_STRING *option)
|
LEX_STRING *option)
|
||||||
{
|
{
|
||||||
register TABLE_LIST *ptr;
|
register TABLE_LIST *ptr;
|
||||||
|
@ -5537,12 +5535,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||||
}
|
}
|
||||||
ptr->select_lex= lex->current_select;
|
ptr->select_lex= lex->current_select;
|
||||||
ptr->cacheable_table= 1;
|
ptr->cacheable_table= 1;
|
||||||
if (use_index_arg)
|
ptr->index_hints= index_hints_arg;
|
||||||
ptr->use_index=(List<String> *) thd->memdup((gptr) use_index_arg,
|
|
||||||
sizeof(*use_index_arg));
|
|
||||||
if (ignore_index_arg)
|
|
||||||
ptr->ignore_index=(List<String> *) thd->memdup((gptr) ignore_index_arg,
|
|
||||||
sizeof(*ignore_index_arg));
|
|
||||||
ptr->option= option ? option->str : 0;
|
ptr->option= option ? option->str : 0;
|
||||||
/* check that used name is unique */
|
/* check that used name is unique */
|
||||||
if (lock_type != TL_IGNORE)
|
if (lock_type != TL_IGNORE)
|
||||||
|
|
|
@ -163,13 +163,15 @@ static COND *make_cond_for_table(COND *cond,table_map table,
|
||||||
static Item* part_of_refkey(TABLE *form,Field *field);
|
static Item* part_of_refkey(TABLE *form,Field *field);
|
||||||
uint find_shortest_key(TABLE *table, const key_map *usable_keys);
|
uint find_shortest_key(TABLE *table, const key_map *usable_keys);
|
||||||
static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,
|
static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,
|
||||||
ha_rows select_limit, bool no_changes);
|
ha_rows select_limit, bool no_changes,
|
||||||
|
key_map *map);
|
||||||
static bool list_contains_unique_index(TABLE *table,
|
static bool list_contains_unique_index(TABLE *table,
|
||||||
bool (*find_func) (Field *, void *), void *data);
|
bool (*find_func) (Field *, void *), void *data);
|
||||||
static bool find_field_in_item_list (Field *field, void *data);
|
static bool find_field_in_item_list (Field *field, void *data);
|
||||||
static bool find_field_in_order_list (Field *field, void *data);
|
static bool find_field_in_order_list (Field *field, void *data);
|
||||||
static int create_sort_index(THD *thd, JOIN *join, ORDER *order,
|
static int create_sort_index(THD *thd, JOIN *join, ORDER *order,
|
||||||
ha_rows filesort_limit, ha_rows select_limit);
|
ha_rows filesort_limit, ha_rows select_limit,
|
||||||
|
bool is_order_by);
|
||||||
static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields,
|
static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields,
|
||||||
Item *having);
|
Item *having);
|
||||||
static int remove_dup_with_compare(THD *thd, TABLE *entry, Field **field,
|
static int remove_dup_with_compare(THD *thd, TABLE *entry, Field **field,
|
||||||
|
@ -652,7 +654,7 @@ void JOIN::remove_subq_pushed_predicates(Item **where)
|
||||||
static void save_index_subquery_explain_info(JOIN_TAB *join_tab, Item* where)
|
static void save_index_subquery_explain_info(JOIN_TAB *join_tab, Item* where)
|
||||||
{
|
{
|
||||||
join_tab->packed_info= TAB_INFO_HAVE_VALUE;
|
join_tab->packed_info= TAB_INFO_HAVE_VALUE;
|
||||||
if (join_tab->table->used_keys.is_set(join_tab->ref.key))
|
if (join_tab->table->covering_keys.is_set(join_tab->ref.key))
|
||||||
join_tab->packed_info |= TAB_INFO_USING_INDEX;
|
join_tab->packed_info |= TAB_INFO_USING_INDEX;
|
||||||
if (where)
|
if (where)
|
||||||
join_tab->packed_info |= TAB_INFO_USING_WHERE;
|
join_tab->packed_info |= TAB_INFO_USING_WHERE;
|
||||||
|
@ -1024,14 +1026,15 @@ JOIN::optimize()
|
||||||
JOIN_TAB *tab= &join_tab[const_tables];
|
JOIN_TAB *tab= &join_tab[const_tables];
|
||||||
bool all_order_fields_used;
|
bool all_order_fields_used;
|
||||||
if (order)
|
if (order)
|
||||||
skip_sort_order= test_if_skip_sort_order(tab, order, select_limit, 1);
|
skip_sort_order= test_if_skip_sort_order(tab, order, select_limit, 1,
|
||||||
|
&tab->table->keys_in_use_for_order_by);
|
||||||
if ((group_list=create_distinct_group(thd, select_lex->ref_pointer_array,
|
if ((group_list=create_distinct_group(thd, select_lex->ref_pointer_array,
|
||||||
order, fields_list,
|
order, fields_list,
|
||||||
&all_order_fields_used)))
|
&all_order_fields_used)))
|
||||||
{
|
{
|
||||||
bool skip_group= (skip_sort_order &&
|
bool skip_group= (skip_sort_order &&
|
||||||
test_if_skip_sort_order(tab, group_list, select_limit,
|
test_if_skip_sort_order(tab, group_list, select_limit, 1,
|
||||||
1) != 0);
|
&tab->table->keys_in_use_for_group_by) != 0);
|
||||||
if ((skip_group && all_order_fields_used) ||
|
if ((skip_group && all_order_fields_used) ||
|
||||||
select_limit == HA_POS_ERROR ||
|
select_limit == HA_POS_ERROR ||
|
||||||
(order && !skip_sort_order))
|
(order && !skip_sort_order))
|
||||||
|
@ -1229,7 +1232,9 @@ JOIN::optimize()
|
||||||
((group_list &&
|
((group_list &&
|
||||||
(!simple_group ||
|
(!simple_group ||
|
||||||
!test_if_skip_sort_order(&join_tab[const_tables], group_list,
|
!test_if_skip_sort_order(&join_tab[const_tables], group_list,
|
||||||
unit->select_limit_cnt, 0))) ||
|
unit->select_limit_cnt, 0,
|
||||||
|
&join_tab[const_tables].table->
|
||||||
|
keys_in_use_for_group_by))) ||
|
||||||
select_distinct) &&
|
select_distinct) &&
|
||||||
tmp_table_param.quick_group && !procedure)
|
tmp_table_param.quick_group && !procedure)
|
||||||
{
|
{
|
||||||
|
@ -1331,7 +1336,7 @@ JOIN::optimize()
|
||||||
DBUG_PRINT("info",("Sorting for group"));
|
DBUG_PRINT("info",("Sorting for group"));
|
||||||
thd->proc_info="Sorting for group";
|
thd->proc_info="Sorting for group";
|
||||||
if (create_sort_index(thd, this, group_list,
|
if (create_sort_index(thd, this, group_list,
|
||||||
HA_POS_ERROR, HA_POS_ERROR) ||
|
HA_POS_ERROR, HA_POS_ERROR, FALSE) ||
|
||||||
alloc_group_fields(this, group_list) ||
|
alloc_group_fields(this, group_list) ||
|
||||||
make_sum_func_list(all_fields, fields_list, 1) ||
|
make_sum_func_list(all_fields, fields_list, 1) ||
|
||||||
setup_sum_funcs(thd, sum_funcs))
|
setup_sum_funcs(thd, sum_funcs))
|
||||||
|
@ -1348,7 +1353,7 @@ JOIN::optimize()
|
||||||
DBUG_PRINT("info",("Sorting for order"));
|
DBUG_PRINT("info",("Sorting for order"));
|
||||||
thd->proc_info="Sorting for order";
|
thd->proc_info="Sorting for order";
|
||||||
if (create_sort_index(thd, this, order,
|
if (create_sort_index(thd, this, order,
|
||||||
HA_POS_ERROR, HA_POS_ERROR))
|
HA_POS_ERROR, HA_POS_ERROR, TRUE))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
order=0;
|
order=0;
|
||||||
}
|
}
|
||||||
|
@ -1375,7 +1380,9 @@ JOIN::optimize()
|
||||||
{
|
{
|
||||||
/* Should always succeed */
|
/* Should always succeed */
|
||||||
if (test_if_skip_sort_order(&join_tab[const_tables],
|
if (test_if_skip_sort_order(&join_tab[const_tables],
|
||||||
order, unit->select_limit_cnt, 0))
|
order, unit->select_limit_cnt, 0,
|
||||||
|
&join_tab[const_tables].table->
|
||||||
|
keys_in_use_for_order_by))
|
||||||
order=0;
|
order=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1568,7 +1575,9 @@ JOIN::exec()
|
||||||
(const_tables == tables ||
|
(const_tables == tables ||
|
||||||
((simple_order || skip_sort_order) &&
|
((simple_order || skip_sort_order) &&
|
||||||
test_if_skip_sort_order(&join_tab[const_tables], order,
|
test_if_skip_sort_order(&join_tab[const_tables], order,
|
||||||
select_limit, 0))))
|
select_limit, 0,
|
||||||
|
&join_tab[const_tables].table->
|
||||||
|
keys_in_use_for_order_by))))
|
||||||
order=0;
|
order=0;
|
||||||
having= tmp_having;
|
having= tmp_having;
|
||||||
select_describe(this, need_tmp,
|
select_describe(this, need_tmp,
|
||||||
|
@ -1744,7 +1753,7 @@ JOIN::exec()
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
if (create_sort_index(thd, curr_join, curr_join->group_list,
|
if (create_sort_index(thd, curr_join, curr_join->group_list,
|
||||||
HA_POS_ERROR, HA_POS_ERROR) ||
|
HA_POS_ERROR, HA_POS_ERROR, FALSE) ||
|
||||||
make_group_fields(this, curr_join))
|
make_group_fields(this, curr_join))
|
||||||
{
|
{
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
@ -1960,7 +1969,8 @@ JOIN::exec()
|
||||||
curr_join->group_list : curr_join->order,
|
curr_join->group_list : curr_join->order,
|
||||||
curr_join->select_limit,
|
curr_join->select_limit,
|
||||||
(select_options & OPTION_FOUND_ROWS ?
|
(select_options & OPTION_FOUND_ROWS ?
|
||||||
HA_POS_ERROR : unit->select_limit_cnt)))
|
HA_POS_ERROR : unit->select_limit_cnt),
|
||||||
|
curr_join->group_list ? TRUE : FALSE))
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
sortorder= curr_join->sortorder;
|
sortorder= curr_join->sortorder;
|
||||||
if (curr_join->const_tables != curr_join->tables &&
|
if (curr_join->const_tables != curr_join->tables &&
|
||||||
|
@ -3964,7 +3974,7 @@ best_access_path(JOIN *join,
|
||||||
/* Limit the number of matched rows */
|
/* Limit the number of matched rows */
|
||||||
tmp= records;
|
tmp= records;
|
||||||
set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
|
set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
|
||||||
if (table->used_keys.is_set(key))
|
if (table->covering_keys.is_set(key))
|
||||||
{
|
{
|
||||||
/* we can use only index tree */
|
/* we can use only index tree */
|
||||||
uint keys_per_block= table->file->stats.block_size/2/
|
uint keys_per_block= table->file->stats.block_size/2/
|
||||||
|
@ -4131,7 +4141,7 @@ best_access_path(JOIN *join,
|
||||||
|
|
||||||
/* Limit the number of matched rows */
|
/* Limit the number of matched rows */
|
||||||
set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
|
set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
|
||||||
if (table->used_keys.is_set(key))
|
if (table->covering_keys.is_set(key))
|
||||||
{
|
{
|
||||||
/* we can use only index tree */
|
/* we can use only index tree */
|
||||||
uint keys_per_block= table->file->stats.block_size/2/
|
uint keys_per_block= table->file->stats.block_size/2/
|
||||||
|
@ -4190,7 +4200,7 @@ best_access_path(JOIN *join,
|
||||||
!(s->quick && best_key && s->quick->index == best_key->key && // (2)
|
!(s->quick && best_key && s->quick->index == best_key->key && // (2)
|
||||||
best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&// (2)
|
best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&// (2)
|
||||||
!((s->table->file->ha_table_flags() & HA_TABLE_SCAN_ON_INDEX) && // (3)
|
!((s->table->file->ha_table_flags() & HA_TABLE_SCAN_ON_INDEX) && // (3)
|
||||||
! s->table->used_keys.is_clear_all() && best_key) && // (3)
|
! s->table->covering_keys.is_clear_all() && best_key) && // (3)
|
||||||
!(s->table->force_index && best_key && !s->quick)) // (4)
|
!(s->table->force_index && best_key && !s->quick)) // (4)
|
||||||
{ // Check full join
|
{ // Check full join
|
||||||
ha_rows rnd_records= s->found_records;
|
ha_rows rnd_records= s->found_records;
|
||||||
|
@ -6096,10 +6106,7 @@ make_join_readinfo(JOIN *join, ulonglong options)
|
||||||
*/
|
*/
|
||||||
if (!ordered_set &&
|
if (!ordered_set &&
|
||||||
(table == join->sort_by_table &&
|
(table == join->sort_by_table &&
|
||||||
(!join->order || join->skip_sort_order ||
|
(!join->order || join->skip_sort_order)) ||
|
||||||
test_if_skip_sort_order(tab, join->order, join->select_limit,
|
|
||||||
1))
|
|
||||||
) ||
|
|
||||||
(join->sort_by_table == (TABLE *) 1 && i != join->const_tables))
|
(join->sort_by_table == (TABLE *) 1 && i != join->const_tables))
|
||||||
ordered_set= 1;
|
ordered_set= 1;
|
||||||
|
|
||||||
|
@ -6115,7 +6122,7 @@ make_join_readinfo(JOIN *join, ulonglong options)
|
||||||
table->status=STATUS_NO_RECORD;
|
table->status=STATUS_NO_RECORD;
|
||||||
tab->read_first_record= join_read_const;
|
tab->read_first_record= join_read_const;
|
||||||
tab->read_record.read_record= join_no_more_records;
|
tab->read_record.read_record= join_no_more_records;
|
||||||
if (table->used_keys.is_set(tab->ref.key) &&
|
if (table->covering_keys.is_set(tab->ref.key) &&
|
||||||
!table->no_keyread)
|
!table->no_keyread)
|
||||||
{
|
{
|
||||||
table->key_read=1;
|
table->key_read=1;
|
||||||
|
@ -6133,7 +6140,7 @@ make_join_readinfo(JOIN *join, ulonglong options)
|
||||||
tab->quick=0;
|
tab->quick=0;
|
||||||
tab->read_first_record= join_read_key;
|
tab->read_first_record= join_read_key;
|
||||||
tab->read_record.read_record= join_no_more_records;
|
tab->read_record.read_record= join_no_more_records;
|
||||||
if (table->used_keys.is_set(tab->ref.key) &&
|
if (table->covering_keys.is_set(tab->ref.key) &&
|
||||||
!table->no_keyread)
|
!table->no_keyread)
|
||||||
{
|
{
|
||||||
table->key_read=1;
|
table->key_read=1;
|
||||||
|
@ -6150,7 +6157,7 @@ make_join_readinfo(JOIN *join, ulonglong options)
|
||||||
}
|
}
|
||||||
delete tab->quick;
|
delete tab->quick;
|
||||||
tab->quick=0;
|
tab->quick=0;
|
||||||
if (table->used_keys.is_set(tab->ref.key) &&
|
if (table->covering_keys.is_set(tab->ref.key) &&
|
||||||
!table->no_keyread)
|
!table->no_keyread)
|
||||||
{
|
{
|
||||||
table->key_read=1;
|
table->key_read=1;
|
||||||
|
@ -6236,15 +6243,15 @@ make_join_readinfo(JOIN *join, ulonglong options)
|
||||||
{
|
{
|
||||||
if (tab->select && tab->select->quick &&
|
if (tab->select && tab->select->quick &&
|
||||||
tab->select->quick->index != MAX_KEY && //not index_merge
|
tab->select->quick->index != MAX_KEY && //not index_merge
|
||||||
table->used_keys.is_set(tab->select->quick->index))
|
table->covering_keys.is_set(tab->select->quick->index))
|
||||||
{
|
{
|
||||||
table->key_read=1;
|
table->key_read=1;
|
||||||
table->file->extra(HA_EXTRA_KEYREAD);
|
table->file->extra(HA_EXTRA_KEYREAD);
|
||||||
}
|
}
|
||||||
else if (!table->used_keys.is_clear_all() &&
|
else if (!table->covering_keys.is_clear_all() &&
|
||||||
!(tab->select && tab->select->quick))
|
!(tab->select && tab->select->quick))
|
||||||
{ // Only read index tree
|
{ // Only read index tree
|
||||||
tab->index=find_shortest_key(table, & table->used_keys);
|
tab->index=find_shortest_key(table, & table->covering_keys);
|
||||||
tab->read_first_record= join_read_first;
|
tab->read_first_record= join_read_first;
|
||||||
tab->type=JT_NEXT; // Read with index_first / index_next
|
tab->type=JT_NEXT; // Read with index_first / index_next
|
||||||
}
|
}
|
||||||
|
@ -9378,7 +9385,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||||
table->copy_blobs= 1;
|
table->copy_blobs= 1;
|
||||||
table->in_use= thd;
|
table->in_use= thd;
|
||||||
table->quick_keys.init();
|
table->quick_keys.init();
|
||||||
table->used_keys.init();
|
table->covering_keys.init();
|
||||||
table->keys_in_use_for_query.init();
|
table->keys_in_use_for_query.init();
|
||||||
|
|
||||||
table->s= share;
|
table->s= share;
|
||||||
|
@ -11003,7 +11010,7 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!table->key_read && table->used_keys.is_set(tab->ref.key) &&
|
if (!table->key_read && table->covering_keys.is_set(tab->ref.key) &&
|
||||||
!table->no_keyread &&
|
!table->no_keyread &&
|
||||||
(int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY)
|
(int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY)
|
||||||
{
|
{
|
||||||
|
@ -11310,7 +11317,7 @@ join_read_first(JOIN_TAB *tab)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
TABLE *table=tab->table;
|
TABLE *table=tab->table;
|
||||||
if (!table->key_read && table->used_keys.is_set(tab->index) &&
|
if (!table->key_read && table->covering_keys.is_set(tab->index) &&
|
||||||
!table->no_keyread)
|
!table->no_keyread)
|
||||||
{
|
{
|
||||||
table->key_read=1;
|
table->key_read=1;
|
||||||
|
@ -11349,7 +11356,7 @@ join_read_last(JOIN_TAB *tab)
|
||||||
{
|
{
|
||||||
TABLE *table=tab->table;
|
TABLE *table=tab->table;
|
||||||
int error;
|
int error;
|
||||||
if (!table->key_read && table->used_keys.is_set(tab->index) &&
|
if (!table->key_read && table->covering_keys.is_set(tab->index) &&
|
||||||
!table->no_keyread)
|
!table->no_keyread)
|
||||||
{
|
{
|
||||||
table->key_read=1;
|
table->key_read=1;
|
||||||
|
@ -12373,7 +12380,7 @@ find_field_in_item_list (Field *field, void *data)
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
|
test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
|
||||||
bool no_changes)
|
bool no_changes, key_map *map)
|
||||||
{
|
{
|
||||||
int ref_key;
|
int ref_key;
|
||||||
uint ref_key_parts;
|
uint ref_key_parts;
|
||||||
|
@ -12383,14 +12390,11 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
|
||||||
DBUG_ENTER("test_if_skip_sort_order");
|
DBUG_ENTER("test_if_skip_sort_order");
|
||||||
LINT_INIT(ref_key_parts);
|
LINT_INIT(ref_key_parts);
|
||||||
|
|
||||||
/* Check which keys can be used to resolve ORDER BY. */
|
|
||||||
usable_keys= table->keys_in_use_for_query;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Keys disabled by ALTER TABLE ... DISABLE KEYS should have already
|
Keys disabled by ALTER TABLE ... DISABLE KEYS should have already
|
||||||
been taken into account.
|
been taken into account.
|
||||||
*/
|
*/
|
||||||
DBUG_ASSERT(usable_keys.is_subset(table->s->keys_in_use));
|
usable_keys= *map;
|
||||||
|
|
||||||
for (ORDER *tmp_order=order; tmp_order ; tmp_order=tmp_order->next)
|
for (ORDER *tmp_order=order; tmp_order ; tmp_order=tmp_order->next)
|
||||||
{
|
{
|
||||||
|
@ -12448,8 +12452,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
|
||||||
If using index only read, only consider other possible index only
|
If using index only read, only consider other possible index only
|
||||||
keys
|
keys
|
||||||
*/
|
*/
|
||||||
if (table->used_keys.is_set(ref_key))
|
if (table->covering_keys.is_set(ref_key))
|
||||||
usable_keys.intersect(table->used_keys);
|
usable_keys.intersect(table->covering_keys);
|
||||||
if ((new_ref_key= test_if_subkey(order, table, ref_key, ref_key_parts,
|
if ((new_ref_key= test_if_subkey(order, table, ref_key, ref_key_parts,
|
||||||
&usable_keys)) < MAX_KEY)
|
&usable_keys)) < MAX_KEY)
|
||||||
{
|
{
|
||||||
|
@ -12564,7 +12568,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
|
||||||
if (select_limit >= table->file->stats.records)
|
if (select_limit >= table->file->stats.records)
|
||||||
{
|
{
|
||||||
keys= *table->file->keys_to_use_for_scanning();
|
keys= *table->file->keys_to_use_for_scanning();
|
||||||
keys.merge(table->used_keys);
|
keys.merge(table->covering_keys);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We are adding here also the index specified in FORCE INDEX clause,
|
We are adding here also the index specified in FORCE INDEX clause,
|
||||||
|
@ -12592,7 +12596,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
|
||||||
tab->read_first_record= (flag > 0 ? join_read_first:
|
tab->read_first_record= (flag > 0 ? join_read_first:
|
||||||
join_read_last);
|
join_read_last);
|
||||||
tab->type=JT_NEXT; // Read with index_first(), index_next()
|
tab->type=JT_NEXT; // Read with index_first(), index_next()
|
||||||
if (table->used_keys.is_set(nr))
|
if (table->covering_keys.is_set(nr))
|
||||||
{
|
{
|
||||||
table->key_read=1;
|
table->key_read=1;
|
||||||
table->file->extra(HA_EXTRA_KEYREAD);
|
table->file->extra(HA_EXTRA_KEYREAD);
|
||||||
|
@ -12618,6 +12622,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
|
||||||
filesort_limit Max number of rows that needs to be sorted
|
filesort_limit Max number of rows that needs to be sorted
|
||||||
select_limit Max number of rows in final output
|
select_limit Max number of rows in final output
|
||||||
Used to decide if we should use index or not
|
Used to decide if we should use index or not
|
||||||
|
is_order_by true if we are sorting on ORDER BY, false if GROUP BY
|
||||||
|
Used to decide if we should use index or not
|
||||||
|
|
||||||
|
|
||||||
IMPLEMENTATION
|
IMPLEMENTATION
|
||||||
|
@ -12636,7 +12642,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
|
||||||
|
|
||||||
static int
|
static int
|
||||||
create_sort_index(THD *thd, JOIN *join, ORDER *order,
|
create_sort_index(THD *thd, JOIN *join, ORDER *order,
|
||||||
ha_rows filesort_limit, ha_rows select_limit)
|
ha_rows filesort_limit, ha_rows select_limit,
|
||||||
|
bool is_order_by)
|
||||||
{
|
{
|
||||||
uint length= 0;
|
uint length= 0;
|
||||||
ha_rows examined_rows;
|
ha_rows examined_rows;
|
||||||
|
@ -12657,7 +12664,9 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
|
||||||
*/
|
*/
|
||||||
if ((order != join->group_list ||
|
if ((order != join->group_list ||
|
||||||
!(join->select_options & SELECT_BIG_RESULT)) &&
|
!(join->select_options & SELECT_BIG_RESULT)) &&
|
||||||
test_if_skip_sort_order(tab,order,select_limit,0))
|
test_if_skip_sort_order(tab,order,select_limit,0,
|
||||||
|
is_order_by ? &table->keys_in_use_for_order_by :
|
||||||
|
&table->keys_in_use_for_group_by))
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
for (ORDER *ord= join->order; ord; ord= ord->next)
|
for (ORDER *ord= join->order; ord; ord= ord->next)
|
||||||
length++;
|
length++;
|
||||||
|
@ -15285,7 +15294,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
|
||||||
/* Build "Extra" field and add it to item_list. */
|
/* Build "Extra" field and add it to item_list. */
|
||||||
my_bool key_read=table->key_read;
|
my_bool key_read=table->key_read;
|
||||||
if ((tab->type == JT_NEXT || tab->type == JT_CONST) &&
|
if ((tab->type == JT_NEXT || tab->type == JT_CONST) &&
|
||||||
table->used_keys.is_set(tab->index))
|
table->covering_keys.is_set(tab->index))
|
||||||
key_read=1;
|
key_read=1;
|
||||||
if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT &&
|
if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT &&
|
||||||
!((QUICK_ROR_INTERSECT_SELECT*)tab->select->quick)->need_to_fetch_row)
|
!((QUICK_ROR_INTERSECT_SELECT*)tab->select->quick)->need_to_fetch_row)
|
||||||
|
|
|
@ -1221,7 +1221,7 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
|
||||||
if (key_part->field &&
|
if (key_part->field &&
|
||||||
(key_part->length !=
|
(key_part->length !=
|
||||||
table->field[key_part->fieldnr-1]->key_length() &&
|
table->field[key_part->fieldnr-1]->key_length() &&
|
||||||
!(key_info->flags & HA_FULLTEXT)))
|
!(key_info->flags & (HA_FULLTEXT | HA_SPATIAL))))
|
||||||
{
|
{
|
||||||
char *end;
|
char *end;
|
||||||
buff[0] = '(';
|
buff[0] = '(';
|
||||||
|
@ -2266,8 +2266,7 @@ int make_table_list(THD *thd, SELECT_LEX *sel,
|
||||||
ident_table.length= strlen(table);
|
ident_table.length= strlen(table);
|
||||||
table_ident= new Table_ident(thd, ident_db, ident_table, 1);
|
table_ident= new Table_ident(thd, ident_db, ident_table, 1);
|
||||||
sel->init_query();
|
sel->init_query();
|
||||||
if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ,
|
if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ))
|
||||||
(List<String> *) 0, (List<String> *) 0))
|
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -5033,8 +5032,7 @@ int make_schema_select(THD *thd, SELECT_LEX *sel,
|
||||||
strlen(schema_table->table_name), 0);
|
strlen(schema_table->table_name), 0);
|
||||||
if (schema_table->old_format(thd, schema_table) || /* Handle old syntax */
|
if (schema_table->old_format(thd, schema_table) || /* Handle old syntax */
|
||||||
!sel->add_table_to_list(thd, new Table_ident(thd, db, table, 0),
|
!sel->add_table_to_list(thd, new Table_ident(thd, db, table, 0),
|
||||||
0, 0, TL_READ, (List<String> *) 0,
|
0, 0, TL_READ))
|
||||||
(List<String> *) 0))
|
|
||||||
{
|
{
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2791,6 +2791,12 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||||
{
|
{
|
||||||
column->length*= sql_field->charset->mbmaxlen;
|
column->length*= sql_field->charset->mbmaxlen;
|
||||||
|
|
||||||
|
if (key->type == Key::SPATIAL && column->length)
|
||||||
|
{
|
||||||
|
my_error(ER_WRONG_SUB_KEY, MYF(0));
|
||||||
|
DBUG_RETURN(-1);
|
||||||
|
}
|
||||||
|
|
||||||
if (f_is_blob(sql_field->pack_flag) ||
|
if (f_is_blob(sql_field->pack_flag) ||
|
||||||
(f_is_geom(sql_field->pack_flag) && key->type != Key::SPATIAL))
|
(f_is_geom(sql_field->pack_flag) && key->type != Key::SPATIAL))
|
||||||
{
|
{
|
||||||
|
@ -2884,6 +2890,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||||
}
|
}
|
||||||
else if (!f_is_geom(sql_field->pack_flag) &&
|
else if (!f_is_geom(sql_field->pack_flag) &&
|
||||||
(column->length > length ||
|
(column->length > length ||
|
||||||
|
!Field::type_can_have_key_part (sql_field->sql_type) ||
|
||||||
((f_is_packed(sql_field->pack_flag) ||
|
((f_is_packed(sql_field->pack_flag) ||
|
||||||
((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
|
((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
|
||||||
(key_info->flags & HA_NOSAME))) &&
|
(key_info->flags & HA_NOSAME))) &&
|
||||||
|
@ -5859,6 +5866,8 @@ view_err:
|
||||||
*/
|
*/
|
||||||
if (!Field::type_can_have_key_part(cfield->field->type()) ||
|
if (!Field::type_can_have_key_part(cfield->field->type()) ||
|
||||||
!Field::type_can_have_key_part(cfield->sql_type) ||
|
!Field::type_can_have_key_part(cfield->sql_type) ||
|
||||||
|
/* spatial keys can't have sub-key length */
|
||||||
|
(key_info->flags & HA_SPATIAL) ||
|
||||||
(cfield->field->field_length == key_part_length &&
|
(cfield->field->field_length == key_part_length &&
|
||||||
!f_is_blob(key_part->key_type)) ||
|
!f_is_blob(key_part->key_type)) ||
|
||||||
(cfield->length && (cfield->length < key_part_length /
|
(cfield->length && (cfield->length < key_part_length /
|
||||||
|
|
|
@ -126,7 +126,7 @@ int mysql_update(THD *thd,
|
||||||
#endif
|
#endif
|
||||||
uint table_count= 0;
|
uint table_count= 0;
|
||||||
ha_rows updated, found;
|
ha_rows updated, found;
|
||||||
key_map old_used_keys;
|
key_map old_covering_keys;
|
||||||
TABLE *table;
|
TABLE *table;
|
||||||
SQL_SELECT *select;
|
SQL_SELECT *select;
|
||||||
READ_RECORD info;
|
READ_RECORD info;
|
||||||
|
@ -165,8 +165,8 @@ int mysql_update(THD *thd,
|
||||||
thd->proc_info="init";
|
thd->proc_info="init";
|
||||||
table= table_list->table;
|
table= table_list->table;
|
||||||
|
|
||||||
/* Calculate "table->used_keys" based on the WHERE */
|
/* Calculate "table->covering_keys" based on the WHERE */
|
||||||
table->used_keys= table->s->keys_in_use;
|
table->covering_keys= table->s->keys_in_use;
|
||||||
table->quick_keys.clear_all();
|
table->quick_keys.clear_all();
|
||||||
|
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
|
@ -176,7 +176,7 @@ int mysql_update(THD *thd,
|
||||||
if (mysql_prepare_update(thd, table_list, &conds, order_num, order))
|
if (mysql_prepare_update(thd, table_list, &conds, order_num, order))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
old_used_keys= table->used_keys; // Keys used in WHERE
|
old_covering_keys= table->covering_keys; // Keys used in WHERE
|
||||||
/* Check the fields we are going to modify */
|
/* Check the fields we are going to modify */
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
table_list->grant.want_privilege= table->grant.want_privilege= want_privilege;
|
table_list->grant.want_privilege= table->grant.want_privilege= want_privilege;
|
||||||
|
@ -229,7 +229,7 @@ int mysql_update(THD *thd,
|
||||||
limit= 0; // Impossible WHERE
|
limit= 0; // Impossible WHERE
|
||||||
}
|
}
|
||||||
// Don't count on usage of 'only index' when calculating which key to use
|
// Don't count on usage of 'only index' when calculating which key to use
|
||||||
table->used_keys.clear_all();
|
table->covering_keys.clear_all();
|
||||||
|
|
||||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||||
if (prune_partitions(thd, table, conds))
|
if (prune_partitions(thd, table, conds))
|
||||||
|
@ -304,7 +304,7 @@ int mysql_update(THD *thd,
|
||||||
We can't update table directly; We must first search after all
|
We can't update table directly; We must first search after all
|
||||||
matching rows before updating the table!
|
matching rows before updating the table!
|
||||||
*/
|
*/
|
||||||
if (used_index < MAX_KEY && old_used_keys.is_set(used_index))
|
if (used_index < MAX_KEY && old_covering_keys.is_set(used_index))
|
||||||
{
|
{
|
||||||
table->key_read=1;
|
table->key_read=1;
|
||||||
table->mark_columns_used_by_index(used_index);
|
table->mark_columns_used_by_index(used_index);
|
||||||
|
@ -1092,7 +1092,7 @@ int multi_update::prepare(List<Item> ¬_used_values,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We have to check values after setup_tables to get used_keys right in
|
We have to check values after setup_tables to get covering_keys right in
|
||||||
reference tables
|
reference tables
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1119,7 +1119,7 @@ int multi_update::prepare(List<Item> ¬_used_values,
|
||||||
update.link_in_list((byte*) tl, (byte**) &tl->next_local);
|
update.link_in_list((byte*) tl, (byte**) &tl->next_local);
|
||||||
tl->shared= table_count++;
|
tl->shared= table_count++;
|
||||||
table->no_keyread=1;
|
table->no_keyread=1;
|
||||||
table->used_keys.clear_all();
|
table->covering_keys.clear_all();
|
||||||
table->pos_in_table_list= tl;
|
table->pos_in_table_list= tl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
162
sql/sql_yacc.yy
162
sql/sql_yacc.yy
|
@ -481,6 +481,7 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal,
|
||||||
struct st_lex *lex;
|
struct st_lex *lex;
|
||||||
sp_head *sphead;
|
sp_head *sphead;
|
||||||
struct p_elem_val *p_elem_value;
|
struct p_elem_val *p_elem_value;
|
||||||
|
enum index_hint_type index_hint;
|
||||||
}
|
}
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
@ -1162,7 +1163,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||||
btree_or_rtree
|
btree_or_rtree
|
||||||
|
|
||||||
%type <string_list>
|
%type <string_list>
|
||||||
key_usage_list using_list
|
using_list
|
||||||
|
|
||||||
%type <key_part>
|
%type <key_part>
|
||||||
key_part
|
key_part
|
||||||
|
@ -1233,7 +1234,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||||
opt_column_list grant_privileges grant_ident grant_list grant_option
|
opt_column_list grant_privileges grant_ident grant_list grant_option
|
||||||
object_privilege object_privilege_list user_list rename_list
|
object_privilege object_privilege_list user_list rename_list
|
||||||
clear_privileges flush_options flush_option
|
clear_privileges flush_options flush_option
|
||||||
equal optional_braces opt_key_definition key_usage_list2
|
equal optional_braces
|
||||||
opt_mi_check_type opt_to mi_check_types normal_join
|
opt_mi_check_type opt_to mi_check_types normal_join
|
||||||
db_to_db table_to_table_list table_to_table opt_table_list opt_as
|
db_to_db table_to_table_list table_to_table opt_table_list opt_as
|
||||||
handler_rkey_function handler_read_or_scan
|
handler_rkey_function handler_read_or_scan
|
||||||
|
@ -1269,6 +1270,8 @@ END_OF_INPUT
|
||||||
%type <spblock> sp_decls sp_decl
|
%type <spblock> sp_decls sp_decl
|
||||||
%type <lex> sp_cursor_stmt
|
%type <lex> sp_cursor_stmt
|
||||||
%type <spname> sp_name
|
%type <spname> sp_name
|
||||||
|
%type <index_hint> index_hint_type
|
||||||
|
%type <num> index_hint_clause
|
||||||
|
|
||||||
%type <NONE>
|
%type <NONE>
|
||||||
'-' '+' '*' '/' '%' '(' ')'
|
'-' '+' '*' '/' '%' '(' ')'
|
||||||
|
@ -5940,12 +5943,8 @@ keycache_list:
|
||||||
assign_to_keycache:
|
assign_to_keycache:
|
||||||
table_ident cache_keys_spec
|
table_ident cache_keys_spec
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
if (!Select->add_table_to_list(YYTHD, $1, NULL, 0, TL_READ,
|
||||||
SELECT_LEX *sel= &lex->select_lex;
|
Select->pop_index_hints()))
|
||||||
if (!sel->add_table_to_list(lex->thd, $1, NULL, 0,
|
|
||||||
TL_READ,
|
|
||||||
sel->get_use_index(),
|
|
||||||
(List<String> *)0))
|
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
@ -5972,33 +5971,26 @@ preload_list:
|
||||||
preload_keys:
|
preload_keys:
|
||||||
table_ident cache_keys_spec opt_ignore_leaves
|
table_ident cache_keys_spec opt_ignore_leaves
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
if (!Select->add_table_to_list(YYTHD, $1, NULL, $3, TL_READ,
|
||||||
SELECT_LEX *sel= &lex->select_lex;
|
Select->pop_index_hints()))
|
||||||
if (!sel->add_table_to_list(lex->thd, $1, NULL, $3,
|
|
||||||
TL_READ,
|
|
||||||
sel->get_use_index(),
|
|
||||||
(List<String> *)0))
|
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
cache_keys_spec:
|
cache_keys_spec:
|
||||||
{ Select->interval_list.empty(); }
|
{
|
||||||
cache_key_list_or_empty
|
Lex->select_lex.alloc_index_hints(YYTHD);
|
||||||
{
|
Select->set_index_hint_type(INDEX_HINT_USE,
|
||||||
LEX *lex=Lex;
|
global_system_variables.old_mode ?
|
||||||
SELECT_LEX *sel= &lex->select_lex;
|
INDEX_HINT_MASK_JOIN :
|
||||||
sel->use_index= sel->interval_list;
|
INDEX_HINT_MASK_ALL);
|
||||||
}
|
}
|
||||||
|
cache_key_list_or_empty
|
||||||
;
|
;
|
||||||
|
|
||||||
cache_key_list_or_empty:
|
cache_key_list_or_empty:
|
||||||
/* empty */ { Lex->select_lex.use_index_ptr= 0; }
|
/* empty */ { }
|
||||||
| opt_key_or_index '(' key_usage_list2 ')'
|
| key_or_index '(' opt_key_usage_list ')'
|
||||||
{
|
|
||||||
SELECT_LEX *sel= &Lex->select_lex;
|
|
||||||
sel->use_index_ptr= &sel->use_index;
|
|
||||||
}
|
|
||||||
;
|
;
|
||||||
|
|
||||||
opt_ignore_leaves:
|
opt_ignore_leaves:
|
||||||
|
@ -7371,20 +7363,16 @@ normal_join:
|
||||||
table_factor:
|
table_factor:
|
||||||
{
|
{
|
||||||
SELECT_LEX *sel= Select;
|
SELECT_LEX *sel= Select;
|
||||||
sel->use_index_ptr=sel->ignore_index_ptr=0;
|
|
||||||
sel->table_join_options= 0;
|
sel->table_join_options= 0;
|
||||||
}
|
}
|
||||||
table_ident opt_table_alias opt_key_definition
|
table_ident opt_table_alias opt_key_definition
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
if (!($$= Select->add_table_to_list(YYTHD, $2, $3,
|
||||||
SELECT_LEX *sel= lex->current_select;
|
Select->get_table_join_options(),
|
||||||
if (!($$= sel->add_table_to_list(lex->thd, $2, $3,
|
Lex->lock_option,
|
||||||
sel->get_table_join_options(),
|
Select->pop_index_hints())))
|
||||||
lex->lock_option,
|
|
||||||
sel->get_use_index(),
|
|
||||||
sel->get_ignore_index())))
|
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
sel->add_joined_table($$);
|
Select->add_joined_table($$);
|
||||||
}
|
}
|
||||||
| '{' ident table_ref LEFT OUTER JOIN_SYM table_ref
|
| '{' ident table_ref LEFT OUTER JOIN_SYM table_ref
|
||||||
ON
|
ON
|
||||||
|
@ -7453,8 +7441,7 @@ table_factor:
|
||||||
lex->current_select= sel= unit->outer_select();
|
lex->current_select= sel= unit->outer_select();
|
||||||
if (!($$= sel->
|
if (!($$= sel->
|
||||||
add_table_to_list(lex->thd, new Table_ident(unit), $6, 0,
|
add_table_to_list(lex->thd, new Table_ident(unit), $6, 0,
|
||||||
TL_READ,(List<String> *)0,
|
TL_READ)))
|
||||||
(List<String> *)0)))
|
|
||||||
|
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
sel->add_joined_table($$);
|
sel->add_joined_table($$);
|
||||||
|
@ -7553,52 +7540,67 @@ opt_outer:
|
||||||
/* empty */ {}
|
/* empty */ {}
|
||||||
| OUTER {};
|
| OUTER {};
|
||||||
|
|
||||||
|
index_hint_clause:
|
||||||
|
/* empty */
|
||||||
|
{
|
||||||
|
$$= global_system_variables.old_mode ?
|
||||||
|
INDEX_HINT_MASK_JOIN : INDEX_HINT_MASK_ALL;
|
||||||
|
}
|
||||||
|
| FOR_SYM JOIN_SYM { $$= INDEX_HINT_MASK_JOIN; }
|
||||||
|
| FOR_SYM ORDER_SYM BY { $$= INDEX_HINT_MASK_ORDER; }
|
||||||
|
| FOR_SYM GROUP_SYM BY { $$= INDEX_HINT_MASK_GROUP; }
|
||||||
|
;
|
||||||
|
|
||||||
|
index_hint_type:
|
||||||
|
FORCE_SYM { $$= INDEX_HINT_FORCE; }
|
||||||
|
| IGNORE_SYM { $$= INDEX_HINT_IGNORE; }
|
||||||
|
;
|
||||||
|
|
||||||
|
index_hint_definition:
|
||||||
|
index_hint_type key_or_index index_hint_clause
|
||||||
|
{
|
||||||
|
Select->set_index_hint_type($1, $3);
|
||||||
|
}
|
||||||
|
'(' key_usage_list ')';
|
||||||
|
| USE_SYM key_or_index index_hint_clause
|
||||||
|
{
|
||||||
|
Select->set_index_hint_type(INDEX_HINT_USE, $3);
|
||||||
|
}
|
||||||
|
'(' opt_key_usage_list ')';
|
||||||
|
|
||||||
|
|
||||||
|
index_hints_list:
|
||||||
|
index_hint_definition
|
||||||
|
| index_hints_list index_hint_definition
|
||||||
|
;
|
||||||
|
|
||||||
|
opt_index_hints_list:
|
||||||
|
/* empty */
|
||||||
|
| { Select->alloc_index_hints(YYTHD); } index_hints_list
|
||||||
|
;
|
||||||
|
|
||||||
opt_key_definition:
|
opt_key_definition:
|
||||||
/* empty */ {}
|
{ Select->clear_index_hints(); }
|
||||||
| USE_SYM key_usage_list
|
opt_index_hints_list
|
||||||
{
|
;
|
||||||
SELECT_LEX *sel= Select;
|
|
||||||
sel->use_index= *$2;
|
opt_key_usage_list:
|
||||||
sel->use_index_ptr= &sel->use_index;
|
/* empty */ { Select->add_index_hint(YYTHD, NULL, 0); }
|
||||||
}
|
| key_usage_list {}
|
||||||
| FORCE_SYM key_usage_list
|
;
|
||||||
{
|
|
||||||
SELECT_LEX *sel= Select;
|
key_usage_element:
|
||||||
sel->use_index= *$2;
|
ident { Select->add_index_hint(YYTHD, $1.str, $1.length); }
|
||||||
sel->use_index_ptr= &sel->use_index;
|
| PRIMARY_SYM
|
||||||
sel->table_join_options|= TL_OPTION_FORCE_INDEX;
|
{
|
||||||
}
|
Select->add_index_hint(YYTHD, (char *)"PRIMARY", 7);
|
||||||
| IGNORE_SYM key_usage_list
|
}
|
||||||
{
|
;
|
||||||
SELECT_LEX *sel= Select;
|
|
||||||
sel->ignore_index= *$2;
|
|
||||||
sel->ignore_index_ptr= &sel->ignore_index;
|
|
||||||
};
|
|
||||||
|
|
||||||
key_usage_list:
|
key_usage_list:
|
||||||
key_or_index { Select->interval_list.empty(); }
|
key_usage_element
|
||||||
'(' key_list_or_empty ')'
|
| key_usage_list ',' key_usage_element
|
||||||
{ $$= &Select->interval_list; }
|
;
|
||||||
;
|
|
||||||
|
|
||||||
key_list_or_empty:
|
|
||||||
/* empty */ {}
|
|
||||||
| key_usage_list2 {}
|
|
||||||
;
|
|
||||||
|
|
||||||
key_usage_list2:
|
|
||||||
key_usage_list2 ',' ident
|
|
||||||
{ Select->
|
|
||||||
interval_list.push_back(new (YYTHD->mem_root) String((const char*) $3.str, $3.length,
|
|
||||||
system_charset_info)); }
|
|
||||||
| ident
|
|
||||||
{ Select->
|
|
||||||
interval_list.push_back(new (YYTHD->mem_root) String((const char*) $1.str, $1.length,
|
|
||||||
system_charset_info)); }
|
|
||||||
| PRIMARY_SYM
|
|
||||||
{ Select->
|
|
||||||
interval_list.push_back(new (YYTHD->mem_root) String("PRIMARY", 7,
|
|
||||||
system_charset_info)); };
|
|
||||||
|
|
||||||
using_list:
|
using_list:
|
||||||
ident
|
ident
|
||||||
|
|
171
sql/table.cc
171
sql/table.cc
|
@ -1338,7 +1338,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
|
||||||
if (!(outparam->alias= my_strdup(alias, MYF(MY_WME))))
|
if (!(outparam->alias= my_strdup(alias, MYF(MY_WME))))
|
||||||
goto err;
|
goto err;
|
||||||
outparam->quick_keys.init();
|
outparam->quick_keys.init();
|
||||||
outparam->used_keys.init();
|
outparam->covering_keys.init();
|
||||||
outparam->keys_in_use_for_query.init();
|
outparam->keys_in_use_for_query.init();
|
||||||
|
|
||||||
/* Allocate handler */
|
/* Allocate handler */
|
||||||
|
@ -4120,6 +4120,175 @@ Item_subselect *st_table_list::containing_subselect()
|
||||||
return (select_lex ? select_lex->master_unit()->item : 0);
|
return (select_lex ? select_lex->master_unit()->item : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Compiles the tagged hints list and fills up the bitmasks.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
process_index_hints()
|
||||||
|
table the TABLE to operate on.
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
The parser collects the index hints for each table in a "tagged list"
|
||||||
|
(st_table_list::index_hints). Using the information in this tagged list
|
||||||
|
this function sets the members st_table::keys_in_use_for_query,
|
||||||
|
st_table::keys_in_use_for_group_by, st_table::keys_in_use_for_order_by,
|
||||||
|
st_table::force_index and st_table::covering_keys.
|
||||||
|
|
||||||
|
Current implementation of the runtime does not allow mixing FORCE INDEX
|
||||||
|
and USE INDEX, so this is checked here. Then the FORCE INDEX list
|
||||||
|
(if non-empty) is appended to the USE INDEX list and a flag is set.
|
||||||
|
|
||||||
|
Multiple hints of the same kind are processed so that each clause
|
||||||
|
is applied to what is computed in the previous clause.
|
||||||
|
For example:
|
||||||
|
USE INDEX (i1) USE INDEX (i2)
|
||||||
|
is equivalent to
|
||||||
|
USE INDEX (i1,i2)
|
||||||
|
and means "consider only i1 and i2".
|
||||||
|
|
||||||
|
Similarly
|
||||||
|
USE INDEX () USE INDEX (i1)
|
||||||
|
is equivalent to
|
||||||
|
USE INDEX (i1)
|
||||||
|
and means "consider only the index i1"
|
||||||
|
|
||||||
|
It is OK to have the same index several times, e.g. "USE INDEX (i1,i1)" is
|
||||||
|
not an error.
|
||||||
|
|
||||||
|
Different kind of hints (USE/FORCE/IGNORE) are processed in the following
|
||||||
|
order:
|
||||||
|
1. All indexes in USE (or FORCE) INDEX are added to the mask.
|
||||||
|
2. All IGNORE INDEX
|
||||||
|
|
||||||
|
e.g. "USE INDEX i1, IGNORE INDEX i1, USE INDEX i1" will not use i1 at all
|
||||||
|
as if we had "USE INDEX i1, USE INDEX i1, IGNORE INDEX i1".
|
||||||
|
|
||||||
|
As an optimization if there is a covering index, and we have
|
||||||
|
IGNORE INDEX FOR GROUP/ORDER, and this index is used for the JOIN part,
|
||||||
|
then we have to ignore the IGNORE INDEX FROM GROUP/ORDER.
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
FALSE no errors found
|
||||||
|
TRUE found and reported an error.
|
||||||
|
*/
|
||||||
|
bool st_table_list::process_index_hints(TABLE *table)
|
||||||
|
{
|
||||||
|
/* initialize the result variables */
|
||||||
|
table->keys_in_use_for_query= table->keys_in_use_for_group_by=
|
||||||
|
table->keys_in_use_for_order_by= table->s->keys_in_use;
|
||||||
|
|
||||||
|
/* index hint list processing */
|
||||||
|
if (index_hints)
|
||||||
|
{
|
||||||
|
key_map index_join[INDEX_HINT_FORCE + 1];
|
||||||
|
key_map index_order[INDEX_HINT_FORCE + 1];
|
||||||
|
key_map index_group[INDEX_HINT_FORCE + 1];
|
||||||
|
index_hint *hint;
|
||||||
|
int type;
|
||||||
|
bool have_empty_use_join= FALSE, have_empty_use_order= FALSE,
|
||||||
|
have_empty_use_group= FALSE;
|
||||||
|
List_iterator <index_hint> iter(*index_hints);
|
||||||
|
|
||||||
|
/* initialize temporary variables used to collect hints of each kind */
|
||||||
|
for (type= INDEX_HINT_IGNORE; type <= INDEX_HINT_FORCE; type++)
|
||||||
|
{
|
||||||
|
index_join[type].clear_all();
|
||||||
|
index_order[type].clear_all();
|
||||||
|
index_group[type].clear_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* iterate over the hints list */
|
||||||
|
while ((hint= iter++))
|
||||||
|
{
|
||||||
|
uint pos;
|
||||||
|
|
||||||
|
/* process empty USE INDEX () */
|
||||||
|
if (hint->type == INDEX_HINT_USE && !hint->key_name.str)
|
||||||
|
{
|
||||||
|
if (hint->clause & INDEX_HINT_MASK_JOIN)
|
||||||
|
{
|
||||||
|
index_join[hint->type].clear_all();
|
||||||
|
have_empty_use_join= TRUE;
|
||||||
|
}
|
||||||
|
if (hint->clause & INDEX_HINT_MASK_ORDER)
|
||||||
|
{
|
||||||
|
index_order[hint->type].clear_all();
|
||||||
|
have_empty_use_order= TRUE;
|
||||||
|
}
|
||||||
|
if (hint->clause & INDEX_HINT_MASK_GROUP)
|
||||||
|
{
|
||||||
|
index_group[hint->type].clear_all();
|
||||||
|
have_empty_use_group= TRUE;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check if an index with the given name exists and get his offset in
|
||||||
|
the keys bitmask for the table
|
||||||
|
*/
|
||||||
|
if (table->s->keynames.type_names == 0 ||
|
||||||
|
(pos= find_type(&table->s->keynames, hint->key_name.str,
|
||||||
|
hint->key_name.length, 1)) <= 0)
|
||||||
|
{
|
||||||
|
my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), hint->key_name.str, alias);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos--;
|
||||||
|
|
||||||
|
/* add to the appropriate clause mask */
|
||||||
|
if (hint->clause & INDEX_HINT_MASK_JOIN)
|
||||||
|
index_join[hint->type].set_bit (pos);
|
||||||
|
if (hint->clause & INDEX_HINT_MASK_ORDER)
|
||||||
|
index_order[hint->type].set_bit (pos);
|
||||||
|
if (hint->clause & INDEX_HINT_MASK_GROUP)
|
||||||
|
index_group[hint->type].set_bit (pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cannot mix USE INDEX and FORCE INDEX */
|
||||||
|
if ((!index_join[INDEX_HINT_FORCE].is_clear_all() ||
|
||||||
|
!index_order[INDEX_HINT_FORCE].is_clear_all() ||
|
||||||
|
!index_group[INDEX_HINT_FORCE].is_clear_all()) &&
|
||||||
|
(!index_join[INDEX_HINT_USE].is_clear_all() || have_empty_use_join ||
|
||||||
|
!index_order[INDEX_HINT_USE].is_clear_all() || have_empty_use_order ||
|
||||||
|
!index_group[INDEX_HINT_USE].is_clear_all() || have_empty_use_group))
|
||||||
|
{
|
||||||
|
my_error(ER_WRONG_USAGE, MYF(0), index_hint_type_name[INDEX_HINT_USE],
|
||||||
|
index_hint_type_name[INDEX_HINT_FORCE]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* process FORCE INDEX as USE INDEX with a flag */
|
||||||
|
if (!index_join[INDEX_HINT_FORCE].is_clear_all() ||
|
||||||
|
!index_order[INDEX_HINT_FORCE].is_clear_all() ||
|
||||||
|
!index_group[INDEX_HINT_FORCE].is_clear_all())
|
||||||
|
{
|
||||||
|
table->force_index= TRUE;
|
||||||
|
index_join[INDEX_HINT_USE].merge(index_join[INDEX_HINT_FORCE]);
|
||||||
|
index_order[INDEX_HINT_USE].merge(index_order[INDEX_HINT_FORCE]);
|
||||||
|
index_group[INDEX_HINT_USE].merge(index_group[INDEX_HINT_FORCE]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* apply USE INDEX */
|
||||||
|
if (!index_join[INDEX_HINT_USE].is_clear_all() || have_empty_use_join)
|
||||||
|
table->keys_in_use_for_query.intersect(index_join[INDEX_HINT_USE]);
|
||||||
|
if (!index_order[INDEX_HINT_USE].is_clear_all() || have_empty_use_order)
|
||||||
|
table->keys_in_use_for_order_by.intersect (index_order[INDEX_HINT_USE]);
|
||||||
|
if (!index_group[INDEX_HINT_USE].is_clear_all() || have_empty_use_group)
|
||||||
|
table->keys_in_use_for_group_by.intersect (index_group[INDEX_HINT_USE]);
|
||||||
|
|
||||||
|
/* apply IGNORE INDEX */
|
||||||
|
table->keys_in_use_for_query.subtract (index_join[INDEX_HINT_IGNORE]);
|
||||||
|
table->keys_in_use_for_order_by.subtract (index_order[INDEX_HINT_IGNORE]);
|
||||||
|
table->keys_in_use_for_group_by.subtract (index_group[INDEX_HINT_IGNORE]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make sure covering_keys don't include indexes disabled with a hint */
|
||||||
|
table->covering_keys.intersect(table->keys_in_use_for_query);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
** Instansiate templates
|
** Instansiate templates
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
29
sql/table.h
29
sql/table.h
|
@ -299,6 +299,12 @@ typedef struct st_table_share
|
||||||
|
|
||||||
|
|
||||||
/* Information for one open table */
|
/* Information for one open table */
|
||||||
|
enum index_hint_type
|
||||||
|
{
|
||||||
|
INDEX_HINT_IGNORE,
|
||||||
|
INDEX_HINT_USE,
|
||||||
|
INDEX_HINT_FORCE
|
||||||
|
};
|
||||||
|
|
||||||
struct st_table {
|
struct st_table {
|
||||||
st_table() {} /* Remove gcc warning */
|
st_table() {} /* Remove gcc warning */
|
||||||
|
@ -318,8 +324,12 @@ struct st_table {
|
||||||
byte *write_row_record; /* Used as optimisation in
|
byte *write_row_record; /* Used as optimisation in
|
||||||
THD::write_row */
|
THD::write_row */
|
||||||
byte *insert_values; /* used by INSERT ... UPDATE */
|
byte *insert_values; /* used by INSERT ... UPDATE */
|
||||||
key_map quick_keys, used_keys;
|
/*
|
||||||
|
Map of keys that can be used to retrieve all data from this table
|
||||||
|
needed by the query without reading the row.
|
||||||
|
*/
|
||||||
|
key_map covering_keys;
|
||||||
|
key_map quick_keys, merge_keys;
|
||||||
/*
|
/*
|
||||||
A set of keys that can be used in the query that references this
|
A set of keys that can be used in the query that references this
|
||||||
table.
|
table.
|
||||||
|
@ -332,7 +342,10 @@ struct st_table {
|
||||||
The set is implemented as a bitmap.
|
The set is implemented as a bitmap.
|
||||||
*/
|
*/
|
||||||
key_map keys_in_use_for_query;
|
key_map keys_in_use_for_query;
|
||||||
key_map merge_keys;
|
/* Map of keys that can be used to calculate GROUP BY without sorting */
|
||||||
|
key_map keys_in_use_for_group_by;
|
||||||
|
/* Map of keys that can be used to calculate ORDER BY without sorting */
|
||||||
|
key_map keys_in_use_for_order_by;
|
||||||
KEY *key_info; /* data of keys in database */
|
KEY *key_info; /* data of keys in database */
|
||||||
|
|
||||||
Field *next_number_field; /* Set if next_number is activated */
|
Field *next_number_field; /* Set if next_number is activated */
|
||||||
|
@ -666,6 +679,7 @@ public:
|
||||||
(TABLE_LIST::join_using_fields != NULL)
|
(TABLE_LIST::join_using_fields != NULL)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
class index_hint;
|
||||||
typedef struct st_table_list
|
typedef struct st_table_list
|
||||||
{
|
{
|
||||||
st_table_list() {} /* Remove gcc warning */
|
st_table_list() {} /* Remove gcc warning */
|
||||||
|
@ -722,7 +736,7 @@ typedef struct st_table_list
|
||||||
*/
|
*/
|
||||||
struct st_table_list *next_name_resolution_table;
|
struct st_table_list *next_name_resolution_table;
|
||||||
/* Index names in a "... JOIN ... USE/IGNORE INDEX ..." clause. */
|
/* Index names in a "... JOIN ... USE/IGNORE INDEX ..." clause. */
|
||||||
List<String> *use_index, *ignore_index;
|
List<index_hint> *index_hints;
|
||||||
TABLE *table; /* opened table */
|
TABLE *table; /* opened table */
|
||||||
uint table_id; /* table id (from binlog) for opened table */
|
uint table_id; /* table id (from binlog) for opened table */
|
||||||
/*
|
/*
|
||||||
|
@ -896,6 +910,13 @@ typedef struct st_table_list
|
||||||
void reinit_before_use(THD *thd);
|
void reinit_before_use(THD *thd);
|
||||||
Item_subselect *containing_subselect();
|
Item_subselect *containing_subselect();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Compiles the tagged hints list and fills up st_table::keys_in_use_for_query,
|
||||||
|
st_table::keys_in_use_for_group_by, st_table::keys_in_use_for_order_by,
|
||||||
|
st_table::force_index and st_table::covering_keys.
|
||||||
|
*/
|
||||||
|
bool process_index_hints(TABLE *table);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool prep_check_option(THD *thd, uint8 check_opt_type);
|
bool prep_check_option(THD *thd, uint8 check_opt_type);
|
||||||
bool prep_where(THD *thd, Item **conds, bool no_where_clause);
|
bool prep_where(THD *thd, Item **conds, bool no_where_clause);
|
||||||
|
|
|
@ -1156,23 +1156,22 @@ int ha_myisam::assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt)
|
||||||
KEY_CACHE *new_key_cache= check_opt->key_cache;
|
KEY_CACHE *new_key_cache= check_opt->key_cache;
|
||||||
const char *errmsg= 0;
|
const char *errmsg= 0;
|
||||||
int error= HA_ADMIN_OK;
|
int error= HA_ADMIN_OK;
|
||||||
ulonglong map= ~(ulonglong) 0;
|
ulonglong map;
|
||||||
TABLE_LIST *table_list= table->pos_in_table_list;
|
TABLE_LIST *table_list= table->pos_in_table_list;
|
||||||
DBUG_ENTER("ha_myisam::assign_to_keycache");
|
DBUG_ENTER("ha_myisam::assign_to_keycache");
|
||||||
|
|
||||||
/* Check validity of the index references */
|
table->keys_in_use_for_query.clear_all();
|
||||||
if (table_list->use_index)
|
|
||||||
|
if (table_list->process_index_hints(table))
|
||||||
{
|
{
|
||||||
/* We only come here when the user did specify an index map */
|
errmsg= thd->net.last_error;
|
||||||
key_map kmap;
|
error= HA_ADMIN_FAILED;
|
||||||
if (get_key_map_from_key_list(&kmap, table, table_list->use_index))
|
goto err;
|
||||||
{
|
|
||||||
errmsg= thd->net.last_error;
|
|
||||||
error= HA_ADMIN_FAILED;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
map= kmap.to_ulonglong();
|
|
||||||
}
|
}
|
||||||
|
map= ~(ulonglong) 0;
|
||||||
|
if (!table->keys_in_use_for_query.is_clear_all())
|
||||||
|
/* use all keys if there's no list specified by the user through hints */
|
||||||
|
map= table->keys_in_use_for_query.to_ulonglong();
|
||||||
|
|
||||||
if ((error= mi_assign_to_key_cache(file, map, new_key_cache)))
|
if ((error= mi_assign_to_key_cache(file, map, new_key_cache)))
|
||||||
{
|
{
|
||||||
|
@ -1208,27 +1207,27 @@ int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
const char *errmsg;
|
const char *errmsg;
|
||||||
ulonglong map= ~(ulonglong) 0;
|
ulonglong map;
|
||||||
TABLE_LIST *table_list= table->pos_in_table_list;
|
TABLE_LIST *table_list= table->pos_in_table_list;
|
||||||
my_bool ignore_leaves= table_list->ignore_leaves;
|
my_bool ignore_leaves= table_list->ignore_leaves;
|
||||||
|
|
||||||
DBUG_ENTER("ha_myisam::preload_keys");
|
DBUG_ENTER("ha_myisam::preload_keys");
|
||||||
|
|
||||||
/* Check validity of the index references */
|
table->keys_in_use_for_query.clear_all();
|
||||||
if (table_list->use_index)
|
|
||||||
|
if (table_list->process_index_hints(table))
|
||||||
{
|
{
|
||||||
key_map kmap;
|
errmsg= thd->net.last_error;
|
||||||
get_key_map_from_key_list(&kmap, table, table_list->use_index);
|
error= HA_ADMIN_FAILED;
|
||||||
if (kmap.is_set_all())
|
goto err;
|
||||||
{
|
|
||||||
errmsg= thd->net.last_error;
|
|
||||||
error= HA_ADMIN_FAILED;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (!kmap.is_clear_all())
|
|
||||||
map= kmap.to_ulonglong();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
map= ~(ulonglong) 0;
|
||||||
|
/* Check validity of the index references */
|
||||||
|
if (!table->keys_in_use_for_query.is_clear_all())
|
||||||
|
/* use all keys if there's no list specified by the user through hints */
|
||||||
|
map= table->keys_in_use_for_query.to_ulonglong();
|
||||||
|
|
||||||
mi_extra(file, HA_EXTRA_PRELOAD_BUFFER_SIZE,
|
mi_extra(file, HA_EXTRA_PRELOAD_BUFFER_SIZE,
|
||||||
(void *) &thd->variables.preload_buff_size);
|
(void *) &thd->variables.preload_buff_size);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue