From 458a947f6c5edae7470f4b30d9b92d4e9862a0dc Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Fri, 26 Dec 2003 12:32:02 +0200 Subject: [PATCH 1/3] Fixed bug in table level privilege GRANT handling. (Bug #2178) Portability fixes --- mysql-test/r/rpl_until.result | 2 +- mysql-test/t/rpl_until.test | 6 +++--- sql/slave.cc | 2 +- sql/slave.h | 5 +++++ sql/sql_acl.cc | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/rpl_until.result b/mysql-test/r/rpl_until.result index c179351551d..82b1ed233ec 100644 --- a/mysql-test/r/rpl_until.result +++ b/mysql-test/r/rpl_until.result @@ -31,7 +31,7 @@ n 4 show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 561 slave-relay-bin.000002 332 master-bin.000001 Yes No 0 0 244 649 Master master-bin.000001 244 No # +# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 561 slave-relay-bin.000002 # master-bin.000001 Yes No 0 0 244 # Master master-bin.000001 244 No # start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291; select * from t1; n diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test index 9bc4ea4e7b1..4508fbea194 100644 --- a/mysql-test/t/rpl_until.test +++ b/mysql-test/t/rpl_until.test @@ -29,7 +29,7 @@ sleep 2; # here table should be still not deleted select * from t1; --replace_result $MASTER_MYPORT MASTER_MYPORT ---replace_column 1 # 33 # +--replace_column 1 # 9 # 23 # 33 # show slave status; # this should fail right after start @@ -59,9 +59,9 @@ stop slave; # this should stop immideately start slave until master_log_file='master-bin.000001', master_log_pos=561; -sleep 2; +--real-sleep 2; # here the sql slave thread should be stopped ---replace_result $MASTER_MYPORT MASTER_MYPORT +--replace_result $MASTER_MYPORT MASTER_MYPORT bin.000005 bin.000004 bin.000006 bin.000004 bin.000007 bin.000004 --replace_column 1 # 9 # 23 # 33 # show slave status; diff --git a/sql/slave.cc b/sql/slave.cc index d2a7d397fa7..36d8975a127 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2682,7 +2682,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) rli->is_until_satisfied()) { sql_print_error("Slave SQL thread stopped because it reached its" - " UNTIL position"); + " UNTIL position %ld", (long) rli->until_pos()); /* Setting abort_slave flag because we do not want additional message about error in query execution to be printed. diff --git a/sql/slave.h b/sql/slave.h index e42b93a47ef..d92c44dd2ba 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -324,6 +324,11 @@ typedef struct st_relay_log_info /* Check if UNTIL condition is satisfied. See slave.cc for more. */ bool is_until_satisfied(); + inline ulonglong until_pos() + { + return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_pos : + group_relay_log_pos); + } } RELAY_LOG_INFO; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 01820917ce9..3f70cc1323b 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2543,7 +2543,7 @@ my_bool grant_init(THD *org_thd) do { GRANT_TABLE *mem_check; - if (!(mem_check=new GRANT_TABLE(t_table,c_table)) || mem_check->ok()) + if (!(mem_check=new GRANT_TABLE(t_table,c_table)) || !mem_check->ok()) { /* This could only happen if we are out memory */ grant_option= FALSE; /* purecov: deadcode */ From 0eb607006879210b04278d0a961e28e72616645d Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Mon, 19 Jan 2004 23:51:17 +0100 Subject: [PATCH 2/3] Code cleanup Fixed bug in optimizer where it didn't choose right table order in some cases --- myisam/mi_delete.c | 4 ---- myisam/mi_delete_table.c | 3 --- myisam/mi_extra.c | 3 --- myisam/mi_locking.c | 3 --- myisam/mi_log.c | 1 - myisam/mi_page.c | 3 --- myisam/mi_rename.c | 3 --- myisam/mi_update.c | 5 ----- myisam/mi_write.c | 4 ---- mysql-test/r/subselect.result | 4 ++-- mysys/charset.c | 13 +++++++------ sql/item_cmpfunc.cc | 15 ++++----------- sql/item_cmpfunc.h | 6 +++--- sql/mysqld.cc | 2 +- sql/set_var.cc | 10 ---------- sql/sql_select.cc | 21 +++++++++++++++++---- 16 files changed, 34 insertions(+), 66 deletions(-) diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c index a55d5b2a5ca..19cfc050ea1 100644 --- a/myisam/mi_delete.c +++ b/myisam/mi_delete.c @@ -20,10 +20,6 @@ #include "rt_index.h" #include -#ifdef __WIN__ -#include -#endif - static int d_search(MI_INFO *info,MI_KEYDEF *keyinfo,uint comp_flag, uchar *key,uint key_length,my_off_t page,uchar *anc_buff); static int del(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key,uchar *anc_buff, diff --git a/myisam/mi_delete_table.c b/myisam/mi_delete_table.c index 6d842d7e6a4..6843881568d 100644 --- a/myisam/mi_delete_table.c +++ b/myisam/mi_delete_table.c @@ -19,9 +19,6 @@ */ #include "fulltext.h" -#ifdef __WIN__ -#include -#endif int mi_delete_table(const char *name) { diff --git a/myisam/mi_extra.c b/myisam/mi_extra.c index 10f52f1e39a..ce072d7d57e 100644 --- a/myisam/mi_extra.c +++ b/myisam/mi_extra.c @@ -18,9 +18,6 @@ #ifdef HAVE_MMAP #include #endif -#ifdef __WIN__ -#include -#endif /* Set options and buffers to optimize table handling diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c index 67ccca52d08..816748d459a 100644 --- a/myisam/mi_locking.c +++ b/myisam/mi_locking.c @@ -22,9 +22,6 @@ */ #include "myisamdef.h" -#ifdef __WIN__ -#include -#endif /* lock table by F_UNLCK, F_RDLCK or F_WRLCK */ diff --git a/myisam/mi_log.c b/myisam/mi_log.c index 1dcfd5250d2..13842c56828 100644 --- a/myisam/mi_log.c +++ b/myisam/mi_log.c @@ -21,7 +21,6 @@ #include "myisamdef.h" #if defined(MSDOS) || defined(__WIN__) -#include #include #ifndef __WIN__ #include diff --git a/myisam/mi_page.c b/myisam/mi_page.c index c70209c2da6..16713c87e10 100644 --- a/myisam/mi_page.c +++ b/myisam/mi_page.c @@ -17,9 +17,6 @@ /* Read and write key blocks */ #include "myisamdef.h" -#ifdef __WIN__ -#include -#endif /* Fetch a key-page in memory */ diff --git a/myisam/mi_rename.c b/myisam/mi_rename.c index db44b8fe28f..8380ee1bfad 100644 --- a/myisam/mi_rename.c +++ b/myisam/mi_rename.c @@ -19,9 +19,6 @@ */ #include "fulltext.h" -#ifdef __WIN__ -#include -#endif int mi_rename(const char *old_name, const char *new_name) { diff --git a/myisam/mi_update.c b/myisam/mi_update.c index d1d41ac351a..f62be133ed9 100644 --- a/myisam/mi_update.c +++ b/myisam/mi_update.c @@ -19,11 +19,6 @@ #include "fulltext.h" #include "rt_index.h" -#ifdef __WIN__ -#include -#endif - - int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec) { int flag,key_changed,save_errno; diff --git a/myisam/mi_write.c b/myisam/mi_write.c index d13ba6c2c4e..4b7a22dac84 100644 --- a/myisam/mi_write.c +++ b/myisam/mi_write.c @@ -20,10 +20,6 @@ #include "rt_index.h" #include -#ifdef __WIN__ -#include -#endif - #define MAX_POINTER_LENGTH 8 /* Functions declared in this file */ diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 672a39299dd..edc8e56f442 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1340,8 +1340,8 @@ a explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 index NULL a 5 NULL 4 Using where; Using index -2 DEPENDENT SUBQUERY t3 index a a 5 NULL 3 Using index -2 DEPENDENT SUBQUERY t1 ref a a 10 func,test.t3.a 1000 Using where; Using index +2 DEPENDENT SUBQUERY t1 ref a a 5 func 1001 Using where; Using index +2 DEPENDENT SUBQUERY t3 index a a 5 NULL 3 Using where; Using index Warnings: Note 1003 select high_priority test.t2.a AS `a` from test.t2 where (test.t2.a,(select 1 AS `Not_used` from test.t1 join test.t3 where ((test.t1.b = test.t3.a) and ((test.t2.a) = test.t1.a)) limit 1)) insert into t1 values (3,31); diff --git a/mysys/charset.c b/mysys/charset.c index f8c8237c88b..fec0778213f 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -533,14 +533,15 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) */ pthread_mutex_lock(&THR_LOCK_charset); - cs= all_charsets[cs_number]; - - if (cs && !(cs->state & MY_CS_COMPILED) && !(cs->state & MY_CS_LOADED)) + if ((cs= all_charsets[cs_number])) { - strxmov(get_charsets_dir(buf), cs->csname, ".xml", NullS); - my_read_charset_file(buf,flags); + if (!(cs->state & MY_CS_COMPILED) && !(cs->state & MY_CS_LOADED)) + { + strxmov(get_charsets_dir(buf), cs->csname, ".xml", NullS); + my_read_charset_file(buf,flags); + } + cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL; } - cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL; pthread_mutex_unlock(&THR_LOCK_charset); return cs; } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index a79ef21e97a..5b27091321c 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1658,26 +1658,19 @@ Item_cond::Item_cond(THD *thd, Item_cond &item) and_tables_cache(item.and_tables_cache) { /* - here should be following text: - - List_iterator_fast li(item.list); - while(Item *it= li++) - list.push_back(it); - - but it do not need, - because this constructor used only for AND/OR and - argument list will be copied by copy_andor_arguments call + item->list will be copied by copy_andor_arguments() call */ - } + void Item_cond::copy_andor_arguments(THD *thd, Item_cond *item) { List_iterator_fast li(item->list); - while(Item *it= li++) + while (Item *it= li++) list.push_back(it->copy_andor_structure(thd)); } + bool Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 541bc47557d..f5cd608ebad 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -919,8 +919,8 @@ public: Item* copy_andor_structure(THD *thd) { Item_cond_and *item; - if((item= new Item_cond_and(thd, *this))) - item->copy_andor_arguments(thd, this); + if ((item= new Item_cond_and(thd, *this))) + item->copy_andor_arguments(thd, this); return item; } Item *neg_transformer(); @@ -940,7 +940,7 @@ public: Item* copy_andor_structure(THD *thd) { Item_cond_or *item; - if((item= new Item_cond_or(thd, *this))) + if ((item= new Item_cond_or(thd, *this))) item->copy_andor_arguments(thd, this); return item; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index e81113f6111..6387e99ca05 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4619,7 +4619,7 @@ The minimum value for this variable is 4096.", (gptr*) &max_system_variables.net_wait_timeout, 0, GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, {"expire_logs_days", OPT_EXPIRE_LOGS_DAYS, - "Logs will be rotated after expire-log-days days ", + "Binary logs will be rotated after expire-log-days days ", (gptr*) &expire_logs_days, (gptr*) &expire_logs_days, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 99, 0, 1, 0}, diff --git a/sql/set_var.cc b/sql/set_var.cc index c8b11eb0f58..ecb85440068 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2629,11 +2629,6 @@ ulong fix_sql_mode(ulong sql_mode) MODE_IGNORE_SPACE | MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | MODE_NO_FIELD_OPTIONS); - if (sql_mode & MODE_MSSQL) - sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | - MODE_IGNORE_SPACE | - MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | - MODE_NO_FIELD_OPTIONS); if (sql_mode & MODE_POSTGRESQL) sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | @@ -2644,11 +2639,6 @@ ulong fix_sql_mode(ulong sql_mode) MODE_IGNORE_SPACE | MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | MODE_NO_FIELD_OPTIONS); - if (sql_mode & MODE_DB2) - sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | - MODE_IGNORE_SPACE | - MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | - MODE_NO_FIELD_OPTIONS); if (sql_mode & MODE_MAXDB) sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a1f6abfd53a..92cdd12ad37 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2688,22 +2688,35 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, do { uint keypart=keyuse->keypart; - uint found_part_ref_or_null= KEY_OPTIMIZE_REF_OR_NULL; + table_map best_part_found_ref= 0; + double best_prev_record_reads= DBL_MAX; do { if (!(rest_tables & keyuse->used_tables) && !(found_ref_or_null & keyuse->optimize)) { found_part|=keyuse->keypart_map; - found_ref|= keyuse->used_tables; + double tmp= prev_record_reads(join, + (found_ref | + keyuse->used_tables)); + if (tmp < best_prev_record_reads) + { + best_part_found_ref= keyuse->used_tables; + best_prev_record_reads= tmp; + } if (rec > keyuse->ref_table_rows) rec= keyuse->ref_table_rows; - found_part_ref_or_null&= keyuse->optimize; + /* + If there is one 'key_column IS NULL' expression, we can + use this ref_or_null optimsation of this field + */ + found_ref_or_null|= (keyuse->optimize & + KEY_OPTIMIZE_REF_OR_NULL); } keyuse++; - found_ref_or_null|= found_part_ref_or_null; } while (keyuse->table == table && keyuse->key == key && keyuse->keypart == keypart); + found_ref|= best_part_found_ref; } while (keyuse->table == table && keyuse->key == key); /* From 6bfede9639855fc215790acc5131c0bd46dea85b Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Thu, 5 Feb 2004 10:22:08 +0100 Subject: [PATCH 3/3] Added SQL_SELECT::cleanup() to make it easier to reuse SQL_SELECT item's for sub selects. Needed for proper fix for bug #2479. Added 'select_to_file' class to be able to merge identical code for select_export and select_dump --- client/mysql.cc | 8 +++- mysys/charset.c | 2 - sql/item_func.cc | 13 ++++-- sql/opt_range.cc | 21 ++++++--- sql/opt_range.h | 1 + sql/sql_class.cc | 110 +++++++++++++++++++++++++--------------------- sql/sql_class.h | 58 ++++++++++++------------ sql/sql_select.cc | 13 +++--- 8 files changed, 131 insertions(+), 95 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 2cdcd23165e..665a8dde82d 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -44,7 +44,7 @@ #include #endif -const char *VER= "14.4"; +const char *VER= "14.5"; /* Don't try to make a nice table if the data is too big */ #define MAX_COLUMN_LENGTH 1024 @@ -2703,6 +2703,9 @@ com_status(String *buffer __attribute__((unused)), char *line __attribute__((unused))) { const char *status; + char buff[22]; + ulonglong id; + tee_puts("--------------", stdout); usage(1); /* Print version */ if (connected) @@ -2748,6 +2751,9 @@ com_status(String *buffer __attribute__((unused)), tee_fprintf(stdout, "Server version:\t\t%s\n", mysql_get_server_info(&mysql)); tee_fprintf(stdout, "Protocol version:\t%d\n", mysql_get_proto_info(&mysql)); tee_fprintf(stdout, "Connection:\t\t%s\n", mysql_get_host_info(&mysql)); + if ((id= mysql_insert_id(&mysql))) + tee_fprintf(stdout, "Insert id:\t\t%s\n", llstr(id, buff)); + tee_fprintf(stdout, "Client characterset:\t%s\n", charset_info->name); tee_fprintf(stdout, "Server characterset:\t%s\n", mysql.charset->name); diff --git a/mysys/charset.c b/mysys/charset.c index c0d8b183c17..5bf0ea972a5 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -537,7 +537,6 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) while we may changing the cs_info_table */ pthread_mutex_lock(&THR_LOCK_charset); - if ((cs= all_charsets[cs_number])) { if (!(cs->state & MY_CS_COMPILED) && !(cs->state & MY_CS_LOADED)) @@ -548,7 +547,6 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL; } pthread_mutex_unlock(&THR_LOCK_charset); - pthread_mutex_unlock(&THR_LOCK_charset); return cs; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 802b6dbb8d6..c995b50109f 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2646,10 +2646,15 @@ longlong Item_func_inet_aton::val_int() } if (c != '.') // IP number can't end on '.' { - switch (dot_count) - { - case 1: result<<= 8; - case 2: result<<= 8; + /* + Handle short-forms addresses according to standard. Examples: + 127 -> 0.0.0.127 + 127.1 -> 127.0.0.1 + 127.2.1 -> 127.2.0.1 + */ + switch (dot_count) { + case 1: result<<= 8; /* Fall through */ + case 2: result<<= 8; /* Fall through */ } return (result << 8) + (ulonglong) byte_result; } diff --git a/sql/opt_range.cc b/sql/opt_range.cc index acc23924f75..17fc948dd6e 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -369,14 +369,25 @@ SQL_SELECT::SQL_SELECT() :quick(0),cond(0),free_cond(0) } -SQL_SELECT::~SQL_SELECT() +void SQL_SELECT::cleanup() { delete quick; + quick= 0; if (free_cond) + { + free_cond=0; delete cond; + cond= 0; + } close_cached_file(&file); } + +SQL_SELECT::~SQL_SELECT() +{ + cleanup(); +} + #undef index // Fix for Unixware 7 QUICK_SELECT::QUICK_SELECT(THD *thd, TABLE *table, uint key_nr, bool no_alloc) @@ -2180,6 +2191,7 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree) param->table->quick_rows[key]=records; param->table->quick_key_parts[key]=param->max_key_part+1; } + DBUG_PRINT("exit", ("Records: %lu", (ulong) records)); DBUG_RETURN(records); } @@ -2532,12 +2544,7 @@ int QUICK_SELECT::get_next() int result; if (range) { // Already read through key -/* result=((range->flag & EQ_RANGE) ? - file->index_next_same(record, (byte*) range->min_key, - range->min_length) : - file->index_next(record)); -*/ - result=((range->flag & (EQ_RANGE | GEOM_FLAG) ) ? + result=((range->flag & (EQ_RANGE | GEOM_FLAG)) ? file->index_next_same(record, (byte*) range->min_key, range->min_length) : file->index_next(record)); diff --git a/sql/opt_range.h b/sql/opt_range.h index 1c209dc7027..bb0d27b722c 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -127,6 +127,7 @@ class SQL_SELECT :public Sql_alloc { SQL_SELECT(); ~SQL_SELECT(); + void cleanup(); bool check_quick(THD *thd, bool force_quick_range, ha_rows limit) { return test_quick_select(thd, key_map(~0), 0, limit, force_quick_range) < 0; } inline bool skipp_record() { return cond ? cond->val_int() == 0 : 0; } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index ce30c6f3d09..2b743fc83c7 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -679,12 +679,24 @@ bool select_send::send_eof() } -/*************************************************************************** -** Export of select to textfile -***************************************************************************/ +/************************************************************************ + Handling writing to file +************************************************************************/ + +void select_to_file::send_error(uint errcode,const char *err) +{ + ::send_error(thd,errcode,err); + if (file > 0) + { + (void) end_io_cache(&cache); + (void) my_close(file,MYF(0)); + (void) my_delete(path,MYF(0)); // Delete file on error + file= -1; + } +} -select_export::~select_export() +select_to_file::~select_to_file() { if (file >= 0) { // This only happens in case of error @@ -692,17 +704,42 @@ select_export::~select_export() (void) my_close(file,MYF(0)); file= -1; } +} + +/*************************************************************************** +** Export of select to textfile +***************************************************************************/ + +select_export::~select_export() +{ thd->sent_row_count=row_count; } -static int create_file(THD *thd, char *path, sql_exchange *exchange, - File *file, IO_CACHE *cache) +/* + Create file with IO cache + + SYNOPSIS + create_file() + thd Thread handle + path File name + exchange Excange class + cache IO cache + + RETURN + >= 0 File handle + -1 Error +*/ + + +static File create_file(THD *thd, char *path, sql_exchange *exchange, + IO_CACHE *cache) { - uint option= 4; + File file; + uint option= MY_UNPACK_FILENAME; #ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS - option|= 1; // Force use of db directory + option|= MY_REPLACE_DIR; // Force use of db directory #endif (void) fn_format(path, exchange->file_name, thd->db ? thd->db : "", "", option); @@ -712,35 +749,32 @@ static int create_file(THD *thd, char *path, sql_exchange *exchange, return 1; } /* Create the file world readable */ - if ((*file= my_create(path, 0666, O_WRONLY, MYF(MY_WME))) < 0) - return 1; + if ((file= my_create(path, 0666, O_WRONLY, MYF(MY_WME))) < 0) + return file; #ifdef HAVE_FCHMOD - (void) fchmod(*file, 0666); // Because of umask() + (void) fchmod(file, 0666); // Because of umask() #else (void) chmod(path, 0666); #endif - if (init_io_cache(cache, *file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME))) + if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME))) { - my_close(*file, MYF(0)); + my_close(file, MYF(0)); my_delete(path, MYF(0)); // Delete file on error, it was just created - *file= -1; - end_io_cache(cache); - return 1; + return -1; } - return 0; + return file; } int select_export::prepare(List &list, SELECT_LEX_UNIT *u) { - char path[FN_REFLEN]; bool blob_flag=0; unit= u; if ((uint) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN) strmake(path,exchange->file_name,FN_REFLEN-1); - if (create_file(thd, path, exchange, &file, &cache)) + if ((file= create_file(thd, path, exchange, &cache)) < 0) return 1; /* Check if there is any blobs in data */ { @@ -912,14 +946,6 @@ err: } -void select_export::send_error(uint errcode, const char *err) -{ - ::send_error(thd,errcode,err); - (void) my_close(file,MYF(0)); - file= -1; -} - - bool select_export::send_eof() { int error=test(end_io_cache(&cache)); @@ -937,24 +963,12 @@ bool select_export::send_eof() ***************************************************************************/ -select_dump::~select_dump() -{ - if (file >= 0) - { // This only happens in case of error - (void) end_io_cache(&cache); - (void) my_close(file,MYF(0)); - file= -1; - } -} - int select_dump::prepare(List &list __attribute__((unused)), SELECT_LEX_UNIT *u) { unit= u; - if (create_file(thd, path, exchange, &file, &cache)) - return 1; - return 0; + return (int) ((file= create_file(thd, path, exchange, &cache)) < 0); } @@ -997,13 +1011,6 @@ err: } -void select_dump::send_error(uint errcode,const char *err) -{ - ::send_error(thd,errcode,err); - (void) my_close(file,MYF(0)); - file= -1; -} - bool select_dump::send_eof() { int error=test(end_io_cache(&cache)); @@ -1015,11 +1022,13 @@ bool select_dump::send_eof() return error; } + select_subselect::select_subselect(Item_subselect *item_arg) { item= item_arg; } + bool select_singlerow_subselect::send_data(List &items) { DBUG_ENTER("select_singlerow_subselect::send_data"); @@ -1042,6 +1051,7 @@ bool select_singlerow_subselect::send_data(List &items) DBUG_RETURN(0); } + bool select_max_min_finder_subselect::send_data(List &items) { DBUG_ENTER("select_max_min_finder_subselect::send_data"); @@ -1147,8 +1157,9 @@ bool select_exists_subselect::send_data(List &items) /*************************************************************************** -** Dump of select to variables + Dump of select to variables ***************************************************************************/ + int select_dumpvar::prepare(List &list, SELECT_LEX_UNIT *u) { List_iterator_fast li(list); @@ -1165,7 +1176,8 @@ int select_dumpvar::prepare(List &list, SELECT_LEX_UNIT *u) { ls= gl++; Item_func_set_user_var *xx = new Item_func_set_user_var(*ls,item); - xx->fix_fields(thd,(TABLE_LIST*) thd->lex->select_lex.table_list.first,&item); + xx->fix_fields(thd,(TABLE_LIST*) thd->lex->select_lex.table_list.first, + &item); xx->fix_length_and_dec(); vars.push_back(xx); } diff --git a/sql/sql_class.h b/sql/sql_class.h index 7971137d848..51dc8270d09 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -962,41 +962,45 @@ public: }; -class select_export :public select_result { - sql_exchange *exchange; - File file; - IO_CACHE cache; - ha_rows row_count; - uint field_term_length; - int field_sep_char,escape_char,line_sep_char; - bool fixed_row_size; -public: - select_export(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L) {} - ~select_export(); - int prepare(List &list, SELECT_LEX_UNIT *u); - bool send_fields(List &list, - uint flag) { return 0; } - bool send_data(List &items); - void send_error(uint errcode,const char *err); - bool send_eof(); -}; - - -class select_dump :public select_result { +class select_to_file :public select_result { +protected: sql_exchange *exchange; File file; IO_CACHE cache; ha_rows row_count; char path[FN_REFLEN]; + public: - select_dump(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L) + select_to_file(sql_exchange *ex) :exchange(ex), file(-1),row_count(0L) { path[0]=0; } - ~select_dump(); - int prepare(List &list, SELECT_LEX_UNIT *u); - bool send_fields(List &list, - uint flag) { return 0; } - bool send_data(List &items); + ~select_to_file(); + bool send_fields(List &list, uint flag) { return 0; } void send_error(uint errcode,const char *err); +}; + + +class select_export :public select_to_file { + uint field_term_length; + int field_sep_char,escape_char,line_sep_char; + bool fixed_row_size; +public: + select_export(sql_exchange *ex) :select_to_file(ex) {} + ~select_export(); + int prepare(List &list, SELECT_LEX_UNIT *u); + bool send_data(List &items); + bool send_eof(); +}; + + +class select_dump :public select_to_file { + sql_exchange *exchange; + File file; + IO_CACHE cache; + ha_rows row_count; +public: + select_dump(sql_exchange *ex) :select_to_file(ex) {} + int prepare(List &list, SELECT_LEX_UNIT *u); + bool send_data(List &items); bool send_eof(); }; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 75a94995830..34739c36b9d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1648,8 +1648,8 @@ static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select, { select->head=table; table->reginfo.impossible_range=0; - if ((error=select->test_quick_select(thd, *(key_map *)keys,(table_map) 0,limit)) - == 1) + if ((error=select->test_quick_select(thd, *(key_map *)keys,(table_map) 0, + limit)) == 1) DBUG_RETURN(select->quick->records); if (error == -1) { @@ -7212,9 +7212,12 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, table->file->info(HA_STATUS_VARIABLE); // Get record count table->sort.found_records=filesort(thd, table,sortorder, length, select, filesort_limit, &examined_rows); - tab->records=table->sort.found_records; // For SQL_CALC_ROWS - delete select; // filesort did select - tab->select=0; + tab->records=table->sort.found_records; // For SQL_CALC_ROWS + if (select) + { + select->cleanup(); // filesort did select + tab->select= 0; + } tab->select_cond=0; tab->type=JT_ALL; // Read with normal read_record tab->read_first_record= join_init_read_record;