summaryrefslogtreecommitdiff
path: root/sql/item_cmpfunc.h
diff options
context:
space:
mode:
authorunknown <sergefp@mysql.com>2006-04-25 23:33:31 +0400
committerunknown <sergefp@mysql.com>2006-04-25 23:33:31 +0400
commit15e00f1f3dc8ed6220e69bd20ba5d9335da070d2 (patch)
treec54aa25462b54e0d9f5d4f51654c9ecbccbc89da /sql/item_cmpfunc.h
parent2a138695bf6eecb3c8f6b4e3fcb9a1a224b53c2d (diff)
downloadmariadb-git-15e00f1f3dc8ed6220e69bd20ba5d9335da070d2.tar.gz
BUG#15872: Don't run the range analyzer on "t1.keypart NOT IN (const1, ..., )", as that consumes
too much memory. Instead, either create the equvalent SEL_TREE manually, or create only two ranges that strictly include the area to scan (Note: just to re-iterate: increasing NOT_IN_IGNORE_THRESHOLD will make optimization run slower for big IN-lists, but the server will not run out of memory. O(N^2) memory use has been eliminated) mysql-test/r/func_in.result: Testcase for BUG#15872 mysql-test/t/func_in.test: Testcase for BUG#15872 sql/item.cc: BUG#15872: Added Item_decimal::set_decimal_value() sql/item.h: UG#15872: Added Item_decimal::set_decimal_value() sql/item_cmpfunc.h: BUG#15872: Added in_vector::create_item(), in_vector::value_to_item() and their implementations in concrete classes. sql/opt_range.cc: BUG#15872: Don't run the range analyzer on "t1.keypart NOT IN (const1, ..., )", as that consumes too much memory. Instead, either A) create the equivalent SEL_TREE manually, making use of the fact that item_not_in->array has an ordered IN-list, or B) create only two ranges: (-inf|NULL) < X < min_value_from_in_list, max_value_from_in_list < X (Choose #B if the IN-list has > 10K elements)
Diffstat (limited to 'sql/item_cmpfunc.h')
-rw-r--r--sql/item_cmpfunc.h77
1 files changed, 74 insertions, 3 deletions
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 67f0a5f5e2e..1837603d78f 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -623,15 +623,17 @@ public:
/* Functions to handle the optimized IN */
+
+/* A vector of values of some type */
+
class in_vector :public Sql_alloc
{
- protected:
+public:
char *base;
uint size;
qsort2_cmp compare;
CHARSET_INFO *collation;
uint count;
-public:
uint used_count;
in_vector() {}
in_vector(uint elements,uint element_length,qsort2_cmp cmp_func,
@@ -647,6 +649,32 @@ public:
qsort2(base,used_count,size,compare,collation);
}
int find(Item *item);
+
+ /*
+ Create an instance of Item_{type} (e.g. Item_decimal) constant object
+ which type allows it to hold an element of this vector without any
+ conversions.
+ The purpose of this function is to be able to get elements of this
+ vector in form of Item_xxx constants without creating Item_xxx object
+ for every array element you get (i.e. this implements "FlyWeight" pattern)
+ */
+ virtual Item* create_item() { return NULL; }
+
+ /*
+ Store the value at position #pos into provided item object
+ SYNOPSIS
+ value_to_item()
+ pos Index of value to store
+ item Constant item to store value into. The item must be of the same
+ type that create_item() returns.
+ */
+ virtual void value_to_item(uint pos, Item *item) { }
+
+ /* Compare values number pos1 and pos2 for equality */
+ bool compare_elems(uint pos1, uint pos2)
+ {
+ return test(compare(collation, base + pos1*size, base + pos2*size));
+ }
};
class in_string :public in_vector
@@ -658,6 +686,16 @@ public:
~in_string();
void set(uint pos,Item *item);
byte *get_value(Item *item);
+ Item* create_item()
+ {
+ return new Item_string(collation);
+ }
+ void value_to_item(uint pos, Item *item)
+ {
+ String *str=((String*) base)+pos;
+ Item_string *to= (Item_string*)item;
+ to->str_value= *str;
+ }
};
class in_longlong :public in_vector
@@ -667,6 +705,19 @@ public:
in_longlong(uint elements);
void set(uint pos,Item *item);
byte *get_value(Item *item);
+
+ Item* create_item()
+ {
+ /*
+ We're created a signed INT, this may not be correct in
+ general case (see BUG#19342).
+ */
+ return new Item_int(0);
+ }
+ void value_to_item(uint pos, Item *item)
+ {
+ ((Item_int*)item)->value= ((longlong*)base)[pos];
+ }
};
class in_double :public in_vector
@@ -676,6 +727,15 @@ public:
in_double(uint elements);
void set(uint pos,Item *item);
byte *get_value(Item *item);
+ Item *create_item()
+ {
+ return new Item_float(0.0);
+ }
+ void value_to_item(uint pos, Item *item)
+ {
+ ((Item_float*)item)->value= ((double*) base)[pos];
+ }
+
};
class in_decimal :public in_vector
@@ -685,6 +745,16 @@ public:
in_decimal(uint elements);
void set(uint pos, Item *item);
byte *get_value(Item *item);
+ Item *create_item()
+ {
+ return new Item_decimal(0, FALSE);
+ }
+ void value_to_item(uint pos, Item *item)
+ {
+ my_decimal *dec= ((my_decimal *)base) + pos;
+ Item_decimal *item_dec= (Item_decimal*)item;
+ item_dec->set_decimal_value(dec);
+ }
};
@@ -864,12 +934,13 @@ public:
class Item_func_in :public Item_func_opt_neg
{
+public:
Item_result cmp_type;
in_vector *array;
cmp_item *in_item;
bool have_null;
DTCollation cmp_collation;
- public:
+
Item_func_in(List<Item> &list)
:Item_func_opt_neg(list), array(0), in_item(0), have_null(0)
{