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;
|
||||
alter table t1 change t t text;
|
||||
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);
|
||||
INSERT INTO t1 VALUES ('test');
|
||||
SELECT LENGTH(s) FROM t1;
|
||||
|
|
|
@ -25,10 +25,11 @@ insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
|
|||
check table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
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
|
||||
teststring
|
||||
teststring
|
||||
teststring
|
||||
select * from t1 where text1='teststring' or text1 like 'teststring_%';
|
||||
text1
|
||||
teststring
|
||||
|
@ -48,10 +49,11 @@ alter table t1 modify text1 char(32) binary not null;
|
|||
check table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
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
|
||||
teststring
|
||||
teststring
|
||||
teststring
|
||||
select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
|
||||
concat('|', text1, '|')
|
||||
|teststring |
|
||||
|
@ -132,10 +134,11 @@ concat('|', text1, '|')
|
|||
drop table t1;
|
||||
create table t1 (text1 varchar(32) not NULL, KEY key1 using BTREE (text1)) engine=heap;
|
||||
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
|
||||
teststring
|
||||
teststring
|
||||
teststring
|
||||
select * from t1 where text1='teststring' or text1 like 'teststring_%';
|
||||
text1
|
||||
teststring
|
||||
|
|
|
@ -1,26 +1,12 @@
|
|||
flush logs;
|
||||
set global expire_logs_days = 3;
|
||||
show variables like 'log%';
|
||||
show variables like 'log_bin%';
|
||||
Variable_name Value
|
||||
log ON
|
||||
log_bin OFF
|
||||
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;
|
||||
show variables like 'log%';
|
||||
show variables like 'log_bin%';
|
||||
Variable_name Value
|
||||
log ON
|
||||
log_bin OFF
|
||||
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;
|
||||
|
|
|
@ -10,7 +10,7 @@ t1 CREATE TABLE `t1` (
|
|||
`fid` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`g` geometry NOT NULL,
|
||||
PRIMARY KEY (`fid`),
|
||||
SPATIAL KEY `g` (`g`(32))
|
||||
SPATIAL KEY `g` (`g`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(150 150, 150 150)'));
|
||||
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,
|
||||
`g` geometry NOT NULL,
|
||||
PRIMARY KEY (`fid`),
|
||||
SPATIAL KEY `g` (`g`(32))
|
||||
SPATIAL KEY `g` (`g`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=101 DEFAULT CHARSET=latin1
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
|
@ -803,7 +803,7 @@ CREATE TABLE t2 (geom GEOMETRY NOT NULL, SPATIAL KEY gk(geom));
|
|||
INSERT INTO t2 SELECT GeomFromText(st) FROM t1;
|
||||
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
|
||||
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:
|
||||
Warning 1101 BLOB/TEXT column 'geometry' can't have a default value
|
||||
INSERT INTO t1 (geometry) VALUES
|
||||
|
@ -820,7 +820,7 @@ test.t1 check status OK
|
|||
drop table t1;
|
||||
CREATE TABLE t1 (
|
||||
c1 geometry NOT NULL default '',
|
||||
SPATIAL KEY i1 (c1(32))
|
||||
SPATIAL KEY i1 (c1)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
Warnings:
|
||||
Warning 1101 BLOB/TEXT column 'c1' can't have a default value
|
||||
|
@ -836,7 +836,7 @@ test.t1 check status OK
|
|||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (
|
||||
c1 geometry NOT NULL default '',
|
||||
SPATIAL KEY i1 (c1(32))
|
||||
SPATIAL KEY i1 (c1)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
Warnings:
|
||||
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,
|
||||
spatial_point point NOT NULL,
|
||||
PRIMARY KEY(id),
|
||||
SPATIAL KEY (spatial_point(32))
|
||||
SPATIAL KEY (spatial_point)
|
||||
)ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
|
||||
INSERT INTO t1 (c2, c1, c3, spatial_point) VALUES
|
||||
('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
|
||||
DROP TABLE t1;
|
||||
SET SQL_MODE = '';
|
||||
CREATE TABLE t1 (a INT, b INT, KEY(a));
|
||||
INSERT INTO t1 VALUES (1, 1), (2, 2), (3,3), (4,4);
|
||||
EXPLAIN SELECT a, SUM(b) FROM t1 GROUP BY a LIMIT 2;
|
||||
CREATE TABLE t1 (a INT, b INT,
|
||||
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;
|
||||
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
|
||||
1 SIMPLE t1 index NULL a 5 NULL 4
|
||||
EXPLAIN SELECT a, SUM(b) FROM t1 IGNORE INDEX (a) GROUP BY a LIMIT 2;
|
||||
1 SIMPLE t1 range PRIMARY,i2 PRIMARY 4 NULL 2 Using where; Using index
|
||||
EXPLAIN SELECT a FROM t1 WHERE a < 2 ORDER BY a;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using temporary; Using filesort
|
||||
DROP TABLE t1;
|
||||
1 SIMPLE t1 range PRIMARY,i2 PRIMARY 4 NULL 2 Using where; Using index
|
||||
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
|
||||
1 SIMPLE t1 system NULL NULL NULL NULL 1
|
||||
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
|
||||
9 2.6667
|
||||
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));
|
||||
INSERT INTO t1 VALUES (1,1),(2,2);
|
||||
CREATE TABLE t2 (a INT, b INT, KEY a (a,b));
|
||||
|
|
|
@ -3933,4 +3933,42 @@ cc cc 7
|
|||
aa aa 2
|
||||
aa aa 2
|
||||
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
|
||||
|
|
|
@ -3873,3 +3873,16 @@ id_1
|
|||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
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;
|
||||
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
|
||||
#
|
||||
|
|
|
@ -16,7 +16,8 @@ drop table if exists t1;
|
|||
create table t1 (text1 varchar(32) not NULL, KEY key1 (text1));
|
||||
insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
|
||||
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 > 'teststring\t';
|
||||
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;
|
||||
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 > 'teststring\t';
|
||||
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;
|
||||
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 >= 'teststring\t';
|
||||
select * from t1 order by text1;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#
|
||||
flush logs;
|
||||
set global expire_logs_days = 3;
|
||||
show variables like 'log%';
|
||||
show variables like 'log_bin%';
|
||||
flush logs;
|
||||
show variables like 'log%';
|
||||
show variables like 'log_bin%';
|
||||
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;
|
||||
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
|
||||
(PolygonFromText('POLYGON((-18.6086111000 -66.9327777000, -18.6055555000
|
||||
|
@ -192,7 +192,7 @@ drop table t1;
|
|||
#
|
||||
CREATE TABLE t1 (
|
||||
c1 geometry NOT NULL default '',
|
||||
SPATIAL KEY i1 (c1(32))
|
||||
SPATIAL KEY i1 (c1)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
INSERT INTO t1 (c1) VALUES (
|
||||
PolygonFromText('POLYGON((-18.6086111000 -66.9327777000,
|
||||
|
@ -206,7 +206,7 @@ DROP TABLE t1;
|
|||
#
|
||||
CREATE TABLE t1 (
|
||||
c1 geometry NOT NULL default '',
|
||||
SPATIAL KEY i1 (c1(32))
|
||||
SPATIAL KEY i1 (c1)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
INSERT INTO t1 (c1) VALUES (
|
||||
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,
|
||||
spatial_point point NOT NULL,
|
||||
PRIMARY KEY(id),
|
||||
SPATIAL KEY (spatial_point(32))
|
||||
SPATIAL KEY (spatial_point)
|
||||
)ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
|
||||
#
|
||||
INSERT INTO t1 (c2, c1, c3, spatial_point) VALUES
|
||||
|
|
|
@ -757,10 +757,66 @@ SET SQL_MODE = '';
|
|||
# Bug #21174: Index degrades sort performance and
|
||||
# optimizer does not honor IGNORE INDEX
|
||||
#
|
||||
CREATE TABLE t1 (a INT, b INT, KEY(a));
|
||||
INSERT INTO t1 VALUES (1, 1), (2, 2), (3,3), (4,4);
|
||||
CREATE TABLE t1 (a INT, b INT,
|
||||
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, SUM(b) FROM t1 IGNORE INDEX (a) GROUP BY a LIMIT 2;
|
||||
EXPLAIN SELECT a FROM t1
|
||||
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);
|
||||
|
||||
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;
|
||||
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
|
||||
#
|
||||
|
|
|
@ -3299,4 +3299,51 @@ SELECT * FROM t1 LEFT JOIN t2 ON t1.name=t2.name;
|
|||
|
||||
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
|
||||
|
|
|
@ -2736,3 +2736,15 @@ DROP TABLE t1;
|
|||
DROP TABLE t2;
|
||||
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_VAR_STRING:
|
||||
case MYSQL_TYPE_STRING:
|
||||
case MYSQL_TYPE_GEOMETRY:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
|
|
|
@ -1374,7 +1374,10 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length,
|
|||
}
|
||||
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:
|
||||
sortorder->length=sortorder->item->max_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 */
|
||||
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
|
||||
The function returns a pointer to an item that is taken from
|
||||
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
|
||||
'this' is returned
|
||||
|
||||
|
@ -4134,7 +4138,8 @@ bool Item_field::set_no_const_sub(byte *arg)
|
|||
of the thransformer method.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
|
@ -4142,6 +4147,14 @@ Item *Item_field::replace_equal_field(byte *arg)
|
|||
{
|
||||
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();
|
||||
if (subst && !field->eq(subst->field))
|
||||
return subst;
|
||||
|
|
|
@ -1811,7 +1811,11 @@ public:
|
|||
str_value.length(), collation.collation);
|
||||
}
|
||||
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);
|
||||
// to prevent drop fixed flag (no need parent cleanup call)
|
||||
void cleanup() {}
|
||||
|
|
|
@ -2021,7 +2021,6 @@ inline void setup_table_map(TABLE *table, TABLE_LIST *table_list, uint tablenr)
|
|||
table->const_table= 0;
|
||||
table->null_row= 0;
|
||||
table->status= STATUS_NO_RECORD;
|
||||
table->keys_in_use_for_query= table->s->keys_in_use;
|
||||
table->maybe_null= table_list->outer_join;
|
||||
TABLE_LIST *embedding= table_list->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->map= (table_map) 1 << tablenr;
|
||||
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_THREAD_HANDLING,
|
||||
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*) &max_system_variables.net_write_timeout, 0, GET_ULONG,
|
||||
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,
|
||||
"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,
|
||||
|
|
|
@ -2111,9 +2111,9 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
|
|||
param.key_parts_end=key_parts;
|
||||
|
||||
/* 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,
|
||||
key_for_use) +
|
||||
(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);
|
||||
|
||||
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);
|
||||
if (param->is_ror_scan)
|
||||
|
@ -9012,7 +9012,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
|
|||
cur_index_info++, cur_index++)
|
||||
{
|
||||
/* 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;
|
||||
|
||||
/*
|
||||
|
|
|
@ -1851,8 +1851,6 @@ bool reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
|
|||
table->const_table=0;
|
||||
table->null_row= table->maybe_null= table->force_index= 0;
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -2271,9 +2269,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
|||
table->const_table=0;
|
||||
table->null_row= table->maybe_null= table->force_index= 0;
|
||||
table->status=STATUS_NO_RECORD;
|
||||
table->keys_in_use_for_query= table->s->keys_in_use;
|
||||
table->insert_values= 0;
|
||||
table->used_keys= table->s->keys_for_keyread;
|
||||
table->fulltext_searched= 0;
|
||||
table->file->ft_handler= 0;
|
||||
if (table->timestamp_field)
|
||||
|
@ -2358,8 +2354,6 @@ static bool reopen_table(TABLE *table)
|
|||
tmp.null_row= table->null_row;
|
||||
tmp.maybe_null= table->maybe_null;
|
||||
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;
|
||||
|
||||
|
@ -3820,7 +3814,7 @@ static void update_field_dependencies(THD *thd, Field *field, TABLE *table)
|
|||
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);
|
||||
|
||||
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;
|
||||
/* Mark field_1 used for table cache. */
|
||||
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);
|
||||
}
|
||||
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;
|
||||
/* Mark field_2 used for table cache. */
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -5704,30 +5698,8 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
|
|||
tablenr= 0;
|
||||
}
|
||||
setup_table_map(table, table_list, tablenr);
|
||||
table->used_keys= table->s->keys_for_keyread;
|
||||
table->merge_keys.clear_all();
|
||||
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 (table_list->process_index_hints(table))
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
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);
|
||||
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);
|
||||
}
|
||||
if (tables->is_natural_join)
|
||||
|
@ -6027,7 +5999,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
|
|||
if (field_table)
|
||||
{
|
||||
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->used_fields++;
|
||||
}
|
||||
|
|
|
@ -243,6 +243,11 @@ struct system_variables
|
|||
|
||||
my_bool low_priority_updates;
|
||||
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 engine_condition_pushdown;
|
||||
my_bool innodb_table_locks;
|
||||
|
@ -278,6 +283,7 @@ struct system_variables
|
|||
DATE_TIME_FORMAT *datetime_format;
|
||||
DATE_TIME_FORMAT *time_format;
|
||||
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 */
|
||||
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'
|
||||
select=make_select(table, 0, 0, conds, 0, &error);
|
||||
if (error)
|
||||
|
@ -553,7 +553,7 @@ multi_delete::initialize_tables(JOIN *join)
|
|||
tbl->no_keyread=1;
|
||||
/* Don't use record cache */
|
||||
tbl->no_cache= 1;
|
||||
tbl->used_keys.clear_all();
|
||||
tbl->covering_keys.clear_all();
|
||||
if (tbl->file->has_transactions())
|
||||
transactional_tables= 1;
|
||||
else
|
||||
|
|
|
@ -567,7 +567,7 @@ SQL_SELECT *prepare_simple_select(THD *thd, Item *cond,
|
|||
cond->fix_fields(thd, &cond); // can never fail
|
||||
|
||||
/* 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);
|
||||
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
|
||||
};
|
||||
|
||||
/*
|
||||
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)
|
||||
{
|
||||
|
@ -1201,7 +1212,6 @@ void st_select_lex::init_select()
|
|||
group_list.empty();
|
||||
type= db= 0;
|
||||
having= 0;
|
||||
use_index_ptr= ignore_index_ptr= 0;
|
||||
table_join_options= 0;
|
||||
in_sum_expr= with_wild= 0;
|
||||
options= 0;
|
||||
|
@ -1209,7 +1219,6 @@ void st_select_lex::init_select()
|
|||
braces= 0;
|
||||
expr_list.empty();
|
||||
interval_list.empty();
|
||||
use_index.empty();
|
||||
ftfunc_list_alloc.empty();
|
||||
inner_sum_func_list= 0;
|
||||
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; }
|
||||
TABLE_LIST* st_select_lex_node::get_table_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; }
|
||||
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,
|
||||
TABLE_LIST *st_select_lex_node::add_table_to_list (THD *thd, Table_ident *table,
|
||||
LEX_STRING *alias,
|
||||
ulong table_join_options,
|
||||
thr_lock_type flags,
|
||||
List<String> *use_index,
|
||||
List<String> *ignore_index,
|
||||
List<index_hint> *hints,
|
||||
LEX_STRING *option)
|
||||
{
|
||||
return 0;
|
||||
|
@ -1550,19 +1556,6 @@ List<Item>* st_select_lex::get_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()
|
||||
{
|
||||
return table_join_options;
|
||||
|
@ -2328,3 +2321,61 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds,
|
|||
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
|
||||
};
|
||||
|
||||
/*
|
||||
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
|
||||
|
||||
|
@ -394,15 +435,12 @@ public:
|
|||
virtual uint get_in_sum_expr();
|
||||
virtual TABLE_LIST* get_table_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 TABLE_LIST *add_table_to_list(THD *thd, Table_ident *table,
|
||||
LEX_STRING *alias,
|
||||
ulong table_options,
|
||||
thr_lock_type flags= TL_UNLOCK,
|
||||
List<String> *use_index= 0,
|
||||
List<String> *ignore_index= 0,
|
||||
List<index_hint> *hints= 0,
|
||||
LEX_STRING *option= 0);
|
||||
virtual void set_lock_for_tables(thr_lock_type lock_type) {}
|
||||
|
||||
|
@ -532,8 +570,7 @@ public:
|
|||
SQL_LIST table_list;
|
||||
SQL_LIST group_list; /* GROUP BY clause. */
|
||||
List<Item> item_list; /* list of fields & expressions */
|
||||
List<String> interval_list, use_index, *use_index_ptr,
|
||||
ignore_index, *ignore_index_ptr;
|
||||
List<String> interval_list;
|
||||
bool is_item_list_lookup;
|
||||
/*
|
||||
Usualy it is pointer to ftfunc_list_alloc, but in union used to create fake
|
||||
|
@ -680,8 +717,7 @@ public:
|
|||
LEX_STRING *alias,
|
||||
ulong table_options,
|
||||
thr_lock_type flags= TL_UNLOCK,
|
||||
List<String> *use_index= 0,
|
||||
List<String> *ignore_index= 0,
|
||||
List<index_hint> *hints= 0,
|
||||
LEX_STRING *option= 0);
|
||||
TABLE_LIST* get_table_list();
|
||||
bool init_nested_join(THD *thd);
|
||||
|
@ -690,8 +726,6 @@ public:
|
|||
void add_joined_table(TABLE_LIST *table);
|
||||
TABLE_LIST *convert_right_join();
|
||||
List<Item>* get_item_list();
|
||||
List<String>* get_use_index();
|
||||
List<String>* get_ignore_index();
|
||||
ulong get_table_join_options();
|
||||
void set_lock_for_tables(thr_lock_type lock_type);
|
||||
inline void init_order()
|
||||
|
@ -731,6 +765,33 @@ public:
|
|||
select lexes.
|
||||
*/
|
||||
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;
|
||||
|
||||
|
|
|
@ -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. */
|
||||
sel->parent_lex= lex;
|
||||
sel->init_query();
|
||||
if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ,
|
||||
(List<String> *) 0, (List<String> *) 0))
|
||||
if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ))
|
||||
DBUG_RETURN(1);
|
||||
lex->query_tables_last= query_tables_last;
|
||||
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;
|
||||
ulong found_access=0;
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
TABLE_LIST *org_tables= tables;
|
||||
#endif
|
||||
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,
|
||||
ulong table_options,
|
||||
thr_lock_type lock_type,
|
||||
List<String> *use_index_arg,
|
||||
List<String> *ignore_index_arg,
|
||||
List<index_hint> *index_hints_arg,
|
||||
LEX_STRING *option)
|
||||
{
|
||||
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->cacheable_table= 1;
|
||||
if (use_index_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->index_hints= index_hints_arg;
|
||||
ptr->option= option ? option->str : 0;
|
||||
/* check that used name is unique */
|
||||
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);
|
||||
uint find_shortest_key(TABLE *table, const key_map *usable_keys);
|
||||
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,
|
||||
bool (*find_func) (Field *, void *), 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 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,
|
||||
Item *having);
|
||||
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)
|
||||
{
|
||||
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;
|
||||
if (where)
|
||||
join_tab->packed_info |= TAB_INFO_USING_WHERE;
|
||||
|
@ -1024,14 +1026,15 @@ JOIN::optimize()
|
|||
JOIN_TAB *tab= &join_tab[const_tables];
|
||||
bool all_order_fields_used;
|
||||
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,
|
||||
order, fields_list,
|
||||
&all_order_fields_used)))
|
||||
{
|
||||
bool skip_group= (skip_sort_order &&
|
||||
test_if_skip_sort_order(tab, group_list, select_limit,
|
||||
1) != 0);
|
||||
test_if_skip_sort_order(tab, group_list, select_limit, 1,
|
||||
&tab->table->keys_in_use_for_group_by) != 0);
|
||||
if ((skip_group && all_order_fields_used) ||
|
||||
select_limit == HA_POS_ERROR ||
|
||||
(order && !skip_sort_order))
|
||||
|
@ -1229,7 +1232,9 @@ JOIN::optimize()
|
|||
((group_list &&
|
||||
(!simple_group ||
|
||||
!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) &&
|
||||
tmp_table_param.quick_group && !procedure)
|
||||
{
|
||||
|
@ -1331,7 +1336,7 @@ JOIN::optimize()
|
|||
DBUG_PRINT("info",("Sorting for group"));
|
||||
thd->proc_info="Sorting for group";
|
||||
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) ||
|
||||
make_sum_func_list(all_fields, fields_list, 1) ||
|
||||
setup_sum_funcs(thd, sum_funcs))
|
||||
|
@ -1348,7 +1353,7 @@ JOIN::optimize()
|
|||
DBUG_PRINT("info",("Sorting for order"));
|
||||
thd->proc_info="Sorting for order";
|
||||
if (create_sort_index(thd, this, order,
|
||||
HA_POS_ERROR, HA_POS_ERROR))
|
||||
HA_POS_ERROR, HA_POS_ERROR, TRUE))
|
||||
DBUG_RETURN(1);
|
||||
order=0;
|
||||
}
|
||||
|
@ -1375,7 +1380,9 @@ JOIN::optimize()
|
|||
{
|
||||
/* Should always succeed */
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1568,7 +1575,9 @@ JOIN::exec()
|
|||
(const_tables == tables ||
|
||||
((simple_order || skip_sort_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;
|
||||
having= tmp_having;
|
||||
select_describe(this, need_tmp,
|
||||
|
@ -1744,7 +1753,7 @@ JOIN::exec()
|
|||
DBUG_VOID_RETURN;
|
||||
}
|
||||
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))
|
||||
{
|
||||
DBUG_VOID_RETURN;
|
||||
|
@ -1960,7 +1969,8 @@ JOIN::exec()
|
|||
curr_join->group_list : curr_join->order,
|
||||
curr_join->select_limit,
|
||||
(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;
|
||||
sortorder= curr_join->sortorder;
|
||||
if (curr_join->const_tables != curr_join->tables &&
|
||||
|
@ -3964,7 +3974,7 @@ best_access_path(JOIN *join,
|
|||
/* Limit the number of matched rows */
|
||||
tmp= records;
|
||||
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 */
|
||||
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 */
|
||||
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 */
|
||||
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)
|
||||
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->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)
|
||||
{ // Check full join
|
||||
ha_rows rnd_records= s->found_records;
|
||||
|
@ -6096,10 +6106,7 @@ make_join_readinfo(JOIN *join, ulonglong options)
|
|||
*/
|
||||
if (!ordered_set &&
|
||||
(table == join->sort_by_table &&
|
||||
(!join->order || join->skip_sort_order ||
|
||||
test_if_skip_sort_order(tab, join->order, join->select_limit,
|
||||
1))
|
||||
) ||
|
||||
(!join->order || join->skip_sort_order)) ||
|
||||
(join->sort_by_table == (TABLE *) 1 && i != join->const_tables))
|
||||
ordered_set= 1;
|
||||
|
||||
|
@ -6115,7 +6122,7 @@ make_join_readinfo(JOIN *join, ulonglong options)
|
|||
table->status=STATUS_NO_RECORD;
|
||||
tab->read_first_record= join_read_const;
|
||||
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->key_read=1;
|
||||
|
@ -6133,7 +6140,7 @@ make_join_readinfo(JOIN *join, ulonglong options)
|
|||
tab->quick=0;
|
||||
tab->read_first_record= join_read_key;
|
||||
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->key_read=1;
|
||||
|
@ -6150,7 +6157,7 @@ make_join_readinfo(JOIN *join, ulonglong options)
|
|||
}
|
||||
delete tab->quick;
|
||||
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->key_read=1;
|
||||
|
@ -6236,15 +6243,15 @@ make_join_readinfo(JOIN *join, ulonglong options)
|
|||
{
|
||||
if (tab->select && tab->select->quick &&
|
||||
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->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))
|
||||
{ // 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->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->in_use= thd;
|
||||
table->quick_keys.init();
|
||||
table->used_keys.init();
|
||||
table->covering_keys.init();
|
||||
table->keys_in_use_for_query.init();
|
||||
|
||||
table->s= share;
|
||||
|
@ -11003,7 +11010,7 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos)
|
|||
}
|
||||
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 &&
|
||||
(int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY)
|
||||
{
|
||||
|
@ -11310,7 +11317,7 @@ join_read_first(JOIN_TAB *tab)
|
|||
{
|
||||
int error;
|
||||
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->key_read=1;
|
||||
|
@ -11349,7 +11356,7 @@ join_read_last(JOIN_TAB *tab)
|
|||
{
|
||||
TABLE *table=tab->table;
|
||||
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->key_read=1;
|
||||
|
@ -12373,7 +12380,7 @@ find_field_in_item_list (Field *field, void *data)
|
|||
|
||||
static bool
|
||||
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;
|
||||
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");
|
||||
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
|
||||
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)
|
||||
{
|
||||
|
@ -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
|
||||
keys
|
||||
*/
|
||||
if (table->used_keys.is_set(ref_key))
|
||||
usable_keys.intersect(table->used_keys);
|
||||
if (table->covering_keys.is_set(ref_key))
|
||||
usable_keys.intersect(table->covering_keys);
|
||||
if ((new_ref_key= test_if_subkey(order, table, ref_key, ref_key_parts,
|
||||
&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)
|
||||
{
|
||||
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,
|
||||
|
@ -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:
|
||||
join_read_last);
|
||||
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->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
|
||||
select_limit Max number of rows in final output
|
||||
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
|
||||
|
@ -12636,7 +12642,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
|
|||
|
||||
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)
|
||||
{
|
||||
uint length= 0;
|
||||
ha_rows examined_rows;
|
||||
|
@ -12657,7 +12664,9 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
|
|||
*/
|
||||
if ((order != join->group_list ||
|
||||
!(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);
|
||||
for (ORDER *ord= join->order; ord; ord= ord->next)
|
||||
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. */
|
||||
my_bool key_read=table->key_read;
|
||||
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;
|
||||
if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT &&
|
||||
!((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 &&
|
||||
(key_part->length !=
|
||||
table->field[key_part->fieldnr-1]->key_length() &&
|
||||
!(key_info->flags & HA_FULLTEXT)))
|
||||
!(key_info->flags & (HA_FULLTEXT | HA_SPATIAL))))
|
||||
{
|
||||
char *end;
|
||||
buff[0] = '(';
|
||||
|
@ -2266,8 +2266,7 @@ int make_table_list(THD *thd, SELECT_LEX *sel,
|
|||
ident_table.length= strlen(table);
|
||||
table_ident= new Table_ident(thd, ident_db, ident_table, 1);
|
||||
sel->init_query();
|
||||
if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ,
|
||||
(List<String> *) 0, (List<String> *) 0))
|
||||
if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -5033,8 +5032,7 @@ int make_schema_select(THD *thd, SELECT_LEX *sel,
|
|||
strlen(schema_table->table_name), 0);
|
||||
if (schema_table->old_format(thd, schema_table) || /* Handle old syntax */
|
||||
!sel->add_table_to_list(thd, new Table_ident(thd, db, table, 0),
|
||||
0, 0, TL_READ, (List<String> *) 0,
|
||||
(List<String> *) 0))
|
||||
0, 0, TL_READ))
|
||||
{
|
||||
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;
|
||||
|
||||
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) ||
|
||||
(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) &&
|
||||
(column->length > length ||
|
||||
!Field::type_can_have_key_part (sql_field->sql_type) ||
|
||||
((f_is_packed(sql_field->pack_flag) ||
|
||||
((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
|
||||
(key_info->flags & HA_NOSAME))) &&
|
||||
|
@ -5859,6 +5866,8 @@ view_err:
|
|||
*/
|
||||
if (!Field::type_can_have_key_part(cfield->field->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 &&
|
||||
!f_is_blob(key_part->key_type)) ||
|
||||
(cfield->length && (cfield->length < key_part_length /
|
||||
|
|
|
@ -126,7 +126,7 @@ int mysql_update(THD *thd,
|
|||
#endif
|
||||
uint table_count= 0;
|
||||
ha_rows updated, found;
|
||||
key_map old_used_keys;
|
||||
key_map old_covering_keys;
|
||||
TABLE *table;
|
||||
SQL_SELECT *select;
|
||||
READ_RECORD info;
|
||||
|
@ -165,8 +165,8 @@ int mysql_update(THD *thd,
|
|||
thd->proc_info="init";
|
||||
table= table_list->table;
|
||||
|
||||
/* Calculate "table->used_keys" based on the WHERE */
|
||||
table->used_keys= table->s->keys_in_use;
|
||||
/* Calculate "table->covering_keys" based on the WHERE */
|
||||
table->covering_keys= table->s->keys_in_use;
|
||||
table->quick_keys.clear_all();
|
||||
|
||||
#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))
|
||||
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 */
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
table_list->grant.want_privilege= table->grant.want_privilege= want_privilege;
|
||||
|
@ -229,7 +229,7 @@ int mysql_update(THD *thd,
|
|||
limit= 0; // Impossible WHERE
|
||||
}
|
||||
// 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
|
||||
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
|
||||
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->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
|
||||
*/
|
||||
|
||||
|
@ -1119,7 +1119,7 @@ int multi_update::prepare(List<Item> ¬_used_values,
|
|||
update.link_in_list((byte*) tl, (byte**) &tl->next_local);
|
||||
tl->shared= table_count++;
|
||||
table->no_keyread=1;
|
||||
table->used_keys.clear_all();
|
||||
table->covering_keys.clear_all();
|
||||
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;
|
||||
sp_head *sphead;
|
||||
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
|
||||
|
||||
%type <string_list>
|
||||
key_usage_list using_list
|
||||
using_list
|
||||
|
||||
%type <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
|
||||
object_privilege object_privilege_list user_list rename_list
|
||||
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
|
||||
db_to_db table_to_table_list table_to_table opt_table_list opt_as
|
||||
handler_rkey_function handler_read_or_scan
|
||||
|
@ -1269,6 +1270,8 @@ END_OF_INPUT
|
|||
%type <spblock> sp_decls sp_decl
|
||||
%type <lex> sp_cursor_stmt
|
||||
%type <spname> sp_name
|
||||
%type <index_hint> index_hint_type
|
||||
%type <num> index_hint_clause
|
||||
|
||||
%type <NONE>
|
||||
'-' '+' '*' '/' '%' '(' ')'
|
||||
|
@ -5940,12 +5943,8 @@ keycache_list:
|
|||
assign_to_keycache:
|
||||
table_ident cache_keys_spec
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
SELECT_LEX *sel= &lex->select_lex;
|
||||
if (!sel->add_table_to_list(lex->thd, $1, NULL, 0,
|
||||
TL_READ,
|
||||
sel->get_use_index(),
|
||||
(List<String> *)0))
|
||||
if (!Select->add_table_to_list(YYTHD, $1, NULL, 0, TL_READ,
|
||||
Select->pop_index_hints()))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
@ -5972,33 +5971,26 @@ preload_list:
|
|||
preload_keys:
|
||||
table_ident cache_keys_spec opt_ignore_leaves
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
SELECT_LEX *sel= &lex->select_lex;
|
||||
if (!sel->add_table_to_list(lex->thd, $1, NULL, $3,
|
||||
TL_READ,
|
||||
sel->get_use_index(),
|
||||
(List<String> *)0))
|
||||
if (!Select->add_table_to_list(YYTHD, $1, NULL, $3, TL_READ,
|
||||
Select->pop_index_hints()))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
cache_keys_spec:
|
||||
{ Select->interval_list.empty(); }
|
||||
cache_key_list_or_empty
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
SELECT_LEX *sel= &lex->select_lex;
|
||||
sel->use_index= sel->interval_list;
|
||||
{
|
||||
Lex->select_lex.alloc_index_hints(YYTHD);
|
||||
Select->set_index_hint_type(INDEX_HINT_USE,
|
||||
global_system_variables.old_mode ?
|
||||
INDEX_HINT_MASK_JOIN :
|
||||
INDEX_HINT_MASK_ALL);
|
||||
}
|
||||
cache_key_list_or_empty
|
||||
;
|
||||
|
||||
cache_key_list_or_empty:
|
||||
/* empty */ { Lex->select_lex.use_index_ptr= 0; }
|
||||
| opt_key_or_index '(' key_usage_list2 ')'
|
||||
{
|
||||
SELECT_LEX *sel= &Lex->select_lex;
|
||||
sel->use_index_ptr= &sel->use_index;
|
||||
}
|
||||
/* empty */ { }
|
||||
| key_or_index '(' opt_key_usage_list ')'
|
||||
;
|
||||
|
||||
opt_ignore_leaves:
|
||||
|
@ -7371,20 +7363,16 @@ normal_join:
|
|||
table_factor:
|
||||
{
|
||||
SELECT_LEX *sel= Select;
|
||||
sel->use_index_ptr=sel->ignore_index_ptr=0;
|
||||
sel->table_join_options= 0;
|
||||
}
|
||||
table_ident opt_table_alias opt_key_definition
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
SELECT_LEX *sel= lex->current_select;
|
||||
if (!($$= sel->add_table_to_list(lex->thd, $2, $3,
|
||||
sel->get_table_join_options(),
|
||||
lex->lock_option,
|
||||
sel->get_use_index(),
|
||||
sel->get_ignore_index())))
|
||||
if (!($$= Select->add_table_to_list(YYTHD, $2, $3,
|
||||
Select->get_table_join_options(),
|
||||
Lex->lock_option,
|
||||
Select->pop_index_hints())))
|
||||
MYSQL_YYABORT;
|
||||
sel->add_joined_table($$);
|
||||
Select->add_joined_table($$);
|
||||
}
|
||||
| '{' ident table_ref LEFT OUTER JOIN_SYM table_ref
|
||||
ON
|
||||
|
@ -7453,8 +7441,7 @@ table_factor:
|
|||
lex->current_select= sel= unit->outer_select();
|
||||
if (!($$= sel->
|
||||
add_table_to_list(lex->thd, new Table_ident(unit), $6, 0,
|
||||
TL_READ,(List<String> *)0,
|
||||
(List<String> *)0)))
|
||||
TL_READ)))
|
||||
|
||||
MYSQL_YYABORT;
|
||||
sel->add_joined_table($$);
|
||||
|
@ -7553,52 +7540,67 @@ opt_outer:
|
|||
/* empty */ {}
|
||||
| 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:
|
||||
/* empty */ {}
|
||||
| USE_SYM key_usage_list
|
||||
{
|
||||
SELECT_LEX *sel= Select;
|
||||
sel->use_index= *$2;
|
||||
sel->use_index_ptr= &sel->use_index;
|
||||
}
|
||||
| FORCE_SYM key_usage_list
|
||||
{
|
||||
SELECT_LEX *sel= Select;
|
||||
sel->use_index= *$2;
|
||||
sel->use_index_ptr= &sel->use_index;
|
||||
sel->table_join_options|= TL_OPTION_FORCE_INDEX;
|
||||
}
|
||||
| IGNORE_SYM key_usage_list
|
||||
{
|
||||
SELECT_LEX *sel= Select;
|
||||
sel->ignore_index= *$2;
|
||||
sel->ignore_index_ptr= &sel->ignore_index;
|
||||
};
|
||||
{ Select->clear_index_hints(); }
|
||||
opt_index_hints_list
|
||||
;
|
||||
|
||||
opt_key_usage_list:
|
||||
/* empty */ { Select->add_index_hint(YYTHD, NULL, 0); }
|
||||
| key_usage_list {}
|
||||
;
|
||||
|
||||
key_usage_element:
|
||||
ident { Select->add_index_hint(YYTHD, $1.str, $1.length); }
|
||||
| PRIMARY_SYM
|
||||
{
|
||||
Select->add_index_hint(YYTHD, (char *)"PRIMARY", 7);
|
||||
}
|
||||
;
|
||||
|
||||
key_usage_list:
|
||||
key_or_index { Select->interval_list.empty(); }
|
||||
'(' key_list_or_empty ')'
|
||||
{ $$= &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)); };
|
||||
key_usage_element
|
||||
| key_usage_list ',' key_usage_element
|
||||
;
|
||||
|
||||
using_list:
|
||||
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))))
|
||||
goto err;
|
||||
outparam->quick_keys.init();
|
||||
outparam->used_keys.init();
|
||||
outparam->covering_keys.init();
|
||||
outparam->keys_in_use_for_query.init();
|
||||
|
||||
/* Allocate handler */
|
||||
|
@ -4120,6 +4120,175 @@ Item_subselect *st_table_list::containing_subselect()
|
|||
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
|
||||
*****************************************************************************/
|
||||
|
|
29
sql/table.h
29
sql/table.h
|
@ -299,6 +299,12 @@ typedef struct st_table_share
|
|||
|
||||
|
||||
/* Information for one open table */
|
||||
enum index_hint_type
|
||||
{
|
||||
INDEX_HINT_IGNORE,
|
||||
INDEX_HINT_USE,
|
||||
INDEX_HINT_FORCE
|
||||
};
|
||||
|
||||
struct st_table {
|
||||
st_table() {} /* Remove gcc warning */
|
||||
|
@ -318,8 +324,12 @@ struct st_table {
|
|||
byte *write_row_record; /* Used as optimisation in
|
||||
THD::write_row */
|
||||
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
|
||||
table.
|
||||
|
@ -332,7 +342,10 @@ struct st_table {
|
|||
The set is implemented as a bitmap.
|
||||
*/
|
||||
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 */
|
||||
|
||||
Field *next_number_field; /* Set if next_number is activated */
|
||||
|
@ -666,6 +679,7 @@ public:
|
|||
(TABLE_LIST::join_using_fields != NULL)
|
||||
*/
|
||||
|
||||
class index_hint;
|
||||
typedef struct st_table_list
|
||||
{
|
||||
st_table_list() {} /* Remove gcc warning */
|
||||
|
@ -722,7 +736,7 @@ typedef struct st_table_list
|
|||
*/
|
||||
struct st_table_list *next_name_resolution_table;
|
||||
/* Index names in a "... JOIN ... USE/IGNORE INDEX ..." clause. */
|
||||
List<String> *use_index, *ignore_index;
|
||||
List<index_hint> *index_hints;
|
||||
TABLE *table; /* 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);
|
||||
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:
|
||||
bool prep_check_option(THD *thd, uint8 check_opt_type);
|
||||
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;
|
||||
const char *errmsg= 0;
|
||||
int error= HA_ADMIN_OK;
|
||||
ulonglong map= ~(ulonglong) 0;
|
||||
ulonglong map;
|
||||
TABLE_LIST *table_list= table->pos_in_table_list;
|
||||
DBUG_ENTER("ha_myisam::assign_to_keycache");
|
||||
|
||||
/* Check validity of the index references */
|
||||
if (table_list->use_index)
|
||||
table->keys_in_use_for_query.clear_all();
|
||||
|
||||
if (table_list->process_index_hints(table))
|
||||
{
|
||||
/* We only come here when the user did specify an index map */
|
||||
key_map kmap;
|
||||
if (get_key_map_from_key_list(&kmap, table, table_list->use_index))
|
||||
{
|
||||
errmsg= thd->net.last_error;
|
||||
error= HA_ADMIN_FAILED;
|
||||
goto err;
|
||||
}
|
||||
map= kmap.to_ulonglong();
|
||||
errmsg= thd->net.last_error;
|
||||
error= HA_ADMIN_FAILED;
|
||||
goto err;
|
||||
}
|
||||
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)))
|
||||
{
|
||||
|
@ -1208,27 +1207,27 @@ int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt)
|
|||
{
|
||||
int error;
|
||||
const char *errmsg;
|
||||
ulonglong map= ~(ulonglong) 0;
|
||||
ulonglong map;
|
||||
TABLE_LIST *table_list= table->pos_in_table_list;
|
||||
my_bool ignore_leaves= table_list->ignore_leaves;
|
||||
|
||||
DBUG_ENTER("ha_myisam::preload_keys");
|
||||
|
||||
/* Check validity of the index references */
|
||||
if (table_list->use_index)
|
||||
table->keys_in_use_for_query.clear_all();
|
||||
|
||||
if (table_list->process_index_hints(table))
|
||||
{
|
||||
key_map kmap;
|
||||
get_key_map_from_key_list(&kmap, table, table_list->use_index);
|
||||
if (kmap.is_set_all())
|
||||
{
|
||||
errmsg= thd->net.last_error;
|
||||
error= HA_ADMIN_FAILED;
|
||||
goto err;
|
||||
}
|
||||
if (!kmap.is_clear_all())
|
||||
map= kmap.to_ulonglong();
|
||||
errmsg= thd->net.last_error;
|
||||
error= HA_ADMIN_FAILED;
|
||||
goto err;
|
||||
}
|
||||
|
||||
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,
|
||||
(void *) &thd->variables.preload_buff_size);
|
||||
|
||||
|
|
Loading…
Reference in a new issue