diff options
Diffstat (limited to 'sql/item.h')
-rw-r--r-- | sql/item.h | 356 |
1 files changed, 306 insertions, 50 deletions
diff --git a/sql/item.h b/sql/item.h index 237a8f7efac..5a760db23f5 100644 --- a/sql/item.h +++ b/sql/item.h @@ -22,6 +22,7 @@ class Protocol; struct st_table_list; void item_init(void); /* Init item functions */ +class Item_field; /* @@ -110,6 +111,7 @@ public: }; typedef bool (Item::*Item_processor)(byte *arg); +typedef Item* (Item::*Item_transformer) (byte *arg); class Item { Item(const Item &); /* Prevent use of these */ @@ -118,8 +120,9 @@ public: static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); } static void *operator new(size_t size, MEM_ROOT *mem_root) { return (void*) alloc_root(mem_root, (uint) size); } - static void operator delete(void *ptr,size_t size) {} - static void operator delete(void *ptr,size_t size, MEM_ROOT *mem_root) {} + static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); } + static void operator delete(void *ptr,size_t size, MEM_ROOT *mem_root) + { TRASH(ptr, size); } enum Type {FIELD_ITEM, FUNC_ITEM, SUM_FUNC_ITEM, STRING_ITEM, INT_ITEM, REAL_ITEM, NULL_ITEM, VARBIN_ITEM, @@ -127,7 +130,7 @@ public: PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM, FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM, SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER, - PARAM_ITEM}; + PARAM_ITEM, TRIGGER_FIELD_ITEM}; enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE }; @@ -137,8 +140,11 @@ public: */ String str_value; my_string name; /* Name from select */ + /* Original item name (if it was renamed)*/ + my_string orig_name; Item *next; uint32 max_length; + uint name_length; /* Length of name */ uint8 marker,decimals; my_bool maybe_null; /* If item may be null */ my_bool null_value; /* if item is null */ @@ -158,18 +164,16 @@ public: optimisation changes in prepared statements */ Item(THD *thd, Item *item); - virtual ~Item() { name=0; } /*lint -e1509 */ + virtual ~Item() + { + name=0; + } /*lint -e1509 */ void set_name(const char *str,uint length, CHARSET_INFO *cs); + void rename(char *new_name); void init_make_field(Send_field *tmp_field,enum enum_field_types type); - virtual void cleanup() - { - DBUG_ENTER("Item::cleanup"); - DBUG_PRINT("info", ("Type: %d", (int)type())); - fixed=0; - marker= 0; - DBUG_VOID_RETURN; - } + virtual void cleanup(); virtual void make_field(Send_field *field); + Field *make_string_field(TABLE *table); virtual bool fix_fields(THD *, struct st_table_list *, Item **); /* should be used in case where we are sure that we do not need @@ -177,6 +181,7 @@ public: */ 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); virtual void save_org_in_field(Field *field) { (void) save_in_field(field, 1); } @@ -188,7 +193,7 @@ public: virtual enum_field_types field_type() const; virtual enum Type type() const =0; /* valXXX methods must return NULL or 0 or 0.0 if null_value is set. */ - virtual double val()=0; + virtual double val_real()=0; virtual longlong val_int()=0; /* Return string representation of this item object. @@ -219,7 +224,7 @@ public: virtual Field *get_tmp_table_field() { return 0; } virtual Field *tmp_table_field(TABLE *t_arg) { return 0; } virtual const char *full_name() const { return name ? name : "???"; } - virtual double val_result() { return val(); } + virtual double val_result() { return val_real(); } virtual longlong val_int_result() { return val_int(); } virtual String *str_result(String* tmp) { return val_str(tmp); } /* bit map of tables used by item */ @@ -305,9 +310,22 @@ public: return (this->*processor)(arg); } + virtual Item* transform(Item_transformer transformer, byte *arg) + { + return (this->*transformer)(arg); + } + virtual bool remove_dependence_processor(byte * arg) { return 0; } virtual bool remove_fixed(byte * arg) { fixed= 0; return 0; } + virtual bool cleanup_processor(byte *arg); + virtual bool collect_item_field_processor(byte * arg) { return 0; } + virtual Item *equal_fields_propagator(byte * arg) { return this; } + virtual Item *set_no_const_sub(byte *arg) { return this; } + virtual bool replace_equal_field_processor(byte * arg) { return 0; } + virtual Item *this_item() { return this; } /* For SPs mostly. */ + virtual Item *this_const_item() const { return const_cast<Item*>(this); } /* For SPs mostly. */ + // Row emulation virtual uint cols() { return 1; } virtual Item* el(uint i) { return this; } @@ -319,6 +337,7 @@ public: virtual void bring_value() {} Field *tmp_table_field_from_field_type(TABLE *table); + virtual Item_field *filed_for_view_update() { return 0; } virtual Item *neg_transformer(THD *thd) { return NULL; } virtual Item *safe_charset_converter(CHARSET_INFO *tocs); @@ -330,6 +349,104 @@ public: }; +// A local SP variable (incl. parameters), used in runtime +class Item_splocal : public Item +{ +private: + + uint m_offset; + LEX_STRING m_name; + +public: + + Item_splocal(LEX_STRING name, uint offset) + : m_offset(offset), m_name(name) + { + Item::maybe_null= TRUE; + } + + Item *this_item(); + Item *this_const_item() const; + + inline uint get_offset() + { + return m_offset; + } + + // Abstract methods inherited from Item. Just defer the call to + // the item in the frame + enum Type type() const; + + inline double val_real() + { + Item *it= this_item(); + double ret= it->val_real(); + Item::null_value= it->null_value; + return ret; + } + + inline longlong val_int() + { + Item *it= this_item(); + longlong ret= it->val_int(); + Item::null_value= it->null_value; + return ret; + } + + inline String *val_str(String *sp) + { + Item *it= this_item(); + String *ret= it->val_str(sp); + Item::null_value= it->null_value; + return ret; + } + + inline bool is_null() + { + Item *it= this_item(); + bool ret= it->is_null(); + Item::null_value= it->null_value; + return ret; + } + + inline void make_field(Send_field *field) + { + Item *it= this_item(); + + it->set_name(m_name.str, m_name.length, system_charset_info); + it->make_field(field); + } + + inline Item_result result_type() const + { + return this_const_item()->result_type(); + } + + inline bool const_item() const + { + return TRUE; + } + + inline int save_in_field(Field *field, bool no_conversions) + { + return this_item()->save_in_field(field, no_conversions); + } + + void print(String *str) + { + str->reserve(m_name.length+8); + str->append(m_name.str, m_name.length); + str->append('@'); + str->qs_append(m_offset); + } + + inline bool send(Protocol *protocol, String *str) + { + return this_item()->send(protocol, str); + } +}; + + class Item_num: public Item { public: @@ -355,6 +472,7 @@ public: const char *db_name; const char *table_name; const char *field_name; + bool alias_name_used; /* true if item was resolved against alias */ /* Cached value of index for this field in table->field array, used by prep. stmts for speeding up their re-execution. Holds NO_CACHED_FIELD_INDEX @@ -374,19 +492,37 @@ public: const char *full_name() const; void cleanup(); bool remove_dependence_processor(byte * arg); + void print(String *str); + + friend bool insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, + const char *table_name, List_iterator<Item> *it, + bool any_privileges, bool allocate_view_names); }; +class Item_equal; +class COND_EQUAL; class Item_field :public Item_ident { +protected: void set_field(Field *field); public: Field *field,*result_field; + Item_equal *item_equal; + bool no_const_subst; + /* + if any_privileges set to TRUE then here real effective privileges will + be stored + */ + uint have_privileges; + /* field need any privileges (for VIEW creation) */ + bool any_privileges; Item_field(const char *db_par,const char *table_name_par, const char *field_name_par) :Item_ident(db_par,table_name_par,field_name_par), - field(0), result_field(0) + field(0), result_field(0), item_equal(0), no_const_subst(0), + have_privileges(0), any_privileges(0) { collation.set(DERIVATION_IMPLICIT); } /* Constructor needed to process subselect with temporary tables (see Item) @@ -406,7 +542,7 @@ public: Item_field(Field *field); enum Type type() const { return FIELD_ITEM; } bool eq(const Item *item, bool binary_cmp) const; - double val(); + double val_real(); longlong val_int(); String *val_str(String*); double val_result(); @@ -434,8 +570,15 @@ public: bool get_time(TIME *ltime); bool is_null() { return field->is_null(); } Item *get_tmp_table_item(THD *thd); + bool collect_item_field_processor(byte * arg); void cleanup(); + Item_equal *find_item_equal(COND_EQUAL *cond_equal); + Item *equal_fields_propagator(byte *arg); + Item *set_no_const_sub(byte *arg); + bool replace_equal_field_processor(byte *arg); inline uint32 max_disp_length() { return field->max_length(); } + Item_field *filed_for_view_update() { return this; } + Item *safe_charset_converter(CHARSET_INFO *tocs); friend class Item_default_value; friend class Item_insert_value; friend class st_select_lex_unit; @@ -454,7 +597,7 @@ public: } enum Type type() const { return NULL_ITEM; } bool eq(const Item *item, bool binary_cmp) const; - double val(); + double val_real(); longlong val_int(); String *val_str(String *str); int save_in_field(Field *field, bool no_conversions); @@ -543,7 +686,7 @@ public: enum Type type() const { return item_type; } enum_field_types field_type() const { return param_type; } - double val(); + double val_real(); longlong val_int(); String *val_str(String*); bool get_time(TIME *tm); @@ -578,7 +721,7 @@ public: */ virtual table_map used_tables() const { return state != NO_VALUE ? (table_map)0 : PARAM_TABLE_BIT; } - void print(String *str) { str->append('?'); } + void print(String *str); /* parameter never equal to other parameter of other item */ bool eq(const Item *item, bool binary_cmp) const { return 0; } bool is_null() @@ -602,7 +745,7 @@ public: enum Item_result result_type () const { return INT_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; } longlong val_int() { DBUG_ASSERT(fixed == 1); return value; } - double val() { DBUG_ASSERT(fixed == 1); return (double) value; } + double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; } String *val_str(String*); int save_in_field(Field *field, bool no_conversions); bool basic_const_item() const { return 1; } @@ -614,13 +757,24 @@ public: }; +class Item_static_int_func :public Item_int +{ + const char *func_name; +public: + Item_static_int_func(const char *str_arg, longlong i, uint length) + :Item_int(NullS, i, length), func_name(str_arg) + {} + void print(String *str) { str->append(func_name); } +}; + + class Item_uint :public Item_int { public: Item_uint(const char *str_arg, uint length); Item_uint(uint32 i) :Item_int((longlong) i, 10) { unsigned_flag= 1; } - double val() + double val_real() { DBUG_ASSERT(fixed == 1); return ulonglong2double((ulonglong)value); } String *val_str(String*); Item *new_item() { return new Item_uint(name,max_length); } @@ -632,29 +786,24 @@ public: class Item_real :public Item_num { + char *presentation; public: double value; // Item_real() :value(0) {} - Item_real(const char *str_arg, uint length) :value(my_atof(str_arg)) - { - name=(char*) str_arg; - decimals=(uint8) nr_of_decimals(str_arg); - max_length=length; - fixed= 1; - } + Item_real(const char *str_arg, uint length); Item_real(const char *str,double val_arg,uint decimal_par,uint length) :value(val_arg) { - name=(char*) str; + presentation= name=(char*) str; decimals=(uint8) decimal_par; max_length=length; fixed= 1; } - Item_real(double value_par) :value(value_par) { fixed= 1; } + Item_real(double value_par) :presentation(0), value(value_par) { fixed= 1; } int save_in_field(Field *field, bool no_conversions); enum Type type() const { return REAL_ITEM; } enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; } - double val() { DBUG_ASSERT(fixed == 1); return value; } + double val_real() { DBUG_ASSERT(fixed == 1); return value; } longlong val_int() { DBUG_ASSERT(fixed == 1); @@ -666,6 +815,19 @@ public: void cleanup() {} Item *new_item() { return new Item_real(name,value,decimals,max_length); } Item_num *neg() { value= -value; return this; } + void print(String *str); +}; + + +class Item_static_real_func :public Item_real +{ + const char *func_name; +public: + Item_static_real_func(const char *str, double val_arg, uint decimal_par, + uint length) + :Item_real(NullS, val_arg, decimal_par, length), func_name(str) + {} + void print(String *str) { str->append(func_name); } }; @@ -712,7 +874,7 @@ public: fixed= 1; } enum Type type() const { return STRING_ITEM; } - double val() + double val_real() { DBUG_ASSERT(fixed == 1); int err; @@ -733,7 +895,7 @@ public: } int save_in_field(Field *field, bool no_conversions); enum Item_result result_type () const { return STRING_RESULT; } - enum_field_types field_type() const { return MYSQL_TYPE_STRING; } + enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; } bool basic_const_item() const { return 1; } bool eq(const Item *item, bool binary_cmp) const; Item *new_item() @@ -749,6 +911,20 @@ public: void cleanup() {} }; + +class Item_static_string_func :public Item_string +{ + const char *func_name; +public: + Item_static_string_func(const char *name_par, const char *str, uint length, + CHARSET_INFO *cs, + Derivation dv= DERIVATION_COERCIBLE) + :Item_string(NullS, str, length, cs, dv), func_name(name_par) + {} + void print(String *str) { str->append(func_name); } +}; + + /* for show tables */ class Item_datetime :public Item_string @@ -783,24 +959,31 @@ public: }; -class Item_varbinary :public Item +class Item_hex_string: public Item { public: - Item_varbinary(const char *str,uint str_length); + Item_hex_string(): Item() {} + Item_hex_string(const char *str,uint str_length); enum Type type() const { return VARBIN_ITEM; } - double val() - { DBUG_ASSERT(fixed == 1); return (double) Item_varbinary::val_int(); } + double val_real() + { DBUG_ASSERT(fixed == 1); return (double) Item_hex_string::val_int(); } longlong val_int(); bool basic_const_item() const { return 1; } String *val_str(String*) { DBUG_ASSERT(fixed == 1); return &str_value; } int save_in_field(Field *field, bool no_conversions); enum Item_result result_type () const { return STRING_RESULT; } - enum_field_types field_type() const { return MYSQL_TYPE_STRING; } + enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; } // to prevent drop fixed flag (no need parent cleanup call) void cleanup() {} }; +class Item_bin_string: public Item_hex_string +{ +public: + Item_bin_string(const char *str,uint str_length); +}; + class Item_result_field :public Item /* Item with result field */ { public: @@ -834,7 +1017,7 @@ public: Item **ref; Item_ref(const char *db_par, const char *table_name_par, const char *field_name_par) - :Item_ident(db_par, table_name_par, field_name_par), ref(0) {} + :Item_ident(db_par, table_name_par, field_name_par), result_field(0), ref(0) {} /* This constructor is used in two scenarios: A) *item = NULL @@ -850,7 +1033,7 @@ public: with Bar, and if we have a more broader set of problems like this. */ Item_ref(Item **item, const char *table_name_par, const char *field_name_par) - :Item_ident(NullS, table_name_par, field_name_par), ref(item) + :Item_ident(NullS, table_name_par, field_name_par), result_field(0), ref(item) { DBUG_ASSERT(item); if (*item) @@ -858,11 +1041,11 @@ public: } /* Constructor need to process subselect with temporary tables (see Item) */ - Item_ref(THD *thd, Item_ref *item) :Item_ident(thd, item), ref(item->ref) {} + 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; } bool eq(const Item *item, bool binary_cmp) const { return ref && (*ref)->eq(item, binary_cmp); } - double val() + double val_real() { DBUG_ASSERT(fixed); double tmp=(*ref)->val_result(); @@ -894,7 +1077,10 @@ public: DBUG_ASSERT(fixed); return (null_value=(*ref)->get_date_result(ltime,fuzzydate)); } - bool send(Protocol *prot, String *tmp){ return (*ref)->send(prot, tmp); } + double val_result(); + longlong val_int_result(); + String *str_result(String* tmp); + bool send(Protocol *prot, String *tmp); void make_field(Send_field *field) { (*ref)->make_field(field); } bool fix_fields(THD *, struct st_table_list *, Item **); int save_in_field(Field *field, bool no_conversions) @@ -907,13 +1093,17 @@ public: return depended_from ? OUTER_REF_TABLE_BIT : (*ref)->used_tables(); } void set_result_field(Field *field) { result_field= field; } + Field *get_tmp_table_field() { return result_field; } bool is_result_field() { return 1; } void save_in_result_field(bool no_conversions) { (*ref)->save_in_field(result_field, no_conversions); } Item *real_item() { return *ref; } + bool walk(Item_processor processor, byte *arg) + { return (*ref)->walk(processor, arg); } void print(String *str); + void cleanup(); }; @@ -970,7 +1160,7 @@ public: Item_ref_null_helper(Item_in_subselect* master, Item **item, const char *table_name_par, const char *field_name_par): Item_ref(item, table_name_par, field_name_par), owner(master) {} - double val(); + double val_real(); longlong val_int(); String* val_str(String* s); bool get_date(TIME *ltime, uint fuzzydate); @@ -1038,7 +1228,7 @@ public: enum Type type() const { return COPY_STR_ITEM; } enum Item_result result_type () const { return STRING_RESULT; } enum_field_types field_type() const { return cached_field_type; } - double val() + double val_real() { int err; return (null_value ? 0.0 : @@ -1142,6 +1332,19 @@ public: return arg->walk(processor, args) || (this->*processor)(args); } + + /* + This method like the walk method traverses the item tree, but + at the same time it can replace some nodes in the tree + */ + Item *transform(Item_transformer transformer, byte *args) + { + Item *new_item= arg->transform(transformer, args); + if (!new_item) + return 0; + arg= new_item; + return (this->*transformer)(args); + } }; class Item_insert_value : public Item_field @@ -1166,6 +1369,59 @@ public: } }; + +/* + We need this two enums here instead of sql_lex.h because + at least one of them is used by Item_trigger_field interface. + + Time when trigger is invoked (i.e. before or after row actually + inserted/updated/deleted). +*/ +enum trg_action_time_type +{ + TRG_ACTION_BEFORE= 0, TRG_ACTION_AFTER= 1 +}; + +/* + Event on which trigger is invoked. +*/ +enum trg_event_type +{ + TRG_EVENT_INSERT= 0 , TRG_EVENT_UPDATE= 1, TRG_EVENT_DELETE= 2 +}; + +/* + Represents NEW/OLD version of field of row which is + changed/read in trigger. + + Note: For this item actual binding to Field object happens not during + fix_fields() (like for Item_field) but during parsing of trigger + definition, when table is opened, with special setup_field() call. +*/ +class Item_trigger_field : public Item_field +{ +public: + /* Is this item represents row from NEW or OLD row ? */ + enum row_version_type {OLD_ROW, NEW_ROW}; + row_version_type row_version; + /* Next in list of all Item_trigger_field's in trigger */ + Item_trigger_field *next_trg_field; + + Item_trigger_field(row_version_type row_ver_par, + const char *field_name_par): + Item_field((const char *)NULL, (const char *)NULL, field_name_par), + row_version(row_ver_par) + {} + void setup_field(THD *thd, TABLE *table, enum trg_event_type event); + enum Type type() const { return TRIGGER_FIELD_ITEM; } + bool eq(const Item *item, bool binary_cmp) const; + bool fix_fields(THD *, struct st_table_list *, Item **); + void print(String *str); + table_map used_tables() const { return (table_map)0L; } + void cleanup(); +}; + + class Item_cache: public Item { protected: @@ -1202,7 +1458,7 @@ public: Item_cache_int(): Item_cache(), value(0) {} void store(Item *item); - double val() { DBUG_ASSERT(fixed == 1); return (double) value; } + double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; } longlong val_int() { DBUG_ASSERT(fixed == 1); return value; } String* val_str(String *str) { @@ -1220,7 +1476,7 @@ public: Item_cache_real(): Item_cache(), value(0) {} void store(Item *item); - double val() { DBUG_ASSERT(fixed == 1); return value; } + double val_real() { DBUG_ASSERT(fixed == 1); return value; } longlong val_int() { DBUG_ASSERT(fixed == 1); @@ -1242,7 +1498,7 @@ public: Item_cache_str(): Item_cache(), value(0) { } void store(Item *item); - double val(); + double val_real(); longlong val_int(); String* val_str(String *) { DBUG_ASSERT(fixed == 1); return value; } enum Item_result result_type() const { return STRING_RESULT; } @@ -1274,7 +1530,7 @@ public: { illegal_method_call((const char*)"make_field"); }; - double val() + double val_real() { illegal_method_call((const char*)"val"); return 0; @@ -1325,7 +1581,7 @@ public: Item_result result_type () const { return item_type; } enum Type type() const { return TYPE_HOLDER; } - double val(); + double val_real(); longlong val_int(); String *val_str(String*); bool join_types(THD *thd, Item *); |