mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 13:02:28 +01:00
Merge tulin@bk-internal.mysql.com:/home/bk/mysql-5.0
into poseidon.ndb.mysql.com:/home/tomas/mysql-5.1 sql/item.cc: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_select.cc: Auto merged sql/sql_yacc.yy: Auto merged sql/table.cc: Auto merged
This commit is contained in:
commit
23f261ef04
19 changed files with 320 additions and 27 deletions
|
@ -253,7 +253,7 @@ concat(':',product,':') sum(profit) avg(profit)
|
||||||
:Computer: 6900 1380.00000
|
:Computer: 6900 1380.00000
|
||||||
:Phone: 10 10.00000
|
:Phone: 10 10.00000
|
||||||
:TV: 600 120.00000
|
:TV: 600 120.00000
|
||||||
:TV: 7785 519.00000
|
NULL 7785 519.00000
|
||||||
select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube;
|
select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube;
|
||||||
ERROR 42000: This version of MySQL doesn't yet support 'CUBE'
|
ERROR 42000: This version of MySQL doesn't yet support 'CUBE'
|
||||||
explain select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube;
|
explain select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube;
|
||||||
|
@ -489,3 +489,69 @@ a SUM(a) SUM(a)+1 CONCAT(SUM(a),'x') SUM(a)+SUM(a) SUM(a)
|
||||||
5 5 6 5x 10 5
|
5 5 6 5x 10 5
|
||||||
NULL 8 9 8x 16 8
|
NULL 8 9 8x 16 8
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (a int(11));
|
||||||
|
INSERT INTO t1 VALUES (1),(2);
|
||||||
|
SELECT a, a+1, SUM(a) FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
a a+1 SUM(a)
|
||||||
|
1 2 1
|
||||||
|
2 3 2
|
||||||
|
NULL NULL 3
|
||||||
|
SELECT a+1 FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
a+1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
NULL
|
||||||
|
SELECT a+SUM(a) FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
a+SUM(a)
|
||||||
|
2
|
||||||
|
4
|
||||||
|
NULL
|
||||||
|
SELECT a, a+1 as b FROM t1 GROUP BY a WITH ROLLUP HAVING b > 2;
|
||||||
|
a b
|
||||||
|
2 3
|
||||||
|
SELECT a, a+1 as b FROM t1 GROUP BY a WITH ROLLUP HAVING a IS NULL;
|
||||||
|
a b
|
||||||
|
NULL NULL
|
||||||
|
SELECT a, a+1 as b FROM t1 GROUP BY a WITH ROLLUP HAVING b IS NULL;
|
||||||
|
a b
|
||||||
|
NULL NULL
|
||||||
|
SELECT IFNULL(a, 'TEST') FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
IFNULL(a, 'TEST')
|
||||||
|
1
|
||||||
|
2
|
||||||
|
TEST
|
||||||
|
CREATE TABLE t2 (a int, b int);
|
||||||
|
INSERT INTO t2 VALUES
|
||||||
|
(1,4),
|
||||||
|
(2,2), (2,2),
|
||||||
|
(4,1), (4,1), (4,1), (4,1),
|
||||||
|
(2,1), (2,1);
|
||||||
|
SELECT a,b,SUM(b) FROM t2 GROUP BY a,b WITH ROLLUP;
|
||||||
|
a b SUM(b)
|
||||||
|
1 4 4
|
||||||
|
1 NULL 4
|
||||||
|
2 1 2
|
||||||
|
2 2 4
|
||||||
|
2 NULL 6
|
||||||
|
4 1 4
|
||||||
|
4 NULL 4
|
||||||
|
NULL NULL 14
|
||||||
|
SELECT a,b,SUM(b), a+b as c FROM t2
|
||||||
|
GROUP BY a,b WITH ROLLUP HAVING c IS NULL;
|
||||||
|
a b SUM(b) c
|
||||||
|
1 NULL 4 NULL
|
||||||
|
2 NULL 6 NULL
|
||||||
|
4 NULL 4 NULL
|
||||||
|
NULL NULL 14 NULL
|
||||||
|
SELECT IFNULL(a, 'TEST'), COALESCE(b, 'TEST') FROM t2
|
||||||
|
GROUP BY a, b WITH ROLLUP;
|
||||||
|
IFNULL(a, 'TEST') COALESCE(b, 'TEST')
|
||||||
|
1 4
|
||||||
|
1 TEST
|
||||||
|
2 1
|
||||||
|
2 2
|
||||||
|
2 TEST
|
||||||
|
4 1
|
||||||
|
4 TEST
|
||||||
|
TEST TEST
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
|
|
@ -646,4 +646,16 @@ drop procedure if exists bug10537|
|
||||||
create procedure bug10537()
|
create procedure bug10537()
|
||||||
load data local infile '/tmp/somefile' into table t1|
|
load data local infile '/tmp/somefile' into table t1|
|
||||||
ERROR 0A000: LOAD DATA is not allowed in stored procedures
|
ERROR 0A000: LOAD DATA is not allowed in stored procedures
|
||||||
|
drop function if exists bug8409|
|
||||||
|
create function bug8409()
|
||||||
|
returns int
|
||||||
|
begin
|
||||||
|
flush tables;
|
||||||
|
return 5;
|
||||||
|
end|
|
||||||
|
ERROR 0A000: FLUSH is not allowed in stored procedures
|
||||||
|
create procedure bug9529_90123456789012345678901234567890123456789012345678901234567890()
|
||||||
|
begin
|
||||||
|
end|
|
||||||
|
ERROR 42000: Identifier name 'bug9529_90123456789012345678901234567890123456789012345678901234567890' is too long
|
||||||
drop table t1|
|
drop table t1|
|
||||||
|
|
|
@ -3098,4 +3098,15 @@ call bug5963_2(1)|
|
||||||
call bug5963_2(1)|
|
call bug5963_2(1)|
|
||||||
drop procedure bug5963_2|
|
drop procedure bug5963_2|
|
||||||
drop table t3|
|
drop table t3|
|
||||||
|
drop function if exists bug9559|
|
||||||
|
create function bug9559()
|
||||||
|
returns int
|
||||||
|
begin
|
||||||
|
set @y = -6/2;
|
||||||
|
return @y;
|
||||||
|
end|
|
||||||
|
select bug9559()|
|
||||||
|
bug9559()
|
||||||
|
-3
|
||||||
|
drop function bug9559|
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
|
|
|
@ -220,3 +220,33 @@ SELECT a, SUM(a), SUM(a)+1, CONCAT(SUM(a),'x'), SUM(a)+SUM(a), SUM(a)
|
||||||
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Tests for bug #7894: ROLLUP over expressions on group by attributes
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a int(11));
|
||||||
|
INSERT INTO t1 VALUES (1),(2);
|
||||||
|
|
||||||
|
SELECT a, a+1, SUM(a) FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
SELECT a+1 FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
SELECT a+SUM(a) FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
SELECT a, a+1 as b FROM t1 GROUP BY a WITH ROLLUP HAVING b > 2;
|
||||||
|
SELECT a, a+1 as b FROM t1 GROUP BY a WITH ROLLUP HAVING a IS NULL;
|
||||||
|
SELECT a, a+1 as b FROM t1 GROUP BY a WITH ROLLUP HAVING b IS NULL;
|
||||||
|
SELECT IFNULL(a, 'TEST') FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
|
||||||
|
CREATE TABLE t2 (a int, b int);
|
||||||
|
INSERT INTO t2 VALUES
|
||||||
|
(1,4),
|
||||||
|
(2,2), (2,2),
|
||||||
|
(4,1), (4,1), (4,1), (4,1),
|
||||||
|
(2,1), (2,1);
|
||||||
|
|
||||||
|
SELECT a,b,SUM(b) FROM t2 GROUP BY a,b WITH ROLLUP;
|
||||||
|
SELECT a,b,SUM(b), a+b as c FROM t2
|
||||||
|
GROUP BY a,b WITH ROLLUP HAVING c IS NULL;
|
||||||
|
SELECT IFNULL(a, 'TEST'), COALESCE(b, 'TEST') FROM t2
|
||||||
|
GROUP BY a, b WITH ROLLUP;
|
||||||
|
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
|
||||||
|
|
|
@ -905,6 +905,31 @@ create procedure bug10537()
|
||||||
load data local infile '/tmp/somefile' into table t1|
|
load data local infile '/tmp/somefile' into table t1|
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# BUG#8409: Stored procedure crash if function contains FLUSH
|
||||||
|
#
|
||||||
|
--disable_warnings
|
||||||
|
drop function if exists bug8409|
|
||||||
|
--enable_warnings
|
||||||
|
--error ER_SP_BADSTATEMENT
|
||||||
|
create function bug8409()
|
||||||
|
returns int
|
||||||
|
begin
|
||||||
|
flush tables;
|
||||||
|
return 5;
|
||||||
|
end|
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# BUG#9529: Stored Procedures: No Warning on truncation of procedure name
|
||||||
|
# during creation.
|
||||||
|
#
|
||||||
|
--error ER_TOO_LONG_IDENT
|
||||||
|
create procedure bug9529_90123456789012345678901234567890123456789012345678901234567890()
|
||||||
|
begin
|
||||||
|
end|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# BUG#NNNN: New bug synopsis
|
# BUG#NNNN: New bug synopsis
|
||||||
#
|
#
|
||||||
|
|
|
@ -3801,6 +3801,25 @@ call bug5963_2(1)|
|
||||||
drop procedure bug5963_2|
|
drop procedure bug5963_2|
|
||||||
drop table t3|
|
drop table t3|
|
||||||
|
|
||||||
|
#
|
||||||
|
# BUG#9559: Functions: Numeric Operations using -ve value gives incorrect
|
||||||
|
# results.
|
||||||
|
#
|
||||||
|
--disable_warnings
|
||||||
|
drop function if exists bug9559|
|
||||||
|
--enable_warnings
|
||||||
|
create function bug9559()
|
||||||
|
returns int
|
||||||
|
begin
|
||||||
|
set @y = -6/2;
|
||||||
|
return @y;
|
||||||
|
end|
|
||||||
|
|
||||||
|
select bug9559()|
|
||||||
|
|
||||||
|
drop function bug9559|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# BUG#NNNN: New bug synopsis
|
# BUG#NNNN: New bug synopsis
|
||||||
#
|
#
|
||||||
|
|
|
@ -301,10 +301,10 @@ void *Item::operator new(size_t size, Item *reuse, uint *rsize)
|
||||||
{
|
{
|
||||||
if (reuse && size <= reuse->rsize)
|
if (reuse && size <= reuse->rsize)
|
||||||
{
|
{
|
||||||
reuse->cleanup();
|
|
||||||
TRASH((void *)reuse, size);
|
|
||||||
if (rsize)
|
if (rsize)
|
||||||
(*rsize)= reuse->rsize;
|
(*rsize)= reuse->rsize;
|
||||||
|
reuse->cleanup();
|
||||||
|
TRASH((void *)reuse, size);
|
||||||
return (void *)reuse;
|
return (void *)reuse;
|
||||||
}
|
}
|
||||||
if (rsize)
|
if (rsize)
|
||||||
|
@ -4363,7 +4363,7 @@ bool Item_ref::get_date(TIME *ltime,uint fuzzydate)
|
||||||
|
|
||||||
my_decimal *Item_ref::val_decimal(my_decimal *decimal_value)
|
my_decimal *Item_ref::val_decimal(my_decimal *decimal_value)
|
||||||
{
|
{
|
||||||
my_decimal *val= (*ref)->val_decimal(decimal_value);
|
my_decimal *val= (*ref)->val_decimal_result(decimal_value);
|
||||||
null_value= (*ref)->null_value;
|
null_value= (*ref)->null_value;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2321,7 +2321,7 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||||
*/
|
*/
|
||||||
and_tables_cache= ~(table_map) 0;
|
and_tables_cache= ~(table_map) 0;
|
||||||
|
|
||||||
if (check_stack_overrun(thd, buff))
|
if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
|
||||||
return TRUE; // Fatal error flag is set!
|
return TRUE; // Fatal error flag is set!
|
||||||
/*
|
/*
|
||||||
The following optimization reduces the depth of an AND-OR tree.
|
The following optimization reduces the depth of an AND-OR tree.
|
||||||
|
|
|
@ -300,7 +300,7 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||||
used_tables_cache= not_null_tables_cache= 0;
|
used_tables_cache= not_null_tables_cache= 0;
|
||||||
const_item_cache=1;
|
const_item_cache=1;
|
||||||
|
|
||||||
if (check_stack_overrun(thd, buff))
|
if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
|
||||||
return TRUE; // Fatal error if flag is set!
|
return TRUE; // Fatal error if flag is set!
|
||||||
if (arg_count)
|
if (arg_count)
|
||||||
{ // Print purify happy
|
{ // Print purify happy
|
||||||
|
@ -2572,7 +2572,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
|
||||||
#endif
|
#endif
|
||||||
DBUG_ENTER("Item_udf_func::fix_fields");
|
DBUG_ENTER("Item_udf_func::fix_fields");
|
||||||
|
|
||||||
if (check_stack_overrun(thd, buff))
|
if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
|
||||||
DBUG_RETURN(TRUE); // Fatal error flag is set!
|
DBUG_RETURN(TRUE); // Fatal error flag is set!
|
||||||
|
|
||||||
udf_func *tmp_udf=find_udf(u_d->name.str,(uint) u_d->name.length,1);
|
udf_func *tmp_udf=find_udf(u_d->name.str,(uint) u_d->name.length,1);
|
||||||
|
@ -3603,7 +3603,7 @@ longlong user_var_entry::val_int(my_bool *null_value)
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
{
|
{
|
||||||
longlong result;
|
longlong result;
|
||||||
my_decimal2int(E_DEC_FATAL_ERROR, (my_decimal *)value, 1, &result);
|
my_decimal2int(E_DEC_FATAL_ERROR, (my_decimal *)value, 0, &result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
|
|
|
@ -138,7 +138,7 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
engine->set_thd((thd= thd_param));
|
engine->set_thd((thd= thd_param));
|
||||||
|
|
||||||
if (check_stack_overrun(thd, (gptr)&res))
|
if (check_stack_overrun(thd, STACK_MIN_SIZE, (gptr)&res))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
res= engine->prepare();
|
res= engine->prepare();
|
||||||
|
|
|
@ -1080,7 +1080,7 @@ extern ulong max_connections,max_connect_errors, connect_timeout;
|
||||||
extern ulong slave_net_timeout, slave_trans_retries;
|
extern ulong slave_net_timeout, slave_trans_retries;
|
||||||
extern uint max_user_connections;
|
extern uint max_user_connections;
|
||||||
extern ulong what_to_log,flush_time;
|
extern ulong what_to_log,flush_time;
|
||||||
extern ulong query_buff_size, thread_stack,thread_stack_min;
|
extern ulong query_buff_size, thread_stack;
|
||||||
extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit;
|
extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit;
|
||||||
extern ulong max_binlog_size, max_relay_log_size;
|
extern ulong max_binlog_size, max_relay_log_size;
|
||||||
extern ulong rpl_recovery_rank, thread_cache_size;
|
extern ulong rpl_recovery_rank, thread_cache_size;
|
||||||
|
@ -1431,11 +1431,11 @@ inline int hexchar_to_int(char c)
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
extern "C" void unireg_abort(int exit_code);
|
extern "C" void unireg_abort(int exit_code);
|
||||||
void kill_delayed_threads(void);
|
void kill_delayed_threads(void);
|
||||||
bool check_stack_overrun(THD *thd,char *dummy);
|
bool check_stack_overrun(THD *thd, long margin, char *dummy);
|
||||||
#else
|
#else
|
||||||
#define unireg_abort(exit_code) DBUG_RETURN(exit_code)
|
#define unireg_abort(exit_code) DBUG_RETURN(exit_code)
|
||||||
inline void kill_delayed_threads(void) {}
|
inline void kill_delayed_threads(void) {}
|
||||||
#define check_stack_overrun(A, B) 0
|
#define check_stack_overrun(A, B, C) 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* MYSQL_CLIENT */
|
#endif /* MYSQL_CLIENT */
|
||||||
|
|
|
@ -350,7 +350,7 @@ uint tc_heuristic_recover= 0;
|
||||||
uint volatile thread_count, thread_running;
|
uint volatile thread_count, thread_running;
|
||||||
ulong back_log, connect_timeout, concurrency;
|
ulong back_log, connect_timeout, concurrency;
|
||||||
ulong server_id, thd_startup_options;
|
ulong server_id, thd_startup_options;
|
||||||
ulong table_cache_size, thread_stack, thread_stack_min, what_to_log;
|
ulong table_cache_size, thread_stack, what_to_log;
|
||||||
ulong query_buff_size, slow_launch_time, slave_open_temp_tables;
|
ulong query_buff_size, slow_launch_time, slave_open_temp_tables;
|
||||||
ulong open_files_limit, max_binlog_size, max_relay_log_size;
|
ulong open_files_limit, max_binlog_size, max_relay_log_size;
|
||||||
ulong slave_net_timeout, slave_trans_retries;
|
ulong slave_net_timeout, slave_trans_retries;
|
||||||
|
@ -2086,7 +2086,15 @@ static void start_signal_handler(void)
|
||||||
(void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
|
(void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
|
||||||
if (!(opt_specialflag & SPECIAL_NO_PRIOR))
|
if (!(opt_specialflag & SPECIAL_NO_PRIOR))
|
||||||
my_pthread_attr_setprio(&thr_attr,INTERRUPT_PRIOR);
|
my_pthread_attr_setprio(&thr_attr,INTERRUPT_PRIOR);
|
||||||
|
#if defined(__ia64__) || defined(__ia64)
|
||||||
|
/*
|
||||||
|
Peculiar things with ia64 platforms - it seems we only have half the
|
||||||
|
stack size in reality, so we have to double it here
|
||||||
|
*/
|
||||||
|
pthread_attr_setstacksize(&thr_attr,thread_stack*2);
|
||||||
|
#else
|
||||||
pthread_attr_setstacksize(&thr_attr,thread_stack);
|
pthread_attr_setstacksize(&thr_attr,thread_stack);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
(void) pthread_mutex_lock(&LOCK_thread_count);
|
(void) pthread_mutex_lock(&LOCK_thread_count);
|
||||||
|
@ -3014,23 +3022,37 @@ int main(int argc, char **argv)
|
||||||
init_signals();
|
init_signals();
|
||||||
if (!(opt_specialflag & SPECIAL_NO_PRIOR))
|
if (!(opt_specialflag & SPECIAL_NO_PRIOR))
|
||||||
my_pthread_setprio(pthread_self(),CONNECT_PRIOR);
|
my_pthread_setprio(pthread_self(),CONNECT_PRIOR);
|
||||||
|
#if defined(__ia64__) || defined(__ia64)
|
||||||
|
/*
|
||||||
|
Peculiar things with ia64 platforms - it seems we only have half the
|
||||||
|
stack size in reality, so we have to double it here
|
||||||
|
*/
|
||||||
|
pthread_attr_setstacksize(&connection_attrib,thread_stack*2);
|
||||||
|
#else
|
||||||
pthread_attr_setstacksize(&connection_attrib,thread_stack);
|
pthread_attr_setstacksize(&connection_attrib,thread_stack);
|
||||||
|
#endif
|
||||||
#ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE
|
#ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE
|
||||||
{
|
{
|
||||||
/* Retrieve used stack size; Needed for checking stack overflows */
|
/* Retrieve used stack size; Needed for checking stack overflows */
|
||||||
size_t stack_size= 0;
|
size_t stack_size= 0;
|
||||||
pthread_attr_getstacksize(&connection_attrib, &stack_size);
|
pthread_attr_getstacksize(&connection_attrib, &stack_size);
|
||||||
|
#if defined(__ia64__) || defined(__ia64)
|
||||||
|
stack_size/= 2;
|
||||||
|
#endif
|
||||||
/* We must check if stack_size = 0 as Solaris 2.9 can return 0 here */
|
/* We must check if stack_size = 0 as Solaris 2.9 can return 0 here */
|
||||||
if (stack_size && stack_size < thread_stack)
|
if (stack_size && stack_size < thread_stack)
|
||||||
{
|
{
|
||||||
if (global_system_variables.log_warnings)
|
if (global_system_variables.log_warnings)
|
||||||
sql_print_warning("Asked for %ld thread stack, but got %ld",
|
sql_print_warning("Asked for %ld thread stack, but got %ld",
|
||||||
thread_stack, stack_size);
|
thread_stack, stack_size);
|
||||||
|
#if defined(__ia64__) || defined(__ia64)
|
||||||
|
thread_stack= stack_size*2;
|
||||||
|
#else
|
||||||
thread_stack= stack_size;
|
thread_stack= stack_size;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
thread_stack_min=thread_stack - STACK_MIN_SIZE;
|
|
||||||
|
|
||||||
(void) thr_setconcurrency(concurrency); // 10 by default
|
(void) thr_setconcurrency(concurrency); // 10 by default
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,10 @@ db_find_routine_aux(THD *thd, int type, sp_name *name,
|
||||||
'db', 'name' and 'type' and the first key is the primary key over the
|
'db', 'name' and 'type' and the first key is the primary key over the
|
||||||
same fields.
|
same fields.
|
||||||
*/
|
*/
|
||||||
|
if (name->m_name.length > table->field[1]->field_length)
|
||||||
|
{
|
||||||
|
DBUG_RETURN(SP_KEY_NOT_FOUND);
|
||||||
|
}
|
||||||
table->field[0]->store(name->m_db.str, name->m_db.length, &my_charset_bin);
|
table->field[0]->store(name->m_db.str, name->m_db.length, &my_charset_bin);
|
||||||
table->field[1]->store(name->m_name.str, name->m_name.length,
|
table->field[1]->store(name->m_name.str, name->m_name.length,
|
||||||
&my_charset_bin);
|
&my_charset_bin);
|
||||||
|
@ -389,6 +393,11 @@ db_create_routine(THD *thd, int type, sp_head *sp)
|
||||||
ret= SP_GET_FIELD_FAILED;
|
ret= SP_GET_FIELD_FAILED;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (sp->m_name.length > table->field[MYSQL_PROC_FIELD_NAME]->field_length)
|
||||||
|
{
|
||||||
|
ret= SP_BAD_IDENTIFIER;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
table->field[MYSQL_PROC_FIELD_DB]->
|
table->field[MYSQL_PROC_FIELD_DB]->
|
||||||
store(sp->m_db.str, sp->m_db.length, system_charset_info);
|
store(sp->m_db.str, sp->m_db.length, system_charset_info);
|
||||||
table->field[MYSQL_PROC_FIELD_NAME]->
|
table->field[MYSQL_PROC_FIELD_NAME]->
|
||||||
|
|
1
sql/sp.h
1
sql/sp.h
|
@ -28,6 +28,7 @@
|
||||||
#define SP_PARSE_ERROR -6
|
#define SP_PARSE_ERROR -6
|
||||||
#define SP_INTERNAL_ERROR -7
|
#define SP_INTERNAL_ERROR -7
|
||||||
#define SP_NO_DB_ERROR -8
|
#define SP_NO_DB_ERROR -8
|
||||||
|
#define SP_BAD_IDENTIFIER -9
|
||||||
|
|
||||||
/* Drop all routines in database 'db' */
|
/* Drop all routines in database 'db' */
|
||||||
int
|
int
|
||||||
|
|
|
@ -564,13 +564,11 @@ sp_head::execute(THD *thd)
|
||||||
Item_change_list old_change_list;
|
Item_change_list old_change_list;
|
||||||
String old_packet;
|
String old_packet;
|
||||||
|
|
||||||
|
/* Use some extra margin for possible SP recursion and functions */
|
||||||
#ifndef EMBEDDED_LIBRARY
|
if (check_stack_overrun(thd, 4*STACK_MIN_SIZE, olddb))
|
||||||
if (check_stack_overrun(thd, olddb))
|
|
||||||
{
|
{
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
dbchanged= FALSE;
|
dbchanged= FALSE;
|
||||||
if (m_db.length &&
|
if (m_db.length &&
|
||||||
|
|
|
@ -4023,6 +4023,12 @@ unsent_create_error:
|
||||||
delete lex->sphead;
|
delete lex->sphead;
|
||||||
lex->sphead= 0;
|
lex->sphead= 0;
|
||||||
goto error;
|
goto error;
|
||||||
|
case SP_BAD_IDENTIFIER:
|
||||||
|
my_error(ER_TOO_LONG_IDENT, MYF(0), name);
|
||||||
|
lex->unit.cleanup();
|
||||||
|
delete lex->sphead;
|
||||||
|
lex->sphead= 0;
|
||||||
|
goto error;
|
||||||
default:
|
default:
|
||||||
my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name);
|
my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name);
|
||||||
lex->unit.cleanup();
|
lex->unit.cleanup();
|
||||||
|
@ -4990,11 +4996,18 @@ long max_stack_used;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
bool check_stack_overrun(THD *thd,char *buf __attribute__((unused)))
|
/*
|
||||||
|
Note: The 'buf' parameter is necessary, even if it is unused here.
|
||||||
|
- fix_fields functions has a "dummy" buffer large enough for the
|
||||||
|
corresponding exec. (Thus we only have to check in fix_fields.)
|
||||||
|
- Passing to check_stack_overrun() prevents the compiler from removing it.
|
||||||
|
*/
|
||||||
|
bool check_stack_overrun(THD *thd, long margin,
|
||||||
|
char *buf __attribute__((unused)))
|
||||||
{
|
{
|
||||||
long stack_used;
|
long stack_used;
|
||||||
if ((stack_used=used_stack(thd->thread_stack,(char*) &stack_used)) >=
|
if ((stack_used=used_stack(thd->thread_stack,(char*) &stack_used)) >=
|
||||||
(long) thread_stack_min)
|
thread_stack - margin)
|
||||||
{
|
{
|
||||||
sprintf(errbuff[0],ER(ER_STACK_OVERRUN),stack_used,thread_stack);
|
sprintf(errbuff[0],ER(ER_STACK_OVERRUN),stack_used,thread_stack);
|
||||||
my_message(ER_STACK_OVERRUN,errbuff[0],MYF(0));
|
my_message(ER_STACK_OVERRUN,errbuff[0],MYF(0));
|
||||||
|
|
|
@ -12810,6 +12810,76 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select)
|
||||||
ROLLUP handling
|
ROLLUP handling
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Replace occurences of group by fields in an expression by ref items
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
change_group_ref()
|
||||||
|
thd reference to the context
|
||||||
|
expr expression to make replacement
|
||||||
|
group_list list of references to group by items
|
||||||
|
changed out: returns 1 if item contains a replaced field item
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
The function replaces occurrences of group by fields in expr
|
||||||
|
by ref objects for these fields unless they are under aggregate
|
||||||
|
functions.
|
||||||
|
|
||||||
|
IMPLEMENTATION
|
||||||
|
The function recursively traverses the tree of the expr expression,
|
||||||
|
looks for occurrences of the group by fields that are not under
|
||||||
|
aggregate functions and replaces them for the corresponding ref items.
|
||||||
|
|
||||||
|
NOTES
|
||||||
|
This substitution is needed GROUP BY queries with ROLLUP if
|
||||||
|
SELECT list contains expressions over group by attributes.
|
||||||
|
|
||||||
|
EXAMPLES
|
||||||
|
SELECT a+1 FROM t1 GROUP BY a WITH ROLLUP
|
||||||
|
SELECT SUM(a)+a FROM t1 GROUP BY a WITH ROLLUP
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 if ok
|
||||||
|
1 on error
|
||||||
|
*/
|
||||||
|
|
||||||
|
static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
|
||||||
|
bool *changed)
|
||||||
|
{
|
||||||
|
if (expr->arg_count)
|
||||||
|
{
|
||||||
|
Item **arg,**arg_end;
|
||||||
|
for (arg= expr->arguments(),
|
||||||
|
arg_end= expr->arguments()+expr->arg_count;
|
||||||
|
arg != arg_end; arg++)
|
||||||
|
{
|
||||||
|
Item *item= *arg;
|
||||||
|
if (item->type() == Item::FIELD_ITEM || item->type() == Item::REF_ITEM)
|
||||||
|
{
|
||||||
|
ORDER *group_tmp;
|
||||||
|
for (group_tmp= group_list; group_tmp; group_tmp= group_tmp->next)
|
||||||
|
{
|
||||||
|
if (item->eq(*group_tmp->item,0))
|
||||||
|
{
|
||||||
|
Item *new_item;
|
||||||
|
if(!(new_item= new Item_ref(group_tmp->item, 0, item->name)))
|
||||||
|
return 1; // fatal_error is set
|
||||||
|
thd->change_item_tree(arg, new_item);
|
||||||
|
*changed= TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (item->type() == Item::FUNC_ITEM)
|
||||||
|
{
|
||||||
|
if (change_group_ref(thd, (Item_func *) item, group_list, changed))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Allocate memory needed for other rollup functions */
|
/* Allocate memory needed for other rollup functions */
|
||||||
|
|
||||||
bool JOIN::rollup_init()
|
bool JOIN::rollup_init()
|
||||||
|
@ -12854,19 +12924,31 @@ bool JOIN::rollup_init()
|
||||||
for (j=0 ; j < fields_list.elements ; j++)
|
for (j=0 ; j < fields_list.elements ; j++)
|
||||||
rollup.fields[i].push_back(rollup.null_items[i]);
|
rollup.fields[i].push_back(rollup.null_items[i]);
|
||||||
}
|
}
|
||||||
List_iterator_fast<Item> it(fields_list);
|
List_iterator_fast<Item> it(all_fields);
|
||||||
Item *item;
|
Item *item;
|
||||||
while ((item= it++))
|
while ((item= it++))
|
||||||
{
|
{
|
||||||
ORDER *group_tmp;
|
ORDER *group_tmp;
|
||||||
for (group_tmp= group_list; group_tmp; group_tmp= group_tmp->next)
|
for (group_tmp= group_list; group_tmp; group_tmp= group_tmp->next)
|
||||||
{
|
{
|
||||||
if (*group_tmp->item == item)
|
if (item->eq(*group_tmp->item,0))
|
||||||
item->maybe_null= 1;
|
item->maybe_null= 1;
|
||||||
}
|
}
|
||||||
|
if (item->type() == Item::FUNC_ITEM)
|
||||||
|
{
|
||||||
|
bool changed= 0;
|
||||||
|
if (change_group_ref(thd, (Item_func *) item, group_list, &changed))
|
||||||
|
return 1;
|
||||||
|
/*
|
||||||
|
We have to prevent creation of a field in a temporary table for
|
||||||
|
an expression that contains GROUP BY attributes.
|
||||||
|
Marking the expression item as 'with_sum_func' will ensure this.
|
||||||
|
*/
|
||||||
|
if (changed)
|
||||||
|
item->with_sum_func= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -12962,14 +13044,14 @@ bool JOIN::rollup_make_fields(List<Item> &fields_arg, List<Item> &sel_fields,
|
||||||
*(*func)= (Item_sum*) item;
|
*(*func)= (Item_sum*) item;
|
||||||
(*func)++;
|
(*func)++;
|
||||||
}
|
}
|
||||||
else if (real_fields)
|
else
|
||||||
{
|
{
|
||||||
/* Check if this is something that is part of this group by */
|
/* Check if this is something that is part of this group by */
|
||||||
ORDER *group_tmp;
|
ORDER *group_tmp;
|
||||||
for (group_tmp= start_group, i= pos ;
|
for (group_tmp= start_group, i= pos ;
|
||||||
group_tmp ; group_tmp= group_tmp->next, i++)
|
group_tmp ; group_tmp= group_tmp->next, i++)
|
||||||
{
|
{
|
||||||
if (*group_tmp->item == item)
|
if (item->eq(*group_tmp->item,0))
|
||||||
{
|
{
|
||||||
Item_null_result *null_item;
|
Item_null_result *null_item;
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -6511,6 +6511,11 @@ flush:
|
||||||
FLUSH_SYM opt_no_write_to_binlog
|
FLUSH_SYM opt_no_write_to_binlog
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
|
if (lex->sphead && lex->sphead->m_type == TYPE_ENUM_FUNCTION)
|
||||||
|
{
|
||||||
|
my_error(ER_SP_BADSTATEMENT, MYF(0), "FLUSH");
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
lex->sql_command= SQLCOM_FLUSH; lex->type=0;
|
lex->sql_command= SQLCOM_FLUSH; lex->type=0;
|
||||||
lex->no_write_to_binlog= $2;
|
lex->no_write_to_binlog= $2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1818,7 +1818,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
|
||||||
bool res= FALSE;
|
bool res= FALSE;
|
||||||
DBUG_ENTER("st_table_list::setup_ancestor");
|
DBUG_ENTER("st_table_list::setup_ancestor");
|
||||||
|
|
||||||
if (check_stack_overrun(thd, (char *)&res))
|
if (check_stack_overrun(thd, STACK_MIN_SIZE, (char *)&res))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
for (tbl= ancestor; tbl; tbl= tbl->next_local)
|
for (tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||||
|
|
Loading…
Reference in a new issue