diff --git a/.bzrignore b/.bzrignore index 17fee4a6fc1..7d35c950ee3 100644 --- a/.bzrignore +++ b/.bzrignore @@ -253,6 +253,7 @@ depcomp extra/comp_err extra/my_print_defaults extra/mysql_install +extra/mysql_waitpid extra/perror extra/replace extra/resolve_stack_dump @@ -350,6 +351,7 @@ libmysqld/opt_range.cc libmysqld/opt_sum.cc libmysqld/password.c libmysqld/procedure.cc +libmysqld/protocol.cc libmysqld/records.cc libmysqld/repl_failsafe.cc libmysqld/set_var.cc @@ -569,6 +571,7 @@ support-files/mysql-log-rotate support-files/mysql.server support-files/mysql.spec tags +test_xml tests/client_test tmp/* tools/my_vsnprintf.c @@ -579,6 +582,3 @@ vio/test-ssl vio/test-sslclient vio/test-sslserver vio/viotest-ssl -libmysqld/protocol.cc -test_xml -extra/mysql_waitpid diff --git a/BUILD/compile-alpha-cxx b/BUILD/compile-alpha-cxx index 3e6eee9a0d6..a342d927868 100755 --- a/BUILD/compile-alpha-cxx +++ b/BUILD/compile-alpha-cxx @@ -4,7 +4,7 @@ make -k clean /bin/rm -f */.deps/*.P config.cache innobase/config.cache bdb/build_unix/config.cache mysql-*.tar.gz aclocal; autoheader; aclocal; automake; autoconf -CC=ccc CFLAGS="-fast" CXX=cxx CXXFLAGS="-fast -noexceptions -nortti" ./configure --prefix=/usr/local/mysql --disable-shared --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-non_shared --with-client-ldflags=-non_shared --without-extra-tools +CC=ccc CFLAGS="-fast" CXX=cxx CXXFLAGS="-fast -noexceptions -nortti" ./configure --prefix=/usr/local/mysql --disable-shared --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-non_shared --with-client-ldflags=-non_shared --without-extra-tools --disable-dependency-tracking make -j2 find . -name ".deps" | xargs rm -r diff --git a/Makefile.am b/Makefile.am index 87d1c7b5b71..7949e7be776 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,10 +21,10 @@ AUTOMAKE_OPTIONS = foreign # These are built from source in the Docs directory EXTRA_DIST = INSTALL-SOURCE README \ COPYING COPYING.LIB -SUBDIRS = include @docs_dirs@ @readline_dir@ \ +SUBDIRS = . include @docs_dirs@ @readline_dir@ \ @thread_dirs@ pstack @sql_client_dirs@ \ - @sql_server_dirs@ @libmysqld_dirs@ scripts man \ - tests BUILD os2 \ + @sql_server_dirs@ scripts man tests \ + BUILD os2 libmysql_r @libmysqld_dirs@ \ @bench_dirs@ support-files @fs_dirs@ @tools_dirs@ # Relink after clean diff --git a/client/mysqltest.c b/client/mysqltest.c index f3037fcc173..8138450680e 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -42,7 +42,7 @@ **********************************************************************/ -#define MTEST_VERSION "1.26" +#define MTEST_VERSION "1.27" #include #include @@ -684,7 +684,7 @@ int open_file(const char* name) if (*cur_file && cur_file == file_stack_end) die("Source directives are nesting too deep"); - if (!(*(cur_file+1) = my_fopen(buff, O_RDONLY, MYF(MY_WME)))) + if (!(*(cur_file+1) = my_fopen(buff, O_RDONLY | O_BINARY, MYF(MY_WME)))) die(NullS); cur_file++; *++lineno=1; @@ -1924,7 +1924,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), argument= buff; } fn_format(buff, argument, "", "", 4); - if (!(*++cur_file = my_fopen(buff, O_RDONLY, MYF(MY_WME)))) + if (!(*++cur_file = my_fopen(buff, O_RDONLY | O_BINARY, MYF(MY_WME)))) die("Could not open %s: errno = %d", argument, errno); break; } diff --git a/configure.in b/configure.in index f2e64ddffe4..38e050404b8 100644 --- a/configure.in +++ b/configure.in @@ -2311,6 +2311,7 @@ EOF if test X"$have_innodb" = Xyes then + innodb_conf_flags="" sql_server_dirs="$sql_server_dirs innobase" echo "CONFIGURING FOR INNODB" if test ! -d "innobase"; then @@ -2323,7 +2324,11 @@ EOF /* ) rel_srcdir="$srcdir" ;; * ) rel_srcdir="../$srcdir" ;; esac - (cd innobase && sh $rel_srcdir/innobase/configure) \ + if test "x$enable_dependency_tracking" == xno + then + innodb_conf_flags=--disable-dependency-tracking + fi + (cd innobase && sh $rel_srcdir/innobase/configure $innodb_conf_flags) \ || AC_MSG_ERROR([could not configure INNODB]) echo "END OF INNODB CONFIGURATION" diff --git a/extra/mysql_waitpid.c b/extra/mysql_waitpid.c index 14d3f893c60..007db959111 100644 --- a/extra/mysql_waitpid.c +++ b/extra/mysql_waitpid.c @@ -1,9 +1,26 @@ -#include +/* 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 */ + +/* Wait until a program dies */ + +#include +#include +#include #include #include -#include -#include -#include static const char *VER= "1.1"; static char *progname; diff --git a/include/my_global.h b/include/my_global.h index 749a326f86f..3b66b3cbc16 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -153,6 +153,13 @@ C_MODE_END #undef HAVE_INITGROUPS #endif +/* gcc/egcs issues */ + +#if defined(__GNUC) && defined(__EXCEPTIONS) +#error "Please add -fno-exceptions to CXXFLAGS and reconfigure/recompile" +#endif + + /* Fix a bug in gcc 2.8.0 on IRIX 6.2 */ #if SIZEOF_LONG == 4 && defined(__LONG_MAX__) #undef __LONG_MAX__ /* Is a longlong value in gcc 2.8.0 ??? */ diff --git a/include/my_pthread.h b/include/my_pthread.h index f75ca8f601a..e0394bc978a 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -581,9 +581,13 @@ extern int pthread_dummy(int); #define THREAD_NAME_SIZE 10 #if defined(__ia64__) -#define DEFAULT_THREAD_STACK (128*1024) +/* + MySQL can survive with 32K, but some glibc libraries require > 128K stack + To resolve hostnames +*/ +#define DEFAULT_THREAD_STACK (192*1024L) #else -#define DEFAULT_THREAD_STACK (64*1024) +#define DEFAULT_THREAD_STACK (192*1024L) #endif struct st_my_thread_var diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c index a1665aefab7..51c164b7cef 100644 --- a/innobase/btr/btr0btr.c +++ b/innobase/btr/btr0btr.c @@ -135,7 +135,7 @@ btr_page_insert_fits( /****************************************************************** Gets the root node of a tree and x-latches it. */ -static + page_t* btr_root_get( /*=========*/ @@ -146,9 +146,6 @@ btr_root_get( ulint space; ulint root_page_no; page_t* root; - - ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), MTR_MEMO_X_LOCK) - || mtr_memo_contains(mtr, dict_tree_get_lock(tree), MTR_MEMO_S_LOCK)); space = dict_tree_get_space(tree); root_page_no = dict_tree_get_page(tree); @@ -334,8 +331,6 @@ btr_page_alloc( page_t* new_page; ulint new_page_no; - ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), - MTR_MEMO_X_LOCK)); if (tree->type & DICT_IBUF) { return(btr_page_alloc_for_ibuf(tree, mtr)); diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index e1d12c9adc4..2416149c3a8 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -3183,7 +3183,7 @@ btr_store_big_rec_extern_fields( ut_ad(mtr_memo_contains(local_mtr, dict_tree_get_lock(index->tree), MTR_MEMO_X_LOCK)); - ut_ad(mtr_memo_contains(local_mtr, buf_block_align(data), + ut_ad(mtr_memo_contains(local_mtr, buf_block_align(rec), MTR_MEMO_PAGE_X_FIX)); ut_a(index->type & DICT_CLUSTERED); @@ -3318,7 +3318,13 @@ void btr_free_externally_stored_field( /*=============================*/ dict_index_t* index, /* in: index of the data, the index - tree MUST be X-latched */ + tree MUST be X-latched; if the tree + height is 1, then also the root page + must be X-latched! (this is relevant + in the case this function is called + from purge where 'data' is located on + an undo log page, not an index + page) */ byte* data, /* in: internally stored data + reference to the externally stored part */ diff --git a/innobase/include/btr0btr.h b/innobase/include/btr0btr.h index 3cd44ab5175..8606fcd2a5c 100644 --- a/innobase/include/btr0btr.h +++ b/innobase/include/btr0btr.h @@ -55,6 +55,15 @@ UNIQUE definition on secondary indexes when we decide if we can use the insert buffer to speed up inserts */ #define BTR_IGNORE_SEC_UNIQUE 2048 +/****************************************************************** +Gets the root node of a tree and x-latches it. */ + +page_t* +btr_root_get( +/*=========*/ + /* out: root page, x-latched */ + dict_tree_t* tree, /* in: index tree */ + mtr_t* mtr); /* in: mtr */ /****************************************************************** Gets a buffer page and declares its latching order level. */ UNIV_INLINE diff --git a/innobase/include/btr0cur.h b/innobase/include/btr0cur.h index 7039ceba245..1d17c0e952d 100644 --- a/innobase/include/btr0cur.h +++ b/innobase/include/btr0cur.h @@ -507,7 +507,13 @@ void btr_free_externally_stored_field( /*=============================*/ dict_index_t* index, /* in: index of the data, the index - tree MUST be X-latched */ + tree MUST be X-latched; if the tree + height is 1, then also the root page + must be X-latched! (this is relevant + in the case this function is called + from purge where 'data' is located on + an undo log page, not an index + page) */ byte* data, /* in: internally stored data + reference to the externally stored part */ diff --git a/innobase/page/page0cur.c b/innobase/page/page0cur.c index bb49e9080ce..1ea6e3e3018 100644 --- a/innobase/page/page0cur.c +++ b/innobase/page/page0cur.c @@ -253,7 +253,8 @@ page_cur_search_with_match( up_matched_bytes = cur_matched_bytes; } - } else if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_LE)) { + } else if (mode == PAGE_CUR_G || mode == PAGE_CUR_LE + || mode == PAGE_CUR_LE_OR_EXTENDS) { low = mid; low_matched_fields = cur_matched_fields; low_matched_bytes = cur_matched_bytes; @@ -308,7 +309,8 @@ page_cur_search_with_match( up_matched_fields = cur_matched_fields; up_matched_bytes = cur_matched_bytes; } - } else if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_LE)) { + } else if (mode == PAGE_CUR_G || mode == PAGE_CUR_LE + || mode == PAGE_CUR_LE_OR_EXTENDS) { low_rec = mid_rec; low_matched_fields = cur_matched_fields; low_matched_bytes = cur_matched_bytes; diff --git a/innobase/row/row0purge.c b/innobase/row/row0purge.c index b64003f22d4..104d71eda2d 100644 --- a/innobase/row/row0purge.c +++ b/innobase/row/row0purge.c @@ -429,7 +429,18 @@ skip_secondaries: index = dict_table_get_first_index(node->table); mtr_x_lock(dict_tree_get_lock(index->tree), &mtr); + + /* NOTE: we must also acquire an X-latch to the + root page of the tree. We will need it when we + free pages from the tree. If the tree is of height 1, + the tree X-latch does NOT protect the root page, + because it is also a leaf page. Since we will have a + latch on an undo log page, we would break the + latching order if we would only later latch the + root page of such a tree! */ + btr_root_get(index->tree, &mtr); + /* We assume in purge of externally stored fields that the space id of the undo log record is 0! */ diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 6612b2006eb..2bdcbe29758 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -1727,6 +1727,7 @@ srv_conc_enter_innodb( ibool has_slept = FALSE; srv_conc_slot_t* slot; ulint i; + char err_buf[1000]; if (srv_thread_concurrency >= 500) { /* Disable the concurrency check */ @@ -1745,6 +1746,16 @@ srv_conc_enter_innodb( retry: os_fast_mutex_lock(&srv_conc_mutex); + if (trx->declared_to_be_inside_innodb) { + ut_print_timestamp(stderr); + + trx_print(err_buf, trx); + + fprintf(stderr, +" InnoDB: Error: trying to declare trx to enter InnoDB, but\n" +"InnoDB: it already is declared.\n%s\n", err_buf); + } + if (srv_conc_n_threads < (lint)srv_thread_concurrency) { srv_conc_n_threads++; @@ -1815,8 +1826,12 @@ retry: /* Go to wait for the event; when a thread leaves InnoDB it will release this thread */ + trx->op_info = "waiting in InnoDB queue"; + os_event_wait(slot->event); + trx->op_info = ""; + os_fast_mutex_lock(&srv_conc_mutex); srv_conc_n_waiting_threads--; diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index f0077f941de..5ac49397c90 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -233,8 +233,19 @@ trx_free( /*=====*/ trx_t* trx) /* in, own: trx object */ { + char err_buf[1000]; + ut_ad(mutex_own(&kernel_mutex)); + if (trx->declared_to_be_inside_innodb) { + ut_print_timestamp(stderr); + trx_print(err_buf, trx); + + fprintf(stderr, +" InnoDB: Error: Freeing a trx which is declared to be processing\n" +"InnoDB: inside InnoDB.\n%s\n", err_buf); + } + ut_a(trx->magic_n == TRX_MAGIC_N); trx->magic_n = 11112222; @@ -1506,10 +1517,10 @@ trx_print( #ifdef UNIV_LINUX buf += sprintf(buf, ", process no %lu", trx->mysql_process_no); -#else +#endif buf += sprintf(buf, ", OS thread id %lu", os_thread_pf(trx->mysql_thread_id)); -#endif + if (ut_strlen(trx->op_info) > 0) { buf += sprintf(buf, " %s", trx->op_info); } @@ -1518,6 +1529,11 @@ trx_print( buf += sprintf(buf, " purge trx"); } + if (trx->declared_to_be_inside_innodb) { + buf += sprintf(buf, ", thread declared inside InnoDB %lu", + trx->n_tickets_to_enter_innodb); + } + buf += sprintf(buf, "\n"); start_of_line = buf; diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index 47b582bc78e..1f74cc23678 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -84,6 +84,8 @@ clean-local: rm -f `echo $(mystringsobjects) | sed "s;\.lo;.c;g"` \ `echo $(dbugobjects) | sed "s;\.lo;.c;g"` \ `echo $(mysysobjects) | sed "s;\.lo;.c;g"` \ + `echo $(vio_objects) | sed "s;\.lo;.c;g"` \ + $(CHARSET_SRCS) $(CHARSET_OBJS) \ $(mystringsextra) $(mysysheaders) \ ../linked_client_sources net.c diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def index 0d650467665..38fb1eaa187 100644 --- a/libmysql/libmysql.def +++ b/libmysql/libmysql.def @@ -100,6 +100,12 @@ EXPORTS mysql_rpl_probe mysql_set_master mysql_add_slave + my_getopt_print_errors + handle_options + my_print_help + my_print_variables + getopt_ull_limit_value + getopt_compare_strings mysql_warning_count mysql_warnings mysql_prepare diff --git a/ltconfig b/ltconfig index 5c6366c9890..a5011a81c19 100755 --- a/ltconfig +++ b/ltconfig @@ -3009,6 +3009,16 @@ hardcode_action=$hardcode_action # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec +# Check if debuild is being run by the current shell. If it is then, +# the DEB_BUILD_ARCH variable should be of non-zero length, indicating +# that we are in the middle of a Debian package build (assuming the +# user isn't doing anything strange with environment variables). +if test -n "`dpkg-architecture -qDEB_BUILD_ARCH`" && ps | grep debuild | grep -v grep > /dev/null; then + # Debian policy mandates that rpaths should not be encoded into a binary + # so it is overridden. + hardcode_libdir_flag_spec=" -D_DEBIAN_PATCHED_LIBTOOL_ " +fi + # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$hardcode_libdir_separator diff --git a/man/isamchk.1 b/man/isamchk.1 index 2552d9f80cd..bfc4ccd9c08 100644 --- a/man/isamchk.1 +++ b/man/isamchk.1 @@ -1,4 +1,4 @@ -.TH ISAMCHK 1 "19 December 2000" +.TH isamchk 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME .BR isamchk \- Description, check and repair of ISAM tables. diff --git a/man/isamlog.1 b/man/isamlog.1 index ef6ceaff8da..a386f11c010 100644 --- a/man/isamlog.1 +++ b/man/isamlog.1 @@ -1,4 +1,4 @@ -.TH ISAMLOG 1 "20 December 2000" +.TH isamlog 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME isamlog - Write info about whats in a nisam log file. .SH USAGE diff --git a/man/mysql.1 b/man/mysql.1 index e10fd589092..6664581072f 100644 --- a/man/mysql.1 +++ b/man/mysql.1 @@ -1,4 +1,4 @@ -.TH MYSQL 1 "13 June 1997" +.TH mysql 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME mysql \- text-based client for mysqld, a SQL-based relational database daemon .SH SYNOPSIS diff --git a/man/mysql_zap.1 b/man/mysql_zap.1 index e57eb7a4d07..144fc212372 100644 --- a/man/mysql_zap.1 +++ b/man/mysql_zap.1 @@ -1,4 +1,4 @@ -.TH ZAP 1 "20 December 2000" +.TH zap 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME zap - a perl script used to kill processes .SH USAGE diff --git a/man/mysqlaccess.1 b/man/mysqlaccess.1 index 0ae06dca137..c1c61d4a8a7 100644 --- a/man/mysqlaccess.1 +++ b/man/mysqlaccess.1 @@ -1,4 +1,4 @@ -.TH MYSQLACCESS 1 "19 December 2000" +.TH mysqlaccess 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME .BR mysqlaccess \- Create new users to mysql. diff --git a/man/mysqladmin.1 b/man/mysqladmin.1 index 1e435006bb2..9d7d73aad21 100644 --- a/man/mysqladmin.1 +++ b/man/mysqladmin.1 @@ -1,4 +1,4 @@ -.TH MYSQLADMIN 1 "18 December 2000" +.TH mysqladmin 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME mysqladmin [OPTIONS] command command.... \- A utility for performing administrative operations .SH OPTION SYNOPSIS diff --git a/man/mysqld.1 b/man/mysqld.1 index 1f87eb9cf32..0a6fcccbef2 100644 --- a/man/mysqld.1 +++ b/man/mysqld.1 @@ -1,4 +1,4 @@ -.TH MYSQLD 1 "19 December 2000" +.TH mysqld 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME .BR mysqld \- Starts the MySQL server demon diff --git a/man/mysqld_multi.1 b/man/mysqld_multi.1 index b7aa77f656d..68b9d1e876f 100644 --- a/man/mysqld_multi.1 +++ b/man/mysqld_multi.1 @@ -1,4 +1,4 @@ -.TH MYSQLD_MULTI 1 "20 December 2000" +.TH mysqld_multi 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME mysqld_multi - is meant for managing several mysqld processes running in different UNIX sockets and TCP/IP ports. .SH USAGE diff --git a/man/mysqld_safe.1 b/man/mysqld_safe.1 index c900d193929..b8271c848cc 100644 --- a/man/mysqld_safe.1 +++ b/man/mysqld_safe.1 @@ -1,4 +1,4 @@ -.TH SAFE_MYSQLD 1 "19 December 2000" "safe_mysqld (mysql)" mysql.com +.TH safe_mysqld 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME mysqld_safe \- start the mysqld daemon on Unix. .SH SYNOPSIS diff --git a/man/mysqldump.1 b/man/mysqldump.1 index b9e5aa33791..b4aba2ade13 100644 --- a/man/mysqldump.1 +++ b/man/mysqldump.1 @@ -1,4 +1,4 @@ -.TH MYSQLDUMP 1 "19 December 2000" +.TH mysqldump 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME mysqldump \- text-based client for dumping or backing up mysql databases , tables and or data. @@ -123,7 +123,7 @@ Connect to host. Lock all tables for read. .TP .BR \-n | \-\-no\-create\-db -'CREATE DATABASE /*!32312 IF NOT EXISTS*/ db_name;' +\&'CREATE DATABASE /*!32312 IF NOT EXISTS*/ db_name;' will not be put in the output. The above line will be added otherwise, if .BR \-\-databases @@ -270,4 +270,4 @@ Manual page by L. (Kill-9) Pedersen (kill-9@kill-9.dk), Mercurmedia Data Model Architect / system developer (http://www.mercurmedia.com) -.\" end of man page \ No newline at end of file +.\" end of man page diff --git a/man/mysqlshow.1 b/man/mysqlshow.1 index 661b2cd02c8..b6aceec82e3 100644 --- a/man/mysqlshow.1 +++ b/man/mysqlshow.1 @@ -1,4 +1,4 @@ -.TH MYSQLSHOW 1 "19 December 2000" +.TH mysqlshow 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME .BR mysqlshow \- Shows the structure of a mysql database (databases,tables and columns) diff --git a/man/perror.1 b/man/perror.1 index 7adf99ea772..38a51593ba1 100644 --- a/man/perror.1 +++ b/man/perror.1 @@ -1,4 +1,4 @@ -.TH PERROR 1 "19 December 2000" +.TH perror 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME .BR perror can be used to display a description for a system error code, or an MyISAM/ISAM table handler error code. The error messages are mostly system dependent. diff --git a/man/replace.1 b/man/replace.1 index 38ffe998027..7c3b79f605b 100644 --- a/man/replace.1 +++ b/man/replace.1 @@ -1,4 +1,4 @@ -.TH REPLACE 1 "20 December 2000" +.TH replace 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME .TP replace - A utility program that is used by msql2mysql, but that has more general applicability as well. replace changes strings in place in files or on the standard input. Uses a finite state machine to match longer strings first. Can be used to swap strings. diff --git a/myisam/mi_create.c b/myisam/mi_create.c index 8087d17904a..8b33930bcf3 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -230,7 +230,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, if (uniques) { max_key_block_length= myisam_block_size; - max_key_length= MI_UNIQUE_HASH_LENGTH; + max_key_length= MI_UNIQUE_HASH_LENGTH + pointer; } for (i=0, keydef=keydefs ; i < keys ; i++ , keydef++) diff --git a/myisam/mi_unique.c b/myisam/mi_unique.c index 682f946eba7..3eb25aefe0e 100644 --- a/myisam/mi_unique.c +++ b/myisam/mi_unique.c @@ -24,7 +24,7 @@ my_bool mi_check_unique(MI_INFO *info, MI_UNIQUEDEF *def, byte *record, { my_off_t lastpos=info->lastpos; MI_KEYDEF *key= &info->s->keyinfo[def->key]; - uchar *key_buff=info->lastkey+info->s->base.max_key_length; + uchar *key_buff=info->lastkey2; DBUG_ENTER("mi_check_unique"); mi_unique_store(record+key->seg->start, unique_hash); @@ -80,7 +80,16 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record) if (keyseg->null_bit) { if (record[keyseg->null_pos] & keyseg->null_bit) + { + /* + Change crc in a way different from an empty string or 0. + (This is an optimisation; The code will work even if this isn't + done) + */ + crc=((crc << 8) + 511+ + (crc >> (8*sizeof(ha_checksum)-8))); continue; + } } pos= record+keyseg->start; if (keyseg->flag & HA_VAR_LENGTH) diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index 281cb90d9bf..1b180a728ba 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -130,7 +130,7 @@ int main(int argc, char **argv) char buff[22],buff2[22]; if (!(check_param.testflag & T_SILENT) || check_param.testflag & T_INFO) puts("\n---------\n"); - printf("\nTotal of all %d ISAM-files:\nData records: %9s Deleted blocks: %9s\n",check_param.total_files,llstr(check_param.total_records,buff), + printf("\nTotal of all %d MyISAM-files:\nData records: %9s Deleted blocks: %9s\n",check_param.total_files,llstr(check_param.total_records,buff), llstr(check_param.total_deleted,buff2)); } free_defaults(default_argv); @@ -330,7 +330,7 @@ static void usage(void) print_version(); puts("By Monty, for your professional use"); puts("This software comes with NO WARRANTY: see the PUBLIC for details.\n"); - puts("Description, check and repair of ISAM tables."); + puts("Description, check and repair of MyISAM tables."); puts("Used without options all tables on the command will be checked for errors"); printf("Usage: %s [OPTIONS] tables[.MYI]\n", my_progname); puts("\nGlobal options:\n\ @@ -1693,7 +1693,7 @@ void mi_check_print_error(MI_CHECK *param, const char *fmt,...) if (!param->warning_printed && !param->error_printed) { if (param->testflag & T_SILENT) - fprintf(stderr,"%s: ISAM file %s\n",my_progname,param->isam_file_name); + fprintf(stderr,"%s: MyISAM file %s\n",my_progname,param->isam_file_name); param->out_flag|= O_DATA_LOST; } param->error_printed|=1; diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index edd573f50a3..1d730e3f7c5 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -332,7 +332,7 @@ while test $# -gt 0; do VALGRIND="valgrind --alignment=8 --leak-check=yes" EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-safemalloc" EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-safemalloc" - #SLEEP_TIME_AFTER_RESTART=120 + SLEEP_TIME_AFTER_RESTART=10 SLEEP_TIME_FOR_DELETE=60 ;; --valgrind-options=*) diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index aa3de48c09e..a63054da88b 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -468,3 +468,17 @@ NOT NULL); max(value) 4 drop table t1,t2,t3; +create table t1 (a blob null); +insert into t1 values (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(""),(""),(""),("b"); +select a,count(*) from t1 group by a; +a count(*) +NULL 9 + 3 +b 1 +set option sql_big_tables=1; +select a,count(*) from t1 group by a; +a count(*) +NULL 9 + 3 +b 1 +drop table t1; diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index 9199f291c08..b28607218d1 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -260,7 +260,7 @@ t3 CREATE TABLE `t3` ( `othr` int(11) NOT NULL default '0' ) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(t1,t2) drop table t3,t2,t1; -create table t1 (a int not null) type=merge; +create table t1 (a int not null, key(a)) type=merge; select * from t1; a drop table t1; @@ -536,7 +536,7 @@ INSERT INTO t2 VALUES (1,2), (2,2); CREATE TABLE t3 ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', KEY a (a,b)) TYPE=MRG_MyISAM UNION=(t1,t2); select max(b) from t3 where a = 2; max(b) -NULL +2 select max(b) from t1 where a = 2; max(b) 1 diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result index 91af34b6681..08612fa191f 100644 --- a/mysql-test/r/null.result +++ b/mysql-test/r/null.result @@ -73,3 +73,39 @@ b ifnull(t2.b,"this is null") NULL this is null NULL this is null drop table t1; +CREATE TABLE t1 (a varchar(16) NOT NULL, b smallint(6) NOT NULL, c datetime NOT NULL, d smallint(6) NOT NULL); +INSERT INTO t1 SET a = "", d= "2003-01-14 03:54:55"; +UPDATE t1 SET d=1/NULL; +UPDATE t1 SET d=NULL; +INSERT INTO t1 (a) values (null); +Column 'a' cannot be null +INSERT INTO t1 (a) values (1/null); +Column 'a' cannot be null +INSERT INTO t1 (a) values (null),(null); +INSERT INTO t1 (b) values (null); +Column 'b' cannot be null +INSERT INTO t1 (b) values (1/null); +Column 'b' cannot be null +INSERT INTO t1 (b) values (null),(null); +INSERT INTO t1 (c) values (null); +Column 'c' cannot be null +INSERT INTO t1 (c) values (1/null); +Column 'c' cannot be null +INSERT INTO t1 (c) values (null),(null); +INSERT INTO t1 (d) values (null); +Column 'd' cannot be null +INSERT INTO t1 (d) values (1/null); +Column 'd' cannot be null +INSERT INTO t1 (d) values (null),(null); +select * from t1; +a b c d + 0 0000-00-00 00:00:00 0 + 0 0000-00-00 00:00:00 0 + 0 0000-00-00 00:00:00 0 + 0 0000-00-00 00:00:00 0 + 0 0000-00-00 00:00:00 0 + 0 0000-00-00 00:00:00 0 + 0 0000-00-00 00:00:00 0 + 0 0000-00-00 00:00:00 0 + 0 0000-00-00 00:00:00 0 +drop table t1; diff --git a/mysql-test/r/rpl_loaddata.result b/mysql-test/r/rpl_loaddata.result new file mode 100644 index 00000000000..27f3d185f63 --- /dev/null +++ b/mysql-test/r/rpl_loaddata.result @@ -0,0 +1,13 @@ +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; +create table t1(a int not null auto_increment, b int, primary key(a) ); +load data infile '../../std_data/rpl_loaddata.dat' into table t1; +select * from t1; +a b +1 10 +2 15 +drop table t1; diff --git a/mysql-test/std_data/rpl_loaddata.dat b/mysql-test/std_data/rpl_loaddata.dat new file mode 100644 index 00000000000..a70a059c2ab --- /dev/null +++ b/mysql-test/std_data/rpl_loaddata.dat @@ -0,0 +1,2 @@ +\N 10 +\N 15 diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index a34c3a12363..bca86f1ef37 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -363,3 +363,14 @@ m.c1id = c1.id AND c1.active = 'Yes' LEFT JOIN t3 AS c2 ON m.c2id = c2.id AND c2.active = 'Yes' WHERE m.pid=1 AND (c1.id IS NOT NULL OR c2.id IS NOT NULL); drop table t1,t2,t3; + +# +# Test bug in GROUP BY on BLOB that is NULL or empty +# + +create table t1 (a blob null); +insert into t1 values (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(""),(""),(""),("b"); +select a,count(*) from t1 group by a; +set option sql_big_tables=1; +select a,count(*) from t1 group by a; +drop table t1; diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index f84e10b0e3c..7a7678afca1 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -109,7 +109,7 @@ drop table t3,t2,t1; # # Test table without unions # -create table t1 (a int not null) type=merge; +create table t1 (a int not null, key(a)) type=merge; select * from t1; drop table t1; diff --git a/mysql-test/t/null.test b/mysql-test/t/null.test index 087ef81e13e..fa36249dce0 100644 --- a/mysql-test/t/null.test +++ b/mysql-test/t/null.test @@ -52,3 +52,34 @@ insert into t1 values(10,null); select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on t2.b=t3.a order by 1; drop table t1; + +# +# Test inserting and updating with NULL +# +CREATE TABLE t1 (a varchar(16) NOT NULL, b smallint(6) NOT NULL, c datetime NOT NULL, d smallint(6) NOT NULL); +INSERT INTO t1 SET a = "", d= "2003-01-14 03:54:55"; +UPDATE t1 SET d=1/NULL; +UPDATE t1 SET d=NULL; +--error 1048 +INSERT INTO t1 (a) values (null); +--error 1048 +INSERT INTO t1 (a) values (1/null); +INSERT INTO t1 (a) values (null),(null); +--error 1048 +INSERT INTO t1 (b) values (null); +--error 1048 +INSERT INTO t1 (b) values (1/null); +INSERT INTO t1 (b) values (null),(null); +--error 1048 +INSERT INTO t1 (c) values (null); +--error 1048 +INSERT INTO t1 (c) values (1/null); +INSERT INTO t1 (c) values (null),(null); +--error 1048 +INSERT INTO t1 (d) values (null); +--error 1048 +INSERT INTO t1 (d) values (1/null); +INSERT INTO t1 (d) values (null),(null); +select * from t1; +drop table t1; + diff --git a/mysql-test/t/rpl_loaddata.test b/mysql-test/t/rpl_loaddata.test new file mode 100644 index 00000000000..d7fc2a10ca4 --- /dev/null +++ b/mysql-test/t/rpl_loaddata.test @@ -0,0 +1,16 @@ +# See if replication of a "LOAD DATA in an autoincrement column" +# Honours autoincrement values +# i.e. if the master and slave have the same sequence +source include/master-slave.inc; + +create table t1(a int not null auto_increment, b int, primary key(a) ); +load data infile '../../std_data/rpl_loaddata.dat' into table t1; +save_master_pos; +connection slave; +sync_with_master; +select * from t1; +connection master; +drop table t1; +save_master_pos; +connection slave; +sync_with_master; diff --git a/mysql-test/t/rpl_log-master.opt b/mysql-test/t/rpl_log-master.opt new file mode 100644 index 00000000000..e0d075c3fbd --- /dev/null +++ b/mysql-test/t/rpl_log-master.opt @@ -0,0 +1 @@ +--skip-external-locking diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh index 3ed295170ad..83ee5023b89 100644 --- a/scripts/mysql_fix_privilege_tables.sh +++ b/scripts/mysql_fix_privilege_tables.sh @@ -1,19 +1,27 @@ #!/bin/sh echo "This scripts updates the mysql.user, mysql.db, mysql.host and the" -echo "mysql.func table to MySQL 3.22.14 and above." +echo "mysql.func tables to MySQL 3.22.14 and above." echo "" echo "This is needed if you want to use the new GRANT functions," -echo "CREATE AGGREAGATE FUNCTION or want to use the more secure passwords in 3.23" +echo "CREATE AGGREGATE FUNCTION or want to use the more secure passwords in 3.23" echo "" -echo "If you get Access denied errors, you should run this script again" -echo "and give the MySQL root user password as a argument!" +echo "If you get 'Access denied' errors, you should run this script again" +echo "and give the MySQL root user password as an argument!" root_password="$1" host="localhost" +user="root" + +if test -z $1 ; then + cmd="@bindir@/mysql -f --user=$user --host=$host mysql" +else + root_password="$1" + cmd="@bindir@/mysql -f --user=$user --password=$root_password --host=$host mysql" +fi echo "Converting all privilege tables to MyISAM format" -@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql < columns_priv.Column_priv" echo "You can ignore any Unknown column errors from this" -@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <""; END_OF_DATA echo "" @@ -168,7 +176,7 @@ fi # Add fields that can be used to limit number of questions and connections # for some users. -@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <reset(); return 0; } + field->reset(); + if (current_thd->count_cuted_fields) + { + current_thd->cuted_fields++; // Increment error counter + return 0; + } + if (!current_thd->no_errors) + my_printf_error(ER_BAD_NULL_ERROR,ER(ER_BAD_NULL_ERROR),MYF(0), + field->field_name); return 1; } diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index cb012d33572..86544542613 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -2272,19 +2272,7 @@ convert_search_mode_to_innobase( case HA_READ_AFTER_KEY: return(PAGE_CUR_G); case HA_READ_BEFORE_KEY: return(PAGE_CUR_L); case HA_READ_PREFIX: return(PAGE_CUR_GE); - case HA_READ_PREFIX_LAST: - /* ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Warning: Using HA_READ_PREFIX_LAST\n"); */ - return(PAGE_CUR_LE); - - /* InnoDB does not yet support ..PREFIX_LAST! - We have to add a new search flag - PAGE_CUR_LE_OR_PREFIX to InnoDB. */ - - /* the above PREFIX flags mean that the last - field in the key value may just be a prefix - of the complete fixed length field */ + case HA_READ_PREFIX_LAST: return(PAGE_CUR_LE_OR_EXTENDS); default: assert(0); } @@ -2489,6 +2477,9 @@ ha_innobase::change_active_index( (trx_t*) current_thd->transaction.all.innobase_tid); ut_a(user_thd == current_thd); + ut_a(prebuilt->trx == + (trx_t*) current_thd->transaction.all.innobase_tid); + active_index = keynr; if (keynr != MAX_KEY && table->keys > 0) { @@ -2520,6 +2511,11 @@ ha_innobase::change_active_index( the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary copying. Starting from MySQL-4.1 we use a more efficient flag here. */ + /* + TODO: In 4.0 the below user_thd was changed to NULL. + Heikki, please delete this comment after you have read this and may + acted upon it. + */ build_template(prebuilt, user_thd, table, ROW_MYSQL_REC_FIELDS); DBUG_RETURN(0); @@ -3025,6 +3021,7 @@ ha_innobase::create( { int error; dict_table_t* innobase_table; + trx_t* parent_trx; trx_t* trx; int primary_key_no; uint i; @@ -3036,6 +3033,16 @@ ha_innobase::create( DBUG_ASSERT(thd != NULL); + /* Get the transaction associated with the current thd, or create one + if not yet created */ + + parent_trx = check_trx_exists(current_thd); + + /* In case MySQL calls this in the middle of a SELECT query, release + possible adaptive hash latch to avoid deadlocks of threads */ + + trx_search_latch_release_if_reserved(parent_trx); + trx = trx_allocate_for_mysql(); if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) { @@ -3196,11 +3203,22 @@ ha_innobase::delete_table( { ulint name_len; int error; + trx_t* parent_trx; trx_t* trx; char norm_name[1000]; DBUG_ENTER("ha_innobase::delete_table"); + /* Get the transaction associated with the current thd, or create one + if not yet created */ + + parent_trx = check_trx_exists(current_thd); + + /* In case MySQL calls this in the middle of a SELECT query, release + possible adaptive hash latch to avoid deadlocks of threads */ + + trx_search_latch_release_if_reserved(parent_trx); + if (lower_case_table_names) { srv_lower_case_table_names = TRUE; } else { @@ -3255,11 +3273,22 @@ innobase_drop_database( the database name is 'test' */ { ulint len = 0; + trx_t* parent_trx; trx_t* trx; char* ptr; int error; char namebuf[10000]; + /* Get the transaction associated with the current thd, or create one + if not yet created */ + + parent_trx = check_trx_exists(current_thd); + + /* In case MySQL calls this in the middle of a SELECT query, release + possible adaptive hash latch to avoid deadlocks of threads */ + + trx_search_latch_release_if_reserved(parent_trx); + ptr = strend(path) - 2; while (ptr >= path && *ptr != '\\' && *ptr != '/') { @@ -3311,12 +3340,23 @@ ha_innobase::rename_table( ulint name_len1; ulint name_len2; int error; + trx_t* parent_trx; trx_t* trx; char norm_from[1000]; char norm_to[1000]; DBUG_ENTER("ha_innobase::rename_table"); + /* Get the transaction associated with the current thd, or create one + if not yet created */ + + parent_trx = check_trx_exists(current_thd); + + /* In case MySQL calls this in the middle of a SELECT query, release + possible adaptive hash latch to avoid deadlocks of threads */ + + trx_search_latch_release_if_reserved(parent_trx); + if (lower_case_table_names) { srv_lower_case_table_names = TRUE; } else { @@ -3363,8 +3403,8 @@ Estimates the number of index records in a range. */ ha_rows ha_innobase::records_in_range( /*==========================*/ - /* out: estimated number of rows, - currently 32-bit int or uint */ + /* out: estimated number of + rows */ int keynr, /* in: index number */ const mysql_byte* start_key, /* in: start key value of the range, may also be empty */ @@ -3395,9 +3435,18 @@ ha_innobase::records_in_range( DBUG_ENTER("records_in_range"); - /* Warning: since it is not sure that MySQL calls external_lock - before calling this function, the trx field in prebuilt can be - obsolete! */ + /* We do not know if MySQL can call this function before calling + external_lock(). To be safe, update the thd of the current table + handle. */ + + update_thd(current_thd); + + prebuilt->trx->op_info = (char*)"estimating records in index range"; + + /* In case MySQL calls this in the middle of a SELECT query, release + possible adaptive hash latch to avoid deadlocks of threads */ + + trx_search_latch_release_if_reserved(prebuilt->trx); active_index = keynr; @@ -3431,6 +3480,8 @@ ha_innobase::records_in_range( my_free((char*) key_val_buff2, MYF(0)); + prebuilt->trx->op_info = (char*)""; + DBUG_RETURN((ha_rows) n_rows); } @@ -3451,11 +3502,21 @@ ha_innobase::estimate_number_of_rows(void) ulonglong estimate; ulonglong local_data_file_length; - /* Warning: since it is not sure that MySQL calls external_lock - before calling this function, the trx field in prebuilt can be - obsolete! */ + DBUG_ENTER("estimate_number_of_rows"); - DBUG_ENTER("info"); + /* We do not know if MySQL can call this function before calling + external_lock(). To be safe, update the thd of the current table + handle. */ + + update_thd(current_thd); + + prebuilt->trx->op_info = (char*) + "calculating upper bound for table rows"; + + /* In case MySQL calls this in the middle of a SELECT query, release + possible adaptive hash latch to avoid deadlocks of threads */ + + trx_search_latch_release_if_reserved(prebuilt->trx); index = dict_table_get_first_index_noninline(prebuilt->table); @@ -3470,6 +3531,8 @@ ha_innobase::estimate_number_of_rows(void) estimate = 2 * local_data_file_length / dict_index_calc_min_rec_len(index); + prebuilt->trx->op_info = (char*)""; + DBUG_RETURN((ha_rows) estimate); } @@ -3520,9 +3583,18 @@ ha_innobase::info( return; } - /* Warning: since it is not sure that MySQL calls external_lock - before calling this function, the trx field in prebuilt can be - obsolete! */ + /* We do not know if MySQL can call this function before calling + external_lock(). To be safe, update the thd of the current table + handle. */ + + update_thd(current_thd); + + /* In case MySQL calls this in the middle of a SELECT query, release + possible adaptive hash latch to avoid deadlocks of threads */ + + prebuilt->trx->op_info = (char*)"returning various info to MySQL"; + + trx_search_latch_release_if_reserved(prebuilt->trx); ib_table = prebuilt->table; @@ -3530,7 +3602,12 @@ ha_innobase::info( /* In sql_show we call with this flag: update then statistics so that they are up-to-date */ + prebuilt->trx->op_info = (char*)"updating table statistics"; + dict_update_statistics(ib_table); + + prebuilt->trx->op_info = (char*) + "returning various info to MySQL"; } if (flag & HA_STATUS_VARIABLE) { @@ -3590,12 +3667,6 @@ ha_innobase::info( } } - /* The trx struct in InnoDB contains a pthread mutex embedded: - in the debug version of MySQL that it replaced by a 'safe mutex' - which is of a different size. We have to use a function to access - trx fields. Otherwise trx->error_info will be a random - pointer and cause a seg fault. */ - if (flag & HA_STATUS_ERRKEY) { ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N); @@ -3604,6 +3675,8 @@ ha_innobase::info( trx_get_error_info(prebuilt->trx)); } + prebuilt->trx->op_info = (char*)""; + DBUG_VOID_RETURN; } @@ -3661,11 +3734,22 @@ ha_innobase::update_table_comment( char* str = my_malloc(length + 16500, MYF(0)); char* pos; - /* Warning: since it is not sure that MySQL calls external_lock - before calling this function, the trx field in prebuilt can be - obsolete! */ + /* We do not know if MySQL can call this function before calling + external_lock(). To be safe, update the thd of the current table + handle. */ + + update_thd(current_thd); + + prebuilt->trx->op_info = (char*)"returning table comment"; + + /* In case MySQL calls this in the middle of a SELECT query, release + possible adaptive hash latch to avoid deadlocks of threads */ + + trx_search_latch_release_if_reserved(prebuilt->trx); if (!str) { + prebuilt->trx->op_info = (char*)""; + return((char*)comment); } @@ -3689,6 +3773,8 @@ ha_innobase::update_table_comment( prebuilt->table); } + prebuilt->trx->op_info = (char*)""; + return(str); } @@ -3704,20 +3790,30 @@ ha_innobase::get_foreign_key_create_info(void) { row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt; char* str; + + ut_a(prebuilt != NULL); + + /* We do not know if MySQL can call this function before calling + external_lock(). To be safe, update the thd of the current table + handle. */ + + update_thd(current_thd); + + prebuilt->trx->op_info = (char*)"getting info on foreign keys"; + + /* In case MySQL calls this in the middle of a SELECT query, release + possible adaptive hash latch to avoid deadlocks of threads */ + + trx_search_latch_release_if_reserved(prebuilt->trx); - if (prebuilt == NULL) { - fprintf(stderr, -"InnoDB: Error: cannot get create info for foreign keys\n"); - - return(NULL); - } - str = (char*)ut_malloc(10000); str[0] = '\0'; dict_print_info_on_foreign_keys(TRUE, str, 9000, prebuilt->table); + prebuilt->trx->op_info = (char*)""; + return(str); } @@ -3793,9 +3889,10 @@ ha_innobase::reset(void) } /********************************************************************** -When we create a temporary table inside MySQL LOCK TABLES, MySQL will -not call external_lock for the temporary table when it uses it. Instead, -it will call this function. */ +Inside LOCK TABLES MySQL will not call external_lock() between SQL +statements. It will call this function at the start of each SQL statement. +Note also a spacial case: if a temporary table is created inside LOCK +TABLES, MySQL has not called external_lock() at all on that table. */ int ha_innobase::start_stmt( @@ -3933,8 +4030,8 @@ ha_innobase::external_lock( trx->mysql_n_tables_locked = 0; - /* Here we release the search latch, auto_inc_lock, - and InnoDB thread FIFO ticket if they were reserved. */ + /* Here we release the search latch and InnoDB + thread FIFO ticket if they were reserved. */ innobase_release_stat_resources(trx); @@ -3978,12 +4075,12 @@ innodb_show_status( DBUG_RETURN(-1); } - /* We let the InnoDB Monitor to output at most 100 kB of text, add + /* We let the InnoDB Monitor to output at most 200 kB of text, add a safety margin of 10 kB for buffer overruns */ - buf = (char*)ut_malloc(110 * 1024); + buf = (char*)ut_malloc(210 * 1024); - srv_sprintf_innodb_monitor(buf, 100 * 1024); + srv_sprintf_innodb_monitor(buf, 200 * 1024); List field_list; @@ -3991,6 +4088,7 @@ innodb_show_status( if (protocol->send_fields(&field_list, 1)) { + ut_free(buf); DBUG_RETURN(-1); } @@ -4241,4 +4339,4 @@ ha_innobase::get_auto_increment() } #endif /* HAVE_INNOBASE_DB */ - + diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index 3bd812821f6..00052239f0b 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -241,7 +241,7 @@ void ha_myisammrg::info(uint flag) #endif if (flag & HA_STATUS_CONST) { - if (table->key_parts) + if (table->key_parts && info.rec_per_key) memcpy((char*) table->key_info[0].rec_per_key, (char*) info.rec_per_key, sizeof(table->key_info[0].rec_per_key)*table->key_parts); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 3d65c05b9cf..79807653317 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1898,7 +1898,7 @@ Item_func_regex::~Item_func_regex() Precomputation dependent only on pattern_len. **********************************************************************/ -void Item_func_like::turboBM_compute_suffixes(int* suff) +void Item_func_like::turboBM_compute_suffixes(int *suff) { const int plm1 = pattern_len - 1; int f = 0; @@ -1940,8 +1940,8 @@ void Item_func_like::turboBM_compute_suffixes(int* suff) if (i < g) g = i; // g = min(i, g) f = i; - while (g >= 0 && likeconv(cs, pattern[g]) == - likeconv(cs, pattern[g + plm1 - f])) + while (g >= 0 && + likeconv(cs, pattern[g]) == likeconv(cs, pattern[g + plm1 - f])) g--; suff[i] = f - g; } @@ -1955,12 +1955,12 @@ void Item_func_like::turboBM_compute_suffixes(int* suff) Precomputation dependent only on pattern_len. **********************************************************************/ -void Item_func_like::turboBM_compute_good_suffix_shifts(int* suff) +void Item_func_like::turboBM_compute_good_suffix_shifts(int *suff) { turboBM_compute_suffixes(suff); - int* end = bmGs + pattern_len; - int* k; + int *end = bmGs + pattern_len; + int *k; for (k = bmGs; k < end; k++) *k = pattern_len; @@ -1974,14 +1974,14 @@ void Item_func_like::turboBM_compute_good_suffix_shifts(int* suff) { for (tmp = plm1 - i; j < tmp; j++) { - int* tmp2 = bmGs + j; + int *tmp2 = bmGs + j; if (*tmp2 == pattern_len) *tmp2 = tmp; } } } - int* tmp2; + int *tmp2; for (tmp = plm1 - i; j < tmp; j++) { tmp2 = bmGs + j; @@ -2014,12 +2014,12 @@ void Item_func_like::turboBM_compute_bad_character_shifts() if (binary()) { for (j = 0; j < plm1; j++) - bmBc[pattern[j]] = plm1 - j; + bmBc[(uint) (uchar) pattern[j]] = plm1 - j; } else { for (j = 0; j < plm1; j++) - bmBc[likeconv(cs,pattern[j])] = plm1 - j; + bmBc[(uint) likeconv(cs,pattern[j])] = plm1 - j; } } @@ -2038,27 +2038,27 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const int u = 0; CHARSET_INFO *cs=system_charset_info; // QQ Needs to be fixed - const int plm1 = pattern_len - 1; - const int tlmpl = text_len - pattern_len; + const int plm1= pattern_len - 1; + const int tlmpl= text_len - pattern_len; /* Searching */ if (binary()) { while (j <= tlmpl) { - register int i = plm1; + register int i= plm1; while (i >= 0 && pattern[i] == text[i + j]) { i--; if (i == plm1 - shift) - i -= u; + i-= u; } if (i < 0) return 1; register const int v = plm1 - i; turboShift = u - v; - bcShift = bmBc[text[i + j]] - plm1 + i; + bcShift = bmBc[(uint) (uchar) text[i + j]] - plm1 + i; shift = max(turboShift, bcShift); shift = max(shift, bmGs[i]); if (shift == bmGs[i]) @@ -2069,7 +2069,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const shift = max(shift, u + 1); u = 0; } - j += shift; + j+= shift; } return 0; } @@ -2082,14 +2082,14 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const { i--; if (i == plm1 - shift) - i -= u; + i-= u; } if (i < 0) return 1; register const int v = plm1 - i; turboShift = u - v; - bcShift = bmBc[likeconv(cs, text[i + j])] - plm1 + i; + bcShift = bmBc[(uint) likeconv(cs, text[i + j])] - plm1 + i; shift = max(turboShift, bcShift); shift = max(shift, bmGs[i]); if (shift == bmGs[i]) @@ -2100,7 +2100,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const shift = max(shift, u + 1); u = 0; } - j += shift; + j+= shift; } return 0; } diff --git a/sql/log_event.cc b/sql/log_event.cc index 4ce491d7cc5..1d27e48f14f 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1331,8 +1331,8 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, bool old_format) { uint data_len; - uint header_len= old_format ? OLD_HEADER_LEN : LOG_EVENT_HEADER_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); exec_time = uint4korr(data_head + L_EXEC_TIME_OFFSET); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f30034049f0..1ed33d5c9db 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -770,7 +770,7 @@ static void *kill_server(void *sig_ptr) #define RETURN_FROM_KILL_SERVER DBUG_RETURN(0) #else static void __cdecl kill_server(int sig_ptr) -#define RETURN_FROM_KILL_SERVER DBUG_RETURN +#define RETURN_FROM_KILL_SERVER DBUG_VOID_RETURN #endif { int sig=(int) (long) sig_ptr; // This is passed a int diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index b1bb36353bf..492834b5bb9 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -38,7 +38,7 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) table_map removed_tables=0; Item *item; COND *org_conds= conds; - + /* Add all ON conditions to WHERE condition */ for (TABLE_LIST *tl=tables; tl ; tl= tl->next) { @@ -165,10 +165,9 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) error=table->file->index_last(table->record[0]) !=0; else { - (void)table->file->index_read(table->record[0], key_buff, + error = table->file->index_read(table->record[0], key_buff, ref.key_length, - HA_READ_AFTER_KEY); - error=table->file->index_prev(table->record[0]) || + HA_READ_PREFIX_LAST) || key_cmp(table,key_buff,ref.key,ref.key_length); } if (table->key_read) diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 96ff33774ac..8fca6300992 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -283,6 +283,20 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, { if (lf_info.wrote_create_file) { + /* + Make sure last block (the one which caused the error) gets logged. + This is needed because otherwise after write of + (to the binlog, not to read_info (which is a cache)) + Delete_file_log_event the bad block will remain in read_info. + At the end of mysql_load(), the destructor of read_info will call + end_io_cache() which will flush read_info, so we will finally have + this in the binlog: + Append_block # The last successfull block + Delete_file + Append_block # The failing block + which is nonsense. + */ + read_info.end_io_cache(); Delete_file_log_event d(thd, log_delayed); mysql_bin_log.write(&d); } @@ -343,8 +357,10 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List &fields, { List_iterator_fast it(fields); Item_field *sql_field; + ulonglong id; DBUG_ENTER("read_fixed_length"); + id=0; /* No fields can be null in this format. mark all fields as not null */ while ((sql_field= (Item_field*) it++)) sql_field->field->set_notnull(); @@ -387,6 +403,14 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List &fields, thd->cuted_fields++; /* To long row */ if (write_record(table,&info)) DBUG_RETURN(1); + /* + If auto_increment values are used, save the first one + for LAST_INSERT_ID() and for the binary/update log. + We can't use insert_id() as we don't want to touch the + last_insert_id_used flag. + */ + if (!id && thd->insert_id_used) + id= thd->last_insert_id; if (table->next_number_field) table->next_number_field->reset(); // Clear for next record if (read_info.next_line()) // Skip to next line @@ -394,6 +418,8 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List &fields, if (read_info.line_cuted) thd->cuted_fields++; /* To long row */ } + if (id && !read_info.error) + thd->insert_id(id); // For binary/update log DBUG_RETURN(test(read_info.error)); } @@ -407,10 +433,12 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, List_iterator_fast it(fields); Item_field *sql_field; uint enclosed_length; + ulonglong id; DBUG_ENTER("read_sep_field"); enclosed_length=enclosed.length(); - + id=0; + for (;;it.rewind()) { if (thd->killed) @@ -463,6 +491,14 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, } if (write_record(table,&info)) DBUG_RETURN(1); + /* + If auto_increment values are used, save the first one + for LAST_INSERT_ID() and for the binary/update log. + We can't use insert_id() as we don't want to touch the + last_insert_id_used flag. + */ + if (!id && thd->insert_id_used) + id= thd->last_insert_id; if (table->next_number_field) table->next_number_field->reset(); // Clear for next record if (read_info.next_line()) // Skip to next line @@ -470,6 +506,8 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, if (read_info.line_cuted) thd->cuted_fields++; /* To long row */ } + if (id && !read_info.error) + thd->insert_id(id); // For binary/update log DBUG_RETURN(test(read_info.error)); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 7f46311cd85..686db8736af 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2030,12 +2030,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, /* We changed a temporary table */ if (error) { - /* - * The following function call will also free a - * new_table pointer. - * Therefore, here new_table pointer is not free'd as it is - * free'd in close_temporary() which is called by by the - * close_temporary_table() function. + /* + The following function call will free the new_table pointer, + in close_temporary_table(), so we can safely directly jump to err */ close_temporary_table(thd,new_db,tmp_name); goto err; diff --git a/strings/Makefile.am b/strings/Makefile.am index dea9effdfeb..c78be3d9cb4 100644 --- a/strings/Makefile.am +++ b/strings/Makefile.am @@ -40,6 +40,7 @@ endif libmystrings_a_SOURCES = $(ASRCS) $(CSRCS) noinst_PROGRAMS = conf_to_src +DISTCLEANFILES = ctype_autoconf.c # Default charset definitions EXTRA_DIST = ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-win1250ch.c \ ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-utf8.c \