Commit 54606df1 authored by Alexander Barkov's avatar Alexander Barkov

A cleanup for MDEV-19908 Add class Type_collection

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 ask the type collection of the non-standard type to aggregate the mixture.

If the non-standard collection fails, then continue aggregation
with Type_handler_data.
parent cefe5bb6
...@@ -75,8 +75,6 @@ SET debug_dbug='+d,num_op'; ...@@ -75,8 +75,6 @@ SET debug_dbug='+d,num_op';
# (GEOMETRY,GEOMETRY) goes through # (GEOMETRY,GEOMETRY) goes through
# Type_collection_geometry::aggregate_for_num_op() which fails. # 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 --error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
SELECT POINT(0,0)+POINT(0,0); SELECT POINT(0,0)+POINT(0,0);
......
...@@ -1396,6 +1396,37 @@ Type_handler::get_handler_by_cmp_type(Item_result type) ...@@ -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() Type_handler_hybrid_field_type::Type_handler_hybrid_field_type()
:m_type_handler(&type_handler_double) :m_type_handler(&type_handler_double)
{ {
...@@ -1853,15 +1884,15 @@ const Type_handler *Type_handler_typelib::cast_to_int_type_handler() const ...@@ -1853,15 +1884,15 @@ const Type_handler *Type_handler_typelib::cast_to_int_type_handler() const
bool bool
Type_handler_hybrid_field_type::aggregate_for_result(const Type_handler *other) Type_handler_hybrid_field_type::aggregate_for_result(const Type_handler *other)
{ {
const Type_collection *collection0= m_type_handler->type_collection(); const Type_handler *hres;
if (collection0 == other->type_collection()) const Type_collection *c;
other= collection0->aggregate_for_result(m_type_handler, other); if (!(c= Type_handler::type_collection_for_aggregation(m_type_handler, other)) ||
else !(hres= c->aggregate_for_result(m_type_handler, other)))
other= type_handler_data-> hres= type_handler_data->
m_type_aggregator_for_result.find_handler(m_type_handler, other); m_type_aggregator_for_result.find_handler(m_type_handler, other);
if (!other) if (!hres)
return true; return true;
m_type_handler= other; m_type_handler= hres;
return false; return false;
} }
...@@ -1985,15 +2016,15 @@ Type_handler_hybrid_field_type::aggregate_for_comparison(const Type_handler *h) ...@@ -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(m_type_handler == m_type_handler->type_handler_for_comparison());
DBUG_ASSERT(h == h->type_handler_for_comparison()); DBUG_ASSERT(h == h->type_handler_for_comparison());
const Type_collection *collection0= m_type_handler->type_collection(); const Type_handler *hres;
if (collection0 == h->type_collection()) const Type_collection *c;
h= collection0->aggregate_for_comparison(m_type_handler, h); if (!(c= Type_handler::type_collection_for_aggregation(m_type_handler, h)) ||
else !(hres= c->aggregate_for_comparison(m_type_handler, h)))
h= type_handler_data-> hres= type_handler_data->
m_type_aggregator_for_comparison.find_handler(m_type_handler, h); m_type_aggregator_for_comparison.find_handler(m_type_handler, h);
if (!h) if (!hres)
return true; return true;
m_type_handler= h; m_type_handler= hres;
DBUG_ASSERT(m_type_handler == m_type_handler->type_handler_for_comparison()); DBUG_ASSERT(m_type_handler == m_type_handler->type_handler_for_comparison());
return false; return false;
} }
...@@ -2066,10 +2097,10 @@ Type_collection_std::aggregate_for_comparison(const Type_handler *ha, ...@@ -2066,10 +2097,10 @@ Type_collection_std::aggregate_for_comparison(const Type_handler *ha,
bool bool
Type_handler_hybrid_field_type::aggregate_for_min_max(const Type_handler *h) Type_handler_hybrid_field_type::aggregate_for_min_max(const Type_handler *h)
{ {
const Type_collection *collection0= m_type_handler->type_collection(); const Type_handler *hres;
if (collection0 == h->type_collection()) const Type_collection *c;
h= collection0->aggregate_for_min_max(m_type_handler, h); if (!(c= Type_handler::type_collection_for_aggregation(m_type_handler, h))||
else !(hres= c->aggregate_for_min_max(m_type_handler, h)))
{ {
/* /*
For now we suppose that these two expressions: 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) ...@@ -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. if type1 and/or type2 are non-traditional.
This may change in the future. This may change in the future.
*/ */
h= type_handler_data-> hres= type_handler_data->
m_type_aggregator_for_result.find_handler(m_type_handler, h); m_type_aggregator_for_result.find_handler(m_type_handler, h);
} }
if (!h) if (!hres)
return true; return true;
m_type_handler= h; m_type_handler= hres;
return false; return false;
} }
...@@ -2225,10 +2256,9 @@ Type_handler_hybrid_field_type::aggregate_for_num_op(const Type_aggregator *agg, ...@@ -2225,10 +2256,9 @@ Type_handler_hybrid_field_type::aggregate_for_num_op(const Type_aggregator *agg,
const Type_handler *h1) const Type_handler *h1)
{ {
const Type_handler *hres; const Type_handler *hres;
const Type_collection *collection0= h0->type_collection(); const Type_collection *c;
if (collection0 == h1->type_collection()) if (!(c= Type_handler::type_collection_for_aggregation(h0, h1)) ||
hres= collection0->aggregate_for_num_op(h0, h1); !(hres= c->aggregate_for_num_op(h0, h1)))
else
hres= agg->find_handler(h0, h1); hres= agg->find_handler(h0, h1);
if (!hres) if (!hres)
return true; return true;
......
...@@ -3349,6 +3349,9 @@ class Type_handler ...@@ -3349,6 +3349,9 @@ class Type_handler
static const Type_handler *get_handler_by_field_type(enum_field_types type); 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_real_type(enum_field_types type);
static const Type_handler *get_handler_by_cmp_type(Item_result 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; virtual const Type_collection *type_collection() const;
static const static const
Type_handler *aggregate_for_result_traditional(const Type_handler *h1, Type_handler *aggregate_for_result_traditional(const Type_handler *h1,
......
...@@ -169,23 +169,8 @@ bool Type_collection_geometry::init_aggregators(Type_handler_data *data, ...@@ -169,23 +169,8 @@ bool Type_collection_geometry::init_aggregators(Type_handler_data *data,
bool Type_collection_geometry::init(Type_handler_data *data) bool Type_collection_geometry::init(Type_handler_data *data)
{ {
#ifndef DBUG_OFF #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; Type_aggregator *nct= &data->m_type_aggregator_non_commutative_test;
if (nct->add(&type_handler_geometry, if (nct->add(&type_handler_point,
&type_handler_geometry,
&type_handler_geometry) ||
nct->add(&type_handler_point,
&type_handler_point,
&type_handler_geometry) ||
nct->add(&type_handler_point,
&type_handler_varchar, &type_handler_varchar,
&type_handler_long_blob)) &type_handler_long_blob))
return true; return true;
......
...@@ -275,9 +275,10 @@ class Type_collection_geometry: public Type_collection ...@@ -275,9 +275,10 @@ class Type_collection_geometry: public Type_collection
{ {
if (a == b) if (a == b)
return a; return a;
DBUG_ASSERT(dynamic_cast<const Type_handler_geometry*>(a)); if (dynamic_cast<const Type_handler_geometry*>(a) &&
DBUG_ASSERT(dynamic_cast<const Type_handler_geometry*>(b)); dynamic_cast<const Type_handler_geometry*>(b))
return &type_handler_geometry; return &type_handler_geometry;
return NULL;
} }
bool init_aggregators(Type_handler_data *data, const Type_handler *geom) const; bool init_aggregators(Type_handler_data *data, const Type_handler *geom) const;
public: public:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment