diff --git a/include/Makefile.am b/include/Makefile.am index 27b359bb6a3..26161b36ab8 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -32,7 +32,8 @@ noinst_HEADERS = config-win.h config-netware.h \ thr_lock.h t_ctype.h violite.h md5.h base64.h \ mysql_version.h.in my_handler.h my_time.h decimal.h \ my_vle.h my_user.h my_atomic.h atomic/nolock.h \ - atomic/rwlock.h atomic/x86-gcc.h atomic/x86-msvc.h + atomic/rwlock.h atomic/x86-gcc.h atomic/x86-msvc.h \ + my_libwrap.h # mysql_version.h are generated CLEANFILES = mysql_version.h my_config.h readline openssl diff --git a/include/my_libwrap.h b/include/my_libwrap.h new file mode 100644 index 00000000000..6437cbaed84 --- /dev/null +++ b/include/my_libwrap.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2000 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 */ + +#ifdef HAVE_LIBWRAP +#include +#include +#ifdef NEED_SYS_SYSLOG_H +#include +#endif /* NEED_SYS_SYSLOG_H */ + +extern void my_fromhost(struct request_info *req); +extern int my_hosts_access(struct request_info *req); +extern char *my_eval_client(struct request_info *req); + +#endif /* HAVE_LIBWRAP */ diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index 772179d758a..bcad0460acc 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -686,3 +686,7 @@ ERROR 42S22: Unknown column 'z' in 'field list' insert into t1(x,y) select x,z from t2 on duplicate key update x=values(t2.x); ERROR 42S22: Unknown column 't2.x' in 'field list' drop table t1,t2; +CREATE TABLE t1 (a int PRIMARY KEY); +INSERT INTO t1 values (1), (2); +INSERT INTO t1 SELECT a + 2 FROM t1 LIMIT 1; +DROP TABLE t1; diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 0ec74f59de3..bb62f2a063b 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -747,6 +747,19 @@ select count(id1) from t1 where id2 = 10; count(id1) 5 drop table t1; +CREATE TABLE t1(a TINYINT, KEY(a)) ENGINE=MyISAM; +INSERT INTO t1 VALUES(1); +SELECT MAX(a) FROM t1 IGNORE INDEX(a); +MAX(a) +1 +ALTER TABLE t1 DISABLE KEYS; +SELECT MAX(a) FROM t1; +MAX(a) +1 +SELECT MAX(a) FROM t1 IGNORE INDEX(a); +MAX(a) +1 +DROP TABLE t1; CREATE TABLE t1(a CHAR(9), b VARCHAR(7)) ENGINE=MyISAM; INSERT INTO t1(a) VALUES('xxxxxxxxx'),('xxxxxxxxx'); UPDATE t1 AS ta1,t1 AS ta2 SET ta1.b='aaaaaa',ta2.b='bbbbbb'; diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 976f7191a5f..355b64e0405 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -392,8 +392,10 @@ drop table t1; # Bug #16546 # -select now() - now() + 0, curtime() - curtime() + 0, - sec_to_time(1) + 0, from_unixtime(1) + 0; +create table t1 select now() - now(), curtime() - curtime(), + sec_to_time(1) + 0, from_unixtime(1) + 0; +show create table t1; +drop table t1; --echo End of 4.1 tests diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index 5dd6f338865..0b9a0e86ba9 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -224,4 +224,17 @@ insert into t1(x,y) select x,z from t2 on duplicate key update x=values(z); insert into t1(x,y) select x,z from t2 on duplicate key update x=values(t2.x); drop table t1,t2; +# +# Bug #9676: INSERT INTO x SELECT .. FROM x LIMIT 1; slows down with big +# tables +# + +#Note: not an exsaustive test : just a check of the code path. +CREATE TABLE t1 (a int PRIMARY KEY); +INSERT INTO t1 values (1), (2); + +INSERT INTO t1 SELECT a + 2 FROM t1 LIMIT 1; + +DROP TABLE t1; + # End of 4.1 tests diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 2cce38498b8..9936b8bfc44 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -697,6 +697,18 @@ select count(*) from t1 where id2 = 10; select count(id1) from t1 where id2 = 10; drop table t1; +# +# BUG##20357 - Got error 124 from storage engine using MIN and MAX functions +# in queries +# +CREATE TABLE t1(a TINYINT, KEY(a)) ENGINE=MyISAM; +INSERT INTO t1 VALUES(1); +SELECT MAX(a) FROM t1 IGNORE INDEX(a); +ALTER TABLE t1 DISABLE KEYS; +SELECT MAX(a) FROM t1; +SELECT MAX(a) FROM t1 IGNORE INDEX(a); +DROP TABLE t1; + # # BUG#18036 - update of table joined to self reports table as crashed # diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index ae3981ce47b..b75d0dd8bb6 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2285,6 +2285,25 @@ EXPLAIN SELECT * FROM t1 FORCE INDEX (a); DROP TABLE t1; +# +# Bug #18759 "Incorrect string to numeric conversion" +# +# This test is here so that the behavior will not be changed to 4.1 +# and not to 5.0 either. In 4.1 and 5.0 sending an integer as a string +# will be converted internally to real (double) value and it is not +# as accurate as bigint (longlong) for integers. Thus the results may +# vary. In 5.1 internally it is decimal, which is a string type and +# will be more accurate. Due to rather big changes needed to fix this +# in 4.1 or 5.0 it is not desired to do it in the stable versions. +# +# This test is here only to make sure that behavior is not changed in +# 4.1 and 5.0 +# +CREATE TABLE t1 (i BIGINT UNSIGNED NOT NULL); +INSERT INTO t1 VALUES (10); +SELECT i='1e+01',i=1e+01, i in (1e+01,1e+01), i in ('1e+01','1e+01') FROM t1; +DROP TABLE t1; + # End of 4.1 tests # diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index c30d5c8f43e..6dd11df5de6 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -248,6 +248,18 @@ fun:_dl_relocate_object } +# +# Warning from my_thread_init becasue mysqld dies before kill thread exists +# + +{ + my_thread_init kill thread memory loss second + Memcheck:Leak + fun:calloc + fun:my_thread_init + fun:kill_server_thread +} + # # Leaks reported in _dl_* internal functions on Linux amd64 / glibc2.3.2. # diff --git a/mysys/Makefile.am b/mysys/Makefile.am index 2838427e9e0..b209d64e78f 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -53,7 +53,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ my_gethostbyname.c rijndael.c my_aes.c sha1.c \ my_handler.c my_netware.c my_largepage.c \ my_memmem.c \ - my_windac.c my_access.c base64.c + my_windac.c my_access.c base64.c my_libwrap.c EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \ thr_mutex.c thr_rwlock.c \ CMakeLists.txt mf_soundex.c \ diff --git a/mysys/my_libwrap.c b/mysys/my_libwrap.c new file mode 100644 index 00000000000..be8adbab0a1 --- /dev/null +++ b/mysys/my_libwrap.c @@ -0,0 +1,42 @@ +/* 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 */ + +/* + This is needed to be able to compile with original libwrap header + files that don't have the prototypes +*/ + +#include +#include + +#ifdef HAVE_LIBWRAP + +void my_fromhost(struct request_info *req) +{ + fromhost(req); +} + +int my_hosts_access(struct request_info *req) +{ + hosts_access(req); +} + +char *my_eval_client(struct request_info *req) +{ + eval_client(req); +} + +#endif /* HAVE_LIBWRAP */ diff --git a/sql/field.cc b/sql/field.cc index 8afd8b20eba..1002725ef53 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4640,7 +4640,7 @@ int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs) } #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { int4store(ptr,tmp); } @@ -4707,7 +4707,7 @@ int Field_timestamp::store(longlong nr, bool unsigned_val) nr, MYSQL_TIMESTAMP_DATETIME, 1); #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { int4store(ptr,timestamp); } @@ -4733,7 +4733,7 @@ longlong Field_timestamp::val_int(void) THD *thd= table ? table->in_use : current_thd; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) temp=uint4korr(ptr); else #endif @@ -4764,7 +4764,7 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr) val_buffer->length(field_length); #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) temp=uint4korr(ptr); else #endif @@ -4829,7 +4829,7 @@ bool Field_timestamp::get_date(TIME *ltime, uint fuzzydate) long temp; THD *thd= table ? table->in_use : current_thd; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) temp=uint4korr(ptr); else #endif @@ -4866,7 +4866,7 @@ int Field_timestamp::cmp(const char *a_ptr, const char *b_ptr) { int32 a,b; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { a=sint4korr(a_ptr); b=sint4korr(b_ptr); @@ -4884,7 +4884,7 @@ int Field_timestamp::cmp(const char *a_ptr, const char *b_ptr) void Field_timestamp::sort_string(char *to,uint length __attribute__((unused))) { #ifdef WORDS_BIGENDIAN - if (!table->s->db_low_byte_first) + if (!table || !table->s->db_low_byte_first) { to[0] = ptr[0]; to[1] = ptr[1]; @@ -4914,7 +4914,7 @@ void Field_timestamp::set_time() long tmp= (long) thd->query_start(); set_notnull(); #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { int4store(ptr,tmp); } @@ -5326,7 +5326,7 @@ int Field_date::store(const char *from, uint len,CHARSET_INFO *cs) from, len, MYSQL_TIMESTAMP_DATE, 1); #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { int4store(ptr,tmp); } @@ -5388,7 +5388,7 @@ int Field_date::store(longlong nr, bool unsigned_val) MYSQL_TIMESTAMP_DATETIME, 1); #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { int4store(ptr, nr); } @@ -5415,7 +5415,7 @@ double Field_date::val_real(void) ASSERT_COLUMN_MARKED_FOR_READ; int32 j; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) j=sint4korr(ptr); else #endif @@ -5429,7 +5429,7 @@ longlong Field_date::val_int(void) ASSERT_COLUMN_MARKED_FOR_READ; int32 j; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) j=sint4korr(ptr); else #endif @@ -5446,7 +5446,7 @@ String *Field_date::val_str(String *val_buffer, val_buffer->alloc(field_length); int32 tmp; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) tmp=sint4korr(ptr); else #endif @@ -5464,7 +5464,7 @@ int Field_date::cmp(const char *a_ptr, const char *b_ptr) { int32 a,b; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { a=sint4korr(a_ptr); b=sint4korr(b_ptr); @@ -5482,7 +5482,7 @@ int Field_date::cmp(const char *a_ptr, const char *b_ptr) void Field_date::sort_string(char *to,uint length __attribute__((unused))) { #ifdef WORDS_BIGENDIAN - if (!table->s->db_low_byte_first) + if (!table || !table->s->db_low_byte_first) { to[0] = ptr[0]; to[1] = ptr[1]; @@ -5729,7 +5729,7 @@ int Field_datetime::store(const char *from,uint len,CHARSET_INFO *cs) from, len, MYSQL_TIMESTAMP_DATETIME, 1); #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { int8store(ptr,tmp); } @@ -5783,7 +5783,7 @@ int Field_datetime::store(longlong nr, bool unsigned_val) MYSQL_TIMESTAMP_DATETIME, 1); #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { int8store(ptr,nr); } @@ -5813,7 +5813,7 @@ int Field_datetime::store_time(TIME *ltime,timestamp_type type) set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); } #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { int8store(ptr,tmp); } @@ -5841,7 +5841,7 @@ longlong Field_datetime::val_int(void) ASSERT_COLUMN_MARKED_FOR_READ; longlong j; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) j=sint8korr(ptr); else #endif @@ -5862,7 +5862,7 @@ String *Field_datetime::val_str(String *val_buffer, int part3; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) tmp=sint8korr(ptr); else #endif @@ -5927,7 +5927,7 @@ int Field_datetime::cmp(const char *a_ptr, const char *b_ptr) { longlong a,b; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) { a=sint8korr(a_ptr); b=sint8korr(b_ptr); @@ -5945,7 +5945,7 @@ int Field_datetime::cmp(const char *a_ptr, const char *b_ptr) void Field_datetime::sort_string(char *to,uint length __attribute__((unused))) { #ifdef WORDS_BIGENDIAN - if (!table->s->db_low_byte_first) + if (!table || !table->s->db_low_byte_first) { to[0] = ptr[0]; to[1] = ptr[1]; diff --git a/sql/field.h b/sql/field.h index 69cb641f158..b19d0ebe139 100644 --- a/sql/field.h +++ b/sql/field.h @@ -822,7 +822,7 @@ public: if ((*null_value= is_null())) return 0; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) + if (table && table->s->db_low_byte_first) return sint4korr(ptr); #endif long tmp; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 763b79cb48f..ce537614386 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -138,7 +138,8 @@ static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) } continue; } - if ((res= items[i]->real_item()->type()) == Item::FIELD_ITEM) + if ((res= items[i]->real_item()->type()) == Item::FIELD_ITEM && + items[i]->result_type() != INT_RESULT) { field= ((Item_field *)items[i]->real_item())->field; break; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 95411db4119..6063eb170b2 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -116,16 +116,7 @@ extern "C" { // Because of SCO 3.2V4.2 #include #endif /* __WIN__ */ -#ifdef HAVE_LIBWRAP -#include -#include -#ifdef NEED_SYS_SYSLOG_H -#include -#endif /* NEED_SYS_SYSLOG_H */ -int allow_severity = LOG_INFO; -int deny_severity = LOG_WARNING; - -#endif /* HAVE_LIBWRAP */ +#include #ifdef HAVE_SYS_MMAN_H #include @@ -687,6 +678,8 @@ static const char* default_dbug_option; #endif #ifdef HAVE_LIBWRAP const char *libwrapName= NULL; +int allow_severity = LOG_INFO; +int deny_severity = LOG_WARNING; #endif #ifdef HAVE_QUERY_CACHE static ulong query_cache_limit= 0; @@ -4239,8 +4232,8 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) struct request_info req; signal(SIGCHLD, SIG_DFL); request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE, new_sock, NULL); - fromhost(&req); - if (!hosts_access(&req)) + my_fromhost(&req); + if (!my_hosts_access(&req)) { /* This may be stupid but refuse() includes an exit(0) @@ -4248,7 +4241,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) clean_exit() - same stupid thing ... */ syslog(deny_severity, "refused connect from %s", - eval_client(&req)); + my_eval_client(&req)); /* C++ sucks (the gibberish in front just translates the supplied diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index e87a478b8d6..93ec48d69f2 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -744,6 +744,12 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref, { KEY_PART_INFO *part,*part_end; key_part_map key_part_to_use= 0; + /* + Perform a check if index is not disabled by ALTER TABLE + or IGNORE INDEX. + */ + if (!table->keys_in_use_for_query.is_set(idx)) + continue; uint jdx= 0; *prefix_len= 0; for (part= keyinfo->key_part, part_end= part+keyinfo->key_parts ; diff --git a/sql/slave.cc b/sql/slave.cc index f143faf427c..d9895323b92 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1419,6 +1419,15 @@ int fetch_master_table(THD *thd, const char *db_name, const char *table_name, if (connect_to_master(thd, mysql, mi)) { my_error(ER_CONNECT_TO_MASTER, MYF(0), mysql_error(mysql)); + /* + We need to clear the active VIO since, theoretically, somebody + might issue an awake() on this thread. If we are then in the + middle of closing and destroying the VIO inside the + mysql_close(), we will have a problem. + */ +#ifdef SIGNAL_WITH_VIO_CLOSE + thd->clear_active_vio(); +#endif mysql_close(mysql); DBUG_RETURN(1); } @@ -3507,6 +3516,17 @@ err: VOID(pthread_mutex_unlock(&LOCK_thread_count)); if (mysql) { + /* + Here we need to clear the active VIO before closing the + connection with the master. The reason is that THD::awake() + might be called from terminate_slave_thread() because somebody + issued a STOP SLAVE. If that happends, the close_active_vio() + can be called in the middle of closing the VIO associated with + the 'mysql' object, causing a crash. + */ +#ifdef SIGNAL_WITH_VIO_CLOSE + thd->clear_active_vio(); +#endif mysql_close(mysql); mi->mysql=0; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a765be0650f..193a29a1fe9 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1071,8 +1071,9 @@ JOIN::optimize() group_list ? 0 : select_distinct, group_list && simple_group, select_options, - (order == 0 || skip_sort_order) ? select_limit : - HA_POS_ERROR, + (order == 0 || skip_sort_order || + test(select_options & OPTION_BUFFER_RESULT)) ? + select_limit : HA_POS_ERROR, (char *) ""))) DBUG_RETURN(1); @@ -8894,6 +8895,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, keyinfo->key_length+= key_part_info->length; } } + else + { + set_if_smaller(table->s->max_rows, rows_limit); + param->end_write_records= rows_limit; + } if (distinct && field_count != param->hidden_field_count) {