From cba0092196bff42e956de6a2c364e3951541a9d6 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 21 Nov 2016 17:23:10 +0400 Subject: [PATCH] MDEV-11294 Move definitions of Derivation, DTCollation, Type_std_attributes from field.h and item.h to sql_type.h --- sql/field.h | 28 ++++---- sql/item.h | 153 ---------------------------------------- sql/item_func.cc | 4 +- sql/sql_type.h | 180 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 196 insertions(+), 169 deletions(-) diff --git a/sql/field.h b/sql/field.h index 36ac7f5f5280e..76cdfe633198d 100644 --- a/sql/field.h +++ b/sql/field.h @@ -31,6 +31,7 @@ #include "my_decimal.h" /* my_decimal */ #include "sql_error.h" /* Sql_condition */ #include "compat56.h" +#include "sql_type.h" /* Type_std_attributes */ class Send_field; class Copy_field; @@ -403,25 +404,10 @@ class Value_source }; -enum Derivation -{ - DERIVATION_IGNORABLE= 6, - DERIVATION_NUMERIC= 5, - DERIVATION_COERCIBLE= 4, - DERIVATION_SYSCONST= 3, - DERIVATION_IMPLICIT= 2, - DERIVATION_NONE= 1, - DERIVATION_EXPLICIT= 0 -}; - - #define STORAGE_TYPE_MASK 7 #define COLUMN_FORMAT_MASK 7 #define COLUMN_FORMAT_SHIFT 3 -#define my_charset_numeric my_charset_latin1 -#define MY_REPERTOIRE_NUMERIC MY_REPERTOIRE_ASCII - /* The length of the header part for each virtual column in the .frm file */ #define FRM_VCOL_OLD_HEADER_SIZE(b) (3 + MY_TEST(b)) #define FRM_VCOL_NEW_BASE_SIZE 16 @@ -796,6 +782,18 @@ class Field: public Value_source uchar null_bit_arg, utype unireg_check_arg, const char *field_name_arg); virtual ~Field() {} + + DTCollation dtcollation() const + { + return DTCollation(charset(), derivation(), repertoire()); + } + Type_std_attributes type_std_attributes() const + { + return Type_std_attributes(field_length, decimals(), + MY_TEST(flags & UNSIGNED_FLAG), + dtcollation()); + } + /** Convenience definition of a copy function returned by Field::get_copy_func() diff --git a/sql/item.h b/sql/item.h index e0634e63c9bd7..b08788903a8ba 100644 --- a/sql/item.h +++ b/sql/item.h @@ -113,124 +113,11 @@ bool mark_unsupported_function(const char *w1, const char *w2, #define SPLIT_SUM_SKIP_REGISTERED 1 /* Skip registered funcs */ #define SPLIT_SUM_SELECT 2 /* SELECT item; Split all parts */ -/* - "Declared Type Collation" - A combination of collation and its derivation. - - Flags for collation aggregation modes: - MY_COLL_ALLOW_SUPERSET_CONV - allow conversion to a superset - MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value - (i.e. constant). - MY_COLL_ALLOW_CONV - allow any kind of conversion - (combination of the above two) - MY_COLL_ALLOW_NUMERIC_CONV - if all items were numbers, convert to - @@character_set_connection - MY_COLL_DISALLOW_NONE - don't allow return DERIVATION_NONE - (e.g. when aggregating for comparison) - MY_COLL_CMP_CONV - combination of MY_COLL_ALLOW_CONV - and MY_COLL_DISALLOW_NONE -*/ - -#define MY_COLL_ALLOW_SUPERSET_CONV 1 -#define MY_COLL_ALLOW_COERCIBLE_CONV 2 -#define MY_COLL_DISALLOW_NONE 4 -#define MY_COLL_ALLOW_NUMERIC_CONV 8 - -#define MY_COLL_ALLOW_CONV (MY_COLL_ALLOW_SUPERSET_CONV | MY_COLL_ALLOW_COERCIBLE_CONV) -#define MY_COLL_CMP_CONV (MY_COLL_ALLOW_CONV | MY_COLL_DISALLOW_NONE) #define NO_EXTRACTION_FL (1 << 6) #define FULL_EXTRACTION_FL (1 << 7) #define EXTRACTION_MASK (NO_EXTRACTION_FL | FULL_EXTRACTION_FL) -class DTCollation { -public: - CHARSET_INFO *collation; - enum Derivation derivation; - uint repertoire; - - void set_repertoire_from_charset(CHARSET_INFO *cs) - { - repertoire= cs->state & MY_CS_PUREASCII ? - MY_REPERTOIRE_ASCII : MY_REPERTOIRE_UNICODE30; - } - DTCollation() - { - collation= &my_charset_bin; - derivation= DERIVATION_NONE; - repertoire= MY_REPERTOIRE_UNICODE30; - } - DTCollation(CHARSET_INFO *collation_arg, Derivation derivation_arg) - { - collation= collation_arg; - derivation= derivation_arg; - set_repertoire_from_charset(collation_arg); - } - DTCollation(CHARSET_INFO *collation_arg, - Derivation derivation_arg, - uint repertoire_arg) - :collation(collation_arg), - derivation(derivation_arg), - repertoire(repertoire_arg) - { } - void set(const DTCollation &dt) - { - collation= dt.collation; - derivation= dt.derivation; - repertoire= dt.repertoire; - } - void set(CHARSET_INFO *collation_arg, Derivation derivation_arg) - { - collation= collation_arg; - derivation= derivation_arg; - set_repertoire_from_charset(collation_arg); - } - void set(CHARSET_INFO *collation_arg, - Derivation derivation_arg, - uint repertoire_arg) - { - collation= collation_arg; - derivation= derivation_arg; - repertoire= repertoire_arg; - } - void set_numeric() - { - collation= &my_charset_numeric; - derivation= DERIVATION_NUMERIC; - repertoire= MY_REPERTOIRE_NUMERIC; - } - void set(CHARSET_INFO *collation_arg) - { - collation= collation_arg; - set_repertoire_from_charset(collation_arg); - } - void set(Derivation derivation_arg) - { derivation= derivation_arg; } - bool aggregate(const DTCollation &dt, uint flags= 0); - bool set(DTCollation &dt1, DTCollation &dt2, uint flags= 0) - { set(dt1); return aggregate(dt2, flags); } - const char *derivation_name() const - { - switch(derivation) - { - case DERIVATION_NUMERIC: return "NUMERIC"; - case DERIVATION_IGNORABLE: return "IGNORABLE"; - case DERIVATION_COERCIBLE: return "COERCIBLE"; - case DERIVATION_IMPLICIT: return "IMPLICIT"; - case DERIVATION_SYSCONST: return "SYSCONST"; - case DERIVATION_EXPLICIT: return "EXPLICIT"; - case DERIVATION_NONE: return "NONE"; - default: return "UNKNOWN"; - } - } - int sortcmp(const String *s, const String *t) const - { - return collation->coll->strnncollsp(collation, - (uchar *) s->ptr(), s->length(), - (uchar *) t->ptr(), t->length()); - } -}; - void dummy_error_processor(THD *thd, void *data); @@ -601,46 +488,6 @@ class String_copier_for_item: public String_copier }; -/** - A class to store type attributes for the standard data types. - Does not include attributes for the extended data types - such as ENUM, SET, GEOMETRY. -*/ -class Type_std_attributes -{ -public: - DTCollation collation; - uint decimals; - /* - The maximum value length in characters multiplied by collation->mbmaxlen. - Almost always it's the maximum value length in bytes. - */ - uint32 max_length; - bool unsigned_flag; - Type_std_attributes() - :collation(&my_charset_bin, DERIVATION_COERCIBLE), - decimals(0), max_length(0), unsigned_flag(false) - { } - Type_std_attributes(const Type_std_attributes *other) - :collation(other->collation), - decimals(other->decimals), - max_length(other->max_length), - unsigned_flag(other->unsigned_flag) - { } - void set(const Type_std_attributes *other) - { - *this= *other; - } - void set(const Field *field) - { - decimals= field->decimals(); - max_length= field->field_length; - collation.set(field->charset()); - unsigned_flag= MY_TEST(field->flags & UNSIGNED_FLAG); - } -}; - - class Item: public Value_source, public Type_std_attributes { diff --git a/sql/item_func.cc b/sql/item_func.cc index 9bafe25e43113..01d4e81f8356a 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -6611,7 +6611,9 @@ void Item_func_sp::fix_length_and_dec() DBUG_ENTER("Item_func_sp::fix_length_and_dec"); DBUG_ASSERT(sp_result_field); - Type_std_attributes::set(sp_result_field); + Type_std_attributes::set(sp_result_field->type_std_attributes()); + // There is a bug in the line below. See MDEV-11292 for details. + collation.derivation= DERIVATION_COERCIBLE; maybe_null= 1; DBUG_VOID_RETURN; diff --git a/sql/sql_type.h b/sql/sql_type.h index 4b05a4663c428..de5c31a87e1b9 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -30,6 +30,186 @@ class Sort_param; struct TABLE; struct SORT_FIELD_ATTR; + +/* + Flags for collation aggregation modes, used in TDCollation::agg(): + + MY_COLL_ALLOW_SUPERSET_CONV - allow conversion to a superset + MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value + (i.e. constant). + MY_COLL_ALLOW_CONV - allow any kind of conversion + (combination of the above two) + MY_COLL_ALLOW_NUMERIC_CONV - if all items were numbers, convert to + @@character_set_connection + MY_COLL_DISALLOW_NONE - don't allow return DERIVATION_NONE + (e.g. when aggregating for comparison) + MY_COLL_CMP_CONV - combination of MY_COLL_ALLOW_CONV + and MY_COLL_DISALLOW_NONE +*/ + +#define MY_COLL_ALLOW_SUPERSET_CONV 1 +#define MY_COLL_ALLOW_COERCIBLE_CONV 2 +#define MY_COLL_DISALLOW_NONE 4 +#define MY_COLL_ALLOW_NUMERIC_CONV 8 + +#define MY_COLL_ALLOW_CONV (MY_COLL_ALLOW_SUPERSET_CONV | MY_COLL_ALLOW_COERCIBLE_CONV) +#define MY_COLL_CMP_CONV (MY_COLL_ALLOW_CONV | MY_COLL_DISALLOW_NONE) + + +#define my_charset_numeric my_charset_latin1 +#define MY_REPERTOIRE_NUMERIC MY_REPERTOIRE_ASCII + + +enum Derivation +{ + DERIVATION_IGNORABLE= 6, + DERIVATION_NUMERIC= 5, + DERIVATION_COERCIBLE= 4, + DERIVATION_SYSCONST= 3, + DERIVATION_IMPLICIT= 2, + DERIVATION_NONE= 1, + DERIVATION_EXPLICIT= 0 +}; + + +/** + "Declared Type Collation" + A combination of collation and its derivation. +*/ + +class DTCollation { +public: + CHARSET_INFO *collation; + enum Derivation derivation; + uint repertoire; + + void set_repertoire_from_charset(CHARSET_INFO *cs) + { + repertoire= cs->state & MY_CS_PUREASCII ? + MY_REPERTOIRE_ASCII : MY_REPERTOIRE_UNICODE30; + } + DTCollation() + { + collation= &my_charset_bin; + derivation= DERIVATION_NONE; + repertoire= MY_REPERTOIRE_UNICODE30; + } + DTCollation(CHARSET_INFO *collation_arg, Derivation derivation_arg) + { + collation= collation_arg; + derivation= derivation_arg; + set_repertoire_from_charset(collation_arg); + } + DTCollation(CHARSET_INFO *collation_arg, + Derivation derivation_arg, + uint repertoire_arg) + :collation(collation_arg), + derivation(derivation_arg), + repertoire(repertoire_arg) + { } + void set(const DTCollation &dt) + { + collation= dt.collation; + derivation= dt.derivation; + repertoire= dt.repertoire; + } + void set(CHARSET_INFO *collation_arg, Derivation derivation_arg) + { + collation= collation_arg; + derivation= derivation_arg; + set_repertoire_from_charset(collation_arg); + } + void set(CHARSET_INFO *collation_arg, + Derivation derivation_arg, + uint repertoire_arg) + { + collation= collation_arg; + derivation= derivation_arg; + repertoire= repertoire_arg; + } + void set_numeric() + { + collation= &my_charset_numeric; + derivation= DERIVATION_NUMERIC; + repertoire= MY_REPERTOIRE_NUMERIC; + } + void set(CHARSET_INFO *collation_arg) + { + collation= collation_arg; + set_repertoire_from_charset(collation_arg); + } + void set(Derivation derivation_arg) + { derivation= derivation_arg; } + bool aggregate(const DTCollation &dt, uint flags= 0); + bool set(DTCollation &dt1, DTCollation &dt2, uint flags= 0) + { set(dt1); return aggregate(dt2, flags); } + const char *derivation_name() const + { + switch(derivation) + { + case DERIVATION_NUMERIC: return "NUMERIC"; + case DERIVATION_IGNORABLE: return "IGNORABLE"; + case DERIVATION_COERCIBLE: return "COERCIBLE"; + case DERIVATION_IMPLICIT: return "IMPLICIT"; + case DERIVATION_SYSCONST: return "SYSCONST"; + case DERIVATION_EXPLICIT: return "EXPLICIT"; + case DERIVATION_NONE: return "NONE"; + default: return "UNKNOWN"; + } + } + int sortcmp(const String *s, const String *t) const + { + return collation->coll->strnncollsp(collation, + (uchar *) s->ptr(), s->length(), + (uchar *) t->ptr(), t->length()); + } +}; + + +/** + A class to store type attributes for the standard data types. + Does not include attributes for the extended data types + such as ENUM, SET, GEOMETRY. +*/ +class Type_std_attributes +{ +public: + DTCollation collation; + uint decimals; + /* + The maximum value length in characters multiplied by collation->mbmaxlen. + Almost always it's the maximum value length in bytes. + */ + uint32 max_length; + bool unsigned_flag; + Type_std_attributes() + :collation(&my_charset_bin, DERIVATION_COERCIBLE), + decimals(0), max_length(0), unsigned_flag(false) + { } + Type_std_attributes(const Type_std_attributes *other) + :collation(other->collation), + decimals(other->decimals), + max_length(other->max_length), + unsigned_flag(other->unsigned_flag) + { } + Type_std_attributes(uint32 max_length_arg, uint decimals_arg, + bool unsigned_flag_arg, const DTCollation &dtc) + :collation(dtc), + decimals(decimals_arg), + max_length(max_length_arg), + unsigned_flag(unsigned_flag_arg) + { } + void set(const Type_std_attributes *other) + { + *this= *other; + } + void set(const Type_std_attributes &other) + { + *this= other; + } +}; + + class Type_handler { protected: