diff options
Diffstat (limited to 'sql/item.cc')
-rw-r--r-- | sql/item.cc | 110 |
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(), |