diff options
author | unknown <igor@rurik.mysql.com> | 2003-12-01 18:47:19 -0800 |
---|---|---|
committer | unknown <igor@rurik.mysql.com> | 2003-12-01 18:47:19 -0800 |
commit | 7b853c645db94e179be5a4086feb5ccb4088280e (patch) | |
tree | 31494d26df6b929335d01f1c5d1433017038d9f5 /sql/item.cc | |
parent | f6697593d252efc2d4a41897fb503e1598af97ad (diff) | |
parent | 7daa6cdc1358b0abcf24a28ed6eda57ba3533d23 (diff) | |
download | mariadb-git-7b853c645db94e179be5a4086feb5ccb4088280e.tar.gz |
Merge
mysql-test/t/range.test:
Auto merged
sql/item.cc:
Auto merged
sql/item.h:
Auto merged
sql/item_cmpfunc.cc:
Auto merged
sql/item_cmpfunc.h:
Auto merged
sql/item_func.cc:
Auto merged
sql/opt_range.cc:
Auto merged
sql/opt_sum.cc:
Auto merged
sql/sql_list.h:
Auto merged
sql/sql_select.h:
Auto merged
Diffstat (limited to 'sql/item.cc')
-rw-r--r-- | sql/item.cc | 167 |
1 files changed, 160 insertions, 7 deletions
diff --git a/sql/item.cc b/sql/item.cc index 5091ea87bee..5f9a9d4a657 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -333,7 +333,7 @@ void Item_field::set_field(Field *field_par) const char *Item_ident::full_name() const { char *tmp; - if (!table_name) + if (!table_name || !field_name) return field_name ? field_name : name ? name : "tmp_field"; if (db_name && db_name[0]) { @@ -533,7 +533,7 @@ String *Item_null::val_str(String *str) void Item_param::set_null() { DBUG_ENTER("Item_param::set_null"); - maybe_null= null_value= 1; + maybe_null= null_value= value_is_set= 1; DBUG_VOID_RETURN; } @@ -542,6 +542,7 @@ void Item_param::set_int(longlong i) DBUG_ENTER("Item_param::set_int"); int_value= (longlong)i; item_type= INT_ITEM; + value_is_set= 1; DBUG_PRINT("info", ("integer: %lld", int_value)); DBUG_VOID_RETURN; } @@ -551,6 +552,7 @@ void Item_param::set_double(double value) DBUG_ENTER("Item_param::set_double"); real_value=value; item_type= REAL_ITEM; + value_is_set= 1; DBUG_PRINT("info", ("double: %lg", real_value)); DBUG_VOID_RETURN; } @@ -561,6 +563,7 @@ void Item_param::set_value(const char *str, uint length) DBUG_ENTER("Item_param::set_value"); str_value.copy(str,length,default_charset()); item_type= STRING_ITEM; + value_is_set= 1; DBUG_PRINT("info", ("string: %s", str_value.ptr())); DBUG_VOID_RETURN; } @@ -582,6 +585,7 @@ void Item_param::set_time(TIME *tm, timestamp_type type) item_is_time= true; item_type= STRING_ITEM; + value_is_set= 1; } @@ -589,6 +593,7 @@ void Item_param::set_longdata(const char *str, ulong length) { str_value.append(str,length); long_data_supplied= 1; + value_is_set= 1; } @@ -1254,6 +1259,15 @@ int Item_string::save_in_field(Field *field, bool no_conversions) -1 : 0; } +int Item_uint::save_in_field(Field *field, bool no_conversions) +{ + /* + TODO: To be fixed when wen have a + field->store(longlong, unsigned_flag) method + */ + return Item_int::save_in_field(field, no_conversions); +} + int Item_int::save_in_field(Field *field, bool no_conversions) { @@ -1411,7 +1425,7 @@ bool Item::send(Protocol *protocol, String *buffer) case MYSQL_TYPE_FLOAT: { float nr; - nr= val(); + nr= (float) val(); if (!null_value) result= protocol->store(nr, decimals, buffer); break; @@ -1717,7 +1731,9 @@ bool Item_insert_value::eq(const Item *item, bool binary_cmp) const } -bool Item_insert_value::fix_fields(THD *thd, struct st_table_list *table_list, Item **items) +bool Item_insert_value::fix_fields(THD *thd, + struct st_table_list *table_list, + Item **items) { bool res= arg->fix_fields(thd, table_list, items); if (res) @@ -1748,10 +1764,10 @@ bool Item_insert_value::fix_fields(THD *thd, struct st_table_list *table_list, I } else { - Field *field=field_arg->field; + Field *tmp_field= field_arg->field; /* charset doesn't matter here, it's to avoid sigsegv only */ - set_field(new Field_null(0,0,Field::NONE,field->field_name,field->table, - &my_charset_bin)); + set_field(new Field_null(0, 0, Field::NONE, tmp_field->field_name, + tmp_field->table, &my_charset_bin)); } return 0; } @@ -1931,6 +1947,8 @@ void Item_cache_str::store(Item *item) } collation.set(item->collation); } + + double Item_cache_str::val() { int err; @@ -1940,6 +1958,8 @@ double Item_cache_str::val() else return (double)0; } + + longlong Item_cache_str::val_int() { int err; @@ -1950,6 +1970,7 @@ longlong Item_cache_str::val_int() return (longlong)0; } + bool Item_cache_row::allocate(uint num) { item_count= num; @@ -1958,6 +1979,7 @@ bool Item_cache_row::allocate(uint num) (Item_cache **) thd->calloc(sizeof(Item_cache *)*item_count))); } + bool Item_cache_row::setup(Item * item) { example= item; @@ -1974,6 +1996,7 @@ bool Item_cache_row::setup(Item * item) return 0; } + void Item_cache_row::store(Item * item) { null_value= 0; @@ -1985,6 +2008,7 @@ void Item_cache_row::store(Item * item) } } + void Item_cache_row::illegal_method_call(const char *method) { DBUG_ENTER("Item_cache_row::illegal_method_call"); @@ -1994,6 +2018,7 @@ void Item_cache_row::illegal_method_call(const char *method) DBUG_VOID_RETURN; } + bool Item_cache_row::check_cols(uint c) { if (c != item_count) @@ -2004,6 +2029,7 @@ bool Item_cache_row::check_cols(uint c) return 0; } + bool Item_cache_row::null_inside() { for (uint i= 0; i < item_count; i++) @@ -2023,6 +2049,7 @@ bool Item_cache_row::null_inside() return 0; } + void Item_cache_row::bring_value() { for (uint i= 0; i < item_count; i++) @@ -2030,6 +2057,132 @@ void Item_cache_row::bring_value() return; } + +Item_type_holder::Item_type_holder(THD *thd, Item *item) + :Item(thd, *item), item_type(item->result_type()) +{ + DBUG_ASSERT(item->fixed); + + /* + 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; + collation.set(item->collation); +} + + +/* + STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT + + ROW_RESULT should never appear in Item_type_holder::join_types, + but it is included in following table just to make table full + (there DBUG_ASSERT in function to catch ROW_RESULT) +*/ +static Item_result type_convertor[4][4]= +{{STRING_RESULT, STRING_RESULT, STRING_RESULT, ROW_RESULT}, + {STRING_RESULT, REAL_RESULT, REAL_RESULT, ROW_RESULT}, + {STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT}, + {ROW_RESULT, ROW_RESULT, ROW_RESULT, ROW_RESULT}}; + +bool Item_type_holder::join_types(THD *thd, Item *item) +{ + bool change_field= 0, skip_store_field= 0; + Item_result new_type= type_convertor[item_type][item->result_type()]; + + // we have both fields + if (field_example && item->type() == Item::FIELD_ITEM) + { + Field *field= ((Item_field *)item)->field; + if (field_example->field_cast_type() != field->field_cast_type()) + { + if (!(change_field= + field_example->field_cast_compatible(field->field_cast_type()))) + { + /* + if old field can't store value of 'worse' new field we will make + decision about result field type based only on Item result type + */ + if (!field->field_cast_compatible(field_example->field_cast_type())) + skip_store_field= 1; + } + } + } + + // size/type should be changed + if (change_field || + (new_type != item_type) || + (max_length < item->max_length) || + ((new_type == INT_RESULT) && + (decimals < item->decimals)) || + (!maybe_null && item->maybe_null) || + (item_type == STRING_RESULT && new_type == STRING_RESULT && + !my_charset_same(collation.collation, item->collation.collation))) + { + // new field has some parameters worse then current + skip_store_field|= (change_field && + (max_length > item->max_length) || + ((new_type == INT_RESULT) && + (decimals > item->decimals)) || + (maybe_null && !item->maybe_null) || + (item_type == STRING_RESULT && + new_type == STRING_RESULT && + !my_charset_same(collation.collation, + item->collation.collation))); + /* + It is safe assign pointer on field, because it will be used just after + all JOIN::prepare calls and before any SELECT execution + */ + if (skip_store_field || item->type() != Item::FIELD_ITEM) + field_example= 0; + else + field_example= ((Item_field*) item)->field; + + const char *old_cs= collation.collation->name, + *old_derivation= collation.derivation_name(); + if (item_type == STRING_RESULT && collation.aggregate(item->collation)) + { + my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0), + old_cs, old_derivation, + item->collation.collation->name, + item->collation.derivation_name(), + "UNION"); + return 1; + } + + max_length= max(max_length, item->max_length); + decimals= max(decimals, item->decimals); + maybe_null|= item->maybe_null; + item_type= new_type; + } + DBUG_ASSERT(item_type != ROW_RESULT); + return 0; +} + + +double Item_type_holder::val() +{ + DBUG_ASSERT(0); // should never be called + return 0.0; +} + + +longlong Item_type_holder::val_int() +{ + DBUG_ASSERT(0); // should never be called + return 0; +} + + +String *Item_type_holder::val_str(String*) +{ + DBUG_ASSERT(0); // should never be called + return 0; +} + /***************************************************************************** ** Instantiate templates *****************************************************************************/ |