summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <sergefp@pylon.mylan>2007-03-29 12:24:23 +0400
committerunknown <sergefp@pylon.mylan>2007-03-29 12:24:23 +0400
commit94069acc2ffb4941daf9d6f3561ff0792f4ea714 (patch)
tree899f2fd8517100118e0727eb54ee00cb8ac31524
parent689910ac9c21e7e117a6fd28fb39233edb07fda4 (diff)
parentbedd5b8766a680539f11ee3f437e4ee1d75b8a87 (diff)
downloadmariadb-git-94069acc2ffb4941daf9d6f3561ff0792f4ea714.tar.gz
Merge mysql.com:/home/psergey/mysql-5.0-merge
into mysql.com:/home/psergey/mysql-5.1-merge BitKeeper/deleted/.del-mysqld.cc.rej: Auto merged mysql-test/r/range.result: Auto merged mysql-test/t/range.test: Auto merged sql/item_sum.cc: Auto merged sql/sql_list.h: Auto merged mysql-test/r/subselect.result: Manual merge mysql-test/t/subselect.test: Manual merge sql/opt_range.cc: Manual merge
-rw-r--r--mysql-test/r/range.result28
-rw-r--r--mysql-test/r/subselect.result22
-rw-r--r--mysql-test/t/range.test32
-rw-r--r--mysql-test/t/subselect.test25
-rw-r--r--sql/item_sum.cc7
-rw-r--r--sql/opt_range.cc163
-rw-r--r--sql/sql_list.h6
7 files changed, 247 insertions, 36 deletions
diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result
index 5cd7e3ebfbd..21b127da412 100644
--- a/mysql-test/r/range.result
+++ b/mysql-test/r/range.result
@@ -717,6 +717,34 @@ d8c4177d225791924.30714720
d8c4177d2380fc201.39666693
d8c4177d24ccef970.14957924
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
CREATE TABLE t1 (
id int(11) NOT NULL auto_increment,
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 3df95536351..4b2ca585d61 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -3924,6 +3924,28 @@ c a (SELECT GROUP_CONCAT(COUNT(a)+1) FROM t2 WHERE m = a)
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;
CREATE TABLE t1 (s1 char(1));
INSERT INTO t1 VALUES ('a');
SELECT * FROM t1 WHERE _utf8'a' = ANY (SELECT s1 FROM t1);
diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test
index b1cec049ab2..68bab0c50a2 100644
--- a/mysql-test/t/range.test
+++ b/mysql-test/t/range.test
@@ -568,6 +568,38 @@ SELECT s.oxid FROM t1 v, t1 s
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
#
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 0ecf0641c5b..88c34bdb9b9 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -2784,6 +2784,31 @@ SELECT COUNT(*) c, 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)
#
CREATE TABLE t1 (s1 char(1));
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 8965a5a8f8c..7d7662f06f7 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -149,6 +149,8 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
if (register_sum_func(thd, ref))
return TRUE;
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)
{
@@ -164,8 +166,9 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
Additionally we have to check whether possible nested set functions
are acceptable here: they are not, if the level of aggregation of
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)
{
my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE),
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 03d97a294ad..0c94a58c429 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -170,6 +170,89 @@ static char is_null_string[2]= {1,0};
- get_quick_select() - Walk the SEL_ARG, materialize the key intervals,
and create QUICK_RANGE_SELECT object that will
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
@@ -200,6 +283,8 @@ public:
enum leaf_color { BLACK,RED } color;
enum Type { IMPOSSIBLE, MAYBE, MAYBE_KEY, KEY_RANGE } type;
+ enum { MAX_SEL_ARGS = 64000 };
+
SEL_ARG() {}
SEL_ARG(SEL_ARG &);
SEL_ARG(Field *,const char *,const char *);
@@ -271,7 +356,8 @@ public:
return new SEL_ARG(field, part, min_value, arg->max_value,
min_flag, arg->max_flag, maybe_flag | arg->maybe_flag);
}
- SEL_ARG *clone(SEL_ARG *new_parent,SEL_ARG **next);
+ SEL_ARG *clone(struct st_qsel_param *param, SEL_ARG *new_parent,
+ SEL_ARG **next);
bool copy_min(SEL_ARG* arg)
{ // Get overlapping range
@@ -423,7 +509,6 @@ public:
{
return parent->left == this ? &parent->left : &parent->right;
}
- SEL_ARG *clone_tree();
/*
@@ -466,6 +551,7 @@ public:
}
return !field->key_cmp(min_val, max_val);
}
+ SEL_ARG *clone_tree(struct st_qsel_param *param);
};
class SEL_IMERGE;
@@ -573,6 +659,8 @@ public:
/* Number of ranges in the last checked tree->key */
uint n_ranges;
uint8 first_null_comp; /* first null component if any, 0 - otherwise */
+ /* Number of SEL_ARG objects allocated by SEL_ARG::clone_tree operations */
+ uint alloced_sel_args;
};
class TABLE_READ_PLAN;
@@ -634,8 +722,8 @@ 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_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 *key_or(SEL_ARG *key1,SEL_ARG *key2);
-static SEL_ARG *key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag);
+static SEL_ARG *key_or(PARAM *param, SEL_ARG *key1,SEL_ARG *key2);
+static SEL_ARG *key_and(PARAM *param, SEL_ARG *key1,SEL_ARG *key2,uint clone_flag);
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,
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();
}
+
/***************************************************************************
** Basic functions for SQL_SELECT and QUICK_RANGE_SELECT
***************************************************************************/
@@ -1510,12 +1599,17 @@ SEL_ARG::SEL_ARG(Field *field_,uint8 part_,char *min_value_,char *max_value_,
left=right= &null_element;
}
-SEL_ARG *SEL_ARG::clone(SEL_ARG *new_parent,SEL_ARG **next_arg)
+SEL_ARG *SEL_ARG::clone(PARAM *param, SEL_ARG *new_parent, SEL_ARG **next_arg)
{
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 (!(tmp= new SEL_ARG(type)))
+ if (!(tmp= new (param->mem_root) SEL_ARG(type)))
return 0; // out of memory
tmp->prev= *next_arg; // Link into next/prev chain
(*next_arg)->next=tmp;
@@ -1523,20 +1617,21 @@ SEL_ARG *SEL_ARG::clone(SEL_ARG *new_parent,SEL_ARG **next_arg)
}
else
{
- if (!(tmp= new SEL_ARG(field,part, min_value,max_value,
- min_flag, max_flag, maybe_flag)))
+ if (!(tmp= new (param->mem_root) SEL_ARG(field,part, min_value,max_value,
+ min_flag, max_flag, maybe_flag)))
return 0; // OOM
tmp->parent=new_parent;
tmp->next_key_part=next_key_part;
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
(*next_arg)->next=tmp;
(*next_arg)= tmp;
if (right != &null_element)
- if (!(tmp->right= right->clone(tmp,next_arg)))
+ if (!(tmp->right= right->clone(param, tmp, next_arg)))
return 0; // OOM
}
increment_use_count(1);
@@ -1614,11 +1709,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(PARAM *param)
{
SEL_ARG tmp_link,*next_arg,*root;
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
tmp_link.next->prev=0; // Fix first link
if (root) // If not OOM
@@ -2120,6 +2216,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
param.real_keynr[param.keys++]=idx;
}
param.key_parts_end=key_parts;
+ param.alloced_sel_args= 0;
/* Calculate cost of full index read for the shortest covering index */
if (!head->covering_keys.is_clear_all())
@@ -5242,7 +5339,8 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param,COND *cond)
while ((item=li++))
{
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
tree=tree_and(param,tree,new_tree);
if (tree && tree->type == SEL_TREE::IMPOSSIBLE)
@@ -5818,9 +5916,9 @@ tree_and(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
tree1->type=SEL_TREE::KEY_SMALLER;
DBUG_RETURN(tree1);
}
-
key_map result_keys;
result_keys.clear_all();
+
/* Join the trees key per key */
SEL_ARG **key1,**key2,**end;
for (key1= tree1->keys,key2= tree2->keys,end=key1+param->keys ;
@@ -5833,7 +5931,7 @@ tree_and(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
flag|=CLONE_KEY1_MAYBE;
if (*key2 && !(*key2)->simple_key())
flag|=CLONE_KEY2_MAYBE;
- *key1=key_and(*key1,*key2,flag);
+ *key1=key_and(param, *key1, *key2, flag);
if (*key1 && (*key1)->type == SEL_ARG::IMPOSSIBLE)
{
tree1->type= SEL_TREE::IMPOSSIBLE;
@@ -5994,7 +6092,7 @@ tree_or(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
for (key1= tree1->keys,key2= tree2->keys,end= key1+param->keys ;
key1 != end ; key1++,key2++)
{
- *key1=key_or(*key1,*key2);
+ *key1=key_or(param, *key1, *key2);
if (*key1)
{
result=tree1; // Added to tree1
@@ -6058,14 +6156,14 @@ tree_or(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
/* And key trees where key1->part < key2 -> part */
static SEL_ARG *
-and_all_keys(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
+and_all_keys(PARAM *param, SEL_ARG *key1, SEL_ARG *key2, uint clone_flag)
{
SEL_ARG *next;
ulong use_count=key1->use_count;
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);
}
if (key1->type == SEL_ARG::MAYBE_KEY)
@@ -6077,7 +6175,7 @@ and_all_keys(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
{
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)
{
key1=key1->tree_delete(next);
@@ -6086,6 +6184,8 @@ and_all_keys(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
next->next_key_part=tmp;
if (use_count)
next->increment_use_count(use_count);
+ if (param->alloced_sel_args > SEL_ARG::MAX_SEL_ARGS)
+ break;
}
else
next->next_key_part=key2;
@@ -6111,7 +6211,7 @@ and_all_keys(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
*/
static SEL_ARG *
-key_and(SEL_ARG *key1, SEL_ARG *key2, uint clone_flag)
+key_and(PARAM *param, SEL_ARG *key1, SEL_ARG *key2, uint clone_flag)
{
if (!key1)
return key2;
@@ -6127,9 +6227,9 @@ key_and(SEL_ARG *key1, SEL_ARG *key2, uint clone_flag)
// key1->part < key2->part
key1->use_count--;
if (key1->use_count > 0)
- if (!(key1= key1->clone_tree()))
+ if (!(key1= key1->clone_tree(param)))
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) &&
@@ -6147,14 +6247,14 @@ key_and(SEL_ARG *key1, SEL_ARG *key2, uint clone_flag)
if (key1->use_count > 1)
{
key1->use_count--;
- if (!(key1=key1->clone_tree()))
+ if (!(key1=key1->clone_tree(param)))
return 0; // OOM
key1->use_count++;
}
if (key1->type == SEL_ARG::MAYBE_KEY)
{ // Both are maybe key
- key1->next_key_part=key_and(key1->next_key_part,key2->next_key_part,
- clone_flag);
+ key1->next_key_part=key_and(param, key1->next_key_part,
+ key2->next_key_part, clone_flag);
if (key1->next_key_part &&
key1->next_key_part->type == SEL_ARG::IMPOSSIBLE)
return key1;
@@ -6165,7 +6265,7 @@ key_and(SEL_ARG *key1, SEL_ARG *key2, uint clone_flag)
if (key2->next_key_part)
{
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
}
@@ -6201,7 +6301,8 @@ key_and(SEL_ARG *key1, SEL_ARG *key2, uint clone_flag)
}
else if (get_range(&e2,&e1,key2))
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);
e2->increment_use_count(1);
if (!next || next->type != SEL_ARG::IMPOSSIBLE)
@@ -6249,7 +6350,7 @@ get_range(SEL_ARG **e1,SEL_ARG **e2,SEL_ARG *root1)
static SEL_ARG *
-key_or(SEL_ARG *key1,SEL_ARG *key2)
+key_or(PARAM *param, SEL_ARG *key1,SEL_ARG *key2)
{
if (!key1)
{
@@ -6297,7 +6398,7 @@ key_or(SEL_ARG *key1,SEL_ARG *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
}
@@ -6441,7 +6542,7 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
{ // tmp.min. <= x <= tmp.max
tmp->maybe_flag|= key.maybe_flag;
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
break;
key.copy_max_to_min(tmp);
@@ -6472,7 +6573,7 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
tmp->increment_use_count(key1->use_count+1);
/* Increment key count as it may be used for next loop */
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);
break;
}
diff --git a/sql/sql_list.h b/sql/sql_list.h
index af30cbe0d6a..ba61a931e04 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -23,7 +23,7 @@
class Sql_alloc
{
public:
- static void *operator new(size_t size)
+ static void *operator new(size_t size) throw ()
{
return (void*) sql_alloc((uint) size);
}
@@ -31,9 +31,9 @@ public:
{
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); }
- 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); }
static void operator delete(void *ptr, size_t size) { TRASH(ptr, size); }
static void operator delete(void *ptr, MEM_ROOT *mem_root)