mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge bk-internal.mysql.com:/home/bk/mysql-5.0
into production.mysql.com:/usersnfs/tulin/mysql-5.0
This commit is contained in:
@ -788,7 +788,8 @@ static void die(const char* fmt, ...)
|
|||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
va_end(args);
|
va_end(args);
|
||||||
cleanup();
|
cleanup();
|
||||||
my_end(0);
|
/* We cannot free DBUG, it is used in global destructors after exit(). */
|
||||||
|
my_end(MY_DONT_FREE_DBUG);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1460,7 +1461,8 @@ int main(int argc, char** argv)
|
|||||||
cleanup();
|
cleanup();
|
||||||
free_defaults(defaults_argv);
|
free_defaults(defaults_argv);
|
||||||
my_free_open_file_info();
|
my_free_open_file_info();
|
||||||
my_end(0);
|
/* We cannot free DBUG, it is used in global destructors after exit(). */
|
||||||
|
my_end(MY_DONT_FREE_DBUG);
|
||||||
exit(exit_value);
|
exit(exit_value);
|
||||||
DBUG_RETURN(exit_value); // Keep compilers happy
|
DBUG_RETURN(exit_value); // Keep compilers happy
|
||||||
}
|
}
|
||||||
|
84
dbug/dbug.c
84
dbug/dbug.c
@ -271,6 +271,8 @@ static unsigned long Clock (void);
|
|||||||
static void CloseFile(FILE *fp);
|
static void CloseFile(FILE *fp);
|
||||||
/* Push current debug state */
|
/* Push current debug state */
|
||||||
static void PushState(void);
|
static void PushState(void);
|
||||||
|
/* Free memory associated with debug state. */
|
||||||
|
static void FreeState (struct state *state);
|
||||||
/* Test for tracing enabled */
|
/* Test for tracing enabled */
|
||||||
static BOOLEAN DoTrace(CODE_STATE *state);
|
static BOOLEAN DoTrace(CODE_STATE *state);
|
||||||
/* Test to see if file is writable */
|
/* Test to see if file is writable */
|
||||||
@ -630,22 +632,7 @@ void _db_pop_ ()
|
|||||||
stack = discard -> next_state;
|
stack = discard -> next_state;
|
||||||
_db_fp_ = stack -> out_file;
|
_db_fp_ = stack -> out_file;
|
||||||
_db_pfp_ = stack -> prof_file;
|
_db_pfp_ = stack -> prof_file;
|
||||||
if (discard -> keywords != NULL) {
|
FreeState(discard);
|
||||||
FreeList (discard -> keywords);
|
|
||||||
}
|
|
||||||
if (discard -> functions != NULL) {
|
|
||||||
FreeList (discard -> functions);
|
|
||||||
}
|
|
||||||
if (discard -> processes != NULL) {
|
|
||||||
FreeList (discard -> processes);
|
|
||||||
}
|
|
||||||
if (discard -> p_functions != NULL) {
|
|
||||||
FreeList (discard -> p_functions);
|
|
||||||
}
|
|
||||||
CloseFile (discard -> out_file);
|
|
||||||
if (discard -> prof_file)
|
|
||||||
CloseFile (discard -> prof_file);
|
|
||||||
free ((char *) discard);
|
|
||||||
if (!(stack->flags & DEBUG_ON))
|
if (!(stack->flags & DEBUG_ON))
|
||||||
_db_on_=0;
|
_db_on_=0;
|
||||||
}
|
}
|
||||||
@ -1160,6 +1147,71 @@ static void PushState ()
|
|||||||
stack=new_malloc;
|
stack=new_malloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FUNCTION
|
||||||
|
*
|
||||||
|
* FreeState Free memory associated with a struct state.
|
||||||
|
*
|
||||||
|
* SYNOPSIS
|
||||||
|
*
|
||||||
|
* static void FreeState (state)
|
||||||
|
* struct state *state;
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
*
|
||||||
|
* Deallocates the memory allocated for various information in a
|
||||||
|
* state.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void FreeState (
|
||||||
|
struct state *state)
|
||||||
|
{
|
||||||
|
if (state -> keywords != NULL) {
|
||||||
|
FreeList (state -> keywords);
|
||||||
|
}
|
||||||
|
if (state -> functions != NULL) {
|
||||||
|
FreeList (state -> functions);
|
||||||
|
}
|
||||||
|
if (state -> processes != NULL) {
|
||||||
|
FreeList (state -> processes);
|
||||||
|
}
|
||||||
|
if (state -> p_functions != NULL) {
|
||||||
|
FreeList (state -> p_functions);
|
||||||
|
}
|
||||||
|
CloseFile (state -> out_file);
|
||||||
|
if (state -> prof_file)
|
||||||
|
CloseFile (state -> prof_file);
|
||||||
|
free ((char *) state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FUNCTION
|
||||||
|
*
|
||||||
|
* _db_end_ End debugging, freeing state stack memory.
|
||||||
|
*
|
||||||
|
* SYNOPSIS
|
||||||
|
*
|
||||||
|
* static VOID _db_end_ ()
|
||||||
|
*
|
||||||
|
* DESCRIPTION
|
||||||
|
*
|
||||||
|
* Ends debugging, de-allocating the memory allocated to the
|
||||||
|
* state stack.
|
||||||
|
*
|
||||||
|
* To be called at the very end of the program.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void _db_end_ ()
|
||||||
|
{
|
||||||
|
reg1 struct state *discard;
|
||||||
|
while((discard= stack) != NULL) {
|
||||||
|
stack= discard -> next_state;
|
||||||
|
FreeState (discard);
|
||||||
|
}
|
||||||
|
_db_on_=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION
|
* FUNCTION
|
||||||
|
@ -40,6 +40,7 @@ extern void _db_doprnt_ _VARARGS((const char *format,...));
|
|||||||
extern void _db_dump_(uint _line_,const char *keyword,const char *memory,
|
extern void _db_dump_(uint _line_,const char *keyword,const char *memory,
|
||||||
uint length);
|
uint length);
|
||||||
extern void _db_output_(uint flag);
|
extern void _db_output_(uint flag);
|
||||||
|
extern void _db_end_(void);
|
||||||
extern void _db_lock_file(void);
|
extern void _db_lock_file(void);
|
||||||
extern void _db_unlock_file(void);
|
extern void _db_unlock_file(void);
|
||||||
|
|
||||||
@ -66,6 +67,7 @@ extern void _db_unlock_file(void);
|
|||||||
#define DBUG_IN_USE (_db_fp_ && _db_fp_ != stderr)
|
#define DBUG_IN_USE (_db_fp_ && _db_fp_ != stderr)
|
||||||
#define DEBUGGER_OFF _no_db_=1;_db_on_=0;
|
#define DEBUGGER_OFF _no_db_=1;_db_on_=0;
|
||||||
#define DEBUGGER_ON _no_db_=0
|
#define DEBUGGER_ON _no_db_=0
|
||||||
|
#define DBUG_END() _db_end_ ()
|
||||||
#define DBUG_LOCK_FILE { _db_lock_file(); }
|
#define DBUG_LOCK_FILE { _db_lock_file(); }
|
||||||
#define DBUG_UNLOCK_FILE { _db_unlock_file(); }
|
#define DBUG_UNLOCK_FILE { _db_unlock_file(); }
|
||||||
#define DBUG_OUTPUT(A) { _db_output_(A); }
|
#define DBUG_OUTPUT(A) { _db_output_(A); }
|
||||||
@ -90,6 +92,7 @@ extern void _db_unlock_file(void);
|
|||||||
#define DBUG_IN_USE 0
|
#define DBUG_IN_USE 0
|
||||||
#define DEBUGGER_OFF
|
#define DEBUGGER_OFF
|
||||||
#define DEBUGGER_ON
|
#define DEBUGGER_ON
|
||||||
|
#define DBUG_END()
|
||||||
#define DBUG_LOCK_FILE
|
#define DBUG_LOCK_FILE
|
||||||
#define DBUG_UNLOCK_FILE
|
#define DBUG_UNLOCK_FILE
|
||||||
#define DBUG_OUTPUT(A)
|
#define DBUG_OUTPUT(A)
|
||||||
|
@ -75,6 +75,7 @@ extern int NEAR my_errno; /* Last error in mysys */
|
|||||||
|
|
||||||
#define MY_CHECK_ERROR 1 /* Params to my_end; Check open-close */
|
#define MY_CHECK_ERROR 1 /* Params to my_end; Check open-close */
|
||||||
#define MY_GIVE_INFO 2 /* Give time info about process*/
|
#define MY_GIVE_INFO 2 /* Give time info about process*/
|
||||||
|
#define MY_DONT_FREE_DBUG 4 /* Do not call DBUG_END() in my_end() */
|
||||||
|
|
||||||
#define ME_HIGHBYTE 8 /* Shift for colours */
|
#define ME_HIGHBYTE 8 /* Shift for colours */
|
||||||
#define ME_NOCUR 1 /* Don't use curses message */
|
#define ME_NOCUR 1 /* Don't use curses message */
|
||||||
|
@ -178,7 +178,7 @@ void STDCALL mysql_server_end()
|
|||||||
/* If library called my_init(), free memory allocated by it */
|
/* If library called my_init(), free memory allocated by it */
|
||||||
if (!org_my_init_done)
|
if (!org_my_init_done)
|
||||||
{
|
{
|
||||||
my_end(0);
|
my_end(MY_DONT_FREE_DBUG);
|
||||||
#ifndef THREAD
|
#ifndef THREAD
|
||||||
/* Remove TRACING, if enabled by mysql_debug() */
|
/* Remove TRACING, if enabled by mysql_debug() */
|
||||||
DBUG_POP();
|
DBUG_POP();
|
||||||
|
@ -326,3 +326,20 @@ deallocate prepare s;
|
|||||||
set @str=NULL;
|
set @str=NULL;
|
||||||
drop table t2;
|
drop table t2;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
create table t1 (
|
||||||
|
some_id smallint(5) unsigned,
|
||||||
|
key (some_id)
|
||||||
|
);
|
||||||
|
insert into t1 values (1),(2);
|
||||||
|
select some_id from t1 where some_id not in(2,-1);
|
||||||
|
some_id
|
||||||
|
1
|
||||||
|
select some_id from t1 where some_id not in(-4,-1,-4);
|
||||||
|
some_id
|
||||||
|
1
|
||||||
|
2
|
||||||
|
select some_id from t1 where some_id not in(-4,-1,3423534,2342342);
|
||||||
|
some_id
|
||||||
|
1
|
||||||
|
2
|
||||||
|
drop table t1;
|
||||||
|
@ -220,3 +220,15 @@ set @str=NULL;
|
|||||||
drop table t2;
|
drop table t2;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
# BUG#19618: Crash in range optimizer for
|
||||||
|
# "unsigned_keypart NOT IN(negative_number,...)"
|
||||||
|
# (introduced in fix BUG#15872)
|
||||||
|
create table t1 (
|
||||||
|
some_id smallint(5) unsigned,
|
||||||
|
key (some_id)
|
||||||
|
);
|
||||||
|
insert into t1 values (1),(2);
|
||||||
|
select some_id from t1 where some_id not in(2,-1);
|
||||||
|
select some_id from t1 where some_id not in(-4,-1,-4);
|
||||||
|
select some_id from t1 where some_id not in(-4,-1,3423534,2342342);
|
||||||
|
drop table t1;
|
||||||
|
@ -192,7 +192,7 @@ drop table t1;
|
|||||||
#
|
#
|
||||||
#14157: utf8 encoding in binlog without set character_set_client
|
#14157: utf8 encoding in binlog without set character_set_client
|
||||||
#
|
#
|
||||||
--exec $MYSQL --character-sets-dir=../sql/share/charsets/ --default-character-set=koi8r test -e 'create table t1 (a int); set names koi8r; create temporary table `<60><><EFBFBD><EFBFBD>` (a int); insert into `<60><><EFBFBD><EFBFBD>` values (1); insert into t1 select * from `<60><><EFBFBD><EFBFBD>`'
|
--exec $MYSQL --character-sets-dir=../sql/share/charsets/ --default-character-set=latin1 test -e 'create table t1 (a int); set names latin1; create temporary table `<60><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>` (a int); insert into `<60><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>` values (1); insert into t1 select * from `<60><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>`'
|
||||||
|
|
||||||
sync_slave_with_master;
|
sync_slave_with_master;
|
||||||
#connection slave;
|
#connection slave;
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
fun:calloc
|
fun:calloc
|
||||||
fun:_dl_allocate_tls
|
fun:_dl_allocate_tls
|
||||||
fun:allocate_stack
|
fun:allocate_stack
|
||||||
fun:pthread_create@@GLIBC_2.1
|
fun:pthread_create*
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -33,15 +33,6 @@
|
|||||||
fun:pthread_create*
|
fun:pthread_create*
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
pthread allocate_dtv memory loss second
|
|
||||||
Memcheck:Leak
|
|
||||||
fun:calloc
|
|
||||||
fun:allocate_dtv
|
|
||||||
fun:_dl_allocate_tls
|
|
||||||
fun:pthread_create*
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
pthread memalign memory loss
|
pthread memalign memory loss
|
||||||
Memcheck:Leak
|
Memcheck:Leak
|
||||||
@ -72,17 +63,6 @@
|
|||||||
obj:/lib/ld-*.so
|
obj:/lib/ld-*.so
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
pthread strstr uninit
|
|
||||||
Memcheck:Cond
|
|
||||||
fun:strstr
|
|
||||||
obj:/lib/tls/libpthread.so.*
|
|
||||||
obj:/lib/tls/libpthread.so.*
|
|
||||||
fun:call_init
|
|
||||||
fun:_dl_init
|
|
||||||
obj:/lib/ld-*.so
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
pthread errno
|
pthread errno
|
||||||
Memcheck:Leak
|
Memcheck:Leak
|
||||||
@ -152,3 +132,163 @@
|
|||||||
obj:*/libz.so.*
|
obj:*/libz.so.*
|
||||||
fun:gzflush
|
fun:gzflush
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Leaks reported in _dl_* internal functions on Linux amd64 / glibc2.3.2.
|
||||||
|
#
|
||||||
|
|
||||||
|
{
|
||||||
|
_dl_start invalid write8
|
||||||
|
Memcheck:Addr8
|
||||||
|
fun:_dl_start
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
_dl_start invalid write4
|
||||||
|
Memcheck:Addr4
|
||||||
|
fun:_dl_start
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
_dl_start/_dl_setup_hash invalid read8
|
||||||
|
Memcheck:Addr8
|
||||||
|
fun:_dl_setup_hash
|
||||||
|
fun:_dl_start
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
_dl_sysdep_start invalid write8
|
||||||
|
Memcheck:Addr8
|
||||||
|
fun:_dl_sysdep_start
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
_dl_init invalid write8
|
||||||
|
Memcheck:Addr8
|
||||||
|
fun:_dl_init
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
_dl_init invalid write4
|
||||||
|
Memcheck:Addr4
|
||||||
|
fun:_dl_init
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
_dl_init/_dl_init invalid read8
|
||||||
|
Memcheck:Addr8
|
||||||
|
fun:_dl_debug_initialize
|
||||||
|
fun:_dl_init
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
_dl_init/_dl_debug_state invalid read8
|
||||||
|
Memcheck:Addr8
|
||||||
|
fun:_dl_debug_state
|
||||||
|
fun:_dl_init
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
init invalid write8
|
||||||
|
Memcheck:Addr8
|
||||||
|
fun:init
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fixup invalid write8
|
||||||
|
Memcheck:Addr8
|
||||||
|
fun:fixup
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fixup/_dl_lookup_versioned_symbol invalid read8
|
||||||
|
Memcheck:Addr8
|
||||||
|
fun:_dl_lookup_versioned_symbol
|
||||||
|
fun:fixup
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
_dl_runtime_resolve invalid read8
|
||||||
|
Memcheck:Addr8
|
||||||
|
fun:_dl_runtime_resolve
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
__libc_start_main invalid write8
|
||||||
|
Memcheck:Addr8
|
||||||
|
fun:__libc_start_main
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
__libc_start_main/__sigjmp_save invalid write4
|
||||||
|
Memcheck:Addr4
|
||||||
|
fun:__sigjmp_save
|
||||||
|
fun:__libc_start_main
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# These seem to be libc threading stuff, not related to MySQL code (allocations
|
||||||
|
# during pthread_exit()). Googling shows other projects also using these
|
||||||
|
# suppressions.
|
||||||
|
#
|
||||||
|
# Note that these all stem from pthread_exit() deeper in the call stack, but
|
||||||
|
# Valgrind only allows the top four calls in the suppressions.
|
||||||
|
#
|
||||||
|
|
||||||
|
{
|
||||||
|
libc pthread_exit 1
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:_dl_new_object
|
||||||
|
fun:_dl_map_object_from_fd
|
||||||
|
fun:_dl_map_object
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
libc pthread_exit 2
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:_dl_map_object
|
||||||
|
fun:dl_open_worker
|
||||||
|
fun:_dl_catch_error
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
libc pthread_exit 3
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:_dl_map_object_deps
|
||||||
|
fun:dl_open_worker
|
||||||
|
fun:_dl_catch_error
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
libc pthread_exit 4
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:calloc
|
||||||
|
fun:_dl_check_map_versions
|
||||||
|
fun:dl_open_worker
|
||||||
|
fun:_dl_catch_error
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
libc pthread_exit 5
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:calloc
|
||||||
|
fun:_dl_new_object
|
||||||
|
fun:_dl_map_object_from_fd
|
||||||
|
fun:_dl_map_object
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# This is seen internally in the system libraries on 64-bit RHAS3.
|
||||||
|
#
|
||||||
|
|
||||||
|
{
|
||||||
|
__lll_mutex_unlock_wake uninitialized
|
||||||
|
Memcheck:Param
|
||||||
|
futex(utime)
|
||||||
|
fun:__lll_mutex_unlock_wake
|
||||||
|
}
|
||||||
|
@ -196,8 +196,10 @@ Voluntary context switches %ld, Involuntary context switches %ld\n",
|
|||||||
_CrtDumpMemoryLeaks();
|
_CrtDumpMemoryLeaks();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(infoflag & MY_DONT_FREE_DBUG))
|
||||||
|
DBUG_END(); /* Must be done before my_thread_end */
|
||||||
#ifdef THREAD
|
#ifdef THREAD
|
||||||
DBUG_POP(); /* Must be done before my_thread_end */
|
|
||||||
my_thread_end();
|
my_thread_end();
|
||||||
my_thread_global_end();
|
my_thread_global_end();
|
||||||
#if defined(SAFE_MUTEX)
|
#if defined(SAFE_MUTEX)
|
||||||
|
@ -1496,6 +1496,7 @@ int Dbtup::interpreterNextLab(Signal* signal,
|
|||||||
// word read. Thus we set the register to be a 32 bit register.
|
// word read. Thus we set the register to be a 32 bit register.
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
TregMemBuffer[theRegister] = 0x50;
|
TregMemBuffer[theRegister] = 0x50;
|
||||||
|
// arithmetic conversion if big-endian
|
||||||
* (Int64*)(TregMemBuffer+theRegister+2) = TregMemBuffer[theRegister+1];
|
* (Int64*)(TregMemBuffer+theRegister+2) = TregMemBuffer[theRegister+1];
|
||||||
} else if (TnoDataRW == 3) {
|
} else if (TnoDataRW == 3) {
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
@ -1554,6 +1555,11 @@ int Dbtup::interpreterNextLab(Signal* signal,
|
|||||||
Tlen = TattrNoOfWords + 1;
|
Tlen = TattrNoOfWords + 1;
|
||||||
if (Toptype == ZUPDATE) {
|
if (Toptype == ZUPDATE) {
|
||||||
if (TattrNoOfWords <= 2) {
|
if (TattrNoOfWords <= 2) {
|
||||||
|
if (TattrNoOfWords == 1) {
|
||||||
|
// arithmetic conversion if big-endian
|
||||||
|
TdataForUpdate[1] = *(Int64*)&TregMemBuffer[theRegister + 2];
|
||||||
|
TdataForUpdate[2] = 0;
|
||||||
|
}
|
||||||
if (TregType == 0) {
|
if (TregType == 0) {
|
||||||
/* --------------------------------------------------------- */
|
/* --------------------------------------------------------- */
|
||||||
// Write a NULL value into the attribute
|
// Write a NULL value into the attribute
|
||||||
|
@ -24,6 +24,7 @@ testOIBasic \
|
|||||||
testOperations \
|
testOperations \
|
||||||
testRestartGci \
|
testRestartGci \
|
||||||
testScan \
|
testScan \
|
||||||
|
testInterpreter \
|
||||||
testScanInterpreter \
|
testScanInterpreter \
|
||||||
testScanPerf \
|
testScanPerf \
|
||||||
testSystemRestart \
|
testSystemRestart \
|
||||||
@ -65,6 +66,7 @@ testOIBasic_SOURCES = testOIBasic.cpp
|
|||||||
testOperations_SOURCES = testOperations.cpp
|
testOperations_SOURCES = testOperations.cpp
|
||||||
testRestartGci_SOURCES = testRestartGci.cpp
|
testRestartGci_SOURCES = testRestartGci.cpp
|
||||||
testScan_SOURCES = testScan.cpp ScanFunctions.hpp
|
testScan_SOURCES = testScan.cpp ScanFunctions.hpp
|
||||||
|
testInterpreter_SOURCES = testInterpreter.cpp
|
||||||
testScanInterpreter_SOURCES = testScanInterpreter.cpp ScanFilter.hpp ScanInterpretTest.hpp
|
testScanInterpreter_SOURCES = testScanInterpreter.cpp ScanFilter.hpp ScanInterpretTest.hpp
|
||||||
testScanPerf_SOURCES = testScanPerf.cpp
|
testScanPerf_SOURCES = testScanPerf.cpp
|
||||||
testSystemRestart_SOURCES = testSystemRestart.cpp
|
testSystemRestart_SOURCES = testSystemRestart.cpp
|
||||||
|
@ -79,46 +79,46 @@ int runTestIncValue32(NDBT_Context* ctx, NDBT_Step* step){
|
|||||||
Ndb* pNdb = GETNDB(step);
|
Ndb* pNdb = GETNDB(step);
|
||||||
|
|
||||||
|
|
||||||
NdbConnection* pTrans = pNdb->startTransaction();
|
NdbConnection* pTrans = pNdb->startTransaction();
|
||||||
if (pTrans == NULL){
|
if (pTrans == NULL){
|
||||||
ERR(pNdb->getNdbError());
|
ERR(pNdb->getNdbError());
|
||||||
return NDBT_FAILED;
|
return NDBT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
NdbOperation* pOp = pTrans->getNdbOperation(pTab->getName());
|
NdbOperation* pOp = pTrans->getNdbOperation(pTab->getName());
|
||||||
if (pOp == NULL) {
|
if (pOp == NULL) {
|
||||||
ERR(pTrans->getNdbError());
|
ERR(pTrans->getNdbError());
|
||||||
pNdb->closeTransaction(pTrans);
|
pNdb->closeTransaction(pTrans);
|
||||||
return NDBT_FAILED;
|
return NDBT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
int check = pOp->interpretedUpdateTuple();
|
int check = pOp->interpretedUpdateTuple();
|
||||||
if( check == -1 ) {
|
if( check == -1 ) {
|
||||||
ERR(pTrans->getNdbError());
|
ERR(pTrans->getNdbError());
|
||||||
pNdb->closeTransaction(pTrans);
|
pNdb->closeTransaction(pTrans);
|
||||||
return NDBT_FAILED;
|
return NDBT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Primary keys
|
// Primary keys
|
||||||
Uint32 pkVal = 1;
|
Uint32 pkVal = 1;
|
||||||
check = pOp->equal("KOL1", pkVal );
|
check = pOp->equal("KOL1", pkVal );
|
||||||
if( check == -1 ) {
|
if( check == -1 ) {
|
||||||
ERR(pTrans->getNdbError());
|
ERR(pTrans->getNdbError());
|
||||||
pNdb->closeTransaction(pTrans);
|
pNdb->closeTransaction(pTrans);
|
||||||
return NDBT_FAILED;
|
return NDBT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attributes
|
// Attributes
|
||||||
|
|
||||||
// Update column
|
// Update column
|
||||||
Uint32 valToIncWith = 1;
|
Uint32 valToIncWith = 1;
|
||||||
check = pOp->incValue("KOL2", valToIncWith);
|
check = pOp->incValue("KOL2", valToIncWith);
|
||||||
if( check == -1 ) {
|
if( check == -1 ) {
|
||||||
ERR(pTrans->getNdbError());
|
ERR(pTrans->getNdbError());
|
||||||
pNdb->closeTransaction(pTrans);
|
pNdb->closeTransaction(pTrans);
|
||||||
return NDBT_FAILED;
|
return NDBT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
NdbRecAttr* valueRec = pOp->getValue("KOL2");
|
NdbRecAttr* valueRec = pOp->getValue("KOL2");
|
||||||
if( valueRec == NULL ) {
|
if( valueRec == NULL ) {
|
||||||
@ -142,6 +142,122 @@ int runTestIncValue32(NDBT_Context* ctx, NDBT_Step* step){
|
|||||||
return NDBT_OK;
|
return NDBT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int runTestBug19537(NDBT_Context* ctx, NDBT_Step* step){
|
||||||
|
int result = NDBT_OK;
|
||||||
|
const NdbDictionary::Table * pTab = ctx->getTab();
|
||||||
|
Ndb* pNdb = GETNDB(step);
|
||||||
|
|
||||||
|
if (strcmp(pTab->getName(), "T1") != 0) {
|
||||||
|
g_err << "runTestBug19537: skip, table != T1" << endl;
|
||||||
|
return NDBT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NdbConnection* pTrans = pNdb->startTransaction();
|
||||||
|
if (pTrans == NULL){
|
||||||
|
ERR(pNdb->getNdbError());
|
||||||
|
return NDBT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
NdbOperation* pOp = pTrans->getNdbOperation(pTab->getName());
|
||||||
|
if (pOp == NULL) {
|
||||||
|
ERR(pTrans->getNdbError());
|
||||||
|
pNdb->closeTransaction(pTrans);
|
||||||
|
return NDBT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pOp->interpretedUpdateTuple() == -1) {
|
||||||
|
ERR(pOp->getNdbError());
|
||||||
|
pNdb->closeTransaction(pTrans);
|
||||||
|
return NDBT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Primary keys
|
||||||
|
const Uint32 pkVal = 1;
|
||||||
|
if (pOp->equal("KOL1", pkVal) == -1) {
|
||||||
|
ERR(pTrans->getNdbError());
|
||||||
|
pNdb->closeTransaction(pTrans);
|
||||||
|
return NDBT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load 64-bit constant into register 1 and
|
||||||
|
// write from register 1 to 32-bit column KOL2
|
||||||
|
const Uint64 reg_val = 0x0102030405060708ULL;
|
||||||
|
|
||||||
|
const Uint32* reg_ptr32 = (const Uint32*)®_val;
|
||||||
|
if (reg_ptr32[0] == 0x05060708 && reg_ptr32[1] == 0x01020304) {
|
||||||
|
g_err << "runTestBug19537: platform is LITTLE endian" << endl;
|
||||||
|
} else if (reg_ptr32[0] == 0x01020304 && reg_ptr32[1] == 0x05060708) {
|
||||||
|
g_err << "runTestBug19537: platform is BIG endian" << endl;
|
||||||
|
} else {
|
||||||
|
g_err << "runTestBug19537: impossible platform"
|
||||||
|
<< hex << " [0]=" << reg_ptr32[0] << " [1]=" <<reg_ptr32[1] << endl;
|
||||||
|
pNdb->closeTransaction(pTrans);
|
||||||
|
return NDBT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pOp->load_const_u64(1, reg_val) == -1 ||
|
||||||
|
pOp->write_attr("KOL2", 1) == -1) {
|
||||||
|
ERR(pOp->getNdbError());
|
||||||
|
pNdb->closeTransaction(pTrans);
|
||||||
|
return NDBT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pTrans->execute(Commit) == -1) {
|
||||||
|
ERR(pTrans->getNdbError());
|
||||||
|
pNdb->closeTransaction(pTrans);
|
||||||
|
return NDBT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read value via a new transaction
|
||||||
|
|
||||||
|
pTrans = pNdb->startTransaction();
|
||||||
|
if (pTrans == NULL){
|
||||||
|
ERR(pNdb->getNdbError());
|
||||||
|
return NDBT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
pOp = pTrans->getNdbOperation(pTab->getName());
|
||||||
|
if (pOp == NULL) {
|
||||||
|
ERR(pTrans->getNdbError());
|
||||||
|
pNdb->closeTransaction(pTrans);
|
||||||
|
return NDBT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint32 kol2 = 0x09090909;
|
||||||
|
if (pOp->readTuple() == -1 ||
|
||||||
|
pOp->equal("KOL1", pkVal) == -1 ||
|
||||||
|
pOp->getValue("KOL2", (char*)&kol2) == 0) {
|
||||||
|
ERR(pOp->getNdbError());
|
||||||
|
pNdb->closeTransaction(pTrans);
|
||||||
|
return NDBT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pTrans->execute(Commit) == -1) {
|
||||||
|
ERR(pTrans->getNdbError());
|
||||||
|
pNdb->closeTransaction(pTrans);
|
||||||
|
return NDBT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expected conversion as in C - truncate to lower (logical) word
|
||||||
|
|
||||||
|
if (kol2 == 0x01020304) {
|
||||||
|
g_err << "runTestBug19537: the bug manifests itself !" << endl;
|
||||||
|
pNdb->closeTransaction(pTrans);
|
||||||
|
return NDBT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kol2 != 0x05060708) {
|
||||||
|
g_err << "runTestBug19537: impossible KOL2 " << hex << kol2 << endl;
|
||||||
|
pNdb->closeTransaction(pTrans);
|
||||||
|
return NDBT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
pNdb->closeTransaction(pTrans);
|
||||||
|
return NDBT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NDBT_TESTSUITE(testInterpreter);
|
NDBT_TESTSUITE(testInterpreter);
|
||||||
TESTCASE("IncValue32",
|
TESTCASE("IncValue32",
|
||||||
@ -156,6 +272,12 @@ TESTCASE("IncValue64",
|
|||||||
INITIALIZER(runTestIncValue64);
|
INITIALIZER(runTestIncValue64);
|
||||||
FINALIZER(runClearTable);
|
FINALIZER(runClearTable);
|
||||||
}
|
}
|
||||||
|
TESTCASE("Bug19537",
|
||||||
|
"Test big-endian write_attr of 32 bit integer\n"){
|
||||||
|
INITIALIZER(runLoadTable);
|
||||||
|
INITIALIZER(runTestBug19537);
|
||||||
|
FINALIZER(runClearTable);
|
||||||
|
}
|
||||||
#if 0
|
#if 0
|
||||||
TESTCASE("MaxTransactions",
|
TESTCASE("MaxTransactions",
|
||||||
"Start transactions until no more can be created\n"){
|
"Start transactions until no more can be created\n"){
|
||||||
|
@ -5365,7 +5365,7 @@ bool Item_trigger_field::eq(const Item *item, bool binary_cmp) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_trigger_field::set_required_privilege(const bool rw)
|
void Item_trigger_field::set_required_privilege(bool rw)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Require SELECT and UPDATE privilege if this field will be read and
|
Require SELECT and UPDATE privilege if this field will be read and
|
||||||
|
@ -2187,7 +2187,7 @@ public:
|
|||||||
void cleanup();
|
void cleanup();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void set_required_privilege(const bool rw);
|
void set_required_privilege(bool rw);
|
||||||
bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
|
bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -986,6 +986,10 @@ static void __cdecl kill_server(int sig_ptr)
|
|||||||
pthread_join(select_thread, NULL); // wait for main thread
|
pthread_join(select_thread, NULL); // wait for main thread
|
||||||
#endif /* __NETWARE__ */
|
#endif /* __NETWARE__ */
|
||||||
|
|
||||||
|
#if defined(__NETWARE__) || (defined(USE_ONE_SIGNAL_HAND) && !defined(__WIN__) && !defined(OS2))
|
||||||
|
my_thread_end();
|
||||||
|
#endif
|
||||||
|
|
||||||
pthread_exit(0); /* purecov: deadcode */
|
pthread_exit(0); /* purecov: deadcode */
|
||||||
|
|
||||||
#endif /* EMBEDDED_LIBRARY */
|
#endif /* EMBEDDED_LIBRARY */
|
||||||
|
109
sql/opt_range.cc
109
sql/opt_range.cc
@ -3503,17 +3503,46 @@ static SEL_TREE *get_func_mm_tree(PARAM *param, Item_func *cond_func,
|
|||||||
|
|
||||||
if (inv)
|
if (inv)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
We get here for conditions like "t.keypart NOT IN (....)".
|
|
||||||
|
|
||||||
If the IN-list contains only constants (and func->array is an ordered
|
|
||||||
array of them), we construct the appropriate SEL_ARG tree manually,
|
|
||||||
because constructing it using the range analyzer (as
|
|
||||||
AND_i( t.keypart != c_i)) will cause lots of memory to be consumed
|
|
||||||
(see BUG#15872).
|
|
||||||
*/
|
|
||||||
if (func->array && func->cmp_type != ROW_RESULT)
|
if (func->array && func->cmp_type != ROW_RESULT)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
We get here for conditions in form "t.key NOT IN (c1, c2, ...)"
|
||||||
|
(where c{i} are constants).
|
||||||
|
Our goal is to produce a SEL_ARG graph that represents intervals:
|
||||||
|
|
||||||
|
($MIN<t.key<c1) OR (c1<t.key<c2) OR (c2<t.key<c3) OR ... (*)
|
||||||
|
|
||||||
|
where $MIN is either "-inf" or NULL.
|
||||||
|
|
||||||
|
The most straightforward way to handle NOT IN would be to convert
|
||||||
|
it to "(t.key != c1) AND (t.key != c2) AND ..." and let the range
|
||||||
|
optimizer to build SEL_ARG graph from that. However that will cause
|
||||||
|
the range optimizer to use O(N^2) memory (it's a bug, not filed),
|
||||||
|
and people do use big NOT IN lists (see BUG#15872). Also, for big
|
||||||
|
NOT IN lists constructing/using graph (*) does not make the query
|
||||||
|
faster.
|
||||||
|
|
||||||
|
So, we will handle NOT IN manually in the following way:
|
||||||
|
* if the number of entries in the NOT IN list is less then
|
||||||
|
NOT_IN_IGNORE_THRESHOLD, we will construct SEL_ARG graph (*)
|
||||||
|
manually.
|
||||||
|
* Otherwise, we will construct a smaller graph: for
|
||||||
|
"t.key NOT IN (c1,...cN)" we construct a graph representing
|
||||||
|
($MIN < t.key) OR (cN < t.key) // here sequence of c_i is
|
||||||
|
// ordered.
|
||||||
|
|
||||||
|
A note about partially-covering indexes: for those (e.g. for
|
||||||
|
"a CHAR(10), KEY(a(5))") the handling is correct (albeit not very
|
||||||
|
efficient):
|
||||||
|
Instead of "t.key < c1" we get "t.key <= prefix-val(c1)".
|
||||||
|
Combining the intervals in (*) together, we get:
|
||||||
|
(-inf<=t.key<=c1) OR (c1<=t.key<=c2) OR (c2<=t.key<=c3) OR ...
|
||||||
|
i.e. actually we get intervals combined into one interval:
|
||||||
|
(-inf<=t.key<=+inf). This doesn't make much sense but it doesn't
|
||||||
|
cause any problems.
|
||||||
|
*/
|
||||||
|
MEM_ROOT *tmp_root= param->mem_root;
|
||||||
|
param->thd->mem_root= param->old_root;
|
||||||
/*
|
/*
|
||||||
Create one Item_type constant object. We'll need it as
|
Create one Item_type constant object. We'll need it as
|
||||||
get_mm_parts only accepts constant values wrapped in Item_Type
|
get_mm_parts only accepts constant values wrapped in Item_Type
|
||||||
@ -3522,25 +3551,35 @@ static SEL_TREE *get_func_mm_tree(PARAM *param, Item_func *cond_func,
|
|||||||
per-statement mem_root (while thd->mem_root is currently pointing
|
per-statement mem_root (while thd->mem_root is currently pointing
|
||||||
to mem_root local to range optimizer).
|
to mem_root local to range optimizer).
|
||||||
*/
|
*/
|
||||||
MEM_ROOT *tmp_root= param->mem_root;
|
|
||||||
param->thd->mem_root= param->old_root;
|
|
||||||
Item *value_item= func->array->create_item();
|
Item *value_item= func->array->create_item();
|
||||||
param->thd->mem_root= tmp_root;
|
param->thd->mem_root= tmp_root;
|
||||||
|
|
||||||
if (!value_item)
|
if (!value_item)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Get a SEL_TREE for "-inf < X < c_0" interval */
|
/* Get a SEL_TREE for "(-inf|NULL) < X < c_0" interval. */
|
||||||
func->array->value_to_item(0, value_item);
|
uint i=0;
|
||||||
tree= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC,
|
do
|
||||||
value_item, cmp_type);
|
{
|
||||||
if (!tree)
|
func->array->value_to_item(i, value_item);
|
||||||
|
tree= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC,
|
||||||
|
value_item, cmp_type);
|
||||||
|
if (!tree)
|
||||||
|
break;
|
||||||
|
i++;
|
||||||
|
} while (i < func->array->count && tree->type == SEL_TREE::IMPOSSIBLE);
|
||||||
|
|
||||||
|
if (!tree || tree->type == SEL_TREE::IMPOSSIBLE)
|
||||||
|
{
|
||||||
|
/* We get here in cases like "t.unsigned NOT IN (-1,-2,-3) */
|
||||||
|
tree= NULL;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
#define NOT_IN_IGNORE_THRESHOLD 1000
|
#define NOT_IN_IGNORE_THRESHOLD 1000
|
||||||
SEL_TREE *tree2;
|
SEL_TREE *tree2;
|
||||||
if (func->array->count < NOT_IN_IGNORE_THRESHOLD)
|
if (func->array->count < NOT_IN_IGNORE_THRESHOLD)
|
||||||
{
|
{
|
||||||
for (uint i=1; i < func->array->count; i++)
|
for (; i < func->array->count; i++)
|
||||||
{
|
{
|
||||||
if (func->array->compare_elems(i, i-1))
|
if (func->array->compare_elems(i, i-1))
|
||||||
{
|
{
|
||||||
@ -3548,32 +3587,44 @@ static SEL_TREE *get_func_mm_tree(PARAM *param, Item_func *cond_func,
|
|||||||
func->array->value_to_item(i, value_item);
|
func->array->value_to_item(i, value_item);
|
||||||
tree2= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC,
|
tree2= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC,
|
||||||
value_item, cmp_type);
|
value_item, cmp_type);
|
||||||
|
if (!tree2)
|
||||||
|
{
|
||||||
|
tree= NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Change all intervals to be "c_{i-1} < X < c_i" */
|
/* Change all intervals to be "c_{i-1} < X < c_i" */
|
||||||
for (uint idx= 0; idx < param->keys; idx++)
|
for (uint idx= 0; idx < param->keys; idx++)
|
||||||
{
|
{
|
||||||
SEL_ARG *new_interval;
|
SEL_ARG *new_interval, *last_val;
|
||||||
if ((new_interval= tree2->keys[idx]))
|
if (((new_interval= tree2->keys[idx])) &&
|
||||||
|
((last_val= tree->keys[idx]->last())))
|
||||||
{
|
{
|
||||||
SEL_ARG *last_val= tree->keys[idx]->last();
|
|
||||||
new_interval->min_value= last_val->max_value;
|
new_interval->min_value= last_val->max_value;
|
||||||
new_interval->min_flag= NEAR_MIN;
|
new_interval->min_flag= NEAR_MIN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
The following doesn't try to allocate memory so no need to
|
||||||
|
check for NULL.
|
||||||
|
*/
|
||||||
tree= tree_or(param, tree, tree2);
|
tree= tree_or(param, tree, tree2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
func->array->value_to_item(func->array->count - 1, value_item);
|
func->array->value_to_item(func->array->count - 1, value_item);
|
||||||
|
|
||||||
/*
|
if (tree && tree->type != SEL_TREE::IMPOSSIBLE)
|
||||||
Get the SEL_TREE for the last "c_last < X < +inf" interval
|
{
|
||||||
(value_item cotains c_last already)
|
/*
|
||||||
*/
|
Get the SEL_TREE for the last "c_last < X < +inf" interval
|
||||||
tree2= get_mm_parts(param, cond_func, field, Item_func::GT_FUNC,
|
(value_item cotains c_last already)
|
||||||
value_item, cmp_type);
|
*/
|
||||||
tree= tree_or(param, tree, tree2);
|
tree2= get_mm_parts(param, cond_func, field, Item_func::GT_FUNC,
|
||||||
|
value_item, cmp_type);
|
||||||
|
tree= tree_or(param, tree, tree2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -6023,20 +6023,21 @@ void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* table privileges */
|
/* table privileges */
|
||||||
|
rw_rdlock(&LOCK_grant);
|
||||||
if (grant->version != grant_version)
|
if (grant->version != grant_version)
|
||||||
{
|
{
|
||||||
rw_rdlock(&LOCK_grant);
|
|
||||||
grant->grant_table=
|
grant->grant_table=
|
||||||
table_hash_search(sctx->host, sctx->ip, db,
|
table_hash_search(sctx->host, sctx->ip, db,
|
||||||
sctx->priv_user,
|
sctx->priv_user,
|
||||||
table, 0); /* purecov: inspected */
|
table, 0); /* purecov: inspected */
|
||||||
grant->version= grant_version; /* purecov: inspected */
|
grant->version= grant_version; /* purecov: inspected */
|
||||||
rw_unlock(&LOCK_grant);
|
|
||||||
}
|
}
|
||||||
if (grant->grant_table != 0)
|
if (grant->grant_table != 0)
|
||||||
{
|
{
|
||||||
grant->privilege|= grant->grant_table->privs;
|
grant->privilege|= grant->grant_table->privs;
|
||||||
}
|
}
|
||||||
|
rw_unlock(&LOCK_grant);
|
||||||
|
|
||||||
DBUG_PRINT("info", ("privilege 0x%lx", grant->privilege));
|
DBUG_PRINT("info", ("privilege 0x%lx", grant->privilege));
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user