Commit 7310d0d2 authored by unknown's avatar unknown

Merge tulin@bk-internal.mysql.com:/home/bk/mysql-4.1

into poseidon.ndb.mysql.com:/home/tomas/mysql-4.1

parents 8a1488cd aa69af38
...@@ -174,3 +174,12 @@ SELECT GREATEST(d,d) FROM t1 WHERE k=2; ...@@ -174,3 +174,12 @@ SELECT GREATEST(d,d) FROM t1 WHERE k=2;
GREATEST(d,d) GREATEST(d,d)
NULL NULL
DROP TABLE t1; DROP TABLE t1;
select 1197.90 mod 50;
1197.90 mod 50
47.90
select 5.1 mod 3, 5.1 mod -3, -5.1 mod 3, -5.1 mod -3;
5.1 mod 3 5.1 mod -3 -5.1 mod 3 -5.1 mod -3
2.1 2.1 -2.1 -2.1
select 5 mod 3, 5 mod -3, -5 mod 3, -5 mod -3;
5 mod 3 5 mod -3 -5 mod 3 -5 mod -3
2 2 -2 -2
use test; drop table if exists t1;
drop table if exists personnel; create table t1 (
Warnings:
Note 1051 Unknown table 'personnel'
create table personnel (
id INTEGER AUTO_INCREMENT PRIMARY KEY, id INTEGER AUTO_INCREMENT PRIMARY KEY,
emp CHAR(10) NOT NULL, emp CHAR(10) NOT NULL,
salary DECIMAL(6,2) NOT NULL, salary DECIMAL(6,2) NOT NULL,
l INTEGER NOT NULL, l INTEGER NOT NULL,
r INTEGER NOT NULL); r INTEGER NOT NULL);
prepare st_ins from 'insert into personnel set emp = ?, salary = ?, l = ?, r = ?'; prepare st_ins from 'insert into t1 set emp = ?, salary = ?, l = ?, r = ?';
set @arg_nam= 'Jerry'; set @arg_nam= 'Jerry';
set @arg_sal= 1000; set @arg_sal= 1000;
set @arg_l= 1; set @arg_l= 1;
...@@ -39,7 +36,7 @@ set @arg_sal= 600; ...@@ -39,7 +36,7 @@ set @arg_sal= 600;
set @arg_l= 9; set @arg_l= 9;
set @arg_r= 10; set @arg_r= 10;
execute st_ins using @arg_nam, @arg_sal, @arg_l, @arg_r ; execute st_ins using @arg_nam, @arg_sal, @arg_l, @arg_r ;
select * from personnel; select * from t1;
id emp salary l r id emp salary l r
1 Jerry 1000.00 1 12 1 Jerry 1000.00 1 12
2 Bert 900.00 2 3 2 Bert 900.00 2 3
...@@ -47,8 +44,8 @@ id emp salary l r ...@@ -47,8 +44,8 @@ id emp salary l r
4 Donna 800.00 5 6 4 Donna 800.00 5 6
5 Eddie 700.00 7 8 5 Eddie 700.00 7 8
6 Fred 600.00 9 10 6 Fred 600.00 9 10
prepare st_raise_base from 'update personnel set salary = salary * ( 1 + ? ) where r - l = 1'; prepare st_raise_base from 'update t1 set salary = salary * ( 1 + ? ) where r - l = 1';
prepare st_raise_mgr from 'update personnel set salary = salary + ? where r - l > 1'; prepare st_raise_mgr from 'update t1 set salary = salary + ? where r - l > 1';
set @arg_percent= .10; set @arg_percent= .10;
set @arg_amount= 100; set @arg_amount= 100;
execute st_raise_base using @arg_percent; execute st_raise_base using @arg_percent;
...@@ -57,7 +54,7 @@ execute st_raise_base using @arg_percent; ...@@ -57,7 +54,7 @@ execute st_raise_base using @arg_percent;
execute st_raise_mgr using @arg_amount; execute st_raise_mgr using @arg_amount;
execute st_raise_base using @arg_percent; execute st_raise_base using @arg_percent;
execute st_raise_mgr using @arg_amount; execute st_raise_mgr using @arg_amount;
select * from personnel; select * from t1;
id emp salary l r id emp salary l r
1 Jerry 1300.00 1 12 1 Jerry 1300.00 1 12
2 Bert 1197.90 2 3 2 Bert 1197.90 2 3
...@@ -65,4 +62,4 @@ id emp salary l r ...@@ -65,4 +62,4 @@ id emp salary l r
4 Donna 1064.80 5 6 4 Donna 1064.80 5 6
5 Eddie 931.70 7 8 5 Eddie 931.70 7 8
6 Fred 798.60 9 10 6 Fred 798.60 9 10
drop table personnel; drop table t1;
...@@ -94,3 +94,16 @@ CREATE TABLE t1 (d varchar(6), k int); ...@@ -94,3 +94,16 @@ CREATE TABLE t1 (d varchar(6), k int);
INSERT INTO t1 VALUES (NULL, 2); INSERT INTO t1 VALUES (NULL, 2);
SELECT GREATEST(d,d) FROM t1 WHERE k=2; SELECT GREATEST(d,d) FROM t1 WHERE k=2;
DROP TABLE t1; DROP TABLE t1;
#
# Bug #6138: mod and doubles
#
select 1197.90 mod 50;
select 5.1 mod 3, 5.1 mod -3, -5.1 mod 3, -5.1 mod -3;
#
# Test for mod and signed integers
#
select 5 mod 3, 5 mod -3, -5 mod 3, -5 mod -3;
...@@ -8,28 +8,29 @@ ...@@ -8,28 +8,29 @@
# Source: http://kris.koehntopp.de/artikel/sql-self-references (dated 1999) # Source: http://kris.koehntopp.de/artikel/sql-self-references (dated 1999)
# Source: http://dbmsmag.com/9603d06.html (dated 1996) # Source: http://dbmsmag.com/9603d06.html (dated 1996)
use test; --disable_warnings
drop table if exists t1;
drop table if exists personnel; --enable_warnings
# "Nested Set": This table represents an employee list with a hierarchy tree. # "Nested Set": This table represents an employee list with a hierarchy tree.
# The tree is not modeled by "parent" links but rather by showing the "left" # The tree is not modeled by "parent" links but rather by showing the "left"
# and "right" border of any person's "region". By convention, "l" < "r". # and "right" border of any person's "region". By convention, "l" < "r".
# As it is a tree, these "regions" of two persons A and B are either disjoint, # As it is a tree, these "regions" of two persons A and B are either disjoint,
# or A's region is completely contained in B's (B is A's boss), or vice versa. # or A's region is completely contained in B's (B.l < A.l < A.r < B.r:
# See the references for more info. # B is A's boss), or vice versa.
# Any other overlaps violate the model. See the references for more info.
create table personnel ( create table t1 (
id INTEGER AUTO_INCREMENT PRIMARY KEY, id INTEGER AUTO_INCREMENT PRIMARY KEY,
emp CHAR(10) NOT NULL, emp CHAR(10) NOT NULL,
salary DECIMAL(6,2) NOT NULL, salary DECIMAL(6,2) NOT NULL,
l INTEGER NOT NULL, l INTEGER NOT NULL,
r INTEGER NOT NULL); r INTEGER NOT NULL);
prepare st_ins from 'insert into personnel set emp = ?, salary = ?, l = ?, r = ?'; prepare st_ins from 'insert into t1 set emp = ?, salary = ?, l = ?, r = ?';
# Initial employee list: # Initial employee list:
# Jerry ( Bert ( ) Chuck ( Donna ( ) Eddie ( ) Fred ( ) ) ) # Jerry ( Bert () Chuck ( Donna () Eddie () Fred () ) )
set @arg_nam= 'Jerry'; set @arg_sal= 1000; set @arg_l= 1; set @arg_r= 12; set @arg_nam= 'Jerry'; set @arg_sal= 1000; set @arg_l= 1; set @arg_r= 12;
execute st_ins using @arg_nam, @arg_sal, @arg_l, @arg_r ; execute st_ins using @arg_nam, @arg_sal, @arg_l, @arg_r ;
set @arg_nam= 'Bert'; set @arg_sal= 900; set @arg_l= 2; set @arg_r= 3; set @arg_nam= 'Bert'; set @arg_sal= 900; set @arg_l= 2; set @arg_r= 3;
...@@ -43,11 +44,11 @@ execute st_ins using @arg_nam, @arg_sal, @arg_l, @arg_r ; ...@@ -43,11 +44,11 @@ execute st_ins using @arg_nam, @arg_sal, @arg_l, @arg_r ;
set @arg_nam= 'Fred'; set @arg_sal= 600; set @arg_l= 9; set @arg_r= 10; set @arg_nam= 'Fred'; set @arg_sal= 600; set @arg_l= 9; set @arg_r= 10;
execute st_ins using @arg_nam, @arg_sal, @arg_l, @arg_r ; execute st_ins using @arg_nam, @arg_sal, @arg_l, @arg_r ;
select * from personnel; select * from t1;
# Three successive raises, each one is 100 units for managers, 10 percent for others. # Three successive raises, each one is 100 units for managers, 10 percent for others.
prepare st_raise_base from 'update personnel set salary = salary * ( 1 + ? ) where r - l = 1'; prepare st_raise_base from 'update t1 set salary = salary * ( 1 + ? ) where r - l = 1';
prepare st_raise_mgr from 'update personnel set salary = salary + ? where r - l > 1'; prepare st_raise_mgr from 'update t1 set salary = salary + ? where r - l > 1';
let $1= 3; let $1= 3;
set @arg_percent= .10; set @arg_percent= .10;
set @arg_amount= 100; set @arg_amount= 100;
...@@ -58,6 +59,14 @@ while ($1) ...@@ -58,6 +59,14 @@ while ($1)
dec $1; dec $1;
} }
select * from personnel; select * from t1;
# Waiting for the resolution of bug#6138
# # Now, increase salary to a multiple of 50
# prepare st_round from 'update t1 set salary = salary + ? - ( salary MOD ? )';
# set @arg_round= 50;
# execute st_round using @arg_round, @arg_round;
#
# select * from t1;
drop table personnel; drop table t1;
...@@ -97,7 +97,7 @@ drop table t1; ...@@ -97,7 +97,7 @@ drop table t1;
# end of bug#1644 # end of bug#1644
# bug#1677: Prepared statement two-table join returns no rows when one is expected # bug#1676: Prepared statement two-table join returns no rows when one is expected
create table t1( create table t1(
cola varchar(50) not null, cola varchar(50) not null,
......
...@@ -651,11 +651,11 @@ void Item_func_int_div::fix_length_and_dec() ...@@ -651,11 +651,11 @@ void Item_func_int_div::fix_length_and_dec()
double Item_func_mod::val() double Item_func_mod::val()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
double value= floor(args[0]->val()+0.5); double x= args[0]->val();
double val2=floor(args[1]->val()+0.5); double y= args[1]->val();
if ((null_value=val2 == 0.0 || args[0]->null_value || args[1]->null_value)) if ((null_value= (y == 0.0) || args[0]->null_value || args[1]->null_value))
return 0.0; /* purecov: inspected */ return 0.0; /* purecov: inspected */
return fmod(value,val2); return fmod(x, y);
} }
longlong Item_func_mod::val_int() longlong Item_func_mod::val_int()
...@@ -670,10 +670,7 @@ longlong Item_func_mod::val_int() ...@@ -670,10 +670,7 @@ longlong Item_func_mod::val_int()
void Item_func_mod::fix_length_and_dec() void Item_func_mod::fix_length_and_dec()
{ {
max_length=args[1]->max_length; Item_num_op::fix_length_and_dec();
decimals=0;
maybe_null=1;
find_num_type();
} }
......
...@@ -1112,6 +1112,13 @@ class select_result :public Sql_alloc { ...@@ -1112,6 +1112,13 @@ class select_result :public Sql_alloc {
unit= u; unit= u;
return 0; return 0;
} }
/*
Because of peculiarities of prepared statements protocol
we need to know number of columns in the result set (if
there is a result set) apart from sending columns metadata.
*/
virtual uint field_count(List<Item> &fields) const
{ return fields.elements; }
virtual bool send_fields(List<Item> &list,uint flag)=0; virtual bool send_fields(List<Item> &list,uint flag)=0;
virtual bool send_data(List<Item> &items)=0; virtual bool send_data(List<Item> &items)=0;
virtual bool initialize_tables (JOIN *join=0) { return 0; } virtual bool initialize_tables (JOIN *join=0) { return 0; }
...@@ -1126,6 +1133,20 @@ class select_result :public Sql_alloc { ...@@ -1126,6 +1133,20 @@ class select_result :public Sql_alloc {
}; };
/*
Base class for select_result descendands which intercept and
transform result set rows. As the rows are not sent to the client,
sending of result set metadata should be suppressed as well.
*/
class select_result_interceptor: public select_result
{
public:
uint field_count(List<Item> &fields) const { return 0; }
bool send_fields(List<Item> &fields, uint flag) { return FALSE; }
};
class select_send :public select_result { class select_send :public select_result {
public: public:
select_send() {} select_send() {}
...@@ -1135,7 +1156,7 @@ class select_send :public select_result { ...@@ -1135,7 +1156,7 @@ class select_send :public select_result {
}; };
class select_to_file :public select_result { class select_to_file :public select_result_interceptor {
protected: protected:
sql_exchange *exchange; sql_exchange *exchange;
File file; File file;
...@@ -1147,7 +1168,6 @@ class select_to_file :public select_result { ...@@ -1147,7 +1168,6 @@ class select_to_file :public select_result {
select_to_file(sql_exchange *ex) :exchange(ex), file(-1),row_count(0L) select_to_file(sql_exchange *ex) :exchange(ex), file(-1),row_count(0L)
{ path[0]=0; } { path[0]=0; }
~select_to_file(); ~select_to_file();
bool send_fields(List<Item> &list, uint flag) { return 0; }
void send_error(uint errcode,const char *err); void send_error(uint errcode,const char *err);
bool send_eof(); bool send_eof();
void cleanup(); void cleanup();
...@@ -1174,7 +1194,7 @@ class select_dump :public select_to_file { ...@@ -1174,7 +1194,7 @@ class select_dump :public select_to_file {
}; };
class select_insert :public select_result { class select_insert :public select_result_interceptor {
public: public:
TABLE *table; TABLE *table;
List<Item> *fields; List<Item> *fields;
...@@ -1190,8 +1210,6 @@ class select_insert :public select_result { ...@@ -1190,8 +1210,6 @@ class select_insert :public select_result {
} }
~select_insert(); ~select_insert();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u); int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list, uint flag)
{ return 0; }
bool send_data(List<Item> &items); bool send_data(List<Item> &items);
void send_error(uint errcode,const char *err); void send_error(uint errcode,const char *err);
bool send_eof(); bool send_eof();
...@@ -1274,7 +1292,7 @@ class TMP_TABLE_PARAM :public Sql_alloc ...@@ -1274,7 +1292,7 @@ class TMP_TABLE_PARAM :public Sql_alloc
} }
}; };
class select_union :public select_result { class select_union :public select_result_interceptor {
public: public:
TABLE *table; TABLE *table;
COPY_INFO info; COPY_INFO info;
...@@ -1283,8 +1301,6 @@ class select_union :public select_result { ...@@ -1283,8 +1301,6 @@ class select_union :public select_result {
select_union(TABLE *table_par); select_union(TABLE *table_par);
~select_union(); ~select_union();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u); int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list, uint flag)
{ return 0; }
bool send_data(List<Item> &items); bool send_data(List<Item> &items);
bool send_eof(); bool send_eof();
bool flush(); bool flush();
...@@ -1292,13 +1308,12 @@ class select_union :public select_result { ...@@ -1292,13 +1308,12 @@ class select_union :public select_result {
}; };
/* Base subselect interface class */ /* Base subselect interface class */
class select_subselect :public select_result class select_subselect :public select_result_interceptor
{ {
protected: protected:
Item_subselect *item; Item_subselect *item;
public: public:
select_subselect(Item_subselect *item); select_subselect(Item_subselect *item);
bool send_fields(List<Item> &list, uint flag) { return 0; };
bool send_data(List<Item> &items)=0; bool send_data(List<Item> &items)=0;
bool send_eof() { return 0; }; bool send_eof() { return 0; };
}; };
...@@ -1435,7 +1450,7 @@ class Unique :public Sql_alloc ...@@ -1435,7 +1450,7 @@ class Unique :public Sql_alloc
}; };
class multi_delete :public select_result class multi_delete :public select_result_interceptor
{ {
TABLE_LIST *delete_tables, *table_being_deleted; TABLE_LIST *delete_tables, *table_being_deleted;
Unique **tempfiles; Unique **tempfiles;
...@@ -1448,8 +1463,6 @@ class multi_delete :public select_result ...@@ -1448,8 +1463,6 @@ class multi_delete :public select_result
multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables); multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables);
~multi_delete(); ~multi_delete();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u); int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list,
uint flag) { return 0; }
bool send_data(List<Item> &items); bool send_data(List<Item> &items);
bool initialize_tables (JOIN *join); bool initialize_tables (JOIN *join);
void send_error(uint errcode,const char *err); void send_error(uint errcode,const char *err);
...@@ -1458,7 +1471,7 @@ class multi_delete :public select_result ...@@ -1458,7 +1471,7 @@ class multi_delete :public select_result
}; };
class multi_update :public select_result class multi_update :public select_result_interceptor
{ {
TABLE_LIST *all_tables, *update_tables, *table_being_updated; TABLE_LIST *all_tables, *update_tables, *table_being_updated;
THD *thd; THD *thd;
...@@ -1477,7 +1490,6 @@ class multi_update :public select_result ...@@ -1477,7 +1490,6 @@ class multi_update :public select_result
List<Item> *values, enum_duplicates handle_duplicates); List<Item> *values, enum_duplicates handle_duplicates);
~multi_update(); ~multi_update();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u); int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list, uint flag) { return 0; }
bool send_data(List<Item> &items); bool send_data(List<Item> &items);
bool initialize_tables (JOIN *join); bool initialize_tables (JOIN *join);
void send_error(uint errcode,const char *err); void send_error(uint errcode,const char *err);
...@@ -1486,7 +1498,7 @@ class multi_update :public select_result ...@@ -1486,7 +1498,7 @@ class multi_update :public select_result
}; };
class select_dumpvar :public select_result { class select_dumpvar :public select_result_interceptor {
ha_rows row_count; ha_rows row_count;
public: public:
List<LEX_STRING> var_list; List<LEX_STRING> var_list;
...@@ -1494,7 +1506,6 @@ class select_dumpvar :public select_result { ...@@ -1494,7 +1506,6 @@ class select_dumpvar :public select_result {
select_dumpvar(void) { var_list.empty(); vars.empty(); row_count=0;} select_dumpvar(void) { var_list.empty(); vars.empty(); row_count=0;}
~select_dumpvar() {} ~select_dumpvar() {}
int prepare(List<Item> &list, SELECT_LEX_UNIT *u); int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list, uint flag) {return 0;}
bool send_data(List<Item> &items); bool send_data(List<Item> &items);
bool send_eof(); bool send_eof();
void cleanup(); void cleanup();
......
...@@ -1064,6 +1064,12 @@ static int mysql_test_select(Prepared_statement *stmt, ...@@ -1064,6 +1064,12 @@ static int mysql_test_select(Prepared_statement *stmt,
DBUG_RETURN(1); DBUG_RETURN(1);
#endif #endif
if (!lex->result && !(lex->result= new (&stmt->mem_root) select_send))
{
send_error(thd);
goto err;
}
if (open_and_lock_tables(thd, tables)) if (open_and_lock_tables(thd, tables))
{ {
send_error(thd); send_error(thd);
...@@ -1087,8 +1093,13 @@ static int mysql_test_select(Prepared_statement *stmt, ...@@ -1087,8 +1093,13 @@ static int mysql_test_select(Prepared_statement *stmt,
} }
else else
{ {
if (send_prep_stmt(stmt, lex->select_lex.item_list.elements) || List<Item> &fields= lex->select_lex.item_list;
thd->protocol_simple.send_fields(&lex->select_lex.item_list, 0) /*
We can use lex->result as it should've been
prepared in unit->prepare call above.
*/
if (send_prep_stmt(stmt, lex->result->field_count(fields)) ||
lex->result->send_fields(fields, 0)
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
|| net_flush(&thd->net) || net_flush(&thd->net)
#endif #endif
......
...@@ -7099,6 +7099,7 @@ static int my_strnncollsp_uca(CHARSET_INFO *cs, ...@@ -7099,6 +7099,7 @@ static int my_strnncollsp_uca(CHARSET_INFO *cs,
{ {
s_res= scanner_handler->next(&sscanner); s_res= scanner_handler->next(&sscanner);
t_res= scanner_handler->next(&tscanner); t_res= scanner_handler->next(&tscanner);
} while ( s_res == t_res && s_res >0);
if (s_res > 0 && t_res < 0) if (s_res > 0 && t_res < 0)
{ {
...@@ -7130,8 +7131,6 @@ static int my_strnncollsp_uca(CHARSET_INFO *cs, ...@@ -7130,8 +7131,6 @@ static int my_strnncollsp_uca(CHARSET_INFO *cs,
return 0; return 0;
} }
} while ( s_res == t_res && s_res >0);
return ( s_res - t_res ); return ( s_res - t_res );
} }
......
...@@ -10625,6 +10625,23 @@ static void test_bug6058() ...@@ -10625,6 +10625,23 @@ static void test_bug6058()
} }
static void test_bug6059()
{
MYSQL_STMT *stmt;
const char *stmt_text;
int rc;
myheader("test_bug6059");
stmt_text= "SELECT 'foo' INTO OUTFILE 'x.3'";
stmt= mysql_stmt_init(mysql);
rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
DIE_UNLESS(mysql_stmt_field_count(stmt) == 0);
mysql_stmt_close(stmt);
}
/* /*
Read and parse arguments and MySQL options from my.cnf Read and parse arguments and MySQL options from my.cnf
...@@ -10938,6 +10955,7 @@ int main(int argc, char **argv) ...@@ -10938,6 +10955,7 @@ int main(int argc, char **argv)
prepared statements */ prepared statements */
test_bug6049(); /* check support for negative TIME values */ test_bug6049(); /* check support for negative TIME values */
test_bug6058(); /* check support for 0000-00-00 dates */ test_bug6058(); /* check support for 0000-00-00 dates */
test_bug6059(); /* correct metadata for SELECT ... INTO OUTFILE */
/* /*
XXX: PLEASE RUN THIS PROGRAM UNDER VALGRIND AND VERIFY THAT YOUR TEST XXX: PLEASE RUN THIS PROGRAM UNDER VALGRIND AND VERIFY THAT YOUR TEST
DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH. DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH.
......
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