diff options
Diffstat (limited to 'sql/item.h')
-rw-r--r-- | sql/item.h | 730 |
1 files changed, 597 insertions, 133 deletions
diff --git a/sql/item.h b/sql/item.h index f96f4cd506a..a5648c5889b 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB +/* Copyright (C) 2000-2003 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 @@ -19,22 +19,89 @@ #pragma interface /* gcc class implementation */ #endif +class Protocol; struct st_table_list; -void item_init(void); /* Init item functions */ +void item_init(void); /* Init item functions */ + + +/* + "Declared Type Collation" + A combination of collation and its deriviation. +*/ + +enum Derivation +{ + DERIVATION_COERCIBLE= 3, + DERIVATION_IMPLICIT= 2, + DERIVATION_NONE= 1, + DERIVATION_EXPLICIT= 0 +}; + +class DTCollation { +public: + CHARSET_INFO *collation; + enum Derivation derivation; + + DTCollation() + { + collation= &my_charset_bin; + derivation= DERIVATION_NONE; + } + DTCollation(CHARSET_INFO *collation_arg, Derivation derivation_arg) + { + collation= collation_arg; + derivation= derivation_arg; + } + void set(DTCollation &dt) + { + collation= dt.collation; + derivation= dt.derivation; + } + void set(CHARSET_INFO *collation_arg, Derivation derivation_arg) + { + collation= collation_arg; + derivation= derivation_arg; + } + void set(CHARSET_INFO *collation_arg) + { collation= collation_arg; } + void set(Derivation derivation_arg) + { derivation= derivation_arg; } + bool aggregate(DTCollation &dt); + bool set(DTCollation &dt1, DTCollation &dt2) + { set(dt1); return aggregate(dt2); } + const char *derivation_name() const + { + switch(derivation) + { + case DERIVATION_COERCIBLE: return "COERCIBLE"; + case DERIVATION_IMPLICIT: return "IMPLICIT"; + case DERIVATION_EXPLICIT: return "EXPLICIT"; + case DERIVATION_NONE: return "NONE"; + default: return "UNKNOWN"; + } + } +}; + +typedef bool (Item::*Item_processor)(byte *arg); class Item { - Item(const Item &); /* Prevent use of these */ + Item(const Item &); /* Prevent use of these */ void operator=(Item &); 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) {} /*lint -e715 */ - enum Type {FIELD_ITEM,FUNC_ITEM,SUM_FUNC_ITEM,STRING_ITEM, - INT_ITEM,REAL_ITEM,NULL_ITEM,VARBIN_ITEM, - COPY_STR_ITEM,FIELD_AVG_ITEM, DEFAULT_ITEM, - PROC_ITEM,COND_ITEM,REF_ITEM,FIELD_STD_ITEM, CONST_ITEM}; - enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE }; + enum Type {FIELD_ITEM, FUNC_ITEM, SUM_FUNC_ITEM, STRING_ITEM, + INT_ITEM, REAL_ITEM, NULL_ITEM, VARBIN_ITEM, + COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_VALUE_ITEM, + PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM, + FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM, + SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER}; + enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE }; + String str_value; /* used to store value */ my_string name; /* Name from select */ Item *next; @@ -42,31 +109,43 @@ public: uint8 marker,decimals; my_bool maybe_null; /* If item may be null */ my_bool null_value; /* if item is null */ - my_bool binary; my_bool unsigned_flag; my_bool with_sum_func; - + my_bool fixed; /* If item fixed with fix_fields */ + DTCollation collation; // alloc & destruct is done as start of select using sql_alloc Item(); + /* + Constructor used by Item_field, Item_ref & agregate (sum) functions. + Used for duplicating lists in processing queries with temporary + tables + Also it used for Item_cond_and/Item_cond_or for creating + top AND/OR ctructure of WHERE clause to protect it of + optimisation changes in prepared statements + */ + Item(THD *thd, Item *item); virtual ~Item() { name=0; } /*lint -e1509 */ - void set_name(char* str,uint length=0); + void set_name(const char *str,uint length, CHARSET_INFO *cs); void init_make_field(Send_field *tmp_field,enum enum_field_types type); - virtual bool fix_fields(THD *,struct st_table_list *); - virtual bool save_in_field(Field *field, bool no_conversions); + virtual void cleanup() { fixed=0; } + virtual void make_field(Send_field *field); + virtual bool fix_fields(THD *, struct st_table_list *, Item **); + virtual int save_in_field(Field *field, bool no_conversions); virtual void save_org_in_field(Field *field) { (void) save_in_field(field, 1); } - virtual bool save_safe_in_field(Field *field) + virtual int save_safe_in_field(Field *field) { return save_in_field(field, 1); } - virtual bool send(THD *thd, String *str); + virtual bool send(Protocol *protocol, String *str); virtual bool eq(const Item *, bool binary_cmp) const; virtual Item_result result_type () const { return REAL_RESULT; } + virtual enum_field_types field_type() const; virtual enum Type type() const =0; virtual double val()=0; virtual longlong val_int()=0; virtual String *val_str(String*)=0; - virtual void make_field(Send_field *field)=0; - virtual Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return 0; } + 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 longlong val_int_result() { return val_int(); } @@ -94,34 +173,83 @@ public: virtual cond_result eq_cmp_result() const { return COND_OK; } inline uint float_length(uint decimals_par) const { return decimals != NOT_FIXED_DEC ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;} + /* + Returns true if this is constant (during query execution, i.e. its value + will not change until next fix_fields) and its value is known. + */ virtual bool const_item() const { return used_tables() == 0; } + /* + Returns true if this is constant but its value may be not known yet. + (Can be used for parameters of prep. stmts or of stored procedures.) + */ + virtual bool const_during_execution() const + { return (used_tables() & ~PARAM_TABLE_BIT) == 0; } virtual void print(String *str_arg) { str_arg->append(full_name()); } + void print_item_w_name(String *); virtual void update_used_tables() {} - virtual void split_sum_func(List<Item> &fields) {} - virtual bool get_date(TIME *ltime,bool fuzzydate); + virtual void split_sum_func(Item **ref_pointer_array, List<Item> &fields) {} + virtual bool get_date(TIME *ltime,uint fuzzydate); virtual bool get_time(TIME *ltime); - virtual bool get_date_result(TIME *ltime,bool fuzzydate) + virtual bool get_date_result(TIME *ltime,uint fuzzydate) { return get_date(ltime,fuzzydate); } virtual bool is_null() { return 0; } - virtual unsigned int size_of()= 0; virtual void top_level_item() {} virtual void set_result_field(Field *field) {} virtual bool is_result_field() { return 0; } virtual void save_in_result_field(bool no_conversions) {} virtual void no_rows_in_result() {} + virtual Item *copy_or_same(THD *thd) { return this; } + virtual Item *copy_andor_structure(THD *thd) { return this; } + virtual Item *real_item() { return this; } + virtual Item *get_tmp_table_item(THD *thd) { return copy_or_same(thd); } + + CHARSET_INFO *default_charset() const; + virtual CHARSET_INFO *compare_collation() { return NULL; } + + virtual bool walk(Item_processor processor, byte *arg) + { + return (this->*processor)(arg); + } + + virtual bool remove_dependence_processor(byte * arg) { return 0; } + virtual bool remove_fixed(byte * arg) { fixed= 0; return 0; } + + // Row emulation + virtual uint cols() { return 1; } + virtual Item* el(uint i) { return this; } + virtual Item** addr(uint i) { return 0; } + virtual bool check_cols(uint c); + // It is not row => null inside is impossible + virtual bool null_inside() { return 0; } + // used in row subselects to get value of elements + virtual void bring_value() {} + + Field *tmp_table_field_from_field_type(TABLE *table); + + /* Used in sql_select.cc:eliminate_not_funcs() */ + virtual Item *neg_transformer() { return NULL; } + void delete_self() + { + cleanup(); + delete this; + } }; +class st_select_lex; class Item_ident :public Item { public: const char *db_name; const char *table_name; const char *field_name; + st_select_lex *depended_from; Item_ident(const char *db_name_par,const char *table_name_par, const char *field_name_par); + Item_ident::Item_ident(THD *thd, Item_ident *item); const char *full_name() const; - unsigned int size_of() { return sizeof(*this);} + + bool remove_dependence_processor(byte * arg); }; @@ -135,7 +263,9 @@ public: 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) - {} + { collation.set(DERIVATION_IMPLICIT); } + // Constructor need to process subselect with temporary tables (see Item) + Item_field(THD *thd, Item_field *item); Item_field(Field *field); enum Type type() const { return FIELD_ITEM; } bool eq(const Item *item, bool binary_cmp) const; @@ -145,28 +275,32 @@ public: double val_result(); longlong val_int_result(); String *str_result(String* tmp); - bool send(THD *thd, String *str_arg) - { - return result_field->send(thd,str_arg); - } - void make_field(Send_field *field); - bool fix_fields(THD *,struct st_table_list *); - bool save_in_field(Field *field,bool no_conversions); + bool send(Protocol *protocol, String *str_arg); + bool fix_fields(THD *, struct st_table_list *, Item **); + void make_field(Send_field *tmp_field); + int save_in_field(Field *field,bool no_conversions); void save_org_in_field(Field *field); table_map used_tables() const; enum Item_result result_type () const { return field->result_type(); } - Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return result_field; } - bool get_date(TIME *ltime,bool fuzzydate); - bool get_date_result(TIME *ltime,bool fuzzydate); + enum_field_types field_type() const + { + return field->type(); + } + Field *get_tmp_table_field() { return result_field; } + Field *tmp_table_field(TABLE *t_arg) { return result_field; } + bool get_date(TIME *ltime,uint fuzzydate); + bool get_date_result(TIME *ltime,uint fuzzydate); bool get_time(TIME *ltime); bool is_null() { return field->is_null(); } - unsigned int size_of() { return sizeof(*this);} + Item *get_tmp_table_item(THD *thd); + void cleanup(); + friend class Item_default_value; + friend class Item_insert_value; }; - class Item_null :public Item { public: @@ -177,46 +311,109 @@ public: double val(); longlong val_int(); String *val_str(String *str); - void make_field(Send_field *field); - bool save_in_field(Field *field, bool no_conversions); - bool save_safe_in_field(Field *field); - enum Item_result result_type () const - { return STRING_RESULT; } - bool send(THD *thd, String *str); + int save_in_field(Field *field, bool no_conversions); + int save_safe_in_field(Field *field); + bool send(Protocol *protocol, String *str); + enum Item_result result_type () const { return STRING_RESULT; } + enum_field_types field_type() const { return MYSQL_TYPE_NULL; } + bool fix_fields(THD *thd, struct st_table_list *list, Item **item) + { + bool res= Item::fix_fields(thd, list, item); + max_length=0; + return res; + } bool basic_const_item() const { return 1; } Item *new_item() { return new Item_null(name); } bool is_null() { return 1; } - unsigned int size_of() { return sizeof(*this);} + void print(String *str) { str->append("NULL", 4); } }; +class Item_param :public Item +{ +public: + bool value_is_set; + longlong int_value; + double real_value; + TIME ltime; + enum Item_result item_result_type; + enum Type item_type; + enum enum_field_types buffer_type; + bool item_is_time; + bool long_data_supplied; + uint pos_in_query; + + Item_param(uint position) + { + name= (char*) "?"; + pos_in_query= position; + item_type= STRING_ITEM; + item_result_type = STRING_RESULT; + item_is_time= false; + long_data_supplied= false; + value_is_set= 0; + } + enum Type type() const { return item_type; } + double val(); + longlong val_int(); + String *val_str(String*); + int save_in_field(Field *field, bool no_conversions); + void set_null(); + void set_int(longlong i); + void set_double(double i); + void set_value(const char *str, uint length); + void set_long_str(const char *str, ulong length); + void set_long_binary(const char *str, ulong length); + void set_longdata(const char *str, ulong length); + void set_long_end(); + void set_time(TIME *tm, timestamp_type type); + bool get_time(TIME *tm); + void reset() {} +#ifndef EMBEDDED_LIBRARY + void (*setup_param_func)(Item_param *param, uchar **pos); +#else + void (*setup_param_func)(Item_param *param, uchar **pos, ulong data_len); +#endif + enum Item_result result_type () const + { return item_result_type; } + String *query_val_str(String *str); + enum_field_types field_type() const { return MYSQL_TYPE_STRING; } + Item *new_item() { return new Item_param(pos_in_query); } + /* + If value for parameter was not set we treat it as non-const + so noone will use parameters value in fix_fields still + parameter is constant during execution. + */ + virtual table_map used_tables() const + { return value_is_set ? (table_map)0 : PARAM_TABLE_BIT; } + void print(String *str) { str->append('?'); } +}; class Item_int :public Item { public: const longlong value; Item_int(int32 i,uint length=11) :value((longlong) i) - { max_length=length;} + { max_length=length; fixed= 1; } #ifdef HAVE_LONG_LONG Item_int(longlong i,uint length=21) :value(i) - { max_length=length;} + { max_length=length; fixed= 1;} #endif Item_int(const char *str_arg,longlong i,uint length) :value(i) - { max_length=length; name=(char*) str_arg;} + { max_length=length; name=(char*) str_arg; fixed= 1; } Item_int(const char *str_arg) : value(str_arg[0] == '-' ? strtoll(str_arg,(char**) 0,10) : (longlong) strtoull(str_arg,(char**) 0,10)) - { max_length= (uint) strlen(str_arg); name=(char*) str_arg;} + { max_length= (uint) strlen(str_arg); name=(char*) str_arg; fixed= 1; } enum Type type() const { return INT_ITEM; } - virtual enum Item_result result_type () const { return INT_RESULT; } + enum Item_result result_type () const { return INT_RESULT; } + enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; } longlong val_int() { return value; } double val() { return (double) value; } String *val_str(String*); - void make_field(Send_field *field); - bool save_in_field(Field *field, bool no_conversions); + int save_in_field(Field *field, bool no_conversions); bool basic_const_item() const { return 1; } Item *new_item() { return new Item_int(name,value,max_length); } void print(String *str); - unsigned int size_of() { return sizeof(*this);} }; @@ -226,17 +423,17 @@ public: Item_uint(const char *str_arg, uint length) : Item_int(str_arg, (longlong) strtoull(str_arg,(char**) 0,10), length) {} Item_uint(uint32 i) :Item_int((longlong) i, 10) {} - double val() { return ulonglong2double(value); } + double val() { return ulonglong2double((ulonglong)value); } String *val_str(String*); - void make_field(Send_field *field); Item *new_item() { return new Item_uint(name,max_length); } - bool fix_fields(THD *thd,struct st_table_list *table_list) + int save_in_field(Field *field, bool no_conversions); + bool fix_fields(THD *thd, struct st_table_list *list, Item **item) { + bool res= Item::fix_fields(thd, list, item); unsigned_flag= 1; - return 0; + return res; } void print(String *str); - unsigned int size_of() { return sizeof(*this);} }; @@ -259,15 +456,14 @@ public: max_length=length; } Item_real(double value_par) :value(value_par) {} - bool save_in_field(Field *field, bool no_conversions); + 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() { return value; } longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5));} String *val_str(String*); - void make_field(Send_field *field); bool basic_const_item() const { return 1; } Item *new_item() { return new Item_real(name,value,decimals,max_length); } - unsigned int size_of() { return sizeof(*this);} }; @@ -279,98 +475,109 @@ public: decimals=NOT_FIXED_DEC; max_length=DBL_DIG+8; } - unsigned int size_of() { return sizeof(*this);} }; class Item_string :public Item { public: - Item_string(const char *str,uint length) + Item_string(const char *str,uint length, + CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE) { - str_value.set(str,length); - max_length=length; - name=(char*) str_value.ptr(); + collation.set(cs, dv); + str_value.set_or_copy_aligned(str,length,cs); + /* + We have to have a different max_length than 'length' here to + ensure that we get the right length if we do use the item + to create a new table. In this case max_length must be the maximum + number of chars for a string of this type because we in create_field:: + divide the max_length with mbmaxlen). + */ + max_length= str_value.numchars()*cs->mbmaxlen; + set_name(str, length, cs); decimals=NOT_FIXED_DEC; } - Item_string(const char *name_par,const char *str,uint length) + Item_string(const char *name_par, const char *str, uint length, + CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE) { - str_value.set(str,length); - max_length=length; - name=(char*) name_par; + collation.set(cs, dv); + str_value.set_or_copy_aligned(str,length,cs); + max_length= str_value.numchars()*cs->mbmaxlen; + set_name(name_par,0,cs); decimals=NOT_FIXED_DEC; } - ~Item_string() {} enum Type type() const { return STRING_ITEM; } - double val() { return atof(str_value.ptr()); } - longlong val_int() { return strtoll(str_value.ptr(),(char**) 0,10); } + double val() + { + int err; + return my_strntod(str_value.charset(), (char*) str_value.ptr(), + str_value.length(), (char**) 0, &err); + } + longlong val_int() + { + int err; + return my_strntoll(str_value.charset(), str_value.ptr(), + str_value.length(), 10, (char**) 0, &err); + } String *val_str(String*) { return (String*) &str_value; } - bool save_in_field(Field *field, bool no_conversions); - void make_field(Send_field *field); + 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; } bool basic_const_item() const { return 1; } bool eq(const Item *item, bool binary_cmp) const; - Item *new_item() { return new Item_string(name,str_value.ptr(),max_length); } - String *const_string() { return &str_value; } - inline void append(char *str,uint length) { str_value.append(str,length); } - void print(String *str); - unsigned int size_of() { return sizeof(*this);} -}; - - -/* For INSERT ... VALUES (DEFAULT) */ - -class Item_default :public Item -{ -public: - Item_default() { name= (char*) "DEFAULT"; } - enum Type type() const { return DEFAULT_ITEM; } - void make_field(Send_field *field) {} - bool save_in_field(Field *field, bool no_conversions) + Item *new_item() { - field->set_default(); - return 0; + return new Item_string(name, str_value.ptr(), max_length, &my_charset_bin); } - virtual double val() { return 0.0; } - virtual longlong val_int() { return 0; } - virtual String *val_str(String *str) { return 0; } - bool basic_const_item() const { return 1; } - unsigned int size_of() { return sizeof(*this);} + String *const_string() { return &str_value; } + inline void append(char *str, uint length) { str_value.append(str, length); } + void print(String *str); }; - /* for show tables */ class Item_datetime :public Item_string { public: - Item_datetime(const char *item_name): Item_string(item_name,"",0) + Item_datetime(const char *item_name): Item_string(item_name,"",0, + &my_charset_bin) { max_length=19;} - void make_field(Send_field *field); - unsigned int size_of() { return sizeof(*this);} + enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } }; class Item_empty_string :public Item_string { public: - Item_empty_string(const char *header,uint length) :Item_string("",0) + Item_empty_string(const char *header,uint length) :Item_string("",0, + &my_charset_bin) { name=(char*) header; max_length=length;} void make_field(Send_field *field); - unsigned int size_of() { return sizeof(*this);} }; +class Item_return_int :public Item_int +{ + enum_field_types int_field_type; +public: + Item_return_int(const char *name, uint length, + enum_field_types field_type_arg) + :Item_int(name, 0, length), int_field_type(field_type_arg) + { + unsigned_flag=1; + } + enum_field_types field_type() const { return int_field_type; } +}; + + class Item_varbinary :public Item { public: Item_varbinary(const char *str,uint str_length); - ~Item_varbinary() {} enum Type type() const { return VARBIN_ITEM; } double val() { return (double) Item_varbinary::val_int(); } longlong val_int(); String *val_str(String*) { return &str_value; } - bool save_in_field(Field *field, bool no_conversions); - void make_field(Send_field *field); - enum Item_result result_type () const; - unsigned int size_of() { return sizeof(*this);} + 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; } }; @@ -379,11 +586,15 @@ class Item_result_field :public Item /* Item with result field */ public: Field *result_field; /* Save result here */ Item_result_field() :result_field(0) {} + // Constructor used for Item_sum/Item_cond_and/or (see Item comment) + Item_result_field(THD *thd, Item_result_field *item): + Item(thd, item), result_field(item->result_field) + {} ~Item_result_field() {} /* Required with gcc 2.95 */ - Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return result_field; } + Field *get_tmp_table_field() { return result_field; } + Field *tmp_table_field(TABLE *t_arg) { return result_field; } table_map used_tables() const { return 1; } virtual void fix_length_and_dec()=0; - unsigned int size_of() { return sizeof(*this);} void set_result_field(Field *field) { result_field= field; } bool is_result_field() { return 1; } void save_in_result_field(bool no_conversions) @@ -396,16 +607,25 @@ public: class Item_ref :public Item_ident { public: - Field *result_field; /* Save result here */ + Field *result_field; /* Save result here */ Item **ref; - Item_ref(char *db_par,char *table_name_par,char *field_name_par) - :Item_ident(db_par,table_name_par,field_name_par),ref(0) {} - Item_ref(Item **item, char *table_name_par,char *field_name_par) - :Item_ident(NullS,table_name_par,field_name_par),ref(item) {} + Item **hook_ptr; /* These two to restore */ + Item *orig_item; /* things in 'cleanup()' */ + Item_ref(Item **hook, Item *original,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), hook_ptr(hook), + orig_item(original) {} + Item_ref(Item **item, Item **hook, + const char *table_name_par, const char *field_name_par) + :Item_ident(NullS,table_name_par,field_name_par), + ref(item), hook_ptr(hook), orig_item(hook ? *hook:0) {} + // Constructor need to process subselect with temporary tables (see Item) + Item_ref(THD *thd, Item_ref *item, Item **hook) + :Item_ident(thd, item), ref(item->ref), + hook_ptr(hook), orig_item(hook ? *hook : 0) {} enum Type type() const { return REF_ITEM; } bool eq(const Item *item, bool binary_cmp) const - { return (*ref)->eq(item, binary_cmp); } - ~Item_ref() { if (ref) delete *ref; } + { return ref && (*ref)->eq(item, binary_cmp); } double val() { double tmp=(*ref)->val_result(); @@ -429,27 +649,57 @@ public: (void) (*ref)->val_int_result(); return (*ref)->null_value; } - bool get_date(TIME *ltime,bool fuzzydate) + bool get_date(TIME *ltime,uint fuzzydate) { return (null_value=(*ref)->get_date_result(ltime,fuzzydate)); } - bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); } + bool send(Protocol *prot, String *tmp){ return (*ref)->send(prot, tmp); } void make_field(Send_field *field) { (*ref)->make_field(field); } - bool fix_fields(THD *,struct st_table_list *); - bool save_in_field(Field *field, bool no_conversions) + bool fix_fields(THD *, struct st_table_list *, Item **); + int save_in_field(Field *field, bool no_conversions) { return (*ref)->save_in_field(field, no_conversions); } void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); } enum Item_result result_type () const { return (*ref)->result_type(); } + enum_field_types field_type() const { return (*ref)->field_type(); } table_map used_tables() const { return (*ref)->used_tables(); } - unsigned int size_of() { return sizeof(*this);} - void set_result_field(Field *field) { result_field= field; } + void set_result_field(Field *field) { result_field= 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; } + void print(String *str); + void cleanup(); +}; + +class Item_in_subselect; +class Item_ref_null_helper: public Item_ref +{ +protected: + Item_in_subselect* owner; +public: + Item_ref_null_helper(Item_in_subselect* master, Item **item, + const char *table_name_par, const char *field_name_par): + Item_ref(item, NULL, table_name_par, field_name_par), owner(master) {} + double val(); + longlong val_int(); + String* val_str(String* s); + bool get_date(TIME *ltime, uint fuzzydate); + void print(String *str); }; +class Item_null_helper :public Item_ref_null_helper +{ + Item *store; +public: + Item_null_helper(Item_in_subselect* master, Item *item, + const char *table_name_par, const char *field_name_par) + :Item_ref_null_helper(master, &store, table_name_par, field_name_par), + store(item) + {} + void print(String *str); +}; /* The following class is used to optimize comparing of date columns @@ -463,23 +713,28 @@ class Item_int_with_ref :public Item_int public: Item_int_with_ref(longlong i, Item *ref_arg) :Item_int(i), ref(ref_arg) {} - bool save_in_field(Field *field, bool no_conversions) + int save_in_field(Field *field, bool no_conversions) { return ref->save_in_field(field, no_conversions); } - unsigned int size_of() { return sizeof(*this);} }; +#include "gstream.h" +#include "spatial.h" #include "item_sum.h" #include "item_func.h" +#include "item_row.h" #include "item_cmpfunc.h" #include "item_strfunc.h" +#include "item_geofunc.h" #include "item_timefunc.h" #include "item_uniq.h" +#include "item_subselect.h" class Item_copy_string :public Item { + enum enum_field_types cached_field_type; public: Item *item; Item_copy_string(Item *i) :item(i) @@ -488,21 +743,29 @@ public: decimals=item->decimals; max_length=item->max_length; name=item->name; + cached_field_type= item->field_type(); } - ~Item_copy_string() { delete item; } 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() - { return null_value ? 0.0 : atof(str_value.c_ptr()); } + { + int err; + return (null_value ? 0.0 : + my_strntod(str_value.charset(), (char*) str_value.ptr(), + str_value.length(),NULL,&err)); + } longlong val_int() - { return null_value ? LL(0) : strtoll(str_value.c_ptr(),(char**) 0,10); } + { + int err; + return null_value ? LL(0) : my_strntoll(str_value.charset(),str_value.ptr(),str_value.length(),10, (char**) 0,&err); + } String *val_str(String*); void make_field(Send_field *field) { item->make_field(field); } void copy(); table_map used_tables() const { return (table_map) 1L; } bool const_item() const { return 0; } bool is_null() { return null_value; } - unsigned int size_of() { return sizeof(*this);} }; @@ -513,7 +776,6 @@ public: Item_buff() :null_value(0) {} virtual bool cmp(void)=0; virtual ~Item_buff(); /*line -e1509 */ - unsigned int size_of() { return sizeof(*this);} }; class Item_str_buff :public Item_buff @@ -524,7 +786,6 @@ public: Item_str_buff(Item *arg) :item(arg),value(arg->max_length) {} bool cmp(void); ~Item_str_buff(); // Deallocate String:s - unsigned int size_of() { return sizeof(*this);} }; @@ -535,7 +796,6 @@ class Item_real_buff :public Item_buff public: Item_real_buff(Item *item_par) :item(item_par),value(0.0) {} bool cmp(void); - unsigned int size_of() { return sizeof(*this);} }; class Item_int_buff :public Item_buff @@ -545,7 +805,6 @@ class Item_int_buff :public Item_buff public: Item_int_buff(Item *item_par) :item(item_par),value(0) {} bool cmp(void); - unsigned int size_of() { return sizeof(*this);} }; @@ -562,9 +821,214 @@ public: buff= (char*) sql_calloc(length=field->pack_length()); } bool cmp(void); - unsigned int size_of() { return sizeof(*this);} }; +class Item_default_value : public Item_field +{ +public: + Item *arg; + Item_default_value() : + Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(NULL) {} + Item_default_value(Item *a) : + Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(a) {} + enum Type type() const { return DEFAULT_VALUE_ITEM; } + bool eq(const Item *item, bool binary_cmp) const; + bool fix_fields(THD *, struct st_table_list *, Item **); + void print(String *str); + virtual bool basic_const_item() const { return true; } + int save_in_field(Field *field_arg, bool no_conversions) + { + if (!arg) + { + field_arg->set_default(); + return 0; + } + return Item_field::save_in_field(field_arg, no_conversions); + } + table_map used_tables() const { return (table_map)0L; } + + bool walk(Item_processor processor, byte *args) + { + return arg->walk(processor, args) || + (this->*processor)(args); + } +}; + +class Item_insert_value : public Item_field +{ +public: + Item *arg; + Item_insert_value(Item *a) : + Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(a) {} + bool eq(const Item *item, bool binary_cmp) const; + bool fix_fields(THD *, struct st_table_list *, Item **); + void print(String *str); + virtual bool basic_const_item() const { return true; } + int save_in_field(Field *field_arg, bool no_conversions) + { + return Item_field::save_in_field(field_arg, no_conversions); + } + table_map used_tables() const { return (table_map)0L; } + + bool walk(Item_processor processor, byte *args) + { + return arg->walk(processor, args) || + (this->*processor)(args); + } +}; + +class Item_cache: public Item +{ +protected: + Item *example; + table_map used_table_map; +public: + Item_cache(): example(0), used_table_map(0) {fixed= 1; null_value= 1;} + + void set_used_tables(table_map map) { used_table_map= map; } + + virtual bool allocate(uint i) { return 0; }; + virtual bool setup(Item *item) + { + example= item; + max_length= item->max_length; + decimals= item->decimals; + collation.set(item->collation); + return 0; + }; + virtual void store(Item *)= 0; + enum Type type() const { return CACHE_ITEM; } + static Item_cache* get_cache(Item_result type); + table_map used_tables() const { return used_table_map; } + void print(String *str); +}; + +class Item_cache_int: public Item_cache +{ + longlong value; +public: + Item_cache_int(): Item_cache() {} + + void store(Item *item); + double val() { return (double) value; } + longlong val_int() { return value; } + String* val_str(String *str) { str->set(value, default_charset()); return str; } + enum Item_result result_type() const { return INT_RESULT; } +}; + +class Item_cache_real: public Item_cache +{ + double value; +public: + Item_cache_real(): Item_cache() {} + + void store(Item *item); + double val() { return value; } + longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5)); } + String* val_str(String *str) + { + str->set(value, decimals, default_charset()); + return str; + } + enum Item_result result_type() const { return REAL_RESULT; } +}; + +class Item_cache_str: public Item_cache +{ + char buffer[80]; + String *value, value_buff; +public: + Item_cache_str(): Item_cache() { } + + void store(Item *item); + double val(); + longlong val_int(); + String* val_str(String *) { return value; } + enum Item_result result_type() const { return STRING_RESULT; } + CHARSET_INFO *charset() const { return value->charset(); }; +}; + +class Item_cache_row: public Item_cache +{ + Item_cache **values; + uint item_count; +public: + Item_cache_row(): Item_cache(), values(0), item_count(2) {} + + /* + 'allocate' used only in row transformer, to preallocate space for row + cache. + */ + bool allocate(uint num); + /* + 'setup' is needed only by row => it not called by simple row subselect + (only by IN subselect (in subselect optimizer)) + */ + bool setup(Item *item); + void store(Item *item); + void illegal_method_call(const char *); + void make_field(Send_field *) + { + illegal_method_call((const char*)"make_field"); + }; + double val() + { + illegal_method_call((const char*)"val"); + return 0; + }; + longlong val_int() + { + illegal_method_call((const char*)"val_int"); + return 0; + }; + String *val_str(String *) + { + illegal_method_call((const char*)"val_str"); + return 0; + }; + enum Item_result result_type() const { return ROW_RESULT; } + + uint cols() { return item_count; } + Item* el(uint i) { return values[i]; } + Item** addr(uint i) { return (Item **) (values + i); } + bool check_cols(uint c); + bool null_inside(); + void bring_value(); + void cleanup() + { + Item_cache::cleanup(); + values= 0; + } +}; + + +/* + Used to store type. name, length of Item for UNIONS & derived table +*/ +class Item_type_holder: public Item +{ +protected: + Item_result item_type; + Item_result orig_type; + Field *field_example; +public: + Item_type_holder(THD*, Item*); + + Item_result result_type () const { return item_type; } + enum Type type() const { return TYPE_HOLDER; } + double val(); + longlong val_int(); + String *val_str(String*); + bool join_types(THD *thd, Item *); + Field *example() { return field_example; } + void cleanup() + { + Item::cleanup(); + item_type= orig_type; + } +}; + + extern Item_buff *new_Item_buff(Item *item); extern Item_result item_cmp_type(Item_result a,Item_result b); extern Item *resolve_const_item(Item *item,Item *cmp_item); |