diff options
Diffstat (limited to 'sql/field.h')
-rw-r--r-- | sql/field.h | 586 |
1 files changed, 378 insertions, 208 deletions
diff --git a/sql/field.h b/sql/field.h index 3e258f81dcc..966549516b1 100644 --- a/sql/field.h +++ b/sql/field.h @@ -20,33 +20,74 @@ variables must declare the size_of() member function. */ -#ifdef __GNUC__ +#ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #define NOT_FIXED_DEC 31 +#define DATETIME_DEC 6 class Send_field; +class Protocol; struct st_cache_field; void field_conv(Field *to,Field *from); -class Field { +inline uint get_enum_pack_length(int elements) +{ + return elements < 256 ? 1 : 2; +} + +inline uint get_set_pack_length(int elements) +{ + uint len= (elements + 7) / 8; + return len > 4 ? 8 : len; +} + +class Field +{ Field(const Item &); /* Prevent use of these */ void operator=(Field &); public: static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); } - static void operator delete(void *ptr_arg, size_t size) {} /*lint -e715 */ + static void operator delete(void *ptr_arg, size_t size) { +#ifdef SAFEMALLOC + bfill(ptr_arg, size, 0x8F); +#endif + } char *ptr; // Position to field in record uchar *null_ptr; // Byte where null_bit is + /* + 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 const char *table_name,*field_name; + LEX_STRING comment; ulong query_id; // For quick test of used fields /* Field is part of the following keys */ - key_map key_start,part_of_key,part_of_sortkey; + key_map key_start,part_of_key,part_of_sortkey; + /* + We use three additional unireg types for TIMESTAMP to overcome limitation + of current binary format of .frm file. We'd like to be able to support + NOW() as default and on update value for such fields but unable to hold + this info anywhere except unireg_check field. This issue will be resolved + in more clean way with transition to new text based .frm format. + See also comment for Field_timestamp::Field_timestamp(). + */ enum utype { NONE,DATE,SHIELD,NOEMPTY,CASEUP,PNR,BGNR,PGNR,YES,NO,REL, CHECK,EMPTY,UNKNOWN_FIELD,CASEDN,NEXT_NUMBER,INTERVAL_FIELD, - BIT_FIELD, TIMESTAMP_FIELD,CAPITALIZE,BLOB_FIELD}; + BIT_FIELD, TIMESTAMP_OLD_FIELD, CAPITALIZE, BLOB_FIELD, + TIMESTAMP_DN_FIELD, TIMESTAMP_UN_FIELD, TIMESTAMP_DNUN_FIELD}; + enum geometry_type + { + GEOM_GEOMETRY = 0, GEOM_POINT = 1, GEOM_LINESTRING = 2, GEOM_POLYGON = 3, + GEOM_MULTIPOINT = 4, GEOM_MULTILINESTRING = 5, GEOM_MULTIPOLYGON = 6, + GEOM_GEOMETRYCOLLECTION = 7 + }; + enum imagetype { itRAW, itMBR}; + utype unireg_check; uint32 field_length; // Length of field uint16 flags; @@ -56,15 +97,32 @@ public: utype unireg_check_arg, const char *field_name_arg, struct st_table *table_arg); virtual ~Field() {} - virtual void store(const char *to,uint length)=0; - virtual void store(double nr)=0; - virtual void store(longlong nr)=0; + /* Store functions returns 1 on overflow and -1 on fatal error */ + virtual int store(const char *to,uint length,CHARSET_INFO *cs)=0; + virtual int store(double nr)=0; + virtual int store(longlong nr)=0; virtual void store_time(TIME *ltime,timestamp_type t_type); virtual double val_real(void)=0; virtual longlong val_int(void)=0; + inline String *val_str(String *str) { return val_str(str, str); } + /* + val_str(buf1, buf2) gets two buffers and should use them as follows: + if it needs a temp buffer to convert result to string - use buf1 + example Field_tiny::val_str() + if the value exists as a string already - use buf2 + example Field_string::val_str() + consequently, buf2 may be created as 'String buf;' - no memory + will be allocated for it. buf1 will be allocated to hold a + value if it's too small. Using allocated buffer for buf2 may result in + an unnecessary free (and later, may be an alloc). + This trickery is used to decrease a number of malloc calls. + */ virtual String *val_str(String*,String *)=0; virtual Item_result result_type () const=0; virtual Item_result cmp_type () const { return result_type(); } + virtual Item_result cast_to_int_type () const { return result_type(); } + static enum_field_types field_type_merge(enum_field_types, enum_field_types); + static Item_result result_merge_type(enum_field_types); bool eq(Field *field) { return ptr == field->ptr && null_ptr == field->null_ptr; } virtual bool eq_def(Field *field); virtual uint32 pack_length() const { return (uint32) field_length; } @@ -72,7 +130,7 @@ public: virtual void reset_fields() {} virtual void set_default() { - my_ptrdiff_t offset = (my_ptrdiff_t) (table->record[2] - + my_ptrdiff_t offset = (my_ptrdiff_t) (table->default_values - table->record[0]); memcpy(ptr, ptr + offset, pack_length()); if (null_ptr) @@ -109,6 +167,13 @@ public: { return null_ptr ? (null_ptr[row_offset] & null_bit ? 1 : 0) : table->null_row; } inline bool is_real_null(uint row_offset=0) { return null_ptr ? (null_ptr[row_offset] & null_bit ? 1 : 0) : 0; } + inline bool is_null_in_record(const uchar *record) + { + if (!null_ptr) + return 0; + return test(record[(uint) (null_ptr - (uchar*) table->record[0])] & + null_bit); + } inline void set_null(int row_offset=0) { if (null_ptr) null_ptr[row_offset]|= null_bit; } inline void set_notnull(int row_offset=0) @@ -117,8 +182,16 @@ public: inline bool real_maybe_null(void) { return null_ptr != 0; } virtual void make_field(Send_field *)=0; virtual void sort_string(char *buff,uint length)=0; - virtual bool optimize_range(uint idx); - virtual bool store_for_compare() { return 0; } + virtual bool optimize_range(uint idx, uint part); + /* + This should be true for fields which, when compared with constant + items, can be casted to longlong. In this case we will at 'fix_fields' + stage cast the constant items to longlongs and at the execution stage + use field->val_int() for comparison. Used to optimize clauses like + 'a_column BETWEEN date_const, date_const'. + */ + virtual bool can_be_compared_as_longlong() const { return FALSE; } + virtual void free() {} Field *new_field(MEM_ROOT *root, struct st_table *new_table) { Field *tmp= (Field*) memdup_root(root,(char*) this,size_of()); @@ -126,10 +199,16 @@ public: { if (tmp->table->maybe_null) tmp->flags&= ~NOT_NULL_FLAG; - tmp->table=new_table; - tmp->key_start=tmp->part_of_key=tmp->part_of_sortkey=0; + tmp->table= new_table; + tmp->key_start.init(0); + tmp->part_of_key.init(0); + tmp->part_of_sortkey.init(0); tmp->unireg_check=Field::NONE; - tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG | ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG); + tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG | + ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG); +#ifdef PROBABLY_WRONG + tmp->table_name= new_table->table_name; +#endif tmp->reset_fields(); } return tmp; @@ -145,21 +224,15 @@ public: if (null_ptr) null_ptr=ADD_TO_PTR(null_ptr,ptr_diff,uchar*); } - inline void get_image(char *buff,uint length) + inline void get_image(char *buff,uint length, CHARSET_INFO *cs) { memcpy(buff,ptr,length); } - inline void set_image(char *buff,uint length) + inline void set_image(char *buff,uint length, CHARSET_INFO *cs) { memcpy(ptr,buff,length); } - virtual void get_key_image(char *buff,uint length) - { get_image(buff,length); } - virtual void set_key_image(char *buff,uint length) - { set_image(buff,length); } - inline int cmp_image(char *buff,uint length) - { - if (binary()) - return memcmp(ptr,buff,length); - else - return my_casecmp(ptr,buff,length); - } + virtual void get_key_image(char *buff,uint length, CHARSET_INFO *cs, + imagetype type) + { get_image(buff,length,cs); } + virtual void set_key_image(char *buff,uint length, CHARSET_INFO *cs) + { set_image(buff,length,cs); } inline longlong val_int_offset(uint row_offset) { ptr+=row_offset; @@ -167,7 +240,7 @@ public: ptr-=row_offset; return tmp; } - bool send(THD *thd, String *packet); + virtual bool send_binary(Protocol *protocol); virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0) { uint32 length=pack_length(); @@ -205,8 +278,24 @@ public: uint offset(); // Should be inline ... void copy_from_tmp(int offset); uint fill_cache_field(struct st_cache_field *copy); - virtual bool get_date(TIME *ltime,bool fuzzydate); + virtual bool get_date(TIME *ltime,uint fuzzydate); virtual bool get_time(TIME *ltime); + virtual CHARSET_INFO *charset(void) const { return &my_charset_bin; } + virtual CHARSET_INFO *sort_charset(void) const { return charset(); } + virtual bool has_charset(void) const { return FALSE; } + virtual void set_charset(CHARSET_INFO *charset) { } + bool set_warning(const unsigned int level, const unsigned int code, + int cuted_increment); + void set_datetime_warning(const uint level, const uint code, + const char *str, uint str_len, + timestamp_type ts_type, int cuted_increment); + void set_datetime_warning(const uint level, const uint code, + longlong nr, timestamp_type ts_type, + int cuted_increment); + void set_datetime_warning(const uint level, const uint code, + double nr, timestamp_type ts_type); + /* maximum possible display length */ + virtual uint32 max_length()= 0; friend bool reopen_table(THD *,struct st_table *,bool); friend int cre_myisam(my_string name, register TABLE *form, uint options, ulonglong auto_increment_value); @@ -221,6 +310,7 @@ public: friend class Item_sum_std; friend class Item_sum_min; friend class Item_sum_max; + friend class Item_func_group_concat; }; @@ -254,20 +344,32 @@ public: class Field_str :public Field { +protected: + CHARSET_INFO *field_charset; public: - double ceiling; // for ::store(double nr) Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, const char *field_name_arg, - struct st_table *table_arg) + struct st_table *table_arg,CHARSET_INFO *charset) :Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, table_arg), ceiling(0.0) - {} + unireg_check_arg, field_name_arg, table_arg) + { + field_charset=charset; + if (charset->state & MY_CS_BINSORT) + flags|=BINARY_FLAG; + } Item_result result_type () const { return STRING_RESULT; } uint decimals() const { return NOT_FIXED_DEC; } - friend class create_field; + int store(double nr); + int store(longlong nr)=0; + int store(const char *to,uint length,CHARSET_INFO *cs)=0; void make_field(Send_field *); uint size_of() const { return sizeof(*this); } + CHARSET_INFO *charset(void) const { return field_charset; } + void set_charset(CHARSET_INFO *charset) { field_charset=charset; } + bool binary() const { return field_charset == &my_charset_bin; } + uint32 max_length() { return field_length; } + friend class create_field; }; @@ -284,11 +386,11 @@ public: {} enum_field_types type() const { return FIELD_TYPE_DECIMAL;} enum ha_base_keytype key_type() const - { return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; } + { return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; } void reset(void); - void store(const char *to,uint length); - void store(double nr); - void store(longlong nr); + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); double val_real(void); longlong val_int(void); String *val_str(String*,String *); @@ -297,6 +399,7 @@ public: void overflow(bool negative); bool zero_pack() const { return 0; } void sql_type(String &str) const; + uint32 max_length() { return field_length; } }; @@ -315,17 +418,19 @@ public: enum_field_types type() const { return FIELD_TYPE_TINY;} enum ha_base_keytype key_type() const { return unsigned_flag ? HA_KEYTYPE_BINARY : HA_KEYTYPE_INT8; } - void store(const char *to,uint length); - void store(double nr); - void store(longlong nr); + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); void reset(void) { ptr[0]=0; } double val_real(void); longlong val_int(void); String *val_str(String*,String *); + bool send_binary(Protocol *protocol); int cmp(const char *,const char*); void sort_string(char *buff,uint length); uint32 pack_length() const { return 1; } void sql_type(String &str) const; + uint32 max_length() { return 4; } }; @@ -340,21 +445,28 @@ public: unireg_check_arg, field_name_arg, table_arg, 0, zero_arg,unsigned_arg) {} + Field_short(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, + struct st_table *table_arg,bool unsigned_arg) + :Field_num((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0, + NONE, field_name_arg, table_arg,0,0,unsigned_arg) + {} enum Item_result result_type () const { return INT_RESULT; } enum_field_types type() const { return FIELD_TYPE_SHORT;} enum ha_base_keytype key_type() const { return unsigned_flag ? HA_KEYTYPE_USHORT_INT : HA_KEYTYPE_SHORT_INT;} - void store(const char *to,uint length); - void store(double nr); - void store(longlong nr); + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); void reset(void) { ptr[0]=ptr[1]=0; } double val_real(void); longlong val_int(void); String *val_str(String*,String *); + bool send_binary(Protocol *protocol); int cmp(const char *,const char*); void sort_string(char *buff,uint length); uint32 pack_length() const { return 2; } void sql_type(String &str) const; + uint32 max_length() { return 6; } }; @@ -373,17 +485,19 @@ public: enum_field_types type() const { return FIELD_TYPE_INT24;} enum ha_base_keytype key_type() const { return unsigned_flag ? HA_KEYTYPE_UINT24 : HA_KEYTYPE_INT24; } - void store(const char *to,uint length); - void store(double nr); - void store(longlong nr); + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); void reset(void) { ptr[0]=ptr[1]=ptr[2]=0; } double val_real(void); longlong val_int(void); String *val_str(String*,String *); + bool send_binary(Protocol *protocol); int cmp(const char *,const char*); void sort_string(char *buff,uint length); uint32 pack_length() const { return 3; } void sql_type(String &str) const; + uint32 max_length() { return 8; } }; @@ -407,17 +521,19 @@ public: enum_field_types type() const { return FIELD_TYPE_LONG;} enum ha_base_keytype key_type() const { return unsigned_flag ? HA_KEYTYPE_ULONG_INT : HA_KEYTYPE_LONG_INT; } - void store(const char *to,uint length); - void store(double nr); - void store(longlong nr); + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; } double val_real(void); longlong val_int(void); + bool send_binary(Protocol *protocol); String *val_str(String*,String *); int cmp(const char *,const char*); void sort_string(char *buff,uint length); uint32 pack_length() const { return 4; } void sql_type(String &str) const; + uint32 max_length() { return 11; } }; @@ -443,18 +559,20 @@ public: enum_field_types type() const { return FIELD_TYPE_LONGLONG;} enum ha_base_keytype key_type() const { return unsigned_flag ? HA_KEYTYPE_ULONGLONG : HA_KEYTYPE_LONGLONG; } - void store(const char *to,uint length); - void store(double nr); - void store(longlong nr); + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=ptr[4]=ptr[5]=ptr[6]=ptr[7]=0; } double val_real(void); longlong val_int(void); String *val_str(String*,String *); + bool send_binary(Protocol *protocol); int cmp(const char *,const char*); void sort_string(char *buff,uint length); uint32 pack_length() const { return 8; } void sql_type(String &str) const; - bool store_for_compare() { return 1; } + bool can_be_compared_as_longlong() const { return TRUE; } + uint32 max_length() { return 20; } }; #endif @@ -469,19 +587,26 @@ public: unireg_check_arg, field_name_arg, table_arg, dec_arg, zero_arg,unsigned_arg) {} + Field_float(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg, + struct st_table *table_arg, uint8 dec_arg) + :Field_num((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0, + NONE, field_name_arg, table_arg,dec_arg,0,0) + {} enum_field_types type() const { return FIELD_TYPE_FLOAT;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_FLOAT; } - void store(const char *to,uint length); - void store(double nr); - void store(longlong nr); + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); void reset(void) { bzero(ptr,sizeof(float)); } double val_real(void); longlong val_int(void); String *val_str(String*,String *); + bool send_binary(Protocol *protocol); int cmp(const char *,const char*); void sort_string(char *buff,uint length); uint32 pack_length() const { return sizeof(float); } void sql_type(String &str) const; + uint32 max_length() { return 24; } }; @@ -503,17 +628,19 @@ public: {} enum_field_types type() const { return FIELD_TYPE_DOUBLE;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_DOUBLE; } - void store(const char *to,uint length); - void store(double nr); - void store(longlong nr); + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); void reset(void) { bzero(ptr,sizeof(double)); } double val_real(void); longlong val_int(void); String *val_str(String*,String *); + bool send_binary(Protocol *protocol); int cmp(const char *,const char*); void sort_string(char *buff,uint length); uint32 pack_length() const { return sizeof(double); } void sql_type(String &str) const; + uint32 max_length() { return 53; } }; @@ -524,14 +651,15 @@ class Field_null :public Field_str { public: Field_null(char *ptr_arg, uint32 len_arg, enum utype unireg_check_arg, const char *field_name_arg, - struct st_table *table_arg) + struct st_table *table_arg, CHARSET_INFO *cs) :Field_str(ptr_arg, len_arg, null, 1, - unireg_check_arg, field_name_arg, table_arg) + unireg_check_arg, field_name_arg, table_arg, cs) {} enum_field_types type() const { return FIELD_TYPE_NULL;} - void store(const char *to, uint length) { null[0]=1; } - void store(double nr) { null[0]=1; } - void store(longlong nr) { null[0]=1; } + int store(const char *to, uint length, CHARSET_INFO *cs) + { null[0]=1; return 0; } + int store(double nr) { null[0]=1; return 0; } + int store(longlong nr) { null[0]=1; return 0; } void reset(void) {} double val_real(void) { return 0.0;} longlong val_int(void) { return 0;} @@ -540,49 +668,50 @@ public: int cmp(const char *a, const char *b) { return 0;} void sort_string(char *buff, uint length) {} uint32 pack_length() const { return 0; } - void sql_type(String &str) const { str.set("null",4); } + void sql_type(String &str) const; uint size_of() const { return sizeof(*this); } + uint32 max_length() { return 4; } }; -class Field_timestamp :public Field_num { -#if MYSQL_VERSION_ID < 40100 - /* - We save the original field length here because field_length is - changed to a mock value in case when the 'new_mode' is in effect. - */ - uint32 orig_field_length; -#endif +class Field_timestamp :public Field_str { public: Field_timestamp(char *ptr_arg, uint32 len_arg, + uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, - struct st_table *table_arg); - enum Item_result result_type () const; + struct st_table *table_arg, + CHARSET_INFO *cs); enum_field_types type() const { return FIELD_TYPE_TIMESTAMP;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; } - void store(const char *to,uint length); - void store(double nr); - void store(longlong nr); + enum Item_result cmp_type () const { return INT_RESULT; } + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; } double val_real(void); longlong val_int(void); String *val_str(String*,String *); + bool send_binary(Protocol *protocol); int cmp(const char *,const char*); void sort_string(char *buff,uint length); uint32 pack_length() const { return 4; } void sql_type(String &str) const; - bool store_for_compare() { return 1; } + bool can_be_compared_as_longlong() const { return TRUE; } bool zero_pack() const { return 0; } void set_time(); virtual void set_default() { - if (table->timestamp_field == this) + if (table->timestamp_field == this && + unireg_check != TIMESTAMP_UN_FIELD) set_time(); else Field::set_default(); } - inline long get_timestamp() + /* Get TIMESTAMP field value as seconds since begging of Unix Epoch */ + inline long get_timestamp(my_bool *null_value) { + if ((*null_value= is_null())) + return 0; #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) return sint4korr(ptr); @@ -591,13 +720,9 @@ public: longget(tmp,ptr); return tmp; } - bool get_date(TIME *ltime,bool fuzzydate); + bool get_date(TIME *ltime,uint fuzzydate); bool get_time(TIME *ltime); - -#if MYSQL_VERSION_ID < 40100 - friend TABLE *open_table(THD *thd,const char *db,const char *table_name, - const char *alias,bool *refresh); -#endif + timestamp_auto_set_type get_auto_set_type() const; }; @@ -611,14 +736,15 @@ public: unireg_check_arg, field_name_arg, table_arg, 1, 1) {} enum_field_types type() const { return FIELD_TYPE_YEAR;} - void store(const char *to,uint length); - void store(double nr); - void store(longlong nr); + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); double val_real(void); longlong val_int(void); String *val_str(String*,String *); + bool send_binary(Protocol *protocol); void sql_type(String &str) const; - bool store_for_compare() { return 1; } + bool can_be_compared_as_longlong() const { return TRUE; } }; @@ -626,29 +752,30 @@ class Field_date :public Field_str { public: Field_date(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, - struct st_table *table_arg) + struct st_table *table_arg, CHARSET_INFO *cs) :Field_str(ptr_arg, 10, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, table_arg) + unireg_check_arg, field_name_arg, table_arg, cs) {} Field_date(bool maybe_null_arg, const char *field_name_arg, - struct st_table *table_arg) + struct st_table *table_arg, CHARSET_INFO *cs) :Field_str((char*) 0,10, maybe_null_arg ? (uchar*) "": 0,0, - NONE, field_name_arg, table_arg) {} + NONE, field_name_arg, table_arg, cs) {} enum_field_types type() const { return FIELD_TYPE_DATE;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; } enum Item_result cmp_type () const { return INT_RESULT; } - void store(const char *to,uint length); - void store(double nr); - void store(longlong nr); + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; } double val_real(void); longlong val_int(void); String *val_str(String*,String *); + bool send_binary(Protocol *protocol); int cmp(const char *,const char*); void sort_string(char *buff,uint length); uint32 pack_length() const { return 4; } void sql_type(String &str) const; - bool store_for_compare() { return 1; } + bool can_be_compared_as_longlong() const { return TRUE; } bool zero_pack() const { return 1; } }; @@ -656,29 +783,30 @@ class Field_newdate :public Field_str { public: Field_newdate(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, - struct st_table *table_arg) + struct st_table *table_arg, CHARSET_INFO *cs) :Field_str(ptr_arg, 10, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, table_arg) + unireg_check_arg, field_name_arg, table_arg, cs) {} enum_field_types type() const { return FIELD_TYPE_DATE;} enum_field_types real_type() const { return FIELD_TYPE_NEWDATE; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_UINT24; } enum Item_result cmp_type () const { return INT_RESULT; } - void store(const char *to,uint length); - void store(double nr); - void store(longlong nr); + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); void store_time(TIME *ltime,timestamp_type type); void reset(void) { ptr[0]=ptr[1]=ptr[2]=0; } double val_real(void); longlong val_int(void); String *val_str(String*,String *); + bool send_binary(Protocol *protocol); int cmp(const char *,const char*); void sort_string(char *buff,uint length); uint32 pack_length() const { return 3; } void sql_type(String &str) const; - bool store_for_compare() { return 1; } + bool can_be_compared_as_longlong() const { return TRUE; } bool zero_pack() const { return 1; } - bool get_date(TIME *ltime,bool fuzzydate); + bool get_date(TIME *ltime,uint fuzzydate); bool get_time(TIME *ltime); }; @@ -687,31 +815,32 @@ class Field_time :public Field_str { public: Field_time(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, - struct st_table *table_arg) + struct st_table *table_arg, CHARSET_INFO *cs) :Field_str(ptr_arg, 8, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, table_arg) + unireg_check_arg, field_name_arg, table_arg, cs) {} Field_time(bool maybe_null_arg, const char *field_name_arg, - struct st_table *table_arg) + struct st_table *table_arg, CHARSET_INFO *cs) :Field_str((char*) 0,8, maybe_null_arg ? (uchar*) "": 0,0, - NONE, field_name_arg, table_arg) {} + NONE, field_name_arg, table_arg, cs) {} enum_field_types type() const { return FIELD_TYPE_TIME;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_INT24; } enum Item_result cmp_type () const { return INT_RESULT; } - void store(const char *to,uint length); - void store(double nr); - void store(longlong nr); + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); void reset(void) { ptr[0]=ptr[1]=ptr[2]=0; } double val_real(void); longlong val_int(void); String *val_str(String*,String *); - bool get_date(TIME *ltime,bool fuzzydate); + bool get_date(TIME *ltime, uint fuzzydate); + bool send_binary(Protocol *protocol); bool get_time(TIME *ltime); int cmp(const char *,const char*); void sort_string(char *buff,uint length); uint32 pack_length() const { return 3; } void sql_type(String &str) const; - bool store_for_compare() { return 1; } + bool can_be_compared_as_longlong() const { return TRUE; } bool zero_pack() const { return 1; } }; @@ -720,61 +849,52 @@ class Field_datetime :public Field_str { public: Field_datetime(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, - struct st_table *table_arg) + struct st_table *table_arg, CHARSET_INFO *cs) :Field_str(ptr_arg, 19, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, table_arg) + unireg_check_arg, field_name_arg, table_arg, cs) {} Field_datetime(bool maybe_null_arg, const char *field_name_arg, - struct st_table *table_arg) + struct st_table *table_arg, CHARSET_INFO *cs) :Field_str((char*) 0,19, maybe_null_arg ? (uchar*) "": 0,0, - NONE, field_name_arg, table_arg) {} + NONE, field_name_arg, table_arg, cs) {} enum_field_types type() const { return FIELD_TYPE_DATETIME;} #ifdef HAVE_LONG_LONG enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONGLONG; } #endif enum Item_result cmp_type () const { return INT_RESULT; } - void store(const char *to,uint length); - void store(double nr); - void store(longlong nr); + uint decimals() const { return DATETIME_DEC; } + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); void store_time(TIME *ltime,timestamp_type type); void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=ptr[4]=ptr[5]=ptr[6]=ptr[7]=0; } double val_real(void); longlong val_int(void); String *val_str(String*,String *); + bool send_binary(Protocol *protocol); int cmp(const char *,const char*); void sort_string(char *buff,uint length); uint32 pack_length() const { return 8; } void sql_type(String &str) const; - bool store_for_compare() { return 1; } + bool can_be_compared_as_longlong() const { return TRUE; } bool zero_pack() const { return 1; } - bool get_date(TIME *ltime,bool fuzzydate); + bool get_date(TIME *ltime,uint fuzzydate); bool get_time(TIME *ltime); }; class Field_string :public Field_str { - bool binary_flag; public: Field_string(char *ptr_arg, uint32 len_arg,uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, - struct st_table *table_arg,bool binary_arg) + struct st_table *table_arg, CHARSET_INFO *cs) :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, table_arg), - binary_flag(binary_arg) - { - if (binary_arg) - flags|=BINARY_FLAG; - } + unireg_check_arg, field_name_arg, table_arg,cs) {}; Field_string(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, - struct st_table *table_arg, bool binary_arg) + struct st_table *table_arg, CHARSET_INFO *cs) :Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0, - NONE, field_name_arg, table_arg), - binary_flag(binary_arg) - { - if (binary_arg) - flags|=BINARY_FLAG; - } + NONE, field_name_arg, table_arg, cs) {}; enum_field_types type() const { @@ -783,13 +903,12 @@ public: FIELD_TYPE_VAR_STRING : FIELD_TYPE_STRING); } enum ha_base_keytype key_type() const - { return binary_flag ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; } + { return binary() ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; } bool zero_pack() const { return 0; } - bool binary() const { return binary_flag; } - void reset(void) { bfill(ptr,field_length,' '); } - void store(const char *to,uint length); - void store(double nr); - void store(longlong nr); + void reset(void) { charset()->cset->fill(charset(),ptr,field_length,' '); } + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(longlong nr); + int store(double nr) { return Field_str::store(nr); } /* QQ: To be deleted */ double val_real(void); longlong val_int(void); String *val_str(String*,String *); @@ -804,52 +923,47 @@ public: uint max_packed_col_length(uint max_length); uint size_of() const { return sizeof(*this); } enum_field_types real_type() const { return FIELD_TYPE_STRING; } + bool has_charset(void) const + { return charset() == &my_charset_bin ? FALSE : TRUE; } }; class Field_varstring :public Field_str { - bool binary_flag; public: Field_varstring(char *ptr_arg, uint32 len_arg,uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, - struct st_table *table_arg,bool binary_arg) + struct st_table *table_arg, CHARSET_INFO *cs) :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, table_arg), - binary_flag(binary_arg) - { - if (binary_arg) - flags|= BINARY_FLAG; - } + unireg_check_arg, field_name_arg, table_arg, cs) + {} Field_varstring(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, - struct st_table *table_arg, bool binary_arg) + struct st_table *table_arg, CHARSET_INFO *cs) :Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0, - NONE, field_name_arg, table_arg), - binary_flag(binary_arg) - { - if (binary_arg) - flags|=BINARY_FLAG; - } + NONE, field_name_arg, table_arg, cs) + {} enum_field_types type() const { return FIELD_TYPE_VAR_STRING; } enum ha_base_keytype key_type() const - { return binary_flag ? HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT; } + { return binary() ? HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT; } bool zero_pack() const { return 0; } - bool binary() const { return binary_flag; } void reset(void) { bzero(ptr,field_length+2); } uint32 pack_length() const { return (uint32) field_length+2; } uint32 key_length() const { return (uint32) field_length; } - void store(const char *to,uint length); - void store(double nr); - void store(longlong nr); + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(longlong nr); + int store(double nr) { return Field_str::store(nr); } /* QQ: To be deleted */ double val_real(void); longlong val_int(void); String *val_str(String*,String *); int cmp(const char *,const char*); void sort_string(char *buff,uint length); + void get_key_image(char *buff,uint length, CHARSET_INFO *cs, imagetype type); + void set_key_image(char *buff,uint length, CHARSET_INFO *cs); void sql_type(String &str) const; char *pack(char *to, const char *from, uint max_length=~(uint) 0); + char *pack_key(char *to, const char *from, uint max_length); const char *unpack(char* to, const char *from); int pack_cmp(const char *a, const char *b, uint key_length); int pack_cmp(const char *b, uint key_length); @@ -857,34 +971,34 @@ public: uint max_packed_col_length(uint max_length); uint size_of() const { return sizeof(*this); } enum_field_types real_type() const { return FIELD_TYPE_VAR_STRING; } + bool has_charset(void) const + { return charset() == &my_charset_bin ? FALSE : TRUE; } }; class Field_blob :public Field_str { +protected: uint packlength; String value; // For temporaries - bool binary_flag; public: Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, struct st_table *table_arg,uint blob_pack_length, - bool binary_arg); + CHARSET_INFO *cs); Field_blob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, - struct st_table *table_arg, bool binary_arg) + struct st_table *table_arg, CHARSET_INFO *cs) :Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0, - NONE, field_name_arg, table_arg), - packlength(3),binary_flag(binary_arg) - { - flags|= BLOB_FLAG; - if (binary_arg) - flags|= BINARY_FLAG; - } + NONE, field_name_arg, table_arg, cs), + packlength(4) + { + flags|= BLOB_FLAG; + } enum_field_types type() const { return FIELD_TYPE_BLOB;} enum ha_base_keytype key_type() const - { return binary_flag ? HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT; } - void store(const char *to,uint length); - void store(double nr); - void store(longlong nr); + { return binary() ? HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT; } + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); double val_real(void); longlong val_int(void); String *val_str(String*,String *); @@ -899,6 +1013,10 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return (uint32) (packlength+table->blob_ptr_size); } + inline uint32 max_data_length() const + { + return (uint32) (((ulonglong) 1 << (packlength*8)) -1); + } void reset(void) { bzero(ptr, packlength+sizeof(char*)); } void reset_fields() { bzero((char*) &value,sizeof(value)); } void store_length(uint32 number); @@ -906,7 +1024,6 @@ public: { return get_length(ptr+row_offset); } uint32 get_length(const char *ptr); void put_length(char *pos, uint32 length); - bool binary() const { return binary_flag; } inline void get_ptr(char **str) { memcpy_fixed(str,ptr+packlength,sizeof(char*)); @@ -921,13 +1038,13 @@ public: store_length(length); memcpy_fixed(ptr+packlength,&data,sizeof(char*)); } - void get_key_image(char *buff,uint length); - void set_key_image(char *buff,uint length); + void get_key_image(char *buff,uint length, CHARSET_INFO *cs, imagetype type); + void set_key_image(char *buff,uint length, CHARSET_INFO *cs); void sql_type(String &str) const; inline bool copy() { char *tmp; get_ptr(&tmp); - if (value.copy(tmp,get_length())) + if (value.copy(tmp,get_length(),charset())) { Field_blob::reset(); return 1; @@ -944,12 +1061,43 @@ public: int pack_cmp(const char *b, uint key_length); uint packed_col_length(const char *col_ptr, uint length); uint max_packed_col_length(uint max_length); - inline void free() { value.free(); } + void free() { value.free(); } inline void clear_temporary() { bzero((char*) &value,sizeof(value)); } friend void field_conv(Field *to,Field *from); uint size_of() const { return sizeof(*this); } + bool has_charset(void) const + { return charset() == &my_charset_bin ? FALSE : TRUE; } + uint32 max_length(); }; +#ifdef HAVE_SPATIAL +class Field_geom :public Field_blob { +public: + enum geometry_type geom_type; + + Field_geom(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg, + enum utype unireg_check_arg, const char *field_name_arg, + struct st_table *table_arg,uint blob_pack_length, + enum geometry_type geom_type_arg) + :Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, + field_name_arg, table_arg, blob_pack_length,&my_charset_bin) + { geom_type= geom_type_arg; } + Field_geom(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, + struct st_table *table_arg, enum geometry_type geom_type_arg) + :Field_blob(len_arg, maybe_null_arg, field_name_arg, + table_arg, &my_charset_bin) + { geom_type= geom_type_arg; } + enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY; } + enum_field_types type() const { return FIELD_TYPE_GEOMETRY; } + void sql_type(String &str) const; + int store(const char *to, uint length, CHARSET_INFO *charset); + int store(double nr) { return 1; } + int store(longlong nr) { return 1; } + + void get_key_image(char *buff,uint length, CHARSET_INFO *cs,imagetype type); + void set_key_image(char *buff,uint length, CHARSET_INFO *cs); +}; +#endif /*HAVE_SPATIAL*/ class Field_enum :public Field_str { protected: @@ -960,19 +1108,21 @@ public: uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, struct st_table *table_arg,uint packlength_arg, - TYPELIB *typelib_arg) + TYPELIB *typelib_arg, + CHARSET_INFO *charset_arg) :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, table_arg), + unireg_check_arg, field_name_arg, table_arg, charset_arg), packlength(packlength_arg),typelib(typelib_arg) { flags|=ENUM_FLAG; } enum_field_types type() const { return FIELD_TYPE_STRING; } enum Item_result cmp_type () const { return INT_RESULT; } + enum Item_result cast_to_int_type () const { return INT_RESULT; } enum ha_base_keytype key_type() const; - void store(const char *to,uint length); - void store(double nr); - void store(longlong nr); + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); void reset() { bzero(ptr,packlength); } double val_real(void); longlong val_int(void); @@ -985,9 +1135,11 @@ public: uint size_of() const { return sizeof(*this); } enum_field_types real_type() const { return FIELD_TYPE_ENUM; } virtual bool zero_pack() const { return 0; } - bool optimize_range(uint idx) { return 0; } - bool binary() const { return 0; } + bool optimize_range(uint idx, uint part) { return 0; } bool eq_def(Field *field); + bool has_charset(void) const { return TRUE; } + /* enum and set are sorted as integers */ + CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; } }; @@ -997,21 +1149,22 @@ public: uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, struct st_table *table_arg,uint32 packlength_arg, - TYPELIB *typelib_arg) + TYPELIB *typelib_arg, CHARSET_INFO *charset_arg) :Field_enum(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, table_arg, packlength_arg, - typelib_arg) + typelib_arg,charset_arg) { flags=(flags & ~ENUM_FLAG) | SET_FLAG; } - void store(const char *to,uint length); - void store(double nr) { Field_set::store((longlong) nr); } - void store(longlong nr); + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr) { return Field_set::store((longlong) nr); } + int store(longlong nr); virtual bool zero_pack() const { return 1; } String *val_str(String*,String *); void sql_type(String &str) const; enum_field_types real_type() const { return FIELD_TYPE_SET; } + bool has_charset(void) const { return TRUE; } }; @@ -1024,18 +1177,31 @@ public: const char *field_name; const char *change; // If done with alter table const char *after; // Put column after this one + LEX_STRING comment; // Comment for field Item *def; // Default value enum enum_field_types sql_type; + /* + At various stages in execution this can be length of field in bytes or + max number of characters. + */ uint32 length; + /* + The value of 'length' before a call to create_length_to_internal_length + */ + uint32 char_length; uint decimals,flags,pack_length; Field::utype unireg_check; TYPELIB *interval; // Which interval to use + List<String> interval_list; + CHARSET_INFO *charset; + Field::geometry_type geom_type; Field *field; // For alter table uint8 row,col,sc_length,interval_id; // For rea_create_table uint offset,pack_flag; create_field() :after(0) {} create_field(Field *field, Field *orig_field); + void create_length_to_internal_length(void); }; @@ -1045,8 +1211,11 @@ public: class Send_field { public: - const char *table_name,*col_name; - uint length,flags,decimals; + const char *db_name; + const char *table_name,*org_table_name; + const char *col_name,*org_col_name; + ulong length; + uint charsetnr, flags, decimals; enum_field_types type; Send_field() {} }; @@ -1078,25 +1247,25 @@ public: Field *make_field(char *ptr, uint32 field_length, uchar *null_pos, uchar null_bit, - uint pack_flag, - enum_field_types field_type, + uint pack_flag, enum_field_types field_type, + CHARSET_INFO *cs, + Field::geometry_type geom_type, Field::utype unireg_check, TYPELIB *interval, const char *field_name, struct st_table *table); uint pack_length_to_packflag(uint type); uint32 calc_pack_length(enum_field_types type,uint32 length); -bool set_field_to_null(Field *field); -bool set_field_to_null_with_conversions(Field *field, bool no_conversions); -uint find_enum(TYPELIB *typelib,const char *x, uint length); -ulonglong find_set(TYPELIB *typelib,const char *x, uint length); -bool test_if_int(const char *str,int length); +int set_field_to_null(Field *field); +int set_field_to_null_with_conversions(Field *field, bool no_conversions); +bool test_if_int(const char *str, int length, const char *int_end, + CHARSET_INFO *cs); /* The following are for the interface with the .frm file */ #define FIELDFLAG_DECIMAL 1 -#define FIELDFLAG_BINARY 1 // Shares same flag +#define FIELDFLAG_BINARY 1 // Shares same flag #define FIELDFLAG_NUMBER 2 #define FIELDFLAG_ZEROFILL 4 #define FIELDFLAG_PACK 120 // Bits used for packing @@ -1104,6 +1273,7 @@ bool test_if_int(const char *str,int length); #define FIELDFLAG_BITFIELD 512 // mangled with decimals! #define FIELDFLAG_BLOB 1024 // mangled with decimals! #define FIELDFLAG_GEOM 2048 // mangled with decimals! + #define FIELDFLAG_LEFT_FULLSCREEN 8192 #define FIELDFLAG_RIGHT_FULLSCREEN 16384 #define FIELDFLAG_FORMAT_NUMBER 16384 // predit: ###,,## in output @@ -1126,7 +1296,7 @@ bool test_if_int(const char *str,int length); #define f_packtype(x) (((x) >> FIELDFLAG_PACK_SHIFT) & 15) #define f_decimals(x) ((uint8) (((x) >> FIELDFLAG_DEC_SHIFT) & FIELDFLAG_MAX_DEC)) #define f_is_alpha(x) (!f_is_num(x)) -#define f_is_binary(x) ((x) & FIELDFLAG_BINARY) +#define f_is_binary(x) ((x) & FIELDFLAG_BINARY) // 4.0- compatibility #define f_is_enum(x) (((x) & (FIELDFLAG_INTERVAL | FIELDFLAG_NUMBER)) == FIELDFLAG_INTERVAL) #define f_is_bitfield(x) (((x) & (FIELDFLAG_BITFIELD | FIELDFLAG_NUMBER)) == FIELDFLAG_BITFIELD) #define f_is_blob(x) (((x) & (FIELDFLAG_BLOB | FIELDFLAG_NUMBER)) == FIELDFLAG_BLOB) |