diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 12 | ||||
-rw-r--r-- | sql/item.h | 59 | ||||
-rw-r--r-- | sql/item_func.h | 5 | ||||
-rw-r--r-- | sql/sql_type.cc | 20 | ||||
-rw-r--r-- | sql/sql_type.h | 2 |
5 files changed, 84 insertions, 14 deletions
diff --git a/sql/item.cc b/sql/item.cc index 870b2449514..bf962777a48 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -9913,18 +9913,14 @@ void Item_cache_row::set_null() Item_type_holder::Item_type_holder(THD *thd, Item *item) :Item(thd, item), Type_handler_hybrid_field_type(item->real_type_handler()), - enum_set_typelib(0), - geometry_type(Field::GEOM_GEOMETRY) + Type_geometry_attributes(item), + enum_set_typelib(0) { DBUG_ASSERT(item->fixed); maybe_null= item->maybe_null; get_full_info(item); DBUG_ASSERT(!decimals || Item_type_holder::result_type() != INT_RESULT); prev_decimal_int_part= item->decimal_int_part(); -#ifdef HAVE_SPATIAL - if (item->field_type() == MYSQL_TYPE_GEOMETRY) - geometry_type= item->get_geometry_type(); -#endif /* HAVE_SPATIAL */ } @@ -9977,9 +9973,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item) else decimals= MY_MAX(decimals, item->decimals); - if (Item_type_holder::field_type() == FIELD_TYPE_GEOMETRY) - geometry_type= - Field_geom::geometry_type_merge(geometry_type, item->get_geometry_type()); + Type_geometry_attributes::join(item); if (Item_type_holder::result_type() == DECIMAL_RESULT) { diff --git a/sql/item.h b/sql/item.h index 241fc0e6398..5b85664bf73 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1825,6 +1825,55 @@ inline Item* get_item_copy (THD *thd, MEM_ROOT *mem_root, T* item) } +class Type_geometry_attributes +{ + uint m_geometry_type; + static const uint m_geometry_type_unknown= Field::GEOM_GEOMETRYCOLLECTION + 1; + void copy(const Item *item) + { + // Ignore implicit NULLs + m_geometry_type= item->type_handler() == &type_handler_geometry ? + item->uint_geometry_type() : + m_geometry_type_unknown; + } +public: + Type_geometry_attributes() + :m_geometry_type(m_geometry_type_unknown) + { } + Type_geometry_attributes(const Item *item) + :m_geometry_type(m_geometry_type_unknown) + { + copy(item); + } + void join(const Item *item) + { + // Ignore implicit NULLs + if (m_geometry_type == m_geometry_type_unknown) + copy(item); + else if (item->type_handler() == &type_handler_geometry) + { + m_geometry_type= + Field_geom::geometry_type_merge((Field_geom::geometry_type) + m_geometry_type, + (Field_geom::geometry_type) + item->uint_geometry_type()); + } + } + Field::geometry_type get_geometry_type() const + { + return m_geometry_type == m_geometry_type_unknown ? + Field::GEOM_GEOMETRY : + (Field::geometry_type) m_geometry_type; + } + void set_geometry_type(uint type) + { + DBUG_ASSERT(type <= m_geometry_type_unknown); + m_geometry_type= type; + } +}; + + + /** Compare two Items for List<Item>::add_unique() */ @@ -5796,12 +5845,11 @@ public: single SP/PS execution. */ class Item_type_holder: public Item, - public Type_handler_hybrid_field_type + public Type_handler_hybrid_field_type, + public Type_geometry_attributes { protected: TYPELIB *enum_set_typelib; - Field::geometry_type geometry_type; - void get_full_info(Item *item); /* It is used to count decimal precision in join_types */ @@ -5850,7 +5898,10 @@ public: make_and_init_table_field(&name, Record_addr(maybe_null), *this, table); } - Field::geometry_type get_geometry_type() const { return geometry_type; }; + Field::geometry_type get_geometry_type() const + { + return Type_geometry_attributes::get_geometry_type(); + } Item* get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; } }; diff --git a/sql/item_func.h b/sql/item_func.h index 4b47c7b1f95..33726cd2d84 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -381,7 +381,8 @@ public: Functions whose returned field type is determined at fix_fields() time. */ class Item_hybrid_func: public Item_func, - public Type_handler_hybrid_field_type + public Type_handler_hybrid_field_type, + public Type_geometry_attributes { protected: bool fix_attributes(Item **item, uint nitems); @@ -402,6 +403,8 @@ public: { return Type_handler_hybrid_field_type::result_type(); } enum Item_result cmp_type () const { return Type_handler_hybrid_field_type::cmp_type(); } + Field::geometry_type get_geometry_type() const + { return Type_geometry_attributes::get_geometry_type(); }; }; diff --git a/sql/sql_type.cc b/sql/sql_type.cc index f52d09cd669..abf0b77481e 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -2148,6 +2148,26 @@ bool Type_handler_timestamp_common:: return false; } +#ifdef HAVE_SPATIAL +bool Type_handler_geometry:: + Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, + Item **items, uint nitems) const +{ + DBUG_ASSERT(nitems > 0); + Type_geometry_attributes gattr(items[0]); + for (uint i= 1; i < nitems; i++) + gattr.join(items[i]); + func->set_geometry_type(gattr.get_geometry_type()); + func->collation.set(&my_charset_bin); + func->unsigned_flag= false; + func->decimals= 0; + func->max_length= (uint32) UINT_MAX32; + func->maybe_null= true; + return false; +} +#endif + + /*************************************************************************/ bool Type_handler:: diff --git a/sql/sql_type.h b/sql/sql_type.h index b94d73e8d23..b4564b293dd 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -2153,6 +2153,8 @@ public: bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const; bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const; bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const; + bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, + Item **items, uint nitems) const; bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const; bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const; |