summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/main/gis-debug.test2
-rw-r--r--sql/sql_type.cc86
-rw-r--r--sql/sql_type.h3
-rw-r--r--sql/sql_type_geom.cc17
-rw-r--r--sql/sql_type_geom.h7
5 files changed, 66 insertions, 49 deletions
diff --git a/mysql-test/main/gis-debug.test b/mysql-test/main/gis-debug.test
index dd1cbd0b932..0e11c11e5b5 100644
--- a/mysql-test/main/gis-debug.test
+++ b/mysql-test/main/gis-debug.test
@@ -75,8 +75,6 @@ SET debug_dbug='+d,num_op';
# (GEOMETRY,GEOMETRY) goes through
# Type_collection_geometry::aggregate_for_num_op() which fails.
-# Type pairs from Type_handler_data::m_type_aggregator_xxx are not even tested,
-# as both sides are from the same type collection.
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
SELECT POINT(0,0)+POINT(0,0);
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index 9b4cd1b0c48..f7e88686e7a 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -1396,6 +1396,37 @@ Type_handler::get_handler_by_cmp_type(Item_result type)
}
+/*
+ If we have a mixture of:
+ - a MariaDB standard (built-in permanent) data type, and
+ - a non-standard (optionally compiled or pluggable) data type,
+ then we ask the type collection of the non-standard type to aggregate
+ the mixture.
+ The standard type collection type_collection_std knows nothing
+ about non-standard types, while non-standard type collections
+ know everything about standard data types.
+*/
+const Type_collection *
+Type_handler::type_collection_for_aggregation(const Type_handler *h0,
+ const Type_handler *h1)
+{
+ const Type_collection *c0= h0->type_collection();
+ const Type_collection *c1= h1->type_collection();
+ if (c0 == c1)
+ return c0;
+ if (c0 == &type_collection_std)
+ return c1;
+ if (c1 == &type_collection_std)
+ return c0;
+ /*
+ A mixture of two non-standard collections.
+ The caller code will continue to aggregate through
+ the type aggregators in Type_handler_data.
+ */
+ return NULL;
+}
+
+
Type_handler_hybrid_field_type::Type_handler_hybrid_field_type()
:m_type_handler(&type_handler_double)
{
@@ -1853,15 +1884,15 @@ const Type_handler *Type_handler_typelib::cast_to_int_type_handler() const
bool
Type_handler_hybrid_field_type::aggregate_for_result(const Type_handler *other)
{
- const Type_collection *collection0= m_type_handler->type_collection();
- if (collection0 == other->type_collection())
- other= collection0->aggregate_for_result(m_type_handler, other);
- else
- other= type_handler_data->
- m_type_aggregator_for_result.find_handler(m_type_handler, other);
- if (!other)
+ const Type_handler *hres;
+ const Type_collection *c;
+ if (!(c= Type_handler::type_collection_for_aggregation(m_type_handler, other)) ||
+ !(hres= c->aggregate_for_result(m_type_handler, other)))
+ hres= type_handler_data->
+ m_type_aggregator_for_result.find_handler(m_type_handler, other);
+ if (!hres)
return true;
- m_type_handler= other;
+ m_type_handler= hres;
return false;
}
@@ -1985,15 +2016,15 @@ Type_handler_hybrid_field_type::aggregate_for_comparison(const Type_handler *h)
{
DBUG_ASSERT(m_type_handler == m_type_handler->type_handler_for_comparison());
DBUG_ASSERT(h == h->type_handler_for_comparison());
- const Type_collection *collection0= m_type_handler->type_collection();
- if (collection0 == h->type_collection())
- h= collection0->aggregate_for_comparison(m_type_handler, h);
- else
- h= type_handler_data->
- m_type_aggregator_for_comparison.find_handler(m_type_handler, h);
- if (!h)
+ const Type_handler *hres;
+ const Type_collection *c;
+ if (!(c= Type_handler::type_collection_for_aggregation(m_type_handler, h)) ||
+ !(hres= c->aggregate_for_comparison(m_type_handler, h)))
+ hres= type_handler_data->
+ m_type_aggregator_for_comparison.find_handler(m_type_handler, h);
+ if (!hres)
return true;
- m_type_handler= h;
+ m_type_handler= hres;
DBUG_ASSERT(m_type_handler == m_type_handler->type_handler_for_comparison());
return false;
}
@@ -2066,10 +2097,10 @@ Type_collection_std::aggregate_for_comparison(const Type_handler *ha,
bool
Type_handler_hybrid_field_type::aggregate_for_min_max(const Type_handler *h)
{
- const Type_collection *collection0= m_type_handler->type_collection();
- if (collection0 == h->type_collection())
- h= collection0->aggregate_for_min_max(m_type_handler, h);
- else
+ const Type_handler *hres;
+ const Type_collection *c;
+ if (!(c= Type_handler::type_collection_for_aggregation(m_type_handler, h))||
+ !(hres= c->aggregate_for_min_max(m_type_handler, h)))
{
/*
For now we suppose that these two expressions:
@@ -2079,12 +2110,12 @@ Type_handler_hybrid_field_type::aggregate_for_min_max(const Type_handler *h)
if type1 and/or type2 are non-traditional.
This may change in the future.
*/
- h= type_handler_data->
- m_type_aggregator_for_result.find_handler(m_type_handler, h);
+ hres= type_handler_data->
+ m_type_aggregator_for_result.find_handler(m_type_handler, h);
}
- if (!h)
+ if (!hres)
return true;
- m_type_handler= h;
+ m_type_handler= hres;
return false;
}
@@ -2225,10 +2256,9 @@ Type_handler_hybrid_field_type::aggregate_for_num_op(const Type_aggregator *agg,
const Type_handler *h1)
{
const Type_handler *hres;
- const Type_collection *collection0= h0->type_collection();
- if (collection0 == h1->type_collection())
- hres= collection0->aggregate_for_num_op(h0, h1);
- else
+ const Type_collection *c;
+ if (!(c= Type_handler::type_collection_for_aggregation(h0, h1)) ||
+ !(hres= c->aggregate_for_num_op(h0, h1)))
hres= agg->find_handler(h0, h1);
if (!hres)
return true;
diff --git a/sql/sql_type.h b/sql/sql_type.h
index e5929e57225..d4fce0fe19f 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -3349,6 +3349,9 @@ public:
static const Type_handler *get_handler_by_field_type(enum_field_types type);
static const Type_handler *get_handler_by_real_type(enum_field_types type);
static const Type_handler *get_handler_by_cmp_type(Item_result type);
+ static const Type_collection *
+ type_collection_for_aggregation(const Type_handler *h1,
+ const Type_handler *h2);
virtual const Type_collection *type_collection() const;
static const
Type_handler *aggregate_for_result_traditional(const Type_handler *h1,
diff --git a/sql/sql_type_geom.cc b/sql/sql_type_geom.cc
index c2c11e952eb..16276250f66 100644
--- a/sql/sql_type_geom.cc
+++ b/sql/sql_type_geom.cc
@@ -169,23 +169,8 @@ bool Type_collection_geometry::init_aggregators(Type_handler_data *data,
bool Type_collection_geometry::init(Type_handler_data *data)
{
#ifndef DBUG_OFF
- /*
- The rules (geometry,geometry)->geometry and (pont,point)->geometry
- are needed here to make sure
- (in gis-debug.test) that they do not affect anything, and these pairs
- returns an error in an expression like (POINT(0,0)+POINT(0,0)).
- Both sides are from the same type collection here,
- so aggregation goes only through Type_collection_xxx::aggregate_yyy()
- and never reaches Type_aggregator::find_handler().
- */
Type_aggregator *nct= &data->m_type_aggregator_non_commutative_test;
- if (nct->add(&type_handler_geometry,
- &type_handler_geometry,
- &type_handler_geometry) ||
- nct->add(&type_handler_point,
- &type_handler_point,
- &type_handler_geometry) ||
- nct->add(&type_handler_point,
+ if (nct->add(&type_handler_point,
&type_handler_varchar,
&type_handler_long_blob))
return true;
diff --git a/sql/sql_type_geom.h b/sql/sql_type_geom.h
index ff21fa51790..9861a771b27 100644
--- a/sql/sql_type_geom.h
+++ b/sql/sql_type_geom.h
@@ -275,9 +275,10 @@ class Type_collection_geometry: public Type_collection
{
if (a == b)
return a;
- DBUG_ASSERT(dynamic_cast<const Type_handler_geometry*>(a));
- DBUG_ASSERT(dynamic_cast<const Type_handler_geometry*>(b));
- return &type_handler_geometry;
+ if (dynamic_cast<const Type_handler_geometry*>(a) &&
+ dynamic_cast<const Type_handler_geometry*>(b))
+ return &type_handler_geometry;
+ return NULL;
}
bool init_aggregators(Type_handler_data *data, const Type_handler *geom) const;
public: