Commit 80b143c1 authored by unknown's avatar unknown

Change of internal key_field=NULL handling to avoid error messages.

Optimized SELECT DISTINCT ... ORDER BY ... LIMIT
Fixed reference to uninitalized variable


mysql-test/r/distinct.result:
  Updated results for new tests
mysql-test/r/func_math.result:
  Fixed test of RND()
mysql-test/r/innodb.result:
  Updated results for new tests
mysql-test/r/null.result:
  Updated results for new tests
mysql-test/t/distinct.test:
  New distinct test
mysql-test/t/func_math.test:
  Fixed test of RND()
mysql-test/t/innodb.test:
  Test for bugs
mysql-test/t/null.test:
  TEst for bugs
sql/field.h:
  Change of NULL handling to avoid error messages
sql/field_conv.cc:
  Change of NULL handling to avoid error messages
sql/item.cc:
  Change of NULL handling to avoid error messages
sql/item.h:
  Change of NULL handling to avoid error messages
sql/item_cmpfunc.cc:
  Change of NULL handling to avoid error messages
sql/item_func.cc:
  Change of NULL handling to avoid error messages
sql/item_func.h:
  Cleaned up RND() handling
sql/item_timefunc.cc:
  Change of NULL handling to avoid error messages
sql/item_timefunc.h:
  Change of NULL handling to avoid error messages
sql/opt_range.cc:
  Fixed bug in <=> NULL
sql/password.c:
  Indentation cleanup
sql/sql_base.cc:
  Change of NULL handling to avoid error messages
sql/sql_class.cc:
  Fixed reference to uninitalized variable
sql/sql_handler.cc:
  Change of NULL handling to avoid error messages
sql/sql_select.cc:
  Change of NULL handling to avoid error messages
  Optimized SELECT DISTINCT ... ORDER BY ... LIMIT
sql/sql_select.h:
  Change of NULL handling to avoid error messages
sql/unireg.cc:
  Change of NULL handling to avoid error messages
parent 4f221e35
...@@ -198,6 +198,30 @@ a ...@@ -198,6 +198,30 @@ a
select distinct 1 from t1,t3 where t1.a=t3.a; select distinct 1 from t1,t3 where t1.a=t3.a;
1 1
1 1
explain SELECT distinct t1.a from t1;
table type possible_keys key key_len ref rows Extra
t1 index NULL PRIMARY 4 NULL 2 Using index
explain SELECT distinct t1.a from t1 order by a desc;
table type possible_keys key key_len ref rows Extra
t1 index NULL PRIMARY 4 NULL 2 Using index
explain SELECT t1.a from t1 group by a order by a desc;
table type possible_keys key key_len ref rows Extra
t1 index NULL PRIMARY 4 NULL 2 Using index
explain SELECT distinct t1.a from t1 order by a desc limit 1;
table type possible_keys key key_len ref rows Extra
t1 index NULL PRIMARY 4 NULL 2 Using index
explain SELECT distinct a from t3 order by a desc limit 2;
table type possible_keys key key_len ref rows Extra
t3 index NULL a 5 NULL 204 Using index
explain SELECT distinct a,b from t3 order by a+1;
table type possible_keys key key_len ref rows Extra
t3 ALL NULL NULL NULL NULL 204 Using temporary; Using filesort
explain SELECT distinct a,b from t3 order by a limit 10;
table type possible_keys key key_len ref rows Extra
t3 index NULL a 5 NULL 204 Using temporary
explain SELECT a,b from t3 group by a,b order by a+1;
table type possible_keys key key_len ref rows Extra
t3 ALL NULL NULL NULL NULL 204 Using temporary; Using filesort
drop table t1,t2,t3,t4; drop table t1,t2,t3,t4;
CREATE TABLE t1 (name varchar(255)); CREATE TABLE t1 (name varchar(255));
INSERT INTO t1 VALUES ('aa'),('ab'),('ac'),('ad'),('ae'); INSERT INTO t1 VALUES ('aa'),('ab'),('ac'),('ad'),('ae');
......
...@@ -31,9 +31,10 @@ log10(100) log10(18) log10(-4) log10(0) log10(NULL) ...@@ -31,9 +31,10 @@ log10(100) log10(18) log10(-4) log10(0) log10(NULL)
select pow(10,log10(10)),power(2,4); select pow(10,log10(10)),power(2,4);
pow(10,log10(10)) power(2,4) pow(10,log10(10)) power(2,4)
10.000000 16.000000 10.000000 16.000000
set @@rand_seed1=10000000,@@rand_seed2=1000000;
select rand(999999),rand(); select rand(999999),rand();
rand(999999) rand() rand(999999) rand()
0.014231365187309 0.8078568166195 0.014231365187309 0.028870999839968
select pi(),sin(pi()/2),cos(pi()/2),abs(tan(pi())),cot(1),asin(1),acos(0),atan(1); select pi(),sin(pi()/2),cos(pi()/2),abs(tan(pi())),cot(1),asin(1),acos(0),atan(1);
PI() sin(pi()/2) cos(pi()/2) abs(tan(pi())) cot(1) asin(1) acos(0) atan(1) PI() sin(pi()/2) cos(pi()/2) abs(tan(pi())) cot(1) asin(1) acos(0) atan(1)
3.141593 1.000000 0.000000 0.000000 0.64209262 1.570796 1.570796 0.785398 3.141593 1.000000 0.000000 0.000000 0.64209262 1.570796 1.570796 0.785398
......
...@@ -1036,3 +1036,25 @@ n d ...@@ -1036,3 +1036,25 @@ n d
1 30 1 30
2 20 2 20
drop table t1,t2; drop table t1,t2;
create table t1 (a int, b int) type=innodb;
insert into t1 values(20,null);
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
t2.b=t3.a;
b ifnull(t2.b,"this is null")
NULL this is null
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
t2.b=t3.a order by 1;
b ifnull(t2.b,"this is null")
NULL this is null
insert into t1 values(10,null);
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
t2.b=t3.a order by 1;
b ifnull(t2.b,"this is null")
NULL this is null
NULL this is null
drop table t1;
create table t1 (a varchar(10) not null) type=myisam;
create table t2 (b varchar(10) not null unique) type=innodb;
select t1.a from t1,t2 where t1.a=t2.b;
a
drop table t1,t2;
...@@ -6,7 +6,7 @@ select 1 | NULL,1 & NULL,1+NULL,1-NULL; ...@@ -6,7 +6,7 @@ select 1 | NULL,1 & NULL,1+NULL,1-NULL;
NULL NULL NULL NULL NULL NULL NULL NULL
select NULL=NULL,NULL<>NULL,IFNULL(NULL,1.1)+0,IFNULL(NULL,1) | 0; select NULL=NULL,NULL<>NULL,IFNULL(NULL,1.1)+0,IFNULL(NULL,1) | 0;
NULL=NULL NULL<>NULL IFNULL(NULL,1.1)+0 IFNULL(NULL,1) | 0 NULL=NULL NULL<>NULL IFNULL(NULL,1.1)+0 IFNULL(NULL,1) | 0
NULL NULL 1.1 1 NULL NULL 1 1
select strcmp("a",NULL),(1<NULL)+0.0,NULL regexp "a",null like "a%","a%" like null; select strcmp("a",NULL),(1<NULL)+0.0,NULL regexp "a",null like "a%","a%" like null;
strcmp("a",NULL) (1<NULL)+0.0 NULL regexp "a" null like "a%" "a%" like null strcmp("a",NULL) (1<NULL)+0.0 NULL regexp "a" null like "a%" "a%" like null
NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
...@@ -56,3 +56,20 @@ indexed_field ...@@ -56,3 +56,20 @@ indexed_field
NULL NULL
NULL NULL
DROP TABLE t1; DROP TABLE t1;
create table t1 (a int, b int) type=myisam;
insert into t1 values(20,null);
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
t2.b=t3.a;
b ifnull(t2.b,"this is null")
NULL this is null
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
t2.b=t3.a order by 1;
b ifnull(t2.b,"this is null")
NULL this is null
insert into t1 values(10,null);
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
t2.b=t3.a order by 1;
b ifnull(t2.b,"this is null")
NULL this is null
NULL this is null
drop table t1;
...@@ -88,6 +88,16 @@ select distinct t1.a from t1,t3 where t1.a=t3.a; ...@@ -88,6 +88,16 @@ select distinct t1.a from t1,t3 where t1.a=t3.a;
#flush status; #flush status;
select distinct 1 from t1,t3 where t1.a=t3.a; select distinct 1 from t1,t3 where t1.a=t3.a;
#show status like 'Handler%'; #show status like 'Handler%';
explain SELECT distinct t1.a from t1;
explain SELECT distinct t1.a from t1 order by a desc;
explain SELECT t1.a from t1 group by a order by a desc;
explain SELECT distinct t1.a from t1 order by a desc limit 1;
explain SELECT distinct a from t3 order by a desc limit 2;
explain SELECT distinct a,b from t3 order by a+1;
explain SELECT distinct a,b from t3 order by a limit 10;
explain SELECT a,b from t3 group by a,b order by a+1;
drop table t1,t2,t3,t4; drop table t1,t2,t3,t4;
CREATE TABLE t1 (name varchar(255)); CREATE TABLE t1 (name varchar(255));
......
...@@ -13,6 +13,7 @@ select ln(exp(10)),exp(ln(sqrt(10))*2),ln(-1),ln(0),ln(NULL); ...@@ -13,6 +13,7 @@ select ln(exp(10)),exp(ln(sqrt(10))*2),ln(-1),ln(0),ln(NULL);
select log2(8),log2(15),log2(-2),log2(0),log2(NULL); select log2(8),log2(15),log2(-2),log2(0),log2(NULL);
select log10(100),log10(18),log10(-4),log10(0),log10(NULL); select log10(100),log10(18),log10(-4),log10(0),log10(NULL);
select pow(10,log10(10)),power(2,4); select pow(10,log10(10)),power(2,4);
set @@rand_seed1=10000000,@@rand_seed2=1000000;
select rand(999999),rand(); select rand(999999),rand();
select pi(),sin(pi()/2),cos(pi()/2),abs(tan(pi())),cot(1),asin(1),acos(0),atan(1); select pi(),sin(pi()/2),cos(pi()/2),abs(tan(pi())),cot(1),asin(1),acos(0),atan(1);
select degrees(pi()),radians(360); select degrees(pi()),radians(360);
...@@ -673,3 +673,26 @@ UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n; ...@@ -673,3 +673,26 @@ UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
select * from t1; select * from t1;
select * from t2; select * from t2;
drop table t1,t2; drop table t1,t2;
#
# Testing of IFNULL
#
create table t1 (a int, b int) type=innodb;
insert into t1 values(20,null);
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
t2.b=t3.a;
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
t2.b=t3.a order by 1;
insert into t1 values(10,null);
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
t2.b=t3.a order by 1;
drop table t1;
#
# Test of read_through not existing const_table
#
create table t1 (a varchar(10) not null) type=myisam;
create table t2 (b varchar(10) not null unique) type=innodb;
select t1.a from t1,t2 where t1.a=t2.b;
drop table t1,t2;
...@@ -34,3 +34,17 @@ SELECT * FROM t1 WHERE indexed_field=NULL; ...@@ -34,3 +34,17 @@ SELECT * FROM t1 WHERE indexed_field=NULL;
SELECT * FROM t1 WHERE indexed_field IS NULL; SELECT * FROM t1 WHERE indexed_field IS NULL;
SELECT * FROM t1 WHERE indexed_field<=>NULL; SELECT * FROM t1 WHERE indexed_field<=>NULL;
DROP TABLE t1; DROP TABLE t1;
#
# Testing of IFNULL
#
create table t1 (a int, b int) type=myisam;
insert into t1 values(20,null);
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
t2.b=t3.a;
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
t2.b=t3.a order by 1;
insert into t1 values(10,null);
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
t2.b=t3.a order by 1;
drop table t1;
...@@ -1058,7 +1058,7 @@ Field *make_field(char *ptr, uint32 field_length, ...@@ -1058,7 +1058,7 @@ Field *make_field(char *ptr, uint32 field_length,
uint pack_length_to_packflag(uint type); uint pack_length_to_packflag(uint type);
uint32 calc_pack_length(enum_field_types type,uint32 length); uint32 calc_pack_length(enum_field_types type,uint32 length);
bool set_field_to_null(Field *field); bool set_field_to_null(Field *field);
bool set_field_to_null_with_conversions(Field *field); bool set_field_to_null_with_conversions(Field *field, bool no_conversions);
uint find_enum(TYPELIB *typelib,const char *x, uint length); uint find_enum(TYPELIB *typelib,const char *x, uint length);
ulonglong find_set(TYPELIB *typelib,const char *x, uint length); ulonglong find_set(TYPELIB *typelib,const char *x, uint length);
bool test_if_int(const char *str,int length); bool test_if_int(const char *str,int length);
......
...@@ -122,8 +122,26 @@ set_field_to_null(Field *field) ...@@ -122,8 +122,26 @@ set_field_to_null(Field *field)
} }
/*
Set field to NULL or TIMESTAMP or to next auto_increment number
SYNOPSIS
set_field_to_null_with_conversions()
field Field to update
no_conversion Set to 1 if we should return 1 if field can't
take null values.
If set to 0 we will do store the 'default value'
if the field is a special field. If not we will
give an error.
RETURN VALUES
0 Field could take 0 or an automatic conversion was used
1 Field could not take NULL and no conversion was used.
If no_conversion was not set, an error message is printed
*/
bool bool
set_field_to_null_with_conversions(Field *field) set_field_to_null_with_conversions(Field *field, bool no_conversions)
{ {
if (field->real_maybe_null()) if (field->real_maybe_null())
{ {
...@@ -131,6 +149,8 @@ set_field_to_null_with_conversions(Field *field) ...@@ -131,6 +149,8 @@ set_field_to_null_with_conversions(Field *field)
field->reset(); field->reset();
return 0; return 0;
} }
if (no_conversions)
return 1;
/* /*
Check if this is a special type, which will get a special walue Check if this is a special type, which will get a special walue
...@@ -156,8 +176,6 @@ set_field_to_null_with_conversions(Field *field) ...@@ -156,8 +176,6 @@ set_field_to_null_with_conversions(Field *field)
} }
static void do_skip(Copy_field *copy __attribute__((unused))) static void do_skip(Copy_field *copy __attribute__((unused)))
{ {
} }
......
...@@ -419,7 +419,7 @@ void Item_field::save_org_in_field(Field *to) ...@@ -419,7 +419,7 @@ void Item_field::save_org_in_field(Field *to)
if (field->is_null()) if (field->is_null())
{ {
null_value=1; null_value=1;
set_field_to_null_with_conversions(to); set_field_to_null_with_conversions(to, 1);
} }
else else
{ {
...@@ -429,12 +429,12 @@ void Item_field::save_org_in_field(Field *to) ...@@ -429,12 +429,12 @@ void Item_field::save_org_in_field(Field *to)
} }
} }
bool Item_field::save_in_field(Field *to) bool Item_field::save_in_field(Field *to, bool no_conversions)
{ {
if (result_field->is_null()) if (result_field->is_null())
{ {
null_value=1; null_value=1;
return set_field_to_null_with_conversions(to); return set_field_to_null_with_conversions(to, no_conversions);
} }
else else
{ {
...@@ -461,9 +461,9 @@ bool Item_field::save_in_field(Field *to) ...@@ -461,9 +461,9 @@ bool Item_field::save_in_field(Field *to)
1 Field doesn't support NULL values and can't handle 'field = NULL' 1 Field doesn't support NULL values and can't handle 'field = NULL'
*/ */
bool Item_null::save_in_field(Field *field) bool Item_null::save_in_field(Field *field, bool no_conversions)
{ {
return set_field_to_null_with_conversions(field); return set_field_to_null_with_conversions(field, no_conversions);
} }
...@@ -485,7 +485,7 @@ bool Item_null::save_safe_in_field(Field *field) ...@@ -485,7 +485,7 @@ bool Item_null::save_safe_in_field(Field *field)
} }
bool Item::save_in_field(Field *field) bool Item::save_in_field(Field *field, bool no_conversions)
{ {
if (result_type() == STRING_RESULT || if (result_type() == STRING_RESULT ||
result_type() == REAL_RESULT && result_type() == REAL_RESULT &&
...@@ -496,7 +496,7 @@ bool Item::save_in_field(Field *field) ...@@ -496,7 +496,7 @@ bool Item::save_in_field(Field *field)
str_value.set_quick(buff,sizeof(buff)); str_value.set_quick(buff,sizeof(buff));
result=val_str(&str_value); result=val_str(&str_value);
if (null_value) if (null_value)
return set_field_to_null_with_conversions(field); return set_field_to_null_with_conversions(field, no_conversions);
field->set_notnull(); field->set_notnull();
field->store(result->ptr(),result->length()); field->store(result->ptr(),result->length());
str_value.set_quick(0, 0); str_value.set_quick(0, 0);
...@@ -513,7 +513,7 @@ bool Item::save_in_field(Field *field) ...@@ -513,7 +513,7 @@ bool Item::save_in_field(Field *field)
{ {
longlong nr=val_int(); longlong nr=val_int();
if (null_value) if (null_value)
return set_field_to_null_with_conversions(field); return set_field_to_null_with_conversions(field, no_conversions);
field->set_notnull(); field->set_notnull();
field->store(nr); field->store(nr);
} }
...@@ -521,7 +521,7 @@ bool Item::save_in_field(Field *field) ...@@ -521,7 +521,7 @@ bool Item::save_in_field(Field *field)
} }
bool Item_string::save_in_field(Field *field) bool Item_string::save_in_field(Field *field, bool no_conversions)
{ {
String *result; String *result;
result=val_str(&str_value); result=val_str(&str_value);
...@@ -532,7 +532,7 @@ bool Item_string::save_in_field(Field *field) ...@@ -532,7 +532,7 @@ bool Item_string::save_in_field(Field *field)
return 0; return 0;
} }
bool Item_int::save_in_field(Field *field) bool Item_int::save_in_field(Field *field, bool no_conversions)
{ {
longlong nr=val_int(); longlong nr=val_int();
if (null_value) if (null_value)
...@@ -542,7 +542,7 @@ bool Item_int::save_in_field(Field *field) ...@@ -542,7 +542,7 @@ bool Item_int::save_in_field(Field *field)
return 0; return 0;
} }
bool Item_real::save_in_field(Field *field) bool Item_real::save_in_field(Field *field, bool no_conversions)
{ {
double nr=val(); double nr=val();
if (null_value) if (null_value)
...@@ -597,7 +597,7 @@ longlong Item_varbinary::val_int() ...@@ -597,7 +597,7 @@ longlong Item_varbinary::val_int()
} }
bool Item_varbinary::save_in_field(Field *field) bool Item_varbinary::save_in_field(Field *field, bool no_conversions)
{ {
field->set_notnull(); field->set_notnull();
if (field->result_type() == STRING_RESULT) if (field->result_type() == STRING_RESULT)
...@@ -658,9 +658,10 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables) ...@@ -658,9 +658,10 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables)
return 0; return 0;
} }
/* /*
** If item is a const function, calculate it and return a const item If item is a const function, calculate it and return a const item
** The original item is freed if not returned The original item is freed if not returned
*/ */
Item_result item_cmp_type(Item_result a,Item_result b) Item_result item_cmp_type(Item_result a,Item_result b)
......
...@@ -53,11 +53,11 @@ public: ...@@ -53,11 +53,11 @@ public:
void set_name(char* str,uint length=0); void set_name(char* str,uint length=0);
void init_make_field(Send_field *tmp_field,enum enum_field_types type); void init_make_field(Send_field *tmp_field,enum enum_field_types type);
virtual bool fix_fields(THD *,struct st_table_list *); virtual bool fix_fields(THD *,struct st_table_list *);
virtual bool save_in_field(Field *field); virtual bool save_in_field(Field *field, bool no_conversions);
virtual void save_org_in_field(Field *field) virtual void save_org_in_field(Field *field)
{ (void) save_in_field(field); } { (void) save_in_field(field, 1); }
virtual bool save_safe_in_field(Field *field) virtual bool save_safe_in_field(Field *field)
{ return save_in_field(field); } { return save_in_field(field, 1); }
virtual bool send(THD *thd, String *str); virtual bool send(THD *thd, String *str);
virtual bool eq(const Item *, bool binary_cmp) const; virtual bool eq(const Item *, bool binary_cmp) const;
virtual Item_result result_type () const { return REAL_RESULT; } virtual Item_result result_type () const { return REAL_RESULT; }
...@@ -130,7 +130,7 @@ public: ...@@ -130,7 +130,7 @@ public:
} }
void make_field(Send_field *field); void make_field(Send_field *field);
bool fix_fields(THD *,struct st_table_list *); bool fix_fields(THD *,struct st_table_list *);
bool save_in_field(Field *field); bool save_in_field(Field *field,bool no_conversions);
void save_org_in_field(Field *field); void save_org_in_field(Field *field);
table_map used_tables() const; table_map used_tables() const;
enum Item_result result_type () const enum Item_result result_type () const
...@@ -156,7 +156,7 @@ public: ...@@ -156,7 +156,7 @@ public:
longlong val_int(); longlong val_int();
String *val_str(String *str); String *val_str(String *str);
void make_field(Send_field *field); void make_field(Send_field *field);
bool save_in_field(Field *field); bool save_in_field(Field *field, bool no_conversions);
bool save_safe_in_field(Field *field); bool save_safe_in_field(Field *field);
enum Item_result result_type () const enum Item_result result_type () const
{ return STRING_RESULT; } { return STRING_RESULT; }
...@@ -190,7 +190,7 @@ public: ...@@ -190,7 +190,7 @@ public:
double val() { return (double) value; } double val() { return (double) value; }
String *val_str(String*); String *val_str(String*);
void make_field(Send_field *field); void make_field(Send_field *field);
bool save_in_field(Field *field); bool save_in_field(Field *field, bool no_conversions);
bool basic_const_item() const { return 1; } bool basic_const_item() const { return 1; }
Item *new_item() { return new Item_int(name,value,max_length); } Item *new_item() { return new Item_int(name,value,max_length); }
void print(String *str); void print(String *str);
...@@ -232,7 +232,7 @@ public: ...@@ -232,7 +232,7 @@ public:
max_length=length; max_length=length;
} }
Item_real(double value_par) :value(value_par) {} Item_real(double value_par) :value(value_par) {}
bool save_in_field(Field *field); bool save_in_field(Field *field, bool no_conversions);
enum Type type() const { return REAL_ITEM; } enum Type type() const { return REAL_ITEM; }
double val() { return value; } double val() { return value; }
longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5));} longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5));}
...@@ -277,7 +277,7 @@ public: ...@@ -277,7 +277,7 @@ public:
double val() { return atof(str_value.ptr()); } double val() { return atof(str_value.ptr()); }
longlong val_int() { return strtoll(str_value.ptr(),(char**) 0,10); } longlong val_int() { return strtoll(str_value.ptr(),(char**) 0,10); }
String *val_str(String*) { return (String*) &str_value; } String *val_str(String*) { return (String*) &str_value; }
bool save_in_field(Field *field); bool save_in_field(Field *field, bool no_conversions);
void make_field(Send_field *field); void make_field(Send_field *field);
enum Item_result result_type () const { return STRING_RESULT; } enum Item_result result_type () const { return STRING_RESULT; }
bool basic_const_item() const { return 1; } bool basic_const_item() const { return 1; }
...@@ -298,7 +298,7 @@ public: ...@@ -298,7 +298,7 @@ public:
Item_default() { name= (char*) "DEFAULT"; } Item_default() { name= (char*) "DEFAULT"; }
enum Type type() const { return DEFAULT_ITEM; } enum Type type() const { return DEFAULT_ITEM; }
void make_field(Send_field *field) {} void make_field(Send_field *field) {}
bool save_in_field(Field *field) bool save_in_field(Field *field, bool no_conversions)
{ {
field->set_default(); field->set_default();
return 0; return 0;
...@@ -339,7 +339,7 @@ public: ...@@ -339,7 +339,7 @@ public:
double val() { return (double) Item_varbinary::val_int(); } double val() { return (double) Item_varbinary::val_int(); }
longlong val_int(); longlong val_int();
String *val_str(String*) { return &str_value; } String *val_str(String*) { return &str_value; }
bool save_in_field(Field *field); bool save_in_field(Field *field, bool no_conversions);
void make_field(Send_field *field); void make_field(Send_field *field);
enum Item_result result_type () const { return INT_RESULT; } enum Item_result result_type () const { return INT_RESULT; }
unsigned int size_of() { return sizeof(*this);} unsigned int size_of() { return sizeof(*this);}
...@@ -401,7 +401,8 @@ public: ...@@ -401,7 +401,8 @@ public:
bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); } bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); }
void make_field(Send_field *field) { (*ref)->make_field(field); } void make_field(Send_field *field) { (*ref)->make_field(field); }
bool fix_fields(THD *,struct st_table_list *); bool fix_fields(THD *,struct st_table_list *);
bool save_in_field(Field *field) { return (*ref)->save_in_field(field); } bool save_in_field(Field *field, bool no_conversions)
{ return (*ref)->save_in_field(field, no_conversions); }
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); } void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
enum Item_result result_type () const { return (*ref)->result_type(); } enum Item_result result_type () const { return (*ref)->result_type(); }
table_map used_tables() const { return (*ref)->used_tables(); } table_map used_tables() const { return (*ref)->used_tables(); }
...@@ -421,9 +422,9 @@ class Item_int_with_ref :public Item_int ...@@ -421,9 +422,9 @@ class Item_int_with_ref :public Item_int
public: public:
Item_int_with_ref(longlong i, Item *ref_arg) :Item_int(i), ref(ref_arg) Item_int_with_ref(longlong i, Item *ref_arg) :Item_int(i), ref(ref_arg)
{} {}
bool save_in_field(Field *field) bool save_in_field(Field *field, bool no_conversions)
{ {
return ref->save_in_field(field); return ref->save_in_field(field, no_conversions);
} }
unsigned int size_of() { return sizeof(*this);} unsigned int size_of() { return sizeof(*this);}
}; };
......
...@@ -48,7 +48,7 @@ static bool convert_constant_item(Field *field, Item **item) ...@@ -48,7 +48,7 @@ static bool convert_constant_item(Field *field, Item **item)
{ {
if ((*item)->const_item() && (*item)->type() != Item::INT_ITEM) if ((*item)->const_item() && (*item)->type() != Item::INT_ITEM)
{ {
if (!(*item)->save_in_field(field) && if (!(*item)->save_in_field(field, 1) &&
!((*item)->null_value)) !((*item)->null_value))
{ {
Item *tmp=new Item_int_with_ref(field->val_int(), *item); Item *tmp=new Item_int_with_ref(field->val_int(), *item);
...@@ -444,15 +444,29 @@ longlong Item_func_between::val_int() ...@@ -444,15 +444,29 @@ longlong Item_func_between::val_int()
return 0; return 0;
} }
static Item_result item_store_type(Item_result a,Item_result b)
{
if (a == STRING_RESULT || b == STRING_RESULT)
return STRING_RESULT;
else if (a == REAL_RESULT || b == REAL_RESULT)
return REAL_RESULT;
else
return INT_RESULT;
}
void void
Item_func_ifnull::fix_length_and_dec() Item_func_ifnull::fix_length_and_dec()
{ {
maybe_null=args[1]->maybe_null; maybe_null=args[1]->maybe_null;
max_length=max(args[0]->max_length,args[1]->max_length); max_length=max(args[0]->max_length,args[1]->max_length);
decimals=max(args[0]->decimals,args[1]->decimals); decimals=max(args[0]->decimals,args[1]->decimals);
cached_result_type=args[0]->result_type(); if ((cached_result_type=item_store_type(args[0]->result_type(),
args[1]->result_type())) !=
REAL_RESULT)
decimals= 0;
} }
double double
Item_func_ifnull::val() Item_func_ifnull::val()
{ {
......
...@@ -696,21 +696,20 @@ double Item_func_round::val() ...@@ -696,21 +696,20 @@ double Item_func_round::val()
} }
double Item_func_rand::val() void Item_func_rand::fix_length_and_dec()
{ {
THD* thd = current_thd; decimals=NOT_FIXED_DEC;
max_length=float_length(decimals);
if (arg_count) if (arg_count)
{ // Only use argument once in query { // Only use argument once in query
uint32 tmp= (uint32) (args[0]->val_int()); uint32 tmp= (uint32) (args[0]->val_int());
randominit(&thd->rand,(uint32) (tmp*0x10001L+55555555L), if ((rand= (struct rand_struct*) sql_alloc(sizeof(*rand))))
randominit(rand,(uint32) (tmp*0x10001L+55555555L),
(uint32) (tmp*0x10000001L)); (uint32) (tmp*0x10000001L));
#ifdef DELETE_ITEMS
delete args[0];
#endif
arg_count=0;
} }
else if (!thd->rand_used) else
{ {
THD *thd= current_thd;
/* /*
No need to send a Rand log event if seed was given eg: RAND(seed), No need to send a Rand log event if seed was given eg: RAND(seed),
as it will be replicated in the query as such. as it will be replicated in the query as such.
...@@ -722,8 +721,14 @@ double Item_func_rand::val() ...@@ -722,8 +721,14 @@ double Item_func_rand::val()
thd->rand_used=1; thd->rand_used=1;
thd->rand_saved_seed1=thd->rand.seed1; thd->rand_saved_seed1=thd->rand.seed1;
thd->rand_saved_seed2=thd->rand.seed2; thd->rand_saved_seed2=thd->rand.seed2;
rand= &thd->rand;
} }
return rnd(&thd->rand); }
double Item_func_rand::val()
{
return rnd(rand);
} }
longlong Item_func_sign::val_int() longlong Item_func_sign::val_int()
......
...@@ -459,20 +459,20 @@ public: ...@@ -459,20 +459,20 @@ public:
const char *func_name() const { return truncate ? "truncate" : "round"; } const char *func_name() const { return truncate ? "truncate" : "round"; }
double val(); double val();
void fix_length_and_dec(); void fix_length_and_dec();
unsigned int size_of() { return sizeof(*this);}
}; };
class Item_func_rand :public Item_real_func class Item_func_rand :public Item_real_func
{ {
struct rand_struct *rand;
public: public:
Item_func_rand(Item *a) :Item_real_func(a) {} Item_func_rand(Item *a) :Item_real_func(a) {}
Item_func_rand() :Item_real_func() {} Item_func_rand() :Item_real_func() {}
double val(); double val();
const char *func_name() const { return "rand"; } const char *func_name() const { return "rand"; }
void fix_length_and_dec() { decimals=NOT_FIXED_DEC; max_length=float_length(decimals); }
bool const_item() const { return 0; } bool const_item() const { return 0; }
table_map used_tables() const { return RAND_TABLE_BIT; } table_map used_tables() const { return RAND_TABLE_BIT; }
void fix_length_and_dec();
}; };
......
...@@ -403,7 +403,7 @@ String *Item_date::val_str(String *str) ...@@ -403,7 +403,7 @@ String *Item_date::val_str(String *str)
} }
bool Item_date::save_in_field(Field *field) bool Item_date::save_in_field(Field *field, bool no_conversions)
{ {
TIME ltime; TIME ltime;
timestamp_type t_type=TIMESTAMP_FULL; timestamp_type t_type=TIMESTAMP_FULL;
...@@ -518,7 +518,7 @@ bool Item_func_now::get_date(TIME *res, ...@@ -518,7 +518,7 @@ bool Item_func_now::get_date(TIME *res,
} }
bool Item_func_now::save_in_field(Field *to) bool Item_func_now::save_in_field(Field *to, bool no_conversions)
{ {
to->set_notnull(); to->set_notnull();
to->store_time(&ltime,TIMESTAMP_FULL); to->store_time(&ltime,TIMESTAMP_FULL);
......
...@@ -231,7 +231,7 @@ public: ...@@ -231,7 +231,7 @@ public:
double val() { return (double) val_int(); } double val() { return (double) val_int(); }
const char *func_name() const { return "date"; } const char *func_name() const { return "date"; }
void fix_length_and_dec() { decimals=0; max_length=10; } void fix_length_and_dec() { decimals=0; max_length=10; }
bool save_in_field(Field *to); bool save_in_field(Field *to, bool no_conversions);
void make_field(Send_field *tmp_field) void make_field(Send_field *tmp_field)
{ {
init_make_field(tmp_field,FIELD_TYPE_DATE); init_make_field(tmp_field,FIELD_TYPE_DATE);
...@@ -316,7 +316,7 @@ public: ...@@ -316,7 +316,7 @@ public:
enum Item_result result_type () const { return STRING_RESULT; } enum Item_result result_type () const { return STRING_RESULT; }
double val() { return (double) value; } double val() { return (double) value; }
longlong val_int() { return value; } longlong val_int() { return value; }
bool save_in_field(Field *to); bool save_in_field(Field *to, bool no_conversions);
String *val_str(String *str) String *val_str(String *str)
{ str_value.set(buff,buff_length); return &str_value; } { str_value.set(buff,buff_length); return &str_value; }
const char *func_name() const { return "now"; } const char *func_name() const { return "now"; }
......
...@@ -1029,7 +1029,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, ...@@ -1029,7 +1029,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
field->cmp_type() != value->result_type()) field->cmp_type() != value->result_type())
DBUG_RETURN(0); DBUG_RETURN(0);
if (value->save_in_field(field)) if (value->save_in_field(field, 1))
{ {
/* This happens when we try to insert a NULL field in a not null column */ /* This happens when we try to insert a NULL field in a not null column */
// TODO; Check if we can we remove the following block. // TODO; Check if we can we remove the following block.
...@@ -1038,9 +1038,9 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, ...@@ -1038,9 +1038,9 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
/* convert column_name <=> NULL -> column_name IS NULL */ /* convert column_name <=> NULL -> column_name IS NULL */
// Get local copy of key // Get local copy of key
char *str= (char*) alloc_root(param->mem_root,1); char *str= (char*) alloc_root(param->mem_root,1);
if (!*str) if (!str)
DBUG_RETURN(0); DBUG_RETURN(0);
*str = 1; *str= 1;
DBUG_RETURN(new SEL_ARG(field,str,str)); DBUG_RETURN(new SEL_ARG(field,str,str));
} }
DBUG_RETURN(&null_element); // cmp with NULL is never true DBUG_RETURN(&null_element); // cmp with NULL is never true
......
...@@ -2098,7 +2098,7 @@ fill_record(List<Item> &fields,List<Item> &values) ...@@ -2098,7 +2098,7 @@ fill_record(List<Item> &fields,List<Item> &values)
while ((field=(Item_field*) f++)) while ((field=(Item_field*) f++))
{ {
value=v++; value=v++;
if (value->save_in_field(field->field)) if (value->save_in_field(field->field, 0))
DBUG_RETURN(1); DBUG_RETURN(1);
} }
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -2116,7 +2116,7 @@ fill_record(Field **ptr,List<Item> &values) ...@@ -2116,7 +2116,7 @@ fill_record(Field **ptr,List<Item> &values)
while ((field = *ptr++)) while ((field = *ptr++))
{ {
value=v++; value=v++;
if (value->save_in_field(field)) if (value->save_in_field(field, 0))
DBUG_RETURN(1); DBUG_RETURN(1);
} }
DBUG_RETURN(0); DBUG_RETURN(0);
......
...@@ -158,9 +158,8 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), ...@@ -158,9 +158,8 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
{ {
pthread_mutex_lock(&LOCK_thread_count); pthread_mutex_lock(&LOCK_thread_count);
ulong tmp=(ulong) (rnd(&sql_rand) * 3000000); ulong tmp=(ulong) (rnd(&sql_rand) * 3000000);
randominit(&rand, tmp + (ulong) start_time,
tmp + (ulong) thread_id);
pthread_mutex_unlock(&LOCK_thread_count); pthread_mutex_unlock(&LOCK_thread_count);
randominit(&rand, tmp + (ulong) start_time, tmp + (ulong) thread_id);
} }
} }
...@@ -171,16 +170,16 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), ...@@ -171,16 +170,16 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
void THD::init(void) void THD::init(void)
{ {
pthread_mutex_lock(&LOCK_global_system_variables);
variables= global_system_variables;
pthread_mutex_unlock(&LOCK_global_system_variables);
server_status= SERVER_STATUS_AUTOCOMMIT; server_status= SERVER_STATUS_AUTOCOMMIT;
update_lock_default= (variables.low_priority_updates ?
TL_WRITE_LOW_PRIORITY :
TL_WRITE);
options= thd_startup_options; options= thd_startup_options;
sql_mode=(uint) opt_sql_mode; sql_mode=(uint) opt_sql_mode;
open_options=ha_open_options; open_options=ha_open_options;
pthread_mutex_lock(&LOCK_global_system_variables); update_lock_default= (variables.low_priority_updates ?
variables= global_system_variables; TL_WRITE_LOW_PRIORITY :
pthread_mutex_unlock(&LOCK_global_system_variables); TL_WRITE);
session_tx_isolation= (enum_tx_isolation) variables.tx_isolation; session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
} }
......
...@@ -180,10 +180,10 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, ...@@ -180,10 +180,10 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
Item *item; Item *item;
for (key_len=0 ; (item=it_ke++) ; key_part++) for (key_len=0 ; (item=it_ke++) ; key_part++)
{ {
item->save_in_field(key_part->field); item->save_in_field(key_part->field, 1);
key_len+=key_part->store_length; key_len+=key_part->store_length;
} }
if (!(key= (byte*) sql_calloc(ALIGN_SIZE(key_len)))) if (!(key= (byte*) thd->calloc(ALIGN_SIZE(key_len))))
{ {
send_error(&thd->net,ER_OUTOFMEMORY); send_error(&thd->net,ER_OUTOFMEMORY);
goto err; goto err;
......
...@@ -130,7 +130,9 @@ static int setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields, ...@@ -130,7 +130,9 @@ static int setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &all_fields, ORDER *order, bool *hidden); List<Item> &all_fields, ORDER *order, bool *hidden);
static bool setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields, static bool setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &all_fields,ORDER *new_order); List<Item> &all_fields,ORDER *new_order);
static ORDER *create_distinct_group(ORDER *order, List<Item> &fields); static ORDER *create_distinct_group(THD *thd, ORDER *order,
List<Item> &fields,
bool *all_order_by_fields_used);
static bool test_if_subpart(ORDER *a,ORDER *b); static bool test_if_subpart(ORDER *a,ORDER *b);
static TABLE *get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables); static TABLE *get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables);
static void calc_group_buffer(JOIN *join,ORDER *group); static void calc_group_buffer(JOIN *join,ORDER *group);
...@@ -228,6 +230,10 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -228,6 +230,10 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
bzero((char*) &keyuse,sizeof(keyuse)); bzero((char*) &keyuse,sizeof(keyuse));
thd->proc_info="init"; thd->proc_info="init";
thd->used_tables=0; // Updated by setup_fields thd->used_tables=0; // Updated by setup_fields
/* select_limit is used to decide if we are likely to scan the whole table */
select_limit= thd->select_limit;
if (having || (select_options & OPTION_FOUND_ROWS))
select_limit= HA_POS_ERROR;
if (setup_tables(tables) || if (setup_tables(tables) ||
setup_fields(thd,tables,fields,1,&all_fields,1) || setup_fields(thd,tables,fields,1,&all_fields,1) ||
...@@ -436,6 +442,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -436,6 +442,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
thd->proc_info="statistics"; thd->proc_info="statistics";
if (make_join_statistics(&join,tables,conds,&keyuse) || thd->fatal_error) if (make_join_statistics(&join,tables,conds,&keyuse) || thd->fatal_error)
goto err; goto err;
thd->proc_info="preparing"; thd->proc_info="preparing";
if (result->initialize_tables(&join)) if (result->initialize_tables(&join))
goto err; goto err;
...@@ -444,7 +451,8 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -444,7 +451,8 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
{ {
error=return_zero_rows(&join,result,tables,fields, error=return_zero_rows(&join,result,tables,fields,
join.tmp_table_param.sum_func_count != 0 && join.tmp_table_param.sum_func_count != 0 &&
!group,0,"",having,procedure); !group,0,"no matching row in const table",having,
procedure);
goto err; goto err;
} }
if (!(thd->options & OPTION_BIG_SELECTS) && if (!(thd->options & OPTION_BIG_SELECTS) &&
...@@ -504,21 +512,47 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -504,21 +512,47 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
if (! hidden_group_fields) if (! hidden_group_fields)
select_distinct=0; select_distinct=0;
} }
else if (select_distinct && join.tables - join.const_tables == 1 && else if (select_distinct && join.tables - join.const_tables == 1)
(thd->select_limit == HA_POS_ERROR ||
(join.select_options & OPTION_FOUND_ROWS) ||
order &&
!(skip_sort_order=
test_if_skip_sort_order(&join.join_tab[join.const_tables],
order, thd->select_limit,1))))
{
if ((group=create_distinct_group(order,fields)))
{ {
select_distinct=0; /*
We are only using one table. In this case we change DISTINCT to a
GROUP BY query if:
- The GROUP BY can be done through indexes (no sort) and the ORDER
BY only uses selected fields.
(In this case we can later optimize away GROUP BY and ORDER BY)
- We are scanning the whole table without LIMIT
This can happen if:
- We are using CALC_FOUND_ROWS
- We are using an ORDER BY that can't be optimized away.
We don't want to use this optimization when we are using LIMIT
because in this case we can just create a temporary table that
holds LIMIT rows and stop when this table is full.
*/
JOIN_TAB *tab= &join.join_tab[join.const_tables];
bool all_order_fields_used;
if (order)
skip_sort_order= test_if_skip_sort_order(tab, order, select_limit, 1);
if ((group=create_distinct_group(thd, order, fields,
&all_order_fields_used)))
{
bool skip_group= (skip_sort_order &&
test_if_skip_sort_order(tab, group, select_limit,
1) != 0);
if ((skip_group && all_order_fields_used) ||
select_limit == HA_POS_ERROR ||
(order && !skip_sort_order))
{
/* Change DISTINCT to GROUP BY */
select_distinct= 0;
no_order= !order; no_order= !order;
if (all_order_fields_used)
order=0;
join.group=1; // For end_write_group join.group=1; // For end_write_group
} }
else if (thd->fatal_error) // End of memory else
group= 0;
} else if (thd->fatal_error) // End of memory
goto err; goto err;
} }
group=remove_const(&join,group,conds,&simple_group); group=remove_const(&join,group,conds,&simple_group);
...@@ -622,10 +656,9 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -622,10 +656,9 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
order=group; order=group;
if (order && if (order &&
(join.const_tables == join.tables || (join.const_tables == join.tables ||
(simple_order && ((simple_order || skip_sort_order) &&
test_if_skip_sort_order(&join.join_tab[join.const_tables], order, test_if_skip_sort_order(&join.join_tab[join.const_tables], order,
(join.select_options & OPTION_FOUND_ROWS) ? select_limit, 0))))
HA_POS_ERROR : thd->select_limit,0))))
order=0; order=0;
select_describe(&join,need_tmp, select_describe(&join,need_tmp,
order != 0 && !skip_sort_order, order != 0 && !skip_sort_order,
...@@ -653,7 +686,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -653,7 +686,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
group ? 0 : select_distinct, group ? 0 : select_distinct,
group && simple_group, group && simple_group,
(order == 0 || skip_sort_order) && (order == 0 || skip_sort_order) &&
!(join.select_options & OPTION_FOUND_ROWS), select_limit != HA_POS_ERROR,
join.select_options))) join.select_options)))
goto err; /* purecov: inspected */ goto err; /* purecov: inspected */
...@@ -706,8 +739,9 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -706,8 +739,9 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
/* Optimize "select distinct b from t1 order by key_part_1 limit #" */ /* Optimize "select distinct b from t1 order by key_part_1 limit #" */
if (order && skip_sort_order) if (order && skip_sort_order)
{ {
(void) test_if_skip_sort_order(&join.join_tab[join.const_tables], /* Should always succeed */
order, thd->select_limit,0); if (test_if_skip_sort_order(&join.join_tab[join.const_tables],
order, thd->select_limit,0))
order=0; order=0;
} }
} }
...@@ -877,8 +911,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -877,8 +911,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
DBUG_EXECUTE("where",print_where(conds,"having after sort");); DBUG_EXECUTE("where",print_where(conds,"having after sort"););
} }
} }
select_limit= thd->select_limit; if (group)
if (having || group || (join.select_options & OPTION_FOUND_ROWS))
select_limit= HA_POS_ERROR; select_limit= HA_POS_ERROR;
else else
{ {
...@@ -953,13 +986,21 @@ static ha_rows get_quick_record_count(SQL_SELECT *select,TABLE *table, ...@@ -953,13 +986,21 @@ static ha_rows get_quick_record_count(SQL_SELECT *select,TABLE *table,
} }
/*
Calculate the best possible join and initialize the join structure
RETURN VALUES
0 ok
1 Fatal error
*/
static bool static bool
make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
DYNAMIC_ARRAY *keyuse_array) DYNAMIC_ARRAY *keyuse_array)
{ {
int error; int error;
uint i,table_count,const_count,found_ref,refs,key,const_ref,eq_part; uint i,table_count,const_count,found_ref,refs,key,const_ref,eq_part;
table_map const_table_map,found_const_table_map,all_table_map; table_map found_const_table_map,all_table_map;
TABLE **table_vector; TABLE **table_vector;
JOIN_TAB *stat,*stat_end,*s,**stat_ref; JOIN_TAB *stat,*stat_end,*s,**stat_ref;
SQL_SELECT *select; SQL_SELECT *select;
...@@ -979,7 +1020,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, ...@@ -979,7 +1020,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
join->best_ref=stat_vector; join->best_ref=stat_vector;
stat_end=stat+table_count; stat_end=stat+table_count;
const_table_map=found_const_table_map=all_table_map=0; found_const_table_map=all_table_map=0;
const_count=0; const_count=0;
for (s=stat,i=0 ; tables ; s++,tables=tables->next,i++) for (s=stat,i=0 ; tables ; s++,tables=tables->next,i++)
...@@ -1070,7 +1111,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, ...@@ -1070,7 +1111,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
DBUG_RETURN(1); DBUG_RETURN(1);
/* Read tables with 0 or 1 rows (system tables) */ /* Read tables with 0 or 1 rows (system tables) */
join->const_table_map=const_table_map; join->const_table_map= 0;
for (POSITION *p_pos=join->positions, *p_end=p_pos+const_count; for (POSITION *p_pos=join->positions, *p_end=p_pos+const_count;
p_pos < p_end ; p_pos < p_end ;
...@@ -1107,16 +1148,16 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, ...@@ -1107,16 +1148,16 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
if (s->dependent) // If dependent on some table if (s->dependent) // If dependent on some table
{ {
// All dep. must be constants // All dep. must be constants
if (s->dependent & ~(join->const_table_map)) if (s->dependent & ~(found_const_table_map))
continue; continue;
if (table->file->records <= 1L && if (table->file->records <= 1L &&
!(table->file->table_flags() & HA_NOT_EXACT_COUNT)) !(table->file->table_flags() & HA_NOT_EXACT_COUNT))
{ // system table { // system table
int tmp; int tmp= 0;
s->type=JT_SYSTEM; s->type=JT_SYSTEM;
join->const_table_map|=table->map; join->const_table_map|=table->map;
set_position(join,const_count++,s,(KEYUSE*) 0); set_position(join,const_count++,s,(KEYUSE*) 0);
if ((tmp=join_read_const_table(s,join->positions+const_count-1))) if ((tmp= join_read_const_table(s,join->positions+const_count-1)))
{ {
if (tmp > 0) if (tmp > 0)
DBUG_RETURN(1); // Fatal error DBUG_RETURN(1); // Fatal error
...@@ -1141,7 +1182,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, ...@@ -1141,7 +1182,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
{ {
if (keyuse->val->type() != Item::NULL_ITEM) if (keyuse->val->type() != Item::NULL_ITEM)
{ {
if (!((~join->const_table_map) & keyuse->used_tables)) if (!((~found_const_table_map) & keyuse->used_tables))
const_ref|= (key_map) 1 << keyuse->keypart; const_ref|= (key_map) 1 << keyuse->keypart;
else else
refs|=keyuse->used_tables; refs|=keyuse->used_tables;
...@@ -1162,7 +1203,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, ...@@ -1162,7 +1203,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
join->const_table_map|=table->map; join->const_table_map|=table->map;
set_position(join,const_count++,s,start_keyuse); set_position(join,const_count++,s,start_keyuse);
if (create_ref_for_key(join, s, start_keyuse, if (create_ref_for_key(join, s, start_keyuse,
join->const_table_map)) found_const_table_map))
DBUG_RETURN(1); DBUG_RETURN(1);
if ((tmp=join_read_const_table(s, if ((tmp=join_read_const_table(s,
join->positions+const_count-1))) join->positions+const_count-1)))
...@@ -1210,8 +1251,8 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, ...@@ -1210,8 +1251,8 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
{ {
ha_rows records; ha_rows records;
if (!select) if (!select)
select=make_select(s->table, join->const_table_map, select=make_select(s->table, found_const_table_map,
join->const_table_map, found_const_table_map,
and_conds(conds,s->on_expr),&error); and_conds(conds,s->on_expr),&error);
records=get_quick_record_count(select,s->table, s->const_keys, records=get_quick_record_count(select,s->table, s->const_keys,
join->row_limit); join->row_limit);
...@@ -2373,12 +2414,13 @@ get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables, ...@@ -2373,12 +2414,13 @@ get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables,
bool bool
store_val_in_field(Field *field,Item *item) store_val_in_field(Field *field,Item *item)
{ {
bool error;
THD *thd=current_thd; THD *thd=current_thd;
ha_rows cuted_fields=thd->cuted_fields; ha_rows cuted_fields=thd->cuted_fields;
thd->count_cuted_fields=1; thd->count_cuted_fields=1;
item->save_in_field(field); error= item->save_in_field(field, 1);
thd->count_cuted_fields=0; thd->count_cuted_fields=0;
return cuted_fields != thd->cuted_fields; return error || cuted_fields != thd->cuted_fields;
} }
...@@ -6577,12 +6619,14 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields, ...@@ -6577,12 +6619,14 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
*/ */
static ORDER * static ORDER *
create_distinct_group(ORDER *order_list,List<Item> &fields) create_distinct_group(THD *thd, ORDER *order_list, List<Item> &fields,
bool *all_order_by_fields_used)
{ {
List_iterator<Item> li(fields); List_iterator<Item> li(fields);
Item *item; Item *item;
ORDER *order,*group,**prev; ORDER *order,*group,**prev;
*all_order_by_fields_used= 1;
while ((item=li++)) while ((item=li++))
item->marker=0; /* Marker that field is not used */ item->marker=0; /* Marker that field is not used */
...@@ -6591,13 +6635,15 @@ create_distinct_group(ORDER *order_list,List<Item> &fields) ...@@ -6591,13 +6635,15 @@ create_distinct_group(ORDER *order_list,List<Item> &fields)
{ {
if (order->in_field_list) if (order->in_field_list)
{ {
ORDER *ord=(ORDER*) sql_memdup(order,sizeof(ORDER)); ORDER *ord=(ORDER*) thd->memdup((char*) order,sizeof(ORDER));
if (!ord) if (!ord)
return 0; return 0;
*prev=ord; *prev=ord;
prev= &ord->next; prev= &ord->next;
(*ord->item)->marker=1; (*ord->item)->marker=1;
} }
else
*all_order_by_fields_used= 0;
} }
li.rewind(); li.rewind();
...@@ -6607,7 +6653,7 @@ create_distinct_group(ORDER *order_list,List<Item> &fields) ...@@ -6607,7 +6653,7 @@ create_distinct_group(ORDER *order_list,List<Item> &fields)
continue; continue;
if (!item->marker) if (!item->marker)
{ {
ORDER *ord=(ORDER*) sql_calloc(sizeof(ORDER)); ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER));
if (!ord) if (!ord)
return 0; return 0;
ord->item=li.ref(); ord->item=li.ref();
...@@ -7059,7 +7105,7 @@ copy_sum_funcs(Item_sum **func_ptr) ...@@ -7059,7 +7105,7 @@ copy_sum_funcs(Item_sum **func_ptr)
{ {
Item_sum *func; Item_sum *func;
for (; (func = *func_ptr) ; func_ptr++) for (; (func = *func_ptr) ; func_ptr++)
(void) func->save_in_field(func->result_field); (void) func->save_in_field(func->result_field, 1);
return; return;
} }
...@@ -7090,7 +7136,7 @@ copy_funcs(Item_result_field **func_ptr) ...@@ -7090,7 +7136,7 @@ copy_funcs(Item_result_field **func_ptr)
{ {
Item_result_field *func; Item_result_field *func;
for (; (func = *func_ptr) ; func_ptr++) for (; (func = *func_ptr) ; func_ptr++)
(void) func->save_in_field(func->result_field); (void) func->save_in_field(func->result_field, 1);
return; return;
} }
......
...@@ -269,8 +269,7 @@ public: ...@@ -269,8 +269,7 @@ public:
{} {}
bool copy() bool copy()
{ {
item->save_in_field(to_field); return item->save_in_field(to_field, 1) || err != 0;
return err != 0;
} }
const char *name() const { return "func"; } const char *name() const { return "func"; }
}; };
...@@ -293,7 +292,8 @@ public: ...@@ -293,7 +292,8 @@ public:
if (!inited) if (!inited)
{ {
inited=1; inited=1;
item->save_in_field(to_field); if (item->save_in_field(to_field, 1))
err= 1;
} }
return err != 0; return err != 0;
} }
......
...@@ -574,7 +574,7 @@ static bool make_empty_rec(File file,enum db_type table_type, ...@@ -574,7 +574,7 @@ static bool make_empty_rec(File file,enum db_type table_type,
if (field->def && if (field->def &&
(regfield->real_type() != FIELD_TYPE_YEAR || (regfield->real_type() != FIELD_TYPE_YEAR ||
field->def->val_int() != 0)) field->def->val_int() != 0))
field->def->save_in_field(regfield); field->def->save_in_field(regfield, 1);
else if (regfield->real_type() == FIELD_TYPE_ENUM && else if (regfield->real_type() == FIELD_TYPE_ENUM &&
(field->flags & NOT_NULL_FLAG)) (field->flags & NOT_NULL_FLAG))
{ {
......
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