mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-19908 Add class Type_collection
This commit is contained in:
@ -356,22 +356,16 @@ SET SESSION debug_dbug="-d,Item_func_in";
|
|||||||
# MDEV-12238 Add Type_handler::Item_func_{plus|minus|mul|div|mod}_fix_length_and_dec()
|
# MDEV-12238 Add Type_handler::Item_func_{plus|minus|mul|div|mod}_fix_length_and_dec()
|
||||||
#
|
#
|
||||||
SET debug_dbug='+d,num_op';
|
SET debug_dbug='+d,num_op';
|
||||||
CREATE TABLE t1 AS SELECT
|
SELECT POINT(0,0)+POINT(0,0);
|
||||||
POINT(0,0)+POINT(0,0),
|
ERROR HY000: Illegal parameter data types geometry and geometry for operation '+'
|
||||||
POINT(0,0)-POINT(0,0),
|
SELECT POINT(0,0)-POINT(0,0);
|
||||||
POINT(0,0)*POINT(0,0),
|
ERROR HY000: Illegal parameter data types geometry and geometry for operation '-'
|
||||||
POINT(0,0)/POINT(0,0),
|
SELECT POINT(0,0)*POINT(0,0);
|
||||||
POINT(0,0) MOD POINT(0,0) LIMIT 0;
|
ERROR HY000: Illegal parameter data types geometry and geometry for operation '*'
|
||||||
SHOW CREATE TABLE t1;
|
SELECT POINT(0,0)/POINT(0,0);
|
||||||
Table Create Table
|
ERROR HY000: Illegal parameter data types geometry and geometry for operation '/'
|
||||||
t1 CREATE TABLE `t1` (
|
SELECT POINT(0,0) MOD POINT(0,0);
|
||||||
`POINT(0,0)+POINT(0,0)` geometry DEFAULT NULL,
|
ERROR HY000: Illegal parameter data types geometry and geometry for operation 'MOD'
|
||||||
`POINT(0,0)-POINT(0,0)` geometry DEFAULT NULL,
|
|
||||||
`POINT(0,0)*POINT(0,0)` geometry DEFAULT NULL,
|
|
||||||
`POINT(0,0)/POINT(0,0)` geometry DEFAULT NULL,
|
|
||||||
`POINT(0,0) MOD POINT(0,0)` geometry DEFAULT NULL
|
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
|
||||||
DROP TABLE t1;
|
|
||||||
CREATE TABLE t1 AS SELECT
|
CREATE TABLE t1 AS SELECT
|
||||||
POINT(0,0)+'0',
|
POINT(0,0)+'0',
|
||||||
POINT(0,0)-'0',
|
POINT(0,0)-'0',
|
||||||
|
@ -73,15 +73,21 @@ SET SESSION debug_dbug="-d,Item_func_in";
|
|||||||
|
|
||||||
SET debug_dbug='+d,num_op';
|
SET debug_dbug='+d,num_op';
|
||||||
|
|
||||||
# (GEOMETRY,GEOMETRY) gives GEOMETRY for all operators
|
# (GEOMETRY,GEOMETRY) goes through
|
||||||
CREATE TABLE t1 AS SELECT
|
# Type_collection_geometry::aggregate_for_num_op() which fails.
|
||||||
POINT(0,0)+POINT(0,0),
|
# Type pairs from Type_handler_data::m_type_aggregator_xxx are not even tested,
|
||||||
POINT(0,0)-POINT(0,0),
|
# as both sides are from the same type collection.
|
||||||
POINT(0,0)*POINT(0,0),
|
|
||||||
POINT(0,0)/POINT(0,0),
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
POINT(0,0) MOD POINT(0,0) LIMIT 0;
|
SELECT POINT(0,0)+POINT(0,0);
|
||||||
SHOW CREATE TABLE t1;
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
DROP TABLE t1;
|
SELECT POINT(0,0)-POINT(0,0);
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT POINT(0,0)*POINT(0,0);
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT POINT(0,0)/POINT(0,0);
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT POINT(0,0) MOD POINT(0,0);
|
||||||
|
|
||||||
# (GEOMETRY,VARCHAR) gives GEOMETRY for all operators
|
# (GEOMETRY,VARCHAR) gives GEOMETRY for all operators
|
||||||
CREATE TABLE t1 AS SELECT
|
CREATE TABLE t1 AS SELECT
|
||||||
|
251
sql/sql_type.cc
251
sql/sql_type.cc
@ -70,8 +70,83 @@ Type_handler_blob_compressed type_handler_blob_compressed;
|
|||||||
|
|
||||||
Type_handler_interval_DDhhmmssff type_handler_interval_DDhhmmssff;
|
Type_handler_interval_DDhhmmssff type_handler_interval_DDhhmmssff;
|
||||||
|
|
||||||
|
|
||||||
|
class Type_collection_std: public Type_collection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const Type_handler *aggregate_for_result(const Type_handler *a,
|
||||||
|
const Type_handler *b)
|
||||||
|
const override
|
||||||
|
{
|
||||||
|
return Type_handler::aggregate_for_result_traditional(a, b);
|
||||||
|
}
|
||||||
|
const Type_handler *aggregate_for_comparison(const Type_handler *a,
|
||||||
|
const Type_handler *b)
|
||||||
|
const override;
|
||||||
|
const Type_handler *aggregate_for_min_max(const Type_handler *a,
|
||||||
|
const Type_handler *b)
|
||||||
|
const override;
|
||||||
|
const Type_handler *aggregate_for_num_op(const Type_handler *a,
|
||||||
|
const Type_handler *b)
|
||||||
|
const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static Type_collection_std type_collection_std;
|
||||||
|
|
||||||
|
const Type_collection *Type_handler::type_collection() const
|
||||||
|
{
|
||||||
|
return &type_collection_std;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_SPATIAL
|
#ifdef HAVE_SPATIAL
|
||||||
Type_handler_geometry type_handler_geometry;
|
Type_handler_geometry type_handler_geometry;
|
||||||
|
|
||||||
|
class Type_collection_geometry: public Type_collection
|
||||||
|
{
|
||||||
|
const Type_handler *aggregate_common(const Type_handler *a,
|
||||||
|
const Type_handler *b) const
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(a == &type_handler_geometry);
|
||||||
|
DBUG_ASSERT(b == &type_handler_geometry);
|
||||||
|
return &type_handler_geometry;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
const Type_handler *aggregate_for_result(const Type_handler *a,
|
||||||
|
const Type_handler *b)
|
||||||
|
const override
|
||||||
|
{
|
||||||
|
return aggregate_common(a, b);
|
||||||
|
}
|
||||||
|
const Type_handler *aggregate_for_comparison(const Type_handler *a,
|
||||||
|
const Type_handler *b)
|
||||||
|
const override
|
||||||
|
{
|
||||||
|
return aggregate_common(a, b);
|
||||||
|
}
|
||||||
|
const Type_handler *aggregate_for_min_max(const Type_handler *a,
|
||||||
|
const Type_handler *b)
|
||||||
|
const override
|
||||||
|
{
|
||||||
|
return aggregate_common(a, b);
|
||||||
|
}
|
||||||
|
const Type_handler *aggregate_for_num_op(const Type_handler *a,
|
||||||
|
const Type_handler *b)
|
||||||
|
const override
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static Type_collection_geometry type_collection_geometry;
|
||||||
|
|
||||||
|
const Type_collection *Type_handler_geometry::type_collection() const
|
||||||
|
{
|
||||||
|
return &type_collection_geometry;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -80,6 +155,14 @@ bool Type_handler_data::init()
|
|||||||
#ifdef HAVE_SPATIAL
|
#ifdef HAVE_SPATIAL
|
||||||
|
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
|
/*
|
||||||
|
The rule (geometry,geometry)->geometry is needed here to make sure
|
||||||
|
(in gis-debug.test) that is does not affect anything, and this pair
|
||||||
|
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().
|
||||||
|
*/
|
||||||
if (m_type_aggregator_non_commutative_test.add(&type_handler_geometry,
|
if (m_type_aggregator_non_commutative_test.add(&type_handler_geometry,
|
||||||
&type_handler_geometry,
|
&type_handler_geometry,
|
||||||
&type_handler_geometry) ||
|
&type_handler_geometry) ||
|
||||||
@ -93,9 +176,6 @@ bool Type_handler_data::init()
|
|||||||
m_type_aggregator_for_result.add(&type_handler_geometry,
|
m_type_aggregator_for_result.add(&type_handler_geometry,
|
||||||
&type_handler_null,
|
&type_handler_null,
|
||||||
&type_handler_geometry) ||
|
&type_handler_geometry) ||
|
||||||
m_type_aggregator_for_result.add(&type_handler_geometry,
|
|
||||||
&type_handler_geometry,
|
|
||||||
&type_handler_geometry) ||
|
|
||||||
m_type_aggregator_for_result.add(&type_handler_geometry,
|
m_type_aggregator_for_result.add(&type_handler_geometry,
|
||||||
&type_handler_hex_hybrid,
|
&type_handler_hex_hybrid,
|
||||||
&type_handler_long_blob) ||
|
&type_handler_long_blob) ||
|
||||||
@ -117,9 +197,6 @@ bool Type_handler_data::init()
|
|||||||
m_type_aggregator_for_result.add(&type_handler_geometry,
|
m_type_aggregator_for_result.add(&type_handler_geometry,
|
||||||
&type_handler_string,
|
&type_handler_string,
|
||||||
&type_handler_long_blob) ||
|
&type_handler_long_blob) ||
|
||||||
m_type_aggregator_for_comparison.add(&type_handler_geometry,
|
|
||||||
&type_handler_geometry,
|
|
||||||
&type_handler_geometry) ||
|
|
||||||
m_type_aggregator_for_comparison.add(&type_handler_geometry,
|
m_type_aggregator_for_comparison.add(&type_handler_geometry,
|
||||||
&type_handler_null,
|
&type_handler_null,
|
||||||
&type_handler_geometry) ||
|
&type_handler_geometry) ||
|
||||||
@ -1446,12 +1523,10 @@ 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)
|
||||||
{
|
{
|
||||||
if (m_type_handler->is_traditional_type() && other->is_traditional_type())
|
const Type_collection *collection0= m_type_handler->type_collection();
|
||||||
{
|
if (collection0 == other->type_collection())
|
||||||
m_type_handler=
|
other= collection0->aggregate_for_result(m_type_handler, other);
|
||||||
Type_handler::aggregate_for_result_traditional(m_type_handler, other);
|
else
|
||||||
return false;
|
|
||||||
}
|
|
||||||
other= type_handler_data->
|
other= 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 (!other)
|
||||||
@ -1572,10 +1647,10 @@ 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();
|
||||||
if (!m_type_handler->is_traditional_type() ||
|
if (collection0 == h->type_collection())
|
||||||
!h->is_traditional_type())
|
h= collection0->aggregate_for_comparison(m_type_handler, h);
|
||||||
{
|
else
|
||||||
h= type_handler_data->
|
h= 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 (!h)
|
||||||
@ -1583,26 +1658,31 @@ Type_handler_hybrid_field_type::aggregate_for_comparison(const Type_handler *h)
|
|||||||
m_type_handler= h;
|
m_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());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Item_result a= cmp_type();
|
|
||||||
Item_result b= h->cmp_type();
|
const Type_handler *
|
||||||
|
Type_collection_std::aggregate_for_comparison(const Type_handler *ha,
|
||||||
|
const Type_handler *hb) const
|
||||||
|
{
|
||||||
|
Item_result a= ha->cmp_type();
|
||||||
|
Item_result b= hb->cmp_type();
|
||||||
if (a == STRING_RESULT && b == STRING_RESULT)
|
if (a == STRING_RESULT && b == STRING_RESULT)
|
||||||
m_type_handler= &type_handler_long_blob;
|
return &type_handler_long_blob;
|
||||||
else if (a == INT_RESULT && b == INT_RESULT)
|
if (a == INT_RESULT && b == INT_RESULT)
|
||||||
m_type_handler= &type_handler_longlong;
|
return &type_handler_longlong;
|
||||||
else if (a == ROW_RESULT || b == ROW_RESULT)
|
if (a == ROW_RESULT || b == ROW_RESULT)
|
||||||
m_type_handler= &type_handler_row;
|
return &type_handler_row;
|
||||||
else if (a == TIME_RESULT || b == TIME_RESULT)
|
if (a == TIME_RESULT || b == TIME_RESULT)
|
||||||
{
|
{
|
||||||
if ((a == TIME_RESULT) + (b == TIME_RESULT) == 1)
|
if ((a == TIME_RESULT) + (b == TIME_RESULT) == 1)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
We're here if there's only one temporal data type:
|
We're here if there's only one temporal data type:
|
||||||
either m_type_handler or h.
|
either m_type_handler or h.
|
||||||
|
Temporal types bit non-temporal types.
|
||||||
*/
|
*/
|
||||||
if (b == TIME_RESULT)
|
const Type_handler *res= b == TIME_RESULT ? hb : ha;
|
||||||
m_type_handler= h; // Temporal types bit non-temporal types
|
|
||||||
/*
|
/*
|
||||||
Compare TIMESTAMP to a non-temporal type as DATETIME.
|
Compare TIMESTAMP to a non-temporal type as DATETIME.
|
||||||
This is needed to make queries with fuzzy dates work:
|
This is needed to make queries with fuzzy dates work:
|
||||||
@ -1610,9 +1690,9 @@ Type_handler_hybrid_field_type::aggregate_for_comparison(const Type_handler *h)
|
|||||||
WHERE
|
WHERE
|
||||||
ts BETWEEN '0000-00-00' AND '2010-00-01 00:00:00';
|
ts BETWEEN '0000-00-00' AND '2010-00-01 00:00:00';
|
||||||
*/
|
*/
|
||||||
if (m_type_handler->type_handler_for_native_format() ==
|
if (res->type_handler_for_native_format() == &type_handler_timestamp2)
|
||||||
&type_handler_timestamp2)
|
return &type_handler_datetime;
|
||||||
m_type_handler= &type_handler_datetime;
|
return res;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1624,19 +1704,15 @@ Type_handler_hybrid_field_type::aggregate_for_comparison(const Type_handler *h)
|
|||||||
to print DATE constants using proper format:
|
to print DATE constants using proper format:
|
||||||
'YYYY-MM-DD' rather than 'YYYY-MM-DD 00:00:00'.
|
'YYYY-MM-DD' rather than 'YYYY-MM-DD 00:00:00'.
|
||||||
*/
|
*/
|
||||||
if (m_type_handler->field_type() != h->field_type())
|
if (ha->field_type() != hb->field_type())
|
||||||
m_type_handler= &type_handler_datetime;
|
return &type_handler_datetime;
|
||||||
|
return ha;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((a == INT_RESULT || a == DECIMAL_RESULT) &&
|
if ((a == INT_RESULT || a == DECIMAL_RESULT) &&
|
||||||
(b == INT_RESULT || b == DECIMAL_RESULT))
|
(b == INT_RESULT || b == DECIMAL_RESULT))
|
||||||
{
|
return &type_handler_newdecimal;
|
||||||
m_type_handler= &type_handler_newdecimal;
|
return &type_handler_double;
|
||||||
}
|
|
||||||
else
|
|
||||||
m_type_handler= &type_handler_double;
|
|
||||||
DBUG_ASSERT(m_type_handler == m_type_handler->type_handler_for_comparison());
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1652,12 +1728,12 @@ Type_handler_hybrid_field_type::aggregate_for_comparison(const Type_handler *h)
|
|||||||
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)
|
||||||
{
|
{
|
||||||
if (!m_type_handler->is_traditional_type() ||
|
const Type_collection *collection0= m_type_handler->type_collection();
|
||||||
!h->is_traditional_type())
|
if (collection0 == h->type_collection())
|
||||||
|
h= collection0->aggregate_for_min_max(m_type_handler, h);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
If at least one data type is non-traditional,
|
|
||||||
do aggregation for result immediately.
|
|
||||||
For now we suppose that these two expressions:
|
For now we suppose that these two expressions:
|
||||||
- LEAST(type1, type2)
|
- LEAST(type1, type2)
|
||||||
- COALESCE(type1, type2)
|
- COALESCE(type1, type2)
|
||||||
@ -1667,77 +1743,72 @@ Type_handler_hybrid_field_type::aggregate_for_min_max(const Type_handler *h)
|
|||||||
*/
|
*/
|
||||||
h= type_handler_data->
|
h= 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 (!h)
|
||||||
return true;
|
return true;
|
||||||
m_type_handler= h;
|
m_type_handler= h;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Item_result a= cmp_type();
|
|
||||||
Item_result b= h->cmp_type();
|
const Type_handler *
|
||||||
|
Type_collection_std::aggregate_for_min_max(const Type_handler *ha,
|
||||||
|
const Type_handler *hb) const
|
||||||
|
{
|
||||||
|
Item_result a= ha->cmp_type();
|
||||||
|
Item_result b= hb->cmp_type();
|
||||||
DBUG_ASSERT(a != ROW_RESULT); // Disallowed by check_cols() in fix_fields()
|
DBUG_ASSERT(a != ROW_RESULT); // Disallowed by check_cols() in fix_fields()
|
||||||
DBUG_ASSERT(b != ROW_RESULT); // Disallowed by check_cols() in fix_fields()
|
DBUG_ASSERT(b != ROW_RESULT); // Disallowed by check_cols() in fix_fields()
|
||||||
|
|
||||||
if (a == STRING_RESULT && b == STRING_RESULT)
|
if (a == STRING_RESULT && b == STRING_RESULT)
|
||||||
m_type_handler=
|
return Type_collection_std::aggregate_for_result(ha, hb);
|
||||||
Type_handler::aggregate_for_result_traditional(m_type_handler, h);
|
if (a == INT_RESULT && b == INT_RESULT)
|
||||||
else if (a == INT_RESULT && b == INT_RESULT)
|
|
||||||
{
|
{
|
||||||
// BIT aggregates with non-BIT as BIGINT
|
// BIT aggregates with non-BIT as BIGINT
|
||||||
if (m_type_handler != h)
|
if (ha != hb)
|
||||||
{
|
{
|
||||||
if (m_type_handler == &type_handler_bit)
|
if (ha == &type_handler_bit)
|
||||||
m_type_handler= &type_handler_longlong;
|
ha= &type_handler_longlong;
|
||||||
else if (h == &type_handler_bit)
|
else if (hb == &type_handler_bit)
|
||||||
h= &type_handler_longlong;
|
hb= &type_handler_longlong;
|
||||||
}
|
}
|
||||||
m_type_handler=
|
return Type_collection_std::aggregate_for_result(ha, hb);
|
||||||
Type_handler::aggregate_for_result_traditional(m_type_handler, h);
|
|
||||||
}
|
}
|
||||||
else if (a == TIME_RESULT || b == TIME_RESULT)
|
if (a == TIME_RESULT || b == TIME_RESULT)
|
||||||
{
|
{
|
||||||
if ((m_type_handler->type_handler_for_native_format() ==
|
if ((ha->type_handler_for_native_format() == &type_handler_timestamp2) +
|
||||||
&type_handler_timestamp2) +
|
(hb->type_handler_for_native_format() == &type_handler_timestamp2) == 1)
|
||||||
(h->type_handler_for_native_format() ==
|
|
||||||
&type_handler_timestamp2) == 1)
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Handle LEAST(TIMESTAMP, non-TIMESTAMP) as DATETIME,
|
Handle LEAST(TIMESTAMP, non-TIMESTAMP) as DATETIME,
|
||||||
to make sure fuzzy dates work in this context:
|
to make sure fuzzy dates work in this context:
|
||||||
LEAST('2001-00-00', timestamp_field)
|
LEAST('2001-00-00', timestamp_field)
|
||||||
*/
|
*/
|
||||||
m_type_handler= &type_handler_datetime2;
|
return &type_handler_datetime2;
|
||||||
}
|
}
|
||||||
else if ((a == TIME_RESULT) + (b == TIME_RESULT) == 1)
|
if ((a == TIME_RESULT) + (b == TIME_RESULT) == 1)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
We're here if there's only one temporal data type:
|
We're here if there's only one temporal data type:
|
||||||
either m_type_handler or h.
|
either m_type_handler or h.
|
||||||
|
Temporal types bit non-temporal types.
|
||||||
*/
|
*/
|
||||||
if (b == TIME_RESULT)
|
return (b == TIME_RESULT) ? hb : ha;
|
||||||
m_type_handler= h; // Temporal types bit non-temporal types
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
We're here if both m_type_handler and h are temporal data types.
|
We're here if both m_type_handler and h are temporal data types.
|
||||||
*/
|
*/
|
||||||
m_type_handler=
|
return Type_collection_std::aggregate_for_result(ha, hb);
|
||||||
Type_handler::aggregate_for_result_traditional(m_type_handler, h);
|
|
||||||
}
|
}
|
||||||
}
|
if ((a == INT_RESULT || a == DECIMAL_RESULT) &&
|
||||||
else if ((a == INT_RESULT || a == DECIMAL_RESULT) &&
|
|
||||||
(b == INT_RESULT || b == DECIMAL_RESULT))
|
(b == INT_RESULT || b == DECIMAL_RESULT))
|
||||||
{
|
{
|
||||||
m_type_handler= &type_handler_newdecimal;
|
return &type_handler_newdecimal;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// Preserve FLOAT if two FLOATs, set to DOUBLE otherwise.
|
// Preserve FLOAT if two FLOATs, set to DOUBLE otherwise.
|
||||||
if (m_type_handler != &type_handler_float || h != &type_handler_float)
|
if (ha == &type_handler_float && hb == &type_handler_float)
|
||||||
m_type_handler= &type_handler_double;
|
return &type_handler_float;
|
||||||
}
|
return &type_handler_double;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1772,8 +1843,8 @@ Type_handler_hybrid_field_type::aggregate_for_min_max(const char *funcname,
|
|||||||
|
|
||||||
|
|
||||||
const Type_handler *
|
const Type_handler *
|
||||||
Type_handler::aggregate_for_num_op_traditional(const Type_handler *h0,
|
Type_collection_std::aggregate_for_num_op(const Type_handler *h0,
|
||||||
const Type_handler *h1)
|
const Type_handler *h1) const
|
||||||
{
|
{
|
||||||
Item_result r0= h0->cmp_type();
|
Item_result r0= h0->cmp_type();
|
||||||
Item_result r1= h1->cmp_type();
|
Item_result r1= h1->cmp_type();
|
||||||
@ -1814,17 +1885,15 @@ 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;
|
||||||
if (h0->is_traditional_type() && h1->is_traditional_type())
|
const Type_collection *collection0= h0->type_collection();
|
||||||
{
|
if (collection0 == h1->type_collection())
|
||||||
set_handler(Type_handler::aggregate_for_num_op_traditional(h0, h1));
|
hres= collection0->aggregate_for_num_op(h0, h1);
|
||||||
return false;
|
else
|
||||||
}
|
hres= agg->find_handler(h0, h1);
|
||||||
if ((hres= agg->find_handler(h0, h1)))
|
if (!hres)
|
||||||
{
|
|
||||||
set_handler(hres);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
|
m_type_handler= hres;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,6 +87,7 @@ class Vers_history_point;
|
|||||||
class Virtual_column_info;
|
class Virtual_column_info;
|
||||||
class Conv_source;
|
class Conv_source;
|
||||||
class ST_FIELD_INFO;
|
class ST_FIELD_INFO;
|
||||||
|
class Type_collection;
|
||||||
|
|
||||||
#define my_charset_numeric my_charset_latin1
|
#define my_charset_numeric my_charset_latin1
|
||||||
|
|
||||||
@ -3281,12 +3282,10 @@ public:
|
|||||||
DBUG_ASSERT(type != TIME_RESULT);
|
DBUG_ASSERT(type != TIME_RESULT);
|
||||||
return get_handler_by_cmp_type(type);
|
return get_handler_by_cmp_type(type);
|
||||||
}
|
}
|
||||||
|
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,
|
||||||
const Type_handler *h2);
|
const Type_handler *h2);
|
||||||
static const
|
|
||||||
Type_handler *aggregate_for_num_op_traditional(const Type_handler *h1,
|
|
||||||
const Type_handler *h2);
|
|
||||||
|
|
||||||
virtual const Name name() const= 0;
|
virtual const Name name() const= 0;
|
||||||
virtual const Name version() const { return m_version_default; }
|
virtual const Name version() const { return m_version_default; }
|
||||||
@ -6372,6 +6371,7 @@ public:
|
|||||||
bool is_param_long_data_type() const { return true; }
|
bool is_param_long_data_type() const { return true; }
|
||||||
uint32 max_display_length_for_field(const Conv_source &src) const;
|
uint32 max_display_length_for_field(const Conv_source &src) const;
|
||||||
uint32 calc_pack_length(uint32 length) const;
|
uint32 calc_pack_length(uint32 length) const;
|
||||||
|
const Type_collection *type_collection() const override;
|
||||||
const Type_handler *type_handler_for_comparison() const;
|
const Type_handler *type_handler_for_comparison() const;
|
||||||
bool type_can_have_key_part() const
|
bool type_can_have_key_part() const
|
||||||
{
|
{
|
||||||
@ -6570,6 +6570,24 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_collection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Type_collection() {}
|
||||||
|
virtual const Type_handler *aggregate_for_result(const Type_handler *h1,
|
||||||
|
const Type_handler *h2)
|
||||||
|
const= 0;
|
||||||
|
virtual const Type_handler *aggregate_for_comparison(const Type_handler *h1,
|
||||||
|
const Type_handler *h2)
|
||||||
|
const= 0;
|
||||||
|
virtual const Type_handler *aggregate_for_min_max(const Type_handler *h1,
|
||||||
|
const Type_handler *h2)
|
||||||
|
const= 0;
|
||||||
|
virtual const Type_handler *aggregate_for_num_op(const Type_handler *h1,
|
||||||
|
const Type_handler *h2)
|
||||||
|
const= 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
A handler for hybrid type functions, e.g.
|
A handler for hybrid type functions, e.g.
|
||||||
|
Reference in New Issue
Block a user