Commit e87583f5 authored by lenz@mysql.com's avatar lenz@mysql.com

Merge lgrimmer@work.mysql.com:/home/bk/mysql-4.0

into mysql.com:/space/my/mysql-4.0
parents 9c838763 e6347704
DROP TABLE IF EXISTS t1;
SELECT IF(NULL AND 1, 1, 2), IF(1 AND NULL, 1, 2);
IF(NULL AND 1, 1, 2) IF(1 AND NULL, 1, 2)
2 2
SELECT NULL AND 1, 1 AND NULL, 0 AND NULL, NULL and 0;
NULL AND 1 1 AND NULL 0 AND NULL NULL and 0
NULL NULL 0 0
create table t1 (a int);
insert into t1 values (0),(1),(NULL);
SELECT * FROM t1 WHERE IF(a AND 1, 0, 1);
a
0
NULL
SELECT * FROM t1 WHERE IF(1 AND a, 0, 1);
a
0
NULL
SELECT * FROM t1 where NOT(a AND 1);
a
0
SELECT * FROM t1 where NOT(1 AND a);
a
0
SELECT * FROM t1 where (a AND 1)=0;
a
0
SELECT * FROM t1 where (1 AND a)=0;
a
0
SELECT * FROM t1 where (1 AND a)=1;
a
1
SELECT * FROM t1 where (1 AND a) IS NULL;
a
NULL
SET @a=0, @b=0;
SELECT * FROM t1 WHERE NULL AND (@a:=@a+1);
a
SELECT * FROM t1 WHERE NOT(a>=0 AND NULL AND (@b:=@b+1));
a
SELECT * FROM t1 WHERE a=2 OR (NULL AND (@a:=@a+1));
a
SELECT * FROM t1 WHERE NOT(a=2 OR (NULL AND (@b:=@b+1)));
a
SELECT @a, @b;
@a @b
0 6
DROP TABLE t1;
......@@ -84,6 +84,12 @@ select yearweek("2000-01-01",1) as '2000', yearweek("2001-01-01",1) as '2001', y
select yearweek("2000-01-06",1) as '2000', yearweek("2001-01-06",1) as '2001', yearweek("2002-01-06",1) as '2002',yearweek("2003-01-06",1) as '2003', yearweek("2004-01-06",1) as '2004', yearweek("2005-01-06",1) as '2005', yearweek("2006-01-06",1) as '2006';
2000 2001 2002 2003 2004 2005 2006
200001 200101 200201 200302 200402 200501 200601
select week(19981231,2), week(19981231,3), week(20000101,2), week(20000101,3);
week(19981231,2) week(19981231,3) week(20000101,2) week(20000101,3)
52 53 52 52
select week(20001231,2),week(20001231,3);
week(20001231,2) week(20001231,3)
1 52
select date_format('1998-12-31','%x-%v'),date_format('1999-01-01','%x-%v');
date_format('1998-12-31','%x-%v') date_format('1999-01-01','%x-%v')
1998-53 1998-53
......
......@@ -30,7 +30,7 @@ SELECT (NULL OR NULL) IS NULL;
1
select NULL AND 0, 0 and NULL;
NULL AND 0 0 and NULL
NULL 0
0 0
select inet_ntoa(null),inet_aton(null),inet_aton("122.256"),inet_aton("122.226."),inet_aton("");
inet_ntoa(null) inet_aton(null) inet_aton("122.256") inet_aton("122.226.") inet_aton("")
NULL NULL NULL NULL NULL
......
#
# Test of boolean operations with NULL
#
DROP TABLE IF EXISTS t1;
SELECT IF(NULL AND 1, 1, 2), IF(1 AND NULL, 1, 2);
SELECT NULL AND 1, 1 AND NULL, 0 AND NULL, NULL and 0;
create table t1 (a int);
insert into t1 values (0),(1),(NULL);
SELECT * FROM t1 WHERE IF(a AND 1, 0, 1);
SELECT * FROM t1 WHERE IF(1 AND a, 0, 1);
SELECT * FROM t1 where NOT(a AND 1);
SELECT * FROM t1 where NOT(1 AND a);
SELECT * FROM t1 where (a AND 1)=0;
SELECT * FROM t1 where (1 AND a)=0;
SELECT * FROM t1 where (1 AND a)=1;
SELECT * FROM t1 where (1 AND a) IS NULL;
# Verify that NULL optimisation works in AND clause:
SET @a=0, @b=0;
SELECT * FROM t1 WHERE NULL AND (@a:=@a+1);
SELECT * FROM t1 WHERE NOT(a>=0 AND NULL AND (@b:=@b+1));
SELECT * FROM t1 WHERE a=2 OR (NULL AND (@a:=@a+1));
SELECT * FROM t1 WHERE NOT(a=2 OR (NULL AND (@b:=@b+1)));
SELECT @a, @b;
DROP TABLE t1;
......@@ -34,6 +34,9 @@ select yearweek("2000-01-01",0) as '2000', yearweek("2001-01-01",0) as '2001', y
select yearweek("2000-01-06",0) as '2000', yearweek("2001-01-06",0) as '2001', yearweek("2002-01-06",0) as '2002',yearweek("2003-01-06",0) as '2003', yearweek("2004-01-06",0) as '2004', yearweek("2005-01-06",0) as '2005', yearweek("2006-01-06",0) as '2006';
select yearweek("2000-01-01",1) as '2000', yearweek("2001-01-01",1) as '2001', yearweek("2002-01-01",1) as '2002',yearweek("2003-01-01",1) as '2003', yearweek("2004-01-01",1) as '2004', yearweek("2005-01-01",1) as '2005', yearweek("2006-01-01",1) as '2006';
select yearweek("2000-01-06",1) as '2000', yearweek("2001-01-06",1) as '2001', yearweek("2002-01-06",1) as '2002',yearweek("2003-01-06",1) as '2003', yearweek("2004-01-06",1) as '2004', yearweek("2005-01-06",1) as '2005', yearweek("2006-01-06",1) as '2006';
select week(19981231,2), week(19981231,3), week(20000101,2), week(20000101,3);
select week(20001231,2),week(20001231,3);
select date_format('1998-12-31','%x-%v'),date_format('1999-01-01','%x-%v');
select date_format('1999-12-31','%x-%v'),date_format('2000-01-01','%x-%v');
......
......@@ -4,7 +4,7 @@ use Getopt::Long;
use POSIX qw(strftime);
$|=1;
$VER="2.4";
$VER="2.5";
$opt_config_file = undef();
$opt_example = 0;
......@@ -212,6 +212,7 @@ sub start_mysqlds()
}
else
{
$options[$j]=~ s/;/\\;/g;
$tmp.= " $options[$j]";
}
}
......
......@@ -204,7 +204,7 @@ else
fi
USER_OPTION=""
if test "x$USER" = "xroot"
if test -w / -o "$USER" = "root"
then
if test "$user" != "root" -o $SET_USER = 1
then
......
......@@ -85,6 +85,7 @@ class Item {
virtual bool get_time(TIME *ltime);
virtual bool is_null() { return 0; }
virtual unsigned int size_of()= 0;
virtual void top_level_item() {}
};
......
......@@ -26,8 +26,8 @@
/*
Test functions
These returns 0LL if false and 1LL if true and null if some arg is null
'AND' and 'OR' never return null
Most of these returns 0LL if false and 1LL if true and
NULL if some arg is NULL.
*/
longlong Item_func_not::val_int()
......@@ -1121,6 +1121,8 @@ Item_cond::fix_fields(THD *thd,TABLE_LIST *tables)
#endif
item= *li.ref(); // new current item
}
if (abort_on_null)
item->top_level_item();
if (item->fix_fields(thd,tables))
return 1; /* purecov: inspected */
used_tables_cache|=item->used_tables();
......@@ -1196,28 +1198,41 @@ void Item_cond::print(String *str)
str->append(')');
}
/*
Evalution of AND(expr, expr, expr ...)
NOTES:
abort_if_null is set for AND expressions for which we don't care if the
result is NULL or 0. This is set for:
- WHERE clause
- HAVING clause
- IF(expression)
RETURN VALUES
1 If all expressions are true
0 If all expressions are false or if we find a NULL expression and
'abort_on_null' is set.
NULL if all expression are either 1 or NULL
*/
longlong Item_cond_and::val_int()
{
List_iterator_fast<Item> li(list);
Item *item;
null_value= 0;
while ((item=li++))
{
if (item->val_int() == 0)
{
/*
TODO: In case of NULL, ANSI would require us to continue evaluation
until we get a FALSE value or run out of values; This would
require a lot of unnecessary evaluation, which we skip for now
*/
null_value=item->null_value;
return 0;
if (abort_on_null || !(null_value= item->null_value))
return 0; // return FALSE
}
}
null_value=0;
return 1;
return null_value ? 0 : 1;
}
longlong Item_cond_or::val_int()
{
List_iterator_fast<Item> li(list);
......@@ -1260,15 +1275,15 @@ longlong Item_cond_or::val_int()
Item *and_expressions(Item *a, Item *b, Item **org_item)
{
if (!a)
return (*org_item= (Item*) b);
return (*org_item= b);
if (a == *org_item)
{
Item_cond *res;
if ((res= new Item_cond_and(a, (Item*) b)))
if ((res= new Item_cond_and(a, b)))
res->used_tables_cache= a->used_tables() | b->used_tables();
return res;
}
if (((Item_cond_and*) a)->add((Item*) b))
if (((Item_cond_and*) a)->add(b))
return 0;
((Item_cond_and*) a)->used_tables_cache|= b->used_tables();
return a;
......
......@@ -216,6 +216,11 @@ class Item_func_if :public Item_func
longlong val_int();
String *val_str(String *str);
enum Item_result result_type () const { return cached_result_type; }
bool fix_fields(THD *thd,struct st_table_list *tlist)
{
args[0]->top_level_item();
return Item_func::fix_fields(thd,tlist);
}
void fix_length_and_dec();
const char *func_name() const { return "if"; }
unsigned int size_of() { return sizeof(*this);}
......@@ -560,10 +565,12 @@ class Item_cond :public Item_bool_func
{
protected:
List<Item> list;
bool abort_on_null;
public:
Item_cond() : Item_bool_func() { const_item_cache=0; }
Item_cond(Item *i1,Item *i2) :Item_bool_func()
{ list.push_back(i1); list.push_back(i2); }
/* Item_cond() is only used to create top level items */
Item_cond() : Item_bool_func(), abort_on_null(1) { const_item_cache=0; }
Item_cond(Item *i1,Item *i2) :Item_bool_func(), abort_on_null(0)
{ list.push_back(i1); list.push_back(i2); }
~Item_cond() { list.delete_elements(); }
bool add(Item *item) { return list.push_back(item); }
bool fix_fields(THD *,struct st_table_list *);
......@@ -576,6 +583,7 @@ class Item_cond :public Item_bool_func
void split_sum_func(List<Item> &fields);
friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
unsigned int size_of() { return sizeof(*this);}
void top_level_item() { abort_on_null=1; }
};
......
......@@ -175,15 +175,28 @@ longlong Item_func_second::val_int()
}
// Returns the week of year in the range of 0 - 53
/*
Returns the week of year.
The bits in week_format has the following meaning:
0 If not set: USA format: Sunday is first day of week
If set: ISO format: Monday is first day of week
1 If not set: Week is in range 0-53
If set Week is in range 1-53.
*/
longlong Item_func_week::val_int()
{
uint year;
uint week_format;
TIME ltime;
if (get_arg0_date(&ltime,0))
return 0;
return (longlong) calc_week(&ltime, 0, args[1]->val_int() == 0, &year);
week_format= args[1]->val_int();
return (longlong) calc_week(&ltime,
(week_format & 2) != 0,
(week_format & 1) == 0,
&year);
}
......@@ -193,7 +206,7 @@ longlong Item_func_yearweek::val_int()
TIME ltime;
if (get_arg0_date(&ltime,0))
return 0;
week=calc_week(&ltime, 1, args[1]->val_int() == 0, &year);
week=calc_week(&ltime, 1, (args[1]->val_int() & 1) == 0, &year);
return week+year*100;
}
......
......@@ -2003,6 +2003,8 @@ int main(int argc, char **argv)
if (ha_init())
{
sql_print_error("Can't init databases");
if (unix_sock != INVALID_SOCKET)
unlink(mysql_unix_port);
exit(1);
}
ha_key_cache();
......@@ -2038,6 +2040,8 @@ int main(int argc, char **argv)
pthread_key_create(&THR_MALLOC,NULL))
{
sql_print_error("Can't create thread-keys");
if (unix_sock != INVALID_SOCKET)
unlink(mysql_unix_port);
exit(1);
}
start_signal_handler(); // Creates pidfile
......@@ -2050,6 +2054,8 @@ int main(int argc, char **argv)
if (!opt_bootstrap)
(void) my_delete(pidfile_name,MYF(MY_WME)); // Not needed anymore
#endif
if (unix_sock != INVALID_SOCKET)
unlink(mysql_unix_port);
exit(1);
}
if (!opt_noacl)
......@@ -4467,8 +4473,8 @@ fn_format_relative_to_data_home(my_string to, const char *name,
static void fix_paths(void)
{
char buff[FN_REFLEN];
(void) fn_format(mysql_home,mysql_home,"","",16); // Remove symlinks
convert_dirname(mysql_home,mysql_home,NullS);
my_realpath(mysql_home,mysql_home,MYF(0));
convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
convert_dirname(language,language,NullS);
(void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir
......
......@@ -376,14 +376,14 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
if (!found)
if_wait_for_refresh=0; // Nothing to wait for
}
if (!tables)
kill_delayed_threads();
if (if_wait_for_refresh)
{
/*
If there is any table that has a lower refresh_version, wait until
this is closed (or this thread is killed) before returning
*/
if (!tables)
kill_delayed_threads();
thd->mysys_var->current_mutex= &LOCK_open;
thd->mysys_var->current_cond= &COND_refresh;
thd->proc_info="Flushing tables";
......@@ -1976,6 +1976,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
Item_cond_and *cond_and=new Item_cond_and();
if (!cond_and) // If not out of memory
DBUG_RETURN(1);
cond_and->top_level_item();
uint i,j;
for (i=0 ; i < t1->fields ; i++)
......
......@@ -3324,12 +3324,16 @@ static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result)
void add_join_on(TABLE_LIST *b,Item *expr)
{
if (!b->on_expr)
b->on_expr=expr;
else
if (expr)
{
// This only happens if you have both a right and left join
b->on_expr=new Item_cond_and(b->on_expr,expr);
if (!b->on_expr)
b->on_expr=expr;
else
{
// This only happens if you have both a right and left join
b->on_expr=new Item_cond_and(b->on_expr,expr);
}
b->on_expr->top_level_item();
}
}
......
......@@ -359,6 +359,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
{
conds->fix_fields(thd,tables);
conds->change_ref_to_fields(thd,tables);
conds->top_level_item();
having=0;
}
}
......@@ -868,6 +869,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
sort_table_cond)))
goto err;
table->select_cond=table->select->cond;
table->select_cond->top_level_item();
DBUG_EXECUTE("where",print_where(table->select->cond,
"select and having"););
having=make_cond_for_table(having,~ (table_map) 0,~used_tables);
......@@ -5384,6 +5386,7 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table)
{
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
{
/* Create new top level AND item */
Item_cond_and *new_cond=new Item_cond_and;
if (!new_cond)
return (COND*) 0; // OOM /* purecov: inspected */
......@@ -5421,7 +5424,8 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table)
new_cond->argument_list()->push_back(fix);
}
new_cond->used_tables_cache=((Item_cond_or*) cond)->used_tables_cache;
return new_cond;
new_cond->top_level_item();
DBUG_RETURN(new_cond);
}
}
......@@ -5772,6 +5776,7 @@ static bool fix_having(JOIN *join, Item **having)
sort_table_cond)))
return 1;
table->select_cond=table->select->cond;
table->select_cond->top_level_item();
DBUG_EXECUTE("where",print_where(table->select_cond,
"select and having"););
*having=make_cond_for_table(*having,~ (table_map) 0,~used_tables);
......
......@@ -2178,15 +2178,25 @@ opt_table_alias:
where_clause:
/* empty */ { Select->where= 0; }
| WHERE expr { Select->where= $2; };
| WHERE expr
{
Select->where= $2;
if ($2)
$2->top_level_item();
}
;
having_clause:
/* empty */
| HAVING { Select->create_refs=1; } expr
{
SELECT_LEX *sel=Select;
sel->having= $3; sel->create_refs=0;
};
sel->having= $3;
sel->create_refs=0;
if ($3)
$3->top_level_item();
}
;
opt_escape:
ESCAPE_SYM TEXT_STRING { $$= $2.str; }
......
......@@ -24,7 +24,7 @@ EXTRA_DIST = auto_increment.res auto_increment.tst \
insert_and_repair.pl \
grant.pl grant.res test_delayed_insert.pl \
pmail.pl mail_to_db.pl table_types.pl \
udf_test udf_test.res
udf_test udf_test.res myisam-big-rows.tst
# Don't update the files from bitkeeper
%::SCCS/s.%
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