diff options
-rw-r--r-- | sql/sql_class.h | 5 | ||||
-rw-r--r-- | sql/sql_delete.cc | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 14 | ||||
-rw-r--r-- | sql/sql_unions.cc | 113 |
4 files changed, 101 insertions, 33 deletions
diff --git a/sql/sql_class.h b/sql/sql_class.h index 14055a1444c..be1f251ed6e 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -421,7 +421,7 @@ public: virtual int prepare(List<Item> &list) { return 0; } virtual bool send_fields(List<Item> &list,uint flag)=0; virtual bool send_data(List<Item> &items)=0; - virtual void initialize_tables (JOIN *join=0) {}; + virtual void initialize_tables (JOIN *join=0) {} virtual void send_error(uint errcode,const char *err)=0; virtual bool send_eof()=0; virtual void abort() {} @@ -475,14 +475,13 @@ public: bool send_eof(); }; class select_insert :public select_result { - protected: + public: TABLE *table; List<Item> *fields; uint save_time_stamp; ulonglong last_insert_id; COPY_INFO info; -public: select_insert(TABLE *table_par,List<Item> *fields_par,enum_duplicates duplic) :table(table_par),fields(fields_par), save_time_stamp(0),last_insert_id(0) { diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 0f70bd71ddd..af523a9e3c4 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -17,6 +17,8 @@ /* Delete of records */ +/* Multi-table deletes were introduced by Monty and Sinisa */ + #include "mysql_priv.h" #include "ha_innobase.h" #include "sql_select.h" diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 928a62a397e..8a578688224 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2445,13 +2445,13 @@ mysql_new_select(LEX *lex) uint select_no=lex->select->select_number; SELECT_LEX *select_lex = (SELECT_LEX *)sql_calloc(sizeof(SELECT_LEX)); lex->select->next=select_lex; - lex->select=select_lex; lex->select->select_number = ++select_no; - lex->select->item_list = lex->select_lex.item_list; - lex->select->item_list.empty(); - lex->select->table_list = lex->select_lex.table_list; - lex->select->table_list.elements=0; - lex->select->table_list.first=0; - lex->select->table_list.next= (byte**) &lex->select->table_list.first; + lex->select=select_lex; select_lex->select_number = ++select_no; + select_lex->table_list.elements=0; + select_lex->table_list.first=0; + select_lex->table_list.next= (byte**) &select_lex->table_list.first; + select_lex->item_list.empty(); select_lex->when_list.empty(); + select_lex->expr_list.empty(); select_lex->interval_list.empty(); + select_lex->use_index.empty(); select_lex->ftfunc_list.empty(); } void diff --git a/sql/sql_unions.cc b/sql/sql_unions.cc index 55aca0f5b68..63ed5fe0c07 100644 --- a/sql/sql_unions.cc +++ b/sql/sql_unions.cc @@ -1,33 +1,100 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & Monty & Sinisa - - 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 */ +#include "mysql_priv.h" /* Union of selects */ -#include "mysql_priv.h" - -/* - Do a union of selects -*/ - int mysql_union(THD *thd,LEX *lex,uint no_of_selects) { - SELECT_LEX *sl; - for (sl=&lex->select_lex;sl;sl=sl->next) + SELECT_LEX *sl, *for_order=&lex->select_lex; uint no=0; int res; + List<Item> fields; TABLE *table; + for (;for_order->next;for_order=for_order->next); + ORDER *some_order = (ORDER *)for_order->order_list.first; + for (sl=&lex->select_lex;sl;sl=sl->next, no++) + { + TABLE_LIST *tables=(TABLE_LIST*) sl->table_list.first; + if (!no) // First we do CREATE from SELECT + { + select_create *result; + lex->create_info.options=HA_LEX_CREATE_TMP_TABLE; + if ((result=new select_create(tables->db ? tables->db : thd->db, + NULL, &lex->create_info, + lex->create_list, + lex->key_list, + sl->item_list,DUP_IGNORE))) + { + res=mysql_select(thd,tables,sl->item_list, + sl->where, + sl->ftfunc_list, + (ORDER*) NULL, + (ORDER*) sl->group_list.first, + sl->having, + (ORDER*) some_order, + sl->options | thd->options, + result); + if (res) + { + result->abort(); + delete result; + return res; + } + else + { + table=result->table; + List_iterator<Item> it(*(result->fields)); + Item *item; + while ((item= it++)) + fields.push_back(item); + } + delete result; + if (reopen_table(table)) return 1; + } + else + return -1; + } + else // Then we do INSERT from SELECT + { + select_result *result; + if ((result=new select_insert(table, &fields, DUP_IGNORE))) + { + res=mysql_select(thd,tables,sl->item_list, + sl->where, + sl->ftfunc_list, + (ORDER*) some_order, + (ORDER*) sl->group_list.first, + sl->having, + (ORDER*) NULL, + sl->options | thd->options, + result); + delete result; + if (res) return 1; + } + else + return -1; + } + } + if (1) // Meaning if not SELECT ... INTO .... which will be done later + { + READ_RECORD info; + int error=0; + if (send_fields(thd,fields,1)) return 1; + SQL_SELECT *select= new SQL_SELECT; + select->head=table; + select->file=*(table->io_cache); + init_read_record(&info,thd,table,select,1,1); + while (!(error=info.read_record(&info)) && !thd->killed) + { + + if (error) + { + table->file->print_error(error,MYF(0)); + break; + } + } + end_read_record(&info); + delete select; + } + else { } return 0; |