summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xBitKeeper/triggers/post-commit2
-rw-r--r--VC++Files/mysys/mysys.dsp4
-rw-r--r--client/mysqlbinlog.cc27
-rw-r--r--client/mysqldump.c36
-rw-r--r--configure.in4
-rw-r--r--extra/resolveip.c4
-rw-r--r--include/config-win.h4
-rw-r--r--include/my_global.h4
-rw-r--r--include/my_net.h9
-rw-r--r--include/my_pthread.h1
-rw-r--r--include/my_sys.h1
-rw-r--r--include/mysql_com.h2
-rw-r--r--include/mysys_err.h3
-rw-r--r--innobase/os/os0file.c10
-rw-r--r--innobase/row/row0sel.c4
-rw-r--r--innobase/srv/srv0srv.c2
-rw-r--r--innobase/srv/srv0start.c22
-rw-r--r--isam/extra.c10
-rw-r--r--libmysql/manager.c2
-rw-r--r--libmysqld/Makefile.am4
-rw-r--r--myisam/ft_boolean_search.c2
-rw-r--r--myisam/mi_extra.c20
-rw-r--r--myisam/mi_locking.c20
-rw-r--r--myisam/myisamchk.c4
-rw-r--r--mysql-test/mysql-test-run.sh13
-rw-r--r--mysql-test/r/fulltext.result2
-rw-r--r--mysql-test/r/func_crypt.result10
-rw-r--r--mysql-test/r/order_by.result6
-rw-r--r--mysql-test/r/query_cache.result43
-rw-r--r--mysql-test/r/range.result17
-rw-r--r--mysql-test/r/rpl_chain_temp_table.result30
-rw-r--r--mysql-test/r/rpl_reset_slave.result10
-rw-r--r--mysql-test/r/rpl_trunc_binlog.result5
-rw-r--r--mysql-test/r/select.result4
-rw-r--r--mysql-test/t/fulltext.test6
-rw-r--r--mysql-test/t/func_crypt.test12
-rw-r--r--mysql-test/t/query_cache-master.opt1
-rw-r--r--mysql-test/t/query_cache.test53
-rw-r--r--mysql-test/t/range.test25
-rw-r--r--mysql-test/t/rpl_chain_temp_table.test99
-rw-r--r--mysql-test/t/rpl_reset_slave.test18
-rw-r--r--mysql-test/t/rpl_trunc_binlog.test2
-rw-r--r--mysys/Makefile.am2
-rw-r--r--mysys/errors.c8
-rw-r--r--mysys/my_new.cc4
-rw-r--r--mysys/my_sync.c60
-rw-r--r--mysys/my_thr_init.c9
-rw-r--r--mysys/thr_alarm.c7
-rw-r--r--scripts/mysql_install_db.sh2
-rw-r--r--scripts/mysql_secure_installation.sh10
-rw-r--r--scripts/mysqlhotcopy.sh19
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/log_event.cc64
-rw-r--r--sql/log_event.h8
-rw-r--r--sql/mysqld.cc25
-rw-r--r--sql/slave.cc27
-rw-r--r--sql/slave.h2
-rw-r--r--sql/sql_base.cc25
-rw-r--r--sql/sql_cache.cc26
-rw-r--r--sql/sql_class.cc5
-rw-r--r--sql/sql_class.h11
-rw-r--r--sql/sql_parse.cc87
-rw-r--r--sql/sql_select.cc80
-rw-r--r--sql/sql_test.cc4
-rw-r--r--sql/unireg.cc9
-rw-r--r--sql/unireg.h2
-rw-r--r--support-files/mysql.server.sh26
67 files changed, 882 insertions, 199 deletions
diff --git a/BitKeeper/triggers/post-commit b/BitKeeper/triggers/post-commit
index a2a0ecb2701..b0d70c85661 100755
--- a/BitKeeper/triggers/post-commit
+++ b/BitKeeper/triggers/post-commit
@@ -19,7 +19,7 @@ BK_STATUS=$BK_STATUS$BK_COMMIT
if [ "$BK_STATUS" = OK ]
then
-CHANGESET=`bk -R prs -r+ -h -d':I:' ChangeSet`
+CHANGESET=`bk -R prs -r+ -h -d':P:::I:' ChangeSet`
#++
# dev-public@
diff --git a/VC++Files/mysys/mysys.dsp b/VC++Files/mysys/mysys.dsp
index 9f7a6bbf2e9..533d4212e2b 100644
--- a/VC++Files/mysys/mysys.dsp
+++ b/VC++Files/mysys/mysys.dsp
@@ -430,6 +430,10 @@ SOURCE=.\my_symlink2.c
# End Source File
# Begin Source File
+SOURCE=.\my_sync.c
+# End Source File
+# Begin Source File
+
SOURCE=.\my_tempnam.c
# End Source File
# Begin Source File
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 68b7da78bbf..f870c92cb6d 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -52,7 +52,7 @@ static const char* host = 0;
static int port = MYSQL_PORT;
static const char* sock= 0;
static const char* user = 0;
-static const char* pass = "";
+static char* pass = 0;
static ulonglong position = 0;
static short binlog_flags = 0;
static MYSQL* mysql = NULL;
@@ -226,7 +226,7 @@ static struct my_option my_long_options[] =
{"offset", 'o', "Skip the first N entries.", (gptr*) &offset, (gptr*) &offset,
0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"password", 'p', "Password to connect to remote server.",
- 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"port", 'P', "Use port to connect to the remote server.",
(gptr*) &port, (gptr*) &port, 0, GET_INT, REQUIRED_ARG, MYSQL_PORT, 0, 0,
0, 0, 0},
@@ -266,6 +266,11 @@ void sql_print_error(const char *format,...)
va_end(args);
}
+static void cleanup()
+{
+ my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
+}
+
static void die(const char* fmt, ...)
{
va_list args;
@@ -274,6 +279,7 @@ static void die(const char* fmt, ...)
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
+ cleanup();
exit(1);
}
@@ -333,6 +339,7 @@ extern "C" my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
{
+ bool tty_password=0;
switch (optid) {
#ifndef DBUG_OFF
case '#':
@@ -343,7 +350,17 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
one_database = 1;
break;
case 'p':
- pass = my_strdup(argument, MYF(0));
+ if (argument)
+ {
+ my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
+ char *start=argument;
+ pass= my_strdup(argument,MYF(MY_FAE));
+ while (*argument) *argument++= 'x'; /* Destroy argument */
+ if (*start)
+ start[1]=0; /* Cut length of argument */
+ }
+ else
+ tty_password=1;
break;
case 'r':
if (!(result_file = my_fopen(argument, O_WRONLY | O_BINARY, MYF(MY_WME))))
@@ -359,6 +376,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
usage();
exit(0);
}
+ if (tty_password)
+ pass= get_tty_password(NullS);
+
return 0;
}
@@ -707,6 +727,7 @@ int main(int argc, char** argv)
my_fclose(result_file, MYF(0));
if (remote_opt)
mysql_close(mysql);
+ cleanup();
free_defaults(defaults_argv);
my_end(0);
return 0;
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 5e83e7bd043..31305c93e6c 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -632,6 +632,7 @@ static my_bool test_if_special_chars(const char *str)
} /* test_if_special_chars */
+
static char *quote_name(const char *name, char *buff, my_bool force)
{
char *to= buff;
@@ -789,7 +790,8 @@ static uint getTableStructure(char *table, char* db)
if (verbose)
fprintf(stderr, "-- Retrieving table structure for table %s...\n", table);
- sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d", (opt_quoted || opt_keywords));
+ sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d",
+ (opt_quoted || opt_keywords));
result_table= quote_name(table, table_buff, 1);
opt_quoted_table= quote_name(table, table_buff2, 0);
if (!opt_xml && !mysql_query(sock,insert_pat))
@@ -1041,7 +1043,8 @@ static uint getTableStructure(char *table, char* db)
else if (keynr == primary_key)
fputs(",\n PRIMARY KEY (",sql_file); /* First UNIQUE is primary */
else
- fprintf(sql_file, ",\n UNIQUE %s (",quote_name(row[2],name_buff,0));
+ fprintf(sql_file, ",\n UNIQUE %s (",quote_name(row[2],name_buff,
+ 0));
}
else
putc(',', sql_file);
@@ -1520,23 +1523,28 @@ static int init_dumping(char *database)
{
if (opt_databases || opt_alldbs)
{
- fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", database);
+ /*
+ length of table name * 2 (if name contain quotas), 2 quotas and 0
+ */
+ char quoted_database_buf[64*2+3];
+ char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted);
+
+ fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase);
if (!opt_create_db)
{
- char qbuf[128];
+ char qbuf[256];
MYSQL_ROW row;
MYSQL_RES *dbinfo;
- sprintf(qbuf,"SHOW CREATE DATABASE WITH IF NOT EXISTS %s",database);
+ sprintf(qbuf,"SHOW CREATE DATABASE WITH IF NOT EXISTS %s",
+ qdatabase);
if (mysql_query(sock, qbuf) || !(dbinfo = mysql_store_result(sock)))
{
/* Old server version, dump generic CREATE DATABASE */
fprintf(md_result_file,
- "\nCREATE DATABASE /*!32312 IF NOT EXISTS*/ %s%s%s;\n",
- (opt_quoted ? "`" : ""),
- database,
- (opt_quoted ? "`" : ""));
+ "\nCREATE DATABASE /*!32312 IF NOT EXISTS*/ %s;\n",
+ qdatabase);
}
else
{
@@ -1547,18 +1555,16 @@ static int init_dumping(char *database)
}
}
}
- fprintf(md_result_file,"\nUSE %s%s%s;\n", (opt_quoted ? "`" : ""),
- database,
- (opt_quoted ? "`" : ""));
+ fprintf(md_result_file,"\nUSE %s;\n", qdatabase);
}
}
- if (extended_insert)
- if (init_dynamic_string(&extended_row, "", 1024, 1024))
- exit(EX_EOM);
+ if (extended_insert && init_dynamic_string(&extended_row, "", 1024, 1024))
+ exit(EX_EOM);
return 0;
} /* init_dumping */
+
static int dump_all_tables_in_db(char *database)
{
char *table;
diff --git a/configure.in b/configure.in
index 207404a89c5..4b930b45f04 100644
--- a/configure.in
+++ b/configure.in
@@ -731,7 +731,7 @@ AC_CHECK_HEADERS(fcntl.h float.h floatingpoint.h ieeefp.h limits.h \
strings.h string.h synch.h sys/mman.h sys/socket.h netinet/in.h arpa/inet.h \
sys/timeb.h sys/types.h sys/un.h sys/vadvise.h sys/wait.h term.h \
unistd.h utime.h sys/utime.h termio.h termios.h sched.h crypt.h alloca.h \
- sys/ioctl.h)
+ sys/ioctl.h malloc.h sys/malloc.h)
#--------------------------------------------------------------------
# Check for system libraries. Adds the library to $LIBS
@@ -1832,7 +1832,7 @@ AC_CHECK_FUNCS(alarm bmove \
pthread_attr_create pthread_getsequence_np pthread_attr_setstacksize \
pthread_attr_getstacksize \
pthread_condattr_create rwlock_init pthread_rwlock_rdlock \
- fchmod getpass getpassphrase initgroups mlockall)
+ fsync fdatasync fchmod getpass getpassphrase initgroups mlockall)
CFLAGS="$ORG_CFLAGS"
diff --git a/extra/resolveip.c b/extra/resolveip.c
index 12e6977c2ba..f8cff2a976c 100644
--- a/extra/resolveip.c
+++ b/extra/resolveip.c
@@ -36,10 +36,6 @@
extern int h_errno;
#endif
-#ifndef HAVE_IN_ADDR_T
-#define in_addr_t ulong
-#endif
-
static my_bool silent;
static struct my_option my_long_options[] =
diff --git a/include/config-win.h b/include/config-win.h
index 884b2edfb63..4fdbfbbd02f 100644
--- a/include/config-win.h
+++ b/include/config-win.h
@@ -183,8 +183,8 @@ inline double rint(double nr)
}
#ifdef _WIN64
-#define ulonglong2double(A) ((double) (A))
-#define my_off_t2double(A) ((double) (A))
+#define ulonglong2double(A) ((double) (ulonglong) (A))
+#define my_off_t2double(A) ((double) (my_off_t) (A))
#else
inline double ulonglong2double(ulonglong value)
diff --git a/include/my_global.h b/include/my_global.h
index 73287a2ba2a..43cacf8fa65 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -594,8 +594,8 @@ extern double my_atof(const char*);
#define closesocket(A) close(A)
#endif
#ifndef ulonglong2double
-#define ulonglong2double(A) ((double) (A))
-#define my_off_t2double(A) ((double) (A))
+#define ulonglong2double(A) ((double) (ulonglong) (A))
+#define my_off_t2double(A) ((double) (my_off_t) (A))
#endif
#endif
diff --git a/include/my_net.h b/include/my_net.h
index 28d862d8528..7b42afa1f3a 100644
--- a/include/my_net.h
+++ b/include/my_net.h
@@ -63,6 +63,15 @@ C_MODE_START
#define O_NONBLOCK 1 /* For emulation of fcntl() */
#endif
+/*
+ On OSes which don't have the in_addr_t, we guess that using uint32 is the best
+ possible choice. We guess this from the fact that on HP-UX64bit & FreeBSD64bit
+ & Solaris64bit, in_addr_t is equivalent to uint32. And on Linux32bit too.
+*/
+#ifndef HAVE_IN_ADDR_T
+#define in_addr_t uint32
+#endif
+
/* Thread safe or portable version of some functions */
void my_inet_ntoa(struct in_addr in, char *buf);
diff --git a/include/my_pthread.h b/include/my_pthread.h
index 82a2bb1accc..a4ea88b20f0 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -645,6 +645,7 @@ struct st_my_thread_var
long id;
int cmp_length;
int volatile abort;
+ my_bool init;
struct st_my_thread_var *next,**prev;
void *opt_info;
#ifndef DBUG_OFF
diff --git a/include/my_sys.h b/include/my_sys.h
index c404e54c2a9..6082b988822 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -614,6 +614,7 @@ extern FILE *my_fopen(const char *FileName,int Flags,myf MyFlags);
extern FILE *my_fdopen(File Filedes,const char *name, int Flags,myf MyFlags);
extern int my_fclose(FILE *fd,myf MyFlags);
extern int my_chsize(File fd,my_off_t newlength, int filler, myf MyFlags);
+extern int my_sync(File fd, myf my_flags);
extern int my_error _VARARGS((int nr,myf MyFlags, ...));
extern int my_printf_error _VARARGS((uint my_err, const char *format,
myf MyFlags, ...)
diff --git a/include/mysql_com.h b/include/mysql_com.h
index be8db185737..f4b6114c8d4 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -33,7 +33,7 @@
#if defined(__WIN__) && !defined( _CUSTOMCONFIG_)
#define MYSQL_NAMEDPIPE "MySQL"
-#define MYSQL_SERVICENAME "MySql"
+#define MYSQL_SERVICENAME "MySQL"
#endif /* __WIN__ */
enum enum_server_command
diff --git a/include/mysys_err.h b/include/mysys_err.h
index a86765c74fd..0ee89e91ee4 100644
--- a/include/mysys_err.h
+++ b/include/mysys_err.h
@@ -21,7 +21,7 @@ extern "C" {
#endif
#define GLOB 0 /* Error maps */
-#define GLOBERRS 27 /* Max number of error messages in map's */
+#define GLOBERRS 28 /* Max number of error messages in map's */
#define EE(X) globerrs[ X ] /* Defines to add error to right map */
extern const char * NEAR globerrs[]; /* my_error_messages is here */
@@ -53,6 +53,7 @@ extern const char * NEAR globerrs[]; /* my_error_messages is here */
#define EE_CANT_READLINK 24
#define EE_CANT_SYMLINK 25
#define EE_REALPATH 26
+#define EE_SYNC 27
/* exit codes for all MySQL programs */
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index 37f64efb27f..b6d4eba9f9b 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -3095,7 +3095,15 @@ consecutive_loop:
/* Do the i/o with ordinary, synchronous i/o functions: */
if (slot->type == OS_FILE_WRITE) {
if (array == os_aio_write_array) {
-
+ if ((total_len % UNIV_PAGE_SIZE != 0)
+ || (slot->offset % UNIV_PAGE_SIZE != 0)) {
+ fprintf(stderr,
+"InnoDB: Error: trying a displaced write to %s %lu %lu, len %lu\n",
+ slot->name, slot->offset_high,
+ slot->offset, total_len);
+ ut_a(0);
+ }
+
/* Do a 'last millisecond' check that the page end
is sensible; reported page checksum errors from
Linux seem to wipe over the page end */
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index 0effdf20766..f41574b2855 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -3287,14 +3287,14 @@ rec_loop:
latest version of the record */
} else if (index == clust_index) {
-
+
/* Fetch a previous version of the row if the current
one is not visible in the snapshot; if we have a very
high force recovery level set, we try to avoid crashes
by skipping this lookup */
if (srv_force_recovery < 5
- && !lock_clust_rec_cons_read_sees(rec, index,
+ && !lock_clust_rec_cons_read_sees(rec, index,
trx->read_view)) {
err = row_sel_build_prev_vers_for_mysql(
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index fa836fb6083..9987804f03e 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -1717,7 +1717,7 @@ srv_init(void)
os_fast_mutex_init(&srv_conc_mutex);
UT_LIST_INIT(srv_conc_queue);
-
+
srv_conc_slots = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_conc_slot_t));
for (i = 0; i < OS_THREAD_MAX_N; i++) {
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 59143e81049..067aec36627 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -1164,6 +1164,28 @@ NetWare. */
/* Note that the call srv_boot() also changes the values of
srv_pool_size etc. to the units used by InnoDB internally */
+ /* Set the maximum number of threads which can wait for a semaphore
+ inside InnoDB */
+#if defined(__WIN__) || defined(__NETWARE__)
+
+/* Create less event semaphores because Win 98/ME had difficulty creating
+40000 event semaphores.
+Comment from Novell, Inc.: also, these just take a lot of memory on
+NetWare. */
+ srv_max_n_threads = 1000;
+#else
+ if (srv_pool_size >= 8 * 1024 * 1024) {
+ /* Here we still have srv_pool_size counted
+ in bytes, srv_boot converts the value to
+ pages; if buffer pool is less than 8 MB,
+ assume fewer threads. */
+ srv_max_n_threads = 10000;
+ } else {
+ srv_max_n_threads = 1000; /* saves several MB of memory,
+ especially in 64-bit
+ computers */
+ }
+#endif
err = srv_boot();
if (err != DB_SUCCESS) {
diff --git a/isam/extra.c b/isam/extra.c
index e2f13532ddf..3bf1dd012ed 100644
--- a/isam/extra.c
+++ b/isam/extra.c
@@ -250,17 +250,15 @@ int nisam_extra(N_INFO *info, enum ha_extra_function function)
pthread_mutex_unlock(&THR_LOCK_isam);
break;
case HA_EXTRA_FLUSH:
-#ifdef __WIN__
if (info->s->not_flushed)
{
info->s->not_flushed=0;
- if (_commit(info->s->kfile))
- error=errno;
- if (_commit(info->dfile))
- error=errno;
+ if (my_sync(info->s->kfile, MYF(0)))
+ error= my_errno;
+ if (my_sync(info->dfile, MYF(0)))
+ error= my_errno;
}
break;
-#endif
case HA_EXTRA_NORMAL: /* Theese isn't in use */
case HA_EXTRA_QUICK:
case HA_EXTRA_KEY_CACHE:
diff --git a/libmysql/manager.c b/libmysql/manager.c
index 1354b98d1c9..ddf9b6c1010 100644
--- a/libmysql/manager.c
+++ b/libmysql/manager.c
@@ -90,7 +90,7 @@ MYSQL_MANAGER* STDCALL mysql_manager_connect(MYSQL_MANAGER* con,
{
my_socket sock;
struct sockaddr_in sock_addr;
- uint32 ip_addr;
+ in_addr_t ip_addr;
char msg_buf[MAX_MYSQL_MANAGER_MSG];
int msg_len;
Vio* vio;
diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am
index 7e04f53e9ff..95cbd4ec826 100644
--- a/libmysqld/Makefile.am
+++ b/libmysqld/Makefile.am
@@ -92,10 +92,10 @@ libmysqld.a: libmysqld_int.a $(INC_LIB)
ar x $$file; \
for obj in *.o ; do mv $$obj $${bfile}_$$obj ; done ; \
ar q ../libmysqld_int2.a *.o ; \
- rm *.o ; \
+ rm -f *.o ; \
done
mv libmysqld_int2.a libmysqld.a
- rm tmp/*
+ rm -f tmp/*
$(RANLIB) libmysqld.a
## XXX: any time the client interface changes, we'll need to bump
diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c
index 95d0149c67d..f3b593f7341 100644
--- a/myisam/ft_boolean_search.c
+++ b/myisam/ft_boolean_search.c
@@ -362,7 +362,7 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query,
Hack: instead of init_queue, we'll use reinit queue to be able
to alloc queue with alloc_root()
*/
- res=ftb->queue.max_elements=1+query_len/(ft_min_word_len+1);
+ res=ftb->queue.max_elements=1+query_len/(min(ft_min_word_len,2)+1);
ftb->queue.root=(byte **)alloc_root(&ftb->mem_root, (res+1)*sizeof(void*));
reinit_queue(& ftb->queue, res, 0, 0,
(int (*)(void*,byte*,byte*))FTB_WORD_cmp, 0);
diff --git a/myisam/mi_extra.c b/myisam/mi_extra.c
index 1d57e0c0e18..8c7515550e7 100644
--- a/myisam/mi_extra.c
+++ b/myisam/mi_extra.c
@@ -336,22 +336,10 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
if (share->not_flushed)
{
share->not_flushed=0;
-#if defined(__WIN__)
- if (_commit(share->kfile))
- error=errno;
- if (_commit(info->dfile))
- error=errno;
-#elif defined(HAVE_FDATASYNC)
- if (fdatasync(share->kfile))
- error=errno;
- if (fdatasync(share->dfile))
- error=errno;
-#elif defined(HAVE_FSYNC)
- if ( fsync(share->kfile))
- error=errno;
- if (fsync(share->dfile))
- error=errno;
-#endif
+ if (my_sync(share->kfile, MYF(0)))
+ error= my_errno;
+ if (my_sync(info->dfile, MYF(0)))
+ error= my_errno;
if (error)
{
share->changed=1;
diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c
index 785979235ce..6f996ab5abd 100644
--- a/myisam/mi_locking.c
+++ b/myisam/mi_locking.c
@@ -98,22 +98,10 @@ int mi_lock_database(MI_INFO *info, int lock_type)
share->changed=0;
if (myisam_flush)
{
-#if defined(__WIN__)
- if (_commit(share->kfile))
- error=errno;
- if (_commit(info->dfile))
- error=errno;
-#elif defined(HAVE_FDATASYNC)
- if (fdatasync(share->kfile))
- error=errno;
- if (fdatasync(share->dfile))
- error=errno;
-#elif defined(HAVE_FSYNC)
- if (fsync(share->kfile))
- error=errno;
- if (fsync(share->dfile))
- error=errno;
-#endif
+ if (my_sync(share->kfile, MYF(0)))
+ error= my_errno;
+ if (my_sync(info->dfile, MYF(0)))
+ error= my_errno;
}
else
share->not_flushed=1;
diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c
index 5a3768c9932..59cc26b198b 100644
--- a/myisam/myisamchk.c
+++ b/myisam/myisamchk.c
@@ -411,6 +411,8 @@ static void usage(void)
-q, --quick Faster repair by not modifying the data file.\n\
One can give a second '-q' to force myisamchk to\n\
modify the original datafile in case of duplicate keys.\n\
+ NOTE: Tables where the data file is currupted can't be\n\
+ fixed with this option.\n\
-u, --unpack Unpack file packed with myisampack.\n\
");
@@ -1109,7 +1111,7 @@ end2:
filename));
if (param->testflag & T_REP_ANY)
VOID(fprintf(stderr,
- "Try fixing it by using the --safe-recover (-o) or the --force (-f) option\n"));
+ "Try fixing it by using the --safe-recover (-o), the --force (-f) option or by not using the --quick (-q) flag\n"));
}
else if (!(param->error_printed & 2) &&
!(param->testflag & T_FORCE_CREATE))
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index eda2f3b2a34..8af3a3ac3ec 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -338,7 +338,13 @@ while test $# -gt 0; do
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --gdb"
;;
--valgrind)
- VALGRIND="valgrind --alignment=8 --leak-check=yes --num-callers=16"
+ VALGRIND=`which valgrind` # this will print an error if not found
+ # Give good warning to the user and stop
+ if [ -z "$VALGRIND" ] ; then
+ $ECHO "You need to have the 'valgrind' program in your PATH to run mysql-test-run with option --valgrind. Valgrind's home page is http://developer.kde.org/~sewardj ."
+ exit 1
+ fi
+ VALGRIND="$VALGRIND --alignment=8 --leak-check=yes --num-callers=16"
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-safemalloc --skip-bdb"
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-safemalloc --skip-bdb"
SLEEP_TIME_AFTER_RESTART=10
@@ -349,6 +355,9 @@ while test $# -gt 0; do
TMP=`$ECHO "$1" | $SED -e "s;--valgrind-options=;;"`
VALGRIND="$VALGRIND $TMP"
;;
+ --valgrind-all)
+ VALGRIND="$VALGRIND -v --show-reachable=yes"
+ ;;
--skip-*)
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT $1"
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT $1"
@@ -1163,7 +1172,7 @@ run_testcase ()
echo $tname > $CURRENT_TEST
SKIP_SLAVE=`$EXPR \( $tname : rpl \) = 0`
if [ $USE_MANAGER = 1 ] ; then
- many_slaves=`$EXPR \( $tname : rpl_failsafe \) != 0`
+ many_slaves=`$EXPR \( \( $tname : rpl_failsafe \) != 0 \) \| \( \( $tname : rpl_chain_temp_table \) != 0 \)`
fi
if [ -n "$SKIP_TEST" ] ; then
diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result
index da3b3d0b8da..56f95ff0c90 100644
--- a/mysql-test/r/fulltext.result
+++ b/mysql-test/r/fulltext.result
@@ -297,6 +297,8 @@ insert into t2 values (3, 1, 'xxbuz');
select * from t1 join t2 using(`t1_id`) where match (t1.name, t2.name) against('xxfoo' in boolean mode);
t1_id name t2_id t1_id name
1 data1 1 1 xxfoo
+select * from t2 where match name against ('a* b* c* d* e* f*' in boolean mode);
+t2_id t1_id name
drop table t1,t2;
SET NAMES latin1;
CREATE TABLE t1 (t text character set utf8 not null, fulltext(t));
diff --git a/mysql-test/r/func_crypt.result b/mysql-test/r/func_crypt.result
index 5ee0f0f3e93..6b63002fd39 100644
--- a/mysql-test/r/func_crypt.result
+++ b/mysql-test/r/func_crypt.result
@@ -1,6 +1,16 @@
+drop table if exists t1;
select length(encrypt('foo', 'ff')) <> 0;
length(encrypt('foo', 'ff')) <> 0
1
+create table t1 (name varchar(50), pw varchar(16));
+insert into t1 values ('tom', password('my_pass'));
+set @pass='my_pass';
+select name from t1 where name='tom' and pw=password(@pass);
+name
+tom
+select name from t1 where name='tom' and pw=password(@undefined);
+name
+drop table t1;
select password('abc');
password('abc')
*0D3CED9BEC10A777AEC23CCC353A8C08A633045E
diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result
index db747e3a7eb..f4878664076 100644
--- a/mysql-test/r/order_by.result
+++ b/mysql-test/r/order_by.result
@@ -306,17 +306,17 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a a 9 NULL 8 Using where; Using index
explain select * from t1 where a = 2 and b >0 order by a desc,b desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 9 NULL 5 Using where; Using index
+1 SIMPLE t1 range a a 9 NULL 4 Using where; Using index
explain select * from t1 where a = 2 and b is null order by a desc,b desc;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a a 9 const,const 1 Using where; Using index; Using filesort
explain select * from t1 where a = 2 and (b is null or b > 0) order by a
desc,b desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 9 NULL 6 Using where; Using index
+1 SIMPLE t1 range a a 9 NULL 5 Using where; Using index
explain select * from t1 where a = 2 and b > 0 order by a desc,b desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 9 NULL 5 Using where; Using index
+1 SIMPLE t1 range a a 9 NULL 4 Using where; Using index
explain select * from t1 where a = 2 and b < 2 order by a desc,b desc;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a a 9 NULL 2 Using where; Using index
diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result
index b446d30c83f..45e195e89f7 100644
--- a/mysql-test/r/query_cache.result
+++ b/mysql-test/r/query_cache.result
@@ -1,8 +1,9 @@
+set GLOBAL query_cache_size=1355776;
flush query cache;
flush query cache;
reset query cache;
flush status;
-drop table if exists t1,t2,t3;
+drop table if exists t1,t2,t3,t4,t11,t21;
drop database if exists mysqltest;
create table t1 (a int not null);
insert into t1 values (1),(2),(3);
@@ -722,6 +723,46 @@ Variable_name Value
Qcache_queries_in_cache 2
SET OPTION SQL_SELECT_LIMIT=DEFAULT;
drop table t1;
+flush query cache;
+reset query cache;
+flush status;
+set GLOBAL query_cache_size=1048576;
+create table t1 (a int not null);
+insert into t1 values (1),(2),(3);
+create table t2 (a text not null);
+create table t3 (a text not null);
+insert into t3 values("1111111111111111111111111111111111111111111111111111");
+insert into t2 select * from t3;
+insert into t3 select * from t2;
+insert into t2 select * from t3;
+insert into t3 select * from t2;
+insert into t2 select * from t3;
+insert into t3 select * from t2;
+insert into t2 select * from t3;
+insert into t3 select * from t2;
+insert into t2 select * from t3;
+insert into t3 select * from t2;
+drop table t2;
+create table t2 (a int not null);
+insert into t2 values (1),(2),(3);
+create table t4 (a int not null);
+insert into t4 values (1),(2),(3);
+select * from t4;
+select * from t2;
+select * from t1 as tt, t1 as ttt where tt.a=1 and ttt.a=2;
+select * from t2;
+select * from t4;
+select * from t1 as tt, t1 as ttt where tt.a=1 and ttt.a=2;
+select * from t2;
+select * from t4;
+select * from t1 as tt, t1 as ttt where tt.a=1 and ttt.a=2;
+delete from t2 where a=1;
+flush query cache;
+select * from t3;
+delete from t4 where a=1;
+flush query cache;
+drop table t1,t2,t3,t4;
+set GLOBAL query_cache_size=0;
SET NAMES koi8r;
CREATE TABLE t1 (a char(1) character set koi8r);
INSERT INTO t1 VALUES (_koi8r'á'),(_koi8r'Á');
diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result
index 38d3d9b2b7d..324eb37b334 100644
--- a/mysql-test/r/range.result
+++ b/mysql-test/r/range.result
@@ -262,6 +262,23 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ref j1 j1 4 const 1 Using where; Using index
1 SIMPLE t1 ALL i2 NULL NULL NULL 4 Range checked for each record (index map: 0x2)
DROP TABLE t1,t2;
+CREATE TABLE t1 (
+a int(11) default NULL,
+b int(11) default NULL,
+KEY a (a),
+KEY b (b)
+) TYPE=MyISAM;
+INSERT INTO t1 VALUES
+(1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(9,1),(10,2),(10,2),
+(13,2),(14,2),(15,2),(16,2),(17,3),(17,3),(16,3),(17,3),(19,3),(20,3),
+(21,4),(22,5),(23,5),(24,5),(25,5),(26,5),(30,5),(31,5),(32,5),(33,5),
+(33,5),(33,5),(33,5),(33,5),(34,5),(35,5);
+EXPLAIN SELECT * FROM t1 WHERE a IN(1,2) AND b=5;
+table type possible_keys key key_len ref rows Extra
+t1 range a,b a 5 NULL 2 Using where
+SELECT * FROM t1 WHERE a IN(1,2) AND b=5;
+a b
+DROP TABLE t1;
create table t1 (id int(10) primary key);
insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9);
select id from t1 where id in (2,5,9) ;
diff --git a/mysql-test/r/rpl_chain_temp_table.result b/mysql-test/r/rpl_chain_temp_table.result
new file mode 100644
index 00000000000..5ece80565c7
--- /dev/null
+++ b/mysql-test/r/rpl_chain_temp_table.result
@@ -0,0 +1,30 @@
+slave stop;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+reset master;
+change master to master_host='127.0.0.1',master_port=9307, master_user='root';
+start slave;
+create temporary table t1 (a int);
+create temporary table t1 (a int);
+show status like 'slave_open_temp_tables';
+Variable_name Value
+Slave_open_temp_tables 2
+create temporary table t1 (a int);
+create temporary table t1 (a int);
+show status like 'slave_open_temp_tables';
+Variable_name Value
+Slave_open_temp_tables 4
+stop slave;
+insert into t1 values(1);
+create table t2 as select * from t1;
+start slave;
+show status like 'slave_open_temp_tables';
+Variable_name Value
+Slave_open_temp_tables 4
+select * from t2;
+a
+1
+drop table t2;
diff --git a/mysql-test/r/rpl_reset_slave.result b/mysql-test/r/rpl_reset_slave.result
index 8887462389d..e1fbf12786d 100644
--- a/mysql-test/r/rpl_reset_slave.result
+++ b/mysql-test/r/rpl_reset_slave.result
@@ -20,3 +20,13 @@ start slave;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master
# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000002 123 master-bin.000001 Yes Yes 0 0 79 123 None 0 No #
+stop slave;
+reset slave;
+start slave;
+create temporary table t1 (a int);
+stop slave;
+reset slave;
+start slave;
+show status like 'slave_open_temp_tables';
+Variable_name Value
+Slave_open_temp_tables 1
diff --git a/mysql-test/r/rpl_trunc_binlog.result b/mysql-test/r/rpl_trunc_binlog.result
index 1cd9cdf08a0..bc5e401287d 100644
--- a/mysql-test/r/rpl_trunc_binlog.result
+++ b/mysql-test/r/rpl_trunc_binlog.result
@@ -8,7 +8,8 @@ stop slave;
flush logs;
reset slave;
start slave;
-show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Replicate_do_table Replicate_ignore_table Replicate_wild_do_table Replicate_wild_ignore_table Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Until_condition Until_Log_File Until_Log_pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_behind_master
# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 4 slave-relay-bin.000002 123 master-bin.000001 Yes No 0 Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. Probably cause is that the master died while writing the transaction to it's binary log. 0 79 326 None 0 No #
-reset master;
+show slave status;
+Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
+127.0.0.1 root MASTER_PORT 1 master-bin.002 4 slave-relay-bin.002 161 master-bin.001 Yes No 0 Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. Probably cause is that the master died while writing the transaction to it's binary log. 0 79 317
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index b9218942a5e..8edd0182dec 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -2150,10 +2150,10 @@ a a a
select * from (t1 as t2 left join t1 as t3 using (a)) inner join t1 on t1.a>1;
a a a
1 1 2
-2 2 2
-3 3 2
1 1 3
+2 2 2
2 2 3
+3 3 2
3 3 3
select * from t1 inner join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1;
a a a
diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test
index 9c48f84161a..467d1aa6f07 100644
--- a/mysql-test/t/fulltext.test
+++ b/mysql-test/t/fulltext.test
@@ -228,6 +228,12 @@ insert into t2 values (1, 1, 'xxfoo');
insert into t2 values (2, 1, 'xxbar');
insert into t2 values (3, 1, 'xxbuz');
select * from t1 join t2 using(`t1_id`) where match (t1.name, t2.name) against('xxfoo' in boolean mode);
+
+#
+# bug with many short (< ft_min_word_len) words in boolean search
+#
+select * from t2 where match name against ('a* b* c* d* e* f*' in boolean mode);
+
drop table t1,t2;
#
diff --git a/mysql-test/t/func_crypt.test b/mysql-test/t/func_crypt.test
index c1c7090cab3..3cf1e15e3ef 100644
--- a/mysql-test/t/func_crypt.test
+++ b/mysql-test/t/func_crypt.test
@@ -1,9 +1,21 @@
-- source include/have_crypt.inc
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
select length(encrypt('foo', 'ff')) <> 0;
--replace_result $1$aa$4OSUA5cjdx0RUQ08opV27/ aaqPiZY5xR5l.
+create table t1 (name varchar(50), pw varchar(16));
+insert into t1 values ('tom', password('my_pass'));
+set @pass='my_pass';
+select name from t1 where name='tom' and pw=password(@pass);
+select name from t1 where name='tom' and pw=password(@undefined);
+drop table t1;
+
# Test new and old password handling functions
+
select password('abc');
select password('');
select old_password('abc');
diff --git a/mysql-test/t/query_cache-master.opt b/mysql-test/t/query_cache-master.opt
deleted file mode 100644
index cfdce628e74..00000000000
--- a/mysql-test/t/query_cache-master.opt
+++ /dev/null
@@ -1 +0,0 @@
---set-variable=query_cache_size=1355776
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
index 0ec6e5ecb73..14cbf4c906d 100644
--- a/mysql-test/t/query_cache.test
+++ b/mysql-test/t/query_cache.test
@@ -3,6 +3,7 @@
#
# Tests with query cache
#
+set GLOBAL query_cache_size=1355776;
# Reset query cache variables.
@@ -11,7 +12,7 @@ flush query cache; # This crashed in some versions
reset query cache;
flush status;
--disable_warnings
-drop table if exists t1,t2,t3;
+drop table if exists t1,t2,t3,t4,t11,t21;
drop database if exists mysqltest;
--enable_warnings
@@ -490,6 +491,55 @@ SET OPTION SQL_SELECT_LIMIT=DEFAULT;
drop table t1;
#
+# query cache crash on using same table twice in one query test
+#
+flush query cache;
+reset query cache;
+flush status;
+set GLOBAL query_cache_size=1048576;
+
+create table t1 (a int not null);
+insert into t1 values (1),(2),(3);
+create table t2 (a text not null);
+create table t3 (a text not null);
+insert into t3 values("1111111111111111111111111111111111111111111111111111");
+insert into t2 select * from t3;
+insert into t3 select * from t2;
+insert into t2 select * from t3;
+insert into t3 select * from t2;
+insert into t2 select * from t3;
+insert into t3 select * from t2;
+insert into t2 select * from t3;
+insert into t3 select * from t2;
+insert into t2 select * from t3;
+insert into t3 select * from t2;
+drop table t2;
+create table t2 (a int not null);
+insert into t2 values (1),(2),(3);
+create table t4 (a int not null);
+insert into t4 values (1),(2),(3);
+
+disable_result_log;
+select * from t4;
+select * from t2;
+select * from t1 as tt, t1 as ttt where tt.a=1 and ttt.a=2;
+select * from t2;
+select * from t4;
+select * from t1 as tt, t1 as ttt where tt.a=1 and ttt.a=2;
+select * from t2;
+select * from t4;
+select * from t1 as tt, t1 as ttt where tt.a=1 and ttt.a=2;
+
+delete from t2 where a=1;
+flush query cache;
+select * from t3;
+enable_result_log;
+delete from t4 where a=1;
+flush query cache;
+
+drop table t1,t2,t3,t4;
+
+#
# Test character set related variables:
# character_set_result
# character_set_client
@@ -535,3 +585,4 @@ show status like "Qcache_queries_in_cache";
# Keep things tidy
#
DROP TABLE t1;
+SET GLOBAL query_cache_size=0;
diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test
index 40ae49f8005..0b39f20e346 100644
--- a/mysql-test/t/range.test
+++ b/mysql-test/t/range.test
@@ -306,3 +306,28 @@ select * from t1, t2 where t1.uid=t2.uid AND t1.uid > 0;
select * from t1, t2 where t1.uid=t2.uid AND t1.uid != 0;
drop table t1,t2;
+
+#
+# bug #1724: use RANGE on more selective column instead of REF on less
+# selective
+
+CREATE TABLE t1 (
+ a int(11) default NULL,
+ b int(11) default NULL,
+ KEY a (a),
+ KEY b (b)
+) TYPE=MyISAM;
+
+
+INSERT INTO t1 VALUES
+(1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(9,1),(10,2),(10,2),
+(13,2),(14,2),(15,2),(16,2),(17,3),(17,3),(16,3),(17,3),(19,3),(20,3),
+(21,4),(22,5),(23,5),(24,5),(25,5),(26,5),(30,5),(31,5),(32,5),(33,5),
+(33,5),(33,5),(33,5),(33,5),(34,5),(35,5);
+
+EXPLAIN SELECT * FROM t1 WHERE a IN(1,2) AND b=5;
+SELECT * FROM t1 WHERE a IN(1,2) AND b=5;
+
+DROP TABLE t1;
+
+# we expect that optimizer will choose key on A
diff --git a/mysql-test/t/rpl_chain_temp_table.test b/mysql-test/t/rpl_chain_temp_table.test
new file mode 100644
index 00000000000..007b018e9d8
--- /dev/null
+++ b/mysql-test/t/rpl_chain_temp_table.test
@@ -0,0 +1,99 @@
+ # This test makes some assumptions about values of thread ids, which should be
+# true if the servers have been restarted for this test. So we want to
+# stop/restart servers. Note that if assumptions are wrong, the test will not
+# fail; it will just fail to test the error-prone scenario.
+# Using the manager is the only way to have more than one slave server.
+# So you must run this test with --manager.
+
+require_manager;
+server_stop master;
+server_start master;
+server_stop slave;
+server_start slave;
+# no need for slave_sec (no assumptions on thread ids for this server).
+
+source include/master-slave.inc;
+connect (slave_sec,localhost,root,,test,0,slave.sock-1);
+connection master;
+save_master_pos;
+connection slave;
+sync_with_master;
+reset master;
+save_master_pos;
+connection slave_sec;
+eval change master to master_host='127.0.0.1',master_port=$SLAVE_MYPORT, master_user='root';
+start slave;
+sync_with_master;
+
+# :P now we have a chain ready-to-test.
+
+connection master;
+create temporary table t1 (a int);
+save_master_pos;
+connection slave;
+sync_with_master;
+connection master1;
+create temporary table t1 (a int);
+save_master_pos;
+connection slave;
+sync_with_master;
+save_master_pos;
+
+# First test:
+
+connection slave_sec;
+# Before BUG#1686 ("If 2 master threads with same-name temp table, slave makes
+# bad binlog") was fixed, sync_with_master failed
+sync_with_master;
+show status like 'slave_open_temp_tables';
+
+# 'master' and 'master1' usually have thread id 2-3 or 3-4.
+# 'slave' and 'slave1' usually have thread id 2-3.
+connection slave;
+create temporary table t1 (a int);
+connection slave1;
+create temporary table t1 (a int);
+# So it's likely that in the binlog of slave we get
+# server_id=of_master thread_id=3 create temp...
+# server_id=of_slave thread_id=3 create temp...
+# which would confuse slave-sec unless slave-sec uses server id to distinguish
+# between temp tables (here thread id is obviously not enough to distinguish).
+
+save_master_pos;
+
+# Second test:
+
+connection slave_sec;
+# If we did not use the server id to distinguish between temp tables,
+# sync_with_master would fail
+sync_with_master;
+show status like 'slave_open_temp_tables';
+
+# Third test (BUG#1240 "slave of slave breaks when STOP SLAVE was issud on
+# parent slave and temp tables").
+stop slave;
+connection slave;
+insert into t1 values(1);
+create table t2 as select * from t1;
+save_master_pos;
+connection slave_sec;
+start slave;
+sync_with_master;
+show status like 'slave_open_temp_tables';
+select * from t2;
+
+# clean up
+connection slave;
+drop table t2;
+save_master_pos;
+connection slave_sec;
+sync_with_master;
+
+# On purpose, we don't delete the temporary tables explicitely.
+# So temp tables remain on slave (remember they are not deleted when the slave
+# SQL thread terminates). If you run this test with
+# --valgrind --valgrind-options=--show-reachable=yes
+# you will see if they get cleaned up at slave's shutdown (that is, if the
+# memory they use is freed (it should) by mysqld before it terminates).
+# If they wouldn't be cleaned up, you would see some "still reachable" blocks in
+# Valgrind.
diff --git a/mysql-test/t/rpl_reset_slave.test b/mysql-test/t/rpl_reset_slave.test
index e03916ec73a..d58e9c711d1 100644
--- a/mysql-test/t/rpl_reset_slave.test
+++ b/mysql-test/t/rpl_reset_slave.test
@@ -2,6 +2,8 @@
# --master-* options from mysqld, as this is what is going to be used next time
# slave threads will be started). In bug 985, it displayed old values (of before
# RESET SLAVE).
+# See if slave crashes when doing a CREATE TEMPORARY TABLE twice, separated by
+# RESET SLAVE.
source include/master-slave.inc;
connection master;
@@ -28,3 +30,19 @@ sync_with_master;
--replace_result $MASTER_MYPORT MASTER_PORT
--replace_column 1 # 33 #
show slave status;
+
+# test of crash with temp tables & RESET SLAVE
+# (test to see if RESET SLAVE clears temp tables in memory and disk)
+stop slave;
+reset slave;
+start slave;
+connection master;
+create temporary table t1 (a int);
+save_master_pos;
+connection slave;
+sync_with_master;
+stop slave;
+reset slave;
+start slave;
+sync_with_master;
+show status like 'slave_open_temp_tables';
diff --git a/mysql-test/t/rpl_trunc_binlog.test b/mysql-test/t/rpl_trunc_binlog.test
index 4c14ec72b5c..32052af9184 100644
--- a/mysql-test/t/rpl_trunc_binlog.test
+++ b/mysql-test/t/rpl_trunc_binlog.test
@@ -23,5 +23,3 @@ sleep 3;
--replace_result $MASTER_MYPORT MASTER_PORT
--replace_column 1 # 33 #
show slave status;
-connection master;
-reset master;
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index 5ff682fbc80..37c79e28395 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -47,7 +47,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\
my_delete.c my_rename.c my_redel.c my_tempnam.c \
my_chsize.c my_lread.c my_lwrite.c my_clock.c \
my_quick.c my_lockmem.c my_static.c \
- my_getopt.c my_mkdir.c \
+ my_sync.c my_getopt.c my_mkdir.c \
default.c my_compress.c checksum.c raid.cc \
my_net.c my_semaphore.c my_port.c my_sleep.c \
charset.c charset-def.c my_bitmap.c my_bit.c md5.c \
diff --git a/mysys/errors.c b/mysys/errors.c
index a2226fc12c5..255b6893c73 100644
--- a/mysys/errors.c
+++ b/mysys/errors.c
@@ -48,6 +48,7 @@ const char * NEAR globerrs[GLOBERRS]=
"Can't read value for symlink '%s' (Error %d)",
"Can't create symlink '%s' pointing at '%s' (Error %d)",
"Error on realpath() on '%s' (Error %d)",
+ "Can't sync file '%s' to disk (Errcode: %d)",
};
void init_glob_errs(void)
@@ -84,8 +85,9 @@ void init_glob_errs()
EE(EE_CANT_MKDIR) ="Can't create directory '%s' (Errcode: %d)";
EE(EE_UNKNOWN_CHARSET)= "Character set '%s' is not a compiled character set and is not specified in the %s file";
EE(EE_OUT_OF_FILERESOURCES)="Out of resources when opening file '%s' (Errcode: %d)";
- EE(EE_CANT_READLINK)="Can't read value for symlink '%s' (Error %d)";
- EE(EE_CANT_SYMLINK)="Can't create symlink '%s' pointing at '%s' (Error %d)";
- EE(EE_REALPATH)="Error on realpath() on '%s' (Error %d)";
+ EE(EE_CANT_READLINK)= "Can't read value for symlink '%s' (Error %d)";
+ EE(EE_CANT_SYMLINK)= "Can't create symlink '%s' pointing at '%s' (Error %d)";
+ EE(EE_REALPATH)= "Error on realpath() on '%s' (Error %d)";
+ EE(EE_SYNC)= "Can't sync file '%s' to disk (Errcode: %d)";
}
#endif
diff --git a/mysys/my_new.cc b/mysys/my_new.cc
index 5cc291af9aa..5f2da90bbd1 100644
--- a/mysys/my_new.cc
+++ b/mysys/my_new.cc
@@ -25,12 +25,12 @@
void *operator new (size_t sz)
{
- return (void *) malloc (sz ? sz+1 : sz);
+ return (void *) malloc (sz ? sz : 1);
}
void *operator new[] (size_t sz)
{
- return (void *) malloc (sz ? sz+1 : sz);
+ return (void *) malloc (sz ? sz : 1);
}
void operator delete (void *ptr)
diff --git a/mysys/my_sync.c b/mysys/my_sync.c
new file mode 100644
index 00000000000..317ca039346
--- /dev/null
+++ b/mysys/my_sync.c
@@ -0,0 +1,60 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "mysys_priv.h"
+#include "mysys_err.h"
+#include <errno.h>
+
+/*
+ Sync data in file to disk
+
+ SYNOPSIS
+ my_sync()
+ fd File descritor to sync
+ my_flags Flags (now only MY_WME is supported)
+
+ NOTE
+ If file system supports its, only file data is synced, not inode date
+
+ RETURN
+ 0 ok
+ -1 error
+*/
+
+int my_sync(File fd, myf my_flags)
+{
+ int res;
+ DBUG_ENTER("my_sync");
+ DBUG_PRINT("my",("Fd: %d my_flags: %d", fd, my_flags));
+
+#if defined(HAVE_FDATASYNC)
+ res= fdatasync(fd);
+#elif defined(HAVE_FSYNC)
+ res=fsync(fd);
+#elif defined(__WIN__)
+ res= _commit(fd);
+#else
+ res= 0; /* No sync (strange OS) */
+#endif
+ if (res)
+ {
+ if (!(my_errno= errno))
+ my_errno= -1; /* Unknown error */
+ if (my_flags & MY_WME)
+ my_error(EE_SYNC, MYF(ME_BELL+ME_WAITTANG), my_filename(fd), my_errno);
+ }
+ DBUG_RETURN(res);
+} /* my_read */
diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c
index 32bc8ea3724..9ee7371b639 100644
--- a/mysys/my_thr_init.c
+++ b/mysys/my_thr_init.c
@@ -159,6 +159,7 @@ my_bool my_thread_init(void)
tmp->id= ++thread_id;
pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST);
pthread_cond_init(&tmp->suspend, NULL);
+ tmp->init= 1;
end:
#if !defined(__WIN__) || defined(USE_TLS) || ! defined(SAFE_MUTEX)
@@ -170,12 +171,14 @@ end:
void my_thread_end(void)
{
- struct st_my_thread_var *tmp=my_thread_var;
+ struct st_my_thread_var *tmp;
+ tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys);
+
#ifdef EXTRA_DEBUG_THREADS
fprintf(stderr,"my_thread_end(): tmp=%p,thread_id=%ld\n",
tmp,pthread_self());
#endif
- if (tmp)
+ if (tmp && tmp->init)
{
#if !defined(DBUG_OFF)
/* tmp->dbug is allocated inside DBUG library */
@@ -191,6 +194,8 @@ void my_thread_end(void)
pthread_mutex_destroy(&tmp->mutex);
#if (!defined(__WIN__) && !defined(OS2)) || defined(USE_TLS)
free(tmp);
+#else
+ tmp->init= 0;
#endif
}
/* The following free has to be done, even if my_thread_var() is 0 */
diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c
index 36bbac16fef..bf40ffc5b4d 100644
--- a/mysys/thr_alarm.c
+++ b/mysys/thr_alarm.c
@@ -714,6 +714,9 @@ void thr_alarm_info(ALARM_INFO *info)
bzero((char*) info, sizeof(*info));
}
+void resize_thr_alarm(uint max_alarms)
+{
+}
/*****************************************************************************
thr_alarm for win95
@@ -793,6 +796,10 @@ void thr_alarm_info(ALARM_INFO *info)
bzero((char*) info, sizeof(*info));
}
+void resize_thr_alarm(uint max_alarms)
+{
+}
+
#endif /* __WIN__ */
#endif /* THREAD */
diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh
index adaac0f3102..acf0f8aa2c8 100644
--- a/scripts/mysql_install_db.sh
+++ b/scripts/mysql_install_db.sh
@@ -167,7 +167,7 @@ then
fi
fi
-if test "$ip_only" ="1"
+if test "$ip_only" = "1"
then
ip=`echo "$resolved" | awk '/ /{print $6}'`
hostname=$ip
diff --git a/scripts/mysql_secure_installation.sh b/scripts/mysql_secure_installation.sh
index d6392c57731..1c7ca34ad59 100644
--- a/scripts/mysql_secure_installation.sh
+++ b/scripts/mysql_secure_installation.sh
@@ -85,9 +85,13 @@ set_root_password() {
return 1
fi
- do_query "SET PASSWORD FOR root=PASSWORD('$password1');"
+ do_query "UPDATE mysql.user SET Password=PASSWORD('$password1') WHERE User='root';"
if [ $? -eq 0 ]; then
echo "Password updated successfully!"
+ echo "Reloading privilege tables.."
+ if ! reload_privilege_tables; then
+ exit 1
+ fi
echo
rootpass=$password1
make_config
@@ -144,11 +148,11 @@ reload_privilege_tables() {
do_query "FLUSH PRIVILEGES;"
if [ $? -eq 0 ]; then
echo " ... Success!"
+ return 0
else
echo " ... Failed!"
+ return 1
fi
-
- return 0
}
interrupt() {
diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh
index f23955da06a..654e5466e12 100644
--- a/scripts/mysqlhotcopy.sh
+++ b/scripts/mysqlhotcopy.sh
@@ -37,7 +37,7 @@ WARNING: THIS PROGRAM IS STILL IN BETA. Comments/patches welcome.
# Documentation continued at end of file
-my $VERSION = "1.19";
+my $VERSION = "1.20";
my $opt_tmpdir = $ENV{TMPDIR} || "/tmp";
@@ -235,10 +235,15 @@ else
# --- resolve database names from regexp ---
if ( defined $opt{regexp} ) {
+ my $t_regex = '.*';
+ if ( $opt{regexp} =~ s{^/(.+)/\./(.+)/$}{$1} ) {
+ $t_regex = $2;
+ }
+
my $sth_dbs = $dbh->prepare("show databases");
$sth_dbs->execute;
while ( my ($db_name) = $sth_dbs->fetchrow_array ) {
- push @db_desc, { 'src' => $db_name } if ( $db_name =~ m/$opt{regexp}/o );
+ push @db_desc, { 'src' => $db_name, 't_regex' => $t_regex } if ( $db_name =~ m/$opt{regexp}/o );
}
}
@@ -413,6 +418,8 @@ foreach my $rdb ( @db_desc ) {
else {
mkdir($tgt_dirpath, 0750) or die "Can't create '$tgt_dirpath': $!\n"
unless -d $tgt_dirpath;
+ my @f_info= stat "$datadir/$rdb->{src}";
+ chown $f_info[4], $f_info[5], $tgt_dirpath;
}
}
}
@@ -938,6 +945,14 @@ server in a mutual replication setup.
Copy all databases with names matching the pattern
+=item --regexp /pattern1/./pattern2/
+
+Copy all tables with names matching pattern2 from all databases with
+names matching pattern1. For example, to select all tables which
+names begin with 'bar' from all databases which names end with 'foo':
+
+ mysqlhotcopy --indices --method=cp --regexp /foo$/./^bar/
+
=item db_name./pattern/
Copy only tables matching pattern. Shell metacharacters ( (, ), |, !,
diff --git a/sql/item_func.cc b/sql/item_func.cc
index e6120f2e93c..3ed0396e373 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2571,7 +2571,7 @@ err:
bool Item_func_get_user_var::const_item() const
{
- return var_entry && current_thd->query_id != var_entry->update_query_id;
+ return (!var_entry || current_thd->query_id != var_entry->update_query_id);
}
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 62dc56e7fd2..c0fd781cede 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -768,11 +768,49 @@ int Query_log_event::write(IO_CACHE* file)
int Query_log_event::write_data(IO_CACHE* file)
{
+ char buf[QUERY_HEADER_LEN];
+
if (!query)
return -1;
- char buf[QUERY_HEADER_LEN];
- int4store(buf + Q_THREAD_ID_OFFSET, thread_id);
+ /*
+ We want to store the thread id:
+ (- as an information for the user when he reads the binlog)
+ - if the query uses temporary table: for the slave SQL thread to know to
+ which master connection the temp table belongs.
+ Now imagine we (write_data()) are called by the slave SQL thread (we are
+ logging a query executed by this thread; the slave runs with
+ --log-slave-updates). Then this query will be logged with
+ thread_id=the_thread_id_of_the_SQL_thread. Imagine that 2 temp tables of
+ the same name were created simultaneously on the master (in the master
+ binlog you have
+ CREATE TEMPORARY TABLE t; (thread 1)
+ CREATE TEMPORARY TABLE t; (thread 2)
+ ...)
+ then in the slave's binlog there will be
+ CREATE TEMPORARY TABLE t; (thread_id_of_the_slave_SQL_thread)
+ CREATE TEMPORARY TABLE t; (thread_id_of_the_slave_SQL_thread)
+ which is bad (same thread id!).
+
+ To avoid this, we log the thread's thread id EXCEPT for the SQL
+ slave thread for which we log the original (master's) thread id.
+ Now this moves the bug: what happens if the thread id on the
+ master was 10 and when the slave replicates the query, a
+ connection number 10 is opened by a normal client on the slave,
+ and updates a temp table of the same name? We get a problem
+ again. To avoid this, in the handling of temp tables (sql_base.cc)
+ we use thread_id AND server_id. TODO when this is merged into
+ 4.1: in 4.1, slave_proxy_id has been renamed to pseudo_thread_id
+ and is a session variable: that's to make mysqlbinlog work with
+ temp tables. We probably need to introduce
+
+ SET PSEUDO_SERVER_ID
+ for mysqlbinlog in 4.1. mysqlbinlog would print:
+ SET PSEUDO_SERVER_ID=
+ SET PSEUDO_THREAD_ID=
+ for each query using temp tables.
+ */
+ int4store(buf + Q_THREAD_ID_OFFSET, slave_proxy_id);
int4store(buf + Q_EXEC_TIME_OFFSET, exec_time);
buf[Q_DB_LEN_OFFSET] = (char) db_len;
int2store(buf + Q_ERR_CODE_OFFSET, error_code);
@@ -790,12 +828,14 @@ int Query_log_event::write_data(IO_CACHE* file)
#ifndef MYSQL_CLIENT
Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
ulong query_length, bool using_trans)
- :Log_event(thd_arg, !thd_arg->tmp_table_used ?
- 0 : LOG_EVENT_THREAD_SPECIFIC_F, using_trans),
+ :Log_event(thd_arg, !thd_arg->tmp_table_used ?
+ 0 : LOG_EVENT_THREAD_SPECIFIC_F, using_trans),
data_buf(0), query(query_arg),
db(thd_arg->db), q_len((uint32) query_length),
- error_code(thd_arg->killed ? ER_SERVER_SHUTDOWN: thd_arg->net.last_errno),
- thread_id(thd_arg->thread_id)
+ error_code(thd_arg->killed ? ER_SERVER_SHUTDOWN: thd_arg->net.last_errno),
+ thread_id(thd_arg->thread_id),
+ /* save the original thread id; we already know the server id */
+ slave_proxy_id(thd_arg->slave_proxy_id)
{
time_t end_time;
time(&end_time);
@@ -836,7 +876,7 @@ Query_log_event::Query_log_event(const char* buf, int event_len,
return;
memcpy(data_buf, buf + Q_DATA_OFFSET, data_len);
- thread_id = uint4korr(buf + Q_THREAD_ID_OFFSET);
+ slave_proxy_id= thread_id= uint4korr(buf + Q_THREAD_ID_OFFSET);
db = data_buf;
db_len = (uint)buf[Q_DB_LEN_OFFSET];
query=data_buf + db_len + 1;
@@ -907,8 +947,8 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
{
thd->set_time((time_t)when);
thd->query_length= q_len;
- VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query = (char*)query;
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query_id = query_id++;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->query_error= 0; // clear error
@@ -1276,7 +1316,7 @@ void Load_log_event::pack_info(Protocol *protocol)
int Load_log_event::write_data_header(IO_CACHE* file)
{
char buf[LOAD_HEADER_LEN];
- int4store(buf + L_THREAD_ID_OFFSET, thread_id);
+ int4store(buf + L_THREAD_ID_OFFSET, slave_proxy_id);
int4store(buf + L_EXEC_TIME_OFFSET, exec_time);
int4store(buf + L_SKIP_LINES_OFFSET, skip_lines);
buf[L_TBL_LEN_OFFSET] = (char)table_name_len;
@@ -1317,7 +1357,9 @@ Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex,
enum enum_duplicates handle_dup,
bool using_trans)
:Log_event(thd_arg, 0, using_trans), thread_id(thd_arg->thread_id),
- num_fields(0), fields(0), field_lens(0),field_block_len(0),
+ slave_proxy_id(thd_arg->slave_proxy_id),
+ num_fields(0),fields(0),
+ field_lens(0),field_block_len(0),
table_name(table_name_arg ? table_name_arg : ""),
db(db_arg), fname(ex->file_name)
{
@@ -1422,7 +1464,7 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len,
char* buf_end = (char*)buf + event_len;
uint header_len= old_format ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
const char* data_head = buf + header_len;
- thread_id = uint4korr(data_head + L_THREAD_ID_OFFSET);
+ slave_proxy_id= thread_id= uint4korr(data_head + L_THREAD_ID_OFFSET);
exec_time = uint4korr(data_head + L_EXEC_TIME_OFFSET);
skip_lines = uint4korr(data_head + L_SKIP_LINES_OFFSET);
table_name_len = (uint)data_head[L_TBL_LEN_OFFSET];
diff --git a/sql/log_event.h b/sql/log_event.h
index 8ba5d0379a0..6cc8a7ca06d 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -455,6 +455,13 @@ public:
uint32 db_len;
uint16 error_code;
ulong thread_id;
+ /*
+ For events created by Query_log_event::exec_event (and
+ Load_log_event::exec_event()) we need the *original* thread id, to be able
+ to log the event with the original (=master's) thread id (fix for
+ BUG#1686).
+ */
+ ulong slave_proxy_id;
#ifndef MYSQL_CLIENT
Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length,
@@ -543,6 +550,7 @@ protected:
public:
ulong thread_id;
+ ulong slave_proxy_id;
uint32 table_name_len;
uint32 db_len;
uint32 fname_len;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 1052eeaf11b..7c432a05786 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -1985,7 +1985,7 @@ extern "C" pthread_handler_decl(handle_shutdown,arg)
#endif
-const char *load_default_groups[]= { "mysqld","server",MYSQL_BASE_VERSION,0 };
+const char *load_default_groups[]= { "mysqld","server",MYSQL_BASE_VERSION,0,0};
bool open_log(MYSQL_LOG *log, const char *hostname,
const char *opt_name, const char *extension,
@@ -2733,7 +2733,7 @@ default_service_handling(char **argv,
const char *extra_opt)
{
char path_and_service[FN_REFLEN+FN_REFLEN+32], *pos, *end;
- end= path_and_service + sizeof(path_and_service)-1;
+ end= path_and_service + sizeof(path_and_service)-3;
/* We have to quote filename if it contains spaces */
pos= add_quoted_string(path_and_service, file_path, end);
@@ -2743,7 +2743,9 @@ default_service_handling(char **argv,
*pos++= ' ';
pos= add_quoted_string(pos, extra_opt, end);
}
- *pos= 0; // Ensure end null
+ /* We must have servicename last */
+ *pos++= ' ';
+ strmake(pos, servicename, (uint) (end+2 - pos));
if (Service.got_service_option(argv, "install"))
{
@@ -2786,10 +2788,16 @@ int main(int argc, char **argv)
if (!default_service_handling(argv, MYSQL_SERVICENAME, MYSQL_SERVICENAME,
file_path, ""))
return 0;
- if (Service.IsService(argv[1]))
+ if (Service.IsService(argv[1])) /* Start an optional service */
{
- /* start an optional service */
- load_default_groups[0]= argv[1];
+ /*
+ Only add the service name to the groups read from the config file
+ if it's not "MySQL". (The default service name should be 'mysqld'
+ but we started a bad tradition by calling it MySQL from the start
+ and we are now stuck with it.
+ */
+ if (my_strcasecmp(argv[1],"mysql"))
+ load_default_groups[3]= argv[1];
start_mode= 1;
Service.Init(argv[1], mysql_service);
return 0;
@@ -2797,8 +2805,7 @@ int main(int argc, char **argv)
}
else if (argc == 3) /* install or remove any optional service */
{
- if (!default_service_handling(argv, argv[2], argv[2], file_path,
- argv[2]))
+ if (!default_service_handling(argv, argv[2], argv[2], file_path, ""))
return 0;
if (Service.IsService(argv[2]))
{
@@ -2810,6 +2817,8 @@ int main(int argc, char **argv)
opt_argc= 2; // Skip service-name
opt_argv=argv;
start_mode= 1;
+ if (my_strcasecmp(argv[2],"mysql"))
+ load_default_groups[3]= argv[2];
Service.Init(argv[2], mysql_service);
return 0;
}
diff --git a/sql/slave.cc b/sql/slave.cc
index 415969a2955..561b32b668c 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -355,6 +355,22 @@ void init_slave_skip_errors(const char* arg)
}
}
+void st_relay_log_info::close_temporary_tables()
+{
+ TABLE *table,*next;
+
+ for (table=save_temporary_tables ; table ; table=next)
+ {
+ next=table->next;
+ /*
+ Don't ask for disk deletion. For now, anyway they will be deleted when
+ slave restarts, but it is a better intention to not delete them.
+ */
+ close_temporary(table, 0);
+ }
+ save_temporary_tables= 0;
+ slave_open_temp_tables= 0;
+}
/*
purge_relay_logs()
@@ -847,6 +863,7 @@ static int end_slave_on_walk(MASTER_INFO* mi, gptr /*unused*/)
void end_slave()
{
+ /* This is called when the server terminates, in close_connections(). */
if (active_mi)
{
/*
@@ -1428,7 +1445,7 @@ file '%s', errno %d)", fname, my_errno);
if (init_relay_log_pos(rli,NullS,BIN_LOG_HEADER_SIZE,0 /* no data lock */,
&msg))
{
- sql_print_error("Failed to open the relay log 'FIRST' (relay_log_pos 4");
+ sql_print_error("Failed to open the relay log 'FIRST' (relay_log_pos 4)");
goto err;
}
rli->group_master_log_name[0]= 0;
@@ -3166,8 +3183,6 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
RPL_LOG_NAME, llstr(rli->group_master_log_pos,llbuff));
err:
- /* Free temporary tables etc */
- thd->cleanup();
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query = thd->db = 0; // extra safety
VOID(pthread_mutex_unlock(&LOCK_thread_count));
@@ -3585,6 +3600,12 @@ void end_relay_log_info(RELAY_LOG_INFO* rli)
}
rli->inited = 0;
rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
+ /*
+ Delete the slave's temporary tables from memory.
+ In the future there will be other actions than this, to ensure persistance
+ of slave's temp tables after shutdown.
+ */
+ rli->close_temporary_tables();
DBUG_VOID_RETURN;
}
diff --git a/sql/slave.h b/sql/slave.h
index 618b04311b9..f8093826f58 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -320,10 +320,10 @@ typedef struct st_relay_log_info
int wait_for_pos(THD* thd, String* log_name, longlong log_pos,
longlong timeout);
+ void close_temporary_tables();
/* Check if UNTIL condition is satisfied. See slave.cc for more. */
bool is_until_satisfied();
-
} RELAY_LOG_INFO;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 88a1d21354b..3976ebd81f4 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -575,6 +575,8 @@ TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name)
uint key_length= (uint) (strmov(strmov(key,db)+1,table_name)-key)+1;
TABLE *table,**prev;
+ int4store(key+key_length,thd->server_id);
+ key_length += 4;
int4store(key+key_length,thd->variables.pseudo_thread_id);
key_length += 4;
@@ -603,18 +605,27 @@ bool close_temporary_table(THD *thd, const char *db, const char *table_name)
return 0;
}
+/*
+ Used by ALTER TABLE when the table is a temporary one. It changes something
+ only if the ALTER contained a RENAME clause (otherwise, table_name is the old
+ name).
+ Prepares a table cache key, which is the concatenation of db, table_name and
+ thd->slave_proxy_id, separated by '\0'.
+*/
bool rename_temporary_table(THD* thd, TABLE *table, const char *db,
const char *table_name)
{
char *key;
if (!(key=(char*) alloc_root(&table->mem_root,
(uint) strlen(db)+
- (uint) strlen(table_name)+6)))
+ (uint) strlen(table_name)+6+4)))
return 1; /* purecov: inspected */
table->key_length=(uint)
(strmov((table->real_name=strmov(table->table_cache_key=key,
db)+1),
table_name) - table->table_cache_key)+1;
+ int4store(key+table->key_length,thd->server_id);
+ table->key_length += 4;
int4store(key+table->key_length,thd->variables.pseudo_thread_id);
table->key_length += 4;
return 0;
@@ -771,12 +782,13 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
if (thd->killed)
DBUG_RETURN(0);
key_length= (uint) (strmov(strmov(key,db)+1,table_name)-key)+1;
- int4store(key + key_length, thd->variables.pseudo_thread_id);
+ int4store(key + key_length, thd->server_id);
+ int4store(key + key_length + 4, thd->variables.pseudo_thread_id);
for (table=thd->temporary_tables; table ; table=table->next)
{
- if (table->key_length == key_length+4 &&
- !memcmp(table->table_cache_key,key,key_length+4))
+ if (table->key_length == key_length+8 &&
+ !memcmp(table->table_cache_key,key,key_length+8))
{
if (table->query_id == thd->query_id)
{
@@ -1671,7 +1683,7 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
total of 6 extra bytes in my_malloc in addition to table/db stuff
*/
if (!(tmp_table=(TABLE*) my_malloc(sizeof(*tmp_table)+(uint) strlen(db)+
- (uint) strlen(table_name)+6,
+ (uint) strlen(table_name)+6+4,
MYF(MY_WME))))
DBUG_RETURN(0); /* purecov: inspected */
@@ -1694,6 +1706,9 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
+1), table_name)
- tmp_table->table_cache_key)+1;
int4store(tmp_table->table_cache_key + tmp_table->key_length,
+ thd->server_id);
+ tmp_table->key_length += 4;
+ int4store(tmp_table->table_cache_key + tmp_table->key_length,
thd->variables.pseudo_thread_id);
tmp_table->key_length += 4;
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 0bae41da002..a4ae8fd5946 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -2761,11 +2761,33 @@ my_bool Query_cache::move_by_type(byte **border,
relink(block, new_block, next, prev, pnext, pprev);
if (queries_blocks == block)
queries_blocks = new_block;
+ Query_cache_block_table *beg_of_table_table= block->table(0),
+ *end_of_table_table= block->table(n_tables);
+ byte *beg_of_new_table_table= (byte*) new_block->table(0);
+
for (TABLE_COUNTER_TYPE j=0; j < n_tables; j++)
{
Query_cache_block_table *block_table = new_block->table(j);
- block_table->next->prev = block_table;
- block_table->prev->next = block_table;
+
+ // use aligment from begining of table if 'next' is in same block
+ if ((beg_of_table_table <= block_table->next) &&
+ (block_table->next < end_of_table_table))
+ ((Query_cache_block_table *)(beg_of_new_table_table +
+ (((byte*)block_table->next) -
+ ((byte*)beg_of_table_table))))->prev=
+ block_table;
+ else
+ block_table->next->prev= block_table;
+
+ // use aligment from begining of table if 'prev' is in same block
+ if ((beg_of_table_table <= block_table->prev) &&
+ (block_table->prev < end_of_table_table))
+ ((Query_cache_block_table *)(beg_of_new_table_table +
+ (((byte*)block_table->prev) -
+ ((byte*)beg_of_table_table))))->next=
+ block_table;
+ else
+ block_table->prev->next = block_table;
}
DBUG_PRINT("qcache", ("after circle tt"));
*border += len;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index ed01e1bb038..6b43c2f796e 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -396,6 +396,11 @@ bool THD::store_globals()
return 1;
mysys_var=my_thread_var;
dbug_thread_id=my_thread_id();
+ /*
+ By default 'slave_proxy_id' is 'thread_id'. They may later become different
+ if this is the slave SQL thread.
+ */
+ slave_proxy_id= thread_id;
return 0;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index c66ebb77020..7a8dc067256 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -481,7 +481,11 @@ public:
char priv_host[MAX_HOSTNAME];
/* remote (peer) port */
uint16 peer_port;
- /* Points to info-string that will show in SHOW PROCESSLIST */
+ /*
+ Points to info-string that we show in SHOW PROCESSLIST
+ You are supposed to update thd->proc_info only if you have coded
+ a time-consuming piece that MySQL can get stuck in for a long time.
+ */
const char *proc_info;
/* points to host if host is available, otherwise points to ip */
const char *host_or_ip;
@@ -510,6 +514,11 @@ public:
enum enum_server_command command;
uint32 server_id;
uint32 file_id; // for LOAD DATA INFILE
+ /*
+ Used in error messages to tell user in what part of MySQL we found an
+ error. E. g. when where= "having clause", if fix_fields() fails, user
+ will know that the error was in having clause.
+ */
const char *where;
time_t start_time,time_after_lock,user_time;
time_t connect_time,thr_create_time; // track down slow pthread_create
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index d6f8e2f66c7..b3c17167a3a 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -172,6 +172,7 @@ static int get_or_create_user_conn(THD *thd, const char *user,
}
}
thd->user_connect=uc;
+ uc->connections++;
end:
(void) pthread_mutex_unlock(&LOCK_user_conn);
return return_val;
@@ -314,14 +315,15 @@ int check_user(THD *thd, enum enum_server_command command,
thd->db_access=0;
/* Don't allow user to connect if he has done too many queries */
- if ((ur.questions || ur.updates ||
- ur.connections || max_user_connections) &&
- get_or_create_user_conn(thd,thd->user,thd->host_or_ip,&ur))
- DBUG_RETURN(-1);
- if (thd->user_connect && (thd->user_connect->user_resources.connections ||
- max_user_connections) &&
- check_for_max_user_connections(thd, thd->user_connect))
- DBUG_RETURN(-1);
+ if ((ur.questions || ur.updates || ur.connections ||
+ max_user_connections) &&
+ get_or_create_user_conn(thd,thd->user,thd->host_or_ip,&ur))
+ DBUG_RETURN(-1);
+ if (thd->user_connect &&
+ (thd->user_connect->user_resources.connections ||
+ max_user_connections) &&
+ check_for_max_user_connections(thd, thd->user_connect))
+ DBUG_RETURN(-1);
/* Change database if necessary: OK or FAIL is sent in mysql_change_db */
if (db && db[0])
@@ -386,42 +388,84 @@ void init_max_user_conn(void)
}
+/*
+ check if user has already too many connections
+
+ SYNOPSIS
+ check_for_max_user_connections()
+ thd Thread handle
+ uc User connect object
+
+ NOTES
+ If check fails, we decrease user connection count, which means one
+ shouldn't call decrease_user_connections() after this function.
+
+ RETURN
+ 0 ok
+ 1 error
+*/
+
static int check_for_max_user_connections(THD *thd, USER_CONN *uc)
{
int error=0;
DBUG_ENTER("check_for_max_user_connections");
+ (void) pthread_mutex_lock(&LOCK_user_conn);
if (max_user_connections &&
- (max_user_connections < (uint) uc->connections))
+ max_user_connections < (uint) uc->connections)
{
net_printf(thd,ER_TOO_MANY_USER_CONNECTIONS, uc->user);
error=1;
goto end;
}
- uc->connections++;
if (uc->user_resources.connections &&
- uc->conn_per_hour++ >= uc->user_resources.connections)
+ uc->user_resources.connections <= uc->conn_per_hour)
{
net_printf(thd, ER_USER_LIMIT_REACHED, uc->user,
"max_connections",
(long) uc->user_resources.connections);
error=1;
+ goto end;
}
-end:
+ uc->conn_per_hour++;
+
+ end:
+ if (error)
+ uc->connections--; // no need for decrease_user_connections() here
+ (void) pthread_mutex_unlock(&LOCK_user_conn);
DBUG_RETURN(error);
}
+/*
+ Decrease user connection count
+
+ SYNOPSIS
+ decrease_user_connections()
+ uc User connection object
+
+ NOTES
+ If there is a n user connection object for a connection
+ (which only happens if 'max_user_connections' is defined or
+ if someone has created a resource grant for a user), then
+ the connection count is always incremented on connect.
+
+ The user connect object is not freed if some users has
+ 'max connections per hour' defined as we need to be able to hold
+ count over the lifetime of the connection.
+*/
+
static void decrease_user_connections(USER_CONN *uc)
{
DBUG_ENTER("decrease_user_connections");
- if ((uc->connections && !--uc->connections) && !mqh_used)
+ (void) pthread_mutex_lock(&LOCK_user_conn);
+ DBUG_ASSERT(uc->connections);
+ if (!--uc->connections && !mqh_used)
{
/* Last connection for user; Delete it */
- (void) pthread_mutex_lock(&LOCK_user_conn);
(void) hash_delete(&hash_user_connections,(byte*) uc);
- (void) pthread_mutex_unlock(&LOCK_user_conn);
}
+ (void) pthread_mutex_unlock(&LOCK_user_conn);
DBUG_VOID_RETURN;
}
@@ -1227,15 +1271,17 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
char *save_user= thd->user;
char *save_priv_user= thd->priv_user;
char *save_db= thd->db;
- USER_CONN *save_uc= thd->user_connect;
- thd->user= my_strdup(user, MYF(0));
- if (!thd->user)
+ USER_CONN *save_user_connect= thd->user_connect;
+
+ if (!(thd->user= my_strdup(user, MYF(0))))
{
thd->user= save_user;
send_error(thd, ER_OUT_OF_RESOURCES);
break;
}
+ /* Clear variables that are allocated */
+ thd->user_connect= 0;
int res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, false);
if (res)
@@ -1246,6 +1292,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
x_free(thd->user);
thd->user= save_user;
thd->priv_user= save_priv_user;
+ thd->user_connect= save_user_connect;
thd->master_access= save_master_access;
thd->db_access= save_db_access;
thd->db= save_db;
@@ -1254,8 +1301,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
else
{
/* we've authenticated new user */
- if (max_connections && save_uc)
- decrease_user_connections(save_uc);
+ if (save_user_connect)
+ decrease_user_connections(save_user_connect);
x_free((gptr) save_db);
x_free((gptr) save_user);
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index bdaed894a52..3decbd62a2c 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1453,10 +1453,21 @@ JOIN::exec()
{
DBUG_VOID_RETURN;
}
+ /*
+ Here we sort rows for ORDER BY/GROUP BY clause, if the optimiser
+ chose FILESORT to be faster than INDEX SCAN or there is no
+ suitable index present.
+ Note, that create_sort_index calls test_if_skip_sort_order and may
+ finally replace sorting with index scan if there is a LIMIT clause in
+ the query. XXX: it's never shown in EXPLAIN!
+ OPTION_FOUND_ROWS supersedes LIMIT and is taken into account.
+ */
if (create_sort_index(thd, curr_join,
curr_join->group_list ?
curr_join->group_list : curr_join->order,
- curr_join->select_limit, unit->select_limit_cnt))
+ curr_join->select_limit,
+ (select_options & OPTION_FOUND_ROWS ?
+ HA_POS_ERROR : unit->select_limit_cnt)))
DBUG_VOID_RETURN;
}
}
@@ -2856,8 +2867,6 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
!(s->table->force_index && best_key))
{ // Check full join
ha_rows rnd_records= s->found_records;
- /* Estimate cost of reading table. */
- tmp= s->table->file->scan_time();
/*
If there is a restriction on the table, assume that 25% of the
rows can be skipped on next part.
@@ -2867,36 +2876,57 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
if (found_constraint)
rnd_records-= rnd_records/4;
- if (s->on_expr) // Can't use join cache
+ /*
+ Range optimizer never proposes a RANGE if it isn't better
+ than FULL: so if RANGE is present, it's always preferred to FULL.
+ Here we estimate its cost.
+ */
+ if (s->quick)
{
+ /*
+ For each record we:
+ - read record range through 'quick'
+ - skip rows which does not satisfy WHERE constraints
+ */
tmp= record_count *
- /* We have to read the whole table for each record */
- (tmp +
- /*
- And we have to skip rows which does not satisfy join
- condition for each record.
- */
- (s->records - rnd_records)/(double) TIME_FOR_COMPARE);
+ (s->quick->read_time +
+ (s->found_records - rnd_records)/(double) TIME_FOR_COMPARE);
}
else
{
- /* We read the table as many times as join buffer becomes full. */
- tmp*= (1.0 + floor((double) cache_record_length(join,idx) *
- record_count /
- (double) thd->variables.join_buff_size));
- /*
- We don't make full cartesian product between rows in the scanned
- table and existing records because we skip all rows from the
- scanned table, which does not satisfy join condition when
- we read the table (see flush_cached_records for details). Here we
- take into account cost to read and skip these records.
- */
- tmp+= (s->records - rnd_records)/(double) TIME_FOR_COMPARE;
+ /* Estimate cost of reading table. */
+ tmp= s->table->file->scan_time();
+ if (s->on_expr) // Can't use join cache
+ {
+ /*
+ For each record we have to:
+ - read the whole table record
+ - skip rows which does not satisfy join condition
+ */
+ tmp= record_count *
+ (tmp +
+ (s->records - rnd_records)/(double) TIME_FOR_COMPARE);
+ }
+ else
+ {
+ /* We read the table as many times as join buffer becomes full. */
+ tmp*= (1.0 + floor((double) cache_record_length(join,idx) *
+ record_count /
+ (double) thd->variables.join_buff_size));
+ /*
+ We don't make full cartesian product between rows in the scanned
+ table and existing records because we skip all rows from the
+ scanned table, which does not satisfy join condition when
+ we read the table (see flush_cached_records for details). Here we
+ take into account cost to read and skip these records.
+ */
+ tmp+= (s->records - rnd_records)/(double) TIME_FOR_COMPARE;
+ }
}
/*
We estimate the cost of evaluating WHERE clause for found records
- as record_count * rnd_records + TIME_FOR_COMPARE. This cost plus
+ as record_count * rnd_records / TIME_FOR_COMPARE. This cost plus
tmp give us total cost of using TABLE SCAN
*/
if (best == DBL_MAX ||
@@ -3320,6 +3350,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
table_map used_tables;
if (join->tables > 1)
cond->update_used_tables(); // Tablenr may have changed
+ if (join->const_tables == join->tables)
+ join->const_table_map|=RAND_TABLE_BIT;
{ // Check const tables
COND *const_cond=
make_cond_for_table(cond,join->const_table_map,(table_map) 0);
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index 47f0932b221..c14d30f8d34 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -22,7 +22,11 @@
#include "sql_select.h"
#include <hash.h>
#include <thr_alarm.h>
+#if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_H)
#include <malloc.h>
+#elif defined(HAVE_MALLINFO) && defined(HAVE_SYS_MALLOC_H)
+#include <sys/malloc.h>
+#endif
/* Intern key cache variables */
extern "C" pthread_mutex_t THR_LOCK_keycache;
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 8606830e450..e93e290bd4c 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -150,16 +150,19 @@ int rea_create_table(THD *thd, my_string file_name,
my_free((gptr) screen_buff,MYF(0));
my_free((gptr) keybuff, MYF(0));
- VOID(my_close(file,MYF(MY_WME)));
- if (ha_create_table(file_name,create_info,0))
+ if (my_sync(file, MYF(MY_WME)))
goto err2;
+ if (my_close(file,MYF(MY_WME)) ||
+ ha_create_table(file_name,create_info,0))
+ goto err3;
DBUG_RETURN(0);
err:
my_free((gptr) screen_buff,MYF(0));
my_free((gptr) keybuff, MYF(0));
+err2:
VOID(my_close(file,MYF(MY_WME)));
- err2:
+err3:
my_delete(file_name,MYF(0));
DBUG_RETURN(1);
} /* rea_create_table */
diff --git a/sql/unireg.h b/sql/unireg.h
index 66a274f3863..8d62959317d 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -43,7 +43,7 @@
#define ERRMAPP 1 /* Errormap f|r my_error */
#define LIBLEN FN_REFLEN-FN_LEN /* Max l{ngd p} dev */
-#define MAX_DBKEY_LENGTH (FN_LEN*2+6) /* extra 4 bytes for slave tmp
+#define MAX_DBKEY_LENGTH (FN_LEN*2+1+1+4+4) /* extra 4+4 bytes for slave tmp
* tables */
#define MAX_ALIAS_NAME 256
#define MAX_FIELD_NAME 34 /* Max colum name length +2 */
diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh
index dec77a15dc5..30ee4ab545f 100644
--- a/support-files/mysql.server.sh
+++ b/support-files/mysql.server.sh
@@ -109,19 +109,6 @@ else
fi
#
-# Set pid file if not given
-#
-if test -z "$pid_file"
-then
- pid_file=$datadir/`@HOSTNAME@`.pid
-else
- case "$pid_file" in
- /* ) ;;
- * ) pid_file="$datadir/$pid_file" ;;
- esac
-fi
-
-#
# Test if someone changed datadir; In this case we should also read the
# default arguments from this directory
#
@@ -134,6 +121,19 @@ fi
parse_arguments `$print_defaults $extra_args mysqld server mysql_server mysql.server`
+#
+# Set pid file if not given
+#
+if test -z "$pid_file"
+then
+ pid_file=$datadir/`@HOSTNAME@`.pid
+else
+ case "$pid_file" in
+ /* ) ;;
+ * ) pid_file="$datadir/$pid_file" ;;
+ esac
+fi
+
# Safeguard (relative paths, core dumps..)
cd $basedir