Commit 25a2c4a7 authored by monty@mysql.com's avatar monty@mysql.com

Cleanup during review

Simple optimization for 2 argument usage to function of variable arguments
Fix stack overrun when using 1+1+1+1+1+1+1+....
Update crash-me results for 5.0
Don't call post_open if pre_open() fails (optimization)
parent a69f4321
...@@ -1738,7 +1738,7 @@ myodbc_remove_escape(MYSQL *mysql,char *name) ...@@ -1738,7 +1738,7 @@ myodbc_remove_escape(MYSQL *mysql,char *name)
/* Default number of rows fetched per one COM_FETCH command. */ /* Default number of rows fetched per one COM_FETCH command. */
#define DEFAULT_PREFETCH_ROWS 1UL #define DEFAULT_PREFETCH_ROWS (ulong) 1
/* /*
These functions are called by function pointer MYSQL_STMT::read_row_func. These functions are called by function pointer MYSQL_STMT::read_row_func.
......
...@@ -887,7 +887,7 @@ report_stats () { ...@@ -887,7 +887,7 @@ report_stats () {
found_error=0 found_error=0
# Find errors # Find errors
for i in "^Warning:" "^Error:" "^==.* at 0x" for i in "^Warning:" "^Error:" "^==.* at 0x" "InnoDB: Warning"
do do
if $GREP "$i" $MY_LOG_DIR/warnings.tmp >> $MY_LOG_DIR/warnings if $GREP "$i" $MY_LOG_DIR/warnings.tmp >> $MY_LOG_DIR/warnings
then then
......
...@@ -911,7 +911,9 @@ DROP TABLE t1; ...@@ -911,7 +911,9 @@ DROP TABLE t1;
# Bug #10465 # Bug #10465
# #
--disable_warnings
CREATE TABLE t1 (GRADE DECIMAL(4) NOT NULL, PRIMARY KEY (GRADE)) ENGINE=INNODB; CREATE TABLE t1 (GRADE DECIMAL(4) NOT NULL, PRIMARY KEY (GRADE)) ENGINE=INNODB;
--enable_warnings
INSERT INTO t1 (GRADE) VALUES (151),(252),(343); INSERT INTO t1 (GRADE) VALUES (151),(252),(343);
SELECT GRADE FROM t1 WHERE GRADE > 160 AND GRADE < 300; SELECT GRADE FROM t1 WHERE GRADE > 160 AND GRADE < 300;
SELECT GRADE FROM t1 WHERE GRADE= 151; SELECT GRADE FROM t1 WHERE GRADE= 151;
......
...@@ -39,10 +39,11 @@ ...@@ -39,10 +39,11 @@
DESCRIPTION DESCRIPTION
This function prepares memory root for further use, sets initial size of This function prepares memory root for further use, sets initial size of
chunk for memory allocation and pre-allocates first block if specified. chunk for memory allocation and pre-allocates first block if specified.
Altough error can happen during execution of this function if pre_alloc_size Altough error can happen during execution of this function if
is non-0 it won't be reported. Instead it will be reported as error in first pre_alloc_size is non-0 it won't be reported. Instead it will be
alloc_root() on this memory root. reported as error in first alloc_root() on this memory root.
*/ */
void init_alloc_root(MEM_ROOT *mem_root, uint block_size, void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
uint pre_alloc_size __attribute__((unused))) uint pre_alloc_size __attribute__((unused)))
{ {
...@@ -71,6 +72,7 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size, ...@@ -71,6 +72,7 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/* /*
SYNOPSIS SYNOPSIS
reset_root_defaults() reset_root_defaults()
...@@ -86,7 +88,7 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size, ...@@ -86,7 +88,7 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
reuse one of existing blocks as prealloc block, or malloc new one of reuse one of existing blocks as prealloc block, or malloc new one of
requested size. If no blocks can be reused, all unused blocks are freed requested size. If no blocks can be reused, all unused blocks are freed
before allocation. before allocation.
*/ */
void reset_root_defaults(MEM_ROOT *mem_root, uint block_size, void reset_root_defaults(MEM_ROOT *mem_root, uint block_size,
uint pre_alloc_size __attribute__((unused))) uint pre_alloc_size __attribute__((unused)))
......
...@@ -684,8 +684,10 @@ void thr_unlock(THR_LOCK_DATA *data) ...@@ -684,8 +684,10 @@ void thr_unlock(THR_LOCK_DATA *data)
lock->read.last=data->prev; lock->read.last=data->prev;
else if (lock_type == TL_WRITE_DELAYED && data->cond) else if (lock_type == TL_WRITE_DELAYED && data->cond)
{ {
/* This only happens in extreme circumstances when a /*
write delayed lock that is waiting for a lock */ This only happens in extreme circumstances when a
write delayed lock that is waiting for a lock
*/
lock->write_wait.last=data->prev; /* Put it on wait queue */ lock->write_wait.last=data->prev; /* Put it on wait queue */
} }
else else
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -284,7 +284,9 @@ public: ...@@ -284,7 +284,9 @@ public:
Item(THD *thd, Item *item); Item(THD *thd, Item *item);
virtual ~Item() virtual ~Item()
{ {
#ifdef EXTRA_DEBUG
name=0; name=0;
#endif
} /*lint -e1509 */ } /*lint -e1509 */
void set_name(const char *str,uint length, CHARSET_INFO *cs); void set_name(const char *str,uint length, CHARSET_INFO *cs);
void rename(char *new_name); void rename(char *new_name);
......
...@@ -211,15 +211,16 @@ void Item_func::set_arguments(List<Item> &list) ...@@ -211,15 +211,16 @@ void Item_func::set_arguments(List<Item> &list)
{ {
allowed_arg_cols= 1; allowed_arg_cols= 1;
arg_count=list.elements; arg_count=list.elements;
if ((args=(Item**) sql_alloc(sizeof(Item*)*arg_count))) args= tmp_arg; // If 2 arguments
if (arg_count <= 2 || (args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
{ {
uint i=0;
List_iterator_fast<Item> li(list); List_iterator_fast<Item> li(list);
Item *item; Item *item;
Item **save_args= args;
while ((item=li++)) while ((item=li++))
{ {
args[i++]= item; *(save_args++)= item;
with_sum_func|=item->with_sum_func; with_sum_func|=item->with_sum_func;
} }
} }
......
...@@ -94,7 +94,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; ...@@ -94,7 +94,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define MAX_FIELDS_BEFORE_HASH 32 #define MAX_FIELDS_BEFORE_HASH 32
#define USER_VARS_HASH_SIZE 16 #define USER_VARS_HASH_SIZE 16
#define STACK_MIN_SIZE 8192 // Abort if less stack during eval. #define STACK_MIN_SIZE 8192 // Abort if less stack during eval.
#define STACK_BUFF_ALLOC 64 // For stack overrun checks #define STACK_BUFF_ALLOC 256 // For stack overrun checks
#ifndef MYSQLD_NET_RETRY_COUNT #ifndef MYSQLD_NET_RETRY_COUNT
#define MYSQLD_NET_RETRY_COUNT 10 // Abort read after this many int. #define MYSQLD_NET_RETRY_COUNT 10 // Abort read after this many int.
#endif #endif
......
...@@ -1904,21 +1904,21 @@ sp_instr_copen::execute(THD *thd, uint *nextp) ...@@ -1904,21 +1904,21 @@ sp_instr_copen::execute(THD *thd, uint *nextp)
else else
{ {
sp_lex_keeper *lex_keeper= c->pre_open(thd); sp_lex_keeper *lex_keeper= c->pre_open(thd);
if (!lex_keeper) // cursor already open or OOM
if (!lex_keeper)
{ {
res= -1; res= -1;
*nextp= m_ip+1; *nextp= m_ip+1;
} }
else else
{
res= lex_keeper->reset_lex_and_exec_core(thd, nextp, FALSE, this); res= lex_keeper->reset_lex_and_exec_core(thd, nextp, FALSE, this);
c->post_open(thd, res ? FALSE : TRUE);
c->post_open(thd, (lex_keeper ? TRUE : FALSE)); }
} }
DBUG_RETURN(res); DBUG_RETURN(res);
} }
int int
sp_instr_copen::exec_core(THD *thd, uint *nextp) sp_instr_copen::exec_core(THD *thd, uint *nextp)
{ {
......
...@@ -168,8 +168,22 @@ sp_rcontext::pop_cursors(uint count) ...@@ -168,8 +168,22 @@ sp_rcontext::pop_cursors(uint count)
* *
*/ */
// We have split this in two to make it easy for sp_instr_copen /*
// to reuse the sp_instr::exec_stmt() code. pre_open cursor
SYNOPSIS
pre_open()
THD Thread handler
NOTES
We have to open cursor in two steps to make it easy for sp_instr_copen
to reuse the sp_instr::exec_stmt() code.
If this function returns 0, post_open should not be called
RETURN
0 ERROR
*/
sp_lex_keeper* sp_lex_keeper*
sp_cursor::pre_open(THD *thd) sp_cursor::pre_open(THD *thd)
{ {
...@@ -179,32 +193,31 @@ sp_cursor::pre_open(THD *thd) ...@@ -179,32 +193,31 @@ sp_cursor::pre_open(THD *thd)
MYF(0)); MYF(0));
return NULL; return NULL;
} }
bzero((char *)&m_mem_root, sizeof(m_mem_root));
init_alloc_root(&m_mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC); init_alloc_root(&m_mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
if ((m_prot= new Protocol_cursor(thd, &m_mem_root)) == NULL) if ((m_prot= new Protocol_cursor(thd, &m_mem_root)) == NULL)
return NULL; return NULL;
m_oprot= thd->protocol; // Save the original protocol /* Save for execution. Will be restored in post_open */
thd->protocol= m_prot; m_oprot= thd->protocol;
m_nseof= thd->net.no_send_eof; m_nseof= thd->net.no_send_eof;
/* Change protocol for execution */
thd->protocol= m_prot;
thd->net.no_send_eof= TRUE; thd->net.no_send_eof= TRUE;
return m_lex_keeper; return m_lex_keeper;
} }
void void
sp_cursor::post_open(THD *thd, my_bool was_opened) sp_cursor::post_open(THD *thd, my_bool was_opened)
{ {
thd->net.no_send_eof= m_nseof; // Restore the originals thd->net.no_send_eof= m_nseof; // Restore the originals
thd->protocol= m_oprot; thd->protocol= m_oprot;
if (was_opened) if ((m_isopen= was_opened))
{
m_isopen= was_opened;
m_current_row= m_prot->data; m_current_row= m_prot->data;
}
} }
int int
sp_cursor::close(THD *thd) sp_cursor::close(THD *thd)
{ {
...@@ -217,6 +230,7 @@ sp_cursor::close(THD *thd) ...@@ -217,6 +230,7 @@ sp_cursor::close(THD *thd)
return 0; return 0;
} }
void void
sp_cursor::destroy() sp_cursor::destroy()
{ {
...@@ -225,7 +239,6 @@ sp_cursor::destroy() ...@@ -225,7 +239,6 @@ sp_cursor::destroy()
delete m_prot; delete m_prot;
m_prot= NULL; m_prot= NULL;
free_root(&m_mem_root, MYF(0)); free_root(&m_mem_root, MYF(0));
bzero((char *)&m_mem_root, sizeof(m_mem_root));
} }
m_isopen= FALSE; m_isopen= FALSE;
} }
......
...@@ -4502,7 +4502,8 @@ unsent_create_error: ...@@ -4502,7 +4502,8 @@ unsent_create_error:
send_ok(thd); send_ok(thd);
break; break;
} }
if (thd->transaction.xa_state == XA_IDLE && thd->lex->xa_opt == XA_ONE_PHASE) if (thd->transaction.xa_state == XA_IDLE &&
thd->lex->xa_opt == XA_ONE_PHASE)
{ {
int r; int r;
if ((r= ha_commit(thd))) if ((r= ha_commit(thd)))
...@@ -4510,8 +4511,8 @@ unsent_create_error: ...@@ -4510,8 +4511,8 @@ unsent_create_error:
else else
send_ok(thd); send_ok(thd);
} }
else else if (thd->transaction.xa_state == XA_PREPARED &&
if (thd->transaction.xa_state == XA_PREPARED && thd->lex->xa_opt == XA_NONE) thd->lex->xa_opt == XA_NONE)
{ {
if (wait_if_global_read_lock(thd, 0, 0)) if (wait_if_global_read_lock(thd, 0, 0))
{ {
......
...@@ -955,14 +955,16 @@ JOIN::optimize() ...@@ -955,14 +955,16 @@ JOIN::optimize()
#endif #endif
DBUG_EXECUTE("info",TEST_join(this);); DBUG_EXECUTE("info",TEST_join(this););
if (const_tables != tables)
{
/* /*
Because filesort always does a full table scan or a quick range scan Because filesort always does a full table scan or a quick range scan
we must add the removed reference to the select for the table. we must add the removed reference to the select for the table.
We only need to do this when we have a simple_order or simple_group We only need to do this when we have a simple_order or simple_group
as in other cases the join is done before the sort. as in other cases the join is done before the sort.
*/ */
if (const_tables != tables && if ((order || group_list) &&
(order || group_list) &&
join_tab[const_tables].type != JT_ALL && join_tab[const_tables].type != JT_ALL &&
join_tab[const_tables].type != JT_FT && join_tab[const_tables].type != JT_FT &&
join_tab[const_tables].type != JT_REF_OR_NULL && join_tab[const_tables].type != JT_REF_OR_NULL &&
...@@ -973,7 +975,7 @@ JOIN::optimize() ...@@ -973,7 +975,7 @@ JOIN::optimize()
} }
if (!(select_options & SELECT_BIG_RESULT) && if (!(select_options & SELECT_BIG_RESULT) &&
((group_list && const_tables != tables && ((group_list &&
(!simple_group || (!simple_group ||
!test_if_skip_sort_order(&join_tab[const_tables], group_list, !test_if_skip_sort_order(&join_tab[const_tables], group_list,
unit->select_limit_cnt, 0))) || unit->select_limit_cnt, 0))) ||
...@@ -982,6 +984,7 @@ JOIN::optimize() ...@@ -982,6 +984,7 @@ JOIN::optimize()
{ {
need_tmp=1; simple_order=simple_group=0; // Force tmp table without sort need_tmp=1; simple_order=simple_group=0; // Force tmp table without sort
} }
}
tmp_having= having; tmp_having= having;
if (select_options & SELECT_DESCRIBE) if (select_options & SELECT_DESCRIBE)
...@@ -5219,7 +5222,10 @@ add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab) ...@@ -5219,7 +5222,10 @@ add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab)
tmp= new Item_func_trig_cond(tmp, &tab->found); tmp= new Item_func_trig_cond(tmp, &tab->found);
} }
if (tmp) if (tmp)
{
tmp->quick_fix_field(); tmp->quick_fix_field();
tmp->update_used_tables();
}
return tmp; return tmp;
} }
...@@ -5376,6 +5382,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) ...@@ -5376,6 +5382,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
JOIN_TAB *first_inner_tab= tab->first_inner; JOIN_TAB *first_inner_tab= tab->first_inner;
table_map current_map= tab->table->map; table_map current_map= tab->table->map;
bool use_quick_range=0; bool use_quick_range=0;
COND *tmp;
/* /*
Following force including random expression in last table condition. Following force including random expression in last table condition.
It solve problem with select like SELECT * FROM t1 WHERE rand() > 0.5 It solve problem with select like SELECT * FROM t1 WHERE rand() > 0.5
...@@ -5397,7 +5405,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) ...@@ -5397,7 +5405,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
join->best_positions[i].records_read= rows2double(tab->quick->records); join->best_positions[i].records_read= rows2double(tab->quick->records);
} }
COND *tmp= NULL; tmp= NULL;
if (cond) if (cond)
tmp= make_cond_for_table(cond,used_tables,current_map); tmp= make_cond_for_table(cond,used_tables,current_map);
if (cond && !tmp && tab->quick) if (cond && !tmp && tab->quick)
......
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