Drizzled Public API Documentation

sql_derived.cc
1 /* Copyright (C) 2002-2003 MySQL AB
2 
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.
6 
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.
11 
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 /*
17  Derived tables
18  These were introduced by Sinisa <sinisa@mysql.com>
19 */
20 #include <config.h>
21 
22 #include <drizzled/sql_lex.h>
23 #include <drizzled/select_union.h>
24 #include <drizzled/sql_select.h>
25 #include <drizzled/session.h>
26 #include <drizzled/open_tables_state.h>
27 
28 namespace drizzled {
29 
30 /*
31  Call given derived table processor (preparing or filling tables)
32 
33  SYNOPSIS
34  handle_derived()
35  lex LEX for this thread
36  processor procedure of derived table processing
37 
38  RETURN
39  false OK
40  true Error
41 */
42 bool handle_derived(LEX *lex, bool (*processor)(Session*, LEX*, TableList*))
43 {
44  bool res= false;
45  if (lex->derived_tables)
46  {
47  lex->session->derived_tables_processing= true;
48  for (Select_Lex *sl= lex->all_selects_list; sl; sl= sl->next_select_in_list())
49  {
50  for (TableList *cursor= sl->get_table_list(); cursor; cursor= cursor->next_local)
51  {
52  if ((res= (*processor)(lex->session, lex, cursor)))
53  goto out;
54  }
55  if (lex->describe)
56  {
57  /*
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
60  */
61  sl->uncacheable.set(UNCACHEABLE_EXPLAIN);
62  sl->master_unit()->uncacheable.set(UNCACHEABLE_EXPLAIN);
63  }
64  }
65  }
66 out:
67  lex->session->derived_tables_processing= false;
68  return res;
69 }
70 
71 /*
72  Create temporary table structure (but do not fill it)
73 
74  SYNOPSIS
75  derived_prepare()
76  session Thread handle
77  lex LEX for this thread
78  orig_table_list TableList for the upper SELECT
79 
80  IMPLEMENTATION
81  Derived table is resolved with temporary table.
82 
83  After table creation, the above TableList is updated with a new table.
84 
85  This function is called before any command containing derived table
86  is executed.
87 
88  Derived tables is stored in session->derived_tables and freed in
89  close_thread_tables()
90 
91  RETURN
92  false OK
93  true Error
94 */
95 bool derived_prepare(Session *session, LEX *, TableList *orig_table_list)
96 {
97  Select_Lex_Unit *unit= orig_table_list->derived;
98  uint64_t create_options;
99  bool res= false;
100  if (unit)
101  {
102  Select_Lex *first_select= unit->first_select();
103  Table *table= 0;
104  select_union *derived_result;
105 
106  /* prevent name resolving out of derived table */
107  for (Select_Lex *sl= first_select; sl; sl= sl->next_select())
108  sl->context.outer_context= 0;
109 
110  derived_result= new select_union;
111 
112  // Select_Lex_Unit::prepare correctly work for single select
113  if ((res= unit->prepare(session, derived_result, 0)))
114  goto exit;
115 
116  create_options= (first_select->options | session->options | TMP_TABLE_ALL_COLUMNS);
117  /*
118  Temp table is created so that it hounours if UNION without ALL is to be
119  processed
120 
121  As 'distinct' parameter we always pass false (0), because underlying
122  query will control distinct condition by itself. Correct test of
123  distinct underlying query will be is_union &&
124  !unit->union_distinct->next_select() (i.e. it is union and last distinct
125  SELECT is last SELECT of UNION).
126  */
127  if ((res= derived_result->create_result_table(session, &unit->types, false,
128  create_options,
129  orig_table_list->alias)))
130  goto exit;
131 
132  table= derived_result->table;
133 
134 exit:
135  /*
136  if it is preparation PS only or commands that need only VIEW structure
137  then we do not need real data and we can skip execution (and parameters
138  is not defined, too)
139  */
140  if (res)
141  {
142  table= 0;
143  delete derived_result;
144  }
145  else
146  {
147  orig_table_list->derived_result= derived_result;
148  orig_table_list->table= table;
149  orig_table_list->setTableName(table->getShare()->getTableName());
150  table->derived_select_number= first_select->select_number;
151  orig_table_list->setSchemaName("");
152  /* Force read of table stats in the optimizer */
153  table->cursor->info(HA_STATUS_VARIABLE);
154  /* Add new temporary table to list of open derived tables */
155  table->setNext(session->open_tables.getDerivedTables());
156  session->open_tables.setDerivedTables(table);
157  }
158  }
159 
160  return res;
161 }
162 
163 /*
164  fill derived table
165 
166  SYNOPSIS
167  derived_filling()
168  session Thread handle
169  lex LEX for this thread
170  unit node that contains all SELECT's for derived tables
171  orig_table_list TableList for the upper SELECT
172 
173  IMPLEMENTATION
174  Derived table is resolved with temporary table. It is created based on the
175  queries defined. After temporary table is filled, if this is not EXPLAIN,
176  then the entire unit / node is deleted. unit is deleted if UNION is used
177  for derived table and node is deleted is it is a simple SELECT.
178  If you use this function, make sure it's not called at prepare.
179  Due to evaluation of LIMIT clause it can not be used at prepared stage.
180 
181  RETURN
182  false OK
183  true Error
184 */
185 bool derived_filling(Session *session, LEX *lex, TableList *orig_table_list)
186 {
187  Table *table= orig_table_list->table;
188  Select_Lex_Unit *unit= orig_table_list->derived;
189  bool res= false;
190 
191  /*check that table creation pass without problem and it is derived table */
192  if (table && unit)
193  {
194  Select_Lex *first_select= unit->first_select();
195  select_union *derived_result= orig_table_list->derived_result;
196  Select_Lex *save_current_select= lex->current_select;
197  if (unit->is_union())
198  {
199  /* execute union without clean up */
200  res= unit->exec();
201  }
202  else
203  {
204  unit->set_limit(first_select);
205  if (unit->select_limit_cnt == HA_POS_ERROR)
206  first_select->options&= ~OPTION_FOUND_ROWS;
207 
208  lex->current_select= first_select;
209  res= select_query(session, &first_select->ref_pointer_array,
210  (TableList*) first_select->table_list.first,
211  first_select->with_wild,
212  first_select->item_list, first_select->where,
213  (first_select->order_list.elements+
214  first_select->group_list.elements),
215  (Order *) first_select->order_list.first,
216  (Order *) first_select->group_list.first,
217  first_select->having,
218  (first_select->options | session->options | SELECT_NO_UNLOCK),
219  derived_result, unit, first_select);
220  }
221 
222  if (! res)
223  {
224  /*
225  Here we entirely fix both TableList and list of SELECT's as
226  there were no derived tables
227  */
228  if (derived_result->flush())
229  res= true;
230 
231  if (! lex->describe)
232  unit->cleanup();
233  }
234  else
235  unit->cleanup();
236  lex->current_select= save_current_select;
237  }
238  return res;
239 }
240 
241 } /* namespace drizzled */
bool select_query(Session *session, Item ***rref_pointer_array, TableList *tables, uint32_t wild_num, List< Item > &fields, COND *conds, uint32_t og_num, Order *order, Order *group, Item *having, uint64_t select_options, select_result *result, Select_Lex_Unit *unit, Select_Lex *select_lex)
Definition: sql_select.cc:368
static const uint32_t UNCACHEABLE_EXPLAIN
forcing to save JOIN for explain
Definition: definitions.h:190