diff options
Diffstat (limited to 'sql/item.h')
-rw-r--r-- | sql/item.h | 498 |
1 files changed, 333 insertions, 165 deletions
diff --git a/sql/item.h b/sql/item.h index b13438b248f..cda2ab73c4a 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1,7 +1,8 @@ #ifndef SQL_ITEM_INCLUDED #define SQL_ITEM_INCLUDED -/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2011, 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 @@ -28,6 +29,10 @@ #include "thr_malloc.h" /* sql_calloc */ #include "field.h" /* Derivation */ +C_MODE_START +#include <ma_dyncol.h> +C_MODE_END + static inline bool trace_unsupported_func(const char *where, const char *processor_name) { @@ -506,6 +511,17 @@ public: }; +struct st_dyncall_create_def +{ + Item *num, *value; + CHARSET_INFO *cs; + uint len, frac; + DYNAMIC_COLUMN_TYPE type; +}; + +typedef struct st_dyncall_create_def DYNCALL_CREATE_DEF; + + typedef bool (Item::*Item_processor) (uchar *arg); /* Analyzer function @@ -522,10 +538,24 @@ typedef bool (Item::*Item_analyzer) (uchar **argp); typedef Item* (Item::*Item_transformer) (uchar *arg); typedef void (*Cond_traverser) (const Item *item, void *arg); +class Item_equal; +class COND_EQUAL; + class Item { Item(const Item &); /* Prevent use of these */ void operator=(Item &); + /** + The index in the JOIN::join_tab array of the JOIN_TAB this Item is attached + to. Items are attached (or 'pushed') to JOIN_TABs during optimization by the + make_cond_for_table procedure. During query execution, this item is + evaluated when the join loop reaches the corresponding JOIN_TAB. + + If the value of join_tab_idx >= MAX_TABLES, this means that there is no + corresponding JOIN_TAB. + */ + uint join_tab_idx; + public: static void *operator new(size_t size) throw () { return sql_alloc(size); } @@ -572,16 +602,23 @@ public: Item *next; uint32 max_length; /* Maximum length, in bytes */ /* - TODO: convert name and name_length fields into String to keep them in sync - (see bug #11829681/60295 etc). + TODO: convert name and name_length fields into LEX_STRING to keep them in + sync (see bug #11829681/60295 etc). Then also remove some strlen(name) + calls. */ uint name_length; /* Length of name */ int8 marker; uint8 decimals; bool maybe_null; /* If item may be null */ + bool in_rollup; /* If used in GROUP BY list + of a query with ROLLUP */ bool null_value; /* if item is null */ bool unsigned_flag; - bool with_sum_func; + bool with_sum_func; /* True if item contains a sum func */ + /** + True if any item except Item_sum_func contains a field. Set during parsing. + */ + bool with_field; bool fixed; /* If item fixed with fix_fields */ bool is_autogenerated_name; /* indicate was name of this Item autogenerated or set by user */ @@ -621,10 +658,17 @@ public: virtual void fix_after_pullout(st_select_lex *new_parent, Item **ref) {}; /* - should be used in case where we are sure that we do not need + This method should be used in case where we are sure that we do not need complete fix_fields() procedure. + Usually this method is used by the optimizer when it has to create a new + item out of other already fixed items. For example, if the optimizer has + to create a new Item_func for an inferred equality whose left and right + parts are already fixed items. In some cases the optimizer cannot use + directly fixed items as the arguments of the created functional item, + but rather uses intermediate type conversion items. Then the method is + supposed to be applied recursively. */ - inline void quick_fix_field() { fixed= 1; } + virtual inline void quick_fix_field() { fixed= 1; } /* Function returns 1 on overflow and -1 on fatal errors */ int save_in_field_no_warnings(Field *field, bool no_conversions); virtual int save_in_field(Field *field, bool no_conversions); @@ -634,11 +678,20 @@ public: { return save_in_field(field, 1); } virtual bool send(Protocol *protocol, String *str); virtual bool eq(const Item *, bool binary_cmp) const; + /* result_type() of an item specifies how the value should be returned */ virtual Item_result result_type() const { return REAL_RESULT; } - virtual Item_result cast_to_int_type() const { return result_type(); } + /* ... while cmp_type() specifies how it should be compared */ + virtual Item_result cmp_type() const; + virtual Item_result cast_to_int_type() const { return cmp_type(); } virtual enum_field_types string_field_type() const; virtual enum_field_types field_type() const; virtual enum Type type() const =0; + /* + real_type() is the type of base item. This is same as type() for + most items, except Item_ref() and Item_cache_wrapper() where it + shows the type for the underlaying item. + */ + virtual enum Type real_type() const { return type(); } /* Return information about function monotonicity. See comment for @@ -862,6 +915,7 @@ public: String *val_string_from_real(String *str); String *val_string_from_int(String *str); String *val_string_from_decimal(String *str); + String *val_string_from_date(String *str); my_decimal *val_decimal_from_real(my_decimal *decimal_value); my_decimal *val_decimal_from_int(my_decimal *decimal_value); my_decimal *val_decimal_from_string(my_decimal *decimal_value); @@ -878,6 +932,8 @@ public: /* This is also used to create fields in CREATE ... SELECT: */ virtual Field *tmp_table_field(TABLE *t_arg) { return 0; } virtual const char *full_name() const { return name ? name : "???"; } + const char *field_name_or_null() + { return real_item()->type() == Item::FIELD_ITEM ? name : NULL; } /* *result* family of methods is analog of *val* family (see above) but @@ -892,13 +948,18 @@ public: { return val_decimal(val); } virtual bool val_bool_result() { return val_bool(); } virtual bool is_null_result() { return is_null(); } - + /* + Returns 1 if result type and collation for val_str() can change between + calls + */ + virtual bool dynamic_result() { return 0; } /* Bitmap of tables used by item (note: if you need to check dependencies on individual columns, check out class Field_enumerator) */ virtual table_map used_tables() const { return (table_map) 0L; } + virtual table_map all_used_tables() const { return used_tables(); } /* Return table map of tables that can't be NULL tables (tables that are used in a context where if they would contain a NULL row generated @@ -953,6 +1014,7 @@ public: } void print_item_w_name(String *, enum_query_type query_type); + void print_value(String *); virtual void update_used_tables() {} virtual void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields) {} @@ -960,7 +1022,9 @@ public: void split_sum_func2(THD *thd, Item **ref_pointer_array, List<Item> &fields, Item **ref, bool skip_registered); virtual bool get_date(MYSQL_TIME *ltime,uint fuzzydate); - virtual bool get_time(MYSQL_TIME *ltime); + bool get_time(MYSQL_TIME *ltime) + { return get_date(ltime, TIME_TIME_ONLY | TIME_FUZZY_DATE); } + bool get_seconds(ulonglong *sec, ulong *sec_part); virtual bool get_date_result(MYSQL_TIME *ltime,uint fuzzydate) { return get_date(ltime,fuzzydate); } /* @@ -1075,10 +1139,14 @@ public: virtual bool reset_query_id_processor(uchar *query_id_arg) { return 0; } virtual bool is_expensive_processor(uchar *arg) { return 0; } virtual bool register_field_in_read_map(uchar *arg) { return 0; } - virtual bool cache_const_expr_analyzer(uchar **arg); - virtual Item* cache_const_expr_transformer(uchar *arg); + virtual bool register_field_in_write_map(uchar *arg) { return 0; } virtual bool enumerate_field_refs_processor(uchar *arg) { return 0; } virtual bool mark_as_eliminated_processor(uchar *arg) { return 0; } + virtual bool eliminate_subselect_processor(uchar *arg) { return 0; } + virtual bool set_fake_select_as_master_processor(uchar *arg) { return 0; } + virtual bool view_used_tables_processor(uchar *arg) { return 0; } + virtual bool eval_not_null_tables(uchar *opt_arg) { return 0; } + virtual bool clear_sum_processor(uchar *opt_arg) { return 0; } /* To call bool function for all arguments */ struct bool_func_call_args @@ -1094,12 +1162,16 @@ public: (this->*(info->bool_function))(); return FALSE; } + /* The next function differs from the previous one that a bitmap to be updated is passed as uchar *arg. */ virtual bool register_field_in_bitmap(uchar *arg) { return 0; } + bool cache_const_expr_analyzer(uchar **arg); + Item* cache_const_expr_transformer(uchar *arg); + /* Check if a partition function is allowed SYNOPSIS @@ -1167,12 +1239,23 @@ public: return FALSE; } + /* + The enumeration Subst_constraint is currently used only in implementations + of the virtual function subst_argument_checker. + */ + enum Subst_constraint + { + NO_SUBST= 0, /* No substitution for a field is allowed */ + ANY_SUBST, /* Any substitution for a field is allowed */ + IDENTITY_SUBST /* Substitution for a field is allowed if any two + different values of the field type are not equal */ + }; + virtual bool subst_argument_checker(uchar **arg) - { - if (*arg) - *arg= NULL; - return TRUE; + { + return (*arg != NULL); } + /* @brief Processor used to check acceptability of an item in the defining @@ -1203,6 +1286,15 @@ public: { return FALSE; } + struct Collect_deps_prm + { + int nest_level; + List<Item> *parameters; + }; + /** + Collect outer references + */ + virtual bool collect_outer_ref_processor(uchar *arg) {return FALSE; } /** Find a function of a given type @@ -1270,47 +1362,17 @@ public: { return 0; } - /* - result_as_longlong() must return TRUE for Items representing DATE/TIME - functions and DATE/TIME table fields. - Those Items have result_type()==STRING_RESULT (and not INT_RESULT), but - their values should be compared as integers (because the integer - representation is more precise than the string one). - */ - virtual bool result_as_longlong() { return FALSE; } - inline bool is_datetime() const - { - switch (field_type()) - { - case MYSQL_TYPE_DATE: - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_TIMESTAMP: - return TRUE; - default: - break; - } - return FALSE; - } /** Check whether this and the given item has compatible comparison context. Used by the equality propagation. See Item_field::equal_fields_propagator. @return - TRUE if the context is the same or if fields could be - compared as DATETIME values by the Arg_comparator. + TRUE if the context is the same FALSE otherwise. */ inline bool has_compatible_context(Item *item) const { - /* Same context. */ - if (cmp_context == (Item_result)-1 || item->cmp_context == cmp_context) - return TRUE; - /* DATETIME comparison context. */ - if (is_datetime()) - return item->is_datetime() || item->cmp_context == STRING_RESULT; - if (item->is_datetime()) - return is_datetime() || cmp_context == STRING_RESULT; - return FALSE; + return cmp_context == IMPOSSIBLE_RESULT || item->cmp_context == cmp_context; } /* Test whether an expression is expensive to compute. Used during @@ -1362,19 +1424,53 @@ public: else max_length= (uint32) max_result_length; } - void fix_length_and_charset_datetime(uint32 max_char_length_arg) - { - collation.set(&my_charset_numeric, DERIVATION_NUMERIC, MY_REPERTOIRE_ASCII); - fix_char_length(max_char_length_arg); - } /* Return TRUE if the item points to a column of an outer-joined table. */ virtual bool is_outer_field() const { DBUG_ASSERT(fixed); return FALSE; } - Item* set_expr_cache(THD *thd, List<Item*> &depends_on); + Item* set_expr_cache(THD *thd); virtual Item *get_cached_item() { return NULL; } + + virtual Item_equal *get_item_equal() { return NULL; } + virtual void set_item_equal(Item_equal *item_eq) {}; + virtual Item_equal *find_item_equal(COND_EQUAL *cond_equal) { return NULL; } + /** + Set the join tab index to the minimal (left-most) JOIN_TAB to which this + Item is attached. The number is an index is depth_first_tab() traversal + order. + */ + virtual void set_join_tab_idx(uint join_tab_idx_arg) + { + if (join_tab_idx_arg < join_tab_idx) + join_tab_idx= join_tab_idx_arg; + } + virtual uint get_join_tab_idx() { return join_tab_idx; } + + table_map view_used_tables(TABLE_LIST *view) + { + view->view_used_tables= 0; + walk(&Item::view_used_tables_processor, 0, (uchar *) view); + return view->view_used_tables; + } + + /** + Collect and add to the list cache parameters for this Item. + + @note Now implemented only for subqueries and in_optimizer, + if we need it for general function then this method should + be defined for Item_func. + */ + virtual void get_cache_parameters(List<Item> ¶meters) { }; }; + +/** + Compare two Items for List<Item>::add_unique() +*/ + +bool cmp_items(Item *a, Item *b); + + /* Class to be used to enumerate all field references in an item tree. This includes references to outside but not fields of the tables within a @@ -1808,10 +1904,15 @@ public: Item_ident(TABLE_LIST *view_arg, const char *field_name_arg); const char *full_name() const; void cleanup(); + st_select_lex *get_depended_from() const; bool remove_dependence_processor(uchar * arg); virtual void print(String *str, enum_query_type query_type); virtual bool change_context_processor(uchar *cntx) { context= (Name_resolution_context *)cntx; return FALSE; } + /** + Collect outer references + */ + virtual bool collect_outer_ref_processor(uchar *arg); friend bool insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, const char *table_name, List_iterator<Item> *it, @@ -1842,9 +1943,6 @@ public: }; -class Item_equal; -class COND_EQUAL; - class Item_field :public Item_ident { protected: @@ -1900,13 +1998,14 @@ public: int save_in_field(Field *field,bool no_conversions); void save_org_in_field(Field *field); table_map used_tables() const; + table_map all_used_tables() const; enum Item_result result_type () const { return field->result_type(); } Item_result cast_to_int_type() const { - return field->cast_to_int_type(); + return field->cmp_type(); } enum_field_types field_type() const { @@ -1921,7 +2020,6 @@ public: Field *tmp_table_field(TABLE *t_arg) { return result_field; } bool get_date(MYSQL_TIME *ltime,uint fuzzydate); bool get_date_result(MYSQL_TIME *ltime,uint fuzzydate); - bool get_time(MYSQL_TIME *ltime); bool is_null() { return field->is_null(); } void update_null_value(); Item *get_tmp_table_item(THD *thd); @@ -1929,16 +2027,15 @@ public: bool add_field_to_set_processor(uchar * arg); bool find_item_in_field_list_processor(uchar *arg); bool register_field_in_read_map(uchar *arg); + bool register_field_in_write_map(uchar *arg); bool register_field_in_bitmap(uchar *arg); bool check_partition_func_processor(uchar *int_arg) {return FALSE;} bool vcol_in_partition_func_processor(uchar *bool_arg); bool check_vcol_func_processor(uchar *arg) { return FALSE;} bool enumerate_field_refs_processor(uchar *arg); void cleanup(); - bool result_as_longlong() - { - return field->can_be_compared_as_longlong(); - } + Item_equal *get_item_equal() { return item_equal; } + void set_item_equal(Item_equal *item_eq) { item_equal= item_eq; } Item_equal *find_item_equal(COND_EQUAL *cond_equal); bool subst_argument_checker(uchar **arg); Item *equal_fields_propagator(uchar *arg); @@ -2096,6 +2193,7 @@ public: Item_param(uint pos_in_query_arg); enum Item_result result_type () const { return item_result_type; } + enum Item_result cast_to_int_type() const { return item_result_type; } enum Type type() const { return item_type; } enum_field_types field_type() const { return param_type; } @@ -2103,7 +2201,6 @@ public: longlong val_int(); my_decimal *val_decimal(my_decimal*); String *val_str(String*); - bool get_time(MYSQL_TIME *tm); bool get_date(MYSQL_TIME *tm, uint fuzzydate); int save_in_field(Field *field, bool no_conversions); @@ -2223,19 +2320,31 @@ class Item_uint :public Item_int { public: Item_uint(const char *str_arg, uint length); - Item_uint(ulonglong i) :Item_int((ulonglong) i, 10) {} + Item_uint(ulonglong i) :Item_int(i, 10) {} Item_uint(const char *str_arg, longlong i, uint length); double val_real() { DBUG_ASSERT(fixed == 1); return ulonglong2double((ulonglong)value); } String *val_str(String*); Item *clone_item() { return new Item_uint(name, value, max_length); } - int save_in_field(Field *field, bool no_conversions); virtual void print(String *str, enum_query_type query_type); Item_num *neg (); uint decimal_precision() const { return max_length; } }; +class Item_datetime :public Item_int +{ +protected: + MYSQL_TIME ltime; +public: + Item_datetime() :Item_int(0) { unsigned_flag=0; } + int save_in_field(Field *field, bool no_conversions); + longlong val_int(); + double val_real() { return (double)val_int(); } + void set(longlong packed); +}; + + /* decimal (fixed point) constant */ class Item_decimal :public Item_num { @@ -2479,14 +2588,16 @@ private: longlong -longlong_from_string_with_check (CHARSET_INFO *cs, const char *cptr, char *end); +longlong_from_string_with_check(CHARSET_INFO *cs, const char *cptr, + const char *end); double -double_from_string_with_check (CHARSET_INFO *cs, const char *cptr, char *end); +double_from_string_with_check(CHARSET_INFO *cs, const char *cptr, + const char *end); class Item_static_string_func :public Item_string { const char *func_name; - public: +public: Item_static_string_func(const char *name_par, const char *str, uint length, CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE) @@ -2526,10 +2637,11 @@ class Item_return_date_time :public Item_partition_func_safe_string { enum_field_types date_time_field_type; public: - Item_return_date_time(const char *name_arg, enum_field_types field_type_arg) - :Item_partition_func_safe_string(name_arg, 0, &my_charset_bin), + Item_return_date_time(const char *name_arg, uint length_arg, + enum_field_types field_type_arg) + :Item_partition_func_safe_string(name_arg, length_arg, &my_charset_bin), date_time_field_type(field_type_arg) - { } + { decimals= 0; } enum_field_types field_type() const { return date_time_field_type; } }; @@ -2660,11 +2772,12 @@ public: enum Ref_Type { REF, DIRECT_REF, VIEW_REF, OUTER_REF, AGGREGATE_REF }; Field *result_field; /* Save result here */ Item **ref; + bool reference_trough_name; Item_ref(Name_resolution_context *context_arg, const char *db_arg, const char *table_name_arg, const char *field_name_arg) :Item_ident(context_arg, db_arg, table_name_arg, field_name_arg), - result_field(0), ref(0) {} + result_field(0), ref(0), reference_trough_name(1) {} /* This constructor is used in two scenarios: A) *item = NULL @@ -2689,6 +2802,8 @@ public: Item_ref(THD *thd, Item_ref *item) :Item_ident(thd, item), result_field(item->result_field), ref(item->ref) {} enum Type type() const { return REF_ITEM; } + enum Type real_type() const { return ref ? (*ref)->type() : + REF_ITEM; } bool eq(const Item *item, bool binary_cmp) const { Item *it= ((Item *) item)->real_item(); @@ -2720,20 +2835,16 @@ public: Field *get_tmp_table_field() { return result_field ? result_field : (*ref)->get_tmp_table_field(); } Item *get_tmp_table_item(THD *thd); - table_map used_tables() const - { - return depended_from ? OUTER_REF_TABLE_BIT : (*ref)->used_tables(); - } - void update_used_tables() - { - if (!depended_from) - (*ref)->update_used_tables(); - } + table_map used_tables() const; + void update_used_tables(); bool const_item() const { return (*ref)->const_item(); } - table_map not_null_tables() const { return (*ref)->not_null_tables(); } + table_map not_null_tables() const + { + return depended_from ? 0 : (*ref)->not_null_tables(); + } void set_result_field(Field *field) { result_field= field; } bool is_result_field() { return 1; } void save_in_result_field(bool no_conversions) @@ -2752,6 +2863,9 @@ public: else return FALSE; } + Item* transform(Item_transformer, uchar *arg); + Item* compile(Item_analyzer analyzer, uchar **arg_p, + Item_transformer transformer, uchar *arg_t); bool enumerate_field_refs_processor(uchar *arg) { return (*ref)->enumerate_field_refs_processor(arg); } void no_rows_in_result() @@ -2763,10 +2877,6 @@ public: (*ref)->restore_to_before_no_rows_in_result(); } virtual void print(String *str, enum_query_type query_type); - bool result_as_longlong() - { - return (*ref)->result_as_longlong(); - } void cleanup(); Item_field *filed_for_view_update() { return (*ref)->filed_for_view_update(); } @@ -2803,12 +2913,7 @@ public: { return trace_unsupported_by_check_vcol_func_processor("ref"); } - bool get_time(MYSQL_TIME *ltime) - { - DBUG_ASSERT(fixed); - return (*ref)->get_time(ltime); - } - virtual bool basic_const_item() const { return ref && (*ref)->basic_const_item(); } + bool basic_const_item() const { return ref && (*ref)->basic_const_item(); } bool is_outer_field() const { DBUG_ASSERT(fixed); @@ -2852,6 +2957,40 @@ public: virtual Ref_Type ref_type() { return DIRECT_REF; } }; + +/** + This class is the same as Item_direct_ref but created to wrap Item_ident + before fix_fields() call +*/ + +class Item_direct_ref_to_ident :public Item_direct_ref +{ + Item_ident *ident; +public: + Item_direct_ref_to_ident(Item_ident *item) + :Item_direct_ref(item->context, (Item**)&item, item->table_name, item->field_name, + FALSE) + { + ident= item; + ref= (Item**)&ident; + } + + bool fix_fields(THD *thd, Item **it) + { + DBUG_ASSERT(ident->type() == FIELD_ITEM || ident->type() == REF_ITEM); + if ((!ident->fixed && ident->fix_fields(thd, ref)) || + ident->check_cols(1)) + return TRUE; + set_properties(); + return FALSE; + } + + virtual void print(String *str, enum_query_type query_type) + { ident->print(str, query_type); } + +}; + + class Item_cache; class Expression_cache; @@ -2874,8 +3013,11 @@ private: */ Item_cache *expr_value; + List<Item> parameters; + Item *check_cache(); - inline void cache(); + void cache(); + void init_on_demand(); public: Item_cache_wrapper(Item *item_arg); @@ -2883,9 +3025,9 @@ public: const char *func_name() const { return "<expr_cache>"; } enum Type type() const { return EXPR_CACHE_ITEM; } - virtual Item *get_cached_item() { return orig_item; } + enum Type real_type() const { return orig_item->type(); } - bool set_cache(THD *thd, List<Item*> &depends_on); + bool set_cache(THD *thd); bool fix_fields(THD *thd, Item **it); void fix_length_and_dec() {} @@ -2900,7 +3042,6 @@ public: bool val_bool(); bool is_null(); bool get_date(MYSQL_TIME *ltime, uint fuzzydate); - bool get_time(MYSQL_TIME *ltime); bool send(Protocol *protocol, String *buffer); void save_org_in_field(Field *field) { @@ -2940,7 +3081,6 @@ public: } bool enumerate_field_refs_processor(uchar *arg) { return orig_item->enumerate_field_refs_processor(arg); } - bool result_as_longlong() { return orig_item->result_as_longlong(); } Item_field *filed_for_view_update() { return orig_item->filed_for_view_update(); } @@ -2964,6 +3104,9 @@ public: if (result_type() == ROW_RESULT) orig_item->bring_value(); } + virtual bool is_expensive() { return orig_item->is_expensive(); } + bool is_expensive_processor(uchar *arg) + { return orig_item->is_expensive_processor(arg); } bool check_vcol_func_processor(uchar *arg) { return trace_unsupported_by_check_vcol_func_processor("cache"); @@ -2977,17 +3120,21 @@ public: */ class Item_direct_view_ref :public Item_direct_ref { + Item_equal *item_equal; + TABLE_LIST *view; public: Item_direct_view_ref(Name_resolution_context *context_arg, Item **item, - const char *table_name_arg, - const char *field_name_arg) - :Item_direct_ref(context_arg, item, table_name_arg, field_name_arg) {} + const char *table_name_arg, + const char *field_name_arg, + TABLE_LIST *view_arg) + :Item_direct_ref(context_arg, item, table_name_arg, field_name_arg), + item_equal(0), view(view_arg) {} /* Constructor need to process subselect with temporary tables (see Item) */ Item_direct_view_ref(THD *thd, Item_direct_ref *item) - :Item_direct_ref(thd, item) {} + :Item_direct_ref(thd, item), item_equal(0) {} Item_direct_view_ref(TABLE_LIST *view_arg, Item **item, const char *field_name_arg) - :Item_direct_ref(view_arg, item, field_name_arg) + :Item_direct_ref(view_arg, item, field_name_arg), item_equal(0) {} bool fix_fields(THD *, Item **); @@ -2999,6 +3146,25 @@ public: return item; } virtual Ref_Type ref_type() { return VIEW_REF; } + Item_equal *get_item_equal() { return item_equal; } + void set_item_equal(Item_equal *item_eq) { item_equal= item_eq; } + Item_equal *find_item_equal(COND_EQUAL *cond_equal); + bool subst_argument_checker(uchar **arg); + Item *equal_fields_propagator(uchar *arg); + Item *replace_equal_field(uchar *arg); + table_map used_tables() const; + bool walk(Item_processor processor, bool walk_subquery, uchar *arg) + { + return (*ref)->walk(processor, walk_subquery, arg) || + (this->*processor)(arg); + } + bool view_used_tables_processor(uchar *arg) + { + TABLE_LIST *view_arg= (TABLE_LIST *) arg; + if (view_arg == view) + view_arg->view_used_tables|= (*ref)->used_tables(); + return 0; + } }; @@ -3089,15 +3255,7 @@ public: bool val_bool(); bool get_date(MYSQL_TIME *ltime, uint fuzzydate); virtual void print(String *str, enum_query_type query_type); - /* - we add RAND_TABLE_BIT to prevent moving this item from HAVING to WHERE - */ - table_map used_tables() const - { - return (depended_from ? - OUTER_REF_TABLE_BIT : - (*ref)->used_tables() | RAND_TABLE_BIT); - } + table_map used_tables() const; }; /* @@ -3358,6 +3516,17 @@ public: value. */ +/* + Cached_item_XXX objects are not exactly caches. They do the following: + + Each Cached_item_XXX object has + - its source item + - saved value of the source item + - cmp() method that compares the saved value with the current value of the + source item, and if they were not equal saves item's value into the saved + value. +*/ + class Cached_item :public Sql_alloc { public: @@ -3476,7 +3645,8 @@ public: { return Item_field::save_in_field(field_arg, no_conversions); } - /* + enum Type type() const { return INSERT_VALUE_ITEM; } + /* We use RAND_TABLE_BIT to prevent Item_insert_value from being treated as a constant and precalculated before execution */ @@ -3582,6 +3752,13 @@ private: }; +/** + @todo + Implement the is_null() method for this class. Currently calling is_null() + on any Item_cache object resolves to Item::is_null(), which reutns FALSE + for any value. +*/ + class Item_cache: public Item_basic_constant { protected: @@ -3665,24 +3842,12 @@ public: return (value_cached || cache_value()) && !null_value; } - /** - If this item caches a field value, return pointer to underlying field. - - @return Pointer to field, or NULL if this is not a cache for a field value. - */ - Field* field() { return cached_field; } - virtual void store(Item *item); virtual bool cache_value()= 0; bool basic_const_item() const { return test(example && example->basic_const_item());} virtual void clear() { null_value= TRUE; value_cached= FALSE; } - Item_result result_type() const - { - if (!example) - return INT_RESULT; - return Field::result_merge_type(example->field_type()); - } + bool is_null() { return null_value; } }; @@ -3691,20 +3856,41 @@ class Item_cache_int: public Item_cache protected: longlong value; public: - Item_cache_int(): Item_cache(), + Item_cache_int(): Item_cache(MYSQL_TYPE_LONGLONG), value(0) {} Item_cache_int(enum_field_types field_type_arg): Item_cache(field_type_arg), value(0) {} - virtual void store(Item *item){ Item_cache::store(item); } - void store_longlong(Item *item, longlong val_arg); double val_real(); longlong val_int(); String* val_str(String *str); my_decimal *val_decimal(my_decimal *); enum Item_result result_type() const { return INT_RESULT; } - bool result_as_longlong() { return TRUE; } bool cache_value(); + int save_in_field(Field *field, bool no_conversions); +}; + + +class Item_cache_temporal: public Item_cache_int +{ +public: + Item_cache_temporal(enum_field_types field_type_arg); + String* val_str(String *str); + bool cache_value(); + bool get_date(MYSQL_TIME *ltime, uint fuzzydate); + int save_in_field(Field *field, bool no_conversions); + void store_packed(longlong val_arg); + /* + Having a clone_item method tells optimizer that this object + is a constant and need not be optimized further. + Important when storing packed datetime values. + */ + Item *clone_item() + { + Item_cache_temporal *item= new Item_cache_temporal(cached_field_type); + item->store_packed(value); + return item; + } }; @@ -3712,7 +3898,7 @@ class Item_cache_real: public Item_cache { double value; public: - Item_cache_real(): Item_cache(), + Item_cache_real(): Item_cache(MYSQL_TYPE_DOUBLE), value(0) {} double val_real(); @@ -3729,7 +3915,7 @@ class Item_cache_decimal: public Item_cache protected: my_decimal decimal_value; public: - Item_cache_decimal(): Item_cache() {} + Item_cache_decimal(): Item_cache(MYSQL_TYPE_NEWDECIMAL) {} double val_real(); longlong val_int(); @@ -3835,40 +4021,6 @@ public: }; -class Item_cache_datetime: public Item_cache -{ -protected: - String str_value; - longlong int_value; - bool str_value_cached; -public: - Item_cache_datetime(enum_field_types field_type_arg): - Item_cache(field_type_arg), int_value(0), str_value_cached(0) - { - cmp_context= STRING_RESULT; - } - - void store(Item *item, longlong val_arg); - void store(Item *item); - double val_real(); - longlong val_int(); - String* val_str(String *str); - my_decimal *val_decimal(my_decimal *); - enum Item_result result_type() const { return STRING_RESULT; } - bool result_as_longlong() { return TRUE; } - /* - In order to avoid INT <-> STRING conversion of a DATETIME value - two cache_value functions are introduced. One (cache_value) caches STRING - value, another (cache_value_int) - INT value. Thus this cache item - completely relies on the ability of the underlying item to do the - correct conversion. - */ - bool cache_value_int(); - bool cache_value(); - void clear() { Item_cache::clear(); str_value_cached= FALSE; } -}; - - /* Item_type_holder used to store type. name, length of Item for UNIONS & derived tables. @@ -3969,6 +4121,22 @@ public: /** + Item iterator over List_iterator_fast for Items +*/ + +class Item_iterator_list: public Item_iterator +{ + List_iterator<Item> list; +public: + Item_iterator_list(List_iterator<Item> &arg_list): + list(arg_list) {} + void open() { list.rewind(); } + Item *next() { return (list++); } + void close() {} +}; + + +/** Item iterator over Item interface for rows */ |