mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 13:02:28 +01:00
Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-5.0
into sanja.is.com.ua:/home/bell/mysql/bk/work-bug3-5.0
This commit is contained in:
commit
a771b57172
12 changed files with 110 additions and 68 deletions
|
@ -342,7 +342,7 @@ AC_SUBST(CXXFLAGS)
|
|||
AC_SUBST(LD)
|
||||
AC_SUBST(INSTALL_SCRIPT)
|
||||
|
||||
export CC CXX CFLAGS LD LDFLAGS AR
|
||||
export CC CXX CFLAGS LD LDFLAGS AR ARFLAGS
|
||||
|
||||
if test "$GCC" = "yes"
|
||||
then
|
||||
|
|
|
@ -117,6 +117,13 @@ case "$target" in
|
|||
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
|
||||
esac
|
||||
|
||||
# must go in pair with AR as set by MYSQL_CHECK_AR
|
||||
if test -z "$ARFLAGS"
|
||||
then
|
||||
ARFLAGS="cru"
|
||||
fi
|
||||
AC_SUBST(ARFLAGS)
|
||||
|
||||
AC_OUTPUT(Makefile os/Makefile ut/Makefile btr/Makefile dnl
|
||||
buf/Makefile data/Makefile dnl
|
||||
dict/Makefile dyn/Makefile dnl
|
||||
|
|
|
@ -303,7 +303,7 @@ sub mysqld_arguments ($$$$$);
|
|||
sub stop_masters_slaves ();
|
||||
sub stop_masters ();
|
||||
sub stop_slaves ();
|
||||
sub run_mysqltest ($$);
|
||||
sub run_mysqltest ($);
|
||||
sub usage ($);
|
||||
|
||||
######################################################################
|
||||
|
@ -1342,10 +1342,11 @@ sub run_testcase ($) {
|
|||
|
||||
if ( ! $glob_use_running_server and ! $glob_use_embedded_server )
|
||||
{
|
||||
if ( $tinfo->{'master_restart'} or $master->[0]->{'uses_special_flags'} )
|
||||
if ( $tinfo->{'master_restart'} or
|
||||
$master->[0]->{'running_master_is_special'} )
|
||||
{
|
||||
stop_masters();
|
||||
$master->[0]->{'uses_special_flags'}= 0; # Forget about why we stopped
|
||||
$master->[0]->{'running_master_is_special'}= 0; # Forget why we stopped
|
||||
}
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
|
@ -1423,9 +1424,9 @@ sub run_testcase ($) {
|
|||
}
|
||||
}
|
||||
|
||||
if ( @{$tinfo->{'master_opt'}} )
|
||||
if ( $tinfo->{'master_restart'} )
|
||||
{
|
||||
$master->[0]->{'uses_special_flags'}= 1;
|
||||
$master->[0]->{'running_master_is_special'}= 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1472,7 +1473,7 @@ sub run_testcase ($) {
|
|||
}
|
||||
unlink($path_timefile);
|
||||
|
||||
my $res= run_mysqltest($tinfo, $tinfo->{'master_opt'});
|
||||
my $res= run_mysqltest($tinfo);
|
||||
|
||||
if ( $res == 0 )
|
||||
{
|
||||
|
@ -1973,9 +1974,8 @@ sub stop_slaves () {
|
|||
}
|
||||
|
||||
|
||||
sub run_mysqltest ($$) {
|
||||
sub run_mysqltest ($) {
|
||||
my $tinfo= shift;
|
||||
my $master_opts= shift;
|
||||
|
||||
my $cmdline_mysqldump= "$exe_mysqldump --no-defaults -uroot " .
|
||||
"--socket=$master->[0]->{'path_mysock'} --password=";
|
||||
|
|
|
@ -160,6 +160,21 @@ t1 CREATE TABLE `t1` (
|
|||
`COALESCE('a' COLLATE latin1_bin,'b')` varchar(1) character set latin1 collate latin1_bin NOT NULL default ''
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
DROP TABLE t1;
|
||||
SELECT 'case+union+test'
|
||||
UNION
|
||||
SELECT CASE LOWER('1') WHEN LOWER('2') THEN 'BUG' ELSE 'nobug' END;
|
||||
case+union+test
|
||||
case+union+test
|
||||
nobug
|
||||
SELECT CASE LOWER('1') WHEN LOWER('2') THEN 'BUG' ELSE 'nobug' END;
|
||||
CASE LOWER('1') WHEN LOWER('2') THEN 'BUG' ELSE 'nobug' END
|
||||
nobug
|
||||
SELECT 'case+union+test'
|
||||
UNION
|
||||
SELECT CASE '1' WHEN '2' THEN 'BUG' ELSE 'nobug' END;
|
||||
case+union+test
|
||||
case+union+test
|
||||
nobug
|
||||
CREATE TABLE t1 (EMPNUM INT);
|
||||
INSERT INTO t1 VALUES (0), (2);
|
||||
CREATE TABLE t2 (EMPNUM DECIMAL (4, 2));
|
||||
|
|
|
@ -111,6 +111,17 @@ explain extended SELECT
|
|||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
# Test for BUG#10151
|
||||
SELECT 'case+union+test'
|
||||
UNION
|
||||
SELECT CASE LOWER('1') WHEN LOWER('2') THEN 'BUG' ELSE 'nobug' END;
|
||||
|
||||
SELECT CASE LOWER('1') WHEN LOWER('2') THEN 'BUG' ELSE 'nobug' END;
|
||||
|
||||
SELECT 'case+union+test'
|
||||
UNION
|
||||
SELECT CASE '1' WHEN '2' THEN 'BUG' ELSE 'nobug' END;
|
||||
|
||||
#
|
||||
# Tests for bug #9939: conversion of the arguments for COALESCE and IFNULL
|
||||
#
|
||||
|
|
|
@ -1420,6 +1420,8 @@ Item *Item_func_case::find_item(String *str)
|
|||
my_decimal *first_expr_dec, first_expr_dec_val;
|
||||
longlong first_expr_int;
|
||||
double first_expr_real;
|
||||
char buff[MAX_FIELD_WIDTH];
|
||||
String buff_str(buff,sizeof(buff),default_charset());
|
||||
|
||||
/* These will be initialized later */
|
||||
LINT_INIT(first_expr_str);
|
||||
|
@ -1433,7 +1435,7 @@ Item *Item_func_case::find_item(String *str)
|
|||
{
|
||||
case STRING_RESULT:
|
||||
// We can't use 'str' here as this may be overwritten
|
||||
if (!(first_expr_str= args[first_expr_num]->val_str(&str_value)))
|
||||
if (!(first_expr_str= args[first_expr_num]->val_str(&buff_str)))
|
||||
return else_expr_num != -1 ? args[else_expr_num] : 0; // Impossible
|
||||
break;
|
||||
case INT_RESULT:
|
||||
|
|
|
@ -509,7 +509,7 @@ sp_head::destroy()
|
|||
delete i;
|
||||
delete_dynamic(&m_instr);
|
||||
m_pcont->destroy();
|
||||
free_items(free_list);
|
||||
free_items();
|
||||
|
||||
/*
|
||||
If we have non-empty LEX stack then we just came out of parser with
|
||||
|
@ -596,7 +596,6 @@ sp_head::execute(THD *thd)
|
|||
ctx->clear_handler();
|
||||
thd->query_error= 0;
|
||||
old_arena= thd->current_arena;
|
||||
thd->current_arena= this;
|
||||
|
||||
/*
|
||||
We have to save/restore this info when we are changing call level to
|
||||
|
@ -636,23 +635,18 @@ sp_head::execute(THD *thd)
|
|||
break;
|
||||
DBUG_PRINT("execute", ("Instruction %u", ip));
|
||||
thd->set_time(); // Make current_time() et al work
|
||||
{
|
||||
/*
|
||||
We have to substitute free_list of executing statement to
|
||||
current_arena to store there all new items created during execution
|
||||
(for example '*' expanding, or items made during permanent subquery
|
||||
transformation)
|
||||
Note: Every statement have to have all its items listed in free_list
|
||||
for correct cleaning them up
|
||||
*/
|
||||
Item *save_free_list= thd->current_arena->free_list;
|
||||
thd->current_arena->free_list= i->free_list;
|
||||
ret= i->execute(thd, &ip);
|
||||
i->free_list= thd->current_arena->free_list;
|
||||
thd->current_arena->free_list= save_free_list;
|
||||
}
|
||||
/*
|
||||
We have to set thd->current_arena before executing the instruction
|
||||
to store in the instruction free_list all new items, created
|
||||
during the first execution (for example expanding of '*' or the
|
||||
items made during other permanent subquery transformations).
|
||||
*/
|
||||
thd->current_arena= i;
|
||||
ret= i->execute(thd, &ip);
|
||||
if (i->free_list)
|
||||
cleanup_items(i->free_list);
|
||||
i->state= Query_arena::EXECUTED;
|
||||
|
||||
// Check if an exception has occurred and a handler has been found
|
||||
// Note: We havo to check even if ret==0, since warnings (and some
|
||||
// errors don't return a non-zero value.
|
||||
|
@ -694,7 +688,6 @@ sp_head::execute(THD *thd)
|
|||
DBUG_ASSERT(!thd->derived_tables);
|
||||
thd->derived_tables= old_derived_tables;
|
||||
|
||||
cleanup_items(thd->current_arena->free_list);
|
||||
thd->current_arena= old_arena;
|
||||
state= EXECUTED;
|
||||
|
||||
|
@ -728,8 +721,8 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
|
|||
sp_rcontext *nctx = NULL;
|
||||
uint i;
|
||||
int ret;
|
||||
MEM_ROOT *old_mem_root, call_mem_root;
|
||||
Item *old_free_list, *call_free_list;
|
||||
MEM_ROOT call_mem_root;
|
||||
Query_arena call_arena(&call_mem_root, INITIALIZED_FOR_SP), backup_arena;
|
||||
|
||||
if (argcount != params)
|
||||
{
|
||||
|
@ -741,14 +734,12 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
|
|||
}
|
||||
|
||||
init_alloc_root(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0);
|
||||
old_mem_root= thd->mem_root;
|
||||
thd->mem_root= &call_mem_root;
|
||||
old_free_list= thd->free_list; // Keep the old list
|
||||
thd->free_list= NULL; // Start a new one
|
||||
|
||||
thd->set_n_backup_item_arena(&call_arena, &backup_arena);
|
||||
|
||||
// QQ Should have some error checking here? (types, etc...)
|
||||
nctx= new sp_rcontext(csize, hmax, cmax);
|
||||
nctx->callers_mem_root= old_mem_root;
|
||||
nctx->callers_mem_root= backup_arena.mem_root;
|
||||
for (i= 0 ; i < argcount ; i++)
|
||||
{
|
||||
sp_pvar_t *pvar = m_pcont->find_pvar(i);
|
||||
|
@ -780,9 +771,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
|
|||
// Partially restore context now.
|
||||
// We still need the call mem root and free list for processing
|
||||
// of the result.
|
||||
call_free_list= thd->free_list;
|
||||
thd->free_list= old_free_list;
|
||||
thd->mem_root= old_mem_root;
|
||||
thd->restore_backup_item_arena(&call_arena, &backup_arena);
|
||||
|
||||
if (m_type == TYPE_ENUM_FUNCTION && ret == 0)
|
||||
{
|
||||
|
@ -802,8 +791,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
|
|||
thd->spcont= octx;
|
||||
|
||||
// Now get rid of the rest of the callee context
|
||||
cleanup_items(call_free_list);
|
||||
free_items(call_free_list);
|
||||
call_arena.free_items();
|
||||
free_root(&call_mem_root, MYF(0));
|
||||
|
||||
DBUG_RETURN(ret);
|
||||
|
@ -835,8 +823,8 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
|
|||
sp_rcontext *octx = thd->spcont;
|
||||
sp_rcontext *nctx = NULL;
|
||||
my_bool tmp_octx = FALSE; // True if we have allocated a temporary octx
|
||||
MEM_ROOT *old_mem_root, call_mem_root;
|
||||
Item *old_free_list, *call_free_list;
|
||||
MEM_ROOT call_mem_root;
|
||||
Query_arena call_arena(&call_mem_root, INITIALIZED_FOR_SP), backup_arena;
|
||||
|
||||
if (args->elements != params)
|
||||
{
|
||||
|
@ -846,10 +834,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
|
|||
}
|
||||
|
||||
init_alloc_root(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0);
|
||||
old_mem_root= thd->mem_root;
|
||||
thd->mem_root= &call_mem_root;
|
||||
old_free_list= thd->free_list; // Keep the old list
|
||||
thd->free_list= NULL; // Start a new one
|
||||
thd->set_n_backup_item_arena(&call_arena, &backup_arena);
|
||||
|
||||
if (csize > 0 || hmax > 0 || cmax > 0)
|
||||
{
|
||||
|
@ -919,9 +904,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
|
|||
// Partially restore context now.
|
||||
// We still need the call mem root and free list for processing
|
||||
// of out parameters.
|
||||
call_free_list= thd->free_list;
|
||||
thd->free_list= old_free_list;
|
||||
thd->mem_root= old_mem_root;
|
||||
thd->restore_backup_item_arena(&call_arena, &backup_arena);
|
||||
|
||||
if (!ret && csize > 0)
|
||||
{
|
||||
|
@ -996,8 +979,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
|
|||
thd->spcont= octx;
|
||||
|
||||
// Now get rid of the rest of the callee context
|
||||
cleanup_items(call_free_list);
|
||||
free_items(call_free_list);
|
||||
call_arena.free_items();
|
||||
thd->lex->unit.cleanup();
|
||||
free_root(&call_mem_root, MYF(0));
|
||||
|
||||
|
@ -1291,6 +1273,13 @@ void sp_head::add_instr(sp_instr *instr)
|
|||
{
|
||||
instr->free_list= m_thd->free_list;
|
||||
m_thd->free_list= 0;
|
||||
/*
|
||||
Memory root of every instruction is designated for permanent
|
||||
transformations (optimizations) made on the parsed tree during
|
||||
the first execution. It points to the memory root of the
|
||||
entire stored procedure, as their life span is equal.
|
||||
*/
|
||||
instr->mem_root= &main_mem_root;
|
||||
insert_dynamic(&m_instr, (gptr)&instr);
|
||||
}
|
||||
|
||||
|
|
|
@ -274,7 +274,7 @@ private:
|
|||
// "Instructions"...
|
||||
//
|
||||
|
||||
class sp_instr : public Sql_alloc
|
||||
class sp_instr :public Query_arena, public Sql_alloc
|
||||
{
|
||||
sp_instr(const sp_instr &); /* Prevent use of these */
|
||||
void operator=(sp_instr &);
|
||||
|
@ -282,17 +282,16 @@ class sp_instr : public Sql_alloc
|
|||
public:
|
||||
|
||||
uint marked;
|
||||
Item *free_list; // My Items
|
||||
uint m_ip; // My index
|
||||
sp_pcontext *m_ctx; // My parse context
|
||||
|
||||
// Should give each a name or type code for debugging purposes?
|
||||
sp_instr(uint ip, sp_pcontext *ctx)
|
||||
:Sql_alloc(), marked(0), free_list(0), m_ip(ip), m_ctx(ctx)
|
||||
:Query_arena(0, INITIALIZED_FOR_SP), marked(0), m_ip(ip), m_ctx(ctx)
|
||||
{}
|
||||
|
||||
virtual ~sp_instr()
|
||||
{ free_items(free_list); }
|
||||
{ free_items(); }
|
||||
|
||||
// Execute this instrution. '*nextp' will be set to the index of the next
|
||||
// instruction to execute. (For most instruction this will be the
|
||||
|
|
|
@ -171,9 +171,6 @@ THD::THD()
|
|||
spcont(NULL)
|
||||
{
|
||||
current_arena= this;
|
||||
#ifndef DBUG_OFF
|
||||
backup_arena= 0;
|
||||
#endif
|
||||
host= user= priv_user= db= ip= 0;
|
||||
catalog= (char*)"std"; // the only catalog we have for now
|
||||
host_or_ip= "connecting host";
|
||||
|
@ -528,7 +525,7 @@ void THD::cleanup_after_query()
|
|||
next_insert_id= 0;
|
||||
}
|
||||
/* Free Items that were created during this execution */
|
||||
free_items(free_list);
|
||||
free_items();
|
||||
/*
|
||||
In the rest of code we assume that free_list never points to garbage:
|
||||
Keep this predicate true.
|
||||
|
@ -1485,6 +1482,21 @@ Query_arena::Type Query_arena::type() const
|
|||
}
|
||||
|
||||
|
||||
void Query_arena::free_items()
|
||||
{
|
||||
Item *next;
|
||||
DBUG_ENTER("Query_arena::free_items");
|
||||
/* This works because items are allocated with sql_alloc() */
|
||||
for (; free_list; free_list= next)
|
||||
{
|
||||
next= free_list->next;
|
||||
free_list->delete_self();
|
||||
}
|
||||
/* Postcondition: free_list is 0 */
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Statement functions
|
||||
*/
|
||||
|
@ -1556,11 +1568,11 @@ void THD::end_statement()
|
|||
void Query_arena::set_n_backup_item_arena(Query_arena *set, Query_arena *backup)
|
||||
{
|
||||
DBUG_ENTER("Query_arena::set_n_backup_item_arena");
|
||||
DBUG_ASSERT(backup_arena == 0);
|
||||
DBUG_ASSERT(backup->is_backup_arena == FALSE);
|
||||
backup->set_item_arena(this);
|
||||
set_item_arena(set);
|
||||
#ifndef DBUG_OFF
|
||||
backup_arena= 1;
|
||||
backup->is_backup_arena= TRUE;
|
||||
#endif
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
@ -1569,10 +1581,11 @@ void Query_arena::set_n_backup_item_arena(Query_arena *set, Query_arena *backup)
|
|||
void Query_arena::restore_backup_item_arena(Query_arena *set, Query_arena *backup)
|
||||
{
|
||||
DBUG_ENTER("Query_arena::restore_backup_item_arena");
|
||||
DBUG_ASSERT(backup->is_backup_arena);
|
||||
set->set_item_arena(this);
|
||||
set_item_arena(backup);
|
||||
#ifndef DBUG_OFF
|
||||
backup_arena= 0;
|
||||
backup->is_backup_arena= FALSE;
|
||||
#endif
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
|
|
@ -663,7 +663,10 @@ public:
|
|||
Item *free_list;
|
||||
MEM_ROOT *mem_root; // Pointer to current memroot
|
||||
#ifndef DBUG_OFF
|
||||
bool backup_arena;
|
||||
bool is_backup_arena; /* True if this arena is used for backup. */
|
||||
#define INIT_ARENA_DBUG_INFO is_backup_arena= 0
|
||||
#else
|
||||
#define INIT_ARENA_DBUG_INFO
|
||||
#endif
|
||||
enum enum_state
|
||||
{
|
||||
|
@ -681,12 +684,14 @@ public:
|
|||
|
||||
Query_arena(MEM_ROOT *mem_root_arg, enum enum_state state_arg) :
|
||||
free_list(0), mem_root(mem_root_arg), state(state_arg)
|
||||
{}
|
||||
{ INIT_ARENA_DBUG_INFO; }
|
||||
/*
|
||||
This constructor is used only when Query_arena is created as
|
||||
backup storage for another instance of Query_arena.
|
||||
*/
|
||||
Query_arena() {};
|
||||
Query_arena() { INIT_ARENA_DBUG_INFO; }
|
||||
|
||||
#undef INIT_ARENA_DBUG_INFO
|
||||
virtual Type type() const;
|
||||
virtual ~Query_arena() {};
|
||||
|
||||
|
@ -726,6 +731,8 @@ public:
|
|||
void set_n_backup_item_arena(Query_arena *set, Query_arena *backup);
|
||||
void restore_backup_item_arena(Query_arena *set, Query_arena *backup);
|
||||
void set_item_arena(Query_arena *set);
|
||||
|
||||
void free_items();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -2429,7 +2429,7 @@ Prepared_statement::~Prepared_statement()
|
|||
{
|
||||
if (cursor)
|
||||
cursor->Cursor::~Cursor();
|
||||
free_items(free_list);
|
||||
free_items();
|
||||
delete lex->result;
|
||||
}
|
||||
|
||||
|
|
|
@ -1914,8 +1914,7 @@ Cursor::close()
|
|||
}
|
||||
join= 0;
|
||||
unit= 0;
|
||||
free_items(free_list);
|
||||
free_list= 0;
|
||||
free_items();
|
||||
/*
|
||||
Must be last, as some memory might be allocated for free purposes,
|
||||
like in free_tmp_table() (TODO: fix this issue)
|
||||
|
|
Loading…
Reference in a new issue