Merge 5.3->5.5
This commit is contained in:
commit
32151409c1
@ -6530,16 +6530,16 @@ id select_type table type possible_keys key key_len ref rows Extra
|
|||||||
1 SIMPLE t1 ref c1 c1 5 const 1 Using index
|
1 SIMPLE t1 ref c1 c1 5 const 1 Using index
|
||||||
EXPLAIN SELECT * FROM t1 WHERE c1=f1();
|
EXPLAIN SELECT * FROM t1 WHERE c1=f1();
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 SIMPLE t1 ref c1 c1 5 const 0 Using where; Using index
|
1 SIMPLE t1 ref c1 c1 5 const 1 Using where; Using index
|
||||||
EXPLAIN SELECT * FROM v1 WHERE c1=1;
|
EXPLAIN SELECT * FROM v1 WHERE c1=1;
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 SIMPLE t1 ref c1 c1 5 const 1 Using index
|
1 SIMPLE t1 ref c1 c1 5 const 1 Using index
|
||||||
EXPLAIN SELECT * FROM v1 WHERE c1=f1();
|
EXPLAIN SELECT * FROM v1 WHERE c1=f1();
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 SIMPLE t1 ref c1 c1 5 const 0 Using where; Using index
|
1 SIMPLE t1 ref c1 c1 5 const 1 Using where; Using index
|
||||||
EXPLAIN SELECT * FROM t1 WHERE c1=f2(10);
|
EXPLAIN SELECT * FROM t1 WHERE c1=f2(10);
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 SIMPLE t1 ref c1 c1 5 const 0 Using where; Using index
|
1 SIMPLE t1 ref c1 c1 5 const 1 Using where; Using index
|
||||||
EXPLAIN SELECT * FROM t1 WHERE c1=f2(c1);
|
EXPLAIN SELECT * FROM t1 WHERE c1=f2(c1);
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 SIMPLE t1 index NULL c1 5 NULL 5 Using where; Using index
|
1 SIMPLE t1 index NULL c1 5 NULL 5 Using where; Using index
|
||||||
@ -7852,6 +7852,38 @@ c1 c2 count(c3)
|
|||||||
2012-03-01 01:00:00 3 1
|
2012-03-01 01:00:00 3 1
|
||||||
2012-03-01 02:00:00 3 1
|
2012-03-01 02:00:00 3 1
|
||||||
DROP PROCEDURE p1;
|
DROP PROCEDURE p1;
|
||||||
|
|
||||||
|
MDEV-3900 Optimizer difference between MySQL and MariaDB with stored functions in WHERE clause of UPDATE or DELETE statements
|
||||||
|
|
||||||
|
CREATE FUNCTION tdn() RETURNS int(7) DETERMINISTIC RETURN to_days(now());
|
||||||
|
CREATE TABLE t1 (pk INT NOT NULL AUTO_INCREMENT PRIMARY KEY, daynum INT, a CHAR(1), INDEX(daynum), INDEX(a)) ENGINE=MyISAM;
|
||||||
|
INSERT INTO t1 (daynum) VALUES (1),(2),(3),(4),(5),(TO_DAYS(NOW())),(7),(8);
|
||||||
|
INSERT INTO t1 (daynum) SELECT a1.daynum FROM t1 a1, t1 a2, t1 a3, t1 a4, t1 a5;
|
||||||
|
FLUSH TABLES;
|
||||||
|
FLUSH STATUS;
|
||||||
|
SHOW STATUS LIKE '%Handler_read%';
|
||||||
|
Variable_name Value
|
||||||
|
Handler_read_first 0
|
||||||
|
Handler_read_key 0
|
||||||
|
Handler_read_last 0
|
||||||
|
Handler_read_next 0
|
||||||
|
Handler_read_prev 0
|
||||||
|
Handler_read_rnd 0
|
||||||
|
Handler_read_rnd_deleted 0
|
||||||
|
Handler_read_rnd_next 0
|
||||||
|
UPDATE t1 SET a = '+' WHERE daynum=tdn();
|
||||||
|
SHOW STATUS LIKE '%Handler_read%';
|
||||||
|
Variable_name Value
|
||||||
|
Handler_read_first 0
|
||||||
|
Handler_read_key 2
|
||||||
|
Handler_read_last 0
|
||||||
|
Handler_read_next 4097
|
||||||
|
Handler_read_prev 0
|
||||||
|
Handler_read_rnd 0
|
||||||
|
Handler_read_rnd_deleted 0
|
||||||
|
Handler_read_rnd_next 0
|
||||||
|
drop function tdn;
|
||||||
|
drop table t1;
|
||||||
#
|
#
|
||||||
# lp:1002157 : testing stored function
|
# lp:1002157 : testing stored function
|
||||||
# bug#62125 result for null incorrectly yields 1292 warning.
|
# bug#62125 result for null incorrectly yields 1292 warning.
|
||||||
|
@ -2274,6 +2274,27 @@ SELECT a3 FROM t3 WHERE b2 = b1 AND b2 <= b1 ORDER BY b3
|
|||||||
a1 b1
|
a1 b1
|
||||||
drop table t1, t2, t3;
|
drop table t1, t2, t3;
|
||||||
#
|
#
|
||||||
|
# MDEV-4056:Server crashes in Item_func_trig_cond::val_int
|
||||||
|
# with FROM and NOT IN subqueries, LEFT JOIN, derived_merge+in_to_exists
|
||||||
|
#
|
||||||
|
set @optimizer_switch_MDEV4056 = @@optimizer_switch;
|
||||||
|
SET optimizer_switch = 'derived_merge=on,in_to_exists=on';
|
||||||
|
CREATE TABLE t1 (a VARCHAR(1)) ENGINE=MyISAM;
|
||||||
|
INSERT INTO t1 VALUES ('x'),('d');
|
||||||
|
CREATE TABLE t2 (pk INT PRIMARY KEY, b INT, c VARCHAR(1)) ENGINE=MyISAM;
|
||||||
|
INSERT INTO t2 VALUES (1,2,'v'),(2,150,'v');
|
||||||
|
SELECT * FROM t1 LEFT JOIN (
|
||||||
|
SELECT * FROM t2 WHERE ( pk, pk ) NOT IN (
|
||||||
|
SELECT MIN(b), SUM(pk) FROM t1
|
||||||
|
)
|
||||||
|
) AS alias1 ON (a = c)
|
||||||
|
WHERE b IS NULL OR a < 'u';
|
||||||
|
a pk b c
|
||||||
|
x NULL NULL NULL
|
||||||
|
d NULL NULL NULL
|
||||||
|
drop table t1,t2;
|
||||||
|
set @@optimizer_switch = @optimizer_switch_MDEV4056;
|
||||||
|
#
|
||||||
# MDEV-3899 Valgrind warnings (blocks are definitely lost) in filesort on IN subquery with SUM and DISTINCT
|
# MDEV-3899 Valgrind warnings (blocks are definitely lost) in filesort on IN subquery with SUM and DISTINCT
|
||||||
#
|
#
|
||||||
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
|
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
|
||||||
|
@ -391,4 +391,22 @@ select 1 from t1 where 1 like (select 1 from t1 where 1 <=> (select 1 from t1 gr
|
|||||||
1
|
1
|
||||||
1
|
1
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
#
|
||||||
|
# MDEV-3988 crash in create_tmp_table
|
||||||
|
#
|
||||||
|
drop table if exists `t1`,`t2`;
|
||||||
|
Warnings:
|
||||||
|
Note 1051 Unknown table 't1'
|
||||||
|
Note 1051 Unknown table 't2'
|
||||||
|
create table `t1`(`a` char(1) character set utf8)engine=innodb;
|
||||||
|
create table `t2`(`b` char(1) character set utf8)engine=memory;
|
||||||
|
select distinct (select 1 from `t2` where `a`) `d2` from `t1`;
|
||||||
|
d2
|
||||||
|
select distinct (select 1 from `t2` where `a`) `d2`, a from `t1`;
|
||||||
|
d2 a
|
||||||
|
select distinct a, (select 1 from `t2` where `a`) `d2` from `t1`;
|
||||||
|
a d2
|
||||||
|
select distinct (1 + (select 1 from `t2` where `a`)) `d2` from `t1`;
|
||||||
|
d2
|
||||||
|
drop table t1,t2;
|
||||||
set optimizer_switch=@subselect_innodb_tmp;
|
set optimizer_switch=@subselect_innodb_tmp;
|
||||||
|
@ -103,5 +103,20 @@ sm
|
|||||||
10323810
|
10323810
|
||||||
10325070
|
10325070
|
||||||
10326330
|
10326330
|
||||||
|
#
|
||||||
|
# Bug mdev-4063: SUM(DISTINCT...) with small'max_heap_table_size
|
||||||
|
# (bug #56927)
|
||||||
|
#
|
||||||
|
SET max_heap_table_size=default;
|
||||||
|
INSERT INTO t1 SELECT id+16384 FROM t1;
|
||||||
|
DELETE FROM t2;
|
||||||
|
INSERT INTO t2 SELECT id FROM t1 ORDER BY id*rand();
|
||||||
|
SELECT SUM(DISTINCT id) sm FROM t2;
|
||||||
|
sm
|
||||||
|
536887296
|
||||||
|
SET max_heap_table_size=16384;
|
||||||
|
SELECT SUM(DISTINCT id) sm FROM t2;
|
||||||
|
sm
|
||||||
|
536887296
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
DROP TABLE t2;
|
DROP TABLE t2;
|
||||||
|
@ -389,6 +389,7 @@ select a from t1 where a=(select 2000 from dual where 1);
|
|||||||
a
|
a
|
||||||
select a from t1 where a=y2k();
|
select a from t1 where a=y2k();
|
||||||
a
|
a
|
||||||
|
00
|
||||||
select a from t1 where a=b;
|
select a from t1 where a=b;
|
||||||
a
|
a
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
@ -182,6 +182,17 @@ a b c
|
|||||||
2 3 y
|
2 3 y
|
||||||
0 1 y,n
|
0 1 y,n
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
ts TIMESTAMP,
|
||||||
|
tsv TIMESTAMP AS (ADDDATE(ts, INTERVAL 1 DAY)) VIRTUAL
|
||||||
|
) ENGINE=MyISAM;
|
||||||
|
INSERT INTO t1 (tsv) VALUES (DEFAULT);
|
||||||
|
INSERT DELAYED INTO t1 (tsv) VALUES (DEFAULT);
|
||||||
|
FLUSH TABLES;
|
||||||
|
SELECT COUNT(*) FROM t1;
|
||||||
|
COUNT(*)
|
||||||
|
2
|
||||||
|
DROP TABLE t1;
|
||||||
create table t1 (a int, b int);
|
create table t1 (a int, b int);
|
||||||
insert into t1 values (3, 30), (4, 20), (1, 20);
|
insert into t1 values (3, 30), (4, 20), (1, 20);
|
||||||
create table t2 (c int, d int, v int as (d+1), index idx(c));
|
create table t2 (c int, d int, v int as (d+1), index idx(c));
|
||||||
|
@ -178,6 +178,25 @@ select * from t2;
|
|||||||
|
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug mdev-3938: INSERT DELAYED for a table with virtual columns
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
ts TIMESTAMP,
|
||||||
|
tsv TIMESTAMP AS (ADDDATE(ts, INTERVAL 1 DAY)) VIRTUAL
|
||||||
|
) ENGINE=MyISAM;
|
||||||
|
|
||||||
|
INSERT INTO t1 (tsv) VALUES (DEFAULT);
|
||||||
|
|
||||||
|
INSERT DELAYED INTO t1 (tsv) VALUES (DEFAULT);
|
||||||
|
|
||||||
|
FLUSH TABLES;
|
||||||
|
|
||||||
|
SELECT COUNT(*) FROM t1;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
#
|
#
|
||||||
# SELECT that uses a virtual column and executed with BKA
|
# SELECT that uses a virtual column and executed with BKA
|
||||||
#
|
#
|
||||||
|
@ -9151,6 +9151,26 @@ CALL p1(1);
|
|||||||
|
|
||||||
DROP PROCEDURE p1;
|
DROP PROCEDURE p1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
--echo MDEV-3900 Optimizer difference between MySQL and MariaDB with stored functions in WHERE clause of UPDATE or DELETE statements
|
||||||
|
--echo
|
||||||
|
|
||||||
|
CREATE FUNCTION tdn() RETURNS int(7) DETERMINISTIC RETURN to_days(now());
|
||||||
|
|
||||||
|
CREATE TABLE t1 (pk INT NOT NULL AUTO_INCREMENT PRIMARY KEY, daynum INT, a CHAR(1), INDEX(daynum), INDEX(a)) ENGINE=MyISAM;
|
||||||
|
INSERT INTO t1 (daynum) VALUES (1),(2),(3),(4),(5),(TO_DAYS(NOW())),(7),(8);
|
||||||
|
INSERT INTO t1 (daynum) SELECT a1.daynum FROM t1 a1, t1 a2, t1 a3, t1 a4, t1 a5;
|
||||||
|
|
||||||
|
FLUSH TABLES;
|
||||||
|
FLUSH STATUS;
|
||||||
|
|
||||||
|
SHOW STATUS LIKE '%Handler_read%';
|
||||||
|
UPDATE t1 SET a = '+' WHERE daynum=tdn();
|
||||||
|
SHOW STATUS LIKE '%Handler_read%';
|
||||||
|
|
||||||
|
drop function tdn;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # lp:1002157 : testing stored function
|
--echo # lp:1002157 : testing stored function
|
||||||
--echo # bug#62125 result for null incorrectly yields 1292 warning.
|
--echo # bug#62125 result for null incorrectly yields 1292 warning.
|
||||||
|
@ -1804,6 +1804,30 @@ SELECT * FROM t1 WHERE a1 IN (
|
|||||||
);
|
);
|
||||||
drop table t1, t2, t3;
|
drop table t1, t2, t3;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-4056:Server crashes in Item_func_trig_cond::val_int
|
||||||
|
--echo # with FROM and NOT IN subqueries, LEFT JOIN, derived_merge+in_to_exists
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
set @optimizer_switch_MDEV4056 = @@optimizer_switch;
|
||||||
|
SET optimizer_switch = 'derived_merge=on,in_to_exists=on';
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a VARCHAR(1)) ENGINE=MyISAM;
|
||||||
|
INSERT INTO t1 VALUES ('x'),('d');
|
||||||
|
|
||||||
|
CREATE TABLE t2 (pk INT PRIMARY KEY, b INT, c VARCHAR(1)) ENGINE=MyISAM;
|
||||||
|
INSERT INTO t2 VALUES (1,2,'v'),(2,150,'v');
|
||||||
|
|
||||||
|
SELECT * FROM t1 LEFT JOIN (
|
||||||
|
SELECT * FROM t2 WHERE ( pk, pk ) NOT IN (
|
||||||
|
SELECT MIN(b), SUM(pk) FROM t1
|
||||||
|
)
|
||||||
|
) AS alias1 ON (a = c)
|
||||||
|
WHERE b IS NULL OR a < 'u';
|
||||||
|
|
||||||
|
drop table t1,t2;
|
||||||
|
set @@optimizer_switch = @optimizer_switch_MDEV4056;
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # MDEV-3899 Valgrind warnings (blocks are definitely lost) in filesort on IN subquery with SUM and DISTINCT
|
--echo # MDEV-3899 Valgrind warnings (blocks are definitely lost) in filesort on IN subquery with SUM and DISTINCT
|
||||||
--echo #
|
--echo #
|
||||||
|
@ -377,4 +377,18 @@ select 1 from t1 where 1 like (select 1 from t1 where 1 <=> (select 1 from t1 gr
|
|||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-3988 crash in create_tmp_table
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
drop table if exists `t1`,`t2`;
|
||||||
|
create table `t1`(`a` char(1) character set utf8)engine=innodb;
|
||||||
|
create table `t2`(`b` char(1) character set utf8)engine=memory;
|
||||||
|
select distinct (select 1 from `t2` where `a`) `d2` from `t1`;
|
||||||
|
select distinct (select 1 from `t2` where `a`) `d2`, a from `t1`;
|
||||||
|
select distinct a, (select 1 from `t2` where `a`) `d2` from `t1`;
|
||||||
|
select distinct (1 + (select 1 from `t2` where `a`)) `d2` from `t1`;
|
||||||
|
|
||||||
|
drop table t1,t2;
|
||||||
|
|
||||||
set optimizer_switch=@subselect_innodb_tmp;
|
set optimizer_switch=@subselect_innodb_tmp;
|
||||||
|
@ -63,5 +63,22 @@ SELECT SUM(DISTINCT id) sm FROM t1;
|
|||||||
SELECT SUM(DISTINCT id) sm FROM t2;
|
SELECT SUM(DISTINCT id) sm FROM t2;
|
||||||
SELECT SUM(DISTINCT id) sm FROM t1 GROUP BY id % 13;
|
SELECT SUM(DISTINCT id) sm FROM t1 GROUP BY id % 13;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug mdev-4063: SUM(DISTINCT...) with small'max_heap_table_size
|
||||||
|
--echo # (bug #56927)
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
SET max_heap_table_size=default;
|
||||||
|
|
||||||
|
INSERT INTO t1 SELECT id+16384 FROM t1;
|
||||||
|
DELETE FROM t2;
|
||||||
|
INSERT INTO t2 SELECT id FROM t1 ORDER BY id*rand();
|
||||||
|
|
||||||
|
SELECT SUM(DISTINCT id) sm FROM t2;
|
||||||
|
|
||||||
|
SET max_heap_table_size=16384;
|
||||||
|
|
||||||
|
SELECT SUM(DISTINCT id) sm FROM t2;
|
||||||
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
DROP TABLE t2;
|
DROP TABLE t2;
|
||||||
|
@ -6524,6 +6524,19 @@ Item_func_sp::init_result_field(THD *thd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@note
|
||||||
|
Deterministic stored procedures are considered inexpensive.
|
||||||
|
Consequently such procedures may be evaluated during optimization,
|
||||||
|
if they are constant (checked by the optimizer).
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool Item_func_sp::is_expensive()
|
||||||
|
{
|
||||||
|
return !(m_sp->m_chistics->detistic);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Initialize local members with values from the Field interface.
|
@brief Initialize local members with values from the Field interface.
|
||||||
|
|
||||||
|
@ -1907,7 +1907,8 @@ private:
|
|||||||
bool init_result_field(THD *thd);
|
bool init_result_field(THD *thd);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool is_expensive_processor(uchar *arg) { return TRUE; }
|
bool is_expensive_processor(uchar *arg)
|
||||||
|
{ return is_expensive(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -1986,7 +1987,7 @@ public:
|
|||||||
|
|
||||||
bool fix_fields(THD *thd, Item **ref);
|
bool fix_fields(THD *thd, Item **ref);
|
||||||
void fix_length_and_dec(void);
|
void fix_length_and_dec(void);
|
||||||
bool is_expensive() { return 1; }
|
bool is_expensive();
|
||||||
|
|
||||||
inline Field *get_sp_result_field()
|
inline Field *get_sp_result_field()
|
||||||
{
|
{
|
||||||
|
@ -145,11 +145,13 @@ void Item_row::update_used_tables()
|
|||||||
{
|
{
|
||||||
used_tables_cache= 0;
|
used_tables_cache= 0;
|
||||||
const_item_cache= 1;
|
const_item_cache= 1;
|
||||||
|
maybe_null= 0;
|
||||||
for (uint i= 0; i < arg_count; i++)
|
for (uint i= 0; i < arg_count; i++)
|
||||||
{
|
{
|
||||||
items[i]->update_used_tables();
|
items[i]->update_used_tables();
|
||||||
used_tables_cache|= items[i]->used_tables();
|
used_tables_cache|= items[i]->used_tables();
|
||||||
const_item_cache&= items[i]->const_item();
|
const_item_cache&= items[i]->const_item();
|
||||||
|
maybe_null|= items[i]->maybe_null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1086,7 +1086,7 @@ void Aggregator_distinct::endup()
|
|||||||
{
|
{
|
||||||
/* go over the tree of distinct keys and calculate the aggregate value */
|
/* go over the tree of distinct keys and calculate the aggregate value */
|
||||||
use_distinct_values= TRUE;
|
use_distinct_values= TRUE;
|
||||||
tree->walk(item_sum_distinct_walk, (void*) this);
|
tree->walk(table, item_sum_distinct_walk, (void*) this);
|
||||||
use_distinct_values= FALSE;
|
use_distinct_values= FALSE;
|
||||||
}
|
}
|
||||||
/* prevent consecutive recalculations */
|
/* prevent consecutive recalculations */
|
||||||
|
@ -8939,7 +8939,8 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
|
|||||||
ER(ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN),
|
ER(ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN),
|
||||||
rfield->field_name, table->s->table_name.str);
|
rfield->field_name, table->s->table_name.str);
|
||||||
}
|
}
|
||||||
if ((value->save_in_field(rfield, 0) < 0) && !ignore_errors)
|
if ((!rfield->vcol_info || rfield->stored_in_db) &&
|
||||||
|
(value->save_in_field(rfield, 0)) < 0 && !ignore_errors)
|
||||||
{
|
{
|
||||||
my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
|
my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -3856,6 +3856,8 @@ class Unique :public Sql_alloc
|
|||||||
uint full_size;
|
uint full_size;
|
||||||
uint min_dupl_count; /* always 0 for unions, > 0 for intersections */
|
uint min_dupl_count; /* always 0 for unions, > 0 for intersections */
|
||||||
|
|
||||||
|
bool merge(TABLE *table, uchar *buff, bool without_last_merge);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ulong elements;
|
ulong elements;
|
||||||
Unique(qsort_cmp2 comp_func, void *comp_func_fixed_arg,
|
Unique(qsort_cmp2 comp_func, void *comp_func_fixed_arg,
|
||||||
@ -3896,7 +3898,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
bool walk(tree_walk_action action, void *walk_action_arg);
|
bool walk(TABLE *table, tree_walk_action action, void *walk_action_arg);
|
||||||
|
|
||||||
uint get_size() const { return size; }
|
uint get_size() const { return size; }
|
||||||
ulonglong get_max_in_memory_size() const { return max_in_memory_size; }
|
ulonglong get_max_in_memory_size() const { return max_in_memory_size; }
|
||||||
|
@ -2320,6 +2320,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
|
|||||||
{
|
{
|
||||||
my_ptrdiff_t adjust_ptrs;
|
my_ptrdiff_t adjust_ptrs;
|
||||||
Field **field,**org_field, *found_next_number_field;
|
Field **field,**org_field, *found_next_number_field;
|
||||||
|
Field **vfield;
|
||||||
TABLE *copy;
|
TABLE *copy;
|
||||||
TABLE_SHARE *share;
|
TABLE_SHARE *share;
|
||||||
uchar *bitmap;
|
uchar *bitmap;
|
||||||
@ -2379,6 +2380,13 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
|
|||||||
if (!copy_tmp)
|
if (!copy_tmp)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
if (share->vfields)
|
||||||
|
{
|
||||||
|
vfield= (Field **) client_thd->alloc((share->vfields+1)*sizeof(Field*));
|
||||||
|
if (!vfield)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy the TABLE object. */
|
/* Copy the TABLE object. */
|
||||||
copy= new (copy_tmp) TABLE;
|
copy= new (copy_tmp) TABLE;
|
||||||
*copy= *table;
|
*copy= *table;
|
||||||
@ -2408,6 +2416,27 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
|
|||||||
}
|
}
|
||||||
*field=0;
|
*field=0;
|
||||||
|
|
||||||
|
if (share->vfields)
|
||||||
|
{
|
||||||
|
copy->vfield= vfield;
|
||||||
|
for (field= copy->field; *field; field++)
|
||||||
|
{
|
||||||
|
if ((*field)->vcol_info)
|
||||||
|
{
|
||||||
|
bool error_reported= FALSE;
|
||||||
|
if (unpack_vcol_info_from_frm(client_thd,
|
||||||
|
client_thd->mem_root,
|
||||||
|
copy,
|
||||||
|
*field,
|
||||||
|
&(*field)->vcol_info->expr_str,
|
||||||
|
&error_reported))
|
||||||
|
goto error;
|
||||||
|
*vfield++= *field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*vfield= 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Adjust timestamp */
|
/* Adjust timestamp */
|
||||||
if (table->timestamp_field)
|
if (table->timestamp_field)
|
||||||
{
|
{
|
||||||
|
@ -14176,10 +14176,20 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
|
|||||||
|
|
||||||
if (group)
|
if (group)
|
||||||
{
|
{
|
||||||
|
ORDER **prev= &group;
|
||||||
if (!param->quick_group)
|
if (!param->quick_group)
|
||||||
group=0; // Can't use group key
|
group=0; // Can't use group key
|
||||||
else for (ORDER *tmp=group ; tmp ; tmp=tmp->next)
|
else for (ORDER *tmp=group ; tmp ; tmp=tmp->next)
|
||||||
{
|
{
|
||||||
|
/* Exclude found constant from the list */
|
||||||
|
if ((*tmp->item)->const_item())
|
||||||
|
{
|
||||||
|
*prev= tmp->next;
|
||||||
|
param->group_parts--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
prev= &(tmp->next);
|
||||||
/*
|
/*
|
||||||
marker == 4 means two things:
|
marker == 4 means two things:
|
||||||
- store NULLs in the key, and
|
- store NULLs in the key, and
|
||||||
|
14
sql/table.cc
14
sql/table.cc
@ -2138,8 +2138,10 @@ end:
|
|||||||
@brief
|
@brief
|
||||||
Unpack the definition of a virtual column from its linear representation
|
Unpack the definition of a virtual column from its linear representation
|
||||||
|
|
||||||
@parm
|
@param
|
||||||
thd The thread object
|
thd The thread object
|
||||||
|
@param
|
||||||
|
mem_root The mem_root object where to allocated memory
|
||||||
@param
|
@param
|
||||||
table The table containing the virtual column
|
table The table containing the virtual column
|
||||||
@param
|
@param
|
||||||
@ -2169,6 +2171,7 @@ end:
|
|||||||
TRUE Otherwise
|
TRUE Otherwise
|
||||||
*/
|
*/
|
||||||
bool unpack_vcol_info_from_frm(THD *thd,
|
bool unpack_vcol_info_from_frm(THD *thd,
|
||||||
|
MEM_ROOT *mem_root,
|
||||||
TABLE *table,
|
TABLE *table,
|
||||||
Field *field,
|
Field *field,
|
||||||
LEX_STRING *vcol_expr,
|
LEX_STRING *vcol_expr,
|
||||||
@ -2196,7 +2199,7 @@ bool unpack_vcol_info_from_frm(THD *thd,
|
|||||||
"PARSE_VCOL_EXPR (<expr_string_from_frm>)".
|
"PARSE_VCOL_EXPR (<expr_string_from_frm>)".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!(vcol_expr_str= (char*) alloc_root(&table->mem_root,
|
if (!(vcol_expr_str= (char*) alloc_root(mem_root,
|
||||||
vcol_expr->length +
|
vcol_expr->length +
|
||||||
parse_vcol_keyword.length + 3)))
|
parse_vcol_keyword.length + 3)))
|
||||||
{
|
{
|
||||||
@ -2230,10 +2233,10 @@ bool unpack_vcol_info_from_frm(THD *thd,
|
|||||||
We need to use CONVENTIONAL_EXECUTION here to ensure that
|
We need to use CONVENTIONAL_EXECUTION here to ensure that
|
||||||
any new items created by fix_fields() are not reverted.
|
any new items created by fix_fields() are not reverted.
|
||||||
*/
|
*/
|
||||||
Query_arena expr_arena(&table->mem_root,
|
Query_arena expr_arena(mem_root,
|
||||||
Query_arena::STMT_CONVENTIONAL_EXECUTION);
|
Query_arena::STMT_CONVENTIONAL_EXECUTION);
|
||||||
if (!(vcol_arena= (Query_arena *) alloc_root(&table->mem_root,
|
if (!(vcol_arena= (Query_arena *) alloc_root(mem_root,
|
||||||
sizeof(Query_arena))))
|
sizeof(Query_arena))))
|
||||||
goto err;
|
goto err;
|
||||||
*vcol_arena= expr_arena;
|
*vcol_arena= expr_arena;
|
||||||
table->expr_arena= vcol_arena;
|
table->expr_arena= vcol_arena;
|
||||||
@ -2491,6 +2494,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
|
|||||||
if ((*field_ptr)->vcol_info)
|
if ((*field_ptr)->vcol_info)
|
||||||
{
|
{
|
||||||
if (unpack_vcol_info_from_frm(thd,
|
if (unpack_vcol_info_from_frm(thd,
|
||||||
|
&outparam->mem_root,
|
||||||
outparam,
|
outparam,
|
||||||
*field_ptr,
|
*field_ptr,
|
||||||
&(*field_ptr)->vcol_info->expr_str,
|
&(*field_ptr)->vcol_info->expr_str,
|
||||||
|
@ -2373,6 +2373,9 @@ void init_mdl_requests(TABLE_LIST *table_list);
|
|||||||
int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
|
int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
|
||||||
uint db_stat, uint prgflag, uint ha_open_flags,
|
uint db_stat, uint prgflag, uint ha_open_flags,
|
||||||
TABLE *outparam, bool is_create_table);
|
TABLE *outparam, bool is_create_table);
|
||||||
|
bool unpack_vcol_info_from_frm(THD *thd, MEM_ROOT *mem_root,
|
||||||
|
TABLE *table, Field *field,
|
||||||
|
LEX_STRING *vcol_expr, bool *error_reported);
|
||||||
TABLE_SHARE *alloc_table_share(TABLE_LIST *table_list, char *key,
|
TABLE_SHARE *alloc_table_share(TABLE_LIST *table_list, char *key,
|
||||||
uint key_length);
|
uint key_length);
|
||||||
void init_tmp_table_share(THD *thd, TABLE_SHARE *share, const char *key,
|
void init_tmp_table_share(THD *thd, TABLE_SHARE *share, const char *key,
|
||||||
|
185
sql/uniques.cc
185
sql/uniques.cc
@ -584,6 +584,7 @@ end:
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
Unique:walk()
|
Unique:walk()
|
||||||
All params are 'IN':
|
All params are 'IN':
|
||||||
|
table parameter for the call of the merge method
|
||||||
action function-visitor, typed in include/my_tree.h
|
action function-visitor, typed in include/my_tree.h
|
||||||
function is called for each unique element
|
function is called for each unique element
|
||||||
arg argument for visitor, which is passed to it on each call
|
arg argument for visitor, which is passed to it on each call
|
||||||
@ -592,30 +593,120 @@ end:
|
|||||||
<> 0 error
|
<> 0 error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool Unique::walk(tree_walk_action action, void *walk_action_arg)
|
bool Unique::walk(TABLE *table, tree_walk_action action, void *walk_action_arg)
|
||||||
{
|
{
|
||||||
int res;
|
int res= 0;
|
||||||
uchar *merge_buffer;
|
uchar *merge_buffer;
|
||||||
|
|
||||||
if (elements == 0) /* the whole tree is in memory */
|
if (elements == 0) /* the whole tree is in memory */
|
||||||
return tree_walk(&tree, action, walk_action_arg, left_root_right);
|
return tree_walk(&tree, action, walk_action_arg, left_root_right);
|
||||||
|
|
||||||
|
table->sort.found_records=elements+tree.elements_in_tree;
|
||||||
/* flush current tree to the file to have some memory for merge buffer */
|
/* flush current tree to the file to have some memory for merge buffer */
|
||||||
if (flush())
|
if (flush())
|
||||||
return 1;
|
return 1;
|
||||||
if (flush_io_cache(&file) || reinit_io_cache(&file, READ_CACHE, 0L, 0, 0))
|
if (flush_io_cache(&file) || reinit_io_cache(&file, READ_CACHE, 0L, 0, 0))
|
||||||
return 1;
|
return 1;
|
||||||
if (!(merge_buffer= (uchar *) my_malloc((ulong) max_in_memory_size, MYF(0))))
|
ulong buff_sz= (max_in_memory_size / full_size + 1) * full_size;
|
||||||
|
if (!(merge_buffer= (uchar *) my_malloc((ulong) buff_sz, MYF(0))))
|
||||||
return 1;
|
return 1;
|
||||||
res= merge_walk(merge_buffer, (ulong) max_in_memory_size, size,
|
if (buff_sz < (ulong) (full_size * (file_ptrs.elements + 1)))
|
||||||
(BUFFPEK *) file_ptrs.buffer,
|
res= merge(table, merge_buffer, buff_sz >= full_size * MERGEBUFF2) ;
|
||||||
(BUFFPEK *) file_ptrs.buffer + file_ptrs.elements,
|
|
||||||
action, walk_action_arg,
|
if (!res)
|
||||||
tree.compare, tree.custom_arg, &file);
|
{
|
||||||
|
res= merge_walk(merge_buffer, (ulong) max_in_memory_size, full_size,
|
||||||
|
(BUFFPEK *) file_ptrs.buffer,
|
||||||
|
(BUFFPEK *) file_ptrs.buffer + file_ptrs.elements,
|
||||||
|
action, walk_action_arg,
|
||||||
|
tree.compare, tree.custom_arg, &file);
|
||||||
|
}
|
||||||
my_free(merge_buffer);
|
my_free(merge_buffer);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
DESCRIPTION
|
||||||
|
Perform multi-pass sort merge of the elements accessed through table->sort,
|
||||||
|
using the buffer buff as the merge buffer. The last pass is not performed
|
||||||
|
if without_last_merge is TRUE.
|
||||||
|
SYNOPSIS
|
||||||
|
Unique:merge()
|
||||||
|
All params are 'IN':
|
||||||
|
table the parameter to access sort context
|
||||||
|
buff merge buffer
|
||||||
|
without_last_merge TRUE <=> do not perform the last merge
|
||||||
|
RETURN VALUE
|
||||||
|
0 OK
|
||||||
|
<> 0 error
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool Unique::merge(TABLE *table, uchar *buff, bool without_last_merge)
|
||||||
|
{
|
||||||
|
SORTPARAM sort_param;
|
||||||
|
IO_CACHE *outfile= table->sort.io_cache;
|
||||||
|
BUFFPEK *file_ptr= (BUFFPEK*) file_ptrs.buffer;
|
||||||
|
uint maxbuffer= file_ptrs.elements - 1;
|
||||||
|
my_off_t save_pos;
|
||||||
|
bool error= 1;
|
||||||
|
|
||||||
|
/* Open cached file if it isn't open */
|
||||||
|
if (!outfile)
|
||||||
|
outfile= table->sort.io_cache= (IO_CACHE*) my_malloc(sizeof(IO_CACHE),
|
||||||
|
MYF(MY_ZEROFILL));
|
||||||
|
if (!outfile ||
|
||||||
|
(! my_b_inited(outfile) &&
|
||||||
|
open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
|
||||||
|
MYF(MY_WME))))
|
||||||
|
return 1;
|
||||||
|
reinit_io_cache(outfile,WRITE_CACHE,0L,0,0);
|
||||||
|
|
||||||
|
bzero((char*) &sort_param,sizeof(sort_param));
|
||||||
|
sort_param.max_rows= elements;
|
||||||
|
sort_param.sort_form= table;
|
||||||
|
sort_param.rec_length= sort_param.sort_length= sort_param.ref_length=
|
||||||
|
full_size;
|
||||||
|
sort_param.min_dupl_count= min_dupl_count;
|
||||||
|
sort_param.res_length= 0;
|
||||||
|
sort_param.keys= (uint) (max_in_memory_size / sort_param.sort_length);
|
||||||
|
sort_param.not_killable= 1;
|
||||||
|
|
||||||
|
sort_param.unique_buff= buff + (sort_param.keys * sort_param.sort_length);
|
||||||
|
|
||||||
|
sort_param.compare= (qsort2_cmp) buffpek_compare;
|
||||||
|
sort_param.cmp_context.key_compare= tree.compare;
|
||||||
|
sort_param.cmp_context.key_compare_arg= tree.custom_arg;
|
||||||
|
|
||||||
|
/* Merge the buffers to one file, removing duplicates */
|
||||||
|
if (merge_many_buff(&sort_param,buff,file_ptr,&maxbuffer,&file))
|
||||||
|
goto err;
|
||||||
|
if (flush_io_cache(&file) ||
|
||||||
|
reinit_io_cache(&file,READ_CACHE,0L,0,0))
|
||||||
|
goto err;
|
||||||
|
sort_param.res_length= sort_param.rec_length-
|
||||||
|
(min_dupl_count ? sizeof(min_dupl_count) : 0);
|
||||||
|
if (without_last_merge)
|
||||||
|
{
|
||||||
|
file_ptrs.elements= maxbuffer+1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (merge_index(&sort_param, buff, file_ptr, maxbuffer, &file, outfile))
|
||||||
|
goto err;
|
||||||
|
error= 0;
|
||||||
|
err:
|
||||||
|
if (flush_io_cache(outfile))
|
||||||
|
error= 1;
|
||||||
|
|
||||||
|
/* Setup io_cache for reading */
|
||||||
|
save_pos= outfile->pos_in_file;
|
||||||
|
if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
|
||||||
|
error= 1;
|
||||||
|
outfile->end_of_file=save_pos;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Modify the TABLE element so that when one calls init_records()
|
Modify the TABLE element so that when one calls init_records()
|
||||||
the rows will be read in priority order.
|
the rows will be read in priority order.
|
||||||
@ -623,12 +714,13 @@ bool Unique::walk(tree_walk_action action, void *walk_action_arg)
|
|||||||
|
|
||||||
bool Unique::get(TABLE *table)
|
bool Unique::get(TABLE *table)
|
||||||
{
|
{
|
||||||
SORTPARAM sort_param;
|
bool rc= 1;
|
||||||
table->sort.found_records=elements+tree.elements_in_tree;
|
uchar *sort_buffer= NULL;
|
||||||
|
table->sort.found_records= elements+tree.elements_in_tree;
|
||||||
|
|
||||||
if (my_b_tell(&file) == 0)
|
if (my_b_tell(&file) == 0)
|
||||||
{
|
{
|
||||||
/* Whole tree is in memory; Don't use disk if you don't need to */
|
/* Whole tree is in memory; Don't use disk if you don't need to */
|
||||||
DBUG_ASSERT(table->sort.record_pointers == NULL);
|
|
||||||
if ((record_pointers=table->sort.record_pointers= (uchar*)
|
if ((record_pointers=table->sort.record_pointers= (uchar*)
|
||||||
my_malloc(size * tree.elements_in_tree, MYF(0))))
|
my_malloc(size * tree.elements_in_tree, MYF(0))))
|
||||||
{
|
{
|
||||||
@ -645,69 +737,16 @@ bool Unique::get(TABLE *table)
|
|||||||
/* Not enough memory; Save the result to file && free memory used by tree */
|
/* Not enough memory; Save the result to file && free memory used by tree */
|
||||||
if (flush())
|
if (flush())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
IO_CACHE *outfile=table->sort.io_cache;
|
ulong buff_sz= (max_in_memory_size / full_size + 1) * full_size;
|
||||||
BUFFPEK *file_ptr= (BUFFPEK*) file_ptrs.buffer;
|
if (!(sort_buffer= (uchar*) my_malloc(buff_sz, MYF(0))))
|
||||||
uint maxbuffer= file_ptrs.elements - 1;
|
|
||||||
uchar *sort_buffer;
|
|
||||||
my_off_t save_pos;
|
|
||||||
bool error=1;
|
|
||||||
|
|
||||||
/* Open cached file if it isn't open */
|
|
||||||
DBUG_ASSERT(table->sort.io_cache == NULL);
|
|
||||||
outfile=table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
|
|
||||||
MYF(MY_ZEROFILL));
|
|
||||||
|
|
||||||
if (!outfile ||
|
|
||||||
(! my_b_inited(outfile) &&
|
|
||||||
open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
|
|
||||||
MYF(MY_WME))))
|
|
||||||
return 1;
|
return 1;
|
||||||
reinit_io_cache(outfile,WRITE_CACHE,0L,0,0);
|
|
||||||
|
|
||||||
bzero((char*) &sort_param,sizeof(sort_param));
|
if (merge(table, sort_buffer, FALSE))
|
||||||
sort_param.max_rows= elements;
|
goto err;
|
||||||
sort_param.sort_form=table;
|
rc= 0;
|
||||||
sort_param.rec_length= sort_param.sort_length= sort_param.ref_length=
|
|
||||||
full_size;
|
|
||||||
sort_param.min_dupl_count= min_dupl_count;
|
|
||||||
sort_param.res_length= 0;
|
|
||||||
sort_param.keys= (uint) (max_in_memory_size / sort_param.sort_length);
|
|
||||||
sort_param.not_killable=1;
|
|
||||||
|
|
||||||
if (!(sort_buffer=(uchar*) my_malloc((sort_param.keys+1) *
|
err:
|
||||||
sort_param.sort_length,
|
my_free(sort_buffer);
|
||||||
MYF(0))))
|
return rc;
|
||||||
return 1;
|
|
||||||
sort_param.unique_buff= sort_buffer+(sort_param.keys*
|
|
||||||
sort_param.sort_length);
|
|
||||||
|
|
||||||
sort_param.compare= (qsort2_cmp) buffpek_compare;
|
|
||||||
sort_param.cmp_context.key_compare= tree.compare;
|
|
||||||
sort_param.cmp_context.key_compare_arg= tree.custom_arg;
|
|
||||||
|
|
||||||
/* Merge the buffers to one file, removing duplicates */
|
|
||||||
if (merge_many_buff(&sort_param,sort_buffer,file_ptr,&maxbuffer,&file))
|
|
||||||
goto err;
|
|
||||||
if (flush_io_cache(&file) ||
|
|
||||||
reinit_io_cache(&file,READ_CACHE,0L,0,0))
|
|
||||||
goto err;
|
|
||||||
sort_param.res_length= sort_param.rec_length-
|
|
||||||
(min_dupl_count ? sizeof(min_dupl_count) : 0);
|
|
||||||
if (merge_index(&sort_param, sort_buffer, file_ptr, maxbuffer, &file, outfile))
|
|
||||||
goto err;
|
|
||||||
error=0;
|
|
||||||
err:
|
|
||||||
my_free(sort_buffer);
|
|
||||||
if (flush_io_cache(outfile))
|
|
||||||
error=1;
|
|
||||||
|
|
||||||
/* Setup io_cache for reading */
|
|
||||||
save_pos=outfile->pos_in_file;
|
|
||||||
if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
|
|
||||||
error=1;
|
|
||||||
outfile->end_of_file=save_pos;
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user