diff options
author | unknown <sergefp@mysql.com> | 2006-04-25 23:33:31 +0400 |
---|---|---|
committer | unknown <sergefp@mysql.com> | 2006-04-25 23:33:31 +0400 |
commit | 15e00f1f3dc8ed6220e69bd20ba5d9335da070d2 (patch) | |
tree | c54aa25462b54e0d9f5d4f51654c9ecbccbc89da /sql/item_cmpfunc.h | |
parent | 2a138695bf6eecb3c8f6b4e3fcb9a1a224b53c2d (diff) | |
download | mariadb-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.h | 77 |
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) { |