Commit 0db0b601 authored by unknown's avatar unknown

Added SQL_SELECT::cleanup() to make it easier to reuse SQL_SELECT item's for...

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:
  Print mysql_insert_id() in 'status'
mysys/charset.c:
  after merge fixup
sql/item_func.cc:
  Code cleanup + new comments
sql/opt_range.cc:
  Added SQL_SELECT::cleanup() to make it easier to reuse SQL_SELECT item's for sub selects.
sql/opt_range.h:
  Added SQL_SELECT::cleanup() to make it easier to reuse SQL_SELECT item's for sub selects.
sql/sql_class.cc:
  Added 'select_to_file' class to be able to merge identical code for select_export and select_dump
sql/sql_class.h:
  Added 'select_to_file' class to be able to merge identical code for select_export and select_dump
sql/sql_select.cc:
  Fixed bug when calling 'delete select' in sub selects. (Bug 2479)
  (Test case is already commited to global source repository)
parent e44a7da2
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
#include <locale.h> #include <locale.h>
#endif #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 */ /* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024 #define MAX_COLUMN_LENGTH 1024
...@@ -2703,6 +2703,9 @@ com_status(String *buffer __attribute__((unused)), ...@@ -2703,6 +2703,9 @@ com_status(String *buffer __attribute__((unused)),
char *line __attribute__((unused))) char *line __attribute__((unused)))
{ {
const char *status; const char *status;
char buff[22];
ulonglong id;
tee_puts("--------------", stdout); tee_puts("--------------", stdout);
usage(1); /* Print version */ usage(1); /* Print version */
if (connected) if (connected)
...@@ -2748,6 +2751,9 @@ com_status(String *buffer __attribute__((unused)), ...@@ -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, "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, "Protocol version:\t%d\n", mysql_get_proto_info(&mysql));
tee_fprintf(stdout, "Connection:\t\t%s\n", mysql_get_host_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", tee_fprintf(stdout, "Client characterset:\t%s\n",
charset_info->name); charset_info->name);
tee_fprintf(stdout, "Server characterset:\t%s\n", mysql.charset->name); tee_fprintf(stdout, "Server characterset:\t%s\n", mysql.charset->name);
......
...@@ -537,7 +537,6 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) ...@@ -537,7 +537,6 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags)
while we may changing the cs_info_table while we may changing the cs_info_table
*/ */
pthread_mutex_lock(&THR_LOCK_charset); pthread_mutex_lock(&THR_LOCK_charset);
if ((cs= all_charsets[cs_number])) if ((cs= all_charsets[cs_number]))
{ {
if (!(cs->state & MY_CS_COMPILED) && !(cs->state & MY_CS_LOADED)) 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) ...@@ -548,7 +547,6 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags)
cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL; cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL;
} }
pthread_mutex_unlock(&THR_LOCK_charset); pthread_mutex_unlock(&THR_LOCK_charset);
pthread_mutex_unlock(&THR_LOCK_charset);
return cs; return cs;
} }
......
...@@ -2646,10 +2646,15 @@ longlong Item_func_inet_aton::val_int() ...@@ -2646,10 +2646,15 @@ longlong Item_func_inet_aton::val_int()
} }
if (c != '.') // IP number can't end on '.' if (c != '.') // IP number can't end on '.'
{ {
switch (dot_count) /*
{ Handle short-forms addresses according to standard. Examples:
case 1: result<<= 8; 127 -> 0.0.0.127
case 2: result<<= 8; 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; return (result << 8) + (ulonglong) byte_result;
} }
......
...@@ -369,14 +369,25 @@ SQL_SELECT::SQL_SELECT() :quick(0),cond(0),free_cond(0) ...@@ -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; delete quick;
quick= 0;
if (free_cond) if (free_cond)
{
free_cond=0;
delete cond; delete cond;
cond= 0;
}
close_cached_file(&file); close_cached_file(&file);
} }
SQL_SELECT::~SQL_SELECT()
{
cleanup();
}
#undef index // Fix for Unixware 7 #undef index // Fix for Unixware 7
QUICK_SELECT::QUICK_SELECT(THD *thd, TABLE *table, uint key_nr, bool no_alloc) 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) ...@@ -2180,6 +2191,7 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree)
param->table->quick_rows[key]=records; param->table->quick_rows[key]=records;
param->table->quick_key_parts[key]=param->max_key_part+1; param->table->quick_key_parts[key]=param->max_key_part+1;
} }
DBUG_PRINT("exit", ("Records: %lu", (ulong) records));
DBUG_RETURN(records); DBUG_RETURN(records);
} }
...@@ -2532,12 +2544,7 @@ int QUICK_SELECT::get_next() ...@@ -2532,12 +2544,7 @@ int QUICK_SELECT::get_next()
int result; int result;
if (range) if (range)
{ // Already read through key { // Already read through key
/* result=((range->flag & EQ_RANGE) ? result=((range->flag & (EQ_RANGE | GEOM_FLAG)) ?
file->index_next_same(record, (byte*) range->min_key,
range->min_length) :
file->index_next(record));
*/
result=((range->flag & (EQ_RANGE | GEOM_FLAG) ) ?
file->index_next_same(record, (byte*) range->min_key, file->index_next_same(record, (byte*) range->min_key,
range->min_length) : range->min_length) :
file->index_next(record)); file->index_next(record));
......
...@@ -127,6 +127,7 @@ class SQL_SELECT :public Sql_alloc { ...@@ -127,6 +127,7 @@ class SQL_SELECT :public Sql_alloc {
SQL_SELECT(); SQL_SELECT();
~SQL_SELECT(); ~SQL_SELECT();
void cleanup();
bool check_quick(THD *thd, bool force_quick_range, ha_rows limit) 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; } { 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; } inline bool skipp_record() { return cond ? cond->val_int() == 0 : 0; }
......
...@@ -679,12 +679,24 @@ bool select_send::send_eof() ...@@ -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) if (file >= 0)
{ // This only happens in case of error { // This only happens in case of error
...@@ -692,17 +704,42 @@ select_export::~select_export() ...@@ -692,17 +704,42 @@ select_export::~select_export()
(void) my_close(file,MYF(0)); (void) my_close(file,MYF(0));
file= -1; file= -1;
} }
}
/***************************************************************************
** Export of select to textfile
***************************************************************************/
select_export::~select_export()
{
thd->sent_row_count=row_count; 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 #ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
option|= 1; // Force use of db directory option|= MY_REPLACE_DIR; // Force use of db directory
#endif #endif
(void) fn_format(path, exchange->file_name, thd->db ? thd->db : "", "", (void) fn_format(path, exchange->file_name, thd->db ? thd->db : "", "",
option); option);
...@@ -712,35 +749,32 @@ static int create_file(THD *thd, char *path, sql_exchange *exchange, ...@@ -712,35 +749,32 @@ static int create_file(THD *thd, char *path, sql_exchange *exchange,
return 1; return 1;
} }
/* Create the file world readable */ /* Create the file world readable */
if ((*file= my_create(path, 0666, O_WRONLY, MYF(MY_WME))) < 0) if ((file= my_create(path, 0666, O_WRONLY, MYF(MY_WME))) < 0)
return 1; return file;
#ifdef HAVE_FCHMOD #ifdef HAVE_FCHMOD
(void) fchmod(*file, 0666); // Because of umask() (void) fchmod(file, 0666); // Because of umask()
#else #else
(void) chmod(path, 0666); (void) chmod(path, 0666);
#endif #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 my_delete(path, MYF(0)); // Delete file on error, it was just created
*file= -1; return -1;
end_io_cache(cache);
return 1;
} }
return 0; return file;
} }
int int
select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u) select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{ {
char path[FN_REFLEN];
bool blob_flag=0; bool blob_flag=0;
unit= u; unit= u;
if ((uint) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN) if ((uint) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
strmake(path,exchange->file_name,FN_REFLEN-1); 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; return 1;
/* Check if there is any blobs in data */ /* Check if there is any blobs in data */
{ {
...@@ -912,14 +946,6 @@ bool select_export::send_data(List<Item> &items) ...@@ -912,14 +946,6 @@ bool select_export::send_data(List<Item> &items)
} }
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() bool select_export::send_eof()
{ {
int error=test(end_io_cache(&cache)); int error=test(end_io_cache(&cache));
...@@ -937,24 +963,12 @@ bool select_export::send_eof() ...@@ -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 int
select_dump::prepare(List<Item> &list __attribute__((unused)), select_dump::prepare(List<Item> &list __attribute__((unused)),
SELECT_LEX_UNIT *u) SELECT_LEX_UNIT *u)
{ {
unit= u; unit= u;
if (create_file(thd, path, exchange, &file, &cache)) return (int) ((file= create_file(thd, path, exchange, &cache)) < 0);
return 1;
return 0;
} }
...@@ -997,13 +1011,6 @@ bool select_dump::send_data(List<Item> &items) ...@@ -997,13 +1011,6 @@ bool select_dump::send_data(List<Item> &items)
} }
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() bool select_dump::send_eof()
{ {
int error=test(end_io_cache(&cache)); int error=test(end_io_cache(&cache));
...@@ -1015,11 +1022,13 @@ bool select_dump::send_eof() ...@@ -1015,11 +1022,13 @@ bool select_dump::send_eof()
return error; return error;
} }
select_subselect::select_subselect(Item_subselect *item_arg) select_subselect::select_subselect(Item_subselect *item_arg)
{ {
item= item_arg; item= item_arg;
} }
bool select_singlerow_subselect::send_data(List<Item> &items) bool select_singlerow_subselect::send_data(List<Item> &items)
{ {
DBUG_ENTER("select_singlerow_subselect::send_data"); DBUG_ENTER("select_singlerow_subselect::send_data");
...@@ -1042,6 +1051,7 @@ bool select_singlerow_subselect::send_data(List<Item> &items) ...@@ -1042,6 +1051,7 @@ bool select_singlerow_subselect::send_data(List<Item> &items)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
bool select_max_min_finder_subselect::send_data(List<Item> &items) bool select_max_min_finder_subselect::send_data(List<Item> &items)
{ {
DBUG_ENTER("select_max_min_finder_subselect::send_data"); DBUG_ENTER("select_max_min_finder_subselect::send_data");
...@@ -1147,8 +1157,9 @@ bool select_exists_subselect::send_data(List<Item> &items) ...@@ -1147,8 +1157,9 @@ bool select_exists_subselect::send_data(List<Item> &items)
/*************************************************************************** /***************************************************************************
** Dump of select to variables Dump of select to variables
***************************************************************************/ ***************************************************************************/
int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u) int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{ {
List_iterator_fast<Item> li(list); List_iterator_fast<Item> li(list);
...@@ -1165,7 +1176,8 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u) ...@@ -1165,7 +1176,8 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{ {
ls= gl++; ls= gl++;
Item_func_set_user_var *xx = new Item_func_set_user_var(*ls,item); 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(); xx->fix_length_and_dec();
vars.push_back(xx); vars.push_back(xx);
} }
......
...@@ -962,41 +962,45 @@ class select_send :public select_result { ...@@ -962,41 +962,45 @@ class select_send :public select_result {
}; };
class select_export :public select_result { class select_to_file :public select_result {
protected:
sql_exchange *exchange; sql_exchange *exchange;
File file; File file;
IO_CACHE cache; IO_CACHE cache;
ha_rows row_count; ha_rows row_count;
char path[FN_REFLEN];
public:
select_to_file(sql_exchange *ex) :exchange(ex), file(-1),row_count(0L)
{ path[0]=0; }
~select_to_file();
bool send_fields(List<Item> &list, uint flag) { return 0; }
void send_error(uint errcode,const char *err);
};
class select_export :public select_to_file {
uint field_term_length; uint field_term_length;
int field_sep_char,escape_char,line_sep_char; int field_sep_char,escape_char,line_sep_char;
bool fixed_row_size; bool fixed_row_size;
public: public:
select_export(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L) {} select_export(sql_exchange *ex) :select_to_file(ex) {}
~select_export(); ~select_export();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u); int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list,
uint flag) { return 0; }
bool send_data(List<Item> &items); bool send_data(List<Item> &items);
void send_error(uint errcode,const char *err);
bool send_eof(); bool send_eof();
}; };
class select_dump :public select_result { class select_dump :public select_to_file {
sql_exchange *exchange; sql_exchange *exchange;
File file; File file;
IO_CACHE cache; IO_CACHE cache;
ha_rows row_count; ha_rows row_count;
char path[FN_REFLEN];
public: public:
select_dump(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L) select_dump(sql_exchange *ex) :select_to_file(ex) {}
{ path[0]=0; }
~select_dump();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u); int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list,
uint flag) { return 0; }
bool send_data(List<Item> &items); bool send_data(List<Item> &items);
void send_error(uint errcode,const char *err);
bool send_eof(); bool send_eof();
}; };
......
...@@ -1648,8 +1648,8 @@ static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select, ...@@ -1648,8 +1648,8 @@ static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select,
{ {
select->head=table; select->head=table;
table->reginfo.impossible_range=0; table->reginfo.impossible_range=0;
if ((error=select->test_quick_select(thd, *(key_map *)keys,(table_map) 0,limit)) if ((error=select->test_quick_select(thd, *(key_map *)keys,(table_map) 0,
== 1) limit)) == 1)
DBUG_RETURN(select->quick->records); DBUG_RETURN(select->quick->records);
if (error == -1) if (error == -1)
{ {
...@@ -7213,8 +7213,11 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, ...@@ -7213,8 +7213,11 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
table->sort.found_records=filesort(thd, table,sortorder, length, table->sort.found_records=filesort(thd, table,sortorder, length,
select, filesort_limit, &examined_rows); select, filesort_limit, &examined_rows);
tab->records=table->sort.found_records; // For SQL_CALC_ROWS tab->records=table->sort.found_records; // For SQL_CALC_ROWS
delete select; // filesort did select if (select)
tab->select=0; {
select->cleanup(); // filesort did select
tab->select= 0;
}
tab->select_cond=0; tab->select_cond=0;
tab->type=JT_ALL; // Read with normal read_record tab->type=JT_ALL; // Read with normal read_record
tab->read_first_record= join_init_read_record; tab->read_first_record= join_init_read_record;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment