Merge bk-internal.mysql.com:/data0/bk/mysql-5.1
into bk-internal.mysql.com:/data0/bk/mysql-5.1-opt
This commit is contained in:
commit
8c3525ff31
@ -214,3 +214,12 @@ select count(*) from t1;
|
|||||||
count(*)
|
count(*)
|
||||||
0
|
0
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
CREATE TABLE t1 (a INT);
|
||||||
|
INSERT INTO t1 VALUES (1);
|
||||||
|
DELETE FROM t1 ORDER BY x;
|
||||||
|
ERROR 42S22: Unknown column 'x' in 'order clause'
|
||||||
|
DELETE FROM t1 ORDER BY t2.x;
|
||||||
|
ERROR 42S22: Unknown column 't2.x' in 'order clause'
|
||||||
|
DELETE FROM t1 ORDER BY (SELECT x);
|
||||||
|
ERROR 42S22: Unknown column 'x' in 'field list'
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -730,6 +730,12 @@ point(b, b) IS NULL linestring(b) IS NULL polygon(b) IS NULL multipoint(b) IS NU
|
|||||||
1 1 1 1 1 1 1
|
1 1 1 1 1 1 1
|
||||||
0 1 1 1 1 1 1
|
0 1 1 1 1 1 1
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
CREATE TABLE t1(a POINT) ENGINE=MyISAM;
|
||||||
|
INSERT INTO t1 VALUES (NULL);
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a
|
||||||
|
NULL
|
||||||
|
DROP TABLE t1;
|
||||||
End of 4.1 tests
|
End of 4.1 tests
|
||||||
create table t1 (s1 geometry not null,s2 char(100));
|
create table t1 (s1 geometry not null,s2 char(100));
|
||||||
create trigger t1_bu before update on t1 for each row set new.s1 = null;
|
create trigger t1_bu before update on t1 for each row set new.s1 = null;
|
||||||
|
@ -1141,4 +1141,9 @@ EXPLAIN SELECT 1 FROM t2 WHERE a IN
|
|||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 PRIMARY t2 index NULL a 5 NULL 4 Using where; Using index
|
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
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 256 Using where
|
||||||
|
SHOW VARIABLES LIKE 'old';
|
||||||
|
Variable_name Value
|
||||||
|
old OFF
|
||||||
|
SET @@old = off;
|
||||||
|
ERROR HY000: Variable 'old' is a read only variable
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
@ -717,6 +717,34 @@ d8c4177d225791924.30714720
|
|||||||
d8c4177d2380fc201.39666693
|
d8c4177d2380fc201.39666693
|
||||||
d8c4177d24ccef970.14957924
|
d8c4177d24ccef970.14957924
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
create table t1 (
|
||||||
|
c1 char(10), c2 char(10), c3 char(10), c4 char(10),
|
||||||
|
c5 char(10), c6 char(10), c7 char(10), c8 char(10),
|
||||||
|
c9 char(10), c10 char(10), c11 char(10), c12 char(10),
|
||||||
|
c13 char(10), c14 char(10), c15 char(10), c16 char(10),
|
||||||
|
index(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,c13,c14,c15,c16)
|
||||||
|
);
|
||||||
|
insert into t1 (c1) values ('1'),('1'),('1'),('1');
|
||||||
|
select * from t1 where
|
||||||
|
c1 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c2 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c3 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c4 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c5 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c6 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c7 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c8 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c9 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c10 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c11 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c12 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c13 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c14 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c15 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c16 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
;
|
||||||
|
c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16
|
||||||
|
drop table t1;
|
||||||
End of 4.1 tests
|
End of 4.1 tests
|
||||||
CREATE TABLE t1 (
|
CREATE TABLE t1 (
|
||||||
id int(11) NOT NULL auto_increment,
|
id int(11) NOT NULL auto_increment,
|
||||||
|
@ -621,3 +621,20 @@ Pos Instruction
|
|||||||
0 stmt 2 "CREATE INDEX idx ON t1 (c1)"
|
0 stmt 2 "CREATE INDEX idx ON t1 (c1)"
|
||||||
DROP PROCEDURE p1;
|
DROP PROCEDURE p1;
|
||||||
End of 5.0 tests.
|
End of 5.0 tests.
|
||||||
|
CREATE PROCEDURE p1()
|
||||||
|
BEGIN
|
||||||
|
DECLARE dummy int default 0;
|
||||||
|
CASE 12
|
||||||
|
WHEN 12
|
||||||
|
THEN SET dummy = 0;
|
||||||
|
END CASE;
|
||||||
|
END//
|
||||||
|
SHOW PROCEDURE CODE p1;
|
||||||
|
Pos Instruction
|
||||||
|
0 set dummy@0 0
|
||||||
|
1 set_case_expr (6) 0 12
|
||||||
|
2 jump_if_not 5(6) (case_expr@0 = 12)
|
||||||
|
3 set dummy@0 0
|
||||||
|
4 jump 6
|
||||||
|
5 error 1339
|
||||||
|
DROP PROCEDURE p1;
|
||||||
|
@ -3905,6 +3905,48 @@ COUNT(*) a
|
|||||||
2 2
|
2 2
|
||||||
3 3
|
3 3
|
||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
|
CREATE TABLE t1 (a int, b int);
|
||||||
|
CREATE TABLE t2 (m int, n int);
|
||||||
|
INSERT INTO t1 VALUES (2,2), (2,2), (3,3), (3,3), (3,3), (4,4);
|
||||||
|
INSERT INTO t2 VALUES (1,11), (2,22), (3,32), (4,44), (4,44);
|
||||||
|
SELECT COUNT(*) c, a,
|
||||||
|
(SELECT GROUP_CONCAT(COUNT(a)) FROM t2 WHERE m = a)
|
||||||
|
FROM t1 GROUP BY a;
|
||||||
|
c a (SELECT GROUP_CONCAT(COUNT(a)) FROM t2 WHERE m = a)
|
||||||
|
2 2 2
|
||||||
|
3 3 3
|
||||||
|
1 4 1,1
|
||||||
|
SELECT COUNT(*) c, a,
|
||||||
|
(SELECT GROUP_CONCAT(COUNT(a)+1) FROM t2 WHERE m = a)
|
||||||
|
FROM t1 GROUP BY a;
|
||||||
|
c a (SELECT GROUP_CONCAT(COUNT(a)+1) FROM t2 WHERE m = a)
|
||||||
|
2 2 3
|
||||||
|
3 3 4
|
||||||
|
1 4 2,2
|
||||||
|
DROP table t1,t2;
|
||||||
|
CREATE TABLE t1 (a int, b int);
|
||||||
|
INSERT INTO t1 VALUES (2,22),(1,11),(2,22);
|
||||||
|
SELECT a FROM t1 WHERE (SELECT COUNT(b) FROM DUAL) > 0 GROUP BY a;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
2
|
||||||
|
SELECT a FROM t1 WHERE (SELECT COUNT(b) FROM DUAL) > 1 GROUP BY a;
|
||||||
|
a
|
||||||
|
SELECT a FROM t1 t0
|
||||||
|
WHERE (SELECT COUNT(t0.b) FROM t1 t WHERE t.b>20) GROUP BY a;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
2
|
||||||
|
SET @@sql_mode='ansi';
|
||||||
|
SELECT a FROM t1 WHERE (SELECT COUNT(b) FROM DUAL) > 0 GROUP BY a;
|
||||||
|
ERROR HY000: Invalid use of group function
|
||||||
|
SELECT a FROM t1 WHERE (SELECT COUNT(b) FROM DUAL) > 1 GROUP BY a;
|
||||||
|
ERROR HY000: Invalid use of group function
|
||||||
|
SELECT a FROM t1 t0
|
||||||
|
WHERE (SELECT COUNT(t0.b) FROM t1 t WHERE t.b>20) GROUP BY a;
|
||||||
|
ERROR HY000: Invalid use of group function
|
||||||
|
SET @@sql_mode=default;
|
||||||
|
DROP TABLE t1;
|
||||||
CREATE TABLE t1 (s1 char(1));
|
CREATE TABLE t1 (s1 char(1));
|
||||||
INSERT INTO t1 VALUES ('a');
|
INSERT INTO t1 VALUES ('a');
|
||||||
SELECT * FROM t1 WHERE _utf8'a' = ANY (SELECT s1 FROM t1);
|
SELECT * FROM t1 WHERE _utf8'a' = ANY (SELECT s1 FROM t1);
|
||||||
|
@ -203,3 +203,21 @@ select * from t1 where a is null;
|
|||||||
delete from t1 where a is null;
|
delete from t1 where a is null;
|
||||||
select count(*) from t1;
|
select count(*) from t1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #26186: delete order by, sometimes accept unknown column
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (1);
|
||||||
|
|
||||||
|
--error ER_BAD_FIELD_ERROR
|
||||||
|
DELETE FROM t1 ORDER BY x;
|
||||||
|
|
||||||
|
# even columns from a table not used in query (and not even existing)
|
||||||
|
--error ER_BAD_FIELD_ERROR
|
||||||
|
DELETE FROM t1 ORDER BY t2.x;
|
||||||
|
|
||||||
|
# subquery (as long as the subquery from is valid or DUAL)
|
||||||
|
--error ER_BAD_FIELD_ERROR
|
||||||
|
DELETE FROM t1 ORDER BY (SELECT x);
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -424,6 +424,14 @@ from t1;
|
|||||||
|
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #27164: Crash when mixing InnoDB and MyISAM Geospatial tables
|
||||||
|
#
|
||||||
|
CREATE TABLE t1(a POINT) ENGINE=MyISAM;
|
||||||
|
INSERT INTO t1 VALUES (NULL);
|
||||||
|
SELECT * FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
--echo End of 4.1 tests
|
--echo End of 4.1 tests
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -755,7 +755,8 @@ SET SQL_MODE = '';
|
|||||||
|
|
||||||
#
|
#
|
||||||
# Bug #21174: Index degrades sort performance and
|
# Bug #21174: Index degrades sort performance and
|
||||||
# optimizer does not honor IGNORE INDEX
|
# optimizer does not honor IGNORE INDEX.
|
||||||
|
# a.k.a WL3527.
|
||||||
#
|
#
|
||||||
CREATE TABLE t1 (a INT, b INT,
|
CREATE TABLE t1 (a INT, b INT,
|
||||||
PRIMARY KEY (a),
|
PRIMARY KEY (a),
|
||||||
@ -819,4 +820,8 @@ EXPLAIN SELECT a, SUM(b) FROM t2 IGNORE INDEX (a) GROUP BY a LIMIT 2;
|
|||||||
EXPLAIN SELECT 1 FROM t2 WHERE a IN
|
EXPLAIN SELECT 1 FROM t2 WHERE a IN
|
||||||
(SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));
|
(SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));
|
||||||
|
|
||||||
|
SHOW VARIABLES LIKE 'old';
|
||||||
|
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
|
||||||
|
SET @@old = off;
|
||||||
|
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
@ -568,6 +568,38 @@ SELECT s.oxid FROM t1 v, t1 s
|
|||||||
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
# BUG#26624 high mem usage (crash) in range optimizer (depends on order of fields in where)
|
||||||
|
create table t1 (
|
||||||
|
c1 char(10), c2 char(10), c3 char(10), c4 char(10),
|
||||||
|
c5 char(10), c6 char(10), c7 char(10), c8 char(10),
|
||||||
|
c9 char(10), c10 char(10), c11 char(10), c12 char(10),
|
||||||
|
c13 char(10), c14 char(10), c15 char(10), c16 char(10),
|
||||||
|
index(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,c13,c14,c15,c16)
|
||||||
|
);
|
||||||
|
|
||||||
|
insert into t1 (c1) values ('1'),('1'),('1'),('1');
|
||||||
|
|
||||||
|
# This must run without crash and fast:
|
||||||
|
select * from t1 where
|
||||||
|
c1 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c2 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c3 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c4 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c5 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c6 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c7 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c8 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c9 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c10 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c11 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c12 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c13 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c14 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c15 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
and c16 in ("abcdefgh", "123456789", "qwertyuio", "asddfgh")
|
||||||
|
;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
--echo End of 4.1 tests
|
--echo End of 4.1 tests
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -447,3 +447,21 @@ DROP PROCEDURE p1;
|
|||||||
|
|
||||||
|
|
||||||
--echo End of 5.0 tests.
|
--echo End of 5.0 tests.
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #26303: reserve() not called before qs_append() may lead to buffer
|
||||||
|
# overflow
|
||||||
|
#
|
||||||
|
DELIMITER //;
|
||||||
|
CREATE PROCEDURE p1()
|
||||||
|
BEGIN
|
||||||
|
DECLARE dummy int default 0;
|
||||||
|
|
||||||
|
CASE 12
|
||||||
|
WHEN 12
|
||||||
|
THEN SET dummy = 0;
|
||||||
|
END CASE;
|
||||||
|
END//
|
||||||
|
DELIMITER ;//
|
||||||
|
SHOW PROCEDURE CODE p1;
|
||||||
|
DROP PROCEDURE p1;
|
||||||
|
@ -2765,6 +2765,50 @@ SELECT COUNT(*), a
|
|||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
|
|
||||||
#
|
#
|
||||||
|
# Bug #27229: GROUP_CONCAT in subselect with COUNT() as an argument
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a int, b int);
|
||||||
|
CREATE TABLE t2 (m int, n int);
|
||||||
|
INSERT INTO t1 VALUES (2,2), (2,2), (3,3), (3,3), (3,3), (4,4);
|
||||||
|
INSERT INTO t2 VALUES (1,11), (2,22), (3,32), (4,44), (4,44);
|
||||||
|
|
||||||
|
SELECT COUNT(*) c, a,
|
||||||
|
(SELECT GROUP_CONCAT(COUNT(a)) FROM t2 WHERE m = a)
|
||||||
|
FROM t1 GROUP BY a;
|
||||||
|
|
||||||
|
SELECT COUNT(*) c, a,
|
||||||
|
(SELECT GROUP_CONCAT(COUNT(a)+1) FROM t2 WHERE m = a)
|
||||||
|
FROM t1 GROUP BY a;
|
||||||
|
|
||||||
|
DROP table t1,t2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #27348: SET FUNCTION used in a subquery from WHERE condition
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a int, b int);
|
||||||
|
INSERT INTO t1 VALUES (2,22),(1,11),(2,22);
|
||||||
|
|
||||||
|
SELECT a FROM t1 WHERE (SELECT COUNT(b) FROM DUAL) > 0 GROUP BY a;
|
||||||
|
SELECT a FROM t1 WHERE (SELECT COUNT(b) FROM DUAL) > 1 GROUP BY a;
|
||||||
|
|
||||||
|
SELECT a FROM t1 t0
|
||||||
|
WHERE (SELECT COUNT(t0.b) FROM t1 t WHERE t.b>20) GROUP BY a;
|
||||||
|
|
||||||
|
SET @@sql_mode='ansi';
|
||||||
|
--error 1111
|
||||||
|
SELECT a FROM t1 WHERE (SELECT COUNT(b) FROM DUAL) > 0 GROUP BY a;
|
||||||
|
--error 1111
|
||||||
|
SELECT a FROM t1 WHERE (SELECT COUNT(b) FROM DUAL) > 1 GROUP BY a;
|
||||||
|
|
||||||
|
--error 1111
|
||||||
|
SELECT a FROM t1 t0
|
||||||
|
WHERE (SELECT COUNT(t0.b) FROM t1 t WHERE t.b>20) GROUP BY a;
|
||||||
|
|
||||||
|
SET @@sql_mode=default;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
# Bug#20835 (literal string with =any values)
|
# Bug#20835 (literal string with =any values)
|
||||||
#
|
#
|
||||||
CREATE TABLE t1 (s1 char(1));
|
CREATE TABLE t1 (s1 char(1));
|
||||||
|
@ -1353,7 +1353,7 @@ public:
|
|||||||
int store_decimal(const my_decimal *);
|
int store_decimal(const my_decimal *);
|
||||||
void get_key_image(char *buff,uint length,imagetype type);
|
void get_key_image(char *buff,uint length,imagetype type);
|
||||||
uint size_of() const { return sizeof(*this); }
|
uint size_of() const { return sizeof(*this); }
|
||||||
int reset(void) { return !maybe_null(); }
|
int reset(void) { return !maybe_null() || Field_blob::reset(); }
|
||||||
};
|
};
|
||||||
#endif /*HAVE_SPATIAL*/
|
#endif /*HAVE_SPATIAL*/
|
||||||
|
|
||||||
|
13
sql/item.cc
13
sql/item.cc
@ -1088,7 +1088,7 @@ bool Item_splocal::set_value(THD *thd, sp_rcontext *ctx, Item **it)
|
|||||||
Item_case_expr methods
|
Item_case_expr methods
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
Item_case_expr::Item_case_expr(int case_expr_id)
|
Item_case_expr::Item_case_expr(uint case_expr_id)
|
||||||
:Item_sp_variable( C_STRING_WITH_LEN("case_expr")),
|
:Item_sp_variable( C_STRING_WITH_LEN("case_expr")),
|
||||||
m_case_expr_id(case_expr_id)
|
m_case_expr_id(case_expr_id)
|
||||||
{
|
{
|
||||||
@ -1125,6 +1125,8 @@ Item_case_expr::this_item_addr(THD *thd, Item **)
|
|||||||
|
|
||||||
void Item_case_expr::print(String *str)
|
void Item_case_expr::print(String *str)
|
||||||
{
|
{
|
||||||
|
if (str->reserve(MAX_INT_WIDTH + sizeof("case_expr@")))
|
||||||
|
return; /* purecov: inspected */
|
||||||
VOID(str->append(STRING_WITH_LEN("case_expr@")));
|
VOID(str->append(STRING_WITH_LEN("case_expr@")));
|
||||||
str->qs_append(m_case_expr_id);
|
str->qs_append(m_case_expr_id);
|
||||||
}
|
}
|
||||||
@ -1289,15 +1291,18 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
|
|||||||
Exception is Item_direct_view_ref which we need to convert to
|
Exception is Item_direct_view_ref which we need to convert to
|
||||||
Item_ref to allow fields from view being stored in tmp table.
|
Item_ref to allow fields from view being stored in tmp table.
|
||||||
*/
|
*/
|
||||||
|
Item_aggregate_ref *item_ref;
|
||||||
uint el= fields.elements;
|
uint el= fields.elements;
|
||||||
Item *new_item, *real_itm= real_item();
|
Item *real_itm= real_item();
|
||||||
|
|
||||||
ref_pointer_array[el]= real_itm;
|
ref_pointer_array[el]= real_itm;
|
||||||
if (!(new_item= new Item_aggregate_ref(&thd->lex->current_select->context,
|
if (!(item_ref= new Item_aggregate_ref(&thd->lex->current_select->context,
|
||||||
ref_pointer_array + el, 0, name)))
|
ref_pointer_array + el, 0, name)))
|
||||||
return; // fatal_error is set
|
return; // fatal_error is set
|
||||||
|
if (type() == SUM_FUNC_ITEM)
|
||||||
|
item_ref->depended_from= ((Item_sum *) this)->depended_from();
|
||||||
fields.push_front(real_itm);
|
fields.push_front(real_itm);
|
||||||
thd->change_item_tree(ref, new_item);
|
thd->change_item_tree(ref, item_ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1116,7 +1116,7 @@ inline Item_result Item_splocal::result_type() const
|
|||||||
class Item_case_expr :public Item_sp_variable
|
class Item_case_expr :public Item_sp_variable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_case_expr(int case_expr_id);
|
Item_case_expr(uint case_expr_id);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Item *this_item();
|
Item *this_item();
|
||||||
@ -1135,7 +1135,7 @@ public:
|
|||||||
void print(String *str);
|
void print(String *str);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_case_expr_id;
|
uint m_case_expr_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
@ -61,9 +61,9 @@ bool Item_sum::init_sum_func_check(THD *thd)
|
|||||||
/* Save a pointer to object to be used in items for nested set functions */
|
/* Save a pointer to object to be used in items for nested set functions */
|
||||||
thd->lex->in_sum_func= this;
|
thd->lex->in_sum_func= this;
|
||||||
nest_level= thd->lex->current_select->nest_level;
|
nest_level= thd->lex->current_select->nest_level;
|
||||||
nest_level_tables_count= thd->lex->current_select->join->tables;
|
|
||||||
ref_by= 0;
|
ref_by= 0;
|
||||||
aggr_level= -1;
|
aggr_level= -1;
|
||||||
|
aggr_sel= NULL;
|
||||||
max_arg_level= -1;
|
max_arg_level= -1;
|
||||||
max_sum_func_level= -1;
|
max_sum_func_level= -1;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -149,9 +149,14 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
|
|||||||
if (register_sum_func(thd, ref))
|
if (register_sum_func(thd, ref))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
invalid= aggr_level < 0 && !(allow_sum_func & (1 << nest_level));
|
invalid= aggr_level < 0 && !(allow_sum_func & (1 << nest_level));
|
||||||
|
if (!invalid && thd->variables.sql_mode & MODE_ANSI)
|
||||||
|
invalid= aggr_level < 0 && max_arg_level < nest_level;
|
||||||
}
|
}
|
||||||
if (!invalid && aggr_level < 0)
|
if (!invalid && aggr_level < 0)
|
||||||
|
{
|
||||||
aggr_level= nest_level;
|
aggr_level= nest_level;
|
||||||
|
aggr_sel= thd->lex->current_select;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
By this moment we either found a subquery where the set function is
|
By this moment we either found a subquery where the set function is
|
||||||
to be aggregated and assigned a value that is >= 0 to aggr_level,
|
to be aggregated and assigned a value that is >= 0 to aggr_level,
|
||||||
@ -161,8 +166,9 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
|
|||||||
Additionally we have to check whether possible nested set functions
|
Additionally we have to check whether possible nested set functions
|
||||||
are acceptable here: they are not, if the level of aggregation of
|
are acceptable here: they are not, if the level of aggregation of
|
||||||
some of them is less than aggr_level.
|
some of them is less than aggr_level.
|
||||||
*/
|
*/
|
||||||
invalid= aggr_level <= max_sum_func_level;
|
if (!invalid)
|
||||||
|
invalid= aggr_level <= max_sum_func_level;
|
||||||
if (invalid)
|
if (invalid)
|
||||||
{
|
{
|
||||||
my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE),
|
my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE),
|
||||||
@ -212,7 +218,6 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
|
|||||||
bool Item_sum::register_sum_func(THD *thd, Item **ref)
|
bool Item_sum::register_sum_func(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
SELECT_LEX *sl;
|
SELECT_LEX *sl;
|
||||||
SELECT_LEX *aggr_sl= NULL;
|
|
||||||
nesting_map allow_sum_func= thd->lex->allow_sum_func;
|
nesting_map allow_sum_func= thd->lex->allow_sum_func;
|
||||||
for (sl= thd->lex->current_select->master_unit()->outer_select() ;
|
for (sl= thd->lex->current_select->master_unit()->outer_select() ;
|
||||||
sl && sl->nest_level > max_arg_level;
|
sl && sl->nest_level > max_arg_level;
|
||||||
@ -222,7 +227,7 @@ bool Item_sum::register_sum_func(THD *thd, Item **ref)
|
|||||||
{
|
{
|
||||||
/* Found the most nested subquery where the function can be aggregated */
|
/* Found the most nested subquery where the function can be aggregated */
|
||||||
aggr_level= sl->nest_level;
|
aggr_level= sl->nest_level;
|
||||||
aggr_sl= sl;
|
aggr_sel= sl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sl && (allow_sum_func & (1 << sl->nest_level)))
|
if (sl && (allow_sum_func & (1 << sl->nest_level)))
|
||||||
@ -233,21 +238,22 @@ bool Item_sum::register_sum_func(THD *thd, Item **ref)
|
|||||||
The set function will be aggregated in this subquery.
|
The set function will be aggregated in this subquery.
|
||||||
*/
|
*/
|
||||||
aggr_level= sl->nest_level;
|
aggr_level= sl->nest_level;
|
||||||
aggr_sl= sl;
|
aggr_sel= sl;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (aggr_level >= 0)
|
if (aggr_level >= 0)
|
||||||
{
|
{
|
||||||
ref_by= ref;
|
ref_by= ref;
|
||||||
/* Add the object to the list of registered objects assigned to aggr_sl */
|
/* Add the object to the list of registered objects assigned to aggr_sel */
|
||||||
if (!aggr_sl->inner_sum_func_list)
|
if (!aggr_sel->inner_sum_func_list)
|
||||||
next= this;
|
next= this;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
next= aggr_sl->inner_sum_func_list->next;
|
next= aggr_sel->inner_sum_func_list->next;
|
||||||
aggr_sl->inner_sum_func_list->next= this;
|
aggr_sel->inner_sum_func_list->next= this;
|
||||||
}
|
}
|
||||||
aggr_sl->inner_sum_func_list= this;
|
aggr_sel->inner_sum_func_list= this;
|
||||||
aggr_sl->with_sum_func= 1;
|
aggr_sel->with_sum_func= 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Mark Item_subselect(s) as containing aggregate function all the way up
|
Mark Item_subselect(s) as containing aggregate function all the way up
|
||||||
@ -265,11 +271,11 @@ bool Item_sum::register_sum_func(THD *thd, Item **ref)
|
|||||||
has aggregate functions directly referenced (i.e. not through a sub-select).
|
has aggregate functions directly referenced (i.e. not through a sub-select).
|
||||||
*/
|
*/
|
||||||
for (sl= thd->lex->current_select;
|
for (sl= thd->lex->current_select;
|
||||||
sl && sl != aggr_sl && sl->master_unit()->item;
|
sl && sl != aggr_sel && sl->master_unit()->item;
|
||||||
sl= sl->master_unit()->outer_select() )
|
sl= sl->master_unit()->outer_select() )
|
||||||
sl->master_unit()->item->with_sum_func= 1;
|
sl->master_unit()->item->with_sum_func= 1;
|
||||||
}
|
}
|
||||||
thd->lex->current_select->mark_as_dependent(aggr_sl);
|
thd->lex->current_select->mark_as_dependent(aggr_sel);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,10 +305,10 @@ Item_sum::Item_sum(List<Item> &list) :arg_count(list.elements),
|
|||||||
|
|
||||||
Item_sum::Item_sum(THD *thd, Item_sum *item):
|
Item_sum::Item_sum(THD *thd, Item_sum *item):
|
||||||
Item_result_field(thd, item), arg_count(item->arg_count),
|
Item_result_field(thd, item), arg_count(item->arg_count),
|
||||||
|
aggr_sel(item->aggr_sel),
|
||||||
nest_level(item->nest_level), aggr_level(item->aggr_level),
|
nest_level(item->nest_level), aggr_level(item->aggr_level),
|
||||||
quick_group(item->quick_group), used_tables_cache(item->used_tables_cache),
|
quick_group(item->quick_group), used_tables_cache(item->used_tables_cache),
|
||||||
forced_const(item->forced_const),
|
forced_const(item->forced_const)
|
||||||
nest_level_tables_count(item->nest_level_tables_count)
|
|
||||||
{
|
{
|
||||||
if (arg_count <= 2)
|
if (arg_count <= 2)
|
||||||
args=tmp_args;
|
args=tmp_args;
|
||||||
@ -449,8 +455,7 @@ void Item_sum::update_used_tables ()
|
|||||||
used_tables_cache&= PSEUDO_TABLE_BITS;
|
used_tables_cache&= PSEUDO_TABLE_BITS;
|
||||||
|
|
||||||
/* the aggregate function is aggregated into its local context */
|
/* the aggregate function is aggregated into its local context */
|
||||||
if (aggr_level == nest_level)
|
used_tables_cache |= (1 << aggr_sel->join->tables) - 1;
|
||||||
used_tables_cache |= (1 << nest_level_tables_count) - 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,6 +233,7 @@ public:
|
|||||||
Item_sum *next; /* next in the circular chain of registered objects */
|
Item_sum *next; /* next in the circular chain of registered objects */
|
||||||
uint arg_count;
|
uint arg_count;
|
||||||
Item_sum *in_sum_func; /* embedding set function if any */
|
Item_sum *in_sum_func; /* embedding set function if any */
|
||||||
|
st_select_lex * aggr_sel; /* select where the function is aggregated */
|
||||||
int8 nest_level; /* number of the nesting level of the set function */
|
int8 nest_level; /* number of the nesting level of the set function */
|
||||||
int8 aggr_level; /* nesting level of the aggregating subquery */
|
int8 aggr_level; /* nesting level of the aggregating subquery */
|
||||||
int8 max_arg_level; /* max level of unbound column references */
|
int8 max_arg_level; /* max level of unbound column references */
|
||||||
@ -242,7 +243,6 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
table_map used_tables_cache;
|
table_map used_tables_cache;
|
||||||
bool forced_const;
|
bool forced_const;
|
||||||
byte nest_level_tables_count;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -365,6 +365,8 @@ public:
|
|||||||
bool init_sum_func_check(THD *thd);
|
bool init_sum_func_check(THD *thd);
|
||||||
bool check_sum_func(THD *thd, Item **ref);
|
bool check_sum_func(THD *thd, Item **ref);
|
||||||
bool register_sum_func(THD *thd, Item **ref);
|
bool register_sum_func(THD *thd, Item **ref);
|
||||||
|
st_select_lex *depended_from()
|
||||||
|
{ return (nest_level == aggr_level ? 0 : aggr_sel); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -6271,7 +6271,7 @@ The minimum value for this variable is 4096.",
|
|||||||
(gptr*) &global_system_variables.net_write_timeout,
|
(gptr*) &global_system_variables.net_write_timeout,
|
||||||
(gptr*) &max_system_variables.net_write_timeout, 0, GET_ULONG,
|
(gptr*) &max_system_variables.net_write_timeout, 0, GET_ULONG,
|
||||||
REQUIRED_ARG, NET_WRITE_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
|
REQUIRED_ARG, NET_WRITE_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
|
||||||
{ "old_mode", OPT_OLD_MODE, "Use compatible behaviour.",
|
{ "old", OPT_OLD_MODE, "Use compatible behavior.",
|
||||||
(gptr*) &global_system_variables.old_mode,
|
(gptr*) &global_system_variables.old_mode,
|
||||||
(gptr*) &max_system_variables.old_mode, 0, GET_BOOL, NO_ARG,
|
(gptr*) &max_system_variables.old_mode, 0, GET_BOOL, NO_ARG,
|
||||||
0, 0, 0, 0, 0, 0},
|
0, 0, 0, 0, 0, 0},
|
||||||
|
174
sql/opt_range.cc
174
sql/opt_range.cc
@ -84,7 +84,7 @@ static int sel_cmp(Field *f,char *a,char *b,uint8 a_flag,uint8 b_flag);
|
|||||||
|
|
||||||
static char is_null_string[2]= {1,0};
|
static char is_null_string[2]= {1,0};
|
||||||
|
|
||||||
|
class RANGE_OPT_PARAM;
|
||||||
/*
|
/*
|
||||||
A construction block of the SEL_ARG-graph.
|
A construction block of the SEL_ARG-graph.
|
||||||
|
|
||||||
@ -170,6 +170,89 @@ static char is_null_string[2]= {1,0};
|
|||||||
- get_quick_select() - Walk the SEL_ARG, materialize the key intervals,
|
- get_quick_select() - Walk the SEL_ARG, materialize the key intervals,
|
||||||
and create QUICK_RANGE_SELECT object that will
|
and create QUICK_RANGE_SELECT object that will
|
||||||
read records within these intervals.
|
read records within these intervals.
|
||||||
|
|
||||||
|
4. SPACE COMPLEXITY NOTES
|
||||||
|
|
||||||
|
SEL_ARG graph is a representation of an ordered disjoint sequence of
|
||||||
|
intervals over the ordered set of index tuple values.
|
||||||
|
|
||||||
|
For multi-part keys, one can construct a WHERE expression such that its
|
||||||
|
list of intervals will be of combinatorial size. Here is an example:
|
||||||
|
|
||||||
|
(keypart1 IN (1,2, ..., n1)) AND
|
||||||
|
(keypart2 IN (1,2, ..., n2)) AND
|
||||||
|
(keypart3 IN (1,2, ..., n3))
|
||||||
|
|
||||||
|
For this WHERE clause the list of intervals will have n1*n2*n3 intervals
|
||||||
|
of form
|
||||||
|
|
||||||
|
(keypart1, keypart2, keypart3) = (k1, k2, k3), where 1 <= k{i} <= n{i}
|
||||||
|
|
||||||
|
SEL_ARG graph structure aims to reduce the amount of required space by
|
||||||
|
"sharing" the elementary intervals when possible (the pic at the
|
||||||
|
beginning of this comment has examples of such sharing). The sharing may
|
||||||
|
prevent combinatorial blowup:
|
||||||
|
|
||||||
|
There are WHERE clauses that have combinatorial-size interval lists but
|
||||||
|
will be represented by a compact SEL_ARG graph.
|
||||||
|
Example:
|
||||||
|
(keypartN IN (1,2, ..., n1)) AND
|
||||||
|
...
|
||||||
|
(keypart2 IN (1,2, ..., n2)) AND
|
||||||
|
(keypart1 IN (1,2, ..., n3))
|
||||||
|
|
||||||
|
but not in all cases:
|
||||||
|
|
||||||
|
- There are WHERE clauses that do have a compact SEL_ARG-graph
|
||||||
|
representation but get_mm_tree() and its callees will construct a
|
||||||
|
graph of combinatorial size.
|
||||||
|
Example:
|
||||||
|
(keypart1 IN (1,2, ..., n1)) AND
|
||||||
|
(keypart2 IN (1,2, ..., n2)) AND
|
||||||
|
...
|
||||||
|
(keypartN IN (1,2, ..., n3))
|
||||||
|
|
||||||
|
- There are WHERE clauses for which the minimal possible SEL_ARG graph
|
||||||
|
representation will have combinatorial size.
|
||||||
|
Example:
|
||||||
|
By induction: Let's take any interval on some keypart in the middle:
|
||||||
|
|
||||||
|
kp15=c0
|
||||||
|
|
||||||
|
Then let's AND it with this interval 'structure' from preceding and
|
||||||
|
following keyparts:
|
||||||
|
|
||||||
|
(kp14=c1 AND kp16=c3) OR keypart14=c2) (*)
|
||||||
|
|
||||||
|
We will obtain this SEL_ARG graph:
|
||||||
|
|
||||||
|
kp14 $ kp15 $ kp16
|
||||||
|
$ $
|
||||||
|
+---------+ $ +---------+ $ +---------+
|
||||||
|
| kp14=c1 |--$-->| kp15=c0 |--$-->| kp16=c3 |
|
||||||
|
+---------+ $ +---------+ $ +---------+
|
||||||
|
| $ $
|
||||||
|
+---------+ $ +---------+ $
|
||||||
|
| kp14=c2 |--$-->| kp15=c0 | $
|
||||||
|
+---------+ $ +---------+ $
|
||||||
|
$ $
|
||||||
|
|
||||||
|
Note that we had to duplicate "kp15=c0" and there was no way to avoid
|
||||||
|
that.
|
||||||
|
The induction step: AND the obtained expression with another "wrapping"
|
||||||
|
expression like (*).
|
||||||
|
When the process ends because of the limit on max. number of keyparts
|
||||||
|
we'll have:
|
||||||
|
|
||||||
|
WHERE clause length is O(3*#max_keyparts)
|
||||||
|
SEL_ARG graph size is O(2^(#max_keyparts/2))
|
||||||
|
|
||||||
|
(it is also possible to construct a case where instead of 2 in 2^n we
|
||||||
|
have a bigger constant, e.g. 4, and get a graph with 4^(31/2)= 2^31
|
||||||
|
nodes)
|
||||||
|
|
||||||
|
We avoid consuming too much memory by setting a limit on the number of
|
||||||
|
SEL_ARG object we can construct during one range analysis invocation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class SEL_ARG :public Sql_alloc
|
class SEL_ARG :public Sql_alloc
|
||||||
@ -200,6 +283,8 @@ public:
|
|||||||
enum leaf_color { BLACK,RED } color;
|
enum leaf_color { BLACK,RED } color;
|
||||||
enum Type { IMPOSSIBLE, MAYBE, MAYBE_KEY, KEY_RANGE } type;
|
enum Type { IMPOSSIBLE, MAYBE, MAYBE_KEY, KEY_RANGE } type;
|
||||||
|
|
||||||
|
enum { MAX_SEL_ARGS = 64000 };
|
||||||
|
|
||||||
SEL_ARG() {}
|
SEL_ARG() {}
|
||||||
SEL_ARG(SEL_ARG &);
|
SEL_ARG(SEL_ARG &);
|
||||||
SEL_ARG(Field *,const char *,const char *);
|
SEL_ARG(Field *,const char *,const char *);
|
||||||
@ -271,7 +356,7 @@ public:
|
|||||||
return new SEL_ARG(field, part, min_value, arg->max_value,
|
return new SEL_ARG(field, part, min_value, arg->max_value,
|
||||||
min_flag, arg->max_flag, maybe_flag | arg->maybe_flag);
|
min_flag, arg->max_flag, maybe_flag | arg->maybe_flag);
|
||||||
}
|
}
|
||||||
SEL_ARG *clone(SEL_ARG *new_parent,SEL_ARG **next);
|
SEL_ARG *clone(RANGE_OPT_PARAM *param, SEL_ARG *new_parent, SEL_ARG **next);
|
||||||
|
|
||||||
bool copy_min(SEL_ARG* arg)
|
bool copy_min(SEL_ARG* arg)
|
||||||
{ // Get overlapping range
|
{ // Get overlapping range
|
||||||
@ -423,7 +508,6 @@ public:
|
|||||||
{
|
{
|
||||||
return parent->left == this ? &parent->left : &parent->right;
|
return parent->left == this ? &parent->left : &parent->right;
|
||||||
}
|
}
|
||||||
SEL_ARG *clone_tree();
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -466,6 +550,7 @@ public:
|
|||||||
}
|
}
|
||||||
return !field->key_cmp(min_val, max_val);
|
return !field->key_cmp(min_val, max_val);
|
||||||
}
|
}
|
||||||
|
SEL_ARG *clone_tree(RANGE_OPT_PARAM *param);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SEL_IMERGE;
|
class SEL_IMERGE;
|
||||||
@ -545,6 +630,8 @@ public:
|
|||||||
using_real_indexes==TRUE
|
using_real_indexes==TRUE
|
||||||
*/
|
*/
|
||||||
uint real_keynr[MAX_KEY];
|
uint real_keynr[MAX_KEY];
|
||||||
|
/* Number of SEL_ARG objects allocated by SEL_ARG::clone_tree operations */
|
||||||
|
uint alloced_sel_args;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PARAM : public RANGE_OPT_PARAM
|
class PARAM : public RANGE_OPT_PARAM
|
||||||
@ -634,8 +721,9 @@ static void print_quick(QUICK_SELECT_I *quick, const key_map *needed_reg);
|
|||||||
static SEL_TREE *tree_and(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2);
|
static SEL_TREE *tree_and(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2);
|
||||||
static SEL_TREE *tree_or(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2);
|
static SEL_TREE *tree_or(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2);
|
||||||
static SEL_ARG *sel_add(SEL_ARG *key1,SEL_ARG *key2);
|
static SEL_ARG *sel_add(SEL_ARG *key1,SEL_ARG *key2);
|
||||||
static SEL_ARG *key_or(SEL_ARG *key1,SEL_ARG *key2);
|
static SEL_ARG *key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2);
|
||||||
static SEL_ARG *key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag);
|
static SEL_ARG *key_and(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2,
|
||||||
|
uint clone_flag);
|
||||||
static bool get_range(SEL_ARG **e1,SEL_ARG **e2,SEL_ARG *root1);
|
static bool get_range(SEL_ARG **e1,SEL_ARG **e2,SEL_ARG *root1);
|
||||||
bool get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
|
bool get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
|
||||||
SEL_ARG *key_tree,char *min_key,uint min_key_flag,
|
SEL_ARG *key_tree,char *min_key,uint min_key_flag,
|
||||||
@ -860,6 +948,7 @@ int imerge_list_or_tree(RANGE_OPT_PARAM *param,
|
|||||||
return im1->is_empty();
|
return im1->is_empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
** Basic functions for SQL_SELECT and QUICK_RANGE_SELECT
|
** Basic functions for SQL_SELECT and QUICK_RANGE_SELECT
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
@ -1510,12 +1599,18 @@ SEL_ARG::SEL_ARG(Field *field_,uint8 part_,char *min_value_,char *max_value_,
|
|||||||
left=right= &null_element;
|
left=right= &null_element;
|
||||||
}
|
}
|
||||||
|
|
||||||
SEL_ARG *SEL_ARG::clone(SEL_ARG *new_parent,SEL_ARG **next_arg)
|
SEL_ARG *SEL_ARG::clone(RANGE_OPT_PARAM *param, SEL_ARG *new_parent,
|
||||||
|
SEL_ARG **next_arg)
|
||||||
{
|
{
|
||||||
SEL_ARG *tmp;
|
SEL_ARG *tmp;
|
||||||
|
|
||||||
|
/* Bail out if we have already generated too many SEL_ARGs */
|
||||||
|
if (++param->alloced_sel_args > MAX_SEL_ARGS)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (type != KEY_RANGE)
|
if (type != KEY_RANGE)
|
||||||
{
|
{
|
||||||
if (!(tmp= new SEL_ARG(type)))
|
if (!(tmp= new (param->mem_root) SEL_ARG(type)))
|
||||||
return 0; // out of memory
|
return 0; // out of memory
|
||||||
tmp->prev= *next_arg; // Link into next/prev chain
|
tmp->prev= *next_arg; // Link into next/prev chain
|
||||||
(*next_arg)->next=tmp;
|
(*next_arg)->next=tmp;
|
||||||
@ -1523,20 +1618,21 @@ SEL_ARG *SEL_ARG::clone(SEL_ARG *new_parent,SEL_ARG **next_arg)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!(tmp= new SEL_ARG(field,part, min_value,max_value,
|
if (!(tmp= new (param->mem_root) SEL_ARG(field,part, min_value,max_value,
|
||||||
min_flag, max_flag, maybe_flag)))
|
min_flag, max_flag, maybe_flag)))
|
||||||
return 0; // OOM
|
return 0; // OOM
|
||||||
tmp->parent=new_parent;
|
tmp->parent=new_parent;
|
||||||
tmp->next_key_part=next_key_part;
|
tmp->next_key_part=next_key_part;
|
||||||
if (left != &null_element)
|
if (left != &null_element)
|
||||||
tmp->left=left->clone(tmp,next_arg);
|
if (!(tmp->left=left->clone(param, tmp, next_arg)))
|
||||||
|
return 0; // OOM
|
||||||
|
|
||||||
tmp->prev= *next_arg; // Link into next/prev chain
|
tmp->prev= *next_arg; // Link into next/prev chain
|
||||||
(*next_arg)->next=tmp;
|
(*next_arg)->next=tmp;
|
||||||
(*next_arg)= tmp;
|
(*next_arg)= tmp;
|
||||||
|
|
||||||
if (right != &null_element)
|
if (right != &null_element)
|
||||||
if (!(tmp->right= right->clone(tmp,next_arg)))
|
if (!(tmp->right= right->clone(param, tmp, next_arg)))
|
||||||
return 0; // OOM
|
return 0; // OOM
|
||||||
}
|
}
|
||||||
increment_use_count(1);
|
increment_use_count(1);
|
||||||
@ -1614,11 +1710,12 @@ static int sel_cmp(Field *field, char *a,char *b,uint8 a_flag,uint8 b_flag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SEL_ARG *SEL_ARG::clone_tree()
|
SEL_ARG *SEL_ARG::clone_tree(RANGE_OPT_PARAM *param)
|
||||||
{
|
{
|
||||||
SEL_ARG tmp_link,*next_arg,*root;
|
SEL_ARG tmp_link,*next_arg,*root;
|
||||||
next_arg= &tmp_link;
|
next_arg= &tmp_link;
|
||||||
root= clone((SEL_ARG *) 0, &next_arg);
|
if (!(root= clone(param, (SEL_ARG *) 0, &next_arg)))
|
||||||
|
return 0;
|
||||||
next_arg->next=0; // Fix last link
|
next_arg->next=0; // Fix last link
|
||||||
tmp_link.next->prev=0; // Fix first link
|
tmp_link.next->prev=0; // Fix first link
|
||||||
if (root) // If not OOM
|
if (root) // If not OOM
|
||||||
@ -2120,6 +2217,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
|
|||||||
param.real_keynr[param.keys++]=idx;
|
param.real_keynr[param.keys++]=idx;
|
||||||
}
|
}
|
||||||
param.key_parts_end=key_parts;
|
param.key_parts_end=key_parts;
|
||||||
|
param.alloced_sel_args= 0;
|
||||||
|
|
||||||
/* Calculate cost of full index read for the shortest covering index */
|
/* Calculate cost of full index read for the shortest covering index */
|
||||||
if (!head->covering_keys.is_clear_all())
|
if (!head->covering_keys.is_clear_all())
|
||||||
@ -2512,6 +2610,7 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond)
|
|||||||
range_par->using_real_indexes= FALSE;
|
range_par->using_real_indexes= FALSE;
|
||||||
range_par->remove_jump_scans= FALSE;
|
range_par->remove_jump_scans= FALSE;
|
||||||
range_par->real_keynr[0]= 0;
|
range_par->real_keynr[0]= 0;
|
||||||
|
range_par->alloced_sel_args= 0;
|
||||||
|
|
||||||
thd->no_errors=1; // Don't warn about NULL
|
thd->no_errors=1; // Don't warn about NULL
|
||||||
thd->mem_root=&alloc;
|
thd->mem_root=&alloc;
|
||||||
@ -5242,7 +5341,8 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param,COND *cond)
|
|||||||
while ((item=li++))
|
while ((item=li++))
|
||||||
{
|
{
|
||||||
SEL_TREE *new_tree=get_mm_tree(param,item);
|
SEL_TREE *new_tree=get_mm_tree(param,item);
|
||||||
if (param->thd->is_fatal_error)
|
if (param->thd->is_fatal_error ||
|
||||||
|
param->alloced_sel_args > SEL_ARG::MAX_SEL_ARGS)
|
||||||
DBUG_RETURN(0); // out of memory
|
DBUG_RETURN(0); // out of memory
|
||||||
tree=tree_and(param,tree,new_tree);
|
tree=tree_and(param,tree,new_tree);
|
||||||
if (tree && tree->type == SEL_TREE::IMPOSSIBLE)
|
if (tree && tree->type == SEL_TREE::IMPOSSIBLE)
|
||||||
@ -5818,9 +5918,9 @@ tree_and(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
|
|||||||
tree1->type=SEL_TREE::KEY_SMALLER;
|
tree1->type=SEL_TREE::KEY_SMALLER;
|
||||||
DBUG_RETURN(tree1);
|
DBUG_RETURN(tree1);
|
||||||
}
|
}
|
||||||
|
|
||||||
key_map result_keys;
|
key_map result_keys;
|
||||||
result_keys.clear_all();
|
result_keys.clear_all();
|
||||||
|
|
||||||
/* Join the trees key per key */
|
/* Join the trees key per key */
|
||||||
SEL_ARG **key1,**key2,**end;
|
SEL_ARG **key1,**key2,**end;
|
||||||
for (key1= tree1->keys,key2= tree2->keys,end=key1+param->keys ;
|
for (key1= tree1->keys,key2= tree2->keys,end=key1+param->keys ;
|
||||||
@ -5833,7 +5933,7 @@ tree_and(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
|
|||||||
flag|=CLONE_KEY1_MAYBE;
|
flag|=CLONE_KEY1_MAYBE;
|
||||||
if (*key2 && !(*key2)->simple_key())
|
if (*key2 && !(*key2)->simple_key())
|
||||||
flag|=CLONE_KEY2_MAYBE;
|
flag|=CLONE_KEY2_MAYBE;
|
||||||
*key1=key_and(*key1,*key2,flag);
|
*key1=key_and(param, *key1, *key2, flag);
|
||||||
if (*key1 && (*key1)->type == SEL_ARG::IMPOSSIBLE)
|
if (*key1 && (*key1)->type == SEL_ARG::IMPOSSIBLE)
|
||||||
{
|
{
|
||||||
tree1->type= SEL_TREE::IMPOSSIBLE;
|
tree1->type= SEL_TREE::IMPOSSIBLE;
|
||||||
@ -5994,7 +6094,7 @@ tree_or(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
|
|||||||
for (key1= tree1->keys,key2= tree2->keys,end= key1+param->keys ;
|
for (key1= tree1->keys,key2= tree2->keys,end= key1+param->keys ;
|
||||||
key1 != end ; key1++,key2++)
|
key1 != end ; key1++,key2++)
|
||||||
{
|
{
|
||||||
*key1=key_or(*key1,*key2);
|
*key1=key_or(param, *key1, *key2);
|
||||||
if (*key1)
|
if (*key1)
|
||||||
{
|
{
|
||||||
result=tree1; // Added to tree1
|
result=tree1; // Added to tree1
|
||||||
@ -6058,14 +6158,15 @@ tree_or(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
|
|||||||
/* And key trees where key1->part < key2 -> part */
|
/* And key trees where key1->part < key2 -> part */
|
||||||
|
|
||||||
static SEL_ARG *
|
static SEL_ARG *
|
||||||
and_all_keys(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
|
and_all_keys(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2,
|
||||||
|
uint clone_flag)
|
||||||
{
|
{
|
||||||
SEL_ARG *next;
|
SEL_ARG *next;
|
||||||
ulong use_count=key1->use_count;
|
ulong use_count=key1->use_count;
|
||||||
|
|
||||||
if (key1->elements != 1)
|
if (key1->elements != 1)
|
||||||
{
|
{
|
||||||
key2->use_count+=key1->elements-1;
|
key2->use_count+=key1->elements-1; //psergey: why we don't count that key1 has n-k-p?
|
||||||
key2->increment_use_count((int) key1->elements-1);
|
key2->increment_use_count((int) key1->elements-1);
|
||||||
}
|
}
|
||||||
if (key1->type == SEL_ARG::MAYBE_KEY)
|
if (key1->type == SEL_ARG::MAYBE_KEY)
|
||||||
@ -6077,7 +6178,7 @@ and_all_keys(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
|
|||||||
{
|
{
|
||||||
if (next->next_key_part)
|
if (next->next_key_part)
|
||||||
{
|
{
|
||||||
SEL_ARG *tmp=key_and(next->next_key_part,key2,clone_flag);
|
SEL_ARG *tmp= key_and(param, next->next_key_part, key2, clone_flag);
|
||||||
if (tmp && tmp->type == SEL_ARG::IMPOSSIBLE)
|
if (tmp && tmp->type == SEL_ARG::IMPOSSIBLE)
|
||||||
{
|
{
|
||||||
key1=key1->tree_delete(next);
|
key1=key1->tree_delete(next);
|
||||||
@ -6086,6 +6187,8 @@ and_all_keys(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
|
|||||||
next->next_key_part=tmp;
|
next->next_key_part=tmp;
|
||||||
if (use_count)
|
if (use_count)
|
||||||
next->increment_use_count(use_count);
|
next->increment_use_count(use_count);
|
||||||
|
if (param->alloced_sel_args > SEL_ARG::MAX_SEL_ARGS)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
next->next_key_part=key2;
|
next->next_key_part=key2;
|
||||||
@ -6102,8 +6205,10 @@ and_all_keys(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
key_and()
|
key_and()
|
||||||
key1 First argument, root of its RB-tree
|
param Range analysis context (needed to track if we have allocated
|
||||||
key2 Second argument, root of its RB-tree
|
too many SEL_ARGs)
|
||||||
|
key1 First argument, root of its RB-tree
|
||||||
|
key2 Second argument, root of its RB-tree
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
RB-tree root of the resulting SEL_ARG graph.
|
RB-tree root of the resulting SEL_ARG graph.
|
||||||
@ -6111,7 +6216,7 @@ and_all_keys(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static SEL_ARG *
|
static SEL_ARG *
|
||||||
key_and(SEL_ARG *key1, SEL_ARG *key2, uint clone_flag)
|
key_and(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2, uint clone_flag)
|
||||||
{
|
{
|
||||||
if (!key1)
|
if (!key1)
|
||||||
return key2;
|
return key2;
|
||||||
@ -6127,9 +6232,9 @@ key_and(SEL_ARG *key1, SEL_ARG *key2, uint clone_flag)
|
|||||||
// key1->part < key2->part
|
// key1->part < key2->part
|
||||||
key1->use_count--;
|
key1->use_count--;
|
||||||
if (key1->use_count > 0)
|
if (key1->use_count > 0)
|
||||||
if (!(key1= key1->clone_tree()))
|
if (!(key1= key1->clone_tree(param)))
|
||||||
return 0; // OOM
|
return 0; // OOM
|
||||||
return and_all_keys(key1,key2,clone_flag);
|
return and_all_keys(param, key1, key2, clone_flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((clone_flag & CLONE_KEY2_MAYBE) &&
|
if (((clone_flag & CLONE_KEY2_MAYBE) &&
|
||||||
@ -6147,14 +6252,14 @@ key_and(SEL_ARG *key1, SEL_ARG *key2, uint clone_flag)
|
|||||||
if (key1->use_count > 1)
|
if (key1->use_count > 1)
|
||||||
{
|
{
|
||||||
key1->use_count--;
|
key1->use_count--;
|
||||||
if (!(key1=key1->clone_tree()))
|
if (!(key1=key1->clone_tree(param)))
|
||||||
return 0; // OOM
|
return 0; // OOM
|
||||||
key1->use_count++;
|
key1->use_count++;
|
||||||
}
|
}
|
||||||
if (key1->type == SEL_ARG::MAYBE_KEY)
|
if (key1->type == SEL_ARG::MAYBE_KEY)
|
||||||
{ // Both are maybe key
|
{ // Both are maybe key
|
||||||
key1->next_key_part=key_and(key1->next_key_part,key2->next_key_part,
|
key1->next_key_part=key_and(param, key1->next_key_part,
|
||||||
clone_flag);
|
key2->next_key_part, clone_flag);
|
||||||
if (key1->next_key_part &&
|
if (key1->next_key_part &&
|
||||||
key1->next_key_part->type == SEL_ARG::IMPOSSIBLE)
|
key1->next_key_part->type == SEL_ARG::IMPOSSIBLE)
|
||||||
return key1;
|
return key1;
|
||||||
@ -6165,7 +6270,7 @@ key_and(SEL_ARG *key1, SEL_ARG *key2, uint clone_flag)
|
|||||||
if (key2->next_key_part)
|
if (key2->next_key_part)
|
||||||
{
|
{
|
||||||
key1->use_count--; // Incremented in and_all_keys
|
key1->use_count--; // Incremented in and_all_keys
|
||||||
return and_all_keys(key1,key2,clone_flag);
|
return and_all_keys(param, key1, key2, clone_flag);
|
||||||
}
|
}
|
||||||
key2->use_count--; // Key2 doesn't have a tree
|
key2->use_count--; // Key2 doesn't have a tree
|
||||||
}
|
}
|
||||||
@ -6201,7 +6306,8 @@ key_and(SEL_ARG *key1, SEL_ARG *key2, uint clone_flag)
|
|||||||
}
|
}
|
||||||
else if (get_range(&e2,&e1,key2))
|
else if (get_range(&e2,&e1,key2))
|
||||||
continue;
|
continue;
|
||||||
SEL_ARG *next=key_and(e1->next_key_part,e2->next_key_part,clone_flag);
|
SEL_ARG *next=key_and(param, e1->next_key_part, e2->next_key_part,
|
||||||
|
clone_flag);
|
||||||
e1->increment_use_count(1);
|
e1->increment_use_count(1);
|
||||||
e2->increment_use_count(1);
|
e2->increment_use_count(1);
|
||||||
if (!next || next->type != SEL_ARG::IMPOSSIBLE)
|
if (!next || next->type != SEL_ARG::IMPOSSIBLE)
|
||||||
@ -6249,7 +6355,7 @@ get_range(SEL_ARG **e1,SEL_ARG **e2,SEL_ARG *root1)
|
|||||||
|
|
||||||
|
|
||||||
static SEL_ARG *
|
static SEL_ARG *
|
||||||
key_or(SEL_ARG *key1,SEL_ARG *key2)
|
key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2)
|
||||||
{
|
{
|
||||||
if (!key1)
|
if (!key1)
|
||||||
{
|
{
|
||||||
@ -6297,7 +6403,7 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
|
|||||||
{
|
{
|
||||||
swap_variables(SEL_ARG *,key1,key2);
|
swap_variables(SEL_ARG *,key1,key2);
|
||||||
}
|
}
|
||||||
if (key1->use_count > 0 || !(key1=key1->clone_tree()))
|
if (key1->use_count > 0 || !(key1=key1->clone_tree(param)))
|
||||||
return 0; // OOM
|
return 0; // OOM
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6441,7 +6547,7 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
|
|||||||
{ // tmp.min. <= x <= tmp.max
|
{ // tmp.min. <= x <= tmp.max
|
||||||
tmp->maybe_flag|= key.maybe_flag;
|
tmp->maybe_flag|= key.maybe_flag;
|
||||||
key.increment_use_count(key1->use_count+1);
|
key.increment_use_count(key1->use_count+1);
|
||||||
tmp->next_key_part=key_or(tmp->next_key_part,key.next_key_part);
|
tmp->next_key_part= key_or(param, tmp->next_key_part, key.next_key_part);
|
||||||
if (!cmp) // Key2 is ready
|
if (!cmp) // Key2 is ready
|
||||||
break;
|
break;
|
||||||
key.copy_max_to_min(tmp);
|
key.copy_max_to_min(tmp);
|
||||||
@ -6472,7 +6578,7 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
|
|||||||
tmp->increment_use_count(key1->use_count+1);
|
tmp->increment_use_count(key1->use_count+1);
|
||||||
/* Increment key count as it may be used for next loop */
|
/* Increment key count as it may be used for next loop */
|
||||||
key.increment_use_count(1);
|
key.increment_use_count(1);
|
||||||
new_arg->next_key_part=key_or(tmp->next_key_part,key.next_key_part);
|
new_arg->next_key_part= key_or(param, tmp->next_key_part, key.next_key_part);
|
||||||
key1=key1->insert(new_arg);
|
key1=key1->insert(new_arg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -356,6 +356,8 @@ sys_var_thd_ulong sys_net_retry_count("net_retry_count",
|
|||||||
&SV::net_retry_count,
|
&SV::net_retry_count,
|
||||||
0, fix_net_retry_count);
|
0, fix_net_retry_count);
|
||||||
sys_var_thd_bool sys_new_mode("new", &SV::new_mode);
|
sys_var_thd_bool sys_new_mode("new", &SV::new_mode);
|
||||||
|
sys_var_bool_ptr_readonly sys_old_mode("old",
|
||||||
|
&global_system_variables.old_mode);
|
||||||
sys_var_thd_bool sys_old_alter_table("old_alter_table",
|
sys_var_thd_bool sys_old_alter_table("old_alter_table",
|
||||||
&SV::old_alter_table);
|
&SV::old_alter_table);
|
||||||
sys_var_thd_bool sys_old_passwords("old_passwords", &SV::old_passwords);
|
sys_var_thd_bool sys_old_passwords("old_passwords", &SV::old_passwords);
|
||||||
@ -942,6 +944,7 @@ SHOW_VAR init_vars[]= {
|
|||||||
{sys_net_retry_count.name, (char*) &sys_net_retry_count, SHOW_SYS},
|
{sys_net_retry_count.name, (char*) &sys_net_retry_count, SHOW_SYS},
|
||||||
{sys_net_write_timeout.name,(char*) &sys_net_write_timeout, SHOW_SYS},
|
{sys_net_write_timeout.name,(char*) &sys_net_write_timeout, SHOW_SYS},
|
||||||
{sys_new_mode.name, (char*) &sys_new_mode, SHOW_SYS},
|
{sys_new_mode.name, (char*) &sys_new_mode, SHOW_SYS},
|
||||||
|
{sys_old_mode.name, (char*) &sys_old_mode, SHOW_SYS},
|
||||||
{sys_old_alter_table.name, (char*) &sys_old_alter_table, SHOW_SYS},
|
{sys_old_alter_table.name, (char*) &sys_old_alter_table, SHOW_SYS},
|
||||||
{sys_old_passwords.name, (char*) &sys_old_passwords, SHOW_SYS},
|
{sys_old_passwords.name, (char*) &sys_old_passwords, SHOW_SYS},
|
||||||
{"open_files_limit", (char*) &open_files_limit, SHOW_LONG},
|
{"open_files_limit", (char*) &open_files_limit, SHOW_LONG},
|
||||||
|
@ -169,6 +169,16 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class sys_var_bool_ptr_readonly :public sys_var_bool_ptr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
sys_var_bool_ptr_readonly(const char *name_arg, my_bool *value_arg)
|
||||||
|
:sys_var_bool_ptr(name_arg, value_arg)
|
||||||
|
{}
|
||||||
|
bool is_readonly() const { return 1; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class sys_var_str :public sys_var
|
class sys_var_str :public sys_var
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -5838,7 +5838,6 @@ bool setup_tables_and_check_access(THD *thd,
|
|||||||
TABLE_LIST *leaves_tmp= NULL;
|
TABLE_LIST *leaves_tmp= NULL;
|
||||||
bool first_table= true;
|
bool first_table= true;
|
||||||
|
|
||||||
thd->leaf_count= 0;
|
|
||||||
if (setup_tables(thd, context, from_clause, tables,
|
if (setup_tables(thd, context, from_clause, tables,
|
||||||
&leaves_tmp, select_insert))
|
&leaves_tmp, select_insert))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -5856,7 +5855,6 @@ bool setup_tables_and_check_access(THD *thd,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
first_table= 0;
|
first_table= 0;
|
||||||
thd->leaf_count++;
|
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -1412,9 +1412,6 @@ public:
|
|||||||
partition_info *work_part_info;
|
partition_info *work_part_info;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* pass up the count of "leaf" tables in a JOIN out of setup_tables() */
|
|
||||||
byte leaf_count;
|
|
||||||
|
|
||||||
THD();
|
THD();
|
||||||
~THD();
|
~THD();
|
||||||
|
|
||||||
|
@ -54,6 +54,27 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||||||
if (mysql_prepare_delete(thd, table_list, &conds))
|
if (mysql_prepare_delete(thd, table_list, &conds))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
|
/* check ORDER BY even if it can be ignored */
|
||||||
|
if (order && order->elements)
|
||||||
|
{
|
||||||
|
TABLE_LIST tables;
|
||||||
|
List<Item> fields;
|
||||||
|
List<Item> all_fields;
|
||||||
|
|
||||||
|
bzero((char*) &tables,sizeof(tables));
|
||||||
|
tables.table = table;
|
||||||
|
tables.alias = table_list->alias;
|
||||||
|
|
||||||
|
if (select_lex->setup_ref_array(thd, order->elements) ||
|
||||||
|
setup_order(thd, select_lex->ref_pointer_array, &tables,
|
||||||
|
fields, all_fields, (ORDER*) order->first))
|
||||||
|
{
|
||||||
|
delete select;
|
||||||
|
free_underlaid_joins(thd, &thd->lex->select_lex);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const_cond= (!conds || conds->const_item());
|
const_cond= (!conds || conds->const_item());
|
||||||
safe_update=test(thd->options & OPTION_SAFE_UPDATES);
|
safe_update=test(thd->options & OPTION_SAFE_UPDATES);
|
||||||
if (safe_update && const_cond)
|
if (safe_update && const_cond)
|
||||||
@ -155,23 +176,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||||||
{
|
{
|
||||||
uint length= 0;
|
uint length= 0;
|
||||||
SORT_FIELD *sortorder;
|
SORT_FIELD *sortorder;
|
||||||
TABLE_LIST tables;
|
|
||||||
List<Item> fields;
|
|
||||||
List<Item> all_fields;
|
|
||||||
ha_rows examined_rows;
|
ha_rows examined_rows;
|
||||||
|
|
||||||
bzero((char*) &tables,sizeof(tables));
|
|
||||||
tables.table = table;
|
|
||||||
tables.alias = table_list->alias;
|
|
||||||
|
|
||||||
if (select_lex->setup_ref_array(thd, order->elements) ||
|
|
||||||
setup_order(thd, select_lex->ref_pointer_array, &tables,
|
|
||||||
fields, all_fields, (ORDER*) order->first))
|
|
||||||
{
|
|
||||||
delete select;
|
|
||||||
free_underlaid_joins(thd, &thd->lex->select_lex);
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((!select || table->quick_keys.is_clear_all()) && limit != HA_POS_ERROR)
|
if ((!select || table->quick_keys.is_clear_all()) && limit != HA_POS_ERROR)
|
||||||
usable_index= get_index_for_order(table, (ORDER*)(order->first), limit);
|
usable_index= get_index_for_order(table, (ORDER*)(order->first), limit);
|
||||||
|
@ -2466,14 +2466,12 @@ bool mysql_insert_select_prepare(THD *thd)
|
|||||||
DBUG_ASSERT(select_lex->leaf_tables != 0);
|
DBUG_ASSERT(select_lex->leaf_tables != 0);
|
||||||
lex->leaf_tables_insert= select_lex->leaf_tables;
|
lex->leaf_tables_insert= select_lex->leaf_tables;
|
||||||
/* skip all leaf tables belonged to view where we are insert */
|
/* skip all leaf tables belonged to view where we are insert */
|
||||||
for (first_select_leaf_table= select_lex->leaf_tables->next_leaf,
|
for (first_select_leaf_table= select_lex->leaf_tables->next_leaf;
|
||||||
thd->leaf_count --;
|
|
||||||
first_select_leaf_table &&
|
first_select_leaf_table &&
|
||||||
first_select_leaf_table->belong_to_view &&
|
first_select_leaf_table->belong_to_view &&
|
||||||
first_select_leaf_table->belong_to_view ==
|
first_select_leaf_table->belong_to_view ==
|
||||||
lex->leaf_tables_insert->belong_to_view;
|
lex->leaf_tables_insert->belong_to_view;
|
||||||
first_select_leaf_table= first_select_leaf_table->next_leaf,
|
first_select_leaf_table= first_select_leaf_table->next_leaf)
|
||||||
thd->leaf_count --)
|
|
||||||
{}
|
{}
|
||||||
select_lex->leaf_tables= first_select_leaf_table;
|
select_lex->leaf_tables= first_select_leaf_table;
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
class Sql_alloc
|
class Sql_alloc
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void *operator new(size_t size)
|
static void *operator new(size_t size) throw ()
|
||||||
{
|
{
|
||||||
return (void*) sql_alloc((uint) size);
|
return (void*) sql_alloc((uint) size);
|
||||||
}
|
}
|
||||||
@ -31,9 +31,9 @@ public:
|
|||||||
{
|
{
|
||||||
return (void*) sql_alloc((uint) size);
|
return (void*) sql_alloc((uint) size);
|
||||||
}
|
}
|
||||||
static void *operator new[](size_t size, MEM_ROOT *mem_root)
|
static void *operator new[](size_t size, MEM_ROOT *mem_root) throw ()
|
||||||
{ return (void*) alloc_root(mem_root, (uint) size); }
|
{ return (void*) alloc_root(mem_root, (uint) size); }
|
||||||
static void *operator new(size_t size, MEM_ROOT *mem_root)
|
static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
|
||||||
{ return (void*) alloc_root(mem_root, (uint) size); }
|
{ return (void*) alloc_root(mem_root, (uint) size); }
|
||||||
static void operator delete(void *ptr, size_t size) { TRASH(ptr, size); }
|
static void operator delete(void *ptr, size_t size) { TRASH(ptr, size); }
|
||||||
static void operator delete(void *ptr, MEM_ROOT *mem_root)
|
static void operator delete(void *ptr, MEM_ROOT *mem_root)
|
||||||
|
@ -413,7 +413,12 @@ JOIN::prepare(Item ***rref_pointer_array,
|
|||||||
tables_list, &select_lex->leaf_tables,
|
tables_list, &select_lex->leaf_tables,
|
||||||
FALSE, SELECT_ACL, SELECT_ACL))
|
FALSE, SELECT_ACL, SELECT_ACL))
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
tables= thd->leaf_count;
|
|
||||||
|
TABLE_LIST *table_ptr;
|
||||||
|
for (table_ptr= select_lex->leaf_tables;
|
||||||
|
table_ptr;
|
||||||
|
table_ptr= table_ptr->next_leaf)
|
||||||
|
tables++;
|
||||||
|
|
||||||
if (setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
|
if (setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
|
||||||
select_lex->setup_ref_array(thd, og_num) ||
|
select_lex->setup_ref_array(thd, og_num) ||
|
||||||
@ -9417,13 +9422,19 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
|||||||
{
|
{
|
||||||
if (item->with_sum_func && type != Item::SUM_FUNC_ITEM)
|
if (item->with_sum_func && type != Item::SUM_FUNC_ITEM)
|
||||||
{
|
{
|
||||||
/*
|
if (item->used_tables() & OUTER_REF_TABLE_BIT)
|
||||||
Mark that the we have ignored an item that refers to a summary
|
item->update_used_tables();
|
||||||
function. We need to know this if someone is going to use
|
if (type == Item::SUBSELECT_ITEM ||
|
||||||
DISTINCT on the result.
|
(item->used_tables() & ~OUTER_REF_TABLE_BIT))
|
||||||
*/
|
{
|
||||||
param->using_indirect_summary_function=1;
|
/*
|
||||||
continue;
|
Mark that the we have ignored an item that refers to a summary
|
||||||
|
function. We need to know this if someone is going to use
|
||||||
|
DISTINCT on the result.
|
||||||
|
*/
|
||||||
|
param->using_indirect_summary_function=1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (item->const_item() && (int) hidden_field_count <= 0)
|
if (item->const_item() && (int) hidden_field_count <= 0)
|
||||||
continue; // We don't have to store this
|
continue; // We don't have to store this
|
||||||
@ -9608,6 +9619,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
|||||||
share->default_values= table->record[1]+alloc_length;
|
share->default_values= table->record[1]+alloc_length;
|
||||||
}
|
}
|
||||||
copy_func[0]=0; // End marker
|
copy_func[0]=0; // End marker
|
||||||
|
param->func_count= copy_func - param->items_to_copy;
|
||||||
|
|
||||||
setup_tmp_table_column_bitmaps(table, bitmaps);
|
setup_tmp_table_column_bitmaps(table, bitmaps);
|
||||||
|
|
||||||
@ -13824,6 +13836,7 @@ count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
|
|||||||
if (!sum_item->quick_group)
|
if (!sum_item->quick_group)
|
||||||
param->quick_group=0; // UDF SUM function
|
param->quick_group=0; // UDF SUM function
|
||||||
param->sum_func_count++;
|
param->sum_func_count++;
|
||||||
|
param->func_count++;
|
||||||
|
|
||||||
for (uint i=0 ; i < sum_item->arg_count ; i++)
|
for (uint i=0 ; i < sum_item->arg_count ; i++)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user