Commit 8c8553af authored by jimw@mysql.com's avatar jimw@mysql.com

Merge changes

parents d017a604 bd9239d4
......@@ -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");
......
......@@ -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
......
......@@ -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));
......
......@@ -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);
......
......@@ -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 *);
......
......@@ -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;
......@@ -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;
......@@ -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;
......@@ -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;
......@@ -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;
......@@ -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;
......@@ -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;
......@@ -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/*
......
......@@ -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)
......
......@@ -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 @@ class Field
*/
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 @@ class Field
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 @@ class Field
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 @@ class Field
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 @@ class Field
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 @@ class Field
{ 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 @@ class Field
*/
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 @@ class Field
{ 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 @@ class Field
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 @@ class Field
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 @@ class Field
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 @@ class Field_str :public 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; }
......@@ -716,7 +719,7 @@ class Field_timestamp :public Field_str {
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 @@ class Field_newdate :public Field_str {
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 @@ class Field_time :public Field_str {
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 @@ class Field_datetime :public Field_str {
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 @@ class Field_string :public Field_str {
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 @@ class Field_string :public Field_str {
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 @@ class Field_string :public Field_str {
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 @@ class Field_varstring :public Field_str {
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 @@ class Field_blob :public Field_str {
}
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 @@ class Field_blob :public Field_str {
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 @@ class Field_blob :public Field_str {
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 @@ class Field_blob :public Field_str {
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 @@ class Field_blob :public Field_str {
uint32 max_length();
};
#ifdef HAVE_SPATIAL
class Field_geom :public Field_blob {
public:
......@@ -1124,19 +1101,19 @@ class Field_geom :public Field_blob {
: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 @@ class Field_set :public Field_enum {
};
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 @@ class create_field :public Sql_alloc {
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)
......@@ -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);
......
......@@ -455,8 +455,7 @@ class handler :public Sql_alloc
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;
......
......@@ -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;
......
......@@ -1579,14 +1579,14 @@ class Item_type_holder: public Item
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()
......
......@@ -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");
......
......@@ -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);
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment