Merge with 4.0
BitKeeper/etc/logging_ok: auto-union BitKeeper/deleted/.del-apply-patch: Delete: netware/BUILD/apply-patch BitKeeper/deleted/.del-save-patch: Delete: netware/BUILD/save-patch BitKeeper/deleted/.del-mini_client.cc~8677895ec8169183: Auto merged BitKeeper/triggers/post-commit: Auto merged VC++Files/mysys/mysys.dsp: Auto merged client/mysqlbinlog.cc: Auto merged extra/resolveip.c: Auto merged include/config-win.h: Auto merged include/my_global.h: Auto merged include/my_sys.h: Auto merged include/mysql_com.h: Auto merged innobase/include/os0thread.h: Auto merged innobase/os/os0file.c: Auto merged innobase/srv/srv0start.c: Auto merged innobase/thr/thr0loc.c: Auto merged libmysql/manager.c: Auto merged libmysqld/Makefile.am: Auto merged libmysqld/lib_sql.cc: Auto merged myisam/ft_boolean_search.c: Auto merged myisam/mi_extra.c: Auto merged myisam/mi_locking.c: Auto merged mysql-test/mysql-test-run.sh: Auto merged mysql-test/r/fulltext.result: Auto merged mysql-test/r/myisam.result: Auto merged mysql-test/r/select.result: Auto merged mysql-test/t/fulltext.test: Auto merged mysql-test/t/myisam.test: Auto merged mysql-test/t/rpl_reset_slave.test: Auto merged mysql-test/t/rpl_trunc_binlog.test: Auto merged mysys/Makefile.am: Auto merged mysys/errors.c: Auto merged mysys/my_symlink.c: Auto merged mysys/my_thr_init.c: Auto merged scripts/mysql_install_db.sh: Auto merged sql/item_func.cc: Auto merged sql/log_event.h: Auto merged sql/mysqld.cc: Auto merged sql/slave.cc: Auto merged sql/sql_cache.cc: Auto merged sql/sql_class.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_repl.cc: Auto merged sql/sql_test.cc: Auto merged sql/unireg.h: Auto merged client/mysqldump.c: merge with 4.0 (quoted names) configure.in: use local file include/my_pthread.h: Use local file innobase/include/srv0srv.h: Use local file innobase/row/row0sel.c: Use local file innobase/srv/srv0srv.c: Use local file libmysql/libmysql.c: Use local file myisam/myisamchk.c: merge fixes mysql-test/r/func_crypt.result: update results mysql-test/r/order_by.result: update results mysql-test/r/query_cache.result: update results mysql-test/r/range.result: update results mysql-test/r/rpl_reset_slave.result: update results mysql-test/r/rpl_trunc_binlog.result: update results mysql-test/t/func_crypt.test: Added disable_warnings/enable warnings mysql-test/t/query_cache.test: merge tests mysql-test/t/range.test: merge tests mysys/charset.c: use local file (will merge patch separately) sql/ha_innodb.cc: use local file sql/log_event.cc: new slave_proxy_id handling sql/slave.h: merge sql/sql_base.cc: merge sql/sql_parse.cc: Fixes for counting user connect resourses Added function comments for involved functions sql/sql_select.cc: Fix for not doing sort with LIMIT when OPTION_FOUND_ROWS is used sql/unireg.cc: merge fixes support-files/mysql.server.sh: merge fixes
This commit is contained in:
commit
f97f48acaf
@ -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@
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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[] =
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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, ...)
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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(
|
||||
|
@ -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++) {
|
||||
|
@ -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) {
|
||||
|
10
isam/extra.c
10
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:
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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'Á');
|
||||
|
@ -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) ;
|
||||
|
30
mysql-test/r/rpl_chain_temp_table.result
Normal file
30
mysql-test/r/rpl_chain_temp_table.result
Normal file
@ -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;
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
#
|
||||
|
@ -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');
|
||||
|
@ -1 +0,0 @@
|
||||
--set-variable=query_cache_size=1355776
|
@ -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
|
||||
|
||||
@ -489,6 +490,55 @@ show status like "Qcache_queries_in_cache";
|
||||
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
|
||||
@ -535,3 +585,4 @@ show status like "Qcache_queries_in_cache";
|
||||
# Keep things tidy
|
||||
#
|
||||
DROP TABLE t1;
|
||||
SET GLOBAL query_cache_size=0;
|
||||
|
@ -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
|
||||
|
99
mysql-test/t/rpl_chain_temp_table.test
Normal file
99
mysql-test/t/rpl_chain_temp_table.test
Normal file
@ -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.
|
@ -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';
|
||||
|
@ -23,5 +23,3 @@ sleep 3;
|
||||
--replace_result $MASTER_MYPORT MASTER_PORT
|
||||
--replace_column 1 # 33 #
|
||||
show slave status;
|
||||
connection master;
|
||||
reset master;
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
60
mysys/my_sync.c
Normal file
60
mysys/my_sync.c
Normal file
@ -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 */
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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 ( (, ), |, !,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
27
sql/slave.cc
27
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
@ -1693,6 +1705,9 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
|
||||
strmov(tmp_table->table_cache_key,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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -108,19 +108,6 @@ else
|
||||
test -z "$print_defaults" && print_defaults="my_print_defaults"
|
||||
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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user