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 */
18
These were introduced by Sinisa <sinisa@mysql.com>
20
#include <drizzled/server_includes.h>
21
#include <drizzled/sql_select.h>
24
Call given derived table processor (preparing or filling tables)
27
mysql_handle_derived()
28
lex LEX for this thread
29
processor procedure of derived table processing
36
mysql_handle_derived(LEX *lex, bool (*processor)(THD*, LEX*, TableList*))
39
if (lex->derived_tables)
41
lex->thd->derived_tables_processing= true;
42
for (SELECT_LEX *sl= lex->all_selects_list;
44
sl= sl->next_select_in_list())
46
for (TableList *cursor= sl->get_table_list();
48
cursor= cursor->next_local)
50
if ((res= (*processor)(lex->thd, lex, cursor)))
56
Force join->join_tmp creation, because we will use this JOIN
57
twice for EXPLAIN and we have to have unchanged join for EXPLAINing
59
sl->uncacheable|= UNCACHEABLE_EXPLAIN;
60
sl->master_unit()->uncacheable|= UNCACHEABLE_EXPLAIN;
65
lex->thd->derived_tables_processing= false;
71
Create temporary table structure (but do not fill it)
74
mysql_derived_prepare()
76
lex LEX for this thread
77
orig_table_list TableList for the upper SELECT
80
Derived table is resolved with temporary table.
82
After table creation, the above TableList is updated with a new table.
84
This function is called before any command containing derived table
87
Derived tables is stored in thd->derived_tables and freed in
95
bool mysql_derived_prepare(THD *thd, LEX *lex __attribute__((unused)),
96
TableList *orig_table_list)
98
SELECT_LEX_UNIT *unit= orig_table_list->derived;
99
uint64_t create_options;
103
SELECT_LEX *first_select= unit->first_select();
105
select_union *derived_result;
107
/* prevent name resolving out of derived table */
108
for (SELECT_LEX *sl= first_select; sl; sl= sl->next_select())
109
sl->context.outer_context= 0;
111
if (!(derived_result= new select_union))
112
return(true); // out of memory
114
// st_select_lex_unit::prepare correctly work for single select
115
if ((res= unit->prepare(thd, derived_result, 0)))
118
create_options= (first_select->options | thd->options |
119
TMP_TABLE_ALL_COLUMNS);
121
Temp table is created so that it hounours if UNION without ALL is to be
124
As 'distinct' parameter we always pass false (0), because underlying
125
query will control distinct condition by itself. Correct test of
126
distinct underlying query will be is_union &&
127
!unit->union_distinct->next_select() (i.e. it is union and last distinct
128
SELECT is last SELECT of UNION).
130
if ((res= derived_result->create_result_table(thd, &unit->types, false,
132
orig_table_list->alias,
136
table= derived_result->table;
140
if it is preparation PS only or commands that need only VIEW structure
141
then we do not need real data and we can skip execution (and parameters
147
table->free_tmp_table(thd);
148
delete derived_result;
152
if (!thd->fill_derived_tables())
154
delete derived_result;
155
derived_result= NULL;
157
orig_table_list->derived_result= derived_result;
158
orig_table_list->table= table;
159
orig_table_list->table_name= table->s->table_name.str;
160
orig_table_list->table_name_length= table->s->table_name.length;
161
table->derived_select_number= first_select->select_number;
162
table->s->tmp_table= NON_TRANSACTIONAL_TMP_TABLE;
163
orig_table_list->db= (char *)"";
164
orig_table_list->db_length= 0;
165
// Force read of table stats in the optimizer
166
table->file->info(HA_STATUS_VARIABLE);
167
/* Add new temporary table to list of open derived tables */
168
table->next= thd->derived_tables;
169
thd->derived_tables= table;
181
mysql_derived_filling()
183
lex LEX for this thread
184
unit node that contains all SELECT's for derived tables
185
orig_table_list TableList for the upper SELECT
188
Derived table is resolved with temporary table. It is created based on the
189
queries defined. After temporary table is filled, if this is not EXPLAIN,
190
then the entire unit / node is deleted. unit is deleted if UNION is used
191
for derived table and node is deleted is it is a simple SELECT.
192
If you use this function, make sure it's not called at prepare.
193
Due to evaluation of LIMIT clause it can not be used at prepared stage.
200
bool mysql_derived_filling(THD *thd, LEX *lex, TableList *orig_table_list)
202
Table *table= orig_table_list->table;
203
SELECT_LEX_UNIT *unit= orig_table_list->derived;
206
/*check that table creation pass without problem and it is derived table */
209
SELECT_LEX *first_select= unit->first_select();
210
select_union *derived_result= orig_table_list->derived_result;
211
SELECT_LEX *save_current_select= lex->current_select;
212
if (unit->is_union())
214
// execute union without clean up
219
unit->set_limit(first_select);
220
if (unit->select_limit_cnt == HA_POS_ERROR)
221
first_select->options&= ~OPTION_FOUND_ROWS;
223
lex->current_select= first_select;
224
res= mysql_select(thd, &first_select->ref_pointer_array,
225
(TableList*) first_select->table_list.first,
226
first_select->with_wild,
227
first_select->item_list, first_select->where,
228
(first_select->order_list.elements+
229
first_select->group_list.elements),
230
(order_st *) first_select->order_list.first,
231
(order_st *) first_select->group_list.first,
232
first_select->having, (order_st*) NULL,
233
(first_select->options | thd->options |
235
derived_result, unit, first_select);
241
Here we entirely fix both TableList and list of SELECT's as
242
there were no derived tables
244
if (derived_result->flush())
252
lex->current_select= save_current_select;