12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
18
19
These were introduced by Sinisa <sinisa@mysql.com>
22
#include <drizzled/sql_lex.h>
23
#include <drizzled/select_union.h>
24
#include <drizzled/sql_select.h>
25
#include <drizzled/session.h>
22
#include "mysql_priv.h"
23
#include "sql_select.h"
31
26
Call given derived table processor (preparing or filling tables)
29
mysql_handle_derived()
35
30
lex LEX for this thread
36
31
processor procedure of derived table processing
42
bool handle_derived(LEX *lex, bool (*processor)(Session*, LEX*, TableList*))
38
mysql_handle_derived(LEX *lex, bool (*processor)(THD*, LEX*, TABLE_LIST*))
45
41
if (lex->derived_tables)
47
lex->session->derived_tables_processing= true;
48
for (Select_Lex *sl= lex->all_selects_list; sl; sl= sl->next_select_in_list())
43
lex->thd->derived_tables_processing= true;
44
for (SELECT_LEX *sl= lex->all_selects_list;
46
sl= sl->next_select_in_list())
50
for (TableList *cursor= sl->get_table_list(); cursor; cursor= cursor->next_local)
48
for (TABLE_LIST *cursor= sl->get_table_list();
50
cursor= cursor->next_local)
52
if ((res= (*processor)(lex->session, lex, cursor)))
52
if ((res= (*processor)(lex->thd, lex, cursor)))
58
Force join->join_tmp creation, because we will use this JOIN
59
twice for EXPLAIN and we have to have unchanged join for EXPLAINing
61
sl->uncacheable.set(UNCACHEABLE_EXPLAIN);
62
sl->master_unit()->uncacheable.set(UNCACHEABLE_EXPLAIN);
58
Force join->join_tmp creation, because we will use this JOIN
59
twice for EXPLAIN and we have to have unchanged join for EXPLAINing
61
sl->uncacheable|= UNCACHEABLE_EXPLAIN;
62
sl->master_unit()->uncacheable|= UNCACHEABLE_EXPLAIN;
67
lex->session->derived_tables_processing= false;
67
lex->thd->derived_tables_processing= false;
72
73
Create temporary table structure (but do not fill it)
76
mysql_derived_prepare()
77
78
lex LEX for this thread
78
orig_table_list TableList for the upper SELECT
79
orig_table_list TABLE_LIST for the upper SELECT
81
82
Derived table is resolved with temporary table.
83
After table creation, the above TableList is updated with a new table.
84
After table creation, the above TABLE_LIST is updated with a new table.
85
86
This function is called before any command containing derived table
88
Derived tables is stored in session->derived_tables and freed in
89
Derived tables is stored in thd->derived_tables and freed in
89
90
close_thread_tables()
95
bool derived_prepare(Session *session, LEX *, TableList *orig_table_list)
97
bool mysql_derived_prepare(THD *thd, LEX *lex __attribute__((__unused__)),
98
TABLE_LIST *orig_table_list)
97
Select_Lex_Unit *unit= orig_table_list->derived;
100
SELECT_LEX_UNIT *unit= orig_table_list->derived;
98
101
uint64_t create_options;
102
Select_Lex *first_select= unit->first_select();
105
SELECT_LEX *first_select= unit->first_select();
104
107
select_union *derived_result;
106
109
/* prevent name resolving out of derived table */
107
for (Select_Lex *sl= first_select; sl; sl= sl->next_select())
110
for (SELECT_LEX *sl= first_select; sl; sl= sl->next_select())
108
111
sl->context.outer_context= 0;
110
113
if (!(derived_result= new select_union))
111
114
return(true); // out of memory
113
// Select_Lex_Unit::prepare correctly work for single select
114
if ((res= unit->prepare(session, derived_result, 0)))
116
// st_select_lex_unit::prepare correctly work for single select
117
if ((res= unit->prepare(thd, derived_result, 0)))
117
create_options= (first_select->options | session->options | TMP_TABLE_ALL_COLUMNS);
120
create_options= (first_select->options | thd->options |
121
TMP_TABLE_ALL_COLUMNS);
119
Temp table is created so that it hounours if UNION without ALL is to be
123
Temp table is created so that it hounours if UNION without ALL is to be
122
126
As 'distinct' parameter we always pass false (0), because underlying
149
free_tmp_table(thd, table);
147
150
delete derived_result;
154
if (!thd->fill_derived_tables())
156
delete derived_result;
157
derived_result= NULL;
151
159
orig_table_list->derived_result= derived_result;
152
160
orig_table_list->table= table;
153
orig_table_list->setTableName(const_cast<char *>(table->getShare()->getTableName()));
154
orig_table_list->table_name_length= table->getShare()->getTableNameSize();
161
orig_table_list->table_name= table->s->table_name.str;
162
orig_table_list->table_name_length= table->s->table_name.length;
155
163
table->derived_select_number= first_select->select_number;
156
orig_table_list->setSchemaName((char *)"");
164
table->s->tmp_table= NON_TRANSACTIONAL_TMP_TABLE;
165
orig_table_list->db= (char *)"";
157
166
orig_table_list->db_length= 0;
158
/* Force read of table stats in the optimizer */
159
table->cursor->info(HA_STATUS_VARIABLE);
167
// Force read of table stats in the optimizer
168
table->file->info(HA_STATUS_VARIABLE);
160
169
/* Add new temporary table to list of open derived tables */
161
table->setNext(session->getDerivedTables());
162
session->setDerivedTables(table);
170
table->next= thd->derived_tables;
171
thd->derived_tables= table;
170
180
fill derived table
174
session Thread handle
183
mysql_derived_filling()
175
185
lex LEX for this thread
176
186
unit node that contains all SELECT's for derived tables
177
orig_table_list TableList for the upper SELECT
187
orig_table_list TABLE_LIST for the upper SELECT
180
190
Derived table is resolved with temporary table. It is created based on the
191
bool derived_filling(Session *session, LEX *lex, TableList *orig_table_list)
202
bool mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
193
Table *table= orig_table_list->table;
194
Select_Lex_Unit *unit= orig_table_list->derived;
204
TABLE *table= orig_table_list->table;
205
SELECT_LEX_UNIT *unit= orig_table_list->derived;
197
208
/*check that table creation pass without problem and it is derived table */
198
209
if (table && unit)
200
Select_Lex *first_select= unit->first_select();
211
SELECT_LEX *first_select= unit->first_select();
201
212
select_union *derived_result= orig_table_list->derived_result;
202
Select_Lex *save_current_select= lex->current_select;
213
SELECT_LEX *save_current_select= lex->current_select;
203
214
if (unit->is_union())
205
/* execute union without clean up */
216
// execute union without clean up
206
217
res= unit->exec();
210
221
unit->set_limit(first_select);
211
222
if (unit->select_limit_cnt == HA_POS_ERROR)
212
first_select->options&= ~OPTION_FOUND_ROWS;
223
first_select->options&= ~OPTION_FOUND_ROWS;
214
225
lex->current_select= first_select;
215
res= select_query(session, &first_select->ref_pointer_array,
216
(TableList*) first_select->table_list.first,
217
first_select->with_wild,
218
first_select->item_list, first_select->where,
219
(first_select->order_list.elements+
220
first_select->group_list.elements),
221
(Order *) first_select->order_list.first,
222
(Order *) first_select->group_list.first,
223
first_select->having,
224
(first_select->options | session->options | SELECT_NO_UNLOCK),
225
derived_result, unit, first_select);
226
res= mysql_select(thd, &first_select->ref_pointer_array,
227
(TABLE_LIST*) first_select->table_list.first,
228
first_select->with_wild,
229
first_select->item_list, first_select->where,
230
(first_select->order_list.elements+
231
first_select->group_list.elements),
232
(ORDER *) first_select->order_list.first,
233
(ORDER *) first_select->group_list.first,
234
first_select->having, (ORDER*) NULL,
235
(first_select->options | thd->options |
237
derived_result, unit, first_select);
231
Here we entirely fix both TableList and list of SELECT's as
243
Here we entirely fix both TABLE_LIST and list of SELECT's as
232
244
there were no derived tables
234
246
if (derived_result->flush())