diff options
Diffstat (limited to 'sql/item.cc')
-rw-r--r-- | sql/item.cc | 232 |
1 files changed, 197 insertions, 35 deletions
diff --git a/sql/item.cc b/sql/item.cc index 8f487872f1b..d253e19e068 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -556,6 +556,18 @@ Item_ident::Item_ident(Name_resolution_context *context_arg, } +Item_ident::Item_ident(TABLE_LIST *view_arg, const char *field_name_arg) + :orig_db_name(NullS), orig_table_name(view_arg->table_name), + orig_field_name(field_name_arg), context(&view_arg->view->select_lex.context), + db_name(NullS), table_name(view_arg->alias), + field_name(field_name_arg), + alias_name_used(FALSE), cached_field_index(NO_CACHED_FIELD_INDEX), + cached_table(NULL), depended_from(NULL) +{ + name = (char*) field_name_arg; +} + + /** Constructor used by Item_field & Item_*_ref (see Item comment) */ @@ -2209,14 +2221,14 @@ String *Item_int::val_str(String *str) { // following assert is redundant, because fixed=1 assigned in constructor DBUG_ASSERT(fixed == 1); - str->set(value, &my_charset_bin); + str->set_int(value, unsigned_flag, &my_charset_bin); return str; } void Item_int::print(String *str, enum_query_type query_type) { // my_charset_bin is good enough for numbers - str_value.set(value, &my_charset_bin); + str_value.set_int(value, unsigned_flag, &my_charset_bin); str->append(str_value); } @@ -4300,17 +4312,33 @@ bool Item_field::fix_fields(THD *thd, Item **reference) It's not an Item_field in the select list so we must make a new Item_ref to point to the Item in the select list and replace the Item_field created by the parser with the new Item_ref. + + NOTE: If we are fixing an alias reference inside ORDER/GROUP BY + item tree, then we use new Item_ref as an intermediate value + to resolve referenced item only. + In this case the new Item_ref item is unused. */ Item_ref *rf= new Item_ref(context, db_name,table_name,field_name); if (!rf) return 1; - thd->change_item_tree(reference, rf); + + bool save_group_fix_field= thd->lex->current_select->group_fix_field; /* - Because Item_ref never substitutes itself with other items - in Item_ref::fix_fields(), we can safely use the original - pointer to it even after fix_fields() - */ - return rf->fix_fields(thd, reference) || rf->check_cols(1); + No need for recursive resolving of aliases. + */ + thd->lex->current_select->group_fix_field= 0; + + bool ret= rf->fix_fields(thd, (Item **) &rf) || rf->check_cols(1); + thd->lex->current_select->group_fix_field= save_group_fix_field; + if (ret) + return TRUE; + + if (save_group_fix_field && alias_name_used) + thd->change_item_tree(reference, *rf->ref); + else + thd->change_item_tree(reference, rf); + + return FALSE; } } } @@ -4459,6 +4487,7 @@ void Item_field::cleanup() I.e. we can drop 'field'. */ field= result_field= 0; + item_equal= NULL; null_value= FALSE; DBUG_VOID_RETURN; } @@ -4899,9 +4928,7 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length) switch (field_type()) { case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_NEWDECIMAL: - field= new Field_new_decimal((uchar*) 0, max_length, null_ptr, 0, - Field::NONE, name, decimals, 0, - unsigned_flag); + field= Field_new_decimal::create_from_item(this); break; case MYSQL_TYPE_TINY: field= new Field_tiny((uchar*) 0, max_length, null_ptr, 0, Field::NONE, @@ -5143,7 +5170,7 @@ int Item::save_in_field(Field *field, bool no_conversions) field->set_notnull(); error=field->store(nr, unsigned_flag); } - return error; + return error ? error : (field->table->in_use->is_error() ? 1 : 0); } @@ -5676,9 +5703,14 @@ void Item_field::print(String *str, enum_query_type query_type) char buff[MAX_FIELD_WIDTH]; String tmp(buff,sizeof(buff),str->charset()); field->val_str(&tmp); - str->append('\''); - str->append(tmp); - str->append('\''); + if (field->is_null()) + str->append("NULL"); + else + { + str->append('\''); + str->append(tmp); + str->append('\''); + } return; } Item_ident::print(str, query_type); @@ -5701,6 +5733,20 @@ Item_ref::Item_ref(Name_resolution_context *context_arg, } +Item_ref::Item_ref(TABLE_LIST *view_arg, Item **item, + const char *field_name_arg, bool alias_name_used_arg) + :Item_ident(view_arg, field_name_arg), + result_field(NULL), ref(item) +{ + alias_name_used= alias_name_used_arg; + /* + This constructor is used to create some internal references over fixed items + */ + if (ref && *ref && (*ref)->fixed) + set_properties(); +} + + /** Resolve the name of a reference to a column reference. @@ -6474,7 +6520,8 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions) { if (!arg) { - if (field_arg->flags & NO_DEFAULT_VALUE_FLAG) + if (field_arg->flags & NO_DEFAULT_VALUE_FLAG && + field_arg->real_type() != MYSQL_TYPE_ENUM) { if (field_arg->reset()) { @@ -6940,9 +6987,24 @@ int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) Item_cache* Item_cache::get_cache(const Item *item) { - switch (item->result_type()) { + return get_cache(item, item->result_type()); +} + + +/** + Get a cache item of given type. + + @param item value to be cached + @param type required type of cache + + @return cache item +*/ + +Item_cache* Item_cache::get_cache(const Item *item, const Item_result type) +{ + switch (type) { case INT_RESULT: - return new Item_cache_int(); + return new Item_cache_int(item->field_type()); case REAL_RESULT: return new Item_cache_real(); case DECIMAL_RESULT: @@ -6958,6 +7020,13 @@ Item_cache* Item_cache::get_cache(const Item *item) } } +void Item_cache::store(Item *item) +{ + example= item; + if (!item) + null_value= TRUE; + value_cached= FALSE; +} void Item_cache::print(String *str, enum_query_type query_type) { @@ -6969,17 +7038,22 @@ void Item_cache::print(String *str, enum_query_type query_type) str->append(')'); } - -void Item_cache_int::store(Item *item) +bool Item_cache_int::cache_value() { - value= item->val_int_result(); - null_value= item->null_value; - unsigned_flag= item->unsigned_flag; + if (!example) + return FALSE; + value_cached= TRUE; + value= example->val_int_result(); + null_value= example->null_value; + unsigned_flag= example->unsigned_flag; + return TRUE; } void Item_cache_int::store(Item *item, longlong val_arg) { + /* An explicit values is given, save it. */ + value_cached= TRUE; value= val_arg; null_value= item->null_value; unsigned_flag= item->unsigned_flag; @@ -6989,6 +7063,8 @@ void Item_cache_int::store(Item *item, longlong val_arg) String *Item_cache_int::val_str(String *str) { DBUG_ASSERT(fixed == 1); + if (!value_cached && !cache_value()) + return NULL; str->set(value, default_charset()); return str; } @@ -6997,21 +7073,52 @@ String *Item_cache_int::val_str(String *str) my_decimal *Item_cache_int::val_decimal(my_decimal *decimal_val) { DBUG_ASSERT(fixed == 1); + if (!value_cached && !cache_value()) + return NULL; int2my_decimal(E_DEC_FATAL_ERROR, value, unsigned_flag, decimal_val); return decimal_val; } +double Item_cache_int::val_real() +{ + DBUG_ASSERT(fixed == 1); + if (!value_cached && !cache_value()) + return 0.0; + return (double) value; +} + +longlong Item_cache_int::val_int() +{ + DBUG_ASSERT(fixed == 1); + if (!value_cached && !cache_value()) + return 0; + return value; +} -void Item_cache_real::store(Item *item) +bool Item_cache_real::cache_value() { - value= item->val_result(); - null_value= item->null_value; + if (!example) + return FALSE; + value_cached= TRUE; + value= example->val_result(); + null_value= example->null_value; + return TRUE; } +double Item_cache_real::val_real() +{ + DBUG_ASSERT(fixed == 1); + if (!value_cached && !cache_value()) + return 0.0; + return value; +} + longlong Item_cache_real::val_int() { DBUG_ASSERT(fixed == 1); + if (!value_cached && !cache_value()) + return 0; return (longlong) rint(value); } @@ -7019,6 +7126,8 @@ longlong Item_cache_real::val_int() String* Item_cache_real::val_str(String *str) { DBUG_ASSERT(fixed == 1); + if (!value_cached && !cache_value()) + return NULL; str->set_real(value, decimals, default_charset()); return str; } @@ -7027,22 +7136,30 @@ String* Item_cache_real::val_str(String *str) my_decimal *Item_cache_real::val_decimal(my_decimal *decimal_val) { DBUG_ASSERT(fixed == 1); + if (!value_cached && !cache_value()) + return NULL; double2my_decimal(E_DEC_FATAL_ERROR, value, decimal_val); return decimal_val; } -void Item_cache_decimal::store(Item *item) +bool Item_cache_decimal::cache_value() { - my_decimal *val= item->val_decimal_result(&decimal_value); - if (!(null_value= item->null_value) && val != &decimal_value) + if (!example) + return FALSE; + value_cached= TRUE; + my_decimal *val= example->val_decimal_result(&decimal_value); + if (!(null_value= example->null_value) && val != &decimal_value) my_decimal2decimal(val, &decimal_value); + return TRUE; } double Item_cache_decimal::val_real() { DBUG_ASSERT(fixed); double res; + if (!value_cached && !cache_value()) + return 0.0; my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &res); return res; } @@ -7051,6 +7168,8 @@ longlong Item_cache_decimal::val_int() { DBUG_ASSERT(fixed); longlong res; + if (!value_cached && !cache_value()) + return 0; my_decimal2int(E_DEC_FATAL_ERROR, &decimal_value, unsigned_flag, &res); return res; } @@ -7058,6 +7177,8 @@ longlong Item_cache_decimal::val_int() String* Item_cache_decimal::val_str(String *str) { DBUG_ASSERT(fixed); + if (!value_cached && !cache_value()) + return NULL; my_decimal_round(E_DEC_FATAL_ERROR, &decimal_value, decimals, FALSE, &decimal_value); my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value, 0, 0, 0, str); @@ -7067,15 +7188,20 @@ String* Item_cache_decimal::val_str(String *str) my_decimal *Item_cache_decimal::val_decimal(my_decimal *val) { DBUG_ASSERT(fixed); + if (!value_cached && !cache_value()) + return NULL; return &decimal_value; } -void Item_cache_str::store(Item *item) +bool Item_cache_str::cache_value() { - value_buff.set(buffer, sizeof(buffer), item->collation.collation); - value= item->str_result(&value_buff); - if ((null_value= item->null_value)) + if (!example) + return FALSE; + value_cached= TRUE; + value_buff.set(buffer, sizeof(buffer), example->collation.collation); + value= example->str_result(&value_buff); + if ((null_value= example->null_value)) value= 0; else if (value != &value_buff) { @@ -7090,6 +7216,7 @@ void Item_cache_str::store(Item *item) value_buff.copy(*value); value= &value_buff; } + return TRUE; } double Item_cache_str::val_real() @@ -7097,6 +7224,8 @@ double Item_cache_str::val_real() DBUG_ASSERT(fixed == 1); int err_not_used; char *end_not_used; + if (!value_cached && !cache_value()) + return 0.0; if (value) return my_strntod(value->charset(), (char*) value->ptr(), value->length(), &end_not_used, &err_not_used); @@ -7108,6 +7237,8 @@ longlong Item_cache_str::val_int() { DBUG_ASSERT(fixed == 1); int err; + if (!value_cached && !cache_value()) + return 0; if (value) return my_strntoll(value->charset(), value->ptr(), value->length(), 10, (char**) 0, &err); @@ -7115,9 +7246,21 @@ longlong Item_cache_str::val_int() return (longlong)0; } + +String* Item_cache_str::val_str(String *str) +{ + DBUG_ASSERT(fixed == 1); + if (!value_cached && !cache_value()) + return 0; + return value; +} + + my_decimal *Item_cache_str::val_decimal(my_decimal *decimal_val) { DBUG_ASSERT(fixed == 1); + if (!value_cached && !cache_value()) + return NULL; if (value) string2my_decimal(E_DEC_FATAL_ERROR, value, decimal_val); else @@ -7128,6 +7271,8 @@ my_decimal *Item_cache_str::val_decimal(my_decimal *decimal_val) int Item_cache_str::save_in_field(Field *field, bool no_conversions) { + if (!value_cached && !cache_value()) + return 0; int res= Item_cache::save_in_field(field, no_conversions); return (is_varbinary && field->type() == MYSQL_TYPE_STRING && value->length() < field->field_length) ? 1 : res; @@ -7162,13 +7307,30 @@ bool Item_cache_row::setup(Item * item) void Item_cache_row::store(Item * item) { + example= item; + if (!item) + { + null_value= TRUE; + return; + } + for (uint i= 0; i < item_count; i++) + values[i]->store(item->element_index(i)); +} + + +bool Item_cache_row::cache_value() +{ + if (!example) + return FALSE; + value_cached= TRUE; null_value= 0; - item->bring_value(); + example->bring_value(); for (uint i= 0; i < item_count; i++) { - values[i]->store(item->element_index(i)); + values[i]->cache_value(); null_value|= values[i]->null_value; } + return TRUE; } |