From 446b9c0768628143e0a52b66ede392823aa89b71 Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Sat, 21 Dec 2002 10:57:53 +0200 Subject: [PATCH 01/32] Moved lower_case_table_name check to right place. --- sql/sql_db.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 338d3161bd4..0be1b7b0411 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -323,9 +323,6 @@ bool mysql_change_db(THD *thd,const char *name) uint db_access; DBUG_ENTER("mysql_change_db"); - if (lower_case_table_names) - casedn_str(dbname); - if (!dbname || !(length=strip_sp(dbname))) { x_free(dbname); /* purecov: inspected */ @@ -338,6 +335,8 @@ bool mysql_change_db(THD *thd,const char *name) x_free(dbname); DBUG_RETURN(1); } + if (lower_case_table_names) + casedn_str(dbname); DBUG_PRINT("general",("Use database: %s", dbname)); if (test_all_bits(thd->master_access,DB_ACLS)) db_access=DB_ACLS; From c0ed25283f29498f2cfd4dd3fa7cabd5558e5a4d Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Mon, 23 Dec 2002 14:36:40 +0100 Subject: [PATCH 02/32] - Applied various patches provided by Christian Hammers (MySQL maintainer for the Debian project) to fix some architecture-specific problems and some bugs --- Makefile.am | 4 ++-- bdb/dist/aclocal/mutex.m4 | 2 +- bdb/include/mutex.h | 2 +- ltconfig | 10 +++++++++ man/isamchk.1 | 2 +- man/isamlog.1 | 2 +- man/mysql.1 | 2 +- man/mysql_zap.1 | 2 +- man/mysqlaccess.1 | 2 +- man/mysqladmin.1 | 2 +- man/mysqld.1 | 2 +- man/mysqld_multi.1 | 2 +- man/mysqldump.1 | 6 +++--- man/mysqlshow.1 | 2 +- man/perror.1 | 2 +- man/replace.1 | 2 +- man/safe_mysqld.1 | 2 +- scripts/mysql_fix_privilege_tables.sh | 29 +++++++++++++++++---------- scripts/mysqlaccess.sh | 2 +- scripts/safe_mysqld.sh | 2 ++ 20 files changed, 50 insertions(+), 31 deletions(-) diff --git a/Makefile.am b/Makefile.am index 35db77c684e..8440077298e 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 MIRRORS -SUBDIRS = include @docs_dirs@ @readline_dir@ \ +SUBDIRS = . include @docs_dirs@ @readline_dir@ \ @thread_dirs@ @sql_client_dirs@ \ @sql_server_dirs@ scripts tests man \ - @bench_dirs@ support-files os2 + @bench_dirs@ support-files os2 libmysql_r # Relink after clean CLEANFILES = linked_client_sources linked_server_sources linked_libmysql_sources linked_libmysql_r_sources linked_include_sources diff --git a/bdb/dist/aclocal/mutex.m4 b/bdb/dist/aclocal/mutex.m4 index 5c9218da163..2010670599f 100644 --- a/bdb/dist/aclocal/mutex.m4 +++ b/bdb/dist/aclocal/mutex.m4 @@ -279,7 +279,7 @@ fi dnl Sparc/gcc: SunOS, Solaris dnl The sparc/gcc code doesn't always work, specifically, I've seen assembler dnl failures from the stbar instruction on SunOS 4.1.4/sun4c and gcc 2.7.2.2. -if test "$db_cv_mutex" = DOESNT_WORK; then +if test "$db_cv_mutex" = no; then AC_TRY_RUN([main(){ #if defined(__sparc__) #if defined(__GNUC__) diff --git a/bdb/include/mutex.h b/bdb/include/mutex.h index 4c1b265355d..9f341695cbf 100644 --- a/bdb/include/mutex.h +++ b/bdb/include/mutex.h @@ -327,7 +327,7 @@ typedef unsigned char tsl_t; */ #define MUTEX_SET(tsl) ({ \ register tsl_t *__l = (tsl); \ - int __r; \ + unsigned char __r; \ asm volatile("tas %1; \n \ seq %0" \ : "=dm" (__r), "=m" (*__l) \ 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 f225dc35d18..6bf83abab5b 100755 --- 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 efc042ccd7c..430b1d3d396 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 96ccca8f50e..baf212015bd 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 98da195894e..e6ff7f4a0d1 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 888cfe8f646..2e0d40c823a 100755 --- 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 58bd2070de6..a67977dcb75 100755 --- 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 d3f22c0be1b..b25606ceda0 100755 --- 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 b68050e92ef..8e77626ad3c 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/mysqldump.1 b/man/mysqldump.1 index f108da17bf9..85c0e2e0c50 100755 --- 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 55a87c1df78..3a78be69d49 100755 --- 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 2853f2cb1ba..bd5a4211f4b 100755 --- 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 10bcf64fc88..3c14989e392 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/man/safe_mysqld.1 b/man/safe_mysqld.1 index 3874801be3b..0505b973672 100755 --- a/man/safe_mysqld.1 +++ b/man/safe_mysqld.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 safe_mysqld \- start the mysqld daemon on Unix. .SH SYNOPSIS diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh index 86312fdab52..1677eaf5f32 100644 --- a/scripts/mysql_fix_privilege_tables.sh +++ b/scripts/mysql_fix_privilege_tables.sh @@ -1,23 +1,30 @@ #!/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 # Fix old password format, add File_priv and func table echo "" echo "If your tables are already up to date or partially up to date you will" echo "get some warnings about 'Duplicated column name'. You can safely ignore these!" -@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql < columns_priv.Column_priv" echo "You can ignore any errors from this" -@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql < Date: Thu, 26 Dec 2002 16:35:15 +0200 Subject: [PATCH 03/32] Updated comment --- sql/sql_table.cc | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e2fa8bc00d5..4691c2fd494 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1528,12 +1528,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; From c729c0ea05d6125aff87737208a14d201fe5e58c Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Thu, 26 Dec 2002 17:50:07 +0200 Subject: [PATCH 04/32] Safety fix to not allow one to specify too big max_alloc_packet to mysqld Safety fix to not cause conflicts with extended packages in 4.0. --- sql/mysqld.cc | 2 +- sql/net_serv.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index bd17f7339a4..e2adc1a068e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2984,7 +2984,7 @@ CHANGEABLE_VAR changeable_vars[] = { #endif ,0, 1, 0, 1 }, { "max_allowed_packet", (long*) &max_allowed_packet, - 1024*1024L, 80, 64*1024*1024L, MALLOC_OVERHEAD, 1024 }, + 1024*1024L, 80, 16*1024*1024L, MALLOC_OVERHEAD, 1024 }, { "max_binlog_cache_size", (long*) &max_binlog_cache_size, ~0L, IO_SIZE, ~0L, 0, IO_SIZE }, { "max_binlog_size", (long*) &max_binlog_size, diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 750079b39a5..2583f0767f4 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -40,7 +40,7 @@ ulong max_allowed_packet=65536; extern ulong net_read_timeout,net_write_timeout; extern uint test_flags; #else -ulong max_allowed_packet=16*1024*1024L; +ulong max_allowed_packet=16*1024*1024L-1; ulong net_read_timeout= NET_READ_TIMEOUT; ulong net_write_timeout= NET_WRITE_TIMEOUT; #endif From fc8a78955b91226f1c8bad594e954c4b8a21612f Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Fri, 27 Dec 2002 17:37:55 +0100 Subject: [PATCH 05/32] - fixes to properly make a "make distclean" (some files were not removed) (There are probably some more to fix) --- libmysql/Makefile.shared | 2 ++ strings/Makefile.am | 1 + 2 files changed, 3 insertions(+) diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index 8fe15cca20c..b1c7438543f 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -77,6 +77,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) $(mystringsgen) $(mysysheaders) \ ctype_extra_sources.c ../linked_client_sources diff --git a/strings/Makefile.am b/strings/Makefile.am index a81ba1c17cb..1acd3365100 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-gb2312.c ctype-gbk.c ctype-sjis.c \ From f22fde21c0667042dd716d9c07081565b7a56c5c Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Fri, 27 Dec 2002 21:39:35 +0200 Subject: [PATCH 06/32] Fixed max_key_length when using UNIQUE keys. This fixed a bug in GROUP BY on a BLOB column with NULL values. --- myisam/mi_create.c | 2 +- myisam/mi_unique.c | 11 ++++++++++- mysql-test/r/group_by.result | 8 ++++++++ mysql-test/t/group_by.test | 11 +++++++++++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/myisam/mi_create.c b/myisam/mi_create.c index 6941db158e1..5a5a49533da 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -224,7 +224,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, if (uniques) { max_key_block_length= MI_KEY_BLOCK_LENGTH; - 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 e598fbeedb4..7f1e6b83a12 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/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 0b720bc3d97..3bd3eeb5efd 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -102,3 +102,11 @@ pid c1id c2id value id active id active 1 4 NULL 4 4 Yes NULL NULL max(value) 4 +a count(*) +NULL 9 + 3 +b 1 +a count(*) +NULL 9 + 3 +b 1 diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index db6baec4b9f..b21ae88007b 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -312,3 +312,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; From a41886a09656cd8fb52720941cb29eb07aa2d67f Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Fri, 27 Dec 2002 23:29:27 +0200 Subject: [PATCH 07/32] Added O_BINARY flag to all my_fopen() calls. (To make the current tests results work on windows) --- client/mysqltest.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index cfb7fe1aeaf..18fafff275e 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -43,7 +43,7 @@ **********************************************************************/ -#define MTEST_VERSION "1.10" +#define MTEST_VERSION "1.11" #include #include @@ -573,7 +573,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(name, O_RDONLY, MYF(MY_WME)))) + if (!(*(cur_file+1) = my_fopen(name, O_RDONLY | O_BINARY, MYF(MY_WME)))) die(NullS); cur_file++; *++lineno=1; @@ -1589,7 +1589,7 @@ int parse_args(int argc, char **argv) result_file = optarg; break; case 'x': - if (!(*cur_file = my_fopen(optarg, O_RDONLY, MYF(MY_WME)))) + if (!(*cur_file = my_fopen(optarg, O_RDONLY | O_BINARY, MYF(MY_WME)))) die("Could not open %s: errno = %d", optarg, errno); break; case 'p': From 42095544eaafdeca09bb5659d66c9cca60a7dd71 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sun, 5 Jan 2003 22:15:03 +0200 Subject: [PATCH 08/32] log0log.c: Backport bugfix from 4.0: combined log file size >= 2 GB could cause log to be written in wrong place btr0pcur.c: Backport bugfix from 4.0: index cursor restoration could theoretically fail --- innobase/btr/btr0pcur.c | 6 ++++++ innobase/log/log0log.c | 32 +++++++++++++++++++++----------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/innobase/btr/btr0pcur.c b/innobase/btr/btr0pcur.c index 8ca3d41f7f9..2b9dc11e683 100644 --- a/innobase/btr/btr0pcur.c +++ b/innobase/btr/btr0pcur.c @@ -292,6 +292,12 @@ btr_pcur_restore_position( mem_heap_free(heap); + /* We have to store position information, modify clock value, etc. + because the cursor may now be on a different page */ + + btr_pcur_store_position(cursor, mtr); + + return(FALSE); } diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c index cb85e9d3ba6..9e40e4898a5 100644 --- a/innobase/log/log0log.c +++ b/innobase/log/log0log.c @@ -437,25 +437,29 @@ log_group_calc_lsn_offset( dulint lsn, /* in: lsn, must be within 4 GB of group->lsn */ log_group_t* group) /* in: log group */ { - dulint gr_lsn; - ulint gr_lsn_size_offset; - ulint difference; - ulint group_size; - ulint offset; + dulint gr_lsn; + ib_longlong gr_lsn_size_offset; + ib_longlong difference; + ib_longlong group_size; + ib_longlong offset; ut_ad(mutex_own(&(log_sys->mutex))); + /* If total log file size is > 2 GB we can easily get overflows + with 32-bit integers. Use 64-bit integers instead. */ + gr_lsn = group->lsn; - gr_lsn_size_offset = log_group_calc_size_offset(group->lsn_offset, - group); - group_size = log_group_get_capacity(group); + gr_lsn_size_offset = (ib_longlong) + log_group_calc_size_offset(group->lsn_offset, group); + + group_size = (ib_longlong) log_group_get_capacity(group); if (ut_dulint_cmp(lsn, gr_lsn) >= 0) { - difference = ut_dulint_minus(lsn, gr_lsn); + difference = (ib_longlong) ut_dulint_minus(lsn, gr_lsn); } else { - difference = ut_dulint_minus(gr_lsn, lsn); + difference = (ib_longlong) ut_dulint_minus(gr_lsn, lsn); difference = difference % group_size; @@ -464,7 +468,13 @@ log_group_calc_lsn_offset( offset = (gr_lsn_size_offset + difference) % group_size; - return(log_group_calc_real_offset(offset, group)); + ut_a(offset <= 0xFFFFFFFF); + + /* printf("Offset is %lu gr_lsn_offset is %lu difference is %lu\n", + (ulint)offset,(ulint)gr_lsn_size_offset, (ulint)difference); + */ + + return(log_group_calc_real_offset((ulint)offset, group)); } /*********************************************************************** From 54ad6de1d9f8824bd92f817a873b8a13c70ea7c2 Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Thu, 9 Jan 2003 11:11:06 +0200 Subject: [PATCH 09/32] Portability fix --- BUILD/compile-alpha-cxx | 2 +- configure.in | 7 ++++++- extra/mysql_waitpid.c | 25 +++++++++++++++++++++---- mysql-test/mysql-test-run.sh | 2 +- 4 files changed, 29 insertions(+), 7 deletions(-) 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/configure.in b/configure.in index 06dc6e03fb6..e689771d1ce 100644 --- a/configure.in +++ b/configure.in @@ -2360,6 +2360,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 @@ -2372,7 +2373,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/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 408c76d8602..a7292ee5eec 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -328,7 +328,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=120 ;; --valgrind-options=*) From 74eea66b5a83340c3fa611db4152092df0f778b6 Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Thu, 9 Jan 2003 23:28:30 +0200 Subject: [PATCH 10/32] Fixed wrong packed length for packet > 16M. --- sql/net_pkg.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/net_pkg.cc b/sql/net_pkg.cc index 0b50b34c7bd..381e0ded3f4 100644 --- a/sql/net_pkg.cc +++ b/sql/net_pkg.cc @@ -206,7 +206,7 @@ net_store_length(char *pkg, ulonglong length) } *packet++=254; int8store(packet,length); - return (char*) packet+9; + return (char*) packet+8; } char * From 1bc3105da34c174f1ffe848a01e9cfb0d4ebc2ec Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Fri, 10 Jan 2003 01:55:05 +0200 Subject: [PATCH 11/32] Fixed core dump bug in str LIKE "%other_str%" where strings contained characters >= 128. Fixed problem with replication LOAD DATA INFILE when using --old-rpl-compat. When executing on master LOAD DATA and InnoDB failed with 'table full' error the binary log was corrupted. --- sql/item_cmpfunc.cc | 47 +++++++++++++++++++++++++-------------------- sql/log_event.cc | 6 +++--- sql/sql_load.cc | 14 ++++++++++++++ 3 files changed, 43 insertions(+), 24 deletions(-) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index a36c96ffea4..2a363164656 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1538,12 +1538,12 @@ 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; int g = plm1; - int* const splm1 = suff + plm1; + int *const splm1 = suff + plm1; *splm1 = pattern_len; @@ -1579,7 +1579,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(pattern[g]) == likeconv(pattern[g + plm1 - f])) + while (g >= 0 && + likeconv(pattern[g]) == likeconv(pattern[g + plm1 - f])) g--; suff[i] = f - g; } @@ -1593,12 +1594,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; @@ -1612,14 +1613,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; @@ -1640,19 +1641,23 @@ void Item_func_like::turboBM_compute_good_suffix_shifts(int* suff) void Item_func_like::turboBM_compute_bad_character_shifts() { - int* i; - int* end = bmBc + alphabet_size; + int *i; + int *end = bmBc + alphabet_size; for (i = bmBc; i < end; i++) *i = pattern_len; int j; const int plm1 = pattern_len - 1; 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(pattern[j])] = plm1 - j; + bmBc[(uint) likeconv(pattern[j])] = plm1 - j; + } } @@ -1669,27 +1674,27 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const int j = 0; int u = 0; - 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]) @@ -1700,7 +1705,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; } @@ -1713,14 +1718,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(text[i + j])] - plm1 + i; + bcShift = bmBc[(uint) likeconv(text[i + j])] - plm1 + i; shift = max(turboShift, bcShift); shift = max(shift, bmGs[i]); if (shift == bmGs[i]) @@ -1731,7 +1736,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 3c2c2fd27b1..45f54e420de 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1202,8 +1202,8 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, { uint data_len; char* buf_end = (char*)buf + event_len; - const char* data_head = buf + ((old_format) ? - OLD_HEADER_LEN : LOG_EVENT_HEADER_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); skip_lines = uint4korr(data_head + L_SKIP_LINES_OFFSET); @@ -1212,7 +1212,7 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, num_fields = uint4korr(data_head + L_NUM_FIELDS_OFFSET); int body_offset = ((buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ? - LOAD_HEADER_LEN + OLD_HEADER_LEN : + LOAD_HEADER_LEN + header_len : get_data_body_offset()); if ((int) event_len < body_offset) diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 6375ba46fd7..908ff8c6361 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); } From 0928c8b4b4bbe8acd7a6e7199b4e9a73e9f0ed47 Mon Sep 17 00:00:00 2001 From: "miguel@light." <> Date: Sat, 11 Jan 2003 01:56:00 -0200 Subject: [PATCH 12/32] Added functions required by MySQLCC --- libmysql/libmysql.def | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def index bf22b95fc8c..7f4edb445e1 100644 --- a/libmysql/libmysql.def +++ b/libmysql/libmysql.def @@ -101,6 +101,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 From c314981049cfb54f8ea256634a97f4a60d16c591 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sun, 12 Jan 2003 22:31:16 +0200 Subject: [PATCH 13/32] trx0trx.c: Add diagnostic prints to determine why the 'queries inside InnoDB' might drift upwards ha_innodb.cc: Add more print space to SHOW INNODB STATUS; remove possible memory leak in case there is an error --- innobase/trx/trx0trx.c | 16 ++++++++++++++++ sql/ha_innodb.cc | 9 ++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index d2219ed019f..357fb01df63 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; @@ -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/sql/ha_innodb.cc b/sql/ha_innodb.cc index baeb16997b6..e7fbe1c521a 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -3938,18 +3938,21 @@ 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; field_list.push_back(new Item_empty_string("Status", strlen(buf))); if(send_fields(thd, field_list, 1)) { + + ut_free(buf); + DBUG_RETURN(-1); } From 40689f64e78efc0e092b00bc1a1cd3d8f6a6b3c1 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Mon, 13 Jan 2003 00:44:42 +0200 Subject: [PATCH 14/32] srv0srv.c: Add another diagnostic print to determine why the 'queries inside InnoDB' counter might drift upwards --- innobase/srv/srv0srv.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index f9eba721cbc..50ad90e60bd 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -1715,6 +1715,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 */ @@ -1733,6 +1734,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++; From 7424bf2ea97b958a392a1e337c3943fe33991733 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Mon, 13 Jan 2003 15:52:39 +0200 Subject: [PATCH 15/32] btr0cur.h, btr0btr.h, btr0btr.c, btr0cur.c, row0purge.c: Fix a hang associated with an index tree of height 1 and purging of BLOB fields from it --- innobase/btr/btr0btr.c | 7 +------ innobase/btr/btr0cur.c | 10 ++++++++-- innobase/include/btr0btr.h | 9 +++++++++ innobase/include/btr0cur.h | 8 +++++++- innobase/row/row0purge.c | 11 +++++++++++ 5 files changed, 36 insertions(+), 9 deletions(-) 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 24f0447d55d..df24689a422 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -3180,7 +3180,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); @@ -3315,7 +3315,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/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! */ From 1b656d45fb23f386607453c22c0d41169dee07f0 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Mon, 13 Jan 2003 23:00:11 +0200 Subject: [PATCH 16/32] sql_handler.cc: Backport the InnoDB HANDLER bug fix from 4.1 --- sql/sql_handler.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 289d2434225..66dcf37d07f 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -109,6 +109,8 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, if (cond && cond->fix_fields(thd,tables)) return -1; + table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it + if (keyname) { if ((keyno=find_type(keyname, &table->keynames, 1+2)-1)<0) @@ -128,8 +130,6 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, insert_fields(thd,tables,tables->db,tables->alias,&it); - table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it - select_limit+=offset_limit; send_fields(thd,list,1); @@ -139,6 +139,8 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, if (!lock) goto err0; // mysql_lock_tables() printed error message already + table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it + for (num_rows=0; num_rows < select_limit; ) { switch(mode) { From 7297dbc75fea0724988f29e4dec806468f56424c Mon Sep 17 00:00:00 2001 From: "arjen@george.bitbike.com" <> Date: Tue, 14 Jan 2003 12:21:18 +1000 Subject: [PATCH 17/32] Text fixes: ISAM -> MyISAM for myisamchk (found by Jocelyn Fournier). --- myisam/myisamchk.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index 0d8d1430ce9..7fa91253850 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -129,7 +129,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); @@ -328,7 +328,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\ @@ -1674,7 +1674,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; From 8dd439e751f908af22ebd11197fd56ade76aa5fa Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Tue, 14 Jan 2003 11:27:26 +0200 Subject: [PATCH 18/32] Guard against compiling without -fno-exceptions Allocate bigger default thread stack because of problems with glibc Fixed bug in UPDATE ... not_null_field=expression_that_returns_null Fixed bug in replication when using auto_increment and LOAD DATA INFILE --- include/my_global.h | 7 ++++++ include/my_pthread.h | 8 +++++-- mysql-test/r/null.result | 36 ++++++++++++++++++++++++++++ mysql-test/r/rpl_loaddata.result | 13 ++++++++++ mysql-test/std_data/rpl_loaddata.dat | 2 ++ mysql-test/t/null.test | 31 ++++++++++++++++++++++++ mysql-test/t/rpl_loaddata.test | 16 +++++++++++++ mysql-test/t/rpl_log-master.opt | 1 + sql/field_conv.cc | 9 +++++++ sql/sql_load.cc | 26 +++++++++++++++++++- 10 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 mysql-test/r/rpl_loaddata.result create mode 100644 mysql-test/std_data/rpl_loaddata.dat create mode 100644 mysql-test/t/rpl_loaddata.test create mode 100644 mysql-test/t/rpl_log-master.opt 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/mysql-test/r/null.result b/mysql-test/r/null.result index cdea66cbf58..ba2161d3147 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/null.test b/mysql-test/t/null.test index ad32e0be6ff..6fea7f0d10d 100644 --- a/mysql-test/t/null.test +++ b/mysql-test/t/null.test @@ -48,3 +48,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/sql/field_conv.cc b/sql/field_conv.cc index ffc93f3e871..42272dd616f 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -118,6 +118,15 @@ set_field_to_null(Field *field) field->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/sql_load.cc b/sql/sql_load.cc index 908ff8c6361..c1c6267879e 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -357,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(); @@ -401,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 @@ -408,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)); } @@ -421,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) @@ -477,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 @@ -484,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)); } From 97279ea8deee3cf9f4bb276af846927fc18bcdbb Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 15 Jan 2003 21:26:45 +0200 Subject: [PATCH 19/32] trx0trx.c: Print also the thread ids in SHOW INNODB STATUS also in Linux --- innobase/trx/trx0trx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index 357fb01df63..38d15866769 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -1517,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); } From 244b378b4781d3985012aeae0ab45dc7ce73102d Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 15 Jan 2003 22:48:02 +0200 Subject: [PATCH 20/32] srv0srv.c: Make SHOW INNODB STATUS aware which trx's are waiting because of innodb_thread_concurrency exceeded --- innobase/srv/srv0srv.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 50ad90e60bd..61f5a847d51 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -1814,8 +1814,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--; From d7cc9da9b6c863d0ce19b648423d362fa34b6965 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Thu, 16 Jan 2003 00:44:27 +0200 Subject: [PATCH 21/32] ha_innodb.cc: Fix a possible hang at the adaptive hash index latch if MySQL does query estimations also in the middle of a SELECT statement processing --- sql/ha_innodb.cc | 132 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 105 insertions(+), 27 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index e7fbe1c521a..5b29811f7b0 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -2994,6 +2994,7 @@ ha_innobase::create( { int error; dict_table_t* innobase_table; + trx_t* parent_trx; trx_t* trx; int primary_key_no; uint i; @@ -3005,6 +3006,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) { @@ -3165,11 +3176,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 { @@ -3224,11 +3246,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 != '/') { @@ -3280,12 +3313,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 { @@ -3332,8 +3376,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 */ @@ -3364,9 +3408,16 @@ 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); + + /* 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; @@ -3420,12 +3471,19 @@ 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("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); + + /* 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); local_data_file_length = ((ulonglong) index->stat_n_leaf_pages) @@ -3489,9 +3547,16 @@ 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 */ + + trx_search_latch_release_if_reserved(prebuilt->trx); ib_table = prebuilt->table; @@ -3559,12 +3624,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); @@ -3630,9 +3689,16 @@ 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); + + /* 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) { return((char*)comment); @@ -3673,6 +3739,17 @@ ha_innobase::get_foreign_key_create_info(void) { row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt; char* str; + + /* 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 */ + + trx_search_latch_release_if_reserved(prebuilt->trx); if (prebuilt == NULL) { fprintf(stderr, @@ -3752,9 +3829,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( @@ -3892,8 +3970,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); @@ -4209,4 +4287,4 @@ ha_innobase::get_auto_increment() } #endif /* HAVE_INNOBASE_DB */ - + From c228dfacdfba2897d80ace6789830497ab25ebef Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Thu, 16 Jan 2003 01:07:08 +0200 Subject: [PATCH 22/32] ha_innodb.cc: Fix a typo --- sql/ha_innodb.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 5b29811f7b0..4733829c295 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -3471,7 +3471,7 @@ ha_innobase::estimate_number_of_rows(void) ulonglong estimate; ulonglong local_data_file_length; - DBUG_ENTER("info"); + DBUG_ENTER("estimate_number_of_rows"); /* We do not know if MySQL can call this function before calling external_lock(). To be safe, update the thd of the current table From 7433ffe8807a2e1d74955231e27394cb2e2e3604 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Thu, 16 Jan 2003 01:13:50 +0200 Subject: [PATCH 23/32] ha_innobase.cc: Backport from 4.0: fix possible adaprive hash index latch hang --- sql/ha_innobase.cc | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/sql/ha_innobase.cc b/sql/ha_innobase.cc index c5b529a3881..19ec6a9bb06 100644 --- a/sql/ha_innobase.cc +++ b/sql/ha_innobase.cc @@ -977,14 +977,14 @@ ha_innobase::open( norm_name, NULL); if (NULL == ib_table) { - sql_print_error("InnoDB error:\n\ -Cannot find table %s from the internal data dictionary\n\ -of InnoDB though the .frm file for the table exists. Maybe you\n\ -have deleted and recreated InnoDB data files but have forgotten\n\ -to delete the corresponding .frm files of InnoDB tables, or you\n\ -have moved .frm files to another database?\n\ -Look from section 15.1 of http://www.innodb.com/ibman.html\n\ -how you can resolve the problem.\n", + sql_print_error("InnoDB error:\n" +"Cannot find table %s from the internal data dictionary\n" +"of InnoDB though the .frm file for the table exists. Maybe you\n" +"have deleted and recreated InnoDB data files but have forgotten\n" +"to delete the corresponding .frm files of InnoDB tables, or you\n" +"have moved .frm files to another database?\n" +"Look from section 15.1 of http://www.innodb.com/ibman.html\n" +"how you can resolve the problem.\n", norm_name); free_share(share); @@ -3062,9 +3062,9 @@ 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! */ + update_thd(current_thd); + + trx_search_latch_release_if_reserved(prebuilt->trx); active_index = keynr; @@ -3117,12 +3117,12 @@ ha_innobase::estimate_number_of_rows(void) dict_index_t* index; ulonglong estimate; ulonglong 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("info"); + DBUG_ENTER("estimate_number_of_rows"); + + update_thd(current_thd); + + trx_search_latch_release_if_reserved(prebuilt->trx); index = dict_table_get_first_index_noninline(prebuilt->table); @@ -3178,9 +3178,9 @@ ha_innobase::info( DBUG_ENTER("info"); - /* Warning: since it is not sure that MySQL calls external_lock - before calling this function, the trx field in prebuilt can be - obsolete! */ + update_thd(current_thd); + + trx_search_latch_release_if_reserved(prebuilt->trx); ib_table = prebuilt->table; From 91ba1345125e6463476ddb9eeedefe7a6220949c Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Thu, 16 Jan 2003 01:21:13 +0200 Subject: [PATCH 24/32] btr0btr.h, btr0btr.c, row0purge.c: Backport from 4.0: fix the BLOB hang if the index tree is of height 1 --- innobase/btr/btr0btr.c | 2 +- innobase/include/btr0btr.h | 9 +++++++++ innobase/row/row0purge.c | 4 +++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c index 15642e6ccbc..32750201c8e 100644 --- a/innobase/btr/btr0btr.c +++ b/innobase/btr/btr0btr.c @@ -116,7 +116,7 @@ btr_page_insert_fits( /****************************************************************** Gets the root node of a tree and x-latches it. */ -static + page_t* btr_root_get( /*=========*/ diff --git a/innobase/include/btr0btr.h b/innobase/include/btr0btr.h index f66ad3639d4..7e9d4b73d90 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/row/row0purge.c b/innobase/row/row0purge.c index 5da98943926..d24b296ec50 100644 --- a/innobase/row/row0purge.c +++ b/innobase/row/row0purge.c @@ -428,7 +428,9 @@ skip_secondaries: index = dict_table_get_first_index(node->table); mtr_x_lock(dict_tree_get_lock(index->tree), &mtr); - + + 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! */ From 0efc57eed6936c5336ac954a86715cc520b06bb2 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Thu, 16 Jan 2003 07:15:55 +0200 Subject: [PATCH 25/32] ha_innodb.cc: Make SHOW INNODB STATUS aware when we are estimating index range size etc. --- sql/ha_innodb.cc | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 4733829c295..b71b6e14ab9 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -3414,6 +3414,8 @@ ha_innobase::records_in_range( 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 */ @@ -3451,6 +3453,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); } @@ -3479,6 +3483,9 @@ ha_innobase::estimate_number_of_rows(void) 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 */ @@ -3497,6 +3504,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); } @@ -3556,6 +3565,8 @@ ha_innobase::info( /* 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; @@ -3564,7 +3575,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) { @@ -3632,6 +3648,8 @@ ha_innobase::info( trx_get_error_info(prebuilt->trx)); } + prebuilt->trx->op_info = (char*)""; + DBUG_VOID_RETURN; } @@ -3695,12 +3713,16 @@ ha_innobase::update_table_comment( 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); } @@ -3724,6 +3746,8 @@ ha_innobase::update_table_comment( prebuilt->table); } + prebuilt->trx->op_info = (char*)""; + return(str); } @@ -3740,30 +3764,29 @@ 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); } From 01573f0d95ecf1873772e62da65e94d34f325a26 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Thu, 16 Jan 2003 08:06:43 +0200 Subject: [PATCH 26/32] ha_innodb.cc: Backport from 4.1: make sure change_active_index is only called with a properly initialized InnoDB table handle --- sql/ha_innodb.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index b71b6e14ab9..f8321064683 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -2460,6 +2460,9 @@ ha_innobase::change_active_index( statistic_increment(ha_read_key_count, &LOCK_status); DBUG_ENTER("change_active_index"); + ut_a(prebuilt->trx == + (trx_t*) current_thd->transaction.all.innobase_tid); + active_index = keynr; if (keynr != MAX_KEY && table->keys > 0) { @@ -2487,9 +2490,9 @@ ha_innobase::change_active_index( /* Maybe MySQL changes the active index for a handle also during some queries, we do not know: then it is safest to build - the template such that all columns will be fetched */ + the template such that all columns will be fetched. */ - build_template(prebuilt, user_thd, table, ROW_MYSQL_WHOLE_ROW); + build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW); DBUG_RETURN(0); } From c16e908a2bb32c4ae945b0d0856a92ae309c8514 Mon Sep 17 00:00:00 2001 From: "serg@serg.mysql.com" <> Date: Thu, 16 Jan 2003 13:23:33 +0100 Subject: [PATCH 27/32] bugfix for 'ANALYZE for MERGE' and table-less MERGE table --- mysql-test/r/merge.result | 2 +- mysql-test/t/merge.test | 2 +- sql/ha_myisammrg.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index f7e692d1c7b..86586d5950d 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -258,7 +258,7 @@ t3 CREATE TABLE `t3` ( `othr` int(11) NOT NULL default '0' ) TYPE=MRG_MyISAM 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; diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index 2199f50fb16..e2cd8b57b7e 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -105,7 +105,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/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index b043c6fd942..a93d2e5ed43 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -231,7 +231,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); From 9a2afb60c77eda602d7809194c0dd3887acda810 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Fri, 17 Jan 2003 00:50:27 +0200 Subject: [PATCH 28/32] ha_innodb.cc: Had forgotten to change ha_innodb.cc to reflect that InnoDB now supports HA_READ_PREFIX_LAST --- sql/ha_innodb.cc | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index f8321064683..b4fe6130e9b 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -2249,19 +2249,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); } From e2548b3fa5b628a44ba86e87fecd62c554b7a01e Mon Sep 17 00:00:00 2001 From: "miguel@hegel.local" <> Date: Thu, 16 Jan 2003 22:29:24 -0400 Subject: [PATCH 29/32] Fix VC++ error compiler --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index e7190f575db..46fbee0a7ea 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -749,7 +749,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 From 390982aaa39687b1b631a013b6ff2108eaab9a96 Mon Sep 17 00:00:00 2001 From: "serg@serg.mysql.com" <> Date: Fri, 17 Jan 2003 12:48:23 +0100 Subject: [PATCH 30/32] bugfix for MERGE tables and MAX(key) --- mysql-test/r/merge.result | 2 +- sql/opt_sum.cc | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index 86586d5950d..0bffc93c284 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -536,7 +536,7 @@ INSERT INTO t2 VALUES (1,2), (2,2); CREATE TABLE t ( 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 t where a = 2; max(b) -NULL +2 select max(b) from t1 where a = 2; max(b) 1 diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index 4b6a196051e..ecfa97586e9 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) From 5c7d1020435c8af77b380c08620af68bd76a5cde Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Fri, 17 Jan 2003 13:57:15 +0200 Subject: [PATCH 31/32] After merge fix --- .bzrignore | 1 + myisam/mi_create.c | 2 +- mysql-test/r/group_by.result | 14 ++++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/.bzrignore b/.bzrignore index 70ecba34c3a..1f577634845 100644 --- a/.bzrignore +++ b/.bzrignore @@ -522,3 +522,4 @@ vio/test-ssl vio/test-sslclient vio/test-sslserver vio/viotest-ssl +extra/mysql_waitpid diff --git a/myisam/mi_create.c b/myisam/mi_create.c index 184f126a5b6..039066c5b37 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -449,7 +449,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, share.base.keystart = share.state.state.key_file_length= MY_ALIGN(info_length, myisam_block_size); share.base.max_key_block_length=max_key_block_length; - share.base.max_key_length=ALIGN_SIZE(max_key_length[+4); + share.base.max_key_length=ALIGN_SIZE(max_key_length+4); share.base.records=ci->max_rows; share.base.reloc= ci->reloc_rows; share.base.reclength=real_reclength; diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index ddddb3fa07d..02773f2eb44 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -467,3 +467,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; From 7c63696a426613d7bbaf64c173576772ad588297 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Fri, 17 Jan 2003 15:26:13 +0200 Subject: [PATCH 32/32] page0cur.c: Fix bug in PAGE_CUR_LE_OR_EXTENDS search --- innobase/page/page0cur.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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;