From a3c5ad17472db208c676bbcb59a41fd7fe12b078 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 21 Dec 2002 10:57:53 +0200 Subject: [PATCH 01/22] 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 a3444f379bfaf60f4ddb125488311480c22df8d7 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Dec 2002 14:36:40 +0100 Subject: [PATCH 02/22] - Applied various patches provided by Christian Hammers (MySQL maintainer for the Debian project) to fix some architecture-specific problems and some bugs Makefile.am: - put current directory (.) at front of SUBDIRS list, so that "distclean" is done last. IF done first, "distclean" in include directory fails because config.h is missing, which is removed by distclean in current directory. (thanks to "jww" for the patch) - make "distclean" in libmysql_r, too (Thanks to Christian Hammers from the Debian project for the patch) bdb/dist/aclocal/mutex.m4: - Sparc patch for mutexes/pthreads from Christopher C. Chimelis and Ben Collins from Debian (thanks to Christian Hammers from the Debian project for forwarding it) bdb/include/mutex.h: - Patch for building on m68k architecture (originally provided by Michael Fedrowitz for Debian Linux, thanks to Christian Hammers from the Debian project for forwarding it) ltconfig: - A hardcoded "rpath" is forbidden by the Debian policy (thanks to Christian Hammers from the Debian project for forwarding this patch) man/isamchk.1: - some syntactical correction in the headlines of the manpages for apropos(1) (Thanks to Christian Hammers from the Debian project for the patch) man/isamlog.1: - some syntactical correction in the headlines of the manpages for apropos(1) (Thanks to Christian Hammers from the Debian project for the patch) man/mysql.1: - some syntactical correction in the headlines of the manpages for apropos(1) (Thanks to Christian Hammers from the Debian project for the patch) man/mysql_zap.1: - some syntactical correction in the headlines of the manpages for apropos(1) (Thanks to Christian Hammers from the Debian project for the patch) man/mysqlaccess.1: - some syntactical correction in the headlines of the manpages for apropos(1) (Thanks to Christian Hammers from the Debian project for the patch) man/mysqladmin.1: - some syntactical correction in the headlines of the manpages for apropos(1) (Thanks to Christian Hammers from the Debian project for the patch) man/mysqld.1: - some syntactical correction in the headlines of the manpages for apropos(1) (Thanks to Christian Hammers from the Debian project for the patch) man/mysqld_multi.1: - some syntactical correction in the headlines of the manpages for apropos(1) (Thanks to Christian Hammers from the Debian project for the patch) man/mysqldump.1: - some syntactical correction in the headlines of the manpages for apropos(1) (Thanks to Christian Hammers from the Debian project for the patch) - fixed nroff mistake man/mysqlshow.1: - some syntactical correction in the headlines of the manpages for apropos(1) (Thanks to Christian Hammers from the Debian project for the patch) man/perror.1: - some syntactical correction in the headlines of the manpages for apropos(1) (Thanks to Christian Hammers from the Debian project for the patch) man/replace.1: - some syntactical correction in the headlines of the manpages for apropos(1) (Thanks to Christian Hammers from the Debian project for the patch) man/safe_mysqld.1: - some syntactical correction in the headlines of the manpages for apropos(1) (Thanks to Christian Hammers from the Debian project for the patch) scripts/mysql_fix_privilege_tables.sh: - fixed some typos - script cleanup scripts/mysqlaccess.sh: - make $script_log path less dependent on the shell scripts/safe_mysqld.sh: - applied patch provided by Debian to enhance security (This way all logs and databases are created world-nothing). --- 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/22] 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 884e3dee03caaece1f82acaaefd2a18caa5d89d4 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 26 Dec 2002 17:50:07 +0200 Subject: [PATCH 04/22] 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: Safety fix to not allow one to specify too big max_alloc_packet sql/net_serv.cc: Safety fix to not cause conflicts with extended packages in 4.0. (Should not cause any notable changes for 3.23 servers) --- 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 22611051945dc581414895086bd114dd597f69c7 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 27 Dec 2002 17:37:55 +0100 Subject: [PATCH 05/22] - fixes to properly make a "make distclean" (some files were not removed) (There are probably some more to fix) libmysql/Makefile.shared: - clean up the vio_* and ctype-* symlinks that are created by link_source (thanks to Christian Hammers from Debian for the patch) strings/Makefile.am: - remove ctype_autonf.c on "make distclean" (it's generated by "configure") --- 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 d78c9adb55a7f43bc234cfbf818ce8183ec73daf Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 27 Dec 2002 21:39:35 +0200 Subject: [PATCH 06/22] 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: Fixed max_key_length when using UNIQUE keys. myisam/mi_unique.c: Simple optimization Make different CRC for keys with null and empty strings. mysql-test/r/group_by.result: Updated results mysql-test/t/group_by.test: Test of bug --- 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 9efb607e11383be71e7c9ca8eabd882e9d6e4afd Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 27 Dec 2002 23:29:27 +0200 Subject: [PATCH 07/22] 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 787307d5562be0b1b0b303add57f136b022cef2b Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 5 Jan 2003 22:15:03 +0200 Subject: [PATCH 08/22] 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: Backport bugfix from 4.0: index cursor restoration could theoretically fail innobase/log/log0log.c: Backport bugfix from 4.0: combined log file size >= 2 GB could cause log to be written in wrong place --- 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 b77dcb19e608d3947257b02e64cc84d09dae1223 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 9 Jan 2003 23:28:30 +0200 Subject: [PATCH 09/22] Fixed wrong packed length for packet > 16M. sql/net_pkg.cc: Fixed wrong packed length for packet > 16M. (Not used in 3.23) --- 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 b96140fe3a430ea4cb330ef915c35357ccc1efe9 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 16 Jan 2003 01:13:50 +0200 Subject: [PATCH 10/22] ha_innobase.cc: Backport from 4.0: fix possible adaprive hash index latch hang sql/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 cb460d38ccbc97c8c4fde22fdb7c4b5333cad8bb Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 16 Jan 2003 01:21:13 +0200 Subject: [PATCH 11/22] btr0btr.h, btr0btr.c, row0purge.c: Backport from 4.0: fix the BLOB hang if the index tree is of height 1 innobase/row/row0purge.c: Backport from 4.0: fix the BLOB hang if the index tree is of height 1 innobase/btr/btr0btr.c: Backport from 4.0: fix the BLOB hang if the index tree is of height 1 innobase/include/btr0btr.h: 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 723e70ebb71072056f8160e63840bda36250845a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Jan 2003 13:52:23 +0200 Subject: [PATCH 12/22] Fixed typo --- myisam/mi_create.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/myisam/mi_create.c b/myisam/mi_create.c index 5a5a49533da..d0ba37a77c6 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -447,7 +447,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, share.base.records=ci->max_rows; share.base.reloc= ci->reloc_rows; share.base.reclength=real_reclength; - share.base.pack_reclength=reclength+ test(options & HA_OPTION_CHECKSUM);; + share.base.pack_reclength=reclength+ test(options & HA_OPTION_CHECKSUM); share.base.max_pack_length=pack_reclength; share.base.min_pack_length=min_pack_length; share.base.pack_bits=packed; From 4dd2eb198f8ab61ed5b4957851d3c6b04a999014 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Jan 2003 13:57:15 +0200 Subject: [PATCH 13/22] After merge fix BitKeeper/etc/ignore: added extra/mysql_waitpid --- .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 380115abd7221d5c5ddd8b8e13060d5f5a92cada Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Jan 2003 15:26:13 +0200 Subject: [PATCH 14/22] page0cur.c: Fix bug in PAGE_CUR_LE_OR_EXTENDS search innobase/page/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; From d26a7d483c53e83bf2d93d439f330c1826055b85 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Jan 2003 15:56:16 +0200 Subject: [PATCH 15/22] Fixed bug with the --slow-log when logging an administrator command (like FLUSH TABLES). (Code is already in 4.0) sql/log.cc: Fixed bug with the --slow-log when logging an administrator command (like FLUSH TABLES). --- sql/log.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/log.cc b/sql/log.cc index b6c842e551d..ab3277fe58b 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -963,6 +963,7 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length, end=strxmov(buff, "# administrator command: ", command_name[thd->command], NullS); query_length=(ulong) (end-buff); + query=buff; } if (my_b_write(&log_file, (byte*) query,query_length) || my_b_write(&log_file, (byte*) ";\n",2) || From 43523184f2c3664b221ef64c5b23dd7710e02bef Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 18 Jan 2003 15:01:56 +0200 Subject: [PATCH 16/22] btr0sea.h, btr0sea.c: Fix a crash in page_dir_find_owner_slot if an adaptive hash index search coincides with purge or an insert innobase/btr/btr0sea.c: Fix a crash in page_dir_find_owner_slot if an adaptive hash index search coincides with purge or an insert innobase/include/btr0sea.h: Fix a crash in page_dir_find_owner_slot if an adaptive hash index search coincides with purge or an insert --- innobase/btr/btr0sea.c | 28 +++++++++++++++++++++++++++- innobase/include/btr0sea.h | 14 ++++++++++---- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index de3fe6e196e..5c5ed934a9b 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -508,6 +508,14 @@ btr_search_check_guess( /*===================*/ /* out: TRUE if success */ btr_cur_t* cursor, /* in: guessed cursor position */ + ibool can_only_compare_to_cursor_rec, + /* in: if we do not have a latch on the page + of cursor, but only a latch on + btr_search_latch, then ONLY the columns + of the record UNDER the cursor are + protected, not the next or previous record + in the chain: we cannot look at the next or + previous record to check our guess! */ dtuple_t* tuple, /* in: data tuple */ ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G, or PAGE_CUR_GE */ @@ -566,6 +574,13 @@ btr_search_check_guess( } } + if (can_only_compare_to_cursor_rec) { + /* Since we could not determine if our guess is right just by + looking at the record under the cursor, return FALSE */ + + return(FALSE); + } + match = 0; bytes = 0; @@ -670,6 +685,7 @@ btr_search_guess_on_hash( ulint fold; ulint tuple_n_fields; dulint tree_id; + ibool can_only_compare_to_cursor_rec = TRUE; #ifdef notdefined btr_cur_t cursor2; btr_pcur_t pcur; @@ -744,6 +760,8 @@ btr_search_guess_on_hash( goto failure; } + can_only_compare_to_cursor_rec = FALSE; + buf_page_dbg_add_level(page, SYNC_TREE_NODE_FROM_HASH); } @@ -775,7 +793,15 @@ btr_search_guess_on_hash( fold); */ } else { - success = btr_search_check_guess(cursor, tuple, mode, mtr); + /* If we only have the latch on btr_search_latch, not on the + page, it only protects the columns of the record the cursor + is positioned on. We cannot look at the next of the previous + record to determine if our guess for the cursor position is + right. */ + + success = btr_search_check_guess(cursor, + can_only_compare_to_cursor_rec, + tuple, mode, mtr); } if (!success) { diff --git a/innobase/include/btr0sea.h b/innobase/include/btr0sea.h index 14feca5d5c5..ee762a12221 100644 --- a/innobase/include/btr0sea.h +++ b/innobase/include/btr0sea.h @@ -234,10 +234,16 @@ struct btr_search_sys_struct{ extern btr_search_sys_t* btr_search_sys; /* The latch protecting the adaptive search system: this latch protects the -(1) positions of records on those pages where a hash index has been built. -NOTE: It does not protect values of non-ordering fields within a record from -being updated in-place! We can use fact (1) to perform unique searches to -indexes. */ +(1) hash index; +(2) columns of a record to which we have a pointer in the hash index; + +but does NOT protect: + +(3) next record offset field in a record; +(4) next or previous records on the same page. + +Bear in mind (3) and (4) when using the hash index. +*/ extern rw_lock_t* btr_search_latch_temp; From 99b314449f3e6529f52f28ae211a3975ff678863 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 18 Jan 2003 15:16:26 +0200 Subject: [PATCH 17/22] btr0sea.c: Backport from 4.0: fix bug in adaptive hash index search innobase/btr/btr0sea.c: Backport from 4.0: fix bug in adaptive hash index search --- innobase/btr/btr0sea.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index 421aafba1c5..fd65a98cc0f 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -470,6 +470,7 @@ btr_search_check_guess( /*===================*/ /* out: TRUE if success */ btr_cur_t* cursor, /* in: guessed cursor position */ + ibool can_only_compare_to_cursor_rec, dtuple_t* tuple, /* in: data tuple */ ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G, or PAGE_CUR_GE */ @@ -528,6 +529,10 @@ btr_search_check_guess( } } + if (can_only_compare_to_cursor_rec) { + return(FALSE); + } + match = 0; bytes = 0; @@ -632,6 +637,7 @@ btr_search_guess_on_hash( ulint fold; ulint tuple_n_fields; dulint tree_id; + ibool can_only_compare_to_cursor_rec = TRUE; #ifdef notdefined btr_cur_t cursor2; btr_pcur_t pcur; @@ -706,6 +712,8 @@ btr_search_guess_on_hash( goto failure; } + can_only_compare_to_cursor_rec = FALSE; + buf_page_dbg_add_level(page, SYNC_TREE_NODE_FROM_HASH); } @@ -737,7 +745,9 @@ btr_search_guess_on_hash( fold); */ } else { - success = btr_search_check_guess(cursor, tuple, mode, mtr); + success = btr_search_check_guess(cursor, + can_only_compare_to_cursor_rec, + tuple, mode, mtr); } if (!success) { From bd70549275027c4c2202038034408721f1aa6367 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 18 Jan 2003 23:38:55 +0200 Subject: [PATCH 18/22] Only set thd->query to 0 if LOCK_thread_count is hold This fixes a possible core dump problem in SHOW PROCESSLIST sql/slave.cc: Only set thd->query to 0 if LOCK_thread_count is hold sql/sql_db.cc: Only set thd->query to 0 if LOCK_thread_count is hold Also first set query_length, then query sql/sql_parse.cc: Indentation changes --- sql/slave.cc | 34 ++++++++++++++++++++++++++-------- sql/sql_db.cc | 10 ++++++---- sql/sql_parse.cc | 17 ++++++++--------- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/sql/slave.cc b/sql/slave.cc index f2f37807128..0bbf9bf227d 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -22,6 +22,7 @@ #include "slave.h" #include #include +#include #define RPL_LOG_NAME (glob_mi.log_file_name[0] ? glob_mi.log_file_name :\ "FIRST") @@ -362,6 +363,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, TABLE_LIST tables; int error= 1; handler *file; + char *query; if (packet_len == packet_error) { @@ -375,15 +377,23 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, return 1; } thd->command = COM_TABLE_DUMP; - thd->query = sql_alloc(packet_len + 1); - if (!thd->query) + /* Note that we should not set thd->query until the area is initalized */ + if (!(query = sql_alloc(packet_len + 1))) { sql_print_error("create_table_from_dump: out of memory"); net_printf(&thd->net, ER_GET_ERRNO, "Out of memory"); return 1; } - memcpy(thd->query, net->read_pos, packet_len); - thd->query[packet_len] = 0; + memcpy(query, net->read_pos, packet_len); + query[packet_len]= 0; + thd->query_length= packet_len; + /* + We make the following lock in an attempt to ensure that the compiler will + not rearrange the code so that thd->query is set too soon + */ + VOID(pthread_mutex_lock(&LOCK_thread_count)); + thd->query= query; + VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->current_tablenr = 0; thd->query_error = 0; thd->net.no_send_ok = 1; @@ -967,10 +977,11 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len) thd->db = rewrite_db((char*)qev->db); if (db_ok(thd->db, replicate_do_db, replicate_ignore_db)) { - thd->query = (char*)qev->query; + thd->query_length= q_len; thd->set_time((time_t)qev->when); thd->current_tablenr = 0; VOID(pthread_mutex_lock(&LOCK_thread_count)); + thd->query = (char*)qev->query; thd->query_id = query_id++; VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->last_nx_table = thd->last_nx_db = 0; @@ -1008,7 +1019,9 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len) else { // master could be inconsistent, abort and tell DBA to check/fix it + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->db = thd->query = 0; + VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->convert_set = 0; close_thread_tables(thd); free_root(&thd->mem_root,0); @@ -1017,7 +1030,9 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len) } } thd->db = 0; // prevent db from being freed + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query = 0; // just to be sure + VOID(pthread_mutex_unlock(&LOCK_thread_count)); // assume no convert for next query unless set explictly thd->convert_set = 0; close_thread_tables(thd); @@ -1059,10 +1074,11 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len) Load_log_event* lev = (Load_log_event*)ev; init_sql_alloc(&thd->mem_root, 8192,0); thd->db = rewrite_db((char*)lev->db); + DBUG_ASSERT(thd->query == 0); thd->query = 0; thd->query_error = 0; - if(db_ok(thd->db, replicate_do_db, replicate_ignore_db)) + if (db_ok(thd->db, replicate_do_db, replicate_ignore_db)) { thd->set_time((time_t)lev->when); thd->current_tablenr = 0; @@ -1490,9 +1506,11 @@ the slave thread with \"mysqladmin start-slave\". We stopped at log \ sql_print_error("Slave thread exiting, replication stopped in log '%s' at \ position %s", RPL_LOG_NAME, llstr(glob_mi.pos,llbuff)); + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query = thd->db = 0; // extra safety - if(mysql) - mc_mysql_close(mysql); + VOID(pthread_mutex_unlock(&LOCK_thread_count)); + if (mysql) + mc_mysql_close(mysql); thd->proc_info = "Waiting for slave mutex on exit"; pthread_mutex_lock(&LOCK_slave); slave_running = 0; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 0be1b7b0411..1ba02bb416c 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -89,9 +89,9 @@ void mysql_create_db(THD *thd, char *db, uint create_options) } if (!thd->query) { - thd->query = path; thd->query_length = (uint) (strxmov(path,"create database ", db, NullS)- path); + thd->query = path; } { mysql_update_log.write(thd,thd->query, thd->query_length); @@ -103,8 +103,9 @@ void mysql_create_db(THD *thd, char *db, uint create_options) } if (thd->query == path) { + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query = 0; // just in case - thd->query_length = 0; + VOID(pthread_mutex_unlock(&LOCK_thread_count)); } send_ok(&thd->net, result); @@ -178,9 +179,9 @@ void mysql_rm_db(THD *thd,char *db,bool if_exists) if (!thd->query) { - thd->query = path; thd->query_length = (uint) (strxmov(path,"drop database ", db, NullS)- path); + thd->query = path; } mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) @@ -190,8 +191,9 @@ void mysql_rm_db(THD *thd,char *db,bool if_exists) } if (thd->query == path) { + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query = 0; // just in case - thd->query_length = 0; + VOID(pthread_mutex_unlock(&LOCK_thread_count)); } send_ok(&thd->net,(ulong) deleted); } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index f26be7f47e0..d8a4a5fee83 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -691,15 +691,15 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd) thd->free_list = 0; thd->query = tbl_name; - if((error = mysqld_dump_create_info(thd, table, -1))) - { - my_error(ER_GET_ERRNO, MYF(0)); - goto err; - } + if ((error = mysqld_dump_create_info(thd, table, -1))) + { + my_error(ER_GET_ERRNO, MYF(0)); + goto err; + } net_flush(&thd->net); error = table->file->dump(thd,fd); - if(error) - my_error(ER_GET_ERRNO, MYF(0)); + if (error) + my_error(ER_GET_ERRNO, MYF(0)); err: @@ -776,9 +776,8 @@ bool do_command(THD *thd) *tbl_name++ = 0; memcpy(tbl_name, data + db_len + 2, tbl_len); tbl_name[tbl_len] = 0; - if(mysql_table_dump(thd, db, tbl_name, -1)) + if (mysql_table_dump(thd, db, tbl_name, -1)) send_error(&thd->net); // dump to NET - break; } case COM_CHANGE_USER: From 88df4e732605df862dd264f65788ab1d58a9b153 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 19 Jan 2003 02:00:26 +0200 Subject: [PATCH 19/22] Fixes cases where thd->query was not protected. This fixes a problem with SHOW PROCESSLIST sql/log_event.cc: Fixes cases where thd->query was not protected sql/sql_acl.cc: Table privileges was not reset on FLUSH PRIVILEGES if tables_priv was empty sql/sql_db.cc: Fixes cases where thd->query was not protected --- sql/log_event.cc | 10 ++++++++-- sql/sql_acl.cc | 1 + sql/sql_db.cc | 10 +++++----- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 45f54e420de..e243a953c63 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1702,10 +1702,11 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) if (db_ok(thd->db, replicate_do_db, replicate_ignore_db)) { - thd->query = (char*)query; thd->set_time((time_t)when); thd->current_tablenr = 0; + thd->query_length= q_len; VOID(pthread_mutex_lock(&LOCK_thread_count)); + thd->query = (char*)query; thd->query_id = query_id++; VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->query_error = 0; // clear error @@ -1760,7 +1761,9 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) else { // master could be inconsistent, abort and tell DBA to check/fix it + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->db = thd->query = 0; + VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->variables.convert_set = 0; close_thread_tables(thd); free_root(&thd->mem_root,0); @@ -1768,7 +1771,9 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) } } thd->db= 0; // prevent db from being freed + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query= 0; // just to be sure + VOID(pthread_mutex_unlock(&LOCK_thread_count)); // assume no convert for next query unless set explictly thd->variables.convert_set = 0; close_thread_tables(thd); @@ -1816,7 +1821,8 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, { init_sql_alloc(&thd->mem_root, 8192,0); thd->db = rewrite_db((char*)db); - thd->query = 0; + DBUG_ASSERT(thd->query == 0); + thd->query = 0; // Should not be needed thd->query_error = 0; if (db_ok(thd->db, replicate_do_db, replicate_ignore_db)) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 1f8f25e5fb8..da563f0547c 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2322,6 +2322,7 @@ my_bool grant_init(THD *org_thd) if (t_table->file->index_first(t_table->record[0])) { t_table->file->index_end(); + return_val= 0; goto end_unlock; } grant_option= TRUE; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index ffb02cd36c1..4cb46c00bed 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -78,9 +78,9 @@ int mysql_create_db(THD *thd, char *db, uint create_options, bool silent) if (!thd->query) { /* The client used the old obsolete mysql_create_db() call */ - thd->query_length = (uint) (strxmov(path,"create database `", db, "`", - NullS) - path); - thd->query = path; + thd->query_length= (uint) (strxmov(path,"create database `", db, "`", + NullS) - path); + thd->query= path; } { mysql_update_log.write(thd,thd->query, thd->query_length); @@ -93,7 +93,7 @@ int mysql_create_db(THD *thd, char *db, uint create_options, bool silent) if (thd->query == path) { VOID(pthread_mutex_lock(&LOCK_thread_count)); - thd->query = 0; // just in case + thd->query= 0; VOID(pthread_mutex_unlock(&LOCK_thread_count)); } send_ok(&thd->net, result); @@ -182,7 +182,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) if (thd->query == path) { VOID(pthread_mutex_lock(&LOCK_thread_count)); - thd->query = 0; // just in case + thd->query= 0; VOID(pthread_mutex_unlock(&LOCK_thread_count)); } send_ok(&thd->net,(ulong) deleted); From 09b1e7d6076748b198f54008495cf4e60e156b86 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 19 Jan 2003 17:15:14 +0200 Subject: [PATCH 20/22] Fixed bug in LEFT JOIN with impossible ON/WHERE expression mysql-test/r/join.result: Test of LEFT JOIN bug mysql-test/t/join.test: Test of LEFT JOIN bug --- mysql-test/r/join.result | 13 ++++++++++-- mysql-test/t/join.test | 9 +++++++-- sql/sql_select.cc | 43 +++++++++++++++++++++++++++++----------- 3 files changed, 49 insertions(+), 16 deletions(-) diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index 96113dcdc8b..ff608825b9c 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -14,8 +14,7 @@ insert into t1 values (101); insert into t1 values (105); insert into t1 values (106); insert into t1 values (107); -insert into t2 values (107); -insert into t2 values (75); +insert into t2 values (107),(75),(1000); select t1.id, t2.id from t1, t2 where t2.id = t1.id; id id 107 107 @@ -28,6 +27,16 @@ select t1.id, count(t2.id) from t1,t2 where t2.id = t1.id group by t2.id; id count(t2.id) 75 1 107 1 +select t1.id,t2.id from t2 left join t1 on t1.id>=74 and t1.id<=0 where t2.id=75 and t1.id is null; +id id +NULL 75 +explain select t1.id,t2.id from t2 left join t1 on t1.id>=74 and t1.id<=0 where t2.id=75 and t1.id is null; +table type possible_keys key key_len ref rows Extra +t1 const PRIMARY NULL NULL NULL 1 Impossible ON condition +t2 ALL NULL NULL NULL NULL 3 Using where +explain select t1.id, t2.id from t1, t2 where t2.id = t1.id and t1.id <0 and t1.id > 0; +Comment +Impossible WHERE noticed after reading const tables drop table t1,t2; CREATE TABLE t1 ( id int(11) NOT NULL auto_increment, diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test index 18006e8fd22..f58281af003 100644 --- a/mysql-test/t/join.test +++ b/mysql-test/t/join.test @@ -19,13 +19,18 @@ insert into t1 values (105); insert into t1 values (106); insert into t1 values (107); -insert into t2 values (107); -insert into t2 values (75); +insert into t2 values (107),(75),(1000); select t1.id, t2.id from t1, t2 where t2.id = t1.id; select t1.id, count(t2.id) from t1,t2 where t2.id = t1.id group by t1.id; select t1.id, count(t2.id) from t1,t2 where t2.id = t1.id group by t2.id; +# +# Test problems with impossible ON or WHERE +# +select t1.id,t2.id from t2 left join t1 on t1.id>=74 and t1.id<=0 where t2.id=75 and t1.id is null; +explain select t1.id,t2.id from t2 left join t1 on t1.id>=74 and t1.id<=0 where t2.id=75 and t1.id is null; +explain select t1.id, t2.id from t1, t2 where t2.id = t1.id and t1.id <0 and t1.id > 0; drop table t1,t2; # diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 237197ba6be..4bae58d70cd 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB +/* Copyright (C) 2000-2003 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 @@ -1009,7 +1009,6 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, table_map found_const_table_map,all_table_map; TABLE **table_vector; JOIN_TAB *stat,*stat_end,*s,**stat_ref; - SQL_SELECT *select; KEYUSE *keyuse,*start_keyuse; table_map outer_join=0; JOIN_TAB *stat_vector[MAX_TABLES+1]; @@ -1021,7 +1020,6 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, table_vector=(TABLE**) join->thd->alloc(sizeof(TABLE*)*(table_count*2)); if (!stat || !stat_ref || !table_vector) DBUG_RETURN(1); // Eom /* purecov: inspected */ - select=0; join->best_ref=stat_vector; @@ -1205,7 +1203,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, { // Found everything for ref. int tmp; ref_changed = 1; - s->type=JT_CONST; + s->type= JT_CONST; join->const_table_map|=table->map; set_position(join,const_count++,s,start_keyuse); if (create_ref_for_key(join, s, start_keyuse, @@ -1256,23 +1254,44 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, if (s->const_keys) { ha_rows records; - if (!select) - select=make_select(s->table, found_const_table_map, - found_const_table_map, - and_conds(conds,s->on_expr),&error); - records=get_quick_record_count(select,s->table, s->const_keys, - join->row_limit); + SQL_SELECT *select; + select= make_select(s->table, found_const_table_map, + found_const_table_map, + s->on_expr ? s->on_expr : conds, + &error); + records= get_quick_record_count(select,s->table, s->const_keys, + join->row_limit); s->quick=select->quick; s->needed_reg=select->needed_reg; select->quick=0; + if (records == 0 && s->table->reginfo.impossible_range) + { + /* + Impossible WHERE or ON expression + In case of ON, we mark that the we match one empty NULL row. + In case of WHERE, don't set found_const_table_map to get the + caller to abort with a zero row result. + */ + join->const_table_map|= s->table->map; + set_position(join,const_count++,s,(KEYUSE*) 0); + s->type= JT_CONST; + if (s->on_expr) + { + /* Generate empty row */ + s->info= "Impossible ON condition"; + found_const_table_map|= s->table->map; + s->type= JT_CONST; + mark_as_null_row(s->table); // All fields are NULL + } + } if (records != HA_POS_ERROR) { s->found_records=records; s->read_time= (ha_rows) (s->quick ? s->quick->read_time : 0.0); } + delete select; } } - delete select; /* Find best combination and return it */ join->join_tab=stat; @@ -2367,7 +2386,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, keyparts != keyinfo->key_parts) j->type=JT_REF; /* Must read with repeat */ else if (ref_key == j->ref.key_copy) - { /* Should never be reached */ + { /* This happen if we are using a constant expression in the ON part of an LEFT JOIN. From f6cbace93e27301bda14d833763b805bf64f0da2 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 20 Jan 2003 18:17:14 +0200 Subject: [PATCH 21/22] Fixed bug with EXPLAIN on empty table mysql-test/r/explain.result: test of bug with EXPLAIN on empty table mysql-test/t/explain.test: test of bug with EXPLAIN on empty table --- mysql-test/r/explain.result | 3 ++ mysql-test/t/explain.test | 7 +++-- sql/sql_select.cc | 55 +++++++++++++++++++------------------ 3 files changed, 37 insertions(+), 28 deletions(-) diff --git a/mysql-test/r/explain.result b/mysql-test/r/explain.result index 876846a5236..fa15165722d 100644 --- a/mysql-test/r/explain.result +++ b/mysql-test/r/explain.result @@ -1,5 +1,8 @@ drop table if exists t1; create table t1 (id int not null, str char(10), unique(str)); +explain select * from t1; +table type possible_keys key key_len ref rows Extra +t1 system NULL NULL NULL NULL 0 const row not found insert into t1 values (1, null),(2, null),(3, "foo"),(4, "bar"); select * from t1 where str is null; id str diff --git a/mysql-test/t/explain.test b/mysql-test/t/explain.test index 31a01ae1360..8a41ebe5b4f 100644 --- a/mysql-test/t/explain.test +++ b/mysql-test/t/explain.test @@ -3,6 +3,7 @@ drop table if exists t1; create table t1 (id int not null, str char(10), unique(str)); +explain select * from t1; insert into t1 values (1, null),(2, null),(3, "foo"),(4, "bar"); select * from t1 where str is null; select * from t1 where str="foo"; @@ -12,8 +13,10 @@ explain select * from t1 ignore key (str) where str="foo"; explain select * from t1 use key (str,str) where str="foo"; #The following should give errors -!$1072 explain select * from t1 use key (str,str,foo) where str="foo"; -!$1072 explain select * from t1 ignore key (str,str,foo) where str="foo"; +--error 1072 +explain select * from t1 use key (str,str,foo) where str="foo"; +--error 1072 +explain select * from t1 ignore key (str,str,foo) where str="foo"; drop table t1; explain select 1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 4bae58d70cd..e811c55ed1b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7352,36 +7352,39 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, if (tab->info) item_list.push_back(new Item_string(tab->info,strlen(tab->info))); - else if (tab->select) + else { - if (tab->use_quick == 2) + if (tab->select) { - sprintf(buff_ptr,"; Range checked for each record (index map: %u)", - tab->keys); - buff_ptr=strend(buff_ptr); + if (tab->use_quick == 2) + { + sprintf(buff_ptr,"; Range checked for each record (index map: %u)", + tab->keys); + buff_ptr=strend(buff_ptr); + } + else + buff_ptr=strmov(buff_ptr,"; Using where"); } - else - buff_ptr=strmov(buff_ptr,"; Using where"); + if (key_read) + buff_ptr= strmov(buff_ptr,"; Using index"); + if (table->reginfo.not_exists_optimize) + buff_ptr= strmov(buff_ptr,"; Not exists"); + if (need_tmp_table) + { + need_tmp_table=0; + buff_ptr= strmov(buff_ptr,"; Using temporary"); + } + if (need_order) + { + need_order=0; + buff_ptr= strmov(buff_ptr,"; Using filesort"); + } + if (distinct && test_all_bits(used_tables,thd->used_tables)) + buff_ptr= strmov(buff_ptr,"; Distinct"); + if (buff_ptr == buff) + buff_ptr+= 2; + item_list.push_back(new Item_string(buff+2,(uint) (buff_ptr - buff)-2)); } - if (key_read) - buff_ptr= strmov(buff_ptr,"; Using index"); - if (table->reginfo.not_exists_optimize) - buff_ptr= strmov(buff_ptr,"; Not exists"); - if (need_tmp_table) - { - need_tmp_table=0; - buff_ptr= strmov(buff_ptr,"; Using temporary"); - } - if (need_order) - { - need_order=0; - buff_ptr= strmov(buff_ptr,"; Using filesort"); - } - if (distinct && test_all_bits(used_tables,thd->used_tables)) - buff_ptr= strmov(buff_ptr,"; Distinct"); - if (buff_ptr == buff) - buff_ptr+= 2; - item_list.push_back(new Item_string(buff+2,(uint) (buff_ptr - buff)-2)); // For next iteration used_tables|=table->map; if (result->send_data(item_list)) From d5833961ced5efb64c62d17dd7e632eefefede3d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jan 2003 00:38:55 +0200 Subject: [PATCH 22/22] ha_innodb.cc: Convert TL_READ_NO_INSERT to TL_READ to allow concurrent inserts to the table in INSERT INTO ... SELECT ... FROM table sql/ha_innodb.cc: Convert TL_READ_NO_INSERT to TL_READ to allow concurrent inserts to the table in INSERT INTO ... SELECT ... FROM table --- sql/ha_innodb.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index b4fe6130e9b..b1cb45be6b3 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -4166,6 +4166,16 @@ ha_innobase::store_lock( lock_type = TL_WRITE_ALLOW_WRITE; } + /* In queries of type INSERT INTO t1 SELECT ... FROM t2 ... + MySQL would use the lock TL_READ_NO_INSERT on t2, and that + would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts + to t2. Convert the lock to a normal read lock to allow + concurrent inserts to t2. */ + + if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables) { + lock_type = TL_READ; + } + lock.type=lock_type; }