summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/mysqlcheck.c2
-rw-r--r--include/ft_global.h2
-rw-r--r--myisam/ft_boolean_search.c7
-rw-r--r--myisam/ft_static.c5
-rw-r--r--myisam/ftdefs.h2
-rw-r--r--mysql-test/r/func_group.result12
-rw-r--r--mysql-test/r/insert_select.result.es12
-rw-r--r--mysql-test/r/type_date.result8
-rw-r--r--mysql-test/r/union.result36
-rw-r--r--mysql-test/t/func_group.test14
-rw-r--r--mysql-test/t/type_date.test7
-rw-r--r--mysql-test/t/union.test35
-rw-r--r--scripts/make_binary_distribution.sh2
-rw-r--r--sql/field.cc35
-rw-r--r--sql/field.h241
-rw-r--r--sql/ha_myisam.h8
-rw-r--r--sql/handler.h3
-rw-r--r--sql/item.cc65
-rw-r--r--sql/item.h4
-rw-r--r--sql/item_func.cc8
-rw-r--r--sql/sql_union.cc14
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);
}
}