diff options
Diffstat (limited to 'sql/field.h')
-rw-r--r-- | sql/field.h | 770 |
1 files changed, 533 insertions, 237 deletions
diff --git a/sql/field.h b/sql/field.h index 14f14afdaf7..bfdb06984af 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; @@ -364,24 +365,25 @@ public: Subst_constraint m_subst_constraint; /* Comparison type. - Impostant only when ANY_SUBSTS. + Important only when ANY_SUBSTS. */ - Item_result m_compare_type; + const Type_handler *m_compare_handler; /* Collation of the comparison operation. Important only when ANY_SUBST. */ CHARSET_INFO *m_compare_collation; public: - Context(Subst_constraint subst, Item_result type, CHARSET_INFO *cs) + Context(Subst_constraint subst, const Type_handler *h, CHARSET_INFO *cs) :m_subst_constraint(subst), - m_compare_type(type), - m_compare_collation(cs) { } + m_compare_handler(h), + m_compare_collation(cs) + { DBUG_ASSERT(h == h->type_handler_for_comparison()); } Subst_constraint subst_constraint() const { return m_subst_constraint; } - Item_result compare_type() const + const Type_handler *compare_type_handler() const { DBUG_ASSERT(m_subst_constraint == ANY_SUBST); - return m_compare_type; + return m_compare_handler; } CHARSET_INFO *compare_collation() const { @@ -393,35 +395,21 @@ public: { // Use this to request only exact value, no invariants. public: Context_identity() - :Context(IDENTITY_SUBST, STRING_RESULT, &my_charset_bin) { } + :Context(IDENTITY_SUBST, &type_handler_long_blob, &my_charset_bin) { } }; class Context_boolean: public Context { // Use this when an item is [a part of] a boolean expression public: - Context_boolean() :Context(ANY_SUBST, INT_RESULT, &my_charset_bin) { } + Context_boolean() + :Context(ANY_SUBST, &type_handler_longlong, &my_charset_bin) { } }; }; -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 @@ -474,16 +462,6 @@ inline bool is_temporal_type_with_date(enum_field_types type) /** - Recognizer for concrete data type (called real_type for some reason), - returning true if it is one of the TIMESTAMP types. -*/ -inline bool is_timestamp_type(enum_field_types type) -{ - return type == MYSQL_TYPE_TIMESTAMP || type == MYSQL_TYPE_TIMESTAMP2; -} - - -/** Convert temporal real types as retuned by field->real_type() to field type as returned by field->type(). @@ -539,27 +517,6 @@ inline bool is_temporal_type(enum_field_types type) } -/** - Tests if field type is temporal and has time part, - i.e. represents TIME, DATETIME or TIMESTAMP types in SQL. - - @param type Field type, as returned by field->type(). - @retval true If field type is temporal type with time part. - @retval false If field type is not temporal type with time part. -*/ -inline bool is_temporal_type_with_time(enum_field_types type) -{ - switch (type) - { - case MYSQL_TYPE_TIME: - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_TIMESTAMP: - return true; - default: - return false; - } -} - enum enum_vcol_info_type { VCOL_GENERATED_VIRTUAL, VCOL_GENERATED_STORED, @@ -629,7 +586,7 @@ public: bool stored_in_db; bool utf8; /* Already in utf8 */ Item *expr; - LEX_STRING name; /* Name of constraint */ + LEX_CSTRING name; /* Name of constraint */ uint flags; Virtual_column_info() @@ -721,12 +678,12 @@ public: */ TABLE *table; // Pointer for table TABLE *orig_table; // Pointer to original table - const char * const *table_name; - const char *field_name; + const char * const *table_name; // Pointer to alias in TABLE + LEX_CSTRING field_name; + LEX_CSTRING comment; /** reference to the list of options or NULL */ engine_option_value *option_list; ha_field_option_struct *option_struct; /* structure with parsed options */ - LEX_STRING comment; /* Field is part of the following keys */ key_map key_start, part_of_key, part_of_key_not_clustered; @@ -815,8 +772,20 @@ public: Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, - const char *field_name_arg); + const LEX_CSTRING *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() @@ -847,6 +816,8 @@ public: enum_check_fields check_level); int store(const LEX_STRING *ls, CHARSET_INFO *cs) { return store(ls->str, ls->length, cs); } + int store(const LEX_CSTRING *ls, CHARSET_INFO *cs) + { return store(ls->str, ls->length, cs); } virtual double val_real(void)=0; virtual longlong val_int(void)=0; virtual bool val_bool(void)= 0; @@ -872,11 +843,15 @@ public: to be quoted when used in constructing an SQL query. */ virtual bool str_needs_quotes() { return FALSE; } - virtual Item_result result_type () const=0; - virtual Item_result cmp_type () const { return result_type(); } - static bool type_can_have_key_part(enum_field_types); + Item_result result_type () const + { + return type_handler()->result_type(); + } + Item_result cmp_type () const + { + return type_handler()->cmp_type(); + } static enum_field_types field_type_merge(enum_field_types, enum_field_types); - static Item_result result_merge_type(enum_field_types); virtual bool eq(Field *field) { return (ptr == field->ptr && null_ptr == field->null_ptr && @@ -989,8 +964,15 @@ public: virtual bool zero_pack() const { return 1; } virtual enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; } virtual uint32 key_length() const { return pack_length(); } - virtual enum_field_types type() const =0; - virtual enum_field_types real_type() const { return type(); } + virtual const Type_handler *type_handler() const= 0; + virtual enum_field_types type() const + { + return type_handler()->field_type(); + } + virtual enum_field_types real_type() const + { + return type_handler()->real_field_type(); + } virtual enum_field_types binlog_type() const { /* @@ -1307,6 +1289,7 @@ public: uint fill_cache_field(struct st_cache_field *copy); virtual bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); bool get_time(MYSQL_TIME *ltime) { return get_date(ltime, TIME_TIME_ONLY); } + virtual TYPELIB *get_typelib() const { return NULL; } virtual CHARSET_INFO *charset(void) const { return &my_charset_bin; } virtual CHARSET_INFO *charset_for_protocol(void) const { return binary() ? &my_charset_bin : charset(); } @@ -1315,9 +1298,6 @@ public: virtual enum Derivation derivation(void) const { return DERIVATION_IMPLICIT; } virtual uint repertoire(void) const { return MY_REPERTOIRE_UNICODE30; } - virtual void set_derivation(enum Derivation derivation_arg, - uint repertoire_arg) - { } virtual int set_time() { return 1; } bool set_warning(Sql_condition::enum_warning_level, unsigned int code, int cuted_increment) const; @@ -1330,7 +1310,7 @@ protected: { return set_warning(Sql_condition::WARN_LEVEL_NOTE, code, cuted_increment); } - void set_datetime_warning(Sql_condition::enum_warning_level, uint code, + void set_datetime_warning(Sql_condition::enum_warning_level, uint code, const ErrConv *str, timestamp_type ts_type, int cuted_increment) const; void set_datetime_warning(uint code, @@ -1546,7 +1526,7 @@ protected: return to + size; } - const uchar *unpack_int(uchar* to, const uchar *from, + const uchar *unpack_int(uchar* to, const uchar *from, const uchar *from_end, size_t size) { if (from + size > from_end) @@ -1605,9 +1585,8 @@ public: bool zerofill,unsigned_flag; // Purify cannot handle bit fields Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, - const char *field_name_arg, + const LEX_CSTRING *field_name_arg, uint8 dec_arg, bool zero_arg, bool unsigned_arg); - enum Item_result result_type () const { return INT_RESULT; } enum Derivation derivation(void) const { return DERIVATION_NUMERIC; } uint repertoire(void) const { return MY_REPERTOIRE_NUMERIC; } CHARSET_INFO *charset(void) const { return &my_charset_numeric; } @@ -1669,8 +1648,8 @@ public: const Item_equal *item_equal); Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, - const char *field_name_arg, CHARSET_INFO *charset); - Item_result result_type () const { return STRING_RESULT; } + const LEX_CSTRING *field_name_arg, + const DTCollation &collation); uint decimals() const { return NOT_FIXED_DEC; } int save_in_field(Field *to) { return save_in_field_str(to); } bool memcpy_field_possible(const Field *from) const @@ -1690,12 +1669,6 @@ public: uint repertoire(void) const { return field_repertoire; } CHARSET_INFO *charset(void) const { return field_charset; } enum Derivation derivation(void) const { return field_derivation; } - void set_derivation(enum Derivation derivation_arg, - uint repertoire_arg) - { - field_derivation= derivation_arg; - field_repertoire= repertoire_arg; - } bool binary() const { return field_charset == &my_charset_bin; } uint32 max_display_length() { return field_length; } friend class Create_field; @@ -1737,9 +1710,10 @@ protected: public: Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, - const char *field_name_arg, CHARSET_INFO *charset_arg) + const LEX_CSTRING *field_name_arg, + const DTCollation &collation) :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, - field_name_arg, charset_arg) + field_name_arg, collation) {} int store_decimal(const my_decimal *d); @@ -1772,13 +1746,12 @@ public: Field_real(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, - const char *field_name_arg, + const LEX_CSTRING *field_name_arg, uint8 dec_arg, bool zero_arg, bool unsigned_arg) :Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, dec_arg, zero_arg, unsigned_arg), not_fixed(dec_arg >= FLOATING_POINT_DECIMALS) {} - Item_result result_type () const { return REAL_RESULT; } Copy_func *get_copy_func(const Field *from) const { return do_field_real; @@ -1809,13 +1782,13 @@ class Field_decimal :public Field_real { public: Field_decimal(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg, + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, uint8 dec_arg,bool zero_arg,bool unsigned_arg) :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, dec_arg, zero_arg, unsigned_arg) {} - enum_field_types type() const { return MYSQL_TYPE_DECIMAL;} + const Type_handler *type_handler() const { return &type_handler_olddecimal; } enum ha_base_keytype key_type() const { return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; } Copy_func *get_copy_func(const Field *from) const @@ -1857,14 +1830,11 @@ public: */ Field_new_decimal(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg, + enum utype unireg_check_arg, + const LEX_CSTRING *field_name_arg, uint8 dec_arg, bool zero_arg, bool unsigned_arg); - Field_new_decimal(uint32 len_arg, bool maybe_null_arg, - const char *field_name_arg, uint8 dec_arg, - bool unsigned_arg); - enum_field_types type() const { return MYSQL_TYPE_NEWDECIMAL;} + const Type_handler *type_handler() const { return &type_handler_newdecimal; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; } - Item_result result_type () const { return DECIMAL_RESULT; } Copy_func *get_copy_func(const Field *from) const { // if (from->real_type() == MYSQL_TYPE_BIT) // QQ: why? @@ -1914,7 +1884,6 @@ public: uint16 mflags, int *order_var); uint is_equal(Create_field *new_field); virtual const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data); - static Field *create_from_item(MEM_ROOT *root, Item *); Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item); }; @@ -1923,13 +1892,13 @@ class Field_tiny :public Field_num { public: Field_tiny(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg, + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, bool zero_arg, bool unsigned_arg) :Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, 0, zero_arg,unsigned_arg) {} - enum_field_types type() const { return MYSQL_TYPE_TINY;} + const Type_handler *type_handler() const { return &type_handler_tiny; } enum ha_base_keytype key_type() const { return unsigned_flag ? HA_KEYTYPE_BINARY : HA_KEYTYPE_INT8; } int store(const char *to,uint length,CHARSET_INFO *charset); @@ -1967,18 +1936,19 @@ class Field_short :public Field_num { public: Field_short(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg, + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, bool zero_arg, bool unsigned_arg) :Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, 0, zero_arg,unsigned_arg) {} - Field_short(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, + Field_short(uint32 len_arg,bool maybe_null_arg, + const LEX_CSTRING *field_name_arg, bool unsigned_arg) :Field_num((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg, 0, 0, unsigned_arg) {} - enum_field_types type() const { return MYSQL_TYPE_SHORT;} + const Type_handler *type_handler() const { return &type_handler_short; } enum ha_base_keytype key_type() const { return unsigned_flag ? HA_KEYTYPE_USHORT_INT : HA_KEYTYPE_SHORT_INT;} int store(const char *to,uint length,CHARSET_INFO *charset); @@ -2007,13 +1977,13 @@ class Field_medium :public Field_num { public: Field_medium(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg, + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, bool zero_arg, bool unsigned_arg) :Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, 0, zero_arg,unsigned_arg) {} - enum_field_types type() const { return MYSQL_TYPE_INT24;} + const Type_handler *type_handler() const { return &type_handler_int24; } enum ha_base_keytype key_type() const { return unsigned_flag ? HA_KEYTYPE_UINT24 : HA_KEYTYPE_INT24; } int store(const char *to,uint length,CHARSET_INFO *charset); @@ -2041,18 +2011,19 @@ class Field_long :public Field_num { public: Field_long(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg, + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, bool zero_arg, bool unsigned_arg) :Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, 0, zero_arg,unsigned_arg) {} - Field_long(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, + Field_long(uint32 len_arg,bool maybe_null_arg, + const LEX_CSTRING *field_name_arg, bool unsigned_arg) :Field_num((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg,0,0,unsigned_arg) {} - enum_field_types type() const { return MYSQL_TYPE_LONG;} + const Type_handler *type_handler() const { return &type_handler_long; } enum ha_base_keytype key_type() const { return unsigned_flag ? HA_KEYTYPE_ULONG_INT : HA_KEYTYPE_LONG_INT; } int store(const char *to,uint length,CHARSET_INFO *charset); @@ -2086,19 +2057,19 @@ class Field_longlong :public Field_num { public: Field_longlong(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg, + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, bool zero_arg, bool unsigned_arg) :Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, 0, zero_arg,unsigned_arg) {} Field_longlong(uint32 len_arg,bool maybe_null_arg, - const char *field_name_arg, - bool unsigned_arg) + const LEX_CSTRING *field_name_arg, + bool unsigned_arg) :Field_num((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg,0,0,unsigned_arg) {} - enum_field_types type() const { return MYSQL_TYPE_LONGLONG;} + const Type_handler *type_handler() const { return &type_handler_longlong; } enum ha_base_keytype key_type() const { return unsigned_flag ? HA_KEYTYPE_ULONGLONG : HA_KEYTYPE_LONGLONG; } int store(const char *to,uint length,CHARSET_INFO *charset); @@ -2135,7 +2106,7 @@ class Field_float :public Field_real { public: Field_float(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg, + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, uint8 dec_arg,bool zero_arg,bool unsigned_arg) :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, @@ -2144,15 +2115,15 @@ public: if (dec_arg >= FLOATING_POINT_DECIMALS) dec_arg= NOT_FIXED_DEC; } - Field_float(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg, - uint8 dec_arg) + Field_float(uint32 len_arg, bool maybe_null_arg, + const LEX_CSTRING *field_name_arg, uint8 dec_arg) :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0, NONE, field_name_arg, dec_arg, 0, 0) { if (dec_arg >= FLOATING_POINT_DECIMALS) dec_arg= NOT_FIXED_DEC; } - enum_field_types type() const { return MYSQL_TYPE_FLOAT;} + const Type_handler *type_handler() const { return &type_handler_float; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_FLOAT; } int store(const char *to,uint length,CHARSET_INFO *charset); int store(double nr); @@ -2176,7 +2147,7 @@ class Field_double :public Field_real { public: Field_double(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg, + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, uint8 dec_arg,bool zero_arg,bool unsigned_arg) :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, @@ -2185,15 +2156,16 @@ public: if (dec_arg >= FLOATING_POINT_DECIMALS) dec_arg= NOT_FIXED_DEC; } - Field_double(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg, - uint8 dec_arg) + Field_double(uint32 len_arg, bool maybe_null_arg, + const LEX_CSTRING *field_name_arg, uint8 dec_arg) :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0, NONE, field_name_arg, dec_arg, 0, 0) { if (dec_arg >= FLOATING_POINT_DECIMALS) dec_arg= NOT_FIXED_DEC; } - Field_double(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg, + Field_double(uint32 len_arg, bool maybe_null_arg, + const LEX_CSTRING *field_name_arg, uint8 dec_arg, bool not_fixed_arg) :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0, NONE, field_name_arg, dec_arg, 0, 0) @@ -2202,7 +2174,7 @@ public: if (dec_arg >= FLOATING_POINT_DECIMALS) dec_arg= NOT_FIXED_DEC; } - enum_field_types type() const { return MYSQL_TYPE_DOUBLE;} + const Type_handler *type_handler() const { return &type_handler_double; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_DOUBLE; } int store(const char *to,uint length,CHARSET_INFO *charset); int store(double nr); @@ -2234,12 +2206,12 @@ class Field_null :public Field_str { static uchar null[1]; public: Field_null(uchar *ptr_arg, uint32 len_arg, - enum utype unireg_check_arg, const char *field_name_arg, - CHARSET_INFO *cs) + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, + const DTCollation &collation) :Field_str(ptr_arg, len_arg, null, 1, - unireg_check_arg, field_name_arg, cs) + unireg_check_arg, field_name_arg, collation) {} - enum_field_types type() const { return MYSQL_TYPE_NULL;} + const Type_handler *type_handler() const { return &type_handler_null; } Copy_func *get_copy_func(const Field *from) const { return do_field_string; @@ -2285,11 +2257,10 @@ protected: public: Field_temporal(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, - const char *field_name_arg) + const LEX_CSTRING *field_name_arg) :Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg) { flags|= BINARY_FLAG; } - Item_result result_type () const { return STRING_RESULT; } int store_hex_hybrid(const char *str, uint length) { return store(str, length, &my_charset_bin); @@ -2310,7 +2281,6 @@ public: CHARSET_INFO *charset(void) const { return &my_charset_numeric; } CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; } bool binary() const { return true; } - enum Item_result cmp_type () const { return TIME_RESULT; } bool val_bool() { return val_real() != 0e0; } uint is_equal(Create_field *new_field); bool eq_def(const Field *field) const @@ -2364,7 +2334,7 @@ public: Field_temporal_with_date(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, - const char *field_name_arg) + const LEX_CSTRING *field_name_arg) :Field_temporal(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg) {} @@ -2384,9 +2354,10 @@ protected: public: Field_timestamp(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg, + enum utype unireg_check_arg, + const LEX_CSTRING *field_name_arg, TABLE_SHARE *share); - enum_field_types type() const { return MYSQL_TYPE_TIMESTAMP;} + const Type_handler *type_handler() const { return &type_handler_timestamp; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; } int store(const char *to,uint length,CHARSET_INFO *charset); int store(double nr); @@ -2453,7 +2424,7 @@ public: Field_timestamp_with_dec(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, - const char *field_name_arg, + const LEX_CSTRING *field_name_arg, TABLE_SHARE *share, uint dec_arg) : Field_timestamp(ptr_arg, MAX_DATETIME_WIDTH + dec_arg + MY_TEST(dec_arg), null_ptr_arg, @@ -2483,11 +2454,15 @@ public: class Field_timestamp_hires :public Field_timestamp_with_dec { + uint sec_part_bytes(uint dec) const + { + return Type_handler_timestamp::sec_part_bytes(dec); + } public: Field_timestamp_hires(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, - const char *field_name_arg, + const LEX_CSTRING *field_name_arg, TABLE_SHARE *share, uint dec_arg) : Field_timestamp_with_dec(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, share, dec_arg) @@ -2497,7 +2472,7 @@ public: my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const; void store_TIME(my_time_t timestamp, ulong sec_part); int cmp(const uchar *,const uchar *); - uint32 pack_length() const; + uint32 pack_length() const { return 4 + sec_part_bytes(dec); } uint size_of() const { return sizeof(*this); } }; @@ -2515,12 +2490,12 @@ public: Field_timestampf(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, - const char *field_name_arg, + const LEX_CSTRING *field_name_arg, TABLE_SHARE *share, uint dec_arg) : Field_timestamp_with_dec(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, share, dec_arg) {} - enum_field_types real_type() const { return MYSQL_TYPE_TIMESTAMP2; } + const Type_handler *type_handler() const { return &type_handler_timestamp2; } enum_field_types binlog_type() const { return MYSQL_TYPE_TIMESTAMP2; } uint32 pack_length() const { @@ -2547,18 +2522,23 @@ class Field_year :public Field_tiny { public: Field_year(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg) + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg) :Field_tiny(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, 1, 1) {} - enum_field_types type() const { return MYSQL_TYPE_YEAR;} + const Type_handler *type_handler() const { return &type_handler_year; } Copy_func *get_copy_func(const Field *from) const { if (eq_def(from)) return get_identical_copy_func(); switch (from->cmp_type()) { case STRING_RESULT: + { + const Type_handler *handler= from->type_handler(); + if (handler == &type_handler_enum || handler == &type_handler_set) + return do_field_int; return do_field_string; + } case TIME_RESULT: return do_field_temporal; case DECIMAL_RESULT: @@ -2593,10 +2573,10 @@ class Field_date :public Field_temporal_with_date { bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const; public: Field_date(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg) + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg) :Field_temporal_with_date(ptr_arg, MAX_DATE_WIDTH, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg) {} - enum_field_types type() const { return MYSQL_TYPE_DATE;} + const Type_handler *type_handler() const { return &type_handler_date; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; } int reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; } bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) @@ -2628,12 +2608,11 @@ class Field_newdate :public Field_temporal_with_date { bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const; public: Field_newdate(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg) + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg) :Field_temporal_with_date(ptr_arg, MAX_DATE_WIDTH, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg) {} - enum_field_types type() const { return MYSQL_TYPE_DATE;} - enum_field_types real_type() const { return MYSQL_TYPE_NEWDATE; } + const Type_handler *type_handler() const { return &type_handler_newdate; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_UINT24; } int reset(void) { ptr[0]=ptr[1]=ptr[2]=0; return 0; } double val_real(void); @@ -2667,11 +2646,13 @@ protected: public: Field_time(uchar *ptr_arg, uint length_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, - const char *field_name_arg) + const LEX_CSTRING *field_name_arg) :Field_temporal(ptr_arg, length_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg), curdays(0) {} - enum_field_types type() const { return MYSQL_TYPE_TIME;} + bool can_be_substituted_to_equal_item(const Context &ctx, + const Item_equal *item_equal); + const Type_handler *type_handler() const { return &type_handler_time; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_INT24; } Copy_func *get_copy_func(const Field *from) const { @@ -2719,7 +2700,8 @@ protected: uint dec; public: Field_time_with_dec(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg, + enum utype unireg_check_arg, + const LEX_CSTRING *field_name_arg, uint dec_arg) :Field_time(ptr_arg, MIN_TIME_WIDTH + dec_arg + MY_TEST(dec_arg), null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg), @@ -2743,7 +2725,7 @@ class Field_time_hires :public Field_time_with_dec { void store_TIME(MYSQL_TIME *ltime); public: Field_time_hires(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg, + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, uint dec_arg) :Field_time_with_dec(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, @@ -2757,7 +2739,7 @@ public: bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); int cmp(const uchar *,const uchar *); void sort_string(uchar *buff,uint length); - uint32 pack_length() const; + uint32 pack_length() const { return Type_handler_time::hires_bytes(dec); } uint size_of() const { return sizeof(*this); } }; @@ -2774,7 +2756,7 @@ class Field_timef :public Field_time_with_dec { } public: Field_timef(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg, + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, uint dec_arg) :Field_time_with_dec(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, @@ -2782,7 +2764,7 @@ public: { DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS); } - enum_field_types real_type() const { return MYSQL_TYPE_TIME2; } + const Type_handler *type_handler() const { return &type_handler_time2; } enum_field_types binlog_type() const { return MYSQL_TYPE_TIME2; } uint32 pack_length() const { @@ -2816,7 +2798,7 @@ class Field_datetime :public Field_temporal_with_date { public: Field_datetime(uchar *ptr_arg, uint length_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, - const char *field_name_arg) + const LEX_CSTRING *field_name_arg) :Field_temporal_with_date(ptr_arg, length_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg) { @@ -2824,7 +2806,7 @@ public: unireg_check == TIMESTAMP_DNUN_FIELD) flags|= ON_UPDATE_NOW_FLAG; } - enum_field_types type() const { return MYSQL_TYPE_DATETIME;} + const Type_handler *type_handler() const { return &type_handler_datetime; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONGLONG; } double val_real(void); longlong val_int(void); @@ -2873,7 +2855,7 @@ protected: public: Field_datetime_with_dec(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, - const char *field_name_arg, uint dec_arg) + const LEX_CSTRING *field_name_arg, uint dec_arg) :Field_datetime(ptr_arg, MAX_DATETIME_WIDTH + dec_arg + MY_TEST(dec_arg), null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg), dec(dec_arg) @@ -2909,14 +2891,14 @@ class Field_datetime_hires :public Field_datetime_with_dec { public: Field_datetime_hires(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, - const char *field_name_arg, uint dec_arg) + const LEX_CSTRING *field_name_arg, uint dec_arg) :Field_datetime_with_dec(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, dec_arg) { DBUG_ASSERT(dec); } int cmp(const uchar *,const uchar *); - uint32 pack_length() const; + uint32 pack_length() const { return Type_handler_datetime::hires_bytes(dec); } bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) { return Field_datetime_hires::get_TIME(ltime, ptr, fuzzydate); } uint size_of() const { return sizeof(*this); } @@ -2937,11 +2919,11 @@ class Field_datetimef :public Field_datetime_with_dec { public: Field_datetimef(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, - const char *field_name_arg, uint dec_arg) + const LEX_CSTRING *field_name_arg, uint dec_arg) :Field_datetime_with_dec(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, dec_arg) {} - enum_field_types real_type() const { return MYSQL_TYPE_DATETIME2; } + const Type_handler *type_handler() const { return &type_handler_datetime2; } enum_field_types binlog_type() const { return MYSQL_TYPE_DATETIME2; } uint32 pack_length() const { @@ -2967,7 +2949,8 @@ public: static inline Field_timestamp * new_Field_timestamp(MEM_ROOT *root,uchar *ptr, uchar *null_ptr, uchar null_bit, - enum Field::utype unireg_check, const char *field_name, + enum Field::utype unireg_check, + const LEX_CSTRING *field_name, TABLE_SHARE *share, uint dec) { if (dec==0) @@ -2983,7 +2966,7 @@ new_Field_timestamp(MEM_ROOT *root,uchar *ptr, uchar *null_ptr, uchar null_bit, static inline Field_time * new_Field_time(MEM_ROOT *root, uchar *ptr, uchar *null_ptr, uchar null_bit, - enum Field::utype unireg_check, const char *field_name, + enum Field::utype unireg_check, const LEX_CSTRING *field_name, uint dec) { if (dec == 0) @@ -2999,7 +2982,7 @@ new_Field_time(MEM_ROOT *root, uchar *ptr, uchar *null_ptr, uchar null_bit, static inline Field_datetime * new_Field_datetime(MEM_ROOT *root, uchar *ptr, uchar *null_ptr, uchar null_bit, enum Field::utype unireg_check, - const char *field_name, uint dec) + const LEX_CSTRING *field_name, uint dec) { if (dec == 0) return new (root) @@ -3018,28 +3001,35 @@ class Field_string :public Field_longstr { public: Warn_filter_string(const THD *thd, const Field_string *field); }; + bool is_var_string() const + { + return can_alter_field_type && + orig_table && + (orig_table->s->db_create_options & HA_OPTION_PACK_RECORD) && + field_length >= 4 && + orig_table->s->frm_version < FRM_VER_TRUE_VARCHAR; + } public: bool can_alter_field_type; Field_string(uchar *ptr_arg, uint32 len_arg,uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg, - CHARSET_INFO *cs) + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, + const DTCollation &collation) :Field_longstr(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, cs), + unireg_check_arg, field_name_arg, collation), can_alter_field_type(1) {}; - Field_string(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, - CHARSET_INFO *cs) + Field_string(uint32 len_arg,bool maybe_null_arg, + const LEX_CSTRING *field_name_arg, + const DTCollation &collation) :Field_longstr((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0, - NONE, field_name_arg, cs), + NONE, field_name_arg, collation), can_alter_field_type(1) {}; - enum_field_types type() const + const Type_handler *type_handler() const { - return ((can_alter_field_type && orig_table && - orig_table->s->db_create_options & HA_OPTION_PACK_RECORD && - field_length >= 4) && - orig_table->s->frm_version < FRM_VER_TRUE_VARCHAR ? - MYSQL_TYPE_VAR_STRING : MYSQL_TYPE_STRING); + if (is_var_string()) + return &type_handler_var_string; + return &type_handler_string; } enum ha_base_keytype key_type() const { return binary() ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; } @@ -3081,7 +3071,6 @@ public: uint packed_col_length(const uchar *to, uint length); uint max_packed_col_length(uint max_length); uint size_of() const { return sizeof(*this); } - enum_field_types real_type() const { return MYSQL_TYPE_STRING; } bool has_charset(void) const { return charset() == &my_charset_bin ? FALSE : TRUE; } Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type); @@ -3111,25 +3100,25 @@ public: Field_varstring(uchar *ptr_arg, uint32 len_arg, uint length_bytes_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg, - TABLE_SHARE *share, CHARSET_INFO *cs) + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, + TABLE_SHARE *share, const DTCollation &collation) :Field_longstr(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, cs), + unireg_check_arg, field_name_arg, collation), length_bytes(length_bytes_arg) { share->varchar_fields++; } Field_varstring(uint32 len_arg,bool maybe_null_arg, - const char *field_name_arg, - TABLE_SHARE *share, CHARSET_INFO *cs) + const LEX_CSTRING *field_name_arg, + TABLE_SHARE *share, const DTCollation &collation) :Field_longstr((uchar*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0, - NONE, field_name_arg, cs), + NONE, field_name_arg, collation), length_bytes(len_arg < 256 ? 1 :2) { share->varchar_fields++; } - enum_field_types type() const { return MYSQL_TYPE_VARCHAR; } + const Type_handler *type_handler() const { return &type_handler_varchar; } enum ha_base_keytype key_type() const; uint row_pack_length() const { return field_length; } bool zero_pack() const { return 0; } @@ -3173,7 +3162,6 @@ public: uint max_packed_col_length(uint max_length); uint32 data_length(); uint size_of() const { return sizeof(*this); } - enum_field_types real_type() const { return MYSQL_TYPE_VARCHAR; } bool has_charset(void) const { return charset() == &my_charset_bin ? FALSE : TRUE; } Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type); @@ -3188,6 +3176,8 @@ private: }; +extern LEX_CSTRING temp_lex_str; + class Field_blob :public Field_longstr { protected: /** @@ -3210,20 +3200,22 @@ protected: static void do_conv_blob(Copy_field *copy); public: Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg, - TABLE_SHARE *share, uint blob_pack_length, CHARSET_INFO *cs); - Field_blob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, - CHARSET_INFO *cs) + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, + TABLE_SHARE *share, uint blob_pack_length, + const DTCollation &collation); + Field_blob(uint32 len_arg,bool maybe_null_arg, const LEX_CSTRING *field_name_arg, + const DTCollation &collation) :Field_longstr((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0, - NONE, field_name_arg, cs), + NONE, field_name_arg, collation), packlength(4) { flags|= BLOB_FLAG; } - Field_blob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, - CHARSET_INFO *cs, bool set_packlength) + Field_blob(uint32 len_arg,bool maybe_null_arg, + const LEX_CSTRING *field_name_arg, + const DTCollation &collation, bool set_packlength) :Field_longstr((uchar*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0, - NONE, field_name_arg, cs) + NONE, field_name_arg, collation) { flags|= BLOB_FLAG; packlength= 4; @@ -3235,10 +3227,27 @@ public: } } Field_blob(uint32 packlength_arg) - :Field_longstr((uchar*) 0, 0, (uchar*) "", 0, NONE, "temp", system_charset_info), + :Field_longstr((uchar*) 0, 0, (uchar*) "", 0, NONE, &temp_lex_str, + system_charset_info), packlength(packlength_arg) {} + const Type_handler *type_handler() const; /* Note that the default copy constructor is used, in clone() */ - enum_field_types type() const { return MYSQL_TYPE_BLOB;} + enum_field_types type() const + { + /* + We cannot return type_handler()->field_type() here. + Some pieces of the code (e.g. in engines) rely on the fact + that Field::type(), Field::real_type() and Item_field::field_type() + return MYSQL_TYPE_BLOB for all blob variants. + We should eventually fix all such code pieces to expect + all BLOB type codes. + */ + return MYSQL_TYPE_BLOB; + } + enum_field_types real_type() const + { + return MYSQL_TYPE_BLOB; + } enum ha_base_keytype key_type() const { return binary() ? HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2; } Copy_func *get_copy_func(const Field *from) const @@ -3417,18 +3426,25 @@ public: enum storage_type storage; Field_geom(uchar *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg, + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, TABLE_SHARE *share, uint blob_pack_length, enum geometry_type geom_type_arg, uint field_srid) - :Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, + :Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, share, blob_pack_length, &my_charset_bin) { geom_type= geom_type_arg; srid= field_srid; } - Field_geom(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, - TABLE_SHARE *share, enum geometry_type geom_type_arg) - :Field_blob(len_arg, maybe_null_arg, field_name_arg, &my_charset_bin) - { geom_type= geom_type_arg; srid= 0; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY2; } - enum_field_types type() const { return MYSQL_TYPE_GEOMETRY; } + const Type_handler *type_handler() const + { + return &type_handler_geometry; + } + enum_field_types type() const + { + return MYSQL_TYPE_GEOMETRY; + } + enum_field_types real_type() const + { + return MYSQL_TYPE_GEOMETRY; + } bool can_optimize_range(const Item_bool_func *cond, const Item *item, bool is_eq_func) const; @@ -3474,19 +3490,18 @@ public: TYPELIB *typelib; Field_enum(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg, + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, uint packlength_arg, TYPELIB *typelib_arg, - CHARSET_INFO *charset_arg) + const DTCollation &collation) :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, charset_arg), + unireg_check_arg, field_name_arg, collation), packlength(packlength_arg),typelib(typelib_arg) { flags|=ENUM_FLAG; } Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type); - enum_field_types type() const { return MYSQL_TYPE_STRING; } - enum Item_result cmp_type () const { return INT_RESULT; } + const Type_handler *type_handler() const { return &type_handler_enum; } enum ha_base_keytype key_type() const; Copy_func *get_copy_func(const Field *from) const { @@ -3527,7 +3542,6 @@ public: void store_type(ulonglong value); void sql_type(String &str) const; uint size_of() const { return sizeof(*this); } - enum_field_types real_type() const { return MYSQL_TYPE_ENUM; } uint pack_length_from_metadata(uint field_metadata) { return (field_metadata & 0x00ff); } uint row_pack_length() const { return pack_length(); } @@ -3538,6 +3552,7 @@ public: /* enum and set are sorted as integers */ CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; } uint decimals() const { return 0; } + TYPELIB *get_typelib() const { return typelib; } virtual uchar *pack(uchar *to, const uchar *from, uint max_length); virtual const uchar *unpack(uchar *to, const uchar *from, @@ -3557,6 +3572,9 @@ public: */ return false; } + bool can_optimize_range(const Item_bool_func *cond, + const Item *item, + bool is_eq_func) const; private: int do_save_field_metadata(uchar *first_byte); uint is_equal(Create_field *new_field); @@ -3567,14 +3585,14 @@ class Field_set :public Field_enum { public: Field_set(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg, + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, uint32 packlength_arg, - TYPELIB *typelib_arg, CHARSET_INFO *charset_arg) + TYPELIB *typelib_arg, const DTCollation &collation) :Field_enum(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, packlength_arg, - typelib_arg,charset_arg), - empty_set_string("", 0, charset_arg) + typelib_arg, collation), + empty_set_string("", 0, collation.collation) { flags=(flags & ~ENUM_FLAG) | SET_FLAG; } @@ -3587,7 +3605,7 @@ public: String *val_str(String*,String *); void sql_type(String &str) const; uint size_of() const { return sizeof(*this); } - enum_field_types real_type() const { return MYSQL_TYPE_SET; } + const Type_handler *type_handler() const { return &type_handler_set; } bool has_charset(void) const { return TRUE; } private: const String empty_set_string; @@ -3616,14 +3634,13 @@ public: uint bytes_in_rec; Field_bit(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg, - enum utype unireg_check_arg, const char *field_name_arg); - enum_field_types type() const { return MYSQL_TYPE_BIT; } + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg); + const Type_handler *type_handler() const { return &type_handler_bit; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_BIT; } uint32 key_length() const { return (uint32) (field_length + 7) / 8; } uint32 max_data_length() const { return (field_length + 7) / 8; } uint32 max_display_length() { return field_length; } uint size_of() const { return sizeof(*this); } - Item_result result_type () const { return INT_RESULT; } int reset(void) { bzero(ptr, bytes_in_rec); if (bit_ptr && (bit_len > 0)) // reset odd bits among null bits @@ -3752,7 +3769,7 @@ class Field_bit_as_char: public Field_bit { public: Field_bit_as_char(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, - enum utype unireg_check_arg, const char *field_name_arg); + enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg); enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; } uint size_of() const { return sizeof(*this); } int store(const char *to, uint length, CHARSET_INFO *charset); @@ -3763,28 +3780,68 @@ public: }; -extern const LEX_STRING null_lex_str; - +extern const LEX_CSTRING null_clex_str; Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root, uchar *ptr, uint32 field_length, uchar *null_pos, uchar null_bit, - uint pack_flag, enum_field_types field_type, + uint pack_flag, const Type_handler *handler, CHARSET_INFO *cs, Field::geometry_type geom_type, uint srid, Field::utype unireg_check, - TYPELIB *interval, const char *field_name); + TYPELIB *interval, const LEX_CSTRING *field_name); /* Create field class for CREATE TABLE */ -class Column_definition: public Sql_alloc +class Column_definition: public Sql_alloc, + public Type_handler_hybrid_field_type { + /** + Create "interval" from "interval_list". + @param mem_root - memory root to create the TYPELIB + instance and its values on + @param reuse_interval_list_values - determines if TYPELIB can reuse strings + from interval_list, or should always + allocate a copy on mem_root, even if + character set conversion is not needed + @retval false on success + @retval true on error (bad values, or EOM) + */ + bool create_interval_from_interval_list(MEM_ROOT *mem_root, + bool reuse_interval_list_values); + + /* + Calculate TYPELIB (set or enum) max and total lengths + + @param cs charset+collation pair of the interval + @param max_length length of the longest item + @param tot_length sum of the item lengths + + After this method call: + - ENUM uses max_length + - SET uses tot_length. + */ + void calculate_interval_lengths(uint32 *max_length, uint32 *tot_length) + { + const char **pos; + uint *len; + *max_length= *tot_length= 0; + for (pos= interval->type_names, len= interval->type_lengths; + *pos ; pos++, len++) + { + size_t length= charset->cset->numchars(charset, *pos, *pos + *len); + *tot_length+= length; + set_if_bigger(*max_length, (uint32)length); + } + } + bool prepare_stage1_check_typelib_default(); + bool prepare_stage1_convert_default(THD *, MEM_ROOT *, CHARSET_INFO *to); + const Type_handler *field_type() const; // Prevent using this public: - const char *field_name; - LEX_STRING comment; // Comment for field + LEX_CSTRING field_name; + LEX_CSTRING comment; // Comment for field Item *on_update; // ON UPDATE NOW() - enum enum_field_types sql_type; /* At various stages in execution this can be length of field in bytes or max number of characters. @@ -3816,19 +3873,111 @@ public: *default_value, // Default value *check_constraint; // Check constraint - Column_definition(): - comment(null_lex_str), - on_update(0), sql_type(MYSQL_TYPE_NULL), + Column_definition() + :Type_handler_hybrid_field_type(&type_handler_null), + comment(null_clex_str), + on_update(NULL), length(0), decimals(0), flags(0), pack_length(0), key_length(0), unireg_check(Field::NONE), - interval(0), srid(0), geom_type(Field::GEOM_GEOMETRY), - option_list(NULL), + interval(0), charset(&my_charset_bin), + srid(0), geom_type(Field::GEOM_GEOMETRY), + option_list(NULL), pack_flag(0), vcol_info(0), default_value(0), check_constraint(0) { interval_list.empty(); } - Column_definition(THD *thd, Field *field, Field *orig_field); - void create_length_to_internal_length(void); + void set_attributes(const Lex_field_type_st &type, CHARSET_INFO *cs); + void create_length_to_internal_length_null() + { + DBUG_ASSERT(length == 0); + key_length= pack_length= 0; + } + void create_length_to_internal_length_simple() + { + key_length= pack_length= type_handler()->calc_pack_length(length); + } + void create_length_to_internal_length_string() + { + length*= charset->mbmaxlen; + key_length= length; + pack_length= type_handler()->calc_pack_length(length); + } + void create_length_to_internal_length_typelib() + { + /* Pack_length already calculated in sql_parse.cc */ + length*= charset->mbmaxlen; + key_length= pack_length; + } + void create_length_to_internal_length_bit(); + void create_length_to_internal_length_newdecimal(); + + /** + Prepare a SET/ENUM field. + Create "interval" from "interval_list" if needed, and adjust "length". + @param mem_root - Memory root to allocate TYPELIB and + its values on + @param reuse_interval_list_values - determines if TYPELIB can reuse value + buffers from interval_list, or should + always allocate a copy on mem_root, + even if character set conversion + is not needed + */ + bool prepare_interval_field(MEM_ROOT *mem_root, + bool reuse_interval_list_values); + + void prepare_interval_field_calc_length() + { + uint32 field_length, dummy; + if (real_field_type() == MYSQL_TYPE_SET) + { + calculate_interval_lengths(&dummy, &field_length); + length= field_length + (interval->count - 1); + } + else /* MYSQL_TYPE_ENUM */ + { + calculate_interval_lengths(&field_length, &dummy); + length= field_length; + } + set_if_smaller(length, MAX_FIELD_WIDTH - 1); + } + + bool prepare_blob_field(THD *thd); + + bool sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root); + + bool prepare_stage1(THD *thd, MEM_ROOT *mem_root, + handler *file, ulonglong table_flags); + bool prepare_stage1_typelib(THD *thd, MEM_ROOT *mem_root, + handler *file, ulonglong table_flags); + bool prepare_stage1_string(THD *thd, MEM_ROOT *mem_root, + handler *file, ulonglong table_flags); + bool prepare_stage1_bit(THD *thd, MEM_ROOT *mem_root, + handler *file, ulonglong table_flags); + + void redefine_stage1_common(const Column_definition *dup_field, + const handler *file, + const Schema_specification_st *schema); + bool redefine_stage1(const Column_definition *dup_field, const handler *file, + const Schema_specification_st *schema) + { + const Type_handler *handler= dup_field->type_handler(); + return handler->Column_definition_redefine_stage1(this, dup_field, + file, schema); + } + bool prepare_stage2(handler *handler, ulonglong table_flags); + bool prepare_stage2_blob(handler *handler, + ulonglong table_flags, uint field_flags); + bool prepare_stage2_varchar(ulonglong table_flags); + bool prepare_stage2_typelib(const char *type_name, uint field_flags, + uint *dup_val_count); + uint pack_flag_numeric(uint dec) const; + uint sign_length() const { return flags & UNSIGNED_FLAG ? 0 : 1; } + bool check_length(uint mysql_errno, uint max_allowed_length) const; + bool fix_attributes_real(uint default_length); + bool fix_attributes_int(uint default_length); + bool fix_attributes_decimal(); + bool fix_attributes_temporal_with_time(uint int_part_length); + bool fix_attributes_bit(); bool check(THD *thd); @@ -3853,16 +4002,16 @@ public: Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root, uchar *ptr, uchar *null_pos, uchar null_bit, - const char *field_name_arg) const + const LEX_CSTRING *field_name_arg) const { return ::make_field(share, mem_root, ptr, (uint32)length, null_pos, null_bit, - pack_flag, sql_type, charset, + pack_flag, type_handler(), charset, geom_type, srid, unireg_check, interval, field_name_arg); } Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root, - const char *field_name_arg) + const LEX_CSTRING *field_name_arg) { return make_field(share, mem_root, (uchar *) 0, (uchar *) "", 0, field_name_arg); @@ -3875,14 +4024,158 @@ public: return unireg_check == Field::TIMESTAMP_DN_FIELD || unireg_check == Field::TIMESTAMP_DNUN_FIELD; } + + // Replace the entire value by another definition + void set_column_definition(const Column_definition *def) + { + *this= *def; + } +}; + + +/** + List of ROW element definitions, e.g.: + DECLARE a ROW(a INT,b VARCHAR(10)) +*/ +class Row_definition_list: public List<class Spvar_definition> +{ +public: + inline bool eq_name(const Spvar_definition *def, const LEX_CSTRING *name) const; + /** + Find a ROW field by name. + @param [IN] name - the name + @param [OUT] offset - if the ROW field found, its offset it returned here + @retval NULL - the ROW field was not found + @retval !NULL - the pointer to the found ROW field + */ + Spvar_definition *find_row_field_by_name(const LEX_CSTRING *name, uint *offset) const + { + // Cast-off the "const" qualifier + List_iterator<Spvar_definition> it(*((List<Spvar_definition>*)this)); + Spvar_definition *def; + for (*offset= 0; (def= it++); (*offset)++) + { + if (eq_name(def, name)) + return def; + } + return 0; + } +}; + + +/** + This class is used during a stored routine or a trigger execution, + at sp_rcontext::create() time. + Currently it can represent: + - variables with explicit data types: DECLARE a INT; + - variables with data type references: DECLARE a t1.a%TYPE; + - ROW type variables + + Notes: + - Scalar variables have m_field_definitions==NULL. + - ROW variables are defined as having MYSQL_TYPE_NULL, + with a non-empty m_field_definitions. + + Data type references to other object types will be added soon, e.g.: + - DECLARE a table_name%ROWTYPE; + - DECLARE a cursor_name%ROWTYPE; + - DECLARE a record_name%TYPE; + - DECLARE a variable_name%TYPE; +*/ +class Spvar_definition: public Column_definition +{ + class Qualified_column_ident *m_column_type_ref; // for %TYPE + class Table_ident *m_table_rowtype_ref; // for table%ROWTYPE + bool m_cursor_rowtype_ref; // for cursor%ROWTYPE + Row_definition_list *m_row_field_definitions; // for ROW +public: + Spvar_definition() + :m_column_type_ref(NULL), + m_table_rowtype_ref(NULL), + m_cursor_rowtype_ref(false), + m_row_field_definitions(NULL) + { } + Spvar_definition(THD *thd, Field *field) + :Column_definition(thd, field, NULL), + m_column_type_ref(NULL), + m_table_rowtype_ref(NULL), + m_cursor_rowtype_ref(false), + m_row_field_definitions(NULL) + { } + const Type_handler *type_handler() const + { + return is_row() || is_table_rowtype_ref() || is_cursor_rowtype_ref() ? + &type_handler_row : + Type_handler_hybrid_field_type::type_handler(); + } + bool is_column_type_ref() const { return m_column_type_ref != 0; } + bool is_table_rowtype_ref() const { return m_table_rowtype_ref != 0; } + bool is_cursor_rowtype_ref() const { return m_cursor_rowtype_ref; } + class Qualified_column_ident *column_type_ref() const + { + return m_column_type_ref; + } + void set_column_type_ref(class Qualified_column_ident *ref) + { + m_column_type_ref= ref; + } + + class Table_ident *table_rowtype_ref() const + { + return m_table_rowtype_ref; + } + void set_table_rowtype_ref(class Table_ident *ref) + { + m_table_rowtype_ref= ref; + } + void set_cursor_rowtype_ref(bool ref) + { + m_cursor_rowtype_ref= ref; + } + + /* + Find a ROW field by name. + See Row_field_list::find_row_field_by_name() for details. + */ + Spvar_definition *find_row_field_by_name(const LEX_CSTRING *name, uint *offset) const + { + DBUG_ASSERT(m_row_field_definitions); + return m_row_field_definitions->find_row_field_by_name(name, offset); + } + uint is_row() const + { + return m_row_field_definitions != NULL; + } + // Check if "this" defines a ROW variable with n elements + uint is_row(uint n) const + { + return m_row_field_definitions != NULL && + m_row_field_definitions->elements == n; + } + Row_definition_list *row_field_definitions() const + { + return m_row_field_definitions; + } + void set_row_field_definitions(Row_definition_list *list) + { + m_row_field_definitions= list; + } + }; +inline bool Row_definition_list::eq_name(const Spvar_definition *def, + const LEX_CSTRING *name) const +{ + return def->field_name.length == name->length && my_strcasecmp(system_charset_info, def->field_name.str, name->str) == 0; +} + + class Create_field :public Column_definition { public: - const char *change; // If done with alter table - const char *after; // Put column after this one + LEX_CSTRING change; // If done with alter table + LEX_CSTRING after; // Put column after this one Field *field; // For alter table TYPELIB *save_interval; // Temporary copy for the above // Used only for UCS2 intervals @@ -3894,16 +4187,20 @@ public: bool create_if_not_exists; // Used in ALTER TABLE IF NOT EXISTS Create_field(): - Column_definition(), change(0), after(0), + Column_definition(), field(0), option_struct(NULL), create_if_not_exists(false) - { } + { + change= after= null_clex_str; + } Create_field(THD *thd, Field *old_field, Field *orig_field): Column_definition(thd, old_field, orig_field), - change(old_field->field_name), after(0), + change(old_field->field_name), field(old_field), option_struct(old_field->option_struct), create_if_not_exists(false) - { } + { + after= null_clex_str; + } /* Used to make a clone of this object for ALTER/CREATE TABLE */ Create_field *clone(MEM_ROOT *mem_root) const; }; @@ -3917,9 +4214,9 @@ class Send_field :public Sql_alloc { public: const char *db_name; const char *table_name,*org_table_name; - const char *col_name,*org_col_name; + LEX_CSTRING col_name, org_col_name; ulong length; - uint charsetnr, flags, decimals; + uint flags, decimals; enum_field_types type; Send_field() {} }; @@ -3967,11 +4264,10 @@ public: uint pack_length_to_packflag(uint type); enum_field_types get_blob_type_from_length(ulong length); -uint32 calc_pack_length(enum_field_types type,uint32 length); int set_field_to_null(Field *field); int set_field_to_null_with_conversions(Field *field, bool no_conversions); int convert_null_to_field_value_or_error(Field *field); -bool check_expression(Virtual_column_info *vcol, const char *name, +bool check_expression(Virtual_column_info *vcol, LEX_CSTRING *name, enum_vcol_info_type type); /* |