mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 10:14:19 +01:00
Merge moonbone.local:/home/evgen/bk-trees/mysql-5.0-opt
into moonbone.local:/work/merge-5.1
This commit is contained in:
commit
a989f7261e
10 changed files with 539 additions and 18 deletions
|
@ -704,6 +704,32 @@ select f1 from t1 where f1 like 'a%';
|
|||
f1
|
||||
a
|
||||
drop table t1;
|
||||
create table t1 (utext varchar(20) character set ucs2);
|
||||
insert into t1 values ("lily");
|
||||
insert into t1 values ("river");
|
||||
prepare stmt from 'select utext from t1 where utext like ?';
|
||||
set @param1='%%';
|
||||
execute stmt using @param1;
|
||||
utext
|
||||
lily
|
||||
river
|
||||
execute stmt using @param1;
|
||||
utext
|
||||
lily
|
||||
river
|
||||
select utext from t1 where utext like '%%';
|
||||
utext
|
||||
lily
|
||||
river
|
||||
drop table t1;
|
||||
deallocate prepare stmt;
|
||||
CREATE TABLE t1 (id int, s char(5) CHARACTER SET ucs2 COLLATE ucs2_unicode_ci);
|
||||
INSERT INTO t1 VALUES (1, 'ZZZZZ'), (1, 'ZZZ'), (2, 'ZZZ'), (2, 'ZZZZZ');
|
||||
SELECT id, MIN(s) FROM t1 GROUP BY id;
|
||||
id MIN(s)
|
||||
1 ZZZ
|
||||
2 ZZZ
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a varchar(64) character set ucs2, b decimal(10,3));
|
||||
INSERT INTO t1 VALUES ("1.1", 0), ("2.1", 0);
|
||||
update t1 set b=a;
|
||||
|
|
|
@ -1152,6 +1152,135 @@ id a
|
|||
6 bbbbbb
|
||||
11 bbbbbb
|
||||
DROP TABLE t1;
|
||||
SET NAMES utf8;
|
||||
CREATE TABLE t1 (
|
||||
a CHAR(13) DEFAULT '',
|
||||
INDEX(a)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
|
||||
INSERT INTO t1 VALUES
|
||||
('Käli Käli 2-4'), ('Käli Käli 2-4'),
|
||||
('Käli Käli 2+4'), ('Käli Käli 2+4'),
|
||||
('Käli Käli 2-6'), ('Käli Käli 2-6');
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
CREATE TABLE t2 (
|
||||
a CHAR(13) DEFAULT '',
|
||||
INDEX(a)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
|
||||
INSERT INTO t2 VALUES
|
||||
('Kali Kali 2-4'), ('Kali Kali 2-4'),
|
||||
('Kali Kali 2+4'), ('Kali Kali 2+4'),
|
||||
('Kali Kali 2-6'), ('Kali Kali 2-6');
|
||||
INSERT INTO t2 SELECT * FROM t2;
|
||||
SELECT a FROM t1 WHERE a LIKE 'Käli Käli 2+4';
|
||||
a
|
||||
Käli Käli 2+4
|
||||
Käli Käli 2+4
|
||||
Käli Käli 2+4
|
||||
Käli Käli 2+4
|
||||
SELECT a FROM t2 WHERE a LIKE 'Kali Kali 2+4';
|
||||
a
|
||||
Kali Kali 2+4
|
||||
Kali Kali 2+4
|
||||
Kali Kali 2+4
|
||||
Kali Kali 2+4
|
||||
EXPLAIN SELECT a FROM t1 WHERE a LIKE 'Käli Käli 2+4';
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range a a 40 NULL 4 Using where; Using index
|
||||
EXPLAIN SELECT a FROM t1 WHERE a = 'Käli Käli 2+4';
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ref a a 40 const 4 Using where; Using index
|
||||
EXPLAIN SELECT a FROM t2 WHERE a LIKE 'Kali Kali 2+4';
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2 range a a 14 NULL 4 Using where; Using index
|
||||
EXPLAIN SELECT a FROM t2 WHERE a = 'Kali Kali 2+4';
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2 ref a a 14 const 4 Using where; Using index
|
||||
DROP TABLE t1,t2;
|
||||
CREATE TABLE t1 (
|
||||
a char(255) DEFAULT '',
|
||||
KEY(a(10))
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
|
||||
INSERT INTO t1 VALUES ('Käli Käli 2-4');
|
||||
SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
|
||||
a
|
||||
Käli Käli 2-4
|
||||
INSERT INTO t1 VALUES ('Käli Käli 2-4');
|
||||
SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
|
||||
a
|
||||
Käli Käli 2-4
|
||||
Käli Käli 2-4
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (
|
||||
a char(255) DEFAULT ''
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
|
||||
INSERT INTO t1 VALUES ('Käli Käli 2-4');
|
||||
INSERT INTO t1 VALUES ('Käli Käli 2-4');
|
||||
SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
|
||||
a
|
||||
Käli Käli 2-4
|
||||
Käli Käli 2-4
|
||||
ALTER TABLE t1 ADD KEY (a(10));
|
||||
SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
|
||||
a
|
||||
Käli Käli 2-4
|
||||
Käli Käli 2-4
|
||||
DROP TABLE t1;
|
||||
SET NAMES latin2;
|
||||
CREATE TABLE t1 (
|
||||
id int(11) NOT NULL default '0',
|
||||
tid int(11) NOT NULL default '0',
|
||||
val text NOT NULL,
|
||||
INDEX idx(tid, val(10))
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
INSERT INTO t1 VALUES
|
||||
(40988,72,'VOLNÝ ADSL'),(41009,72,'VOLNÝ ADSL'),
|
||||
(41032,72,'VOLNÝ ADSL'),(41038,72,'VOLNÝ ADSL'),
|
||||
(41063,72,'VOLNÝ ADSL'),(41537,72,'VOLNÝ ADSL Office'),
|
||||
(42141,72,'VOLNÝ ADSL'),(42565,72,'VOLNÝ ADSL Combi'),
|
||||
(42749,72,'VOLNÝ ADSL'),(44205,72,'VOLNÝ ADSL');
|
||||
SELECT * FROM t1 WHERE tid=72 and val LIKE 'VOLNY ADSL';
|
||||
id tid val
|
||||
40988 72 VOLNÝ ADSL
|
||||
41009 72 VOLNÝ ADSL
|
||||
41032 72 VOLNÝ ADSL
|
||||
41038 72 VOLNÝ ADSL
|
||||
41063 72 VOLNÝ ADSL
|
||||
42141 72 VOLNÝ ADSL
|
||||
42749 72 VOLNÝ ADSL
|
||||
44205 72 VOLNÝ ADSL
|
||||
SELECT * FROM t1 WHERE tid=72 and val LIKE 'VOLNÝ ADSL';
|
||||
id tid val
|
||||
40988 72 VOLNÝ ADSL
|
||||
41009 72 VOLNÝ ADSL
|
||||
41032 72 VOLNÝ ADSL
|
||||
41038 72 VOLNÝ ADSL
|
||||
41063 72 VOLNÝ ADSL
|
||||
42141 72 VOLNÝ ADSL
|
||||
42749 72 VOLNÝ ADSL
|
||||
44205 72 VOLNÝ ADSL
|
||||
SELECT * FROM t1 WHERE tid=72 and val LIKE '%VOLNÝ ADSL';
|
||||
id tid val
|
||||
40988 72 VOLNÝ ADSL
|
||||
41009 72 VOLNÝ ADSL
|
||||
41032 72 VOLNÝ ADSL
|
||||
41038 72 VOLNÝ ADSL
|
||||
41063 72 VOLNÝ ADSL
|
||||
42141 72 VOLNÝ ADSL
|
||||
42749 72 VOLNÝ ADSL
|
||||
44205 72 VOLNÝ ADSL
|
||||
ALTER TABLE t1 DROP KEY idx;
|
||||
ALTER TABLE t1 ADD KEY idx (tid,val(11));
|
||||
SELECT * FROM t1 WHERE tid=72 and val LIKE 'VOLNÝ ADSL';
|
||||
id tid val
|
||||
40988 72 VOLNÝ ADSL
|
||||
41009 72 VOLNÝ ADSL
|
||||
41032 72 VOLNÝ ADSL
|
||||
41038 72 VOLNÝ ADSL
|
||||
41063 72 VOLNÝ ADSL
|
||||
42141 72 VOLNÝ ADSL
|
||||
42749 72 VOLNÝ ADSL
|
||||
44205 72 VOLNÝ ADSL
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1(id varchar(20) NOT NULL) DEFAULT CHARSET=utf8;
|
||||
INSERT INTO t1 VALUES ('xxx'), ('aa'), ('yyy'), ('aa');
|
||||
SELECT id FROM t1;
|
||||
|
|
|
@ -504,6 +504,57 @@ a 2 b
|
|||
2 2 4
|
||||
3 2 5
|
||||
DROP TABLE t1,t2;
|
||||
CREATE TABLE t1(a INT PRIMARY KEY, b INT);
|
||||
INSERT INTO t1 VALUES (1,1), (2,1), (3,1);
|
||||
EXPLAIN SELECT DISTINCT a FROM t1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 index NULL PRIMARY 4 NULL 3 Using index
|
||||
EXPLAIN SELECT DISTINCT a,b FROM t1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3
|
||||
EXPLAIN SELECT DISTINCT t1_1.a, t1_1.b FROM t1 t1_1, t1 t1_2;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1_1 ALL NULL NULL NULL NULL 3 Using temporary
|
||||
1 SIMPLE t1_2 index NULL PRIMARY 4 NULL 3 Using index; Distinct
|
||||
EXPLAIN SELECT DISTINCT t1_1.a, t1_1.b FROM t1 t1_1, t1 t1_2
|
||||
WHERE t1_1.a = t1_2.a;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1_1 ALL PRIMARY NULL NULL NULL 3 Using temporary
|
||||
1 SIMPLE t1_2 eq_ref PRIMARY PRIMARY 4 test.t1_1.a 1 Using index; Distinct
|
||||
EXPLAIN SELECT a FROM t1 GROUP BY a;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 index NULL PRIMARY 4 NULL 3 Using index
|
||||
EXPLAIN SELECT a,b FROM t1 GROUP BY a,b;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3
|
||||
EXPLAIN SELECT DISTINCT a,b FROM t1 GROUP BY a,b;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3
|
||||
CREATE TABLE t2(a INT, b INT, c INT, d INT, PRIMARY KEY (a,b));
|
||||
INSERT INTO t2 VALUES (1,1,1,50), (1,2,3,40), (2,1,3,4);
|
||||
EXPLAIN SELECT DISTINCT a FROM t2;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2 index NULL PRIMARY 8 NULL 3 Using index
|
||||
EXPLAIN SELECT DISTINCT a,a FROM t2;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2 index NULL PRIMARY 8 NULL 3 Using index
|
||||
EXPLAIN SELECT DISTINCT b,a FROM t2;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2 index NULL PRIMARY 8 NULL 3 Using index
|
||||
EXPLAIN SELECT DISTINCT a,c FROM t2;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using temporary
|
||||
EXPLAIN SELECT DISTINCT c,a,b FROM t2;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 3
|
||||
EXPLAIN SELECT DISTINCT a,b,d FROM t2 GROUP BY c,b,d;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using temporary; Using filesort
|
||||
CREATE UNIQUE INDEX c_b_unq ON t2 (c,b);
|
||||
EXPLAIN SELECT DISTINCT a,b,d FROM t2 GROUP BY c,b,d;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 3
|
||||
DROP TABLE t1,t2;
|
||||
create table t1 (id int, dsc varchar(50));
|
||||
insert into t1 values (1, "line number one"), (2, "line number two"), (3, "line number three");
|
||||
select distinct id, IFNULL(dsc, '-') from t1;
|
||||
|
|
|
@ -439,6 +439,32 @@ insert into t1 values('a');
|
|||
create index t1f1 on t1(f1);
|
||||
select f1 from t1 where f1 like 'a%';
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug#9442 Set parameter make query fail if column character set is UCS2
|
||||
#
|
||||
create table t1 (utext varchar(20) character set ucs2);
|
||||
insert into t1 values ("lily");
|
||||
insert into t1 values ("river");
|
||||
prepare stmt from 'select utext from t1 where utext like ?';
|
||||
set @param1='%%';
|
||||
execute stmt using @param1;
|
||||
execute stmt using @param1;
|
||||
select utext from t1 where utext like '%%';
|
||||
drop table t1;
|
||||
deallocate prepare stmt;
|
||||
|
||||
#
|
||||
# Bug #20076: server crashes for a query with GROUP BY if MIN/MAX aggregation
|
||||
# over a 'ucs2' field uses a temporary table
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (id int, s char(5) CHARACTER SET ucs2 COLLATE ucs2_unicode_ci);
|
||||
INSERT INTO t1 VALUES (1, 'ZZZZZ'), (1, 'ZZZ'), (2, 'ZZZ'), (2, 'ZZZZZ');
|
||||
|
||||
SELECT id, MIN(s) FROM t1 GROUP BY id;
|
||||
|
||||
DROP TABLE t1;
|
||||
# End of 4.1 tests
|
||||
|
||||
#
|
||||
|
|
|
@ -938,6 +938,94 @@ SELECT id, a FROM t1 WHERE a='bbbbbb' ORDER BY b;
|
|||
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Bug#16674: LIKE predicate for a utf8 character set column
|
||||
#
|
||||
|
||||
SET NAMES utf8;
|
||||
|
||||
CREATE TABLE t1 (
|
||||
a CHAR(13) DEFAULT '',
|
||||
INDEX(a)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
|
||||
INSERT INTO t1 VALUES
|
||||
('Käli Käli 2-4'), ('Käli Käli 2-4'),
|
||||
('Käli Käli 2+4'), ('Käli Käli 2+4'),
|
||||
('Käli Käli 2-6'), ('Käli Käli 2-6');
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
|
||||
CREATE TABLE t2 (
|
||||
a CHAR(13) DEFAULT '',
|
||||
INDEX(a)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
|
||||
|
||||
INSERT INTO t2 VALUES
|
||||
('Kali Kali 2-4'), ('Kali Kali 2-4'),
|
||||
('Kali Kali 2+4'), ('Kali Kali 2+4'),
|
||||
('Kali Kali 2-6'), ('Kali Kali 2-6');
|
||||
INSERT INTO t2 SELECT * FROM t2;
|
||||
|
||||
SELECT a FROM t1 WHERE a LIKE 'Käli Käli 2+4';
|
||||
SELECT a FROM t2 WHERE a LIKE 'Kali Kali 2+4';
|
||||
|
||||
EXPLAIN SELECT a FROM t1 WHERE a LIKE 'Käli Käli 2+4';
|
||||
EXPLAIN SELECT a FROM t1 WHERE a = 'Käli Käli 2+4';
|
||||
EXPLAIN SELECT a FROM t2 WHERE a LIKE 'Kali Kali 2+4';
|
||||
EXPLAIN SELECT a FROM t2 WHERE a = 'Kali Kali 2+4';
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
CREATE TABLE t1 (
|
||||
a char(255) DEFAULT '',
|
||||
KEY(a(10))
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
|
||||
INSERT INTO t1 VALUES ('Käli Käli 2-4');
|
||||
SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
|
||||
INSERT INTO t1 VALUES ('Käli Käli 2-4');
|
||||
SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (
|
||||
a char(255) DEFAULT ''
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
|
||||
INSERT INTO t1 VALUES ('Käli Käli 2-4');
|
||||
INSERT INTO t1 VALUES ('Käli Käli 2-4');
|
||||
SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
|
||||
ALTER TABLE t1 ADD KEY (a(10));
|
||||
SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Bug#18359: LIKE predicate for a 'utf8' text column with a partial index
|
||||
# (see bug #16674 as well)
|
||||
#
|
||||
|
||||
SET NAMES latin2;
|
||||
|
||||
CREATE TABLE t1 (
|
||||
id int(11) NOT NULL default '0',
|
||||
tid int(11) NOT NULL default '0',
|
||||
val text NOT NULL,
|
||||
INDEX idx(tid, val(10))
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
INSERT INTO t1 VALUES
|
||||
(40988,72,'VOLNÝ ADSL'),(41009,72,'VOLNÝ ADSL'),
|
||||
(41032,72,'VOLNÝ ADSL'),(41038,72,'VOLNÝ ADSL'),
|
||||
(41063,72,'VOLNÝ ADSL'),(41537,72,'VOLNÝ ADSL Office'),
|
||||
(42141,72,'VOLNÝ ADSL'),(42565,72,'VOLNÝ ADSL Combi'),
|
||||
(42749,72,'VOLNÝ ADSL'),(44205,72,'VOLNÝ ADSL');
|
||||
|
||||
SELECT * FROM t1 WHERE tid=72 and val LIKE 'VOLNY ADSL';
|
||||
SELECT * FROM t1 WHERE tid=72 and val LIKE 'VOLNÝ ADSL';
|
||||
SELECT * FROM t1 WHERE tid=72 and val LIKE '%VOLNÝ ADSL';
|
||||
|
||||
ALTER TABLE t1 DROP KEY idx;
|
||||
ALTER TABLE t1 ADD KEY idx (tid,val(11));
|
||||
|
||||
SELECT * FROM t1 WHERE tid=72 and val LIKE 'VOLNÝ ADSL';
|
||||
|
||||
DROP TABLE t1;
|
||||
# End of 4.1 tests
|
||||
|
||||
#
|
||||
|
|
|
@ -348,6 +348,34 @@ SELECT DISTINCT a, b, 2 FROM t2;
|
|||
SELECT DISTINCT 2, a, b FROM t2;
|
||||
SELECT DISTINCT a, 2, b FROM t2;
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# Bug#16458: Simple SELECT FOR UPDATE causes "Result Set not updatable"
|
||||
# error.
|
||||
#
|
||||
CREATE TABLE t1(a INT PRIMARY KEY, b INT);
|
||||
INSERT INTO t1 VALUES (1,1), (2,1), (3,1);
|
||||
EXPLAIN SELECT DISTINCT a FROM t1;
|
||||
EXPLAIN SELECT DISTINCT a,b FROM t1;
|
||||
EXPLAIN SELECT DISTINCT t1_1.a, t1_1.b FROM t1 t1_1, t1 t1_2;
|
||||
EXPLAIN SELECT DISTINCT t1_1.a, t1_1.b FROM t1 t1_1, t1 t1_2
|
||||
WHERE t1_1.a = t1_2.a;
|
||||
EXPLAIN SELECT a FROM t1 GROUP BY a;
|
||||
EXPLAIN SELECT a,b FROM t1 GROUP BY a,b;
|
||||
EXPLAIN SELECT DISTINCT a,b FROM t1 GROUP BY a,b;
|
||||
|
||||
CREATE TABLE t2(a INT, b INT, c INT, d INT, PRIMARY KEY (a,b));
|
||||
INSERT INTO t2 VALUES (1,1,1,50), (1,2,3,40), (2,1,3,4);
|
||||
EXPLAIN SELECT DISTINCT a FROM t2;
|
||||
EXPLAIN SELECT DISTINCT a,a FROM t2;
|
||||
EXPLAIN SELECT DISTINCT b,a FROM t2;
|
||||
EXPLAIN SELECT DISTINCT a,c FROM t2;
|
||||
EXPLAIN SELECT DISTINCT c,a,b FROM t2;
|
||||
|
||||
EXPLAIN SELECT DISTINCT a,b,d FROM t2 GROUP BY c,b,d;
|
||||
CREATE UNIQUE INDEX c_b_unq ON t2 (c,b);
|
||||
EXPLAIN SELECT DISTINCT a,b,d FROM t2 GROUP BY c,b,d;
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
# Bug 9784 DISTINCT IFNULL truncates data
|
||||
|
|
|
@ -2123,7 +2123,6 @@ Item_sum_hybrid::min_max_update_str_field()
|
|||
|
||||
if (!args[0]->null_value)
|
||||
{
|
||||
res_str->strip_sp();
|
||||
result_field->val_str(&tmp_value);
|
||||
|
||||
if (result_field->is_null() ||
|
||||
|
|
|
@ -106,8 +106,8 @@ public:
|
|||
SEL_ARG(Field *field, uint8 part, char *min_value, char *max_value,
|
||||
uint8 min_flag, uint8 max_flag, uint8 maybe_flag);
|
||||
SEL_ARG(enum Type type_arg)
|
||||
:elements(1),use_count(1),left(0),next_key_part(0),color(BLACK),
|
||||
type(type_arg),min_flag(0)
|
||||
:min_flag(0),elements(1),use_count(1),left(0),next_key_part(0),
|
||||
color(BLACK), type(type_arg)
|
||||
{}
|
||||
inline bool is_same(SEL_ARG *arg)
|
||||
{
|
||||
|
|
|
@ -163,6 +163,10 @@ 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);
|
||||
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);
|
||||
static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields,
|
||||
|
@ -868,6 +872,40 @@ JOIN::optimize()
|
|||
if (old_group_list && !group_list)
|
||||
select_distinct= 0;
|
||||
}
|
||||
/*
|
||||
Check if we can optimize away GROUP BY/DISTINCT.
|
||||
We can do that if there are no aggregate functions and the
|
||||
fields in DISTINCT clause (if present) and/or columns in GROUP BY
|
||||
(if present) contain direct references to all key parts of
|
||||
an unique index (in whatever order).
|
||||
Note that the unique keys for DISTINCT and GROUP BY should not
|
||||
be the same (as long as they are unique).
|
||||
|
||||
The FROM clause must contain a single non-constant table.
|
||||
*/
|
||||
if (tables - const_tables == 1 && (group_list || select_distinct) &&
|
||||
!tmp_table_param.sum_func_count &&
|
||||
(!join_tab[const_tables].select ||
|
||||
!join_tab[const_tables].select->quick ||
|
||||
join_tab[const_tables].select->quick->get_type() !=
|
||||
QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX))
|
||||
{
|
||||
if (group_list &&
|
||||
list_contains_unique_index(join_tab[const_tables].table,
|
||||
find_field_in_order_list,
|
||||
(void *) group_list))
|
||||
{
|
||||
group_list= 0;
|
||||
group= 0;
|
||||
}
|
||||
if (select_distinct &&
|
||||
list_contains_unique_index(join_tab[const_tables].table,
|
||||
find_field_in_item_list,
|
||||
(void *) &fields_list))
|
||||
{
|
||||
select_distinct= 0;
|
||||
}
|
||||
}
|
||||
if (!group_list && group)
|
||||
{
|
||||
order=0; // The output has only one row
|
||||
|
@ -11307,6 +11345,140 @@ test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts,
|
|||
return best;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Check if GROUP BY/DISTINCT can be optimized away because the set is
|
||||
already known to be distinct.
|
||||
|
||||
SYNOPSIS
|
||||
list_contains_unique_index ()
|
||||
table The table to operate on.
|
||||
find_func function to iterate over the list and search
|
||||
for a field
|
||||
|
||||
DESCRIPTION
|
||||
Used in removing the GROUP BY/DISTINCT of the following types of
|
||||
statements:
|
||||
SELECT [DISTINCT] <unique_key_cols>... FROM <single_table_ref>
|
||||
[GROUP BY <unique_key_cols>,...]
|
||||
|
||||
If (a,b,c is distinct)
|
||||
then <any combination of a,b,c>,{whatever} is also distinct
|
||||
|
||||
This function checks if all the key parts of any of the unique keys
|
||||
of the table are referenced by a list : either the select list
|
||||
through find_field_in_item_list or GROUP BY list through
|
||||
find_field_in_order_list.
|
||||
If the above holds then we can safely remove the GROUP BY/DISTINCT,
|
||||
as no result set can be more distinct than an unique key.
|
||||
|
||||
RETURN VALUE
|
||||
1 found
|
||||
0 not found.
|
||||
*/
|
||||
|
||||
static bool
|
||||
list_contains_unique_index(TABLE *table,
|
||||
bool (*find_func) (Field *, void *), void *data)
|
||||
{
|
||||
for (uint keynr= 0; keynr < table->s->keys; keynr++)
|
||||
{
|
||||
if (keynr == table->s->primary_key ||
|
||||
(table->key_info[keynr].flags & HA_NOSAME))
|
||||
{
|
||||
KEY *keyinfo= table->key_info + keynr;
|
||||
KEY_PART_INFO *key_part, *key_part_end;
|
||||
|
||||
for (key_part=keyinfo->key_part,
|
||||
key_part_end=key_part+ keyinfo->key_parts;
|
||||
key_part < key_part_end;
|
||||
key_part++)
|
||||
{
|
||||
if (!find_func(key_part->field, data))
|
||||
break;
|
||||
}
|
||||
if (key_part == key_part_end)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Helper function for list_contains_unique_index.
|
||||
Find a field reference in a list of ORDER structures.
|
||||
|
||||
SYNOPSIS
|
||||
find_field_in_order_list ()
|
||||
field The field to search for.
|
||||
data ORDER *.The list to search in
|
||||
|
||||
DESCRIPTION
|
||||
Finds a direct reference of the Field in the list.
|
||||
|
||||
RETURN VALUE
|
||||
1 found
|
||||
0 not found.
|
||||
*/
|
||||
|
||||
static bool
|
||||
find_field_in_order_list (Field *field, void *data)
|
||||
{
|
||||
ORDER *group= (ORDER *) data;
|
||||
bool part_found= 0;
|
||||
for (ORDER *tmp_group= group; tmp_group; tmp_group=tmp_group->next)
|
||||
{
|
||||
Item *item= (*tmp_group->item)->real_item();
|
||||
if (item->type() == Item::FIELD_ITEM &&
|
||||
((Item_field*) item)->field->eq(field))
|
||||
{
|
||||
part_found= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return part_found;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Helper function for list_contains_unique_index.
|
||||
Find a field reference in a dynamic list of Items.
|
||||
|
||||
SYNOPSIS
|
||||
find_field_in_item_list ()
|
||||
field in The field to search for.
|
||||
data in List<Item> *.The list to search in
|
||||
|
||||
DESCRIPTION
|
||||
Finds a direct reference of the Field in the list.
|
||||
|
||||
RETURN VALUE
|
||||
1 found
|
||||
0 not found.
|
||||
*/
|
||||
|
||||
static bool
|
||||
find_field_in_item_list (Field *field, void *data)
|
||||
{
|
||||
List<Item> *fields= (List<Item> *) data;
|
||||
bool part_found= 0;
|
||||
List_iterator<Item> li(*fields);
|
||||
Item *item;
|
||||
|
||||
while ((item= li++))
|
||||
{
|
||||
if (item->type() == Item::FIELD_ITEM &&
|
||||
((Item_field*) item)->field->eq(field))
|
||||
{
|
||||
part_found= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return part_found;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Test if we can skip the ORDER BY by using an index.
|
||||
|
||||
|
|
|
@ -527,27 +527,20 @@ my_bool my_like_range_mb(CHARSET_INFO *cs,
|
|||
char *min_str,char *max_str,
|
||||
uint *min_length,uint *max_length)
|
||||
{
|
||||
uint mblen;
|
||||
const char *end= ptr + ptr_length;
|
||||
char *min_org= min_str;
|
||||
char *min_end= min_str + res_length;
|
||||
char *max_end= max_str + res_length;
|
||||
uint charlen= res_length / cs->mbmaxlen;
|
||||
uint maxcharlen= res_length / cs->mbmaxlen;
|
||||
|
||||
for (; ptr != end && min_str != min_end && charlen > 0 ; ptr++, charlen--)
|
||||
for (; ptr != end && min_str != min_end && maxcharlen ; maxcharlen--)
|
||||
{
|
||||
/* We assume here that escape, w_any, w_namy are one-byte characters */
|
||||
if (*ptr == escape && ptr+1 != end)
|
||||
{
|
||||
ptr++; /* Skip escape */
|
||||
*min_str++= *max_str++ = *ptr;
|
||||
continue;
|
||||
}
|
||||
if (*ptr == w_one || *ptr == w_many) /* '_' and '%' in SQL */
|
||||
{
|
||||
charlen= my_charpos(cs, min_org, min_str, res_length/cs->mbmaxlen);
|
||||
|
||||
if (charlen < (uint) (min_str - min_org))
|
||||
min_str= min_org + charlen;
|
||||
|
||||
ptr++; /* Skip escape */
|
||||
else if (*ptr == w_one || *ptr == w_many) /* '_' and '%' in SQL */
|
||||
{
|
||||
/*
|
||||
Calculate length of keys:
|
||||
'a\0\0... is the smallest possible string when we have space expand
|
||||
|
@ -571,7 +564,16 @@ my_bool my_like_range_mb(CHARSET_INFO *cs,
|
|||
pad_max_char(cs, max_str, max_end);
|
||||
return 0;
|
||||
}
|
||||
*min_str++= *max_str++ = *ptr;
|
||||
if ((mblen= my_ismbchar(cs, ptr, end)) > 1)
|
||||
{
|
||||
if (ptr+mblen > end || min_str+mblen > min_end)
|
||||
break;
|
||||
while (mblen--)
|
||||
*min_str++= *max_str++= *ptr++;
|
||||
}
|
||||
else
|
||||
*min_str++= *max_str++= *ptr++;
|
||||
|
||||
}
|
||||
|
||||
*min_length= *max_length = (uint) (min_str - min_org);
|
||||
|
|
Loading…
Add table
Reference in a new issue