From afac3c31278d491e8e1329129b38df4ab2e9371e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Sep 2004 22:06:30 -0700 Subject: [PATCH 1/6] select.result, select.test: Added a test case for bug #5333. null_key.result, key_primary.result: Made covering index usable for const tables. sql_select.cc: Made covering index usable for const tables: downported the corresponding code from 4.1. Simultaneously fixed bug #5333 reported for 4.1. The bug was due to the fact that field index in join structures was always set to 0 for const tables. sql/sql_select.cc: Made covering index usable for const tables: downported the corresponding code from 4.1. Simultaneously fixed bug #5333 reported for 4.1. The bug was due to the fact that field index in join structures was always set to 0 for const tables. mysql-test/t/select.test: Added a test case for bug #5333. mysql-test/r/key_primary.result: Made covering index usable for const tables. mysql-test/r/null_key.result: Made covering index usable for const tables. mysql-test/r/select.result: Added a test case for bug #5333. --- mysql-test/r/key_primary.result | 2 +- mysql-test/r/null_key.result | 2 +- mysql-test/r/select.result | 16 ++++++++++++++++ mysql-test/t/select.test | 21 +++++++++++++++++++++ sql/sql_select.cc | 11 ++++++++++- 5 files changed, 49 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/key_primary.result b/mysql-test/r/key_primary.result index 87289f1cf54..3216ead667b 100644 --- a/mysql-test/r/key_primary.result +++ b/mysql-test/r/key_primary.result @@ -13,7 +13,7 @@ t1 AB% describe select * from t1 where t1="ABC"; table type possible_keys key key_len ref rows Extra -t1 const PRIMARY PRIMARY 3 const 1 +t1 const PRIMARY PRIMARY 3 const 1 Using index describe select * from t1 where t1="ABCD"; Comment Impossible WHERE noticed after reading const tables diff --git a/mysql-test/r/null_key.result b/mysql-test/r/null_key.result index 009a3e06eb2..41b0ae26617 100644 --- a/mysql-test/r/null_key.result +++ b/mysql-test/r/null_key.result @@ -12,7 +12,7 @@ table type possible_keys key key_len ref rows Extra t1 ref a,b a 9 const,const 1 Using where; Using index explain select * from t1 where a=2 and b = 2; table type possible_keys key key_len ref rows Extra -t1 const a,b a 9 const,const 1 +t1 const a,b a 9 const,const 1 Using index explain select * from t1 where a<=>b limit 2; table type possible_keys key key_len ref rows Extra t1 index NULL a 9 NULL 12 Using where; Using index diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 206fa507615..ce5ea94a08e 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2327,3 +2327,19 @@ select * from t2,t3 where t2.s = t3.s; s s two two drop table t1, t2, t3; +CREATE TABLE t1 ( +i int(11) NOT NULL default '0', +c char(10) NOT NULL default '', +PRIMARY KEY (i), +UNIQUE KEY c (c) +) TYPE=MyISAM; +INSERT INTO t1 VALUES (1,'a'); +INSERT INTO t1 VALUES (2,'b'); +INSERT INTO t1 VALUES (3,'c'); +EXPLAIN SELECT i FROM t1 WHERE i=1; +table type possible_keys key key_len ref rows Extra +t1 const PRIMARY PRIMARY 4 const 1 Using index +EXPLAIN SELECT i FROM t1 WHERE i=1; +table type possible_keys key key_len ref rows Extra +t1 const PRIMARY PRIMARY 4 const 1 Using index +DROP TABLE t1; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 7cb157f194e..dae44159683 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -1874,3 +1874,24 @@ select * from t3 where s = 'one'; select * from t1,t2 where t1.s = t2.s; select * from t2,t3 where t2.s = t3.s; drop table t1, t2, t3; + +# +# Covering index is mentioned in EXPLAIN output for const tables (bug #5333) +# + +CREATE TABLE t1 ( + i int(11) NOT NULL default '0', + c char(10) NOT NULL default '', + PRIMARY KEY (i), + UNIQUE KEY c (c) +) TYPE=MyISAM; + +INSERT INTO t1 VALUES (1,'a'); +INSERT INTO t1 VALUES (2,'b'); +INSERT INTO t1 VALUES (3,'c'); + +EXPLAIN SELECT i FROM t1 WHERE i=1; + +EXPLAIN SELECT i FROM t1 WHERE i=1; + +DROP TABLE t1; \ No newline at end of file diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 882f345a1ca..d2b9f9d4588 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -4901,6 +4901,15 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos) } else { + if (!table->key_read && + (table->used_keys & ((key_map) 1 << tab->ref.key)) && + !table->no_keyread && + (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY) + { + table->key_read=1; + table->file->extra(HA_EXTRA_KEYREAD); + tab->index= tab->ref.key; + } if ((error=join_read_const(tab))) { tab->info="unique row not found"; @@ -7617,7 +7626,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, sprintf(buff3,"%.0f",join->best_positions[i].records_read); item_list.push_back(new Item_string(buff3,strlen(buff3))); my_bool key_read=table->key_read; - if (tab->type == JT_NEXT && + if ((tab->type == JT_NEXT || tab->type == JT_CONST) && ((table->used_keys & ((key_map) 1 << tab->index)))) key_read=1; From 71ba3e55b788e8c701b7292051f04e6fce55f26f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 6 Sep 2004 16:48:11 +0500 Subject: [PATCH 2/6] A fix (bug #2205 USE database doesn't work after DROP database + CREATE database) (Jani's CS 1.1675 04/01/05 21:45:14 was adapted an aplied). client/mysql.cc: A fix (bug #2205 USE database doesn't work after DROP database + CREATE database). --- client/mysql.cc | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 154695aa9e5..1858699e8da 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2200,8 +2200,9 @@ static int com_source(String *buffer, char *line) static int com_use(String *buffer __attribute__((unused)), char *line) { - char *tmp; - char buff[256]; + char *tmp, buff[FN_REFLEN + 1]; + MYSQL_RES *res; + MYSQL_ROW row; while (isspace(*line)) line++; @@ -2214,6 +2215,30 @@ com_use(String *buffer __attribute__((unused)), char *line) put_info("USE must be followed by a database name",INFO_ERROR); return 0; } + /* + We need to recheck the current database, because it may change + under our feet, for example if DROP DATABASE or RENAME DATABASE + (latter one not yet available by the time the comment was written) + */ + current_db= 0; // Let's reset current_db, assume it's gone + /* + We don't care about in case of an error below because current_db + was just set to 0. + */ + if (!mysql_query(&mysql, "SELECT DATABASE()") && + (res= mysql_use_result(&mysql))) + { + row= mysql_fetch_row(res); + if (row[0] && + (!current_db || cmp_database(current_db, row[0]))) + { + my_free(current_db, MYF(MY_ALLOW_ZERO_PTR)); + current_db= my_strdup(row[0], MYF(MY_WME)); + } + (void) mysql_fetch_row(res); // Read eof + mysql_free_result(res); + } + if (!current_db || cmp_database(current_db,tmp)) { if (one_database) From ee511e55e7598767924d73e9fe08a480e1c2c72d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 7 Sep 2004 14:24:47 +0500 Subject: [PATCH 3/6] A fix (Bug #5432: Is this a leak in mysql console client?) --- client/mysql.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 1858699e8da..3cc8b41af66 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2220,7 +2220,9 @@ com_use(String *buffer __attribute__((unused)), char *line) under our feet, for example if DROP DATABASE or RENAME DATABASE (latter one not yet available by the time the comment was written) */ - current_db= 0; // Let's reset current_db, assume it's gone + /* Let's reset current_db, assume it's gone */ + my_free(current_db, MYF(MY_ALLOW_ZERO_PTR)); + current_db= 0; /* We don't care about in case of an error below because current_db was just set to 0. @@ -2229,10 +2231,8 @@ com_use(String *buffer __attribute__((unused)), char *line) (res= mysql_use_result(&mysql))) { row= mysql_fetch_row(res); - if (row[0] && - (!current_db || cmp_database(current_db, row[0]))) + if (row[0]) { - my_free(current_db, MYF(MY_ALLOW_ZERO_PTR)); current_db= my_strdup(row[0], MYF(MY_WME)); } (void) mysql_fetch_row(res); // Read eof From 3a476a6e91bcd8f219393b7ec670c4833f534ea3 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 7 Sep 2004 14:20:48 +0200 Subject: [PATCH 4/6] clean up at end of test (thanks serg) mysql-test/r/rpl_set_charset.result: result update mysql-test/t/rpl_set_charset.test: clean up on slave too. --- mysql-test/r/rpl_set_charset.result | 1 - mysql-test/t/rpl_set_charset.test | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/mysql-test/r/rpl_set_charset.result b/mysql-test/r/rpl_set_charset.result index 7297d80865b..9c7ea73c741 100644 --- a/mysql-test/r/rpl_set_charset.result +++ b/mysql-test/r/rpl_set_charset.result @@ -48,5 +48,4 @@ C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF C0 D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF D0 E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF E0 F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF F0 -drop table t1; drop database mysqltest1; diff --git a/mysql-test/t/rpl_set_charset.test b/mysql-test/t/rpl_set_charset.test index dcfc11bf25e..bd68ce17bbc 100644 --- a/mysql-test/t/rpl_set_charset.test +++ b/mysql-test/t/rpl_set_charset.test @@ -34,9 +34,7 @@ use mysqltest1; select "--- on slave ---"; select hex(a),b from t1 order by b; connection master; -drop table t1; +drop database mysqltest1; save_master_pos; connection slave; sync_with_master; -connection master; -drop database mysqltest1; From 32db5b4c5eb4dddf6401f3a926645a1972fa5369 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 7 Sep 2004 14:57:54 +0200 Subject: [PATCH 5/6] when we update thd->db in replication, it's safer to update thd->db_length too. This does not fix any known bug, but is still a good idea. sql/log_event.cc: when we update thd->db in replication, it's safer to update thd->db_length too. sql/slave.cc: when we update thd->db in replication, it's safer to update thd->db_length too. sql/sql_db.cc: comment --- sql/log_event.cc | 14 ++++++++++---- sql/slave.cc | 13 +++++++++---- sql/sql_db.cc | 9 +++++++++ 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 5526795c9d1..f707eabebd5 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1806,7 +1806,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) { int expected_error, actual_error= 0; init_sql_alloc(&thd->mem_root, thd->variables.query_alloc_block_size,0); - thd->db= (char*) rewrite_db(db); + thd->db= (char*) rewrite_db(db); // thd->db_length is set later if needed /* InnoDB internally stores the master log position it has processed so far; @@ -1836,6 +1836,11 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) { thd->set_time((time_t)when); thd->current_tablenr = 0; + /* + We cannot use db_len from event to fill thd->db_length, because + rewrite_db() may have changed db. + */ + thd->db_length= thd->db ? strlen(thd->db) : 0; thd->query_length= q_len; thd->query= (char *) query; VOID(pthread_mutex_lock(&LOCK_thread_count)); @@ -1930,7 +1935,7 @@ end: VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->db= 0; // prevent db from being freed thd->query= 0; // just to be sure - thd->query_length= 0; + thd->query_length= thd->db_length =0; VOID(pthread_mutex_unlock(&LOCK_thread_count)); close_thread_tables(thd); free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); @@ -1968,7 +1973,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, { char *load_data_query= 0; init_sql_alloc(&thd->mem_root, thd->variables.query_alloc_block_size, 0); - thd->db= (char*) rewrite_db(db); + thd->db= (char*) rewrite_db(db); // thd->db_length is set later if needed DBUG_ASSERT(thd->query == 0); clear_all_errors(thd, rli); @@ -2001,6 +2006,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, { thd->set_time((time_t)when); thd->current_tablenr = 0; + thd->db_length= thd->db ? strlen(thd->db) : 0; VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query_id = query_id++; VOID(pthread_mutex_unlock(&LOCK_thread_count)); @@ -2117,7 +2123,7 @@ Slave: load data infile on table '%s' at log position %s in log \ VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->db= 0; thd->query= 0; - thd->query_length= 0; + thd->query_length= thd->db_length= 0; VOID(pthread_mutex_unlock(&LOCK_thread_count)); close_thread_tables(thd); if (load_data_query) diff --git a/sql/slave.cc b/sql/slave.cc index 4416a2544ef..18e0ec5929f 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1124,6 +1124,7 @@ slaves can't replicate a 5.0 or newer master."; Used by fetch_master_table (used by LOAD TABLE tblname FROM MASTER and LOAD DATA FROM MASTER). Drops the table (if 'overwrite' is true) and recreates it from the dump. Honours replication inclusion/exclusion rules. + db must be non-zero (guarded by assertion). RETURN VALUES 0 success @@ -1134,8 +1135,8 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, const char* table_name, bool overwrite) { ulong packet_len = my_net_read(net); // read create table statement - char *query; - char* save_db; + char *query, *save_db; + uint32 save_db_length; Vio* save_vio; HA_CHECK_OPT check_opt; TABLE_LIST tables; @@ -1193,9 +1194,13 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, thd->proc_info = "Creating table from master dump"; // save old db in case we are creating in a different database save_db = thd->db; + save_db_length= thd->db_length; thd->db = (char*)db; + DBUG_ASSERT(thd->db); + thd->db_length= strlen(thd->db); mysql_parse(thd, thd->query, packet_len); // run create table thd->db = save_db; // leave things the way the were before + thd->db_length= save_db_length; thd->options = save_options; if (thd->query_error) @@ -2689,7 +2694,7 @@ err: IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff)); VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query = thd->db = 0; // extra safety - thd->query_length = 0; + thd->query_length= thd->db_length= 0; VOID(pthread_mutex_unlock(&LOCK_thread_count)); if (mysql) { @@ -2838,7 +2843,7 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ err: VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query = thd->db = 0; // extra safety - thd->query_length = 0; + thd->query_length= thd->db_length= 0; VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->proc_info = "Waiting for slave mutex on exit"; pthread_mutex_lock(&rli->run_lock); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 3d877403813..c8874701aa1 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -385,6 +385,15 @@ err: } +/* + Changes the current database. + + NOTES + Do as little as possible in this function, as it is not called for the + replication slave SQL thread (for that thread, setting of thd->db is done + in ::exec_event() methods of log_event.cc). +*/ + bool mysql_change_db(THD *thd,const char *name) { int length, db_length; From 95036003c6bf0e0c685789f118a225f70b164a17 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 7 Sep 2004 10:03:46 -0700 Subject: [PATCH 6/6] select.test: Added newline at the end of file. mysql-test/t/select.test: Added newline at the end of file. --- mysql-test/t/select.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index dae44159683..03490360b35 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -1894,4 +1894,4 @@ EXPLAIN SELECT i FROM t1 WHERE i=1; EXPLAIN SELECT i FROM t1 WHERE i=1; -DROP TABLE t1; \ No newline at end of file +DROP TABLE t1;