diff options
Diffstat (limited to 'sql/field.h')
-rw-r--r-- | sql/field.h | 324 |
1 files changed, 191 insertions, 133 deletions
diff --git a/sql/field.h b/sql/field.h index c3a90dc0754..9604f3fe227 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1,4 +1,7 @@ -/* Copyright (C) 2000-2006 MySQL AB +#ifndef FIELD_INCLUDED +#define FIELD_INCLUDED + +/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,7 +16,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - /* Because of the function new_field() all field classes that have static variables must declare the size_of() member function. @@ -29,6 +31,8 @@ const uint32 max_field_size= (uint32) 4294967295U; class Send_field; class Protocol; class Create_field; +class Relay_log_info; + struct st_cache_field; int field_conv(Field *to,Field *from); @@ -48,7 +52,8 @@ class Field Field(const Item &); /* Prevent use of these */ void operator=(Field &); public: - static void *operator new(size_t size) {return sql_alloc(size); } + static void *operator new(size_t size) throw () + { return sql_alloc(size); } static void operator delete(void *ptr_arg, size_t size) { TRASH(ptr_arg, size); } uchar *ptr; // Position to field in record @@ -57,8 +62,8 @@ public: Note that you can use table->in_use as replacement for current_thd member only inside of val_*() and store() members (e.g. you can't use it in cons) */ - struct st_table *table; // Pointer for table - struct st_table *orig_table; // Pointer to original table + TABLE *table; // Pointer for table + TABLE *orig_table; // Pointer to original table const char **table_name, *field_name; LEX_STRING comment; /* Field is part of the following keys */ @@ -144,7 +149,7 @@ public: virtual bool eq(Field *field) { return (ptr == field->ptr && null_ptr == field->null_ptr && - null_bit == field->null_bit); + null_bit == field->null_bit && field->type() == type()); } virtual bool eq_def(Field *field); @@ -161,7 +166,8 @@ public: table, which is located on disk). */ virtual uint32 pack_length_in_rec() const { return pack_length(); } - virtual int compatible_field_size(uint field_metadata); + virtual int compatible_field_size(uint field_metadata, + const Relay_log_info *); virtual uint pack_length_from_metadata(uint field_metadata) { return field_metadata; } /* @@ -205,7 +211,7 @@ public: memcpy(ptr, ptr + l_offset, pack_length()); if (null_ptr) *null_ptr= ((*null_ptr & (uchar) ~null_bit) | - null_ptr[l_offset] & null_bit); + (null_ptr[l_offset] & null_bit)); } virtual bool binary() const { return 1; } virtual bool zero_pack() const { return 1; } @@ -297,12 +303,12 @@ public: */ virtual bool can_be_compared_as_longlong() const { return FALSE; } virtual void free() {} - virtual Field *new_field(MEM_ROOT *root, struct st_table *new_table, + virtual Field *new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type); - virtual Field *new_key_field(MEM_ROOT *root, struct st_table *new_table, + virtual Field *new_key_field(MEM_ROOT *root, TABLE *new_table, uchar *new_ptr, uchar *new_null_ptr, uint new_null_bit); - Field *clone(MEM_ROOT *mem_root, struct st_table *new_table); + Field *clone(MEM_ROOT *mem_root, TABLE *new_table); inline void move_field(uchar *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg) { ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg; @@ -403,32 +409,11 @@ public: DBUG_RETURN(result); } - virtual uchar *pack_key(uchar* to, const uchar *from, - uint max_length, bool low_byte_first) - { - return pack(to, from, max_length, low_byte_first); - } - virtual uchar *pack_key_from_key_image(uchar* to, const uchar *from, - uint max_length, bool low_byte_first) - { - return pack(to, from, max_length, low_byte_first); - } - virtual const uchar *unpack_key(uchar* to, const uchar *from, - uint max_length, bool low_byte_first) - { - return unpack(to, from, max_length, low_byte_first); - } virtual uint packed_col_length(const uchar *to, uint length) { return length;} virtual uint max_packed_col_length(uint max_length) { return max_length;} - virtual int pack_cmp(const uchar *a,const uchar *b, uint key_length_arg, - my_bool insert_or_update) - { return cmp(a,b); } - virtual int pack_cmp(const uchar *b, uint key_length_arg, - my_bool insert_or_update) - { return cmp(ptr,b); } uint offset(uchar *record) { return (uint) (ptr - record); @@ -468,6 +453,13 @@ public: /* maximum possible display length */ virtual uint32 max_display_length()= 0; + /** + Whether a field being created is compatible with a existing one. + + Used by the ALTER TABLE code to evaluate whether the new definition + of a table is compatible with the old definition so that it can + determine if data needs to be copied over (table data change). + */ virtual uint is_equal(Create_field *new_field); /* convert decimal to longlong with overflow check */ longlong convert_decimal2longlong(const my_decimal *val, bool unsigned_flag, @@ -528,11 +520,86 @@ private: */ virtual int do_save_field_metadata(uchar *metadata_ptr) { return 0; } + +protected: + /* + Helper function to pack()/unpack() int32 values + */ + static void handle_int32(uchar *to, const uchar *from, + bool low_byte_first_from, bool low_byte_first_to) + { + int32 val; +#ifdef WORDS_BIGENDIAN + if (low_byte_first_from) + val = sint4korr(from); + else +#endif + longget(val, from); + +#ifdef WORDS_BIGENDIAN + if (low_byte_first_to) + int4store(to, val); + else +#endif + longstore(to, val); + } + + /* + Helper function to pack()/unpack() int64 values + */ + static void handle_int64(uchar* to, const uchar *from, + bool low_byte_first_from, bool low_byte_first_to) + { + int64 val; +#ifdef WORDS_BIGENDIAN + if (low_byte_first_from) + val = sint8korr(from); + else +#endif + longlongget(val, from); + +#ifdef WORDS_BIGENDIAN + if (low_byte_first_to) + int8store(to, val); + else +#endif + longlongstore(to, val); + } + + uchar *pack_int32(uchar *to, const uchar *from, bool low_byte_first_to) + { + handle_int32(to, from, table->s->db_low_byte_first, low_byte_first_to); + return to + sizeof(int32); + } + + const uchar *unpack_int32(uchar* to, const uchar *from, + bool low_byte_first_from) + { + handle_int32(to, from, low_byte_first_from, table->s->db_low_byte_first); + return from + sizeof(int32); + } + + uchar *pack_int64(uchar* to, const uchar *from, bool low_byte_first_to) + { + handle_int64(to, from, table->s->db_low_byte_first, low_byte_first_to); + return to + sizeof(int64); + } + + const uchar *unpack_int64(uchar* to, const uchar *from, + bool low_byte_first_from) + { + handle_int64(to, from, low_byte_first_from, table->s->db_low_byte_first); + return from + sizeof(int64); + } }; class Field_num :public Field { public: + /** + The scale of the Field's value, i.e. the number of digits to the right + of the decimal point. + */ const uint8 dec; bool zerofill,unsigned_flag; // Purify cannot handle bit fields Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, @@ -593,7 +660,8 @@ public: class Field_longstr :public Field_str { protected: - int report_if_important_data(const char *ptr, const char *end); + int report_if_important_data(const char *ptr, const char *end, + bool count_spaces); public: Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, @@ -690,6 +758,11 @@ public: Field_new_decimal(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg, uint8 dec_arg, bool unsigned_arg); + /* + Create a field to hold a decimal value from an item. + Truncates the precision and/or scale if necessary. + */ + static Field_new_decimal *new_decimal_field(const Item *item); enum_field_types type() const { return MYSQL_TYPE_NEWDECIMAL;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; } Item_result result_type () const { return DECIMAL_RESULT; } @@ -714,7 +787,8 @@ public: uint32 pack_length() const { return (uint32) bin_size; } uint pack_length_from_metadata(uint field_metadata); uint row_pack_length() { return pack_length(); } - int compatible_field_size(uint field_metadata); + int compatible_field_size(uint field_metadata, + const Relay_log_info *rli); uint is_equal(Create_field *new_field); virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data, bool low_byte_first); @@ -914,43 +988,16 @@ public: void sql_type(String &str) const; uint32 max_display_length() { return MY_INT32_NUM_DECIMAL_DIGITS; } virtual uchar *pack(uchar* to, const uchar *from, - uint max_length, bool low_byte_first) + uint max_length __attribute__((unused)), + bool low_byte_first) { - int32 val; -#ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) - val = sint4korr(from); - else -#endif - longget(val, from); - -#ifdef WORDS_BIGENDIAN - if (low_byte_first) - int4store(to, val); - else -#endif - longstore(to, val); - return to + sizeof(val); + return pack_int32(to, from, low_byte_first); } - virtual const uchar *unpack(uchar* to, const uchar *from, - uint param_data, bool low_byte_first) + uint param_data __attribute__((unused)), + bool low_byte_first) { - int32 val; -#ifdef WORDS_BIGENDIAN - if (low_byte_first) - val = sint4korr(from); - else -#endif - longget(val, from); - -#ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) - int4store(to, val); - else -#endif - longstore(to, val); - return from + sizeof(val); + return unpack_int32(to, from, low_byte_first); } }; @@ -995,43 +1042,16 @@ public: bool can_be_compared_as_longlong() const { return TRUE; } uint32 max_display_length() { return 20; } virtual uchar *pack(uchar* to, const uchar *from, - uint max_length, bool low_byte_first) + uint max_length __attribute__((unused)), + bool low_byte_first) { - int64 val; -#ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) - val = sint8korr(from); - else -#endif - longlongget(val, from); - -#ifdef WORDS_BIGENDIAN - if (low_byte_first) - int8store(to, val); - else -#endif - longlongstore(to, val); - return to + sizeof(val); + return pack_int64(to, from, low_byte_first); } - virtual const uchar *unpack(uchar* to, const uchar *from, - uint param_data, bool low_byte_first) + uint param_data __attribute__((unused)), + bool low_byte_first) { - int64 val; -#ifdef WORDS_BIGENDIAN - if (low_byte_first) - val = sint8korr(from); - else -#endif - longlongget(val, from); - -#ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) - int8store(to, val); - else -#endif - longlongstore(to, val); - return from + sizeof(val); + return unpack_int64(to, from, low_byte_first); } }; #endif @@ -1205,6 +1225,17 @@ public: bool get_date(MYSQL_TIME *ltime,uint fuzzydate); bool get_time(MYSQL_TIME *ltime); timestamp_auto_set_type get_auto_set_type() const; + uchar *pack(uchar *to, const uchar *from, + uint max_length __attribute__((unused)), bool low_byte_first) + { + return pack_int32(to, from, low_byte_first); + } + const uchar *unpack(uchar* to, const uchar *from, + uint param_data __attribute__((unused)), + bool low_byte_first) + { + return unpack_int32(to, from, low_byte_first); + } }; @@ -1259,6 +1290,17 @@ public: void sql_type(String &str) const; bool can_be_compared_as_longlong() const { return TRUE; } bool zero_pack() const { return 1; } + uchar *pack(uchar* to, const uchar *from, + uint max_length __attribute__((unused)), bool low_byte_first) + { + return pack_int32(to, from, low_byte_first); + } + const uchar *unpack(uchar* to, const uchar *from, + uint param_data __attribute__((unused)), + bool low_byte_first) + { + return unpack_int32(to, from, low_byte_first); + } }; @@ -1372,6 +1414,17 @@ public: bool zero_pack() const { return 1; } bool get_date(MYSQL_TIME *ltime,uint fuzzydate); bool get_time(MYSQL_TIME *ltime); + uchar *pack(uchar* to, const uchar *from, + uint max_length __attribute__((unused)), bool low_byte_first) + { + return pack_int64(to, from, low_byte_first); + } + const uchar *unpack(uchar* to, const uchar *from, + uint param_data __attribute__((unused)), + bool low_byte_first) + { + return unpack_int64(to, from, low_byte_first); + } }; @@ -1423,18 +1476,22 @@ public: virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data, bool low_byte_first); uint pack_length_from_metadata(uint field_metadata) - { return (field_metadata & 0x00ff); } + { + DBUG_PRINT("debug", ("field_metadata: 0x%04x", field_metadata)); + if (field_metadata == 0) + return row_pack_length(); + return (((field_metadata >> 4) & 0x300) ^ 0x300) + (field_metadata & 0x00ff); + } + int compatible_field_size(uint field_metadata, + const Relay_log_info *rli); uint row_pack_length() { return (field_length + 1); } - int pack_cmp(const uchar *a,const uchar *b,uint key_length, - my_bool insert_or_update); - int pack_cmp(const uchar *b,uint key_length,my_bool insert_or_update); 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 *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type); + Field *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); @@ -1501,16 +1558,8 @@ public: void sql_type(String &str) const; virtual uchar *pack(uchar *to, const uchar *from, uint max_length, bool low_byte_first); - uchar *pack_key(uchar *to, const uchar *from, uint max_length, bool low_byte_first); - uchar *pack_key_from_key_image(uchar* to, const uchar *from, - uint max_length, bool low_byte_first); virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data, bool low_byte_first); - const uchar *unpack_key(uchar* to, const uchar *from, - uint max_length, bool low_byte_first); - int pack_cmp(const uchar *a, const uchar *b, uint key_length, - my_bool insert_or_update); - int pack_cmp(const uchar *b, uint key_length,my_bool insert_or_update); int cmp_binary(const uchar *a,const uchar *b, uint32 max_length=~0L); int key_cmp(const uchar *,const uchar*); int key_cmp(const uchar *str, uint length); @@ -1521,8 +1570,8 @@ public: enum_field_types real_type() const { return MYSQL_TYPE_VARCHAR; } bool has_charset(void) const { return charset() == &my_charset_bin ? FALSE : TRUE; } - Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type); - Field *new_key_field(MEM_ROOT *root, struct st_table *new_table, + Field *new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type); + Field *new_key_field(MEM_ROOT *root, TABLE *new_table, uchar *new_ptr, uchar *new_null_ptr, uint new_null_bit); uint is_equal(Create_field *new_field); @@ -1534,8 +1583,16 @@ private: class Field_blob :public Field_longstr { protected: + /** + The number of bytes used to represent the length of the blob. + */ uint packlength; - String value; // For temporaries + + /** + The 'value'-object is a cache fronting the storage engine. + */ + String value; + public: Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, @@ -1606,6 +1663,7 @@ public: } int reset(void) { bzero(ptr, packlength+sizeof(uchar*)); return 0; } void reset_fields() { bzero((uchar*) &value,sizeof(value)); } + uint32 get_field_buffer_size(void) { return value.alloced_length(); } #ifndef WORDS_BIGENDIAN static #endif @@ -1677,17 +1735,8 @@ public: } virtual uchar *pack(uchar *to, const uchar *from, uint max_length, bool low_byte_first); - uchar *pack_key(uchar *to, const uchar *from, - uint max_length, bool low_byte_first); - uchar *pack_key_from_key_image(uchar* to, const uchar *from, - uint max_length, bool low_byte_first); virtual const uchar *unpack(uchar *to, const uchar *from, uint param_data, bool low_byte_first); - const uchar *unpack_key(uchar* to, const uchar *from, - uint max_length, bool low_byte_first); - int pack_cmp(const uchar *a, const uchar *b, uint key_length, - my_bool insert_or_update); - int pack_cmp(const uchar *b, uint key_length,my_bool insert_or_update); uint packed_col_length(const uchar *col_ptr, uint length); uint max_packed_col_length(uint max_length); void free() { value.free(); } @@ -1752,7 +1801,7 @@ public: { flags|=ENUM_FLAG; } - Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type); + Field *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; } enum Item_result cast_to_int_type () const { return INT_RESULT; } @@ -1781,6 +1830,7 @@ public: CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; } private: int do_save_field_metadata(uchar *first_byte); + uint is_equal(Create_field *new_field); }; @@ -1851,9 +1901,12 @@ public: virtual bool str_needs_quotes() { return TRUE; } my_decimal *val_decimal(my_decimal *); int cmp(const uchar *a, const uchar *b) - { - DBUG_ASSERT(ptr == a); - return Field_bit::key_cmp(b, bytes_in_rec+test(bit_len)); + { + DBUG_ASSERT(ptr == a || ptr == b); + if (ptr == a) + return Field_bit::key_cmp(b, bytes_in_rec+test(bit_len)); + else + return Field_bit::key_cmp(a, bytes_in_rec+test(bit_len)) * -1; } int cmp_binary_offset(uint row_offset) { return cmp_offset(row_offset); } @@ -1876,7 +1929,8 @@ public: uint pack_length_from_metadata(uint field_metadata); uint row_pack_length() { return (bytes_in_rec + ((bit_len > 0) ? 1 : 0)); } - int compatible_field_size(uint field_metadata); + int compatible_field_size(uint field_metadata, + const Relay_log_info *rli); void sql_type(String &str) const; virtual uchar *pack(uchar *to, const uchar *from, uint max_length, bool low_byte_first); @@ -1884,7 +1938,7 @@ public: uint param_data, bool low_byte_first); virtual void set_default(); - Field *new_key_field(MEM_ROOT *root, struct st_table *new_table, + Field *new_key_field(MEM_ROOT *root, TABLE *new_table, uchar *new_ptr, uchar *new_null_ptr, uint new_null_bit); void set_bit_ptr(uchar *bit_ptr_arg, uchar bit_ofs_arg) @@ -1895,7 +1949,6 @@ public: bool eq(Field *field) { return (Field::eq(field) && - field->type() == type() && bit_ptr == ((Field_bit *)field)->bit_ptr && bit_ofs == ((Field_bit *)field)->bit_ofs); } @@ -1905,6 +1958,7 @@ public: Field::move_field_offset(ptr_diff); bit_ptr= ADD_TO_PTR(bit_ptr, ptr_diff, uchar*); } + void hash(ulong *nr, ulong *nr2); private: virtual size_t do_last_null_byte() const; @@ -1993,7 +2047,7 @@ public: A class for sending info to the client */ -class Send_field { +class Send_field :public Sql_alloc { public: const char *db_name; const char *table_name,*org_table_name; @@ -2069,6 +2123,7 @@ int set_field_to_null_with_conversions(Field *field, bool no_conversions); #define FIELDFLAG_NO_DEFAULT 16384 /* sql */ #define FIELDFLAG_SUM ((uint) 32768)// predit: +#fieldflag #define FIELDFLAG_MAYBE_NULL ((uint) 32768)// sql +#define FIELDFLAG_HEX_ESCAPE ((uint) 0x10000) #define FIELDFLAG_PACK_SHIFT 3 #define FIELDFLAG_DEC_SHIFT 8 #define FIELDFLAG_MAX_DEC 31 @@ -2094,3 +2149,6 @@ int set_field_to_null_with_conversions(Field *field, bool no_conversions); #define f_maybe_null(x) (x & FIELDFLAG_MAYBE_NULL) #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) + +#endif /* FIELD_INCLUDED */ |