diff options
Diffstat (limited to 'sql/item_cmpfunc.h')
-rw-r--r-- | sql/item_cmpfunc.h | 301 |
1 files changed, 182 insertions, 119 deletions
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 69b22fd66d5..67035384cf7 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1,7 +1,7 @@ #ifndef ITEM_CMPFUNC_INCLUDED #define ITEM_CMPFUNC_INCLUDED - -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. + Copyright (c) 2009-2011, Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,39 +33,29 @@ class Arg_comparator; typedef int (Arg_comparator::*arg_cmp_func)(); -typedef int (*Item_field_cmpfunc)(Item_field *f1, Item_field *f2, void *arg); +typedef int (*Item_field_cmpfunc)(Item *f1, Item *f2, void *arg); class Arg_comparator: public Sql_alloc { Item **a, **b; arg_cmp_func func; Item_result_field *owner; + bool set_null; // TRUE <=> set owner->null_value Arg_comparator *comparators; // used only for compare_row() double precision; /* Fields used in DATE/DATETIME comparison. */ THD *thd; - enum_field_types a_type, b_type; // Types of a and b items Item *a_cache, *b_cache; // Cached values of a and b items - bool is_nulls_eq; // TRUE <=> compare for the EQUAL_FUNC - bool set_null; // TRUE <=> set owner->null_value // when one of arguments is NULL. - enum enum_date_cmp_type { CMP_DATE_DFLT= 0, CMP_DATE_WITH_DATE, - CMP_DATE_WITH_STR, CMP_STR_WITH_DATE }; - longlong (*get_value_a_func)(THD *thd, Item ***item_arg, Item **cache_arg, - Item *warn_item, bool *is_null); - longlong (*get_value_b_func)(THD *thd, Item ***item_arg, Item **cache_arg, - Item *warn_item, bool *is_null); - bool try_year_cmp_func(Item_result type); public: DTCollation cmp_collation; /* Allow owner function to use string buffers. */ String value1, value2; - Arg_comparator(): comparators(0), thd(0), a_cache(0), b_cache(0), set_null(TRUE), - get_value_a_func(0), get_value_b_func(0) {}; - Arg_comparator(Item **a1, Item **a2): a(a1), b(a2), comparators(0), thd(0), - a_cache(0), b_cache(0), set_null(TRUE), - get_value_a_func(0), get_value_b_func(0) {}; + Arg_comparator(): set_null(TRUE), comparators(0), thd(0), + a_cache(0), b_cache(0) {}; + Arg_comparator(Item **a1, Item **a2): a(a1), b(a2), set_null(TRUE), + comparators(0), thd(0), a_cache(0), b_cache(0) {}; int set_compare_func(Item_result_field *owner, Item_result type); inline int set_compare_func(Item_result_field *owner_arg) @@ -82,8 +72,8 @@ public: { set_null= set_null_arg; return set_cmp_func(owner_arg, a1, a2, - item_cmp_type((*a1)->result_type(), - (*a2)->result_type())); + item_cmp_type((*a1)->cmp_type(), + (*a2)->cmp_type())); } inline int compare() { return (this->*func)(); } @@ -106,14 +96,12 @@ public: int compare_real_fixed(); int compare_e_real_fixed(); int compare_datetime(); // compare args[0] & args[1] as DATETIMEs - - static enum enum_date_cmp_type can_compare_as_dates(Item *a, Item *b, - ulonglong *const_val_arg); + int compare_e_datetime(); Item** cache_converted_constant(THD *thd, Item **value, Item **cache, Item_result type); void set_datetime_cmp_func(Item_result_field *owner_arg, Item **a1, Item **b1); - static arg_cmp_func comparator_matrix [5][2]; + static arg_cmp_func comparator_matrix [6][2]; inline bool is_owner_equal_func() { return (owner->type() == Item::FUNC_ITEM && @@ -124,17 +112,6 @@ public: delete [] comparators; comparators= 0; } - /* - Set correct cmp_context if items would be compared as INTs. - */ - inline void set_cmp_context_for_datetime() - { - DBUG_ASSERT(func == &Arg_comparator::compare_datetime); - if ((*a)->result_as_longlong()) - (*a)->cmp_context= INT_RESULT; - if ((*b)->result_as_longlong()) - (*b)->cmp_context= INT_RESULT; - } friend class Item_func; }; @@ -283,6 +260,13 @@ public: void keep_top_level_cache(); Item *transform(Item_transformer transformer, uchar *arg); virtual Item *expr_cache_insert_transformer(uchar *thd_arg); + bool is_expensive_processor(uchar *arg); + bool is_expensive(); + void set_join_tab_idx(uint join_tab_idx_arg) + { args[1]->set_join_tab_idx(join_tab_idx_arg); } + virtual void get_cache_parameters(List<Item> ¶meters); + bool is_top_level_item(); + bool eval_not_null_tables(uchar *opt_arg); }; class Comp_creator @@ -290,7 +274,14 @@ class Comp_creator public: Comp_creator() {} /* Remove gcc warning */ virtual ~Comp_creator() {} /* Remove gcc warning */ + /** + Create operation with given arguments. + */ virtual Item_bool_func2* create(Item *a, Item *b) const = 0; + /** + Create operation with given arguments in swap order. + */ + virtual Item_bool_func2* create_swap(Item *a, Item *b) const = 0; virtual const char* symbol(bool invert) const = 0; virtual bool eqne_op() const = 0; virtual bool l_op() const = 0; @@ -302,6 +293,7 @@ public: Eq_creator() {} /* Remove gcc warning */ virtual ~Eq_creator() {} /* Remove gcc warning */ virtual Item_bool_func2* create(Item *a, Item *b) const; + virtual Item_bool_func2* create_swap(Item *a, Item *b) const; virtual const char* symbol(bool invert) const { return invert? "<>" : "="; } virtual bool eqne_op() const { return 1; } virtual bool l_op() const { return 0; } @@ -313,6 +305,7 @@ public: Ne_creator() {} /* Remove gcc warning */ virtual ~Ne_creator() {} /* Remove gcc warning */ virtual Item_bool_func2* create(Item *a, Item *b) const; + virtual Item_bool_func2* create_swap(Item *a, Item *b) const; virtual const char* symbol(bool invert) const { return invert? "=" : "<>"; } virtual bool eqne_op() const { return 1; } virtual bool l_op() const { return 0; } @@ -324,6 +317,7 @@ public: Gt_creator() {} /* Remove gcc warning */ virtual ~Gt_creator() {} /* Remove gcc warning */ virtual Item_bool_func2* create(Item *a, Item *b) const; + virtual Item_bool_func2* create_swap(Item *a, Item *b) const; virtual const char* symbol(bool invert) const { return invert? "<=" : ">"; } virtual bool eqne_op() const { return 0; } virtual bool l_op() const { return 0; } @@ -335,6 +329,7 @@ public: Lt_creator() {} /* Remove gcc warning */ virtual ~Lt_creator() {} /* Remove gcc warning */ virtual Item_bool_func2* create(Item *a, Item *b) const; + virtual Item_bool_func2* create_swap(Item *a, Item *b) const; virtual const char* symbol(bool invert) const { return invert? ">=" : "<"; } virtual bool eqne_op() const { return 0; } virtual bool l_op() const { return 1; } @@ -346,6 +341,7 @@ public: Ge_creator() {} /* Remove gcc warning */ virtual ~Ge_creator() {} /* Remove gcc warning */ virtual Item_bool_func2* create(Item *a, Item *b) const; + virtual Item_bool_func2* create_swap(Item *a, Item *b) const; virtual const char* symbol(bool invert) const { return invert? "<" : ">="; } virtual bool eqne_op() const { return 0; } virtual bool l_op() const { return 0; } @@ -357,6 +353,7 @@ public: Le_creator() {} /* Remove gcc warning */ virtual ~Le_creator() {} /* Remove gcc warning */ virtual Item_bool_func2* create(Item *a, Item *b) const; + virtual Item_bool_func2* create_swap(Item *a, Item *b) const; virtual const char* symbol(bool invert) const { return invert? ">" : "<="; } virtual bool eqne_op() const { return 0; } virtual bool l_op() const { return 1; } @@ -409,7 +406,30 @@ public: } Item *neg_transformer(THD *thd); virtual Item *negated_item(); - bool subst_argument_checker(uchar **arg) { return TRUE; } + bool subst_argument_checker(uchar **arg) + { + return (*arg != NULL); + } +}; + +/** + XOR inherits from Item_bool_func2 because it is not optimized yet. + Later, when XOR is optimized, it needs to inherit from + Item_cond instead. See WL#5800. +*/ +class Item_func_xor :public Item_bool_func2 +{ +public: + Item_func_xor(Item *i1, Item *i2) :Item_bool_func2(i1, i2) {} + enum Functype functype() const { return XOR_FUNC; } + const char *func_name() const { return "xor"; } + longlong val_int(); + void top_level_item() {} + Item *neg_transformer(THD *thd); + bool subst_argument_checker(uchar **arg) + { + return (*arg != NULL); + } }; class Item_func_not :public Item_bool_func @@ -481,7 +501,7 @@ public: show(0) {} virtual void top_level_item() { abort_on_null= 1; } - bool top_level() { return abort_on_null; } + bool is_top_level_item() { return abort_on_null; } longlong val_int(); enum Functype functype() const { return NOT_ALL_FUNC; } const char *func_name() const { return "<not>"; } @@ -645,9 +665,7 @@ public: Item_result cmp_type; String value0,value1,value2; /* TRUE <=> arguments will be compared as dates. */ - bool compare_as_dates; - /* Comparators used for DATE/DATETIME comparison. */ - Arg_comparator ge_cmp, le_cmp; + Item *compare_as_dates; Item_func_between(Item *a, Item *b, Item *c) :Item_func_opt_neg(a, b, c), compare_as_dates(FALSE) {} longlong val_int(); @@ -660,6 +678,7 @@ public: bool is_bool_func() { return 1; } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } uint decimal_precision() const { return 1; } + bool eval_not_null_tables(uchar *opt_arg); }; @@ -725,6 +744,7 @@ public: const char *func_name() const { return "coalesce"; } table_map not_null_tables() const { return 0; } enum_field_types field_type() const { return cached_field_type; } + bool get_date(MYSQL_TIME *ltime,uint fuzzydate); }; @@ -764,6 +784,7 @@ public: void fix_length_and_dec(); uint decimal_precision() const; const char *func_name() const { return "if"; } + bool eval_not_null_tables(uchar *opt_arg); }; @@ -930,6 +951,16 @@ public: lval_cache(0) {}; void set(uint pos,Item *item); uchar *get_value(Item *item); + Item* create_item() + { + return new Item_datetime(); + } + void value_to_item(uint pos, Item *item) + { + packed_longlong *val= reinterpret_cast<packed_longlong*>(base)+pos; + Item_datetime *dt= reinterpret_cast<Item_datetime*>(item); + dt->set(val->val); + } friend int cmp_longlong(void *cmp_arg, packed_longlong *a,packed_longlong *b); }; @@ -989,7 +1020,8 @@ public: virtual int cmp(Item *item)= 0; // for optimized IN with row virtual int compare(cmp_item *item)= 0; - static cmp_item* get_comparator(Item_result type, CHARSET_INFO *cs); + static cmp_item* get_comparator(Item_result type, Item * warn_item, + CHARSET_INFO *cs); virtual cmp_item *make_same()= 0; virtual void store_value_by_template(cmp_item *tmpl, Item *item) { @@ -1185,7 +1217,7 @@ class Item_func_case :public Item_func Item_result cmp_type; DTCollation cmp_collation; enum_field_types cached_field_type; - cmp_item *cmp_items[5]; /* For all result types */ + cmp_item *cmp_items[6]; /* For all result types */ cmp_item *case_item; public: Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg) @@ -1275,7 +1307,7 @@ public: Item_int_func::cleanup(); delete array; array= 0; - for (i= 0; i <= (uint)DECIMAL_RESULT + 1; i++) + for (i= 0; i <= (uint)TIME_RESULT; i++) { delete cmp_items[i]; cmp_items[i]= 0; @@ -1290,6 +1322,7 @@ public: bool nulls_in_row(); bool is_bool_func() { return 1; } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } + bool eval_not_null_tables(uchar *opt_arg); }; class cmp_item_row :public cmp_item @@ -1325,8 +1358,6 @@ public: class Item_func_isnull :public Item_bool_func { -protected: - longlong cached_value; public: Item_func_isnull(Item *a) :Item_bool_func(a) {} longlong val_int(); @@ -1344,17 +1375,12 @@ public: { used_tables_cache= 0; /* is always false */ const_item_cache= 1; - cached_value= (longlong) 0; } else { args[0]->update_used_tables(); - if ((const_item_cache= !(used_tables_cache= args[0]->used_tables()) && - !with_subselect)) - { - /* Remember if the value is always NULL or never NULL */ - cached_value= (longlong) args[0]->is_null(); - } + used_tables_cache= args[0]->used_tables(); + const_item_cache= args[0]->const_item(); } } table_map not_null_tables() const { return 0; } @@ -1387,6 +1413,7 @@ public: */ table_map used_tables() const { return used_tables_cache | RAND_TABLE_BIT; } + bool const_item() const { return FALSE; } }; @@ -1536,6 +1563,7 @@ public: bool subst_argument_checker(uchar **arg) { return TRUE; } Item *compile(Item_analyzer analyzer, uchar **arg_p, Item_transformer transformer, uchar *arg_t); + bool eval_not_null_tables(uchar *opt_arg); }; @@ -1616,28 +1644,64 @@ public: class Item_equal: public Item_bool_func { - List<Item_field> fields; /* list of equal field items */ - Item *const_item; /* optional constant item equal to fields items */ + /* + The list of equal items. Currently the list can contain: + - Item_fields items for references to table columns + - Item_direct_view_ref items for references to view columns + - one const item + + If the list contains a constant item this item is always first in the list. + The list contains at least two elements. + Currently all Item_fields/Item_direct_view_ref items in the list should + refer to table columns with equavalent type definitions. In particular + if these are string columns they should have the same charset/collation. + + Use objects of the companion class Item_equal_fields_iterator to iterate + over all items from the list of the Item_field/Item_direct_view_ref classes. + */ + List<Item> equal_items; + /* + TRUE <-> one of the items is a const item. + Such item is always first in in the equal_items list + */ + bool with_const; + /* + The field eval_item is used when this item is evaluated + with the method val_int() + */ cmp_item *eval_item; - Arg_comparator cmp; + /* + This initially is set to FALSE. It becomes TRUE when this item is evaluated + as being always false. If the flag is TRUE the contents of the list + the equal_items should be ignored. + */ bool cond_false; + /* + compare_as_dates=TRUE <-> constants equal to fields from equal_items + must be compared as datetimes and not as strings. + compare_as_dates can be TRUE only if with_const=TRUE + */ bool compare_as_dates; + /* + The comparator used to compare constants equal to fields from equal_items + as datetimes. The comparator is used only if compare_as_dates=TRUE + */ + Arg_comparator cmp; public: inline Item_equal() - : Item_bool_func(), const_item(0), eval_item(0), cond_false(0) + : Item_bool_func(), with_const(FALSE), eval_item(0), cond_false(0) { const_item_cache=0 ;} - Item_equal(Item_field *f1, Item_field *f2); - Item_equal(Item *c, Item_field *f); + Item_equal(Item *f1, Item *f2, bool with_const_item); Item_equal(Item_equal *item_equal); - inline Item* get_const() { return const_item; } - void compare_const(Item *c); - void add(Item *c, Item_field *f); - void add(Item *c); - void add(Item_field *f); - uint members(); + /* Currently the const item is always the first in the list of equal items */ + inline Item* get_const() { return with_const ? equal_items.head() : NULL; } + void add_const(Item *c, Item *f = NULL); + /** Add a non-constant item to the multiple equality */ + void add(Item *f) { equal_items.push_back(f); } bool contains(Field *field); - Item_field* get_first(Item_field *field); - uint n_fields() { return fields.elements; } + Item* get_first(Item *field); + /** Get number of field items / references to field items in this object */ + uint n_field_items() { return equal_items.elements-test(with_const); } void merge(Item_equal *item); void update_const(); enum Functype functype() const { return MULT_EQUAL_FUNC; } @@ -1645,18 +1709,18 @@ public: const char *func_name() const { return "multiple equal"; } optimize_type select_optimize() const { return OPTIMIZE_EQUAL; } void sort(Item_field_cmpfunc compare, void *arg); - friend class Item_equal_iterator; void fix_length_and_dec(); bool fix_fields(THD *thd, Item **ref); void update_used_tables(); bool walk(Item_processor processor, bool walk_subquery, uchar *arg); Item *transform(Item_transformer transformer, uchar *arg); virtual void print(String *str, enum_query_type query_type); - CHARSET_INFO *compare_collation() - { return fields.head()->collation.collation; } + CHARSET_INFO *compare_collation(); + friend class Item_equal_fields_iterator; friend Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, Item_equal *item_equal); - friend bool setup_sj_materialization(struct st_join_table *tab); + friend bool setup_sj_materialization_part1(struct st_join_table *tab); + friend bool setup_sj_materialization_part2(struct st_join_table *tab); }; class COND_EQUAL: public Sql_alloc @@ -1674,23 +1738,52 @@ public: }; -class Item_equal_iterator : public List_iterator_fast<Item_field> +/* + The class Item_equal_fields_iterator is used to iterate over references + to table/view columns from a list of equal items. +*/ + +class Item_equal_fields_iterator : public List_iterator_fast<Item> { + Item_equal *item_equal; + Item *curr_item; public: - inline Item_equal_iterator(Item_equal &item_equal) - :List_iterator_fast<Item_field> (item_equal.fields) - {} - inline Item_field* operator++(int) - { - Item_field *item= (*(List_iterator_fast<Item_field> *) this)++; - return item; + Item_equal_fields_iterator(Item_equal &item_eq) + :List_iterator_fast<Item> (item_eq.equal_items) + { + curr_item= NULL; + item_equal= &item_eq; + if (item_eq.with_const) + { + List_iterator_fast<Item> *list_it= this; + curr_item= (*list_it)++; + } } - inline void rewind(void) + Item* operator++(int) { - List_iterator_fast<Item_field>::rewind(); + List_iterator_fast<Item> *list_it= this; + curr_item= (*list_it)++; + return curr_item; + } + Item ** ref() + { + return List_iterator_fast<Item>::ref(); } + void rewind(void) + { + List_iterator_fast<Item> *list_it= this; + list_it->rewind(); + if (item_equal->with_const) + curr_item= (*list_it)++; + } + Field *get_curr_field() + { + Item_field *item= (Item_field *) (curr_item->real_item()); + return item->field; + } }; + class Item_cond_and :public Item_cond { public: @@ -1746,6 +1839,14 @@ public: Item *neg_transformer(THD *thd); }; +class Item_func_dyncol_exists :public Item_bool_func +{ +public: + Item_func_dyncol_exists(Item *str, Item *num) :Item_bool_func(str, num) {} + longlong val_int(); + const char *func_name() const { return "column_exists"; } +}; + inline bool is_cond_or(Item *item) { if (item->type() != Item::COND_ITEM) @@ -1755,45 +1856,6 @@ inline bool is_cond_or(Item *item) return (cond_item->functype() == Item_func::COND_OR_FUNC); } -/* - XOR is Item_cond, not an Item_int_func because we could like to - optimize (a XOR b) later on. It's low prio, though -*/ - -class Item_cond_xor :public Item_cond -{ -public: - Item_cond_xor(Item *i1,Item *i2) :Item_cond(i1,i2) - { - /* - Items must be stored in args[] as well because this Item_cond is - treated as a FUNC_ITEM (see type()). I.e., users of it will get - it's children by calling arguments(), not argument_list(). This - is a temporary solution until XOR is optimized and treated like - a full Item_cond citizen. - */ - arg_count= 2; - args= tmp_arg; - args[0]= i1; - args[1]= i2; - } - enum Functype functype() const { return COND_XOR_FUNC; } - /* TODO: remove the next line when implementing XOR optimization */ - enum Type type() const { return FUNC_ITEM; } - longlong val_int(); - const char *func_name() const { return "xor"; } - void top_level_item() {} - /* Since child Items are stored in args[], Items cannot be added. - However, since Item_cond_xor is treated as a FUNC_ITEM (see - type()), the methods below should never be called. - */ - bool add(Item *item) { DBUG_ASSERT(FALSE); return FALSE; } - bool add_at_head(Item *item) { DBUG_ASSERT(FALSE); return FALSE; } - bool add_at_head(List<Item> *nlist) { DBUG_ASSERT(FALSE); return FALSE; } - void copy_andor_arguments(THD *thd, Item_cond *item) { DBUG_ASSERT(FALSE); } -}; - - /* Some useful inline functions */ inline Item *and_conds(Item *a, Item *b) @@ -1826,3 +1888,4 @@ extern Ge_creator ge_creator; extern Le_creator le_creator; #endif /* ITEM_CMPFUNC_INCLUDED */ + |