diff options
Diffstat (limited to 'sql/field.h')
-rw-r--r-- | sql/field.h | 366 |
1 files changed, 316 insertions, 50 deletions
diff --git a/sql/field.h b/sql/field.h index 287837ee1e7..e1017f04c27 100644 --- a/sql/field.h +++ b/sql/field.h @@ -32,6 +32,7 @@ #include "sql_error.h" /* Sql_condition */ #include "compat56.h" #include "sql_type.h" /* Type_std_attributes */ +#include "field_comp.h" class Send_field; class Copy_field; @@ -49,8 +50,9 @@ class Virtual_tmp_table; enum enum_check_fields { CHECK_FIELD_IGNORE, + CHECK_FIELD_EXPRESSION, CHECK_FIELD_WARN, - CHECK_FIELD_ERROR_FOR_NULL + CHECK_FIELD_ERROR_FOR_NULL, }; /* @@ -557,6 +559,7 @@ static inline const char *vcol_type_name(enum_vcol_info_type type) #define VCOL_TIME_FUNC 8 #define VCOL_AUTO_INC 16 #define VCOL_IMPOSSIBLE 32 +#define VCOL_NOT_VIRTUAL 64 /* Function can't be virtual */ #define VCOL_NOT_STRICTLY_DETERMINISTIC \ (VCOL_NON_DETERMINISTIC | VCOL_TIME_FUNC | VCOL_SESSION_FUNC) @@ -672,7 +675,17 @@ public: static void operator delete(void *ptr, MEM_ROOT *mem_root) { DBUG_ASSERT(0); } + /** + Used by System Versioning. + */ + virtual void set_max() + { DBUG_ASSERT(0); } + virtual bool is_max() + { DBUG_ASSERT(0); return false; } + uchar *ptr; // Position to field in record + + field_visibility_t invisible; /** 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. @@ -713,7 +726,8 @@ public: TIMESTAMP_OLD_FIELD=18, // TIMESTAMP created before 4.1.3 TIMESTAMP_DN_FIELD=21, // TIMESTAMP DEFAULT NOW() TIMESTAMP_UN_FIELD=22, // TIMESTAMP ON UPDATE NOW() - TIMESTAMP_DNUN_FIELD=23 // TIMESTAMP DEFAULT NOW() ON UPDATE NOW() + TIMESTAMP_DNUN_FIELD=23, // TIMESTAMP DEFAULT NOW() ON UPDATE NOW() + TMYSQL_COMPRESSED= 24, // Compatibility with TMySQL }; enum geometry_type { @@ -917,8 +931,21 @@ public: DBUG_RETURN(field_metadata); } virtual uint row_pack_length() const { return 0; } + + + /** + Retrieve the field metadata for fields. + + This default implementation returns 0 and saves 0 in the first_byte value. + + @param first_byte First byte of field metadata + + @returns 0 no bytes written. + */ + virtual int save_field_metadata(uchar *first_byte) - { return do_save_field_metadata(first_byte); } + { return 0; } + /* data_length() return the "real size" of the data in memory. @@ -989,6 +1016,13 @@ public: } bool set_explicit_default(Item *value); + virtual my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const + { DBUG_ASSERT(0); return 0; } + my_time_t get_timestamp(ulong *sec_part) const + { + return get_timestamp(ptr, sec_part); + } + /** Evaluates the @c UPDATE default function, if one exists, and stores the result in the record buffer. If no such function exists for the column, @@ -1430,6 +1464,21 @@ public: FIELD_FLAGS_COLUMN_FORMAT; } + bool vers_sys_field() const + { + return flags & (VERS_SYS_START_FLAG | VERS_SYS_END_FLAG); + } + + bool vers_update_unversioned() const + { + return flags & VERS_UPDATE_UNVERSIONED_FLAG; + } + + virtual bool vers_trx_id() const + { + return false; + } + /* Validate a non-null field value stored in the given record according to the current thread settings, e.g. sql_mode. @@ -1517,6 +1566,8 @@ public: /* Mark field in read map. Updates also virtual fields */ void register_field_in_read_map(); + virtual Compression_method *compression_method() const { return 0; } + virtual Virtual_tmp_table **virtual_tmp_table_addr() { return NULL; @@ -1551,19 +1602,6 @@ private: */ virtual size_t do_last_null_byte() const; -/** - Retrieve the field metadata for fields. - - This default implementation returns 0 and saves 0 in the metadata_ptr - value. - - @param metadata_ptr First byte of field metadata - - @returns 0 no bytes written. -*/ - virtual int do_save_field_metadata(uchar *metadata_ptr) - { return 0; } - protected: uchar *pack_int(uchar *to, const uchar *from, size_t size) { @@ -1704,7 +1742,7 @@ public: charset() == from->charset(); } int store(double nr); - int store(longlong nr, bool unsigned_val)=0; + int store(longlong nr, bool unsigned_val); int store_decimal(const my_decimal *); int store(const char *to,uint length,CHARSET_INFO *cs)=0; int store_hex_hybrid(const char *str, uint length) @@ -1752,6 +1790,11 @@ protected: const Item *item) const; bool cmp_to_string_with_stricter_collation(const Item_bool_func *cond, const Item *item) const; + int compress(char *to, uint *to_length, + const char *from, uint length, + CHARSET_INFO *cs); + String *uncompress(String *val_buffer, String *val_ptr, + const uchar *from, uint from_length); public: Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, @@ -1862,7 +1905,7 @@ public: /* New decimal/numeric field which use fixed point arithmetic */ class Field_new_decimal :public Field_num { private: - int do_save_field_metadata(uchar *first_byte); + int save_field_metadata(uchar *first_byte); public: /* The maximum number of decimal digits can be stored */ uint precision; @@ -2144,6 +2187,57 @@ public: { return unpack_int64(to, from, from_end); } + + void set_max(); + bool is_max(); +}; + + +class Field_vers_trx_id :public Field_longlong { + MYSQL_TIME cache; + ulonglong cached; +public: + Field_vers_trx_id(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + uchar null_bit_arg, enum utype unireg_check_arg, + const LEX_CSTRING *field_name_arg, bool zero_arg, + bool unsigned_arg) + : Field_longlong(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, + unireg_check_arg, field_name_arg, zero_arg, + unsigned_arg), + cached(0) + {} + enum_field_types real_type() const { return MYSQL_TYPE_LONGLONG; } + enum_field_types type() const { return MYSQL_TYPE_LONGLONG;} + uint size_of() const { return sizeof(*this); } + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate, ulonglong trx_id); + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + { + return get_date(ltime, fuzzydate, (ulonglong) val_int()); + } + bool test_if_equality_guarantees_uniqueness(const Item *item) const; + bool can_optimize_keypart_ref(const Item_bool_func *cond, + const Item *item) const + { + return true; + } + + bool can_optimize_group_min_max(const Item_bool_func *cond, + const Item *const_item) const + { + return true; + } + bool can_optimize_range(const Item_bool_func *cond, + const Item *item, + bool is_eq_func) const + { + return true; + } + /* cmp_type() cannot be TIME_RESULT, because we want to compare this field against + integers. But in all other cases we treat it as TIME_RESULT! */ + bool vers_trx_id() const + { + return true; + } }; @@ -2184,7 +2278,7 @@ public: uint row_pack_length() const { return pack_length(); } void sql_type(String &str) const; private: - int do_save_field_metadata(uchar *first_byte); + int save_field_metadata(uchar *first_byte); }; @@ -2237,7 +2331,7 @@ public: uint row_pack_length() const { return pack_length(); } void sql_type(String &str) const; private: - int do_save_field_metadata(uchar *first_byte); + int save_field_metadata(uchar *first_byte); }; @@ -2279,13 +2373,11 @@ public: bool can_optimize_keypart_ref(const Item_bool_func *cond, const Item *item) const { - DBUG_ASSERT(0); return false; } bool can_optimize_group_min_max(const Item_bool_func *cond, const Item *const_item) const { - DBUG_ASSERT(0); return false; } }; @@ -2426,7 +2518,7 @@ public: return res; } /* Get TIMESTAMP field value as seconds since begging of Unix Epoch */ - virtual my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const; + my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const; my_time_t get_timestamp(ulong *sec_part) const { return get_timestamp(ptr, sec_part); @@ -2525,7 +2617,7 @@ public: TIMESTAMP(0..6) - MySQL56 version */ class Field_timestampf :public Field_timestamp_with_dec { - int do_save_field_metadata(uchar *metadata_ptr) + int save_field_metadata(uchar *metadata_ptr) { *metadata_ptr= (uchar) decimals(); return 1; @@ -2556,8 +2648,14 @@ public: { return memcmp(a_ptr, b_ptr, pack_length()); } + void set_max(); + bool is_max(); void store_TIME(my_time_t timestamp, ulong sec_part); my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const; + my_time_t get_timestamp(ulong *sec_part) const + { + return get_timestamp(ptr, sec_part); + } uint size_of() const { return sizeof(*this); } }; @@ -2793,7 +2891,7 @@ public: */ class Field_timef :public Field_time_with_dec { void store_TIME(MYSQL_TIME *ltime); - int do_save_field_metadata(uchar *metadata_ptr) + int save_field_metadata(uchar *metadata_ptr) { *metadata_ptr= (uchar) decimals(); return 1; @@ -2955,7 +3053,7 @@ public: class Field_datetimef :public Field_datetime_with_dec { void store_TIME(MYSQL_TIME *ltime); bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const; - int do_save_field_metadata(uchar *metadata_ptr) + int save_field_metadata(uchar *metadata_ptr) { *metadata_ptr= (uchar) decimals(); return 1; @@ -3086,8 +3184,7 @@ public: return 0; } int store(const char *to,uint length,CHARSET_INFO *charset); - int store(longlong nr, bool unsigned_val); - int store(double nr) { return Field_str::store(nr); } /* QQ: To be deleted */ + using Field_str::store; double val_real(void); longlong val_int(void); String *val_str(String*,String *); @@ -3120,7 +3217,7 @@ public: Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type); virtual uint get_key_image(uchar *buff,uint length, imagetype type); private: - int do_save_field_metadata(uchar *first_byte); + int save_field_metadata(uchar *first_byte); }; @@ -3134,6 +3231,15 @@ public: { return length_bytes == 1 ? (uint) *ptr : uint2korr(ptr); } +protected: + void store_length(uint32 number) + { + if (length_bytes == 1) + *ptr= (uchar) number; + else + int2store(ptr, number); + } +public: /* The maximum space available in a Field_varstring, in bytes. See length_bytes. @@ -3178,11 +3284,11 @@ public: bool memcpy_field_possible(const Field *from) const { return Field_str::memcpy_field_possible(from) && + !compression_method() == !from->compression_method() && length_bytes == ((Field_varstring*) from)->length_bytes; } int store(const char *to,uint length,CHARSET_INFO *charset); - int store(longlong nr, bool unsigned_val); - int store(double nr) { return Field_str::store(nr); } /* QQ: To be deleted */ + using Field_str::store; double val_real(void); longlong val_int(void); String *val_str(String*,String *); @@ -3216,10 +3322,91 @@ public: void hash(ulong *nr, ulong *nr2); uint length_size() { return length_bytes; } private: - int do_save_field_metadata(uchar *first_byte); + int save_field_metadata(uchar *first_byte); }; +class Field_varstring_compressed: public Field_varstring { +public: + Field_varstring_compressed(uchar *ptr_arg, + uint32 len_arg, uint length_bytes_arg, + uchar *null_ptr_arg, uchar null_bit_arg, + enum utype unireg_check_arg, + const LEX_CSTRING *field_name_arg, + TABLE_SHARE *share, const DTCollation &collation, + Compression_method *compression_method_arg): + Field_varstring(ptr_arg, len_arg, length_bytes_arg, null_ptr_arg, + null_bit_arg, unireg_check_arg, field_name_arg, + share, collation), + compression_method_ptr(compression_method_arg) { DBUG_ASSERT(len_arg > 0); } + Compression_method *compression_method() const + { return compression_method_ptr; } +private: + Compression_method *compression_method_ptr; + int store(const char *to, uint length, CHARSET_INFO *charset); + using Field_str::store; + String *val_str(String *, String *); + double val_real(void); + longlong val_int(void); + uint size_of() const { return sizeof(*this); } + enum_field_types binlog_type() const { return MYSQL_TYPE_VARCHAR_COMPRESSED; } + void sql_type(String &str) const + { + Field_varstring::sql_type(str); + str.append(STRING_WITH_LEN(" /*!100301 COMPRESSED*/")); + } + uint32 max_display_length() { return field_length - 1; } + int cmp_max(const uchar *a_ptr, const uchar *b_ptr, uint max_len); + + /* + Compressed fields can't have keys as two rows may have different + compression methods or compression levels. + */ + + int key_cmp(const uchar *str, uint length) + { DBUG_ASSERT(0); return 0; } + using Field_varstring::key_cmp; +}; + + +static inline uint8 number_storage_requirement(uint32 n) +{ + return n < 256 ? 1 : n < 65536 ? 2 : n < 16777216 ? 3 : 4; +} + + +static inline void store_bigendian(ulonglong num, uchar *to, uint bytes) +{ + switch(bytes) { + case 1: mi_int1store(to, num); break; + case 2: mi_int2store(to, num); break; + case 3: mi_int3store(to, num); break; + case 4: mi_int4store(to, num); break; + case 5: mi_int5store(to, num); break; + case 6: mi_int6store(to, num); break; + case 7: mi_int7store(to, num); break; + case 8: mi_int8store(to, num); break; + default: DBUG_ASSERT(0); + } +} + + +static inline longlong read_bigendian(const uchar *from, uint bytes) +{ + switch(bytes) { + case 1: return mi_uint1korr(from); + case 2: return mi_uint2korr(from); + case 3: return mi_uint3korr(from); + case 4: return mi_uint4korr(from); + case 5: return mi_uint5korr(from); + case 6: return mi_uint6korr(from); + case 7: return mi_uint7korr(from); + case 8: return mi_sint8korr(from); + default: DBUG_ASSERT(0); return 0; + } +} + + extern LEX_CSTRING temp_lex_str; class Field_blob :public Field_longstr { @@ -3262,13 +3449,7 @@ public: NONE, field_name_arg, collation) { flags|= BLOB_FLAG; - packlength= 4; - if (set_packlength) - { - packlength= len_arg <= 255 ? 1 : - len_arg <= 65535 ? 2 : - len_arg <= 16777215 ? 3 : 4; - } + packlength= set_packlength ? number_storage_requirement(len_arg) : 4; } Field_blob(uint32 packlength_arg) :Field_longstr((uchar*) 0, 0, (uchar*) "", 0, NONE, &temp_lex_str, @@ -3301,7 +3482,8 @@ public: if (from->type() == MYSQL_TYPE_BIT) return do_field_int; */ - if (!(from->flags & BLOB_FLAG) || from->charset() != charset()) + if (!(from->flags & BLOB_FLAG) || from->charset() != charset() || + !from->compression_method() != !compression_method()) return do_conv_blob; if (from->pack_length() != Field_blob::pack_length()) return do_copy_blob; @@ -3318,11 +3500,11 @@ public: bool memcpy_field_possible(const Field *from) const { return Field_str::memcpy_field_possible(from) && + !compression_method() == !from->compression_method() && !table->copy_blobs; } - int store(const char *to,uint length,CHARSET_INFO *charset); - int store(double nr); - int store(longlong nr, bool unsigned_val); + int store(const char *to, uint length, CHARSET_INFO *charset); + using Field_str::store; double val_real(void); longlong val_int(void); String *val_str(String*,String *); @@ -3456,7 +3638,54 @@ public: uint32 char_length() const; uint is_equal(Create_field *new_field); private: - int do_save_field_metadata(uchar *first_byte); + int save_field_metadata(uchar *first_byte); +}; + + +class Field_blob_compressed: public Field_blob { +public: + Field_blob_compressed(uchar *ptr_arg, uchar *null_ptr_arg, + uchar null_bit_arg, enum utype unireg_check_arg, + const LEX_CSTRING *field_name_arg, TABLE_SHARE *share, + uint blob_pack_length, const DTCollation &collation, + Compression_method *compression_method_arg): + Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, + field_name_arg, share, blob_pack_length, collation), + compression_method_ptr(compression_method_arg) {} + Compression_method *compression_method() const + { return compression_method_ptr; } +private: + Compression_method *compression_method_ptr; + int store(const char *to, uint length, CHARSET_INFO *charset); + using Field_str::store; + String *val_str(String *, String *); + double val_real(void); + longlong val_int(void); + uint size_of() const { return sizeof(*this); } + enum_field_types binlog_type() const { return MYSQL_TYPE_BLOB_COMPRESSED; } + void sql_type(String &str) const + { + Field_blob::sql_type(str); + str.append(STRING_WITH_LEN(" /*!100301 COMPRESSED*/")); + } + + /* + Compressed fields can't have keys as two rows may have different + compression methods or compression levels. + */ + + uint get_key_image(uchar *buff, uint length, imagetype type_arg) + { DBUG_ASSERT(0); return 0; } + void set_key_image(const uchar *buff, uint length) + { DBUG_ASSERT(0); } + int key_cmp(const uchar *a, const uchar *b) + { DBUG_ASSERT(0); return 0; } + int key_cmp(const uchar *str, uint length) + { DBUG_ASSERT(0); return 0; } + Field *new_key_field(MEM_ROOT *root, TABLE *new_table, + uchar *new_ptr, uint32 length, + uchar *new_null_ptr, uint new_null_bit) + { DBUG_ASSERT(0); return 0; } }; @@ -3621,7 +3850,7 @@ public: const Item *item, bool is_eq_func) const; private: - int do_save_field_metadata(uchar *first_byte); + int save_field_metadata(uchar *first_byte); uint is_equal(Create_field *new_field); }; @@ -3799,7 +4028,7 @@ public: private: virtual size_t do_last_null_byte() const; - int do_save_field_metadata(uchar *first_byte); + int save_field_metadata(uchar *first_byte); }; @@ -3848,7 +4077,8 @@ Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root, CHARSET_INFO *cs, Field::geometry_type geom_type, uint srid, Field::utype unireg_check, - TYPELIB *interval, const LEX_CSTRING *field_name); + TYPELIB *interval, const LEX_CSTRING *field_name, + uint32 flags); /* Create field class for CREATE TABLE @@ -3898,15 +4128,23 @@ class Column_definition: public Sql_alloc, 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 + Compression_method *compression_method_ptr; public: LEX_CSTRING field_name; LEX_CSTRING comment; // Comment for field + enum enum_column_versioning + { + VERSIONING_NOT_SET, + WITH_VERSIONING, + WITHOUT_VERSIONING + }; Item *on_update; // ON UPDATE NOW() /* At various stages in execution this can be length of field in bytes or max number of characters. */ ulonglong length; + field_visibility_t invisible; /* The value of `length' as set by parser: is the number of characters for most of the types, or of bytes for BLOBs or numeric types. @@ -3933,18 +4171,23 @@ public: *default_value, // Default value *check_constraint; // Check constraint + enum_column_versioning versioning; + Column_definition() :Type_handler_hybrid_field_type(&type_handler_null), + compression_method_ptr(0), comment(null_clex_str), - on_update(NULL), length(0), decimals(0), + on_update(NULL), length(0), invisible(VISIBLE), decimals(0), flags(0), pack_length(0), key_length(0), unireg_check(Field::NONE), 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) + vcol_info(0), default_value(0), check_constraint(0), + versioning(VERSIONING_NOT_SET) { interval_list.empty(); } + Column_definition(THD *thd, Field *field, Field *orig_field); void set_attributes(const Lex_field_type_st &type, CHARSET_INFO *cs); void create_length_to_internal_length_null() @@ -3959,6 +4202,8 @@ public: void create_length_to_internal_length_string() { length*= charset->mbmaxlen; + if (real_field_type() == MYSQL_TYPE_VARCHAR && compression_method()) + length++; DBUG_ASSERT(length <= UINT_MAX32); key_length= (uint) length; pack_length= type_handler()->calc_pack_length((uint32) length); @@ -4069,7 +4314,7 @@ public: (uint32)length, null_pos, null_bit, pack_flag, type_handler(), charset, geom_type, srid, unireg_check, interval, - field_name_arg); + field_name_arg, flags); } Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *field_name_arg) const @@ -4108,6 +4353,11 @@ public: { *this= *def; } + bool set_compressed(const char *method); + void set_compression_method(Compression_method *compression_method_arg) + { compression_method_ptr= compression_method_arg; } + Compression_method *compression_method() const + { return compression_method_ptr; } }; @@ -4406,5 +4656,21 @@ bool check_expression(Virtual_column_info *vcol, LEX_CSTRING *name, #define f_no_default(x) ((x) & FIELDFLAG_NO_DEFAULT) #define f_bit_as_char(x) ((x) & FIELDFLAG_TREAT_BIT_AS_CHAR) #define f_is_hex_escape(x) ((x) & FIELDFLAG_HEX_ESCAPE) +#define f_visibility(x) (static_cast<field_visibility_t> ((x) & INVISIBLE_MAX_BITS)) + +inline +ulonglong TABLE::vers_end_id() const +{ + DBUG_ASSERT(versioned(VERS_TRX_ID)); + return static_cast<ulonglong>(vers_end_field()->val_int()); +} + +inline +ulonglong TABLE::vers_start_id() const +{ + DBUG_ASSERT(versioned(VERS_TRX_ID)); + return static_cast<ulonglong>(vers_start_field()->val_int()); +} + #endif /* FIELD_INCLUDED */ |