From 891e8d076c839993fabed540a1c7b82a343739d5 Mon Sep 17 00:00:00 2001 From: "jimw@mysql.com" <> Date: Tue, 1 Feb 2005 15:08:31 -0800 Subject: Fix value of YEAR field when set from a non-numeric string. (Bug #6067) --- sql/field.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/field.cc b/sql/field.cc index 7357bc06f11..a2b749257df 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -3511,9 +3511,17 @@ void Field_time::sql_type(String &res) const int Field_year::store(const char *from, uint len,CHARSET_INFO *cs) { - int not_used; // We can ignore result from str2int + int err; char *end; - long nr= my_strntol(cs, from, len, 10, &end, ¬_used); + long nr= my_strntol(cs, from, len, 10, &end, &err); + + if (err) + { + if (table->in_use->count_cuted_fields) + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1); + *ptr= 0; + return 0; + } if (nr < 0 || nr >= 100 && nr <= 1900 || nr > 2155) { -- cgit v1.2.1 From 34915f7a91b7ba56f5bbb4ac6d6301f847a7d48b Mon Sep 17 00:00:00 2001 From: "gluh@gluh.mysql.r18.ru" <> Date: Fri, 4 Feb 2005 15:31:36 +0300 Subject: A fix: bug#6931: Date Type column problem when using UNION-Table bug#7833: Wrong datatype of aggregate column is returned --- sql/field.cc | 35 ++++++++++++++++++++++++++++++ sql/field.h | 1 + sql/item.cc | 65 +++++++++++++++++++++++++++++++++++++++++++++----------- sql/item.h | 4 ++-- sql/sql_union.cc | 14 ++++++++++-- 5 files changed, 103 insertions(+), 16 deletions(-) (limited to 'sql') diff --git a/sql/field.cc b/sql/field.cc index 7357bc06f11..9965cb792be 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -245,6 +245,7 @@ static Field::field_cast_enum field_cast_date[]= Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; static Field::field_cast_enum field_cast_newdate[]= {Field::FIELD_CAST_NEWDATE, + Field::FIELD_CAST_DATE, Field::FIELD_CAST_DATETIME, Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; @@ -6024,6 +6025,40 @@ Field *make_field(char *ptr, uint32 field_length, } +/* + Check if field_type is appropriate field type + to create field for tmp table using + item->tmp_table_field() method + + SYNOPSIS + field_types_to_be_kept() + field_type - field type + + NOTE + it is used in function get_holder_example_field() + from item.cc + + RETURN + 1 - can use item->tmp_table_field() method + 0 - can not use item->tmp_table_field() method + +*/ + +bool field_types_to_be_kept(enum_field_types field_type) +{ + switch (field_type) + { + case FIELD_TYPE_DATE: + case FIELD_TYPE_NEWDATE: + case FIELD_TYPE_TIME: + case FIELD_TYPE_DATETIME: + return 1; + default: + return 0; + } +} + + /* Create a field suitable for create of table */ create_field::create_field(Field *old_field,Field *orig_field) diff --git a/sql/field.h b/sql/field.h index 27a01a69273..fd0f2f9c2f1 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1265,6 +1265,7 @@ int set_field_to_null(Field *field); int set_field_to_null_with_conversions(Field *field, bool no_conversions); bool test_if_int(const char *str, int length, const char *int_end, CHARSET_INFO *cs); +bool field_types_to_be_kept(enum_field_types field_type); /* The following are for the interface with the .frm file diff --git a/sql/item.cc b/sql/item.cc index ab29c147dfb..d61d628e8fa 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2639,7 +2639,53 @@ void Item_cache_row::bring_value() } -Item_type_holder::Item_type_holder(THD *thd, Item *item) +/* + Returns field for temporary table dependind on item type + + SYNOPSIS + get_holder_example_field() + thd - thread handler + item - pointer to item + table - empty table object + + NOTE + It is possible to return field for Item_func + items only if field type of this item is + date or time or datetime type. + also see function field_types_to_be_kept() from + field.cc + + RETURN + # - field + 0 - no field +*/ + +Field *get_holder_example_field(THD *thd, Item *item, TABLE *table) +{ + DBUG_ASSERT(table); + + Item_func *tmp_item= 0; + if (item->type() == Item::FIELD_ITEM) + return (((Item_field*) item)->field); + if (item->type() == Item::FUNC_ITEM) + tmp_item= (Item_func *) item; + else if (item->type() == Item::SUM_FUNC_ITEM) + { + Item_sum *item_sum= (Item_sum *) item; + if (item_sum->keep_field_type()) + { + if (item_sum->args[0]->type() == Item::FIELD_ITEM) + return (((Item_field*) item_sum->args[0])->field); + if (item_sum->args[0]->type() == Item::FUNC_ITEM) + tmp_item= (Item_func *) item_sum->args[0]; + } + } + return (tmp_item && field_types_to_be_kept(tmp_item->field_type()) ? + tmp_item->tmp_table_field(table) : 0); +} + + +Item_type_holder::Item_type_holder(THD *thd, Item *item, TABLE *table) :Item(thd, item), item_type(item->result_type()), orig_type(item_type) { @@ -2649,10 +2695,7 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item) It is safe assign pointer on field, because it will be used just after all JOIN::prepare calls and before any SELECT execution */ - if (item->type() == Item::FIELD_ITEM) - field_example= ((Item_field*) item)->field; - else - field_example= 0; + field_example= get_holder_example_field(thd, item, table); max_length= real_length(item); maybe_null= item->maybe_null; collation.set(item->collation); @@ -2692,25 +2735,23 @@ inline bool is_attr_compatible(Item *from, Item *to) (to->maybe_null || !from->maybe_null) && (to->result_type() != STRING_RESULT || from->result_type() != STRING_RESULT || - my_charset_same(from->collation.collation, - to->collation.collation))); + (from->collation.collation == to->collation.collation))); } -bool Item_type_holder::join_types(THD *thd, Item *item) +bool Item_type_holder::join_types(THD *thd, Item *item, TABLE *table) { uint32 new_length= real_length(item); bool use_new_field= 0, use_expression_type= 0; Item_result new_result_type= type_convertor[item_type][item->result_type()]; - bool item_is_a_field= item->type() == Item::FIELD_ITEM; - + Field *field= get_holder_example_field(thd, item, table); + bool item_is_a_field= field; /* Check if both items point to fields: in this case we can adjust column types of result table in the union smartly. */ if (field_example && item_is_a_field) { - Field *field= ((Item_field *)item)->field; /* Can 'field_example' field store data of the column? */ if ((use_new_field= (!field->field_cast_compatible(field_example->field_cast_type()) || @@ -2751,7 +2792,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item) It is safe to assign a pointer to field here, because it will be used before any table is closed. */ - field_example= ((Item_field*) item)->field; + field_example= field; } old_cs= collation.collation->name; diff --git a/sql/item.h b/sql/item.h index 237a8f7efac..e0de7452eec 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1321,14 +1321,14 @@ protected: Item_result orig_type; Field *field_example; public: - Item_type_holder(THD*, Item*); + Item_type_holder(THD*, Item*, TABLE *); 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 *); + bool join_types(THD *thd, Item *, TABLE *); Field *example() { return field_example; } static uint32 real_length(Item *item); void cleanup() diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 027a21db7ac..882316d57d7 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -148,6 +148,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, SELECT_LEX *sl, *first_select; select_result *tmp_result; bool is_union; + TABLE *empty_table= 0; DBUG_ENTER("st_select_lex_unit::prepare"); describe= test(additional_options & SELECT_DESCRIBE); @@ -239,13 +240,21 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, goto err; if (sl == first_select) { + /* + We need to create an empty table object. It is used + to create tmp_table fields in Item_type_holder. + The main reason of this is that we can't create + field object without table. + */ + DBUG_ASSERT(!empty_table); + empty_table= (TABLE*) thd->calloc(sizeof(TABLE)); types.empty(); List_iterator_fast it(sl->item_list); Item *item_tmp; while ((item_tmp= it++)) { /* Error's in 'new' will be detected after loop */ - types.push_back(new Item_type_holder(thd_arg, item_tmp)); + types.push_back(new Item_type_holder(thd_arg, item_tmp, empty_table)); } if (thd_arg->is_fatal_error) @@ -264,7 +273,8 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, Item *type, *item_tmp; while ((type= tp++, item_tmp= it++)) { - if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp)) + if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp, + empty_table)) DBUG_RETURN(-1); } } -- cgit v1.2.1 From cc1ee6475f9a15415c81867f239f71a0bb1c969c Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Fri, 4 Feb 2005 15:24:06 +0100 Subject: indexless boolean fulltext search was depending on default_charset_info - Bug#8159 ftbw->off wasn't cleared on reinit - Bug#8234 --- sql/ha_myisam.h | 8 ++++++-- sql/handler.h | 3 +-- sql/item_func.cc | 8 +++----- 3 files changed, 10 insertions(+), 9 deletions(-) (limited to 'sql') diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h index 972d6b18e19..1e6cf2f4ada 100644 --- a/sql/ha_myisam.h +++ b/sql/ha_myisam.h @@ -88,8 +88,12 @@ class ha_myisam: public handler ft_handler->please->reinit_search(ft_handler); return 0; } - FT_INFO *ft_init_ext(uint flags, uint inx,const byte *key, uint keylen) - { return ft_init_search(flags,file,inx,(byte*) key,keylen, table->record[0]); } + FT_INFO *ft_init_ext(uint flags, uint inx,String *key) + { + return ft_init_search(flags,file,inx, + (byte *)key->ptr(), key->length(), key->charset(), + table->record[0]); + } int ft_read(byte *buf); int rnd_init(bool scan); int rnd_next(byte *buf); diff --git a/sql/handler.h b/sql/handler.h index 245defe61e0..0426312f404 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -373,8 +373,7 @@ public: int compare_key(key_range *range); virtual int ft_init() { return HA_ERR_WRONG_COMMAND; } void ft_end() { ft_handler=NULL; } - virtual FT_INFO *ft_init_ext(uint flags,uint inx,const byte *key, - uint keylen) + virtual FT_INFO *ft_init_ext(uint flags, uint inx,String *key) { return NULL; } virtual int ft_read(byte *buf) { return HA_ERR_WRONG_COMMAND; } virtual int rnd_next(byte *buf)=0; diff --git a/sql/item_func.cc b/sql/item_func.cc index bff49541252..85cd1c693b7 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3047,9 +3047,7 @@ void Item_func_match::init_search(bool no_order) if (join_key && !no_order) flags|=FT_SORTED; - ft_handler=table->file->ft_init_ext(flags, key, - (byte*) ft_tmp->ptr(), - ft_tmp->length()); + ft_handler=table->file->ft_init_ext(flags, key, ft_tmp); if (join_key) table->file->ft_handler=ft_handler; @@ -3091,12 +3089,12 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) } /* Check that all columns come from the same table. - We've already checked that columns in MATCH are fields so + We've already checked that columns in MATCH are fields so PARAM_TABLE_BIT can only appear from AGAINST argument. */ if ((used_tables_cache & ~PARAM_TABLE_BIT) != item->used_tables()) key=NO_SUCH_KEY; - + if (key == NO_SUCH_KEY && !(flags & FT_BOOL)) { my_error(ER_WRONG_ARGUMENTS,MYF(0),"MATCH"); -- cgit v1.2.1