diff options
-rw-r--r-- | client/mysqlcheck.c | 2 | ||||
-rw-r--r-- | include/ft_global.h | 2 | ||||
-rw-r--r-- | myisam/ft_boolean_search.c | 7 | ||||
-rw-r--r-- | myisam/ft_static.c | 5 | ||||
-rw-r--r-- | myisam/ftdefs.h | 2 | ||||
-rw-r--r-- | mysql-test/r/func_group.result | 12 | ||||
-rw-r--r-- | mysql-test/r/insert_select.result.es | 12 | ||||
-rw-r--r-- | mysql-test/r/type_date.result | 8 | ||||
-rw-r--r-- | mysql-test/r/union.result | 36 | ||||
-rw-r--r-- | mysql-test/t/func_group.test | 14 | ||||
-rw-r--r-- | mysql-test/t/type_date.test | 7 | ||||
-rw-r--r-- | mysql-test/t/union.test | 35 | ||||
-rw-r--r-- | scripts/make_binary_distribution.sh | 2 | ||||
-rw-r--r-- | sql/field.cc | 35 | ||||
-rw-r--r-- | sql/field.h | 241 | ||||
-rw-r--r-- | sql/ha_myisam.h | 8 | ||||
-rw-r--r-- | sql/handler.h | 3 | ||||
-rw-r--r-- | sql/item.cc | 65 | ||||
-rw-r--r-- | sql/item.h | 4 | ||||
-rw-r--r-- | sql/item_func.cc | 8 | ||||
-rw-r--r-- | sql/sql_union.cc | 14 |
21 files changed, 334 insertions, 188 deletions
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 980046fe6e6..15be51853cd 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -195,7 +195,7 @@ static void usage(void) puts("and you are welcome to modify and redistribute it under the GPL license.\n"); puts("This program can be used to CHECK (-c,-m,-C), REPAIR (-r), ANALYZE (-a)"); puts("or OPTIMIZE (-o) tables. Some of the options (like -e or -q) can be"); - puts("used at the same time. It works on MyISAM and in some cases on BDB tables."); + puts("used at the same time. Not all options are supported by all storage engines."); puts("Please consult the MySQL manual for latest information about the"); puts("above. The options -c,-r,-a and -o are exclusive to each other, which"); puts("means that the last option will be used, if several was specified.\n"); diff --git a/include/ft_global.h b/include/ft_global.h index 94f6ad9ef51..c3f60d13a7a 100644 --- a/include/ft_global.h +++ b/include/ft_global.h @@ -62,7 +62,7 @@ void ft_free_stopwords(void); #define FT_SORTED 2 #define FT_EXPAND 4 /* query expansion */ -FT_INFO *ft_init_search(uint,void *, uint, byte *, uint, byte *); +FT_INFO *ft_init_search(uint,void *, uint, byte *, uint,CHARSET_INFO *, byte *); my_bool ft_boolean_check_syntax_string(const byte *); #ifdef __cplusplus diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c index 4e66bd92a94..a5b4439a57f 100644 --- a/myisam/ft_boolean_search.c +++ b/myisam/ft_boolean_search.c @@ -366,6 +366,7 @@ static void _ftb_init_index_search(FT_INFO *ftb) reset_tree(& ftb->no_dupes); } + ftbw->off=0; /* in case of reinit */ if (_ft2_search(ftb, ftbw, 1)) return; } @@ -374,7 +375,7 @@ static void _ftb_init_index_search(FT_INFO *ftb) FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query, - uint query_len) + uint query_len, CHARSET_INFO *cs) { FTB *ftb; FTB_EXPR *ftbe; @@ -386,8 +387,8 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query, ftb->state=UNINITIALIZED; ftb->info=info; ftb->keynr=keynr; - ftb->charset= ((keynr==NO_SUCH_KEY) ? - default_charset_info : info->s->keyinfo[keynr].seg->charset); + ftb->charset=cs; + DBUG_ASSERT(keynr==NO_SUCH_KEY || cs == info->s->keyinfo[keynr].seg->charset); ftb->with_scan=0; ftb->lastpos=HA_OFFSET_ERROR; bzero(& ftb->no_dupes, sizeof(TREE)); diff --git a/myisam/ft_static.c b/myisam/ft_static.c index cf4a8dd2a73..e221950f445 100644 --- a/myisam/ft_static.c +++ b/myisam/ft_static.c @@ -57,11 +57,12 @@ const struct _ft_vft _ft_vft_boolean = { FT_INFO *ft_init_search(uint flags, void *info, uint keynr, - byte *query, uint query_len, byte *record) + byte *query, uint query_len, CHARSET_INFO *cs, + byte *record) { FT_INFO *res; if (flags & FT_BOOL) - res= ft_init_boolean_search((MI_INFO *)info, keynr, query, query_len); + res= ft_init_boolean_search((MI_INFO *)info, keynr, query, query_len,cs); else res= ft_init_nlq_search((MI_INFO *)info, keynr, query, query_len, flags, record); diff --git a/myisam/ftdefs.h b/myisam/ftdefs.h index e7a0829e140..ddb9fbfead2 100644 --- a/myisam/ftdefs.h +++ b/myisam/ftdefs.h @@ -131,7 +131,7 @@ FT_WORD * _mi_ft_parserecord(MI_INFO *, uint, const byte *); uint _mi_ft_parse(TREE *, MI_INFO *, uint, const byte *, my_bool); FT_INFO *ft_init_nlq_search(MI_INFO *, uint, byte *, uint, uint, byte *); -FT_INFO *ft_init_boolean_search(MI_INFO *, uint, byte *, uint); +FT_INFO *ft_init_boolean_search(MI_INFO *, uint, byte *, uint, CHARSET_INFO *); extern const struct _ft_vft _ft_vft_nlq; int ft_nlq_read_next(FT_INFO *, char *); diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index df95193043e..706bf4c5c6b 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -737,3 +737,15 @@ one 2 two 2 three 1 drop table t1; +create table t1(f1 datetime); +insert into t1 values (now()); +create table t2 select f2 from (select max(now()) f2 from t1) a; +show columns from t2; +Field Type Null Key Default Extra +f2 datetime 0000-00-00 00:00:00 +drop table t2; +create table t2 select f2 from (select now() f2 from t1) a; +show columns from t2; +Field Type Null Key Default Extra +f2 datetime 0000-00-00 00:00:00 +drop table t2, t1; diff --git a/mysql-test/r/insert_select.result.es b/mysql-test/r/insert_select.result.es index 9e11402733d..9cac6d31b8f 100644 --- a/mysql-test/r/insert_select.result.es +++ b/mysql-test/r/insert_select.result.es @@ -633,3 +633,15 @@ No Field Count 0 1 100 0 2 100 drop table t1, t2; +CREATE TABLE t1 ( +ID int(11) NOT NULL auto_increment, +NO int(11) NOT NULL default '0', +SEQ int(11) NOT NULL default '0', +PRIMARY KEY (ID), +KEY t1$NO (SEQ,NO) +) ENGINE=MyISAM; +INSERT INTO t1 (SEQ, NO) SELECT "1" AS SEQ, IF(MAX(NO) IS NULL, 0, MAX(NO)) + 1 AS NO FROM t1 WHERE (SEQ = 1); +select SQL_BUFFER_RESULT * from t1 WHERE (SEQ = 1); +ID NO SEQ +1 1 1 +drop table t1; diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result index 71d1b9ad381..3428b5969d9 100644 --- a/mysql-test/r/type_date.result +++ b/mysql-test/r/type_date.result @@ -96,3 +96,11 @@ f2 19781126 19781126 DROP TABLE t1, t2, t3; +CREATE TABLE t1 (y YEAR); +INSERT INTO t1 VALUES ('abc'); +Warnings: +Warning 1265 Data truncated for column 'y' at row 1 +SELECT * FROM t1; +y +0000 +DROP TABLE t1; diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index a63358ff2bc..cdae2cd1bcf 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -1137,3 +1137,39 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; drop table t2; +create table t1(a1 int, f1 char(10)); +create table t2 +select f2,a1 from (select a1, CAST('2004-12-31' AS DATE) f2 from t1) a +union +select f2,a1 from (select a1, CAST('2004-12-31' AS DATE) f2 from t1) a +order by f2, a1; +show columns from t2; +Field Type Null Key Default Extra +f2 date YES NULL +a1 int(11) YES NULL +drop table t1, t2; +create table t1 (f1 int); +create table t2 (f1 int, f2 int ,f3 date); +create table t3 (f1 int, f2 char(10)); +create table t4 +( +select t2.f3 as sdate +from t1 +left outer join t2 on (t1.f1 = t2.f1) +inner join t3 on (t2.f2 = t3.f1) +order by t1.f1, t3.f1, t2.f3 +) +union +( +select cast('2004-12-31' as date) as sdate +from t1 +left outer join t2 on (t1.f1 = t2.f1) +inner join t3 on (t2.f2 = t3.f1) +group by t1.f1 +order by t1.f1, t3.f1, t2.f3 +) +order by sdate; +show columns from t4; +Field Type Null Key Default Extra +sdate date YES NULL +drop table t1, t2, t3, t4; diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index 65ef9f2535c..a47218e5c01 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -473,3 +473,17 @@ INSERT INTO t1 VALUES select val, count(*) from t1 group by val; drop table t1; + + +# +# Bug 7833: Wrong datatype of aggregate column is returned +# + +create table t1(f1 datetime); +insert into t1 values (now()); +create table t2 select f2 from (select max(now()) f2 from t1) a; +show columns from t2; +drop table t2; +create table t2 select f2 from (select now() f2 from t1) a; +show columns from t2; +drop table t2, t1; diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test index 64420a85189..304ed19b971 100644 --- a/mysql-test/t/type_date.test +++ b/mysql-test/t/type_date.test @@ -107,3 +107,10 @@ SELECT * FROM t2; SELECT * FROM t3; DROP TABLE t1, t2, t3; + +# Test that setting YEAR to invalid string results in default value, not +# 2000. (Bug #6067) +CREATE TABLE t1 (y YEAR); +INSERT INTO t1 VALUES ('abc'); +SELECT * FROM t1; +DROP TABLE t1; diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index 6045d8e3c30..be6bc7a48d8 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -682,3 +682,38 @@ show create table t1; drop table t1; drop table t2; +# +# Bug 6931: Date Type column problem when using UNION-Table. +# +create table t1(a1 int, f1 char(10)); +create table t2 +select f2,a1 from (select a1, CAST('2004-12-31' AS DATE) f2 from t1) a +union +select f2,a1 from (select a1, CAST('2004-12-31' AS DATE) f2 from t1) a +order by f2, a1; +show columns from t2; +drop table t1, t2; + +create table t1 (f1 int); +create table t2 (f1 int, f2 int ,f3 date); +create table t3 (f1 int, f2 char(10)); +create table t4 +( + select t2.f3 as sdate + from t1 + left outer join t2 on (t1.f1 = t2.f1) + inner join t3 on (t2.f2 = t3.f1) + order by t1.f1, t3.f1, t2.f3 +) +union +( + select cast('2004-12-31' as date) as sdate + from t1 + left outer join t2 on (t1.f1 = t2.f1) + inner join t3 on (t2.f2 = t3.f1) + group by t1.f1 + order by t1.f1, t3.f1, t2.f3 +) +order by sdate; +show columns from t4; +drop table t1, t2, t3, t4; diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index 4743b37a098..4c339b063d9 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -221,7 +221,7 @@ $CP mysql-test/std_data/*.dat mysql-test/std_data/*.frm \ mysql-test/std_data/des_key_file mysql-test/std_data/*.*001 \ $BASE/mysql-test/std_data $CP mysql-test/t/*test mysql-test/t/*.opt mysql-test/t/*.slave-mi mysql-test/t/*.sh $BASE/mysql-test/t -$CP mysql-test/r/*result mysql-test/r/*.require $BASE/mysql-test/r +$CP mysql-test/r/*result mysql-test/r/*result.es mysql-test/r/*.require $BASE/mysql-test/r if [ $BASE_SYSTEM != "netware" ] ; then chmod a+x $BASE/bin/* diff --git a/sql/field.cc b/sql/field.cc index aa2c5805bfe..f95eaaba5df 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -261,6 +261,7 @@ static Field::field_cast_enum field_cast_date[]= Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; static Field::field_cast_enum field_cast_newdate[]= {Field::FIELD_CAST_NEWDATE, + Field::FIELD_CAST_DATE, Field::FIELD_CAST_DATETIME, Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; @@ -6834,6 +6835,40 @@ Field *make_field(char *ptr, uint32 field_length, } +/* + Check if field_type is appropriate field type + to create field for tmp table using + item->tmp_table_field() method + + SYNOPSIS + field_types_to_be_kept() + field_type - field type + + NOTE + it is used in function get_holder_example_field() + from item.cc + + RETURN + 1 - can use item->tmp_table_field() method + 0 - can not use item->tmp_table_field() method + +*/ + +bool field_types_to_be_kept(enum_field_types field_type) +{ + switch (field_type) + { + case FIELD_TYPE_DATE: + case FIELD_TYPE_NEWDATE: + case FIELD_TYPE_TIME: + case FIELD_TYPE_DATETIME: + return 1; + default: + return 0; + } +} + + /* Create a field suitable for create of table */ create_field::create_field(Field *old_field,Field *orig_field) diff --git a/sql/field.h b/sql/field.h index af300c8d471..fd0f2f9c2f1 100644 --- a/sql/field.h +++ b/sql/field.h @@ -37,7 +37,11 @@ class Field 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) { TRASH(ptr_arg, size); } + 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 @@ -47,7 +51,7 @@ public: */ struct st_table *table; // Pointer for table struct st_table *orig_table; // Pointer to original table - const char **table_name, *field_name; + 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 */ @@ -80,7 +84,7 @@ public: FIELD_CAST_TIMESTAMP, FIELD_CAST_YEAR, FIELD_CAST_DATE, FIELD_CAST_NEWDATE, FIELD_CAST_TIME, FIELD_CAST_DATETIME, FIELD_CAST_STRING, FIELD_CAST_VARSTRING, FIELD_CAST_BLOB, - FIELD_CAST_GEOM, FIELD_CAST_ENUM, FIELD_CAST_SET, FIELD_CAST_BIT + FIELD_CAST_GEOM, FIELD_CAST_ENUM, FIELD_CAST_SET }; utype unireg_check; @@ -96,7 +100,7 @@ public: 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 int store_time(TIME *ltime, timestamp_type t_type); + 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); } @@ -113,22 +117,16 @@ public: This trickery is used to decrease a number of malloc calls. */ virtual String *val_str(String*,String *)=0; - String *val_int_as_str(String *val_buffer, my_bool unsigned_flag); virtual Item_result result_type () const=0; virtual Item_result cmp_type () const { return result_type(); } - bool eq(Field *field) - { - return (ptr == field->ptr && null_ptr == field->null_ptr && - null_bit == field->null_bit); - } + 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; } - virtual uint32 pack_length_in_rec() const { return pack_length(); } virtual void reset(void) { bzero(ptr,pack_length()); } virtual void reset_fields() {} virtual void set_default() { - my_ptrdiff_t offset = (my_ptrdiff_t) (table->s->default_values - + my_ptrdiff_t offset = (my_ptrdiff_t) (table->default_values - table->record[0]); memcpy(ptr, ptr + offset, pack_length()); if (null_ptr) @@ -145,9 +143,10 @@ public: virtual int cmp(const char *,const char *)=0; virtual int cmp_binary(const char *a,const char *b, uint32 max_length=~0L) { return memcmp(a,b,pack_length()); } - int cmp_offset(uint row_offset) { return cmp(ptr,ptr+row_offset); } - int cmp_binary_offset(uint row_offset) - { return cmp_binary(ptr, ptr+row_offset); }; + virtual int cmp_offset(uint row_offset) + { return memcmp(ptr,ptr+row_offset,pack_length()); } + virtual int cmp_binary_offset(uint row_offset) + { return memcmp(ptr,ptr+row_offset,pack_length()); } virtual int key_cmp(const byte *a,const byte *b) { return cmp((char*) a,(char*) b); } virtual int key_cmp(const byte *str, uint length) @@ -177,7 +176,7 @@ public: { if (null_ptr) null_ptr[row_offset]&= (uchar) ~null_bit; } inline bool maybe_null(void) { return null_ptr != 0 || table->maybe_null; } inline bool real_maybe_null(void) { return null_ptr != 0; } - virtual void make_field(Send_field *); + virtual void make_field(Send_field *)=0; virtual void sort_string(char *buff,uint length)=0; virtual bool optimize_range(uint idx, uint part); /* @@ -189,11 +188,28 @@ 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_key_field(MEM_ROOT *root, struct st_table *new_table, - char *new_ptr, uchar *new_null_ptr, - uint new_null_bit); - virtual void move_field(char *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg) + Field *new_field(MEM_ROOT *root, struct st_table *new_table) + { + Field *tmp= (Field*) memdup_root(root,(char*) this,size_of()); + if (tmp) + { + if (tmp->table->maybe_null) + tmp->flags&= ~NOT_NULL_FLAG; + 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); +#ifdef PROBABLY_WRONG + tmp->table_name= new_table->table_name; +#endif + tmp->reset_fields(); + } + return tmp; + } + inline void move_field(char *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg) { ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg; } @@ -208,10 +224,11 @@ public: { memcpy(buff,ptr,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, imagetype type) - { get_image(buff,length, &my_charset_bin); } - virtual void set_key_image(char *buff,uint length) - { set_image(buff,length, &my_charset_bin); } + 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; @@ -219,17 +236,6 @@ public: ptr-=row_offset; return tmp; } - - inline String *val_str(String *str, char *new_ptr) - { - char *old_ptr= ptr; - ptr= new_ptr; - val_str(str); - ptr= old_ptr; - return str; - } - bool quote_data(String *unquoted_string); - bool needs_quotes(void); virtual bool send_binary(Protocol *protocol); virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0) { @@ -261,11 +267,9 @@ public: virtual uint max_packed_col_length(uint max_length) { return max_length;} - virtual int pack_cmp(const char *a,const char *b, uint key_length_arg, - my_bool insert_or_update) + virtual int pack_cmp(const char *a,const char *b, uint key_length_arg) { return cmp(a,b); } - virtual int pack_cmp(const char *b, uint key_length_arg, - my_bool insert_or_update) + virtual int pack_cmp(const char *b, uint key_length_arg) { return cmp(ptr,b); } uint offset(); // Should be inline ... void copy_from_tmp(int offset); @@ -277,8 +281,6 @@ public: virtual void set_charset(CHARSET_INFO *charset) { } bool set_warning(const unsigned int level, const unsigned int code, int cuted_increment); - bool check_int(const char *str, int length, const char *int_end, - CHARSET_INFO *cs); void set_datetime_warning(const uint level, const uint code, const char *str, uint str_len, timestamp_type ts_type, int cuted_increment); @@ -358,6 +360,7 @@ public: 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; } @@ -716,7 +719,7 @@ public: if ((*null_value= is_null())) return 0; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table->db_low_byte_first) return sint4korr(ptr); #endif long tmp; @@ -800,7 +803,7 @@ public: int store(const char *to,uint length,CHARSET_INFO *charset); int store(double nr); int store(longlong nr); - int store_time(TIME *ltime, timestamp_type type); + 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); @@ -833,7 +836,6 @@ public: 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; } - int store_time(TIME *ltime, timestamp_type type); int store(const char *to,uint length,CHARSET_INFO *charset); int store(double nr); int store(longlong nr); @@ -874,7 +876,7 @@ public: int store(const char *to,uint length,CHARSET_INFO *charset); int store(double nr); int store(longlong nr); - int store_time(TIME *ltime, timestamp_type type); + 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); @@ -907,11 +909,9 @@ public: enum_field_types type() const { - return ((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); + return ((table && table->db_create_options & HA_OPTION_PACK_RECORD && + field_length >= 4) ? + FIELD_TYPE_VAR_STRING : FIELD_TYPE_STRING); } enum ha_base_keytype key_type() const { return binary() ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; } @@ -928,9 +928,8 @@ public: void sql_type(String &str) const; char *pack(char *to, const char *from, uint max_length=~(uint) 0); const char *unpack(char* to, const char *from); - int pack_cmp(const char *a,const char *b,uint key_length, - my_bool insert_or_update); - int pack_cmp(const char *b,uint key_length,my_bool insert_or_update); + int pack_cmp(const char *a,const char *b,uint key_length); + int pack_cmp(const char *b,uint key_length); uint packed_col_length(const char *to, uint length); uint max_packed_col_length(uint max_length); uint size_of() const { return sizeof(*this); } @@ -938,43 +937,31 @@ public: bool has_charset(void) const { return charset() == &my_charset_bin ? FALSE : TRUE; } field_cast_enum field_cast_type() { return FIELD_CAST_STRING; } - Field *new_field(MEM_ROOT *root, struct st_table *new_table); }; class Field_varstring :public Field_str { public: - /* Store number of bytes used to store length (1 or 2) */ - uint32 length_bytes; - Field_varstring(char *ptr_arg, - uint32 len_arg, uint length_bytes_arg, - uchar *null_ptr_arg, + 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, CHARSET_INFO *cs) :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, table_arg, cs), - length_bytes(length_bytes_arg) - { - if (table) - table->s->varchar_fields++; - } + 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, CHARSET_INFO *cs) :Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0, - NONE, field_name_arg, table_arg, cs), - length_bytes(len_arg < 256 ? 1 :2) - { - if (table) - table->s->varchar_fields++; - } + NONE, field_name_arg, table_arg, cs) + {} - enum_field_types type() const { return MYSQL_TYPE_VARCHAR; } - enum ha_base_keytype key_type() const; + enum_field_types type() const { return FIELD_TYPE_VAR_STRING; } + enum ha_base_keytype key_type() const + { return binary() ? HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT; } bool zero_pack() const { return 0; } - void reset(void) { bzero(ptr,field_length+length_bytes); } - uint32 pack_length() const { return (uint32) field_length+length_bytes; } + 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; } int store(const char *to,uint length,CHARSET_INFO *charset); int store(longlong nr); @@ -984,31 +971,21 @@ public: 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, imagetype type); - 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; char *pack(char *to, const char *from, uint max_length=~(uint) 0); char *pack_key(char *to, const char *from, uint max_length); - char *pack_key_from_key_image(char* to, const char *from, uint max_length); const char *unpack(char* to, const char *from); - const char *unpack_key(char* to, const char *from, uint max_length); - int pack_cmp(const char *a, const char *b, uint key_length, - my_bool insert_or_update); - int pack_cmp(const char *b, uint key_length,my_bool insert_or_update); - int cmp_binary(const char *a,const char *b, uint32 max_length=~0L); - int key_cmp(const byte *,const byte*); - int key_cmp(const byte *str, uint length); + int pack_cmp(const char *a, const char *b, uint key_length); + int pack_cmp(const char *b, uint key_length); uint packed_col_length(const char *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_VARCHAR; } + enum_field_types real_type() const { return FIELD_TYPE_VAR_STRING; } bool has_charset(void) const { return charset() == &my_charset_bin ? FALSE : TRUE; } field_cast_enum field_cast_type() { return FIELD_CAST_VARSTRING; } - Field *new_field(MEM_ROOT *root, struct st_table *new_table); - Field *new_key_field(MEM_ROOT *root, struct st_table *new_table, - char *new_ptr, uchar *new_null_ptr, - uint new_null_bit); }; @@ -1031,7 +1008,7 @@ public: } enum_field_types type() const { return FIELD_TYPE_BLOB;} enum ha_base_keytype key_type() const - { return binary() ? HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2; } + { 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); @@ -1040,13 +1017,15 @@ public: String *val_str(String*,String *); int cmp(const char *,const char*); int cmp(const char *a, uint32 a_length, const char *b, uint32 b_length); + int cmp_offset(uint offset); int cmp_binary(const char *a,const char *b, uint32 max_length=~0L); + int cmp_binary_offset(uint row_offset); int key_cmp(const byte *,const byte*); int key_cmp(const byte *str, uint length); uint32 key_length() const { return 0; } void sort_string(char *buff,uint length); uint32 pack_length() const - { return (uint32) (packlength+table->s->blob_ptr_size); } + { return (uint32) (packlength+table->blob_ptr_size); } inline uint32 max_data_length() const { return (uint32) (((ulonglong) 1 << (packlength*8)) -1); @@ -1072,8 +1051,8 @@ public: store_length(length); memcpy_fixed(ptr+packlength,&data,sizeof(char*)); } - void get_key_image(char *buff,uint length, imagetype type); - 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; @@ -1087,13 +1066,12 @@ public: return 0; } char *pack(char *to, const char *from, uint max_length= ~(uint) 0); + const char *unpack(char *to, const char *from); char *pack_key(char *to, const char *from, uint max_length); char *pack_key_from_key_image(char* to, const char *from, uint max_length); - const char *unpack(char *to, const char *from); const char *unpack_key(char* to, const char *from, uint max_length); - int pack_cmp(const char *a, const char *b, uint key_length, - my_bool insert_or_update); - int pack_cmp(const char *b, uint key_length,my_bool insert_or_update); + int pack_cmp(const char *a, const char *b, uint key_length); + 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); void free() { value.free(); } @@ -1106,7 +1084,6 @@ public: uint32 max_length(); }; - #ifdef HAVE_SPATIAL class Field_geom :public Field_blob { public: @@ -1124,19 +1101,19 @@ public: :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_VARBINARY2; } + 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,imagetype type); + void get_key_image(char *buff,uint length, CHARSET_INFO *cs,imagetype type); + void set_key_image(char *buff,uint length, CHARSET_INFO *cs); field_cast_enum field_cast_type() { return FIELD_CAST_GEOM; } }; #endif /*HAVE_SPATIAL*/ - class Field_enum :public Field_str { protected: uint packlength; @@ -1205,52 +1182,6 @@ public: }; -class Field_bit :public Field { -public: - uchar *bit_ptr; // position in record where 'uneven' bits store - uchar bit_ofs; // offset to 'uneven' high bits - uint bit_len; // number of 'uneven' high bits - Field_bit(char *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, - struct st_table *table_arg); - enum_field_types type() const { return FIELD_TYPE_BIT; } - enum ha_base_keytype key_type() const { return HA_KEYTYPE_BIT; } - uint32 key_length() const { return (uint32) field_length + (bit_len > 0); } - uint32 max_length() { return (uint32) field_length + (bit_len > 0); } - uint size_of() const { return sizeof(*this); } - Item_result result_type () const { return INT_RESULT; } - void reset(void) { bzero(ptr, field_length); } - 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 *); - int cmp(const char *a, const char *b) - { return cmp_binary(a, b); } - int key_cmp(const byte *a, const byte *b) - { return cmp_binary((char *) a, (char *) b); } - int key_cmp(const byte *str, uint length); - int cmp_offset(uint row_offset); - void get_key_image(char *buff, uint length, imagetype type); - void set_key_image(char *buff, uint length) - { Field_bit::store(buff, length, &my_charset_bin); } - void sort_string(char *buff, uint length) - { get_key_image(buff, length, itRAW); } - uint32 pack_length() const - { return (uint32) field_length + (bit_len > 0); } - uint32 pack_length_in_rec() const { return field_length; } - void sql_type(String &str) const; - field_cast_enum field_cast_type() { return FIELD_CAST_BIT; } - char *pack(char *to, const char *from, uint max_length=~(uint) 0); - const char *unpack(char* to, const char *from); - Field *new_key_field(MEM_ROOT *root, struct st_table *new_table, - char *new_ptr, uchar *new_null_ptr, - uint new_null_bit); -}; - - /* Create field class for CREATE TABLE */ @@ -1263,8 +1194,8 @@ public: LEX_STRING comment; // Comment for field Item *def; // Default value enum enum_field_types sql_type; - ulong length; - uint decimals, flags, pack_length, key_length; + uint32 length; + uint decimals,flags,pack_length; Field::utype unireg_check; TYPELIB *interval; // Which interval to use List<String> interval_list; @@ -1329,10 +1260,12 @@ Field *make_field(char *ptr, uint32 field_length, TYPELIB *interval, const char *field_name, struct st_table *table); 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); +bool test_if_int(const char *str, int length, const char *int_end, + CHARSET_INFO *cs); +bool field_types_to_be_kept(enum_field_types field_type); /* The following are for the interface with the .frm file @@ -1351,7 +1284,6 @@ int set_field_to_null_with_conversions(Field *field, bool no_conversions); #define FIELDFLAG_LEFT_FULLSCREEN 8192 #define FIELDFLAG_RIGHT_FULLSCREEN 16384 #define FIELDFLAG_FORMAT_NUMBER 16384 // predit: ###,,## in output -#define FIELDFLAG_NO_DEFAULT 16384 /* sql */ #define FIELDFLAG_SUM ((uint) 32768)// predit: +#fieldflag #define FIELDFLAG_MAYBE_NULL ((uint) 32768)// sql #define FIELDFLAG_PACK_SHIFT 3 @@ -1360,6 +1292,8 @@ int set_field_to_null_with_conversions(Field *field, bool no_conversions); #define FIELDFLAG_NUM_SCREEN_TYPE 0x7F01 #define FIELDFLAG_ALFA_SCREEN_TYPE 0x7800 +#define FIELD_SORT_REVERSE 16384 + #define MTYP_TYPENR(type) (type & 127) /* Remove bits from type */ #define f_is_dec(x) ((x) & FIELDFLAG_DECIMAL) @@ -1377,4 +1311,3 @@ int set_field_to_null_with_conversions(Field *field, bool no_conversions); #define f_is_equ(x) ((x) & (1+2+FIELDFLAG_PACK+31*256)) #define f_settype(x) (((int) x) << FIELDFLAG_PACK_SHIFT) #define f_maybe_null(x) (x & FIELDFLAG_MAYBE_NULL) -#define f_no_default(x) (x & FIELDFLAG_NO_DEFAULT) diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h index d2fe36c8357..7e14a3b7941 100644 --- a/sql/ha_myisam.h +++ b/sql/ha_myisam.h @@ -88,8 +88,12 @@ class ha_myisam: public handler ft_handler->please->reinit_search(ft_handler); return 0; } - FT_INFO *ft_init_ext(uint flags, uint inx,const byte *key, uint keylen) - { return ft_init_search(flags,file,inx,(byte*) key,keylen, table->record[0]); } + FT_INFO *ft_init_ext(uint flags, uint inx,String *key) + { + return ft_init_search(flags,file,inx, + (byte *)key->ptr(), key->length(), key->charset(), + table->record[0]); + } int ft_read(byte *buf); int rnd_init(bool scan); int rnd_next(byte *buf); diff --git a/sql/handler.h b/sql/handler.h index 04f196dccca..8ad49456bf6 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -455,8 +455,7 @@ public: int compare_key(key_range *range); virtual int ft_init() { return HA_ERR_WRONG_COMMAND; } void ft_end() { ft_handler=NULL; } - virtual FT_INFO *ft_init_ext(uint flags,uint inx,const byte *key, - uint keylen) + virtual FT_INFO *ft_init_ext(uint flags, uint inx,String *key) { return NULL; } virtual int ft_read(byte *buf) { return HA_ERR_WRONG_COMMAND; } virtual int rnd_next(byte *buf)=0; diff --git a/sql/item.cc b/sql/item.cc index 08de3889ae6..a0d1d8cbacf 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3633,7 +3633,53 @@ void Item_cache_row::bring_value() } -Item_type_holder::Item_type_holder(THD *thd, Item *item) +/* + Returns field for temporary table dependind on item type + + SYNOPSIS + get_holder_example_field() + thd - thread handler + item - pointer to item + table - empty table object + + NOTE + It is possible to return field for Item_func + items only if field type of this item is + date or time or datetime type. + also see function field_types_to_be_kept() from + field.cc + + RETURN + # - field + 0 - no field +*/ + +Field *get_holder_example_field(THD *thd, Item *item, TABLE *table) +{ + DBUG_ASSERT(table); + + Item_func *tmp_item= 0; + if (item->type() == Item::FIELD_ITEM) + return (((Item_field*) item)->field); + if (item->type() == Item::FUNC_ITEM) + tmp_item= (Item_func *) item; + else if (item->type() == Item::SUM_FUNC_ITEM) + { + Item_sum *item_sum= (Item_sum *) item; + if (item_sum->keep_field_type()) + { + if (item_sum->args[0]->type() == Item::FIELD_ITEM) + return (((Item_field*) item_sum->args[0])->field); + if (item_sum->args[0]->type() == Item::FUNC_ITEM) + tmp_item= (Item_func *) item_sum->args[0]; + } + } + return (tmp_item && field_types_to_be_kept(tmp_item->field_type()) ? + tmp_item->tmp_table_field(table) : 0); +} + + +Item_type_holder::Item_type_holder(THD *thd, Item *item, TABLE *table) :Item(thd, item), item_type(item->result_type()), orig_type(item_type) { @@ -3643,10 +3689,7 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item) It is safe assign pointer on field, because it will be used just after all JOIN::prepare calls and before any SELECT execution */ - if (item->type() == Item::FIELD_ITEM) - field_example= ((Item_field*) item)->field; - else - field_example= 0; + field_example= get_holder_example_field(thd, item, table); max_length= real_length(item); maybe_null= item->maybe_null; collation.set(item->collation); @@ -3686,25 +3729,23 @@ inline bool is_attr_compatible(Item *from, Item *to) (to->maybe_null || !from->maybe_null) && (to->result_type() != STRING_RESULT || from->result_type() != STRING_RESULT || - my_charset_same(from->collation.collation, - to->collation.collation))); + (from->collation.collation == to->collation.collation))); } -bool Item_type_holder::join_types(THD *thd, Item *item) +bool Item_type_holder::join_types(THD *thd, Item *item, TABLE *table) { uint32 new_length= real_length(item); bool use_new_field= 0, use_expression_type= 0; Item_result new_result_type= type_convertor[item_type][item->result_type()]; - bool item_is_a_field= item->type() == Item::FIELD_ITEM; - + Field *field= get_holder_example_field(thd, item, table); + bool item_is_a_field= field; /* Check if both items point to fields: in this case we can adjust column types of result table in the union smartly. */ if (field_example && item_is_a_field) { - Field *field= ((Item_field *)item)->field; /* Can 'field_example' field store data of the column? */ if ((use_new_field= (!field->field_cast_compatible(field_example->field_cast_type()) || @@ -3745,7 +3786,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item) It is safe to assign a pointer to field here, because it will be used before any table is closed. */ - field_example= ((Item_field*) item)->field; + field_example= field; } old_cs= collation.collation->name; diff --git a/sql/item.h b/sql/item.h index 6857b4acf82..8209c566025 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1579,14 +1579,14 @@ protected: Item_result orig_type; Field *field_example; public: - Item_type_holder(THD*, Item*); + Item_type_holder(THD*, Item*, TABLE *); Item_result result_type () const { return item_type; } enum Type type() const { return TYPE_HOLDER; } double val_real(); longlong val_int(); String *val_str(String*); - bool join_types(THD *thd, Item *); + bool join_types(THD *thd, Item *, TABLE *); Field *example() { return field_example; } static uint32 real_length(Item *item); void cleanup() diff --git a/sql/item_func.cc b/sql/item_func.cc index 8ee1891eafd..3143d21c34b 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3138,9 +3138,7 @@ void Item_func_match::init_search(bool no_order) if (join_key && !no_order) flags|=FT_SORTED; - ft_handler=table->file->ft_init_ext(flags, key, - (byte*) ft_tmp->ptr(), - ft_tmp->length()); + ft_handler=table->file->ft_init_ext(flags, key, ft_tmp); if (join_key) table->file->ft_handler=ft_handler; @@ -3182,12 +3180,12 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) } /* Check that all columns come from the same table. - We've already checked that columns in MATCH are fields so + We've already checked that columns in MATCH are fields so PARAM_TABLE_BIT can only appear from AGAINST argument. */ if ((used_tables_cache & ~PARAM_TABLE_BIT) != item->used_tables()) key=NO_SUCH_KEY; - + if (key == NO_SUCH_KEY && !(flags & FT_BOOL)) { my_error(ER_WRONG_ARGUMENTS,MYF(0),"MATCH"); diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 0a91eb4c0e1..29897c70023 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -153,6 +153,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, SELECT_LEX *sl, *first_select; select_result *tmp_result; bool is_union; + TABLE *empty_table= 0; DBUG_ENTER("st_select_lex_unit::prepare"); describe= test(additional_options & SELECT_DESCRIBE); @@ -249,13 +250,21 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, goto err; if (sl == first_select) { + /* + We need to create an empty table object. It is used + to create tmp_table fields in Item_type_holder. + The main reason of this is that we can't create + field object without table. + */ + DBUG_ASSERT(!empty_table); + empty_table= (TABLE*) thd->calloc(sizeof(TABLE)); types.empty(); List_iterator_fast<Item> it(sl->item_list); Item *item_tmp; while ((item_tmp= it++)) { /* Error's in 'new' will be detected after loop */ - types.push_back(new Item_type_holder(thd_arg, item_tmp)); + types.push_back(new Item_type_holder(thd_arg, item_tmp, empty_table)); } if (thd_arg->is_fatal_error) @@ -274,7 +283,8 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, Item *type, *item_tmp; while ((type= tp++, item_tmp= it++)) { - if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp)) + if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp, + empty_table)) DBUG_RETURN(TRUE); } } |