summaryrefslogtreecommitdiff
path: root/sql/item.h
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item.h')
-rw-r--r--sql/item.h730
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);