Commit e5ac58e6 authored by igor@igor-inspiron.creware.com's avatar igor@igor-inspiron.creware.com

Merge ibabaev@bk-internal.mysql.com:/home/bk/mysql-5.0

into igor-inspiron.creware.com:/home/igor/mysql-5.0
parents cdb1474d 38041160
...@@ -87,6 +87,7 @@ hf@deer.mysql.r18.ru ...@@ -87,6 +87,7 @@ hf@deer.mysql.r18.ru
hf@genie.(none) hf@genie.(none)
holyfoot@mysql.com holyfoot@mysql.com
igor@hundin.mysql.fi igor@hundin.mysql.fi
igor@igor-inspiron.creware.com
igor@linux.local igor@linux.local
igor@rurik.mysql.com igor@rurik.mysql.com
ingo@mysql.com ingo@mysql.com
......
...@@ -160,3 +160,20 @@ t1 CREATE TABLE `t1` ( ...@@ -160,3 +160,20 @@ t1 CREATE TABLE `t1` (
`COALESCE('a' COLLATE latin1_bin,'b')` varchar(1) character set latin1 collate latin1_bin NOT NULL default '' `COALESCE('a' COLLATE latin1_bin,'b')` varchar(1) character set latin1 collate latin1_bin NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (EMPNUM INT);
INSERT INTO t1 VALUES (0), (2);
CREATE TABLE t2 (EMPNUM DECIMAL (4, 2));
INSERT INTO t2 VALUES (0.0), (9.0);
SELECT COALESCE(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM,
t1.EMPNUM AS EMPMUM1, t2.EMPNUM AS EMPNUM2
FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM;
CEMPNUM EMPMUM1 EMPNUM2
0.00 0 0.00
2.00 2 NULL
SELECT IFNULL(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM,
t1.EMPNUM AS EMPMUM1, t2.EMPNUM AS EMPNUM2
FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM;
CEMPNUM EMPMUM1 EMPNUM2
0.00 0 0.00
2.00 2 NULL
DROP TABLE t1,t2;
...@@ -110,3 +110,22 @@ explain extended SELECT ...@@ -110,3 +110,22 @@ explain extended SELECT
COALESCE('a' COLLATE latin1_bin,'b'); COALESCE('a' COLLATE latin1_bin,'b');
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
DROP TABLE t1; DROP TABLE t1;
#
# Tests for bug #9939: conversion of the arguments for COALESCE and IFNULL
#
CREATE TABLE t1 (EMPNUM INT);
INSERT INTO t1 VALUES (0), (2);
CREATE TABLE t2 (EMPNUM DECIMAL (4, 2));
INSERT INTO t2 VALUES (0.0), (9.0);
SELECT COALESCE(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM,
t1.EMPNUM AS EMPMUM1, t2.EMPNUM AS EMPNUM2
FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM;
SELECT IFNULL(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM,
t1.EMPNUM AS EMPMUM1, t2.EMPNUM AS EMPNUM2
FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM;
DROP TABLE t1,t2;
...@@ -1116,8 +1116,8 @@ Item_func_ifnull::fix_length_and_dec() ...@@ -1116,8 +1116,8 @@ Item_func_ifnull::fix_length_and_dec()
max_length= (max(args[0]->max_length - args[0]->decimals, max_length= (max(args[0]->max_length - args[0]->decimals,
args[1]->max_length - args[1]->decimals) + args[1]->max_length - args[1]->decimals) +
decimals); decimals);
agg_result_type(&cached_result_type, args, 2); agg_result_type(&hybrid_type, args, 2);
switch (cached_result_type) { switch (hybrid_type) {
case STRING_RESULT: case STRING_RESULT:
agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV); agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV);
break; break;
...@@ -1155,7 +1155,7 @@ Field *Item_func_ifnull::tmp_table_field(TABLE *table) ...@@ -1155,7 +1155,7 @@ Field *Item_func_ifnull::tmp_table_field(TABLE *table)
} }
double double
Item_func_ifnull::val_real() Item_func_ifnull::real_op()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
double value= args[0]->val_real(); double value= args[0]->val_real();
...@@ -1171,7 +1171,7 @@ Item_func_ifnull::val_real() ...@@ -1171,7 +1171,7 @@ Item_func_ifnull::val_real()
} }
longlong longlong
Item_func_ifnull::val_int() Item_func_ifnull::int_op()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
longlong value=args[0]->val_int(); longlong value=args[0]->val_int();
...@@ -1187,7 +1187,7 @@ Item_func_ifnull::val_int() ...@@ -1187,7 +1187,7 @@ Item_func_ifnull::val_int()
} }
my_decimal *Item_func_ifnull::val_decimal(my_decimal *decimal_value) my_decimal *Item_func_ifnull::decimal_op(my_decimal *decimal_value)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
my_decimal *value= args[0]->val_decimal(decimal_value); my_decimal *value= args[0]->val_decimal(decimal_value);
...@@ -1204,7 +1204,7 @@ my_decimal *Item_func_ifnull::val_decimal(my_decimal *decimal_value) ...@@ -1204,7 +1204,7 @@ my_decimal *Item_func_ifnull::val_decimal(my_decimal *decimal_value)
String * String *
Item_func_ifnull::val_str(String *str) Item_func_ifnull::str_op(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
String *res =args[0]->val_str(str); String *res =args[0]->val_str(str);
...@@ -1685,7 +1685,7 @@ void Item_func_case::print(String *str) ...@@ -1685,7 +1685,7 @@ void Item_func_case::print(String *str)
Coalesce - return first not NULL argument. Coalesce - return first not NULL argument.
*/ */
String *Item_func_coalesce::val_str(String *str) String *Item_func_coalesce::str_op(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
null_value=0; null_value=0;
...@@ -1699,7 +1699,7 @@ String *Item_func_coalesce::val_str(String *str) ...@@ -1699,7 +1699,7 @@ String *Item_func_coalesce::val_str(String *str)
return 0; return 0;
} }
longlong Item_func_coalesce::val_int() longlong Item_func_coalesce::int_op()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
null_value=0; null_value=0;
...@@ -1713,7 +1713,7 @@ longlong Item_func_coalesce::val_int() ...@@ -1713,7 +1713,7 @@ longlong Item_func_coalesce::val_int()
return 0; return 0;
} }
double Item_func_coalesce::val_real() double Item_func_coalesce::real_op()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
null_value=0; null_value=0;
...@@ -1728,7 +1728,7 @@ double Item_func_coalesce::val_real() ...@@ -1728,7 +1728,7 @@ double Item_func_coalesce::val_real()
} }
my_decimal *Item_func_coalesce::val_decimal(my_decimal *decimal_value) my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
null_value= 0; null_value= 0;
...@@ -1745,8 +1745,8 @@ my_decimal *Item_func_coalesce::val_decimal(my_decimal *decimal_value) ...@@ -1745,8 +1745,8 @@ my_decimal *Item_func_coalesce::val_decimal(my_decimal *decimal_value)
void Item_func_coalesce::fix_length_and_dec() void Item_func_coalesce::fix_length_and_dec()
{ {
agg_result_type(&cached_result_type, args, arg_count); agg_result_type(&hybrid_type, args, arg_count);
switch (cached_result_type) { switch (hybrid_type) {
case STRING_RESULT: case STRING_RESULT:
count_only_length(); count_only_length();
decimals= NOT_FIXED_DEC; decimals= NOT_FIXED_DEC;
......
...@@ -453,23 +453,19 @@ public: ...@@ -453,23 +453,19 @@ public:
}; };
class Item_func_coalesce :public Item_func class Item_func_coalesce :public Item_func_numhybrid
{ {
protected: protected:
enum Item_result cached_result_type; Item_func_coalesce(Item *a, Item *b) :Item_func_numhybrid(a, b) {}
Item_func_coalesce(Item *a, Item *b)
:Item_func(a, b), cached_result_type(INT_RESULT)
{}
public: public:
Item_func_coalesce(List<Item> &list) Item_func_coalesce(List<Item> &list) :Item_func_numhybrid(list) {}
:Item_func(list),cached_result_type(INT_RESULT) double real_op();
{} longlong int_op();
double val_real(); String *str_op(String *);
longlong val_int(); my_decimal *decimal_op(my_decimal *);
String *val_str(String *);
my_decimal *val_decimal(my_decimal *);
void fix_length_and_dec(); void fix_length_and_dec();
enum Item_result result_type () const { return cached_result_type; } void find_num_type() {}
enum Item_result result_type () const { return hybrid_type; }
const char *func_name() const { return "coalesce"; } const char *func_name() const { return "coalesce"; }
table_map not_null_tables() const { return 0; } table_map not_null_tables() const { return 0; }
}; };
...@@ -482,10 +478,10 @@ protected: ...@@ -482,10 +478,10 @@ protected:
bool field_type_defined; bool field_type_defined;
public: public:
Item_func_ifnull(Item *a, Item *b) :Item_func_coalesce(a,b) {} Item_func_ifnull(Item *a, Item *b) :Item_func_coalesce(a,b) {}
double val_real(); double real_op();
longlong val_int(); longlong int_op();
String *val_str(String *str); String *str_op(String *str);
my_decimal *val_decimal(my_decimal *); my_decimal *decimal_op(my_decimal *);
enum_field_types field_type() const; enum_field_types field_type() const;
void fix_length_and_dec(); void fix_length_and_dec();
const char *func_name() const { return "ifnull"; } const char *func_name() const { return "ifnull"; }
......
...@@ -817,6 +817,8 @@ String *Item_func_numhybrid::val_str(String *str) ...@@ -817,6 +817,8 @@ String *Item_func_numhybrid::val_str(String *str)
str->set(nr,decimals,&my_charset_bin); str->set(nr,decimals,&my_charset_bin);
break; break;
} }
case STRING_RESULT:
return str_op(&str_value);
default: default:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
...@@ -841,6 +843,14 @@ double Item_func_numhybrid::val_real() ...@@ -841,6 +843,14 @@ double Item_func_numhybrid::val_real()
return (double)int_op(); return (double)int_op();
case REAL_RESULT: case REAL_RESULT:
return real_op(); return real_op();
case STRING_RESULT:
{
char *end_not_used;
int err_not_used;
String *res= str_op(&str_value);
return (res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(),
&end_not_used, &err_not_used) : 0.0);
}
default: default:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
...@@ -865,6 +875,15 @@ longlong Item_func_numhybrid::val_int() ...@@ -865,6 +875,15 @@ longlong Item_func_numhybrid::val_int()
return int_op(); return int_op();
case REAL_RESULT: case REAL_RESULT:
return (longlong)real_op(); return (longlong)real_op();
case STRING_RESULT:
{
char *end_not_used;
int err_not_used;
String *res= str_op(&str_value);
CHARSET_INFO *cs= str_value.charset();
return (res ? (*(cs->cset->strtoll10))(cs, res->ptr(), &end_not_used,
&err_not_used) : 0);
}
default: default:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
...@@ -893,6 +912,12 @@ my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value) ...@@ -893,6 +912,12 @@ my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value)
break; break;
} }
case STRING_RESULT: case STRING_RESULT:
{
String *res= str_op(&str_value);
str2my_decimal(E_DEC_FATAL_ERROR, (char*) res->ptr(),
res->length(), res->charset(), decimal_value);
break;
}
case ROW_RESULT: case ROW_RESULT:
default: default:
DBUG_ASSERT(0); DBUG_ASSERT(0);
......
...@@ -194,6 +194,9 @@ public: ...@@ -194,6 +194,9 @@ public:
Item_func_numhybrid(Item *a,Item *b) Item_func_numhybrid(Item *a,Item *b)
:Item_func(a,b),hybrid_type(REAL_RESULT) :Item_func(a,b),hybrid_type(REAL_RESULT)
{} {}
Item_func_numhybrid(List<Item> &list)
:Item_func(list),hybrid_type(REAL_RESULT)
{}
enum Item_result result_type () const { return hybrid_type; } enum Item_result result_type () const { return hybrid_type; }
void fix_length_and_dec(); void fix_length_and_dec();
...@@ -208,6 +211,7 @@ public: ...@@ -208,6 +211,7 @@ public:
virtual longlong int_op()= 0; virtual longlong int_op()= 0;
virtual double real_op()= 0; virtual double real_op()= 0;
virtual my_decimal *decimal_op(my_decimal *)= 0; virtual my_decimal *decimal_op(my_decimal *)= 0;
virtual String *str_op(String *)= 0;
bool is_null() { (void) val_real(); return null_value; } bool is_null() { (void) val_real(); return null_value; }
}; };
...@@ -220,6 +224,7 @@ public: ...@@ -220,6 +224,7 @@ public:
void fix_num_length_and_dec(); void fix_num_length_and_dec();
void find_num_type(); void find_num_type();
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
}; };
...@@ -231,6 +236,7 @@ class Item_num_op :public Item_func_numhybrid ...@@ -231,6 +236,7 @@ class Item_num_op :public Item_func_numhybrid
virtual void result_precision()= 0; virtual void result_precision()= 0;
void print(String *str) { print_op(str); } void print(String *str) { print_op(str); }
void find_num_type(); void find_num_type();
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
}; };
......
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