summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/item.cc12
-rw-r--r--sql/item.h59
-rw-r--r--sql/item_func.h5
-rw-r--r--sql/sql_type.cc20
-rw-r--r--sql/sql_type.h2
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;