mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-9217 Split Item::tmp_table_field_from_field_type() into virtual methods in Type_handler
- Adding Type_handler::make_table_field() and moving pieces of the code from Item::tmp_table_field_from_field_type() to virtual implementations for various type handlers. - Adding a new Type_all_attributes, to access to Item's extended attributes, such as decimal_precision() and geometry_type(). - Adding a new class Record_addr, to pass record related information to Type_handler methods (ptr, null_ptr and null_bit) as a single structure. Note, later it will possibly be extended for BIT-alike field purposes, by adding new members (bit_ptr_arg, bit_ofs_arg). - Moving the code from Field_new_decimal::create_from_item() to Type_handler_newdecimal::make_table_field(). - Removing Field_new_decimal() and Field_geom() helper constructor variants that were used for temporary field creation. - Adding Item_field::type_handler(), Field::type_handler() and Field_blob::type_handler() to return correct type handlers for blob variants, according to Field_blob::packlength. - Adding Type_handler_blob_common, as a common parent for Type_handler_tiny_blob, Type_handler_blob, Type_handler_medium_blob and Type_handler_long_blob. - Implementing Type_handler_blob_common::Item_hybrid_func_fix_attributes(). It's needed for cases when TEXT variants of different character sets are mixed in LEAST, GREATEST, CASE and its abreviations (IF, IFNULL, COALESCE), e.g.: CREATE TABLE t1 ( a TINYTEXT CHARACTER SET latin1, b TINYTEXT CHARACTER SET utf8 ); CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1; Type handler aggregation returns TINYTEXT as a common data type for the two columns. But as conversion from latin1 to utf8 happens for "a", the maximum possible length of "a" grows from 255 to 255*3. Type_handler_blob_common::Item_hybrid_func_fix_attributes() makes sure to update the blob type handler according to max_length. - Adding Type_handler::blob_type_handler(uint max_octet_length). - Adding a few m_type_aggregator_for_result.add() pairs, because now Item_xxx::type_handler() can return pointers to type_handler_tiny_blob, type_handler_blob, type_handler_medium_blob, type_handler_long_blob. Before the patch only type_handler_blob was possible result of type_handler(). - Making type_handler_tiny_blob, type_handler_blob, type_handler_medium_blob, type_handler_long_blob public. - Removing the condition in Item_sum_avg::create_tmp_field() checking Item_sum_avg::result_type() against DECIMAL_RESULT. Now both REAL_RESULT and DECIMAL_RESULT are symmetrically handled by tmp_table_field_from_field_type(). - Removing Item_geometry_func::create_field_for_create_select(), as the inherited version perfectly works. - Fixing Item_func_as_wkb::field_type() to return MYSQL_TYPE_LONG_BLOB rather than MYSQL_TYPE_BLOB. It's needed to make sure that tmp_table_field_from_field_type() creates a LONGBLOB field for AsWKB(). - Fixing Item_func_as_wkt::fix_length_and_dec() to set max_length to UINT32_MAX rather than MAX_BLOB_WIDTH, to make sure that tmp_table_field_from_field_type() creates a LONGTEXT field for AsWKT(). - Removing Item_func_set_user_var::create_field_for_create_select(), as the inherited version works fine. - Adding Item_func_get_user_var::create_field_for_create_select() to make sure that "CREATE TABLE t1 AS SELECT @string_user variable" always creates a field of LONGTEXT/LONGBLOB type. - Item_func_ifnull::create_field_for_create_select() behavior has changed. Before the patch it passed set_blob_packflag=false, which meant to create LONGBLOB for all blob variants. Now it takes into account max_length, which gives better column data types for: CREATE TABLE t2 AS SELECT IFNULL(blob_column1, blob_column2) FROM t1; - Fixing Item_func_nullif::fix_length_and_dec() to use set_handler(args[2]->type_handler()) instead of set_handler_by_field_type(args[2]->field_type()). This is needed to distinguish between BLOB variants. - Implementing Item_blob::type_handler(), to make sure to create proper BLOB field variant, according to max_length, for queries like: CREATE TABLE t1 AS SELECT some_blob_field FROM INFORMATION_SCHEMA.SOME_TABLE; - Fixing Item_field::real_type_handler() to make sure that the code aggregating fields for UNION gets a proper BLOB variant type handler from fields. - Adding a special code into Item_type_holder::make_field_by_type(), to make sure that after aggregating field types it also properly takes into account max_length when mixing TEXT variants of different character sets and chooses a proper TEXT variant: CREATE TABLE t1 ( a TINYTEXT CHARACTER SET latin1, b TINYTEXT CHARACTER SET utf8 ); CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1; - Adding tests, for better coverage of IFNULL, NULLIF, UNION. - The fact that tmp_table_field_from_field_type() now takes into account BLOB variants (instead of always creating LONGBLOB), tests results for WEIGHT_STRING() and NULLIF() and UNION have become more precise.
This commit is contained in:
186
sql/sql_type.h
186
sql/sql_type.h
@ -314,6 +314,27 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class Type_all_attributes: public Type_std_attributes
|
||||
{
|
||||
public:
|
||||
Type_all_attributes()
|
||||
:Type_std_attributes()
|
||||
{ }
|
||||
Type_all_attributes(const Type_all_attributes *other)
|
||||
:Type_std_attributes(other)
|
||||
{ }
|
||||
// Returns total number of decimal digits
|
||||
virtual uint decimal_precision() const= 0;
|
||||
/*
|
||||
Field::geometry_type is not visible here.
|
||||
Let's use an "uint" wrapper for now. Later when we move Field_geom
|
||||
into a plugin, this method will be replaced to some generic
|
||||
datatype indepented method.
|
||||
*/
|
||||
virtual uint uint_geometry_type() const= 0;
|
||||
};
|
||||
|
||||
|
||||
class Name: private LEX_CSTRING
|
||||
{
|
||||
public:
|
||||
@ -327,6 +348,31 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class Record_addr
|
||||
{
|
||||
public:
|
||||
uchar *ptr; // Position to field in record
|
||||
/**
|
||||
Byte where the @c NULL bit is stored inside a record. If this Field is a
|
||||
@c NOT @c NULL field, this member is @c NULL.
|
||||
*/
|
||||
uchar *null_ptr;
|
||||
uchar null_bit; // Bit used to test null bit
|
||||
Record_addr(uchar *ptr_arg,
|
||||
uchar *null_ptr_arg,
|
||||
uchar null_bit_arg)
|
||||
:ptr(ptr_arg),
|
||||
null_ptr(null_ptr_arg),
|
||||
null_bit(null_bit_arg)
|
||||
{ }
|
||||
Record_addr(bool maybe_null)
|
||||
:ptr(NULL),
|
||||
null_ptr(maybe_null ? (uchar*) "" : 0),
|
||||
null_bit(0)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
class Type_handler
|
||||
{
|
||||
protected:
|
||||
@ -342,6 +388,7 @@ protected:
|
||||
bool
|
||||
Item_func_or_sum_illegal_param(const Item_func_or_sum *) const;
|
||||
public:
|
||||
static const Type_handler *blob_type_handler(uint max_octet_length);
|
||||
static const Type_handler *string_type_handler(uint max_octet_length);
|
||||
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);
|
||||
@ -431,6 +478,14 @@ public:
|
||||
virtual Field *make_conversion_table_field(TABLE *TABLE,
|
||||
uint metadata,
|
||||
const Field *target) const= 0;
|
||||
virtual Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const= 0;
|
||||
Field *make_and_init_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
virtual void make_sort_key(uchar *to, Item *item,
|
||||
const SORT_FIELD_ATTR *sort_field,
|
||||
Sort_param *param) const= 0;
|
||||
@ -630,6 +685,14 @@ public:
|
||||
DBUG_ASSERT(0);
|
||||
return NULL;
|
||||
}
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const
|
||||
{
|
||||
DBUG_ASSERT(0);
|
||||
return NULL;
|
||||
}
|
||||
void make_sort_key(uchar *to, Item *item,
|
||||
const SORT_FIELD_ATTR *sort_field,
|
||||
Sort_param *param) const
|
||||
@ -1179,6 +1242,10 @@ public:
|
||||
uint32 max_display_length(const Item *item) const { return 4; }
|
||||
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1192,6 +1259,10 @@ public:
|
||||
uint32 max_display_length(const Item *item) const { return 6; }
|
||||
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1208,6 +1279,10 @@ public:
|
||||
}
|
||||
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1221,6 +1296,10 @@ public:
|
||||
uint32 max_display_length(const Item *item) const { return 20; }
|
||||
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1234,6 +1313,10 @@ public:
|
||||
uint32 max_display_length(const Item *item) const { return 8; }
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1247,6 +1330,10 @@ public:
|
||||
uint32 max_display_length(const Item *item) const;
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1264,6 +1351,10 @@ public:
|
||||
}
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1278,6 +1369,10 @@ public:
|
||||
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const;
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1291,6 +1386,10 @@ public:
|
||||
uint32 max_display_length(const Item *item) const { return 53; }
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1321,6 +1420,10 @@ public:
|
||||
virtual ~Type_handler_time() {}
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1331,6 +1434,10 @@ public:
|
||||
enum_field_types real_field_type() const { return MYSQL_TYPE_TIME2; }
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1367,6 +1474,10 @@ public:
|
||||
virtual ~Type_handler_date() {}
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1376,6 +1487,10 @@ public:
|
||||
virtual ~Type_handler_newdate() {}
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1402,6 +1517,10 @@ public:
|
||||
virtual ~Type_handler_datetime() {}
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1412,6 +1531,10 @@ public:
|
||||
enum_field_types real_field_type() const { return MYSQL_TYPE_DATETIME2; }
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1438,6 +1561,10 @@ public:
|
||||
virtual ~Type_handler_timestamp() {}
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1448,6 +1575,10 @@ public:
|
||||
enum_field_types real_field_type() const { return MYSQL_TYPE_TIMESTAMP2; }
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1460,6 +1591,10 @@ public:
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_DECIMAL; }
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1472,6 +1607,10 @@ public:
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1486,6 +1625,10 @@ public:
|
||||
uint32 max_display_length(const Item *item) const { return 0; }
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1499,6 +1642,10 @@ public:
|
||||
bool is_param_long_data_type() const { return true; }
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1512,6 +1659,10 @@ public:
|
||||
bool is_param_long_data_type() const { return true; }
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1525,6 +1676,8 @@ public:
|
||||
return false; // Materialization does not work with BLOB columns
|
||||
}
|
||||
bool is_param_long_data_type() const { return true; }
|
||||
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
Item **items, uint nitems) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1537,6 +1690,10 @@ public:
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_TINY_BLOB; }
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1549,6 +1706,10 @@ public:
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_MEDIUM_BLOB; }
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1561,6 +1722,10 @@ public:
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_LONG_BLOB; }
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1573,6 +1738,10 @@ public:
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1593,6 +1762,11 @@ public:
|
||||
}
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
|
||||
bool is_traditional_type() const
|
||||
{
|
||||
return false;
|
||||
@ -1629,6 +1803,10 @@ public:
|
||||
virtual enum_field_types real_field_type() const { return MYSQL_TYPE_ENUM; }
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1642,6 +1820,10 @@ public:
|
||||
virtual enum_field_types real_field_type() const { return MYSQL_TYPE_SET; }
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
Field *make_table_field(const LEX_CSTRING *name,
|
||||
const Record_addr &addr,
|
||||
const Type_all_attributes &attr,
|
||||
TABLE *table) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1742,6 +1924,10 @@ extern Type_handler_time2 type_handler_time2;
|
||||
extern Type_handler_newdate type_handler_newdate;
|
||||
extern Type_handler_datetime2 type_handler_datetime2;
|
||||
|
||||
extern Type_handler_tiny_blob type_handler_tiny_blob;
|
||||
extern Type_handler_blob type_handler_blob;
|
||||
extern Type_handler_medium_blob type_handler_medium_blob;
|
||||
extern Type_handler_long_blob type_handler_long_blob;
|
||||
|
||||
class Type_aggregator
|
||||
{
|
||||
|
Reference in New Issue
Block a user