summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/sp.result38
-rw-r--r--mysql-test/r/subselect4.result21
-rw-r--r--mysql-test/r/subselect_innodb.result18
-rw-r--r--mysql-test/r/sum_distinct-big.result15
-rw-r--r--mysql-test/r/type_year.result1
-rw-r--r--mysql-test/suite/vcol/r/vcol_misc.result11
-rw-r--r--mysql-test/suite/vcol/t/vcol_misc.test19
-rw-r--r--mysql-test/t/sp.test20
-rw-r--r--mysql-test/t/subselect4.test24
-rw-r--r--mysql-test/t/subselect_innodb.test14
-rw-r--r--mysql-test/t/sum_distinct-big.test17
-rw-r--r--sql/item_func.cc13
-rw-r--r--sql/item_func.h5
-rw-r--r--sql/item_row.cc2
-rw-r--r--sql/item_sum.cc2
-rw-r--r--sql/sql_base.cc3
-rw-r--r--sql/sql_class.h4
-rw-r--r--sql/sql_insert.cc29
-rw-r--r--sql/sql_select.cc10
-rw-r--r--sql/table.cc14
-rw-r--r--sql/table.h3
-rw-r--r--sql/uniques.cc153
22 files changed, 366 insertions, 70 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index b5e6e84a49a..defd3955f6c 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -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
EXPLAIN SELECT * FROM t1 WHERE c1=f1();
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;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref c1 c1 5 const 1 Using index
EXPLAIN SELECT * FROM v1 WHERE c1=f1();
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);
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);
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
@@ -7852,6 +7852,38 @@ c1 c2 count(c3)
2012-03-01 01:00:00 3 1
2012-03-01 02:00:00 3 1
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
# bug#62125 result for null incorrectly yields 1292 warning.
diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result
index 7f507b7e2d1..2814e5a6dcd 100644
--- a/mysql-test/r/subselect4.result
+++ b/mysql-test/r/subselect4.result
@@ -2274,6 +2274,27 @@ SELECT a3 FROM t3 WHERE b2 = b1 AND b2 <= b1 ORDER BY b3
a1 b1
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
#
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
diff --git a/mysql-test/r/subselect_innodb.result b/mysql-test/r/subselect_innodb.result
index a4670872fad..a6967527a2d 100644
--- a/mysql-test/r/subselect_innodb.result
+++ b/mysql-test/r/subselect_innodb.result
@@ -391,4 +391,22 @@ select 1 from t1 where 1 like (select 1 from t1 where 1 <=> (select 1 from t1 gr
1
1
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;
diff --git a/mysql-test/r/sum_distinct-big.result b/mysql-test/r/sum_distinct-big.result
index 9b55d59ab91..d4933b31f80 100644
--- a/mysql-test/r/sum_distinct-big.result
+++ b/mysql-test/r/sum_distinct-big.result
@@ -103,5 +103,20 @@ sm
10323810
10325070
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 t2;
diff --git a/mysql-test/r/type_year.result b/mysql-test/r/type_year.result
index 4b9bf6f433f..38bddd42cfa 100644
--- a/mysql-test/r/type_year.result
+++ b/mysql-test/r/type_year.result
@@ -389,6 +389,7 @@ select a from t1 where a=(select 2000 from dual where 1);
a
select a from t1 where a=y2k();
a
+00
select a from t1 where a=b;
a
drop table t1;
diff --git a/mysql-test/suite/vcol/r/vcol_misc.result b/mysql-test/suite/vcol/r/vcol_misc.result
index 17b38b7d7af..14467b2d630 100644
--- a/mysql-test/suite/vcol/r/vcol_misc.result
+++ b/mysql-test/suite/vcol/r/vcol_misc.result
@@ -182,6 +182,17 @@ a b c
2 3 y
0 1 y,n
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);
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));
diff --git a/mysql-test/suite/vcol/t/vcol_misc.test b/mysql-test/suite/vcol/t/vcol_misc.test
index 01404046cde..3c51ee4b685 100644
--- a/mysql-test/suite/vcol/t/vcol_misc.test
+++ b/mysql-test/suite/vcol/t/vcol_misc.test
@@ -179,6 +179,25 @@ select * from 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
#
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 2528f0d7b2b..0a368826ee7 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -9151,6 +9151,26 @@ CALL p1(1);
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 # lp:1002157 : testing stored function
--echo # bug#62125 result for null incorrectly yields 1292 warning.
diff --git a/mysql-test/t/subselect4.test b/mysql-test/t/subselect4.test
index d939c60ddd1..37f660d6682 100644
--- a/mysql-test/t/subselect4.test
+++ b/mysql-test/t/subselect4.test
@@ -1805,6 +1805,30 @@ SELECT * FROM t1 WHERE a1 IN (
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 # MDEV-3899 Valgrind warnings (blocks are definitely lost) in filesort on IN subquery with SUM and DISTINCT
--echo #
diff --git a/mysql-test/t/subselect_innodb.test b/mysql-test/t/subselect_innodb.test
index 3af8f31062c..83c36b16163 100644
--- a/mysql-test/t/subselect_innodb.test
+++ b/mysql-test/t/subselect_innodb.test
@@ -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;
+--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;
diff --git a/mysql-test/t/sum_distinct-big.test b/mysql-test/t/sum_distinct-big.test
index 0859f4b3d89..d3710056c9a 100644
--- a/mysql-test/t/sum_distinct-big.test
+++ b/mysql-test/t/sum_distinct-big.test
@@ -63,5 +63,22 @@ SELECT SUM(DISTINCT id) sm FROM t1;
SELECT SUM(DISTINCT id) sm FROM t2;
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 t2;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 7053b8fec65..7f309c7a4d3 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -6525,6 +6525,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.
@note called from Item::fix_fields.
diff --git a/sql/item_func.h b/sql/item_func.h
index 4306c6ea47a..7b6b60b2914 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1907,7 +1907,8 @@ private:
bool init_result_field(THD *thd);
protected:
- bool is_expensive_processor(uchar *arg) { return TRUE; }
+ bool is_expensive_processor(uchar *arg)
+ { return is_expensive(); }
public:
@@ -1986,7 +1987,7 @@ public:
bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec(void);
- bool is_expensive() { return 1; }
+ bool is_expensive();
inline Field *get_sp_result_field()
{
diff --git a/sql/item_row.cc b/sql/item_row.cc
index 2c4a628075e..cfd2f34095c 100644
--- a/sql/item_row.cc
+++ b/sql/item_row.cc
@@ -145,11 +145,13 @@ void Item_row::update_used_tables()
{
used_tables_cache= 0;
const_item_cache= 1;
+ maybe_null= 0;
for (uint i= 0; i < arg_count; i++)
{
items[i]->update_used_tables();
used_tables_cache|= items[i]->used_tables();
const_item_cache&= items[i]->const_item();
+ maybe_null|= items[i]->maybe_null;
}
}
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 58d605478af..04358ac8c45 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1086,7 +1086,7 @@ void Aggregator_distinct::endup()
{
/* go over the tree of distinct keys and calculate the aggregate value */
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;
}
/* prevent consecutive recalculations */
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 83ed29064b5..c76f2d43279 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -8939,7 +8939,8 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
ER(ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN),
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));
goto err;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index e92ba129a29..bdf08cea250 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -3856,6 +3856,8 @@ class Unique :public Sql_alloc
uint full_size;
uint min_dupl_count; /* always 0 for unions, > 0 for intersections */
+ bool merge(TABLE *table, uchar *buff, bool without_last_merge);
+
public:
ulong elements;
Unique(qsort_cmp2 comp_func, void *comp_func_fixed_arg,
@@ -3896,7 +3898,7 @@ public:
}
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; }
ulonglong get_max_in_memory_size() const { return max_in_memory_size; }
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 45cc7357155..d6212ded9ba 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -2320,6 +2320,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
{
my_ptrdiff_t adjust_ptrs;
Field **field,**org_field, *found_next_number_field;
+ Field **vfield;
TABLE *copy;
TABLE_SHARE *share;
uchar *bitmap;
@@ -2379,6 +2380,13 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
if (!copy_tmp)
goto error;
+ if (share->vfields)
+ {
+ vfield= (Field **) client_thd->alloc((share->vfields+1)*sizeof(Field*));
+ if (!vfield)
+ goto error;
+ }
+
/* Copy the TABLE object. */
copy= new (copy_tmp) TABLE;
*copy= *table;
@@ -2408,6 +2416,27 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
}
*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 */
if (table->timestamp_field)
{
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 1146d37d06b..232ace2858c 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -14176,10 +14176,20 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
if (group)
{
+ ORDER **prev= &group;
if (!param->quick_group)
group=0; // Can't use group key
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:
- store NULLs in the key, and
diff --git a/sql/table.cc b/sql/table.cc
index a36a6d19484..fba45f421ed 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -2138,9 +2138,11 @@ end:
@brief
Unpack the definition of a virtual column from its linear representation
- @parm
+ @param
thd The thread object
@param
+ mem_root The mem_root object where to allocated memory
+ @param
table The table containing the virtual column
@param
field The field for the virtual
@@ -2169,6 +2171,7 @@ end:
TRUE Otherwise
*/
bool unpack_vcol_info_from_frm(THD *thd,
+ MEM_ROOT *mem_root,
TABLE *table,
Field *field,
LEX_STRING *vcol_expr,
@@ -2196,7 +2199,7 @@ bool unpack_vcol_info_from_frm(THD *thd,
"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 +
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
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);
- if (!(vcol_arena= (Query_arena *) alloc_root(&table->mem_root,
- sizeof(Query_arena))))
+ if (!(vcol_arena= (Query_arena *) alloc_root(mem_root,
+ sizeof(Query_arena))))
goto err;
*vcol_arena= expr_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 (unpack_vcol_info_from_frm(thd,
+ &outparam->mem_root,
outparam,
*field_ptr,
&(*field_ptr)->vcol_info->expr_str,
diff --git a/sql/table.h b/sql/table.h
index 59e142eaa20..c21b01f53f7 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -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,
uint db_stat, uint prgflag, uint ha_open_flags,
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,
uint key_length);
void init_tmp_table_share(THD *thd, TABLE_SHARE *share, const char *key,
diff --git a/sql/uniques.cc b/sql/uniques.cc
index 69de2844f5b..72411be5cd6 100644
--- a/sql/uniques.cc
+++ b/sql/uniques.cc
@@ -584,6 +584,7 @@ end:
SYNOPSIS
Unique:walk()
All params are 'IN':
+ table parameter for the call of the merge method
action function-visitor, typed in include/my_tree.h
function is called for each unique element
arg argument for visitor, which is passed to it on each call
@@ -592,72 +593,68 @@ end:
<> 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;
if (elements == 0) /* the whole tree is in memory */
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 */
if (flush())
return 1;
if (flush_io_cache(&file) || reinit_io_cache(&file, READ_CACHE, 0L, 0, 0))
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;
- res= merge_walk(merge_buffer, (ulong) max_in_memory_size, size,
- (BUFFPEK *) file_ptrs.buffer,
- (BUFFPEK *) file_ptrs.buffer + file_ptrs.elements,
- action, walk_action_arg,
- tree.compare, tree.custom_arg, &file);
+ if (buff_sz < (ulong) (full_size * (file_ptrs.elements + 1)))
+ res= merge(table, merge_buffer, buff_sz >= full_size * MERGEBUFF2) ;
+
+ if (!res)
+ {
+ 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);
return res;
}
+
/*
- Modify the TABLE element so that when one calls init_records()
- the rows will be read in priority order.
-*/
+ 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::get(TABLE *table)
+bool Unique::merge(TABLE *table, uchar *buff, bool without_last_merge)
{
SORTPARAM sort_param;
- table->sort.found_records=elements+tree.elements_in_tree;
- if (my_b_tell(&file) == 0)
- {
- /* 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*)
- my_malloc(size * tree.elements_in_tree, MYF(0))))
- {
- tree_walk_action action= min_dupl_count ?
- (tree_walk_action) unique_intersect_write_to_ptrs :
- (tree_walk_action) unique_write_to_ptrs;
- filtered_out_elems= 0;
- (void) tree_walk(&tree, action,
- this, left_root_right);
- table->sort.found_records-= filtered_out_elems;
- return 0;
- }
- }
- /* Not enough memory; Save the result to file && free memory used by tree */
- if (flush())
- return 1;
-
- IO_CACHE *outfile=table->sort.io_cache;
+ IO_CACHE *outfile= table->sort.io_cache;
BUFFPEK *file_ptr= (BUFFPEK*) file_ptrs.buffer;
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));
+ 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,
@@ -667,47 +664,89 @@ bool Unique::get(TABLE *table)
bzero((char*) &sort_param,sizeof(sort_param));
sort_param.max_rows= elements;
- sort_param.sort_form=table;
+ 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.not_killable= 1;
- if (!(sort_buffer=(uchar*) my_malloc((sort_param.keys+1) *
- sort_param.sort_length,
- MYF(0))))
- return 1;
- sort_param.unique_buff= sort_buffer+(sort_param.keys*
- sort_param.sort_length);
+ 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,sort_buffer,file_ptr,&maxbuffer,&file))
+ 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 (merge_index(&sort_param, sort_buffer, file_ptr, maxbuffer, &file, outfile))
+ 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;
+ error= 0;
err:
- my_free(sort_buffer);
if (flush_io_cache(outfile))
- error=1;
+ error= 1;
/* Setup io_cache for reading */
- save_pos=outfile->pos_in_file;
+ save_pos= outfile->pos_in_file;
if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
- error=1;
+ error= 1;
outfile->end_of_file=save_pos;
return error;
}
+/*
+ Modify the TABLE element so that when one calls init_records()
+ the rows will be read in priority order.
+*/
+
+bool Unique::get(TABLE *table)
+{
+ bool rc= 1;
+ uchar *sort_buffer= NULL;
+ table->sort.found_records= elements+tree.elements_in_tree;
+
+ if (my_b_tell(&file) == 0)
+ {
+ /* Whole tree is in memory; Don't use disk if you don't need to */
+ if ((record_pointers=table->sort.record_pointers= (uchar*)
+ my_malloc(size * tree.elements_in_tree, MYF(0))))
+ {
+ tree_walk_action action= min_dupl_count ?
+ (tree_walk_action) unique_intersect_write_to_ptrs :
+ (tree_walk_action) unique_write_to_ptrs;
+ filtered_out_elems= 0;
+ (void) tree_walk(&tree, action,
+ this, left_root_right);
+ table->sort.found_records-= filtered_out_elems;
+ return 0;
+ }
+ }
+ /* Not enough memory; Save the result to file && free memory used by tree */
+ if (flush())
+ return 1;
+
+ ulong buff_sz= (max_in_memory_size / full_size + 1) * full_size;
+ if (!(sort_buffer= (uchar*) my_malloc(buff_sz, MYF(0))))
+ return 1;
+
+ if (merge(table, sort_buffer, FALSE))
+ goto err;
+ rc= 0;
+
+err:
+ my_free(sort_buffer);
+ return rc;
+}