summaryrefslogtreecommitdiff
path: root/sql/item.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item.cc')
-rw-r--r--sql/item.cc110
1 files changed, 93 insertions, 17 deletions
diff --git a/sql/item.cc b/sql/item.cc
index 657b8e1edbe..2a0afe27949 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -103,21 +103,33 @@ void Item::print_item_w_name(String *str)
Item_ident::Item_ident(const char *db_name_par,const char *table_name_par,
const char *field_name_par)
- :db_name(db_name_par),table_name(table_name_par),field_name(field_name_par),
+ :changed_during_fix_field(0), db_name(db_name_par),
+ table_name(table_name_par), field_name(field_name_par),
depended_from(0)
{
name = (char*) field_name_par;
}
// Constructor used by Item_field & Item_ref (see Item comment)
-Item_ident::Item_ident(THD *thd, Item_ident *item):
- Item(thd, item),
- db_name(item->db_name),
- table_name(item->table_name),
- field_name(item->field_name),
- depended_from(item->depended_from)
+Item_ident::Item_ident(THD *thd, Item_ident *item)
+ :Item(thd, item),
+ changed_during_fix_field(0),
+ db_name(item->db_name),
+ table_name(item->table_name),
+ field_name(item->field_name),
+ depended_from(item->depended_from)
{}
+void Item_ident::cleanup()
+{
+ Item::cleanup();
+ if (changed_during_fix_field)
+ {
+ *changed_during_fix_field= this;
+ changed_during_fix_field= 0;
+ }
+}
+
bool Item_ident::remove_dependence_processor(byte * arg)
{
DBUG_ENTER("Item_ident::remove_dependence_processor");
@@ -289,11 +301,15 @@ bool DTCollation::aggregate(DTCollation &dt)
return 0;
}
-Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name)
+Item_field::Item_field(Field *f, bool already_fixed)
+ :Item_ident(NullS, f->table_name, f->field_name)
+#ifndef DBUG_OFF
+ ,double_fix(0)
+#endif
{
set_field(f);
collation.set(DERIVATION_IMPLICIT);
- fixed= 1; // This item is not needed in fix_fields
+ fixed= already_fixed;
}
// Constructor need to process subselect with temporary tables (see Item)
@@ -301,6 +317,9 @@ Item_field::Item_field(THD *thd, Item_field *item)
:Item_ident(thd, item),
field(item->field),
result_field(item->result_field)
+#ifndef DBUG_OFF
+ ,double_fix(0)
+#endif
{
collation.set(DERIVATION_IMPLICIT);
}
@@ -341,6 +360,7 @@ const char *Item_ident::full_name() const
/* ARGSUSED */
String *Item_field::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
if ((null_value=field->is_null()))
return 0;
str->set_charset(str_value.charset());
@@ -349,6 +369,7 @@ String *Item_field::val_str(String *str)
double Item_field::val()
{
+ DBUG_ASSERT(fixed == 1);
if ((null_value=field->is_null()))
return 0.0;
return field->val_real();
@@ -356,6 +377,7 @@ double Item_field::val()
longlong Item_field::val_int()
{
+ DBUG_ASSERT(fixed == 1);
if ((null_value=field->is_null()))
return 0;
return field->val_int();
@@ -465,6 +487,7 @@ Item *Item_field::get_tmp_table_item(THD *thd)
String *Item_int::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
str->set(value, &my_charset_bin);
return str;
}
@@ -479,6 +502,7 @@ void Item_int::print(String *str)
String *Item_uint::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
str->set((ulonglong) value, &my_charset_bin);
return str;
}
@@ -494,6 +518,7 @@ void Item_uint::print(String *str)
String *Item_real::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
str->set(value,decimals,&my_charset_bin);
return str;
}
@@ -510,11 +535,25 @@ void Item_string::print(String *str)
bool Item_null::eq(const Item *item, bool binary_cmp) const
{ return item->type() == type(); }
-double Item_null::val() { null_value=1; return 0.0; }
-longlong Item_null::val_int() { null_value=1; return 0; }
+double Item_null::val()
+{
+ // NULL can be used without fix_fields
+ null_value=1;
+ return 0.0;
+}
+longlong Item_null::val_int()
+{
+ // NULL can be used without fix_fields
+ null_value=1;
+ return 0;
+}
/* ARGSUSED */
String *Item_null::val_str(String *str)
-{ null_value=1; return 0;}
+{
+ // NULL can be used without fix_fields
+ null_value=1;
+ return 0;
+}
/*********************** Item_param related ******************************/
@@ -650,6 +689,7 @@ bool Item_param::get_time(TIME *res)
double Item_param::val()
{
+ DBUG_ASSERT(fixed == 1);
int err;
switch (item_result_type) {
case STRING_RESULT:
@@ -665,8 +705,9 @@ double Item_param::val()
longlong Item_param::val_int()
{
- int err;
- switch (item_result_type) {
+ DBUG_ASSERT(fixed == 1);
+ int err;
+ switch (item_result_type) {
case STRING_RESULT:
return my_strntoll(str_value.charset(),
str_value.ptr(),str_value.length(),10,
@@ -681,6 +722,7 @@ longlong Item_param::val_int()
String *Item_param::val_str(String* str)
{
+ DBUG_ASSERT(fixed == 1);
switch (item_result_type) {
case INT_RESULT:
str->set(int_value, &my_charset_bin);
@@ -699,7 +741,8 @@ String *Item_param::val_str(String* str)
*/
String *Item_param::query_val_str(String* str)
-{
+{
+ DBUG_ASSERT(fixed == 1);
switch (item_result_type) {
case INT_RESULT:
case REAL_RESULT:
@@ -772,6 +815,7 @@ void Item_copy_string::copy()
/* ARGSUSED */
String *Item_copy_string::val_str(String *str)
{
+ // Item_copy_string is used without fix_fields call
if (null_value)
return (String*) 0;
return &str_value;
@@ -786,28 +830,41 @@ bool Item::fix_fields(THD *thd,
struct st_table_list *list,
Item ** ref)
{
+
+ // We do not check fields which are fixed during construction
+ DBUG_ASSERT(fixed == 0 || type() == INT_ITEM || type() == CACHE_ITEM ||
+ type() == STRING_ITEM || type() == MYSQL_TYPE_DATETIME);
fixed= 1;
return 0;
}
double Item_ref_null_helper::val()
{
+ DBUG_ASSERT(fixed == 1);
double tmp= (*ref)->val_result();
owner->was_null|= null_value= (*ref)->null_value;
return tmp;
}
+
+
longlong Item_ref_null_helper::val_int()
{
+ DBUG_ASSERT(fixed == 1);
longlong tmp= (*ref)->val_int_result();
owner->was_null|= null_value= (*ref)->null_value;
return tmp;
}
+
+
String* Item_ref_null_helper::val_str(String* s)
{
+ DBUG_ASSERT(fixed == 1);
String* tmp= (*ref)->str_result(s);
owner->was_null|= null_value= (*ref)->null_value;
return tmp;
}
+
+
bool Item_ref_null_helper::get_date(TIME *ltime, uint fuzzydate)
{
return (owner->was_null|= null_value= (*ref)->get_date(ltime, fuzzydate));
@@ -847,6 +904,7 @@ static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
+ DBUG_ASSERT(fixed == 0 || double_fix == 0);
if (!field) // If field is not checked
{
TABLE_LIST *where= 0;
@@ -952,6 +1010,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
ref,
(char *)table_name,
(char *)field_name);
+ register_item_tree_changing(ref);
if (!rf)
return 1;
/*
@@ -1005,6 +1064,11 @@ void Item_field::cleanup()
{
DBUG_ENTER("Item_field::cleanup");
Item_ident::cleanup();
+ /*
+ Even if this object was created by direct link to field in setup_wild()
+ it will be linked correctly next tyme by name of field and table alias.
+ I.e. we can drop 'field'.
+ */
field= result_field= 0;
DBUG_VOID_RETURN;
}
@@ -1323,6 +1387,7 @@ Item_varbinary::Item_varbinary(const char *str, uint str_length)
longlong Item_varbinary::val_int()
{
+ DBUG_ASSERT(fixed == 1);
char *end=(char*) str_value.ptr()+str_value.length(),
*ptr=end-min(str_value.length(),sizeof(longlong));
@@ -1479,6 +1544,7 @@ bool Item_field::send(Protocol *protocol, String *buffer)
bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{
+ DBUG_ASSERT(fixed == 0);
uint counter;
if (!ref)
{
@@ -1582,8 +1648,9 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{
ref= 0; // To prevent "delete *ref;" on ~Item_erf() of this item
Item_field* fld;
- if (!((*reference)= fld= new Item_field(tmp)))
+ if (!((*reference)= fld= new Item_field(tmp, 1)))
return 1;
+ register_item_tree_changing(reference);
mark_as_dependent(thd, last, thd->lex->current_select, fld);
return 0;
}
@@ -1695,8 +1762,12 @@ bool Item_default_value::fix_fields(THD *thd,
struct st_table_list *table_list,
Item **items)
{
+ DBUG_ASSERT(fixed == 0);
if (!arg)
+ {
+ fixed= 1;
return 0;
+ }
if (arg->fix_fields(thd, table_list, &arg))
return 1;
@@ -1717,6 +1788,7 @@ bool Item_default_value::fix_fields(THD *thd,
def_field->move_field(def_field->table->default_values -
def_field->table->record[0]);
set_field(def_field);
+ fixed= 1;
return 0;
}
@@ -1743,6 +1815,7 @@ bool Item_insert_value::fix_fields(THD *thd,
struct st_table_list *table_list,
Item **items)
{
+ DBUG_ASSERT(fixed == 0);
if (arg->fix_fields(thd, table_list, &arg))
return 1;
@@ -1773,6 +1846,7 @@ bool Item_insert_value::fix_fields(THD *thd,
set_field(new Field_null(0, 0, Field::NONE, tmp_field->field_name,
tmp_field->table, &my_charset_bin));
}
+ fixed= 1;
return 0;
}
@@ -1936,7 +2010,8 @@ void Item_cache_str::store(Item *item)
double Item_cache_str::val()
-{
+{
+ DBUG_ASSERT(fixed == 1);
int err;
if (value)
return my_strntod(value->charset(), (char*) value->ptr(),
@@ -1948,6 +2023,7 @@ double Item_cache_str::val()
longlong Item_cache_str::val_int()
{
+ DBUG_ASSERT(fixed == 1);
int err;
if (value)
return my_strntoll(value->charset(), value->ptr(),