1
/* Copyright (C) 2002-2003 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
19
These were introduced by Sinisa <sinisa@mysql.com>
23
#include "mysql_priv.h"
24
#include "sql_select.h"
29
Call given derived table processor (preparing or filling tables)
32
mysql_handle_derived()
33
lex LEX for this thread
34
processor procedure of derived table processing
42
mysql_handle_derived(LEX *lex, bool (*processor)(THD*, LEX*, TABLE_LIST*))
45
if (lex->derived_tables)
47
lex->thd->derived_tables_processing= TRUE;
48
for (SELECT_LEX *sl= lex->all_selects_list;
50
sl= sl->next_select_in_list())
52
for (TABLE_LIST *cursor= sl->get_table_list();
54
cursor= cursor->next_local)
56
if ((res= (*processor)(lex->thd, lex, cursor)))
62
Force join->join_tmp creation, because we will use this JOIN
63
twice for EXPLAIN and we have to have unchanged join for EXPLAINing
65
sl->uncacheable|= UNCACHEABLE_EXPLAIN;
66
sl->master_unit()->uncacheable|= UNCACHEABLE_EXPLAIN;
71
lex->thd->derived_tables_processing= FALSE;
77
Create temporary table structure (but do not fill it)
80
mysql_derived_prepare()
82
lex LEX for this thread
83
orig_table_list TABLE_LIST for the upper SELECT
86
Derived table is resolved with temporary table.
88
After table creation, the above TABLE_LIST is updated with a new table.
90
This function is called before any command containing derived table
93
Derived tables is stored in thd->derived_tables and freed in
101
bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
103
SELECT_LEX_UNIT *unit= orig_table_list->derived;
104
ulonglong create_options;
105
DBUG_ENTER("mysql_derived_prepare");
109
SELECT_LEX *first_select= unit->first_select();
111
select_union *derived_result;
113
/* prevent name resolving out of derived table */
114
for (SELECT_LEX *sl= first_select; sl; sl= sl->next_select())
115
sl->context.outer_context= 0;
117
if (!(derived_result= new select_union))
118
DBUG_RETURN(TRUE); // out of memory
120
// st_select_lex_unit::prepare correctly work for single select
121
if ((res= unit->prepare(thd, derived_result, 0)))
124
create_options= (first_select->options | thd->options |
125
TMP_TABLE_ALL_COLUMNS);
127
Temp table is created so that it hounours if UNION without ALL is to be
130
As 'distinct' parameter we always pass FALSE (0), because underlying
131
query will control distinct condition by itself. Correct test of
132
distinct underlying query will be is_union &&
133
!unit->union_distinct->next_select() (i.e. it is union and last distinct
134
SELECT is last SELECT of UNION).
136
if ((res= derived_result->create_result_table(thd, &unit->types, FALSE,
138
orig_table_list->alias,
142
table= derived_result->table;
146
if it is preparation PS only or commands that need only VIEW structure
147
then we do not need real data and we can skip execution (and parameters
153
free_tmp_table(thd, table);
154
delete derived_result;
158
if (!thd->fill_derived_tables())
160
delete derived_result;
161
derived_result= NULL;
163
orig_table_list->derived_result= derived_result;
164
orig_table_list->table= table;
165
orig_table_list->table_name= table->s->table_name.str;
166
orig_table_list->table_name_length= table->s->table_name.length;
167
table->derived_select_number= first_select->select_number;
168
table->s->tmp_table= NON_TRANSACTIONAL_TMP_TABLE;
169
orig_table_list->db= (char *)"";
170
orig_table_list->db_length= 0;
171
// Force read of table stats in the optimizer
172
table->file->info(HA_STATUS_VARIABLE);
173
/* Add new temporary table to list of open derived tables */
174
table->next= thd->derived_tables;
175
thd->derived_tables= table;
187
mysql_derived_filling()
189
lex LEX for this thread
190
unit node that contains all SELECT's for derived tables
191
orig_table_list TABLE_LIST for the upper SELECT
194
Derived table is resolved with temporary table. It is created based on the
195
queries defined. After temporary table is filled, if this is not EXPLAIN,
196
then the entire unit / node is deleted. unit is deleted if UNION is used
197
for derived table and node is deleted is it is a simple SELECT.
198
If you use this function, make sure it's not called at prepare.
199
Due to evaluation of LIMIT clause it can not be used at prepared stage.
206
bool mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
208
TABLE *table= orig_table_list->table;
209
SELECT_LEX_UNIT *unit= orig_table_list->derived;
212
/*check that table creation pass without problem and it is derived table */
215
SELECT_LEX *first_select= unit->first_select();
216
select_union *derived_result= orig_table_list->derived_result;
217
SELECT_LEX *save_current_select= lex->current_select;
218
if (unit->is_union())
220
// execute union without clean up
225
unit->set_limit(first_select);
226
if (unit->select_limit_cnt == HA_POS_ERROR)
227
first_select->options&= ~OPTION_FOUND_ROWS;
229
lex->current_select= first_select;
230
res= mysql_select(thd, &first_select->ref_pointer_array,
231
(TABLE_LIST*) first_select->table_list.first,
232
first_select->with_wild,
233
first_select->item_list, first_select->where,
234
(first_select->order_list.elements+
235
first_select->group_list.elements),
236
(ORDER *) first_select->order_list.first,
237
(ORDER *) first_select->group_list.first,
238
first_select->having, (ORDER*) NULL,
239
(first_select->options | thd->options |
241
derived_result, unit, first_select);
247
Here we entirely fix both TABLE_LIST and list of SELECT's as
248
there were no derived tables
250
if (derived_result->flush())
258
lex->current_select= save_current_select;