From 71ec20ec1f92fe70e9e027fc847c36a071bab7f1 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sat, 15 Jan 2005 01:06:15 +0200 Subject: [PATCH 01/12] dict0load.c, dict0crea.c: Add diagnostic code to track corruption in mix_len; it was reported on the mailing list Jan 14, 2005 --- innobase/dict/dict0crea.c | 11 +++++++++++ innobase/dict/dict0load.c | 17 +++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c index cbdc0aab53c..d9e89316613 100644 --- a/innobase/dict/dict0crea.c +++ b/innobase/dict/dict0crea.c @@ -81,6 +81,17 @@ dict_create_sys_tables_tuple( dfield_set_data(dfield, ptr, 8); /* 7: MIX_LEN --------------------------*/ + + /* Track corruption reported on mailing list Jan 14, 2005 */ + if (table->mix_len != 0 && table->mix_len != 0x80000000) { + fprintf(stderr, +"InnoDB: Error: mix_len is %lu in table %s\n", (ulong)table->mix_len, + table->name); + mem_analyze_corruption((byte*)&(table->mix_len)); + + ut_error; + } + dfield = dtuple_get_nth_field(entry, 5); ptr = mem_heap_alloc(heap, 4); diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c index 61facc8818d..e52c81c82e8 100644 --- a/innobase/dict/dict0load.c +++ b/innobase/dict/dict0load.c @@ -729,6 +729,7 @@ dict_load_table( ulint space; ulint n_cols; ulint err; + ulint mix_len; mtr_t mtr; #ifdef UNIV_SYNC_DEBUG @@ -775,6 +776,22 @@ dict_load_table( return(NULL); } + /* Track a corruption bug reported on the MySQL mailing list Jan 14, + 2005: mix_id had a value different from 0 */ + + field = rec_get_nth_field(rec, 7, &len); + ut_a(len == 4); + + mix_len = mach_read_from_4(field); + + if (mix_len != 0 && mix_len != 0x80000000) { + ut_print_timestamp(stderr); + + fprintf(stderr, + " InnoDB: table %s has a nonsensical mix len %lu\n", + name, (ulong)mix_len); + } + #if MYSQL_VERSION_ID < 50300 /* Starting from MySQL 5.0.3, the high-order bit of MIX_LEN is the "compact format" flag. */ From f1dc2017c1f1cdb46edf818083d3e717f42ff11c Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sat, 15 Jan 2005 01:10:40 +0200 Subject: [PATCH 02/12] dict0load.c: Correct typo in comment --- innobase/dict/dict0load.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c index e52c81c82e8..717c64c3963 100644 --- a/innobase/dict/dict0load.c +++ b/innobase/dict/dict0load.c @@ -777,7 +777,7 @@ dict_load_table( } /* Track a corruption bug reported on the MySQL mailing list Jan 14, - 2005: mix_id had a value different from 0 */ + 2005: mix_len had a value different from 0 */ field = rec_get_nth_field(rec, 7, &len); ut_a(len == 4); From 7fb0de20f3c60187331df1166a967183dc3b7bdd Mon Sep 17 00:00:00 2001 From: "timour@mysql.com" <> Date: Wed, 19 Jan 2005 12:55:54 +0200 Subject: [PATCH 03/12] Final patch for BUG#4285. This patch collects all previous patches into one. The main problem was due to that there is are two variables - dflt_key_cache and sql_key_cache with have more or less duplicate function. The reson for the bug was that the default value in the key cache hash was set to dflt_key_cache, then sql_key_cache was set to a new key cache object, and then dflt_key_cache was set to sql_key_cache which was different from the dflt_key_cache_var. After sending SIGHUP, the server was using the original default value for the key cache hash, which was different from the actual key cache object used for the default key cache. --- include/keycache.h | 5 ++++- mysys/mf_keycache.c | 35 +++++++++++++++++++++++++++++++++++ sql/mysql_priv.h | 1 - sql/mysqld.cc | 13 +++++-------- sql/set_var.cc | 4 ++-- sql/sql_parse.cc | 14 +++----------- sql/sql_show.cc | 2 +- 7 files changed, 50 insertions(+), 24 deletions(-) diff --git a/include/keycache.h b/include/keycache.h index 26ee0ccadb1..a292a69b0a3 100644 --- a/include/keycache.h +++ b/include/keycache.h @@ -88,12 +88,13 @@ typedef struct st_key_cache ulong param_division_limit; /* min. percentage of warm blocks */ ulong param_age_threshold; /* determines when hot block is downgraded */ - /* Statistics variables */ + /* Statistics variables. These are reset in reset_key_cache_counters(). */ ulong global_blocks_changed; /* number of currently dirty blocks */ ulong global_cache_w_requests;/* number of write requests (write hits) */ ulong global_cache_write; /* number of writes from the cache to files */ ulong global_cache_r_requests;/* number of read requests (read hits) */ ulong global_cache_read; /* number of reads from files to the cache */ + int blocks; /* max number of blocks in the cache */ my_bool in_init; /* Set to 1 in MySQL during init/resize */ } KEY_CACHE; @@ -132,5 +133,7 @@ extern my_bool multi_key_cache_set(const byte *key, uint length, KEY_CACHE *key_cache); extern void multi_key_cache_change(KEY_CACHE *old_data, KEY_CACHE *new_data); +extern int reset_key_cache_counters(const char *name, + KEY_CACHE *key_cache); C_MODE_END #endif /* _keycache_h */ diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 052d6c79ab9..a1227989a4b 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -2444,6 +2444,41 @@ static int flush_all_key_blocks(KEY_CACHE *keycache) } +/* + Reset the counters of a key cache. + + SYNOPSIS + reset_key_cache_counters() + name the name of a key cache + key_cache pointer to the key kache to be reset + + DESCRIPTION + This procedure is used by process_key_caches() to reset the counters of all + currently used key caches, both the default one and the named ones. + + RETURN + 0 on success (always because it can't fail) +*/ + +int reset_key_cache_counters(const char *name, KEY_CACHE *key_cache) +{ + DBUG_ENTER("reset_key_cache_counters"); + if (!key_cache->key_cache_inited) + { + DBUG_PRINT("info", ("Key cache %s not initialized.", name)); + DBUG_RETURN(0); + } + DBUG_PRINT("info", ("Resetting counters for key cache %s.", name)); + + key_cache->global_blocks_changed= 0; /* Key_blocks_not_flushed */ + key_cache->global_cache_r_requests= 0; /* Key_read_requests */ + key_cache->global_cache_read= 0; /* Key_reads */ + key_cache->global_cache_w_requests= 0; /* Key_write_requests */ + key_cache->global_cache_write= 0; /* Key_writes */ + DBUG_RETURN(0); +} + + #ifndef DBUG_OFF /* Test if disk-cache is ok diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 4b785aafc5f..4f4aea66dd7 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -938,7 +938,6 @@ extern SHOW_COMP_OPTION have_ndbcluster; extern struct system_variables global_system_variables; extern struct system_variables max_system_variables; extern struct rand_struct sql_rand; -extern KEY_CACHE *sql_key_cache; extern const char *opt_date_time_formats[]; extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[]; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d1fef3519bf..21b1cb7ffd0 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -383,7 +383,6 @@ struct system_variables max_system_variables; MY_TMPDIR mysql_tmpdir_list; MY_BITMAP temp_pool; -KEY_CACHE *sql_key_cache; CHARSET_INFO *system_charset_info, *files_charset_info ; CHARSET_INFO *national_charset_info, *table_alias_charset; @@ -1846,14 +1845,14 @@ We will try our best to scrape up some info that will hopefully help diagnose\n\ the problem, but since we have already crashed, something is definitely wrong\n\ and this may fail.\n\n"); fprintf(stderr, "key_buffer_size=%lu\n", - (ulong) sql_key_cache->key_cache_mem_size); + (ulong) dflt_key_cache->key_cache_mem_size); fprintf(stderr, "read_buffer_size=%ld\n", global_system_variables.read_buff_size); fprintf(stderr, "max_used_connections=%ld\n", max_used_connections); fprintf(stderr, "max_connections=%ld\n", max_connections); fprintf(stderr, "threads_connected=%d\n", thread_count); fprintf(stderr, "It is possible that mysqld could use up to \n\ key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %ld K\n\ -bytes of memory\n", ((ulong) sql_key_cache->key_cache_mem_size + +bytes of memory\n", ((ulong) dflt_key_cache->key_cache_mem_size + (global_system_variables.read_buff_size + global_system_variables.sortbuff_size) * max_connections)/ 1024); @@ -2120,12 +2119,12 @@ extern "C" void *signal_hand(void *arg __attribute__((unused))) case SIGHUP: if (!abort_loop) { + mysql_print_status((THD*) 0); // Print some debug info reload_acl_and_cache((THD*) 0, (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST | REFRESH_STATUS | REFRESH_GRANT | REFRESH_THREADS | REFRESH_HOSTS), (TABLE_LIST*) 0, NULL); // Flush logs - mysql_print_status((THD*) 0); // Send debug some info } break; #ifdef USE_ONE_SIGNAL_HAND @@ -2699,8 +2698,6 @@ server."); /* call ha_init_key_cache() on all key caches to init them */ process_key_caches(&ha_init_key_cache); - /* We must set dflt_key_cache in case we are using ISAM tables */ - dflt_key_cache= sql_key_cache; #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && !defined(EMBEDDED_LIBRARY) if (locked_in_memory && !getuid()) @@ -5598,10 +5595,10 @@ static void mysql_init_variables(void) threads.empty(); thread_cache.empty(); key_caches.empty(); - multi_keycache_init(); - if (!(sql_key_cache= get_or_create_key_cache(default_key_cache_base.str, + if (!(dflt_key_cache= get_or_create_key_cache(default_key_cache_base.str, default_key_cache_base.length))) exit(1); + multi_keycache_init(); /* set key_cache_hash.default_value = dflt_key_cache */ /* Initialize structures that is used when processing options */ replicate_rewrite_db.empty(); diff --git a/sql/set_var.cc b/sql/set_var.cc index e44ac742abe..1237c31075c 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2174,7 +2174,7 @@ bool sys_var_key_buffer_size::update(THD *thd, set_var *var) if (!tmp) // Zero size means delete { - if (key_cache == sql_key_cache) + if (key_cache == dflt_key_cache) goto end; // Ignore default key cache if (key_cache->key_cache_inited) // If initied @@ -2188,7 +2188,7 @@ bool sys_var_key_buffer_size::update(THD *thd, set_var *var) base_name->length, &list); key_cache->in_init= 1; pthread_mutex_unlock(&LOCK_global_system_variables); - error= reassign_keycache_tables(thd, key_cache, sql_key_cache); + error= reassign_keycache_tables(thd, key_cache, dflt_key_cache); pthread_mutex_lock(&LOCK_global_system_variables); key_cache->in_init= 0; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c81aefc9cea..9eb4019b5d7 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4946,6 +4946,7 @@ void kill_one_thread(THD *thd, ulong id) net_printf(thd,error,id); } + /* Clear most status variables */ static void refresh_status(void) @@ -4955,18 +4956,9 @@ static void refresh_status(void) { if (ptr->type == SHOW_LONG) *(ulong*) ptr->value= 0; - else if (ptr->type == SHOW_KEY_CACHE_LONG) - { - /* - Reset value in 'default' key cache. - This needs to be recoded when we have thread specific key values - */ - char *value= (((char*) sql_key_cache) + - (uint) ((char*) (ptr->value) - - (char*) &dflt_key_cache_var)); - *(ulong*) value= 0; - } } + /* Reset the counters of all key caches (default and named). */ + process_key_caches(reset_key_cache_counters); pthread_mutex_unlock(&LOCK_status); } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 8929872c466..d9acd47c5a6 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2066,7 +2066,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, #endif /* HAVE_OPENSSL */ case SHOW_KEY_CACHE_LONG: case SHOW_KEY_CACHE_CONST_LONG: - value= (value-(char*) &dflt_key_cache_var)+ (char*) sql_key_cache; + value= (value-(char*) &dflt_key_cache_var)+ (char*) dflt_key_cache; end= int10_to_str(*(long*) value, buff, 10); break; case SHOW_UNDEF: // Show never happen From 2f6e0864ad0039cad473e028cade2095d45fe699 Mon Sep 17 00:00:00 2001 From: "bar@mysql.com" <> Date: Fri, 21 Jan 2005 16:49:20 +0400 Subject: [PATCH 04/12] Bug#7943: Wrong prefix lengths reported on UTF-8 columns SHOW KEYS FROM t1 now displays number of characters in Sub_part, not number of bytes, to be compatible with SHOW CREATE TABLE. --- mysql-test/r/ctype_mb.result | 4 ++-- sql/sql_show.cc | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/ctype_mb.result b/mysql-test/r/ctype_mb.result index 5e273b3c800..dbdb9c1343c 100644 --- a/mysql-test/r/ctype_mb.result +++ b/mysql-test/r/ctype_mb.result @@ -33,7 +33,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 SHOW KEYS FROM t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment -t1 1 key_a 1 a A NULL 9 NULL YES BTREE +t1 1 key_a 1 a A NULL 3 NULL YES BTREE ALTER TABLE t1 CHANGE a a CHAR(4); SHOW CREATE TABLE t1; Table Create Table @@ -53,5 +53,5 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 SHOW KEYS FROM t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment -t1 1 key_a 1 a A NULL 9 NULL YES BTREE +t1 1 key_a 1 a A NULL 3 NULL YES BTREE DROP TABLE t1; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 8929872c466..91cac29f3a3 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1025,7 +1025,8 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list) /* Check if we have a key part that only uses part of the field */ if (!(key_info->flags & HA_FULLTEXT) && (!key_part->field || key_part->length != table->field[key_part->fieldnr-1]->key_length())) - protocol->store_tiny((longlong) key_part->length); + protocol->store_tiny((longlong) key_part->length / + key_part->field->charset()->mbmaxlen); else protocol->store_null(); protocol->store_null(); // No pack_information yet From 9a03676b697752c482c6229e1dd576f670c2d8a8 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Fri, 21 Jan 2005 17:54:50 +0200 Subject: [PATCH 05/12] dict0dict.c: Fix bug #7831: ALTER TABLE ... ADD CONSTRAINT PRIMARY KEY ... complained about bad foreign key definition --- innobase/dict/dict0dict.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index 2e6504cac11..186f3be2f31 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -2895,9 +2895,9 @@ loop: constraint_name = NULL; if (ptr1 < ptr2) { - /* The user has specified a constraint name. Pick it so + /* The user may have specified a constraint name. Pick it so that we can store 'databasename/constraintname' as the id of - the id of the constraint to system tables. */ + of the constraint to system tables. */ ptr = ptr1; ptr = dict_accept(ptr, "CONSTRAINT", &success); @@ -2934,6 +2934,10 @@ loop: ptr = dict_accept(ptr, "FOREIGN", &success); + if (!success) { + goto loop; + } + if (!isspace(*ptr)) { goto loop; } From d6706798d2839b303fddde69c206adacb43ab1f2 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Fri, 21 Jan 2005 17:59:23 +0200 Subject: [PATCH 06/12] fil0fil.c: Fix bug #8021 :Windows error number 87 with multiple tablespaces after mysqld restart; still has to be tested on Windows that this now works --- innobase/fil/fil0fil.c | 78 ++++++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 25 deletions(-) diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c index d1a083fcd66..ea34b6ffd93 100644 --- a/innobase/fil/fil0fil.c +++ b/innobase/fil/fil0fil.c @@ -477,28 +477,33 @@ fil_node_open_file( ut_a(node->n_pending == 0); ut_a(node->open == FALSE); - /* printf("Opening file %s\n", node->name); */ - - if (space->purpose == FIL_LOG) { - node->handle = os_file_create(node->name, OS_FILE_OPEN, - OS_FILE_AIO, OS_LOG_FILE, &ret); - } else if (node->is_raw_disk) { - node->handle = os_file_create(node->name, - OS_FILE_OPEN_RAW, - OS_FILE_AIO, OS_DATA_FILE, &ret); - } else { - node->handle = os_file_create(node->name, OS_FILE_OPEN, - OS_FILE_AIO, OS_DATA_FILE, &ret); - } - - ut_a(ret); - - node->open = TRUE; - - system->n_open++; - if (node->size == 0) { + /* It must be a single-table tablespace and we do not know the + size of the file yet. First we open the file in the normal + mode, no async I/O here, for simplicity. Then do some checks, + and close the file again. + NOTE that we could not use the simple file read function + os_file_read() in Windows to read from a file opened for + async I/O! */ + + node->handle = os_file_create_simple_no_error_handling( + node->name, OS_FILE_OPEN, + OS_FILE_READ_ONLY, &success); + if (!success) { + /* The following call prints an error message */ + os_file_get_last_error(TRUE); + + ut_print_timestamp(stderr); + + fprintf(stderr, +" InnoDB: Fatal error: cannot open %s\n." +"InnoDB: Have you deleted .ibd files under a running mysqld server?\n", + node->name); + ut_a(0); + } + ut_a(space->purpose != FIL_LOG); + ut_a(space->id != 0); os_file_get_size(node->handle, &size_low, &size_high); @@ -508,11 +513,6 @@ fil_node_open_file( node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE); #else - /* It must be a single-table tablespace and we do not know the - size of the file yet */ - - ut_a(space->id != 0); - if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) { fprintf(stderr, "InnoDB: Error: the size of single-table tablespace file %s\n" @@ -536,6 +536,10 @@ fil_node_open_file( ut_free(buf2); + /* Close the file now that we have read the space id from it */ + + os_file_close(node->handle); + if (space_id == ULINT_UNDEFINED || space_id == 0) { fprintf(stderr, "InnoDB: Error: tablespace id %lu in file %s is not sensible\n", @@ -563,6 +567,30 @@ fil_node_open_file( space->size += node->size; } + /* printf("Opening file %s\n", node->name); */ + + /* Open the file for reading and writing, in Windows normally in the + unbuffered async I/O mode, though global variables may make + os_file_create() to fall back to the normal file I/O mode. */ + + if (space->purpose == FIL_LOG) { + node->handle = os_file_create(node->name, OS_FILE_OPEN, + OS_FILE_AIO, OS_LOG_FILE, &ret); + } else if (node->is_raw_disk) { + node->handle = os_file_create(node->name, + OS_FILE_OPEN_RAW, + OS_FILE_AIO, OS_DATA_FILE, &ret); + } else { + node->handle = os_file_create(node->name, OS_FILE_OPEN, + OS_FILE_AIO, OS_DATA_FILE, &ret); + } + + ut_a(ret); + + node->open = TRUE; + + system->n_open++; + if (space->purpose == FIL_TABLESPACE && space->id != 0) { /* Put the node to the LRU list */ UT_LIST_ADD_FIRST(LRU, system->LRU, node); From e291e98d2d55ad5123190a1ab08e1b80650f6024 Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.ndb.mysql.com" <> Date: Fri, 21 Jan 2005 17:57:44 +0100 Subject: [PATCH 07/12] Bug#8070 corrected possible unalignment in NdbRecAttr access methods --- ndb/include/ndbapi/NdbRecAttr.hpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/ndb/include/ndbapi/NdbRecAttr.hpp b/ndb/include/ndbapi/NdbRecAttr.hpp index da03df13027..29eab64a84f 100644 --- a/ndb/include/ndbapi/NdbRecAttr.hpp +++ b/ndb/include/ndbapi/NdbRecAttr.hpp @@ -304,7 +304,9 @@ inline Int64 NdbRecAttr::int64_value() const { - return *(Int64*)theRef; + Int64 val; + memcpy(&val,theRef,8); + return val; } inline @@ -332,7 +334,9 @@ inline Uint64 NdbRecAttr::u_64_value() const { - return *(Uint64*)theRef; + Uint64 val; + memcpy(&val,theRef,8); + return val; } inline @@ -360,14 +364,18 @@ inline float NdbRecAttr::float_value() const { - return *(float*)theRef; + float val; + memcpy(&val,theRef,sizeof(val)); + return val; } inline double NdbRecAttr::double_value() const { - return *(double*)theRef; + double val; + memcpy(&val,theRef,sizeof(val)); + return val; } inline From e30b5f86e513de6e464a3ca489f8733e2c2ff881 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sat, 22 Jan 2005 04:45:22 +0200 Subject: [PATCH 08/12] fil0fil.c: Fix a race condition that could cause the assertion space->n_pending_flushes == 0 to fail in fil0fil.c, in fil_space_free(), in DROP TABLE or in ALTER TABLE --- innobase/fil/fil0fil.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c index ea34b6ffd93..5f71c00aea6 100644 --- a/innobase/fil/fil0fil.c +++ b/innobase/fil/fil0fil.c @@ -4139,7 +4139,8 @@ fil_flush_file_spaces( space = UT_LIST_GET_FIRST(system->space_list); while (space) { - if (space->purpose == purpose) { + if (space->purpose == purpose && !space->is_being_deleted) { + space->n_pending_flushes++; /* prevent dropping of the space while we are flushing */ From 8527f256c0688a4ecbd79b60534184a92b5d755f Mon Sep 17 00:00:00 2001 From: "igor@rurik.mysql.com" <> Date: Sat, 22 Jan 2005 02:40:27 -0800 Subject: [PATCH 09/12] select_found.result, select_found.test: Added a test case for bug #7945. sql_select.cc: Fixed bug #7945. If DISTINCT is used only with constants in a query with GROUP BY, we can apply an optimization that set LIMIT to 1 only in the case when there is no SQL_CALC_FOUND_ROWS. --- mysql-test/r/select_found.result | 8 ++++++++ mysql-test/t/select_found.test | 9 +++++++++ sql/sql_select.cc | 13 ++++++++++--- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/select_found.result b/mysql-test/r/select_found.result index 444124bcd67..11629addba4 100644 --- a/mysql-test/r/select_found.result +++ b/mysql-test/r/select_found.result @@ -223,3 +223,11 @@ SELECT FOUND_ROWS(); FOUND_ROWS() 0 DROP TABLE t1; +CREATE TABLE t1 (a int, b int); +INSERT INTO t1 VALUES (1,2), (1,3), (1,4), (1,5); +SELECT SQL_CALC_FOUND_ROWS DISTINCT 'a' FROM t1 GROUP BY b LIMIT 2; +a +a +SELECT FOUND_ROWS(); +FOUND_ROWS() +1 diff --git a/mysql-test/t/select_found.test b/mysql-test/t/select_found.test index 7599277a867..997cadc2992 100644 --- a/mysql-test/t/select_found.test +++ b/mysql-test/t/select_found.test @@ -146,3 +146,12 @@ INSERT INTO t1 VALUES (0), (0), (1), (2); SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a = 0 GROUP BY a HAVING a > 10; SELECT FOUND_ROWS(); DROP TABLE t1; + +# +# Bug #7945: group by + distinct with constant expression + limit +# + +CREATE TABLE t1 (a int, b int); +INSERT INTO t1 VALUES (1,2), (1,3), (1,4), (1,5); +SELECT SQL_CALC_FOUND_ROWS DISTINCT 'a' FROM t1 GROUP BY b LIMIT 2; +SELECT FOUND_ROWS(); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index eda4ce73186..468cdf05d36 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2114,9 +2114,15 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, x = used key parts (1 <= x <= c) */ double rec_per_key; +#if 0 if (!(rec_per_key=(double) keyinfo->rec_per_key[keyinfo->key_parts-1])) rec_per_key=(double) s->records/rec+1; +#else + rec_per_key= keyinfo->rec_per_key[keyinfo->key_parts-1] ? + (double) keyinfo->rec_per_key[keyinfo->key_parts-1] : + (double) s->records/rec+1; +#endif if (!s->records) tmp=0; @@ -6276,13 +6282,14 @@ remove_duplicates(JOIN *join, TABLE *entry,List &fields, Item *having) field_count++; } - if (!field_count) - { // only const items + if (!field_count && !(join->select_options & OPTION_FOUND_ROWS)) + { // only const items with no OPTION_FOUND_ROWS join->thd->select_limit=1; // Only send first row DBUG_RETURN(0); } Field **first_field=entry->field+entry->fields - field_count; - offset=entry->field[entry->fields - field_count]->offset(); + offset= field_count ? + entry->field[entry->fields - field_count]->offset() : 0; reclength=entry->reclength-offset; free_io_cache(entry); // Safety From e38381f24126f86aa77ee3523923dd9635737f7c Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.ndb.mysql.com" <> Date: Sun, 23 Jan 2005 12:12:50 +0100 Subject: [PATCH 10/12] backported from 5.0 extra option to ndb_waiter --- ndb/tools/waiter.cpp | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/ndb/tools/waiter.cpp b/ndb/tools/waiter.cpp index 4b86de36514..dfdb11524e3 100644 --- a/ndb/tools/waiter.cpp +++ b/ndb/tools/waiter.cpp @@ -31,11 +31,13 @@ waitClusterStatus(const char* _addr, ndb_mgm_node_status _status, unsigned int _timeout); enum ndb_waiter_options { - NDB_STD_OPTS_OPTIONS + NDB_STD_OPTS_OPTIONS, + OPT_WAIT_STATUS_NOT_STARTED }; NDB_STD_OPTS_VARS; static int _no_contact = 0; +static int _not_started = 0; static int _timeout = 120; static struct my_option my_long_options[] = { @@ -43,6 +45,9 @@ static struct my_option my_long_options[] = { "no-contact", 'n', "Wait for cluster no contact", (gptr*) &_no_contact, (gptr*) &_no_contact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "not-started", OPT_WAIT_STATUS_NOT_STARTED, "Wait for cluster not started", + (gptr*) &_not_started, (gptr*) &_not_started, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, { "timeout", 't', "Timeout to wait", (gptr*) &_timeout, (gptr*) &_timeout, 0, GET_INT, REQUIRED_ARG, 120, 0, 0, 0, 0, 0 }, @@ -91,12 +96,22 @@ int main(int argc, char** argv){ if (_hostName == 0) _hostName= opt_connect_str; - if (_no_contact) { - if (waitClusterStatus(_hostName, NDB_MGM_NODE_STATUS_NO_CONTACT, _timeout) != 0) - return NDBT_ProgramExit(NDBT_FAILED); - } else if (waitClusterStatus(_hostName, NDB_MGM_NODE_STATUS_STARTED, _timeout) != 0) - return NDBT_ProgramExit(NDBT_FAILED); + enum ndb_mgm_node_status wait_status; + if (_no_contact) + { + wait_status= NDB_MGM_NODE_STATUS_NO_CONTACT; + } + else if (_not_started) + { + wait_status= NDB_MGM_NODE_STATUS_NOT_STARTED; + } + else + { + wait_status= NDB_MGM_NODE_STATUS_STARTED; + } + if (waitClusterStatus(_hostName, wait_status, _timeout) != 0) + return NDBT_ProgramExit(NDBT_FAILED); return NDBT_ProgramExit(NDBT_OK); } From 241a18585b3b4189bfc6c83be61b076b50ca8fb1 Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.ndb.mysql.com" <> Date: Mon, 24 Jan 2005 10:33:39 +0100 Subject: [PATCH 11/12] remmoved inline in NdbRecAttr methods including memcpy --- ndb/include/ndbapi/NdbRecAttr.hpp | 36 ------------------------------- ndb/src/ndbapi/NdbRecAttr.cpp | 32 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 36 deletions(-) diff --git a/ndb/include/ndbapi/NdbRecAttr.hpp b/ndb/include/ndbapi/NdbRecAttr.hpp index 29eab64a84f..05635a99385 100644 --- a/ndb/include/ndbapi/NdbRecAttr.hpp +++ b/ndb/include/ndbapi/NdbRecAttr.hpp @@ -300,15 +300,6 @@ NdbRecAttr::arraySize() const return theArraySize; } -inline -Int64 -NdbRecAttr::int64_value() const -{ - Int64 val; - memcpy(&val,theRef,8); - return val; -} - inline Int32 NdbRecAttr::int32_value() const @@ -330,15 +321,6 @@ NdbRecAttr::char_value() const return *(char*)theRef; } -inline -Uint64 -NdbRecAttr::u_64_value() const -{ - Uint64 val; - memcpy(&val,theRef,8); - return val; -} - inline Uint32 NdbRecAttr::u_32_value() const @@ -360,24 +342,6 @@ NdbRecAttr::u_char_value() const return *(Uint8*)theRef; } -inline -float -NdbRecAttr::float_value() const -{ - float val; - memcpy(&val,theRef,sizeof(val)); - return val; -} - -inline -double -NdbRecAttr::double_value() const -{ - double val; - memcpy(&val,theRef,sizeof(val)); - return val; -} - inline void NdbRecAttr::release() diff --git a/ndb/src/ndbapi/NdbRecAttr.cpp b/ndb/src/ndbapi/NdbRecAttr.cpp index bcd91292fcd..f2427fb32e8 100644 --- a/ndb/src/ndbapi/NdbRecAttr.cpp +++ b/ndb/src/ndbapi/NdbRecAttr.cpp @@ -245,3 +245,35 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r) return out; } + +Int64 +NdbRecAttr::int64_value() const +{ + Int64 val; + memcpy(&val,theRef,8); + return val; +} + +Uint64 +NdbRecAttr::u_64_value() const +{ + Uint64 val; + memcpy(&val,theRef,8); + return val; +} + +float +NdbRecAttr::float_value() const +{ + float val; + memcpy(&val,theRef,sizeof(val)); + return val; +} + +double +NdbRecAttr::double_value() const +{ + double val; + memcpy(&val,theRef,sizeof(val)); + return val; +} From a551510cfd20c6be84d29575917fc39a27250e47 Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.ndb.mysql.com" <> Date: Mon, 24 Jan 2005 10:47:51 +0100 Subject: [PATCH 12/12] mysql-test-run.sh: backported access to ndb_mgm from 5.0 --- mysql-test/mysql-test-run.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 722da516d9b..5c4fe0577a2 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -537,6 +537,7 @@ if [ x$SOURCE_DIST = x1 ] ; then INSTALL_DB="./install_test_db" MYSQL_FIX_SYSTEM_TABLES="$BASEDIR/scripts/mysql_fix_privilege_tables" NDB_TOOLS_DIR="$BASEDIR/ndb/tools" + NDB_MGM="$BASEDIR/ndb/src/mgmclient/ndb_mgm" else if test -x "$BASEDIR/libexec/mysqld" then @@ -558,6 +559,7 @@ else INSTALL_DB="./install_test_db --bin" MYSQL_FIX_SYSTEM_TABLES="$CLIENT_BINDIR/mysql_fix_privilege_tables" NDB_TOOLS_DIR="$CLIENT_BINDIR" + NDB_MGM="$CLIENT_BINDIR/ndb_mgm" if test -d "$BASEDIR/share/mysql/english" then LANGUAGE="$BASEDIR/share/mysql/english/" @@ -607,6 +609,7 @@ MYSQL="$MYSQL --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --u export MYSQL MYSQL_DUMP MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES export CLIENT_BINDIR TESTS_BINDIR CHARSETSDIR export NDB_TOOLS_DIR +export NDB_MGM MYSQL_TEST_ARGS="--no-defaults --socket=$MASTER_MYSOCK --database=$DB \ --user=$DBUSER --password=$DBPASSWD --silent -v --skip-safemalloc \