Commit 51e5344d authored by Sinisa@sinisa.nasamreza.org's avatar Sinisa@sinisa.nasamreza.org

Merge sinisa@bk-internal.mysql.com:/home/bk/mysql-4.0

into sinisa.nasamreza.org:/mnt/work/mysql-4.0
parents e68fba32 fef194fc
...@@ -919,7 +919,6 @@ void _db_doprnt_ (const char *format,...) ...@@ -919,7 +919,6 @@ void _db_doprnt_ (const char *format,...)
} }
(void) fprintf (_db_fp_, "%s: ", state->u_keyword); (void) fprintf (_db_fp_, "%s: ", state->u_keyword);
(void) vfprintf (_db_fp_, format, args); (void) vfprintf (_db_fp_, format, args);
va_end(args);
(void) fputc('\n',_db_fp_); (void) fputc('\n',_db_fp_);
dbug_flush(state); dbug_flush(state);
errno=save_errno; errno=save_errno;
......
...@@ -35,6 +35,14 @@ static void setup_key_functions(MI_KEYDEF *keyinfo); ...@@ -35,6 +35,14 @@ static void setup_key_functions(MI_KEYDEF *keyinfo);
pos+=size;} pos+=size;}
#define disk_pos_assert(pos, end_pos) \
if (pos > end_pos) \
{ \
my_errno=HA_ERR_CRASHED; \
goto err; \
}
/****************************************************************************** /******************************************************************************
** Return the shared struct if the table is already open. ** Return the shared struct if the table is already open.
** In MySQL the server will handle version issues. ** In MySQL the server will handle version issues.
...@@ -70,7 +78,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -70,7 +78,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
key_parts,unique_key_parts,tmp_length,uniques; key_parts,unique_key_parts,tmp_length,uniques;
char name_buff[FN_REFLEN], org_name [FN_REFLEN], index_name[FN_REFLEN], char name_buff[FN_REFLEN], org_name [FN_REFLEN], index_name[FN_REFLEN],
data_name[FN_REFLEN]; data_name[FN_REFLEN];
char *disk_cache,*disk_pos; char *disk_cache, *disk_pos, *end_pos;
MI_INFO info,*m_info,*old_info; MI_INFO info,*m_info,*old_info;
MYISAM_SHARE share_buff,*share; MYISAM_SHARE share_buff,*share;
ulong rec_per_key_part[MI_MAX_POSSIBLE_KEY*MI_MAX_KEY_SEG]; ulong rec_per_key_part[MI_MAX_POSSIBLE_KEY*MI_MAX_KEY_SEG];
...@@ -138,11 +146,12 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -138,11 +146,12 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
info_length=mi_uint2korr(share->state.header.header_length); info_length=mi_uint2korr(share->state.header.header_length);
base_pos=mi_uint2korr(share->state.header.base_pos); base_pos=mi_uint2korr(share->state.header.base_pos);
if (!(disk_cache=(char*) my_alloca(info_length))) if (!(disk_cache=(char*) my_alloca(info_length+128)))
{ {
my_errno=ENOMEM; my_errno=ENOMEM;
goto err; goto err;
} }
end_pos=disk_cache+info_length;
errpos=2; errpos=2;
VOID(my_seek(kfile,0L,MY_SEEK_SET,MYF(0))); VOID(my_seek(kfile,0L,MY_SEEK_SET,MYF(0)));
...@@ -288,6 +297,8 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -288,6 +297,8 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
for (i=0 ; i < keys ; i++) for (i=0 ; i < keys ; i++)
{ {
disk_pos=mi_keydef_read(disk_pos, &share->keyinfo[i]); disk_pos=mi_keydef_read(disk_pos, &share->keyinfo[i]);
disk_pos_assert(disk_pos + share->keyinfo[i].keysegs * MI_KEYSEG_SIZE,
end_pos);
set_if_smaller(share->blocksize,share->keyinfo[i].block_length); set_if_smaller(share->blocksize,share->keyinfo[i].block_length);
share->keyinfo[i].seg=pos; share->keyinfo[i].seg=pos;
for (j=0 ; j < share->keyinfo[i].keysegs; j++,pos++) for (j=0 ; j < share->keyinfo[i].keysegs; j++,pos++)
...@@ -319,6 +330,8 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -319,6 +330,8 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
for (i=0 ; i < uniques ; i++) for (i=0 ; i < uniques ; i++)
{ {
disk_pos=mi_uniquedef_read(disk_pos, &share->uniqueinfo[i]); disk_pos=mi_uniquedef_read(disk_pos, &share->uniqueinfo[i]);
disk_pos_assert(disk_pos + share->uniqueinfo[i].keysegs *
MI_KEYSEG_SIZE, end_pos);
share->uniqueinfo[i].seg=pos; share->uniqueinfo[i].seg=pos;
for (j=0 ; j < share->uniqueinfo[i].keysegs; j++,pos++) for (j=0 ; j < share->uniqueinfo[i].keysegs; j++,pos++)
{ {
...@@ -344,6 +357,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -344,6 +357,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
for (i=0 ; i < keys ; i++) for (i=0 ; i < keys ; i++)
setup_key_functions(share->keyinfo+i); setup_key_functions(share->keyinfo+i);
disk_pos_assert(disk_pos + share->base.fields *MI_COLUMNDEF_SIZE, end_pos);
for (i=j=offset=0 ; i < share->base.fields ; i++) for (i=j=offset=0 ; i < share->base.fields ; i++)
{ {
disk_pos=mi_recinfo_read(disk_pos,&share->rec[i]); disk_pos=mi_recinfo_read(disk_pos,&share->rec[i]);
......
...@@ -330,7 +330,7 @@ while test $# -gt 0; do ...@@ -330,7 +330,7 @@ while test $# -gt 0; do
USE_RUNNING_SERVER="" USE_RUNNING_SERVER=""
;; ;;
--valgrind) --valgrind)
VALGRIND="valgrind --alignment=8 --leak-check=yes" VALGRIND="valgrind --alignment=8 --leak-check=yes --num-callers=16"
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-safemalloc" EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-safemalloc"
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-safemalloc" EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-safemalloc"
SLEEP_TIME_AFTER_RESTART=10 SLEEP_TIME_AFTER_RESTART=10
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "mysys_priv.h" #include "mysys_priv.h"
#include "m_string.h" #include "m_string.h"
#include "m_ctype.h" #include "m_ctype.h"
#include <my_dir.h>
char *defaults_extra_file=0; char *defaults_extra_file=0;
...@@ -61,13 +62,13 @@ DATADIR, ...@@ -61,13 +62,13 @@ DATADIR,
NullS, NullS,
}; };
#define default_ext ".cnf" /* extension for config file */ #define default_ext ".cnf" /* extension for config file */
#ifdef __WIN__ #ifdef __WIN__
#include <winbase.h> #include <winbase.h>
#define windows_ext ".ini" #define windows_ext ".ini"
#endif #endif
static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc, static my_bool search_default_file(DYNAMIC_ARRAY *args,MEM_ROOT *alloc,
const char *dir, const char *config_file, const char *dir, const char *config_file,
const char *ext, TYPELIB *group); const char *ext, TYPELIB *group);
...@@ -242,6 +243,20 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc, ...@@ -242,6 +243,20 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
{ {
strmov(name,config_file); strmov(name,config_file);
} }
fn_format(name,name,"","",4);
#if !defined(__WIN__) && !defined(OS2)
{
MY_STAT stat_info;
if (!my_stat(name,&stat_info,MYF(0)))
return 0;
if (stat_info.st_mode & S_IWOTH) /* ignore world-writeable files */
{
fprintf(stderr, "warning: World-writeable config file %s is ignored\n",
name);
return 0;
}
}
#endif
if (!(fp = my_fopen(fn_format(name,name,"","",4),O_RDONLY,MYF(0)))) if (!(fp = my_fopen(fn_format(name,name,"","",4),O_RDONLY,MYF(0))))
return 0; /* Ignore wrong files */ return 0; /* Ignore wrong files */
......
...@@ -103,7 +103,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) ...@@ -103,7 +103,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
char dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1]; char dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1];
#endif #endif
DBUG_ENTER("my_dir"); DBUG_ENTER("my_dir");
DBUG_PRINT("my",("path: '%s' stat: %d MyFlags: %d",path,MyFlags)); DBUG_PRINT("my",("path: '%s' MyFlags: %d",path,MyFlags));
#if defined(THREAD) && !defined(HAVE_READDIR_R) #if defined(THREAD) && !defined(HAVE_READDIR_R)
pthread_mutex_lock(&THR_LOCK_open); pthread_mutex_lock(&THR_LOCK_open);
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
******************************************************************************/ ******************************************************************************/
char autoclose; char autoclose;
char basedir[PATH_MAX]; char basedir[PATH_MAX];
char checktables;
char datadir[PATH_MAX]; char datadir[PATH_MAX];
char pid_file[PATH_MAX]; char pid_file[PATH_MAX];
char address[PATH_MAX]; char address[PATH_MAX];
...@@ -54,6 +55,7 @@ FILE *log_fd = NULL; ...@@ -54,6 +55,7 @@ FILE *log_fd = NULL;
******************************************************************************/ ******************************************************************************/
void usage(void);
void vlog(char *, va_list); void vlog(char *, va_list);
void log(char *, ...); void log(char *, ...);
void start_defaults(int, char*[]); void start_defaults(int, char*[]);
...@@ -74,6 +76,42 @@ void mysql_start(int, char*[]); ...@@ -74,6 +76,42 @@ void mysql_start(int, char*[]);
/****************************************************************************** /******************************************************************************
usage()
Show usage.
******************************************************************************/
void usage(void)
{
// keep the screen up
setscreenmode(SCR_NO_MODE);
puts("\
\n\
usage: mysqld_safe [options]\n\
\n\
Program to start the MySQL daemon and restart it if it dies unexpectedly.\n\
All options, besides those listed below, are passed on to the MySQL daemon.\n\
\n\
options:\n\
\n\
--autoclose Automatically close the mysqld_safe screen.\n\
\n\
--check-tables Check the tables before starting the MySQL daemon.\n\
\n\
--err-log=<file> Send the MySQL daemon error output to <file>.\n\
\n\
--help Show this help information.\n\
\n\
--mysqld=<file> Use the <file> MySQL daemon.\n\
\n\
");
exit(-1);
}
/******************************************************************************
vlog() vlog()
Log the message. Log the message.
...@@ -136,6 +174,9 @@ void start_defaults(int argc, char *argv[]) ...@@ -136,6 +174,9 @@ void start_defaults(int argc, char *argv[])
// basedir // basedir
get_basedir(argv[0], basedir); get_basedir(argv[0], basedir);
// check-tables
checktables = FALSE;
// hostname // hostname
if (gethostname(hostname,PATH_MAX) < 0) if (gethostname(hostname,PATH_MAX) < 0)
{ {
...@@ -279,13 +320,15 @@ void parse_args(int argc, char *argv[]) ...@@ -279,13 +320,15 @@ void parse_args(int argc, char *argv[])
OPT_PORT, OPT_PORT,
OPT_ERR_LOG, OPT_ERR_LOG,
OPT_SAFE_LOG, OPT_SAFE_LOG,
OPT_MYSQLD OPT_MYSQLD,
OPT_HELP
}; };
static struct option options[] = static struct option options[] =
{ {
{"autoclose", no_argument, &autoclose, TRUE}, {"autoclose", no_argument, &autoclose, TRUE},
{"basedir", required_argument, 0, OPT_BASEDIR}, {"basedir", required_argument, 0, OPT_BASEDIR},
{"check-tables", no_argument, &checktables, TRUE},
{"datadir", required_argument, 0, OPT_DATADIR}, {"datadir", required_argument, 0, OPT_DATADIR},
{"pid-file", required_argument, 0, OPT_PID_FILE}, {"pid-file", required_argument, 0, OPT_PID_FILE},
{"bind-address", required_argument, 0, OPT_BIND_ADDRESS}, {"bind-address", required_argument, 0, OPT_BIND_ADDRESS},
...@@ -293,6 +336,7 @@ void parse_args(int argc, char *argv[]) ...@@ -293,6 +336,7 @@ void parse_args(int argc, char *argv[])
{"err-log", required_argument, 0, OPT_ERR_LOG}, {"err-log", required_argument, 0, OPT_ERR_LOG},
{"safe-log", required_argument, 0, OPT_SAFE_LOG}, {"safe-log", required_argument, 0, OPT_SAFE_LOG},
{"mysqld", required_argument, 0, OPT_MYSQLD}, {"mysqld", required_argument, 0, OPT_MYSQLD},
{"help", no_argument, 0, OPT_HELP},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
...@@ -341,6 +385,10 @@ void parse_args(int argc, char *argv[]) ...@@ -341,6 +385,10 @@ void parse_args(int argc, char *argv[])
strcpy(mysqld, optarg); strcpy(mysqld, optarg);
break; break;
case OPT_HELP:
usage();
break;
default: default:
// ignore // ignore
break; break;
...@@ -563,6 +611,8 @@ void mysql_start(int argc, char *argv[]) ...@@ -563,6 +611,8 @@ void mysql_start(int argc, char *argv[])
static char *private_options[] = static char *private_options[] =
{ {
"--autoclose", "--autoclose",
"--check-tables",
"--help",
"--err-log=", "--err-log=",
"--mysqld=", "--mysqld=",
NULL NULL
...@@ -594,7 +644,7 @@ void mysql_start(int argc, char *argv[]) ...@@ -594,7 +644,7 @@ void mysql_start(int argc, char *argv[])
do do
{ {
// check the database tables // check the database tables
check_tables(); if (checktables) check_tables();
// status // status
time(&cal); time(&cal);
......
...@@ -2421,6 +2421,14 @@ void Field_double::sql_type(String &res) const ...@@ -2421,6 +2421,14 @@ void Field_double::sql_type(String &res) const
** by handler.cc. The form->timestamp points at the automatic timestamp. ** by handler.cc. The form->timestamp points at the automatic timestamp.
****************************************************************************/ ****************************************************************************/
enum Item_result Field_timestamp::result_type() const
{
return (!current_thd->variables.new_mode &&
(field_length == 8 || field_length == 14) ? INT_RESULT :
STRING_RESULT);
}
Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg, Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg,
enum utype unireg_check_arg, enum utype unireg_check_arg,
const char *field_name_arg, const char *field_name_arg,
...@@ -2783,6 +2791,23 @@ void Field_timestamp::set_time() ...@@ -2783,6 +2791,23 @@ void Field_timestamp::set_time()
longstore(ptr,tmp); longstore(ptr,tmp);
} }
/*
This is an exact copy of Field_num except that 'length' is depending
on --new mode
*/
void Field_timestamp::make_field(Send_field *field)
{
field->table_name=table_name;
field->col_name=field_name;
/* If --new, then we are using "YYYY-MM-DD HH:MM:SS" format */
field->length= current_thd->variables.new_mode ? 19 : field_length;
field->type=type();
field->flags=table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags;
field->decimals=dec;
}
/**************************************************************************** /****************************************************************************
** time type ** time type
** In string context: HH:MM:SS ** In string context: HH:MM:SS
......
...@@ -541,7 +541,7 @@ public: ...@@ -541,7 +541,7 @@ public:
Field_timestamp(char *ptr_arg, uint32 len_arg, Field_timestamp(char *ptr_arg, uint32 len_arg,
enum utype unireg_check_arg, const char *field_name_arg, enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg); struct st_table *table_arg);
enum Item_result result_type () const { return field_length == 8 || field_length == 14 ? INT_RESULT : STRING_RESULT; } enum Item_result result_type () const;
enum_field_types type() const { return FIELD_TYPE_TIMESTAMP;} enum_field_types type() const { return FIELD_TYPE_TIMESTAMP;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
void store(const char *to,uint length); void store(const char *to,uint length);
...@@ -575,6 +575,7 @@ public: ...@@ -575,6 +575,7 @@ public:
void fill_and_store(char *from,uint len); void fill_and_store(char *from,uint len);
bool get_date(TIME *ltime,bool fuzzydate); bool get_date(TIME *ltime,bool fuzzydate);
bool get_time(TIME *ltime); bool get_time(TIME *ltime);
void make_field(Send_field *field);
}; };
......
...@@ -4225,7 +4225,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), ...@@ -4225,7 +4225,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
if (!mysqld_user) if (!mysqld_user)
mysqld_user= argument; mysqld_user= argument;
else else
fprintf(stderr, "Warning: Ignoring user change to '%s' becasue the user is set to '%s' earlier on the command line\n", argument, mysqld_user); fprintf(stderr, "Warning: Ignoring user change to '%s' because the user was set to '%s' earlier on the command line\n", argument, mysqld_user);
break; break;
case 'L': case 'L':
strmake(language, argument, sizeof(language)-1); strmake(language, argument, sizeof(language)-1);
......
...@@ -401,9 +401,9 @@ int terminate_slave_threads(MASTER_INFO* mi,int thread_mask,bool skip_lock) ...@@ -401,9 +401,9 @@ int terminate_slave_threads(MASTER_INFO* mi,int thread_mask,bool skip_lock)
DBUG_PRINT("info",("Terminating IO thread")); DBUG_PRINT("info",("Terminating IO thread"));
mi->abort_slave=1; mi->abort_slave=1;
if ((error=terminate_slave_thread(mi->io_thd,io_lock, if ((error=terminate_slave_thread(mi->io_thd,io_lock,
io_cond_lock, io_cond_lock,
&mi->stop_cond, &mi->stop_cond,
&mi->slave_running)) && &mi->slave_running)) &&
!force_all) !force_all)
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -443,12 +443,10 @@ int terminate_slave_thread(THD* thd, pthread_mutex_t* term_lock, ...@@ -443,12 +443,10 @@ int terminate_slave_thread(THD* thd, pthread_mutex_t* term_lock,
be referening freed memory trying to kick it be referening freed memory trying to kick it
*/ */
THD_CHECK_SENTRY(thd); THD_CHECK_SENTRY(thd);
if (*slave_running)
while (*slave_running) // Should always be true
{ {
KICK_SLAVE(thd); KICK_SLAVE(thd);
}
while (*slave_running)
{
/* /*
There is a small chance that slave thread might miss the first There is a small chance that slave thread might miss the first
alarm. To protect againts it, resend the signal until it reacts alarm. To protect againts it, resend the signal until it reacts
...@@ -456,10 +454,6 @@ int terminate_slave_thread(THD* thd, pthread_mutex_t* term_lock, ...@@ -456,10 +454,6 @@ int terminate_slave_thread(THD* thd, pthread_mutex_t* term_lock,
struct timespec abstime; struct timespec abstime;
set_timespec(abstime,2); set_timespec(abstime,2);
pthread_cond_timedwait(term_cond, cond_lock, &abstime); pthread_cond_timedwait(term_cond, cond_lock, &abstime);
if (*slave_running)
{
KICK_SLAVE(thd);
}
} }
if (term_lock) if (term_lock)
pthread_mutex_unlock(term_lock); pthread_mutex_unlock(term_lock);
......
...@@ -419,12 +419,14 @@ CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, long key_length) ...@@ -419,12 +419,14 @@ CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, long key_length)
#ifdef SIGNAL_WITH_VIO_CLOSE #ifdef SIGNAL_WITH_VIO_CLOSE
void THD::close_active_vio() void THD::close_active_vio()
{ {
DBUG_ENTER("close_active_vio");
safe_mutex_assert_owner(&LOCK_delete); safe_mutex_assert_owner(&LOCK_delete);
if (active_vio) if (active_vio)
{ {
vio_close(active_vio); vio_close(active_vio);
active_vio = 0; active_vio = 0;
} }
DBUG_RETURN;
} }
#endif #endif
......
...@@ -139,9 +139,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, ...@@ -139,9 +139,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
*/ */
if ((lock_type == TL_WRITE_DELAYED && if ((lock_type == TL_WRITE_DELAYED &&
((specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) || ((specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) ||
thd->slave_thread)) || thd->slave_thread || !max_insert_delayed_threads)) ||
(lock_type == TL_WRITE_CONCURRENT_INSERT && duplic == DUP_REPLACE) || (lock_type == TL_WRITE_CONCURRENT_INSERT && duplic == DUP_REPLACE))
!max_insert_delayed_threads)
lock_type=TL_WRITE; lock_type=TL_WRITE;
if (lock_type == TL_WRITE_DELAYED) if (lock_type == TL_WRITE_DELAYED)
......
...@@ -1595,6 +1595,7 @@ mysql_execute_command(void) ...@@ -1595,6 +1595,7 @@ mysql_execute_command(void)
for (table = tables->next ; table ; table=table->next) for (table = tables->next ; table ; table=table->next)
table->lock_type= lex->lock_option; table->lock_type= lex->lock_option;
} }
select_lex->options|= SELECT_NO_UNLOCK;
thd->offset_limit=select_lex->offset_limit; thd->offset_limit=select_lex->offset_limit;
thd->select_limit=select_lex->select_limit+select_lex->offset_limit; thd->select_limit=select_lex->select_limit+select_lex->offset_limit;
if (thd->select_limit < select_lex->select_limit) if (thd->select_limit < select_lex->select_limit)
...@@ -1928,6 +1929,8 @@ mysql_execute_command(void) ...@@ -1928,6 +1929,8 @@ mysql_execute_command(void)
if ((res=check_table_access(thd, SELECT_ACL, save_next))) if ((res=check_table_access(thd, SELECT_ACL, save_next)))
goto error; goto error;
} }
/* Don't unlock tables until command is written to binary log */
select_lex->options|= SELECT_NO_UNLOCK;
select_result *result; select_result *result;
thd->offset_limit=select_lex->offset_limit; thd->offset_limit=select_lex->offset_limit;
......
...@@ -4469,7 +4469,11 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure) ...@@ -4469,7 +4469,11 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
error=0; error=0;
if (!table) // If sending data to client if (!table) // If sending data to client
{ {
join_free(join); // Unlock all cursors /*
The following will unlock all cursors if the command wasn't an
update command
*/
join_free(join);
if (join->result->send_eof()) if (join->result->send_eof())
error= 1; // Don't send error error= 1; // Don't send error
} }
......
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