~drizzle-trunk/drizzle/development

1 by brian
clean slate
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
17
/*
18
  Derived tables
19
  These were introduced by Sinisa <sinisa@mysql.com>
20
*/
21
22
#include "mysql_priv.h"
23
#include "sql_select.h"
24
25
/*
26
  Call given derived table processor (preparing or filling tables)
27
28
  SYNOPSIS
29
    mysql_handle_derived()
30
    lex                 LEX for this thread
31
    processor           procedure of derived table processing
32
33
  RETURN
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
34
    false  OK
35
    true   Error
1 by brian
clean slate
36
*/
37
bool
38
mysql_handle_derived(LEX *lex, bool (*processor)(THD*, LEX*, TABLE_LIST*))
39
{
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
40
  bool res= false;
1 by brian
clean slate
41
  if (lex->derived_tables)
42
  {
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
43
    lex->thd->derived_tables_processing= true;
1 by brian
clean slate
44
    for (SELECT_LEX *sl= lex->all_selects_list;
45
	 sl;
46
	 sl= sl->next_select_in_list())
47
    {
48
      for (TABLE_LIST *cursor= sl->get_table_list();
49
	   cursor;
50
	   cursor= cursor->next_local)
51
      {
52
	if ((res= (*processor)(lex->thd, 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|= UNCACHEABLE_EXPLAIN;
62
	sl->master_unit()->uncacheable|= UNCACHEABLE_EXPLAIN;
63
      }
64
    }
65
  }
66
out:
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
67
  lex->thd->derived_tables_processing= false;
1 by brian
clean slate
68
  return res;
69
}
70
71
72
/*
73
  Create temporary table structure (but do not fill it)
74
75
  SYNOPSIS
76
    mysql_derived_prepare()
77
    thd			Thread handle
78
    lex                 LEX for this thread
79
    orig_table_list     TABLE_LIST for the upper SELECT
80
81
  IMPLEMENTATION
82
    Derived table is resolved with temporary table.
83
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
87
    is executed.
88
89
    Derived tables is stored in thd->derived_tables and freed in
90
    close_thread_tables()
91
92
  RETURN
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
93
    false  OK
94
    true   Error
1 by brian
clean slate
95
*/
96
77.1.46 by Monty Taylor
Finished the warnings work!
97
bool mysql_derived_prepare(THD *thd, LEX *lex __attribute__((__unused__)),
98
                           TABLE_LIST *orig_table_list)
1 by brian
clean slate
99
{
100
  SELECT_LEX_UNIT *unit= orig_table_list->derived;
101
  ulonglong create_options;
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
102
  bool res= false;
1 by brian
clean slate
103
  if (unit)
104
  {
105
    SELECT_LEX *first_select= unit->first_select();
106
    TABLE *table= 0;
107
    select_union *derived_result;
108
109
    /* prevent name resolving out of derived table */
110
    for (SELECT_LEX *sl= first_select; sl; sl= sl->next_select())
111
      sl->context.outer_context= 0;
112
113
    if (!(derived_result= new select_union))
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
114
      return(true); // out of memory
1 by brian
clean slate
115
116
    // st_select_lex_unit::prepare correctly work for single select
117
    if ((res= unit->prepare(thd, derived_result, 0)))
118
      goto exit;
119
120
    create_options= (first_select->options | thd->options |
121
                     TMP_TABLE_ALL_COLUMNS);
122
    /*
123
      Temp table is created so that it hounours if UNION without ALL is to be 
124
      processed
125
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
126
      As 'distinct' parameter we always pass false (0), because underlying
1 by brian
clean slate
127
      query will control distinct condition by itself. Correct test of
128
      distinct underlying query will be is_union &&
129
      !unit->union_distinct->next_select() (i.e. it is union and last distinct
130
      SELECT is last SELECT of UNION).
131
    */
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
132
    if ((res= derived_result->create_result_table(thd, &unit->types, false,
1 by brian
clean slate
133
                                                  create_options,
134
                                                  orig_table_list->alias,
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
135
                                                  false)))
1 by brian
clean slate
136
      goto exit;
137
138
    table= derived_result->table;
139
140
exit:
141
    /*
142
      if it is preparation PS only or commands that need only VIEW structure
143
      then we do not need real data and we can skip execution (and parameters
144
      is not defined, too)
145
    */
146
    if (res)
147
    {
148
      if (table)
149
	free_tmp_table(thd, table);
150
      delete derived_result;
151
    }
152
    else
153
    {
154
      if (!thd->fill_derived_tables())
155
      {
156
	delete derived_result;
157
	derived_result= NULL;
158
      }
159
      orig_table_list->derived_result= derived_result;
160
      orig_table_list->table= table;
161
      orig_table_list->table_name=        table->s->table_name.str;
162
      orig_table_list->table_name_length= table->s->table_name.length;
163
      table->derived_select_number= first_select->select_number;
164
      table->s->tmp_table= NON_TRANSACTIONAL_TMP_TABLE;
165
      orig_table_list->db= (char *)"";
166
      orig_table_list->db_length= 0;
167
      // Force read of table stats in the optimizer
168
      table->file->info(HA_STATUS_VARIABLE);
169
      /* Add new temporary table to list of open derived tables */
170
      table->next= thd->derived_tables;
171
      thd->derived_tables= table;
172
    }
173
  }
174
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
175
  return(res);
1 by brian
clean slate
176
}
177
178
179
/*
180
  fill derived table
181
182
  SYNOPSIS
183
    mysql_derived_filling()
184
    thd			Thread handle
185
    lex                 LEX for this thread
186
    unit                node that contains all SELECT's for derived tables
187
    orig_table_list     TABLE_LIST for the upper SELECT
188
189
  IMPLEMENTATION
190
    Derived table is resolved with temporary table. It is created based on the
191
    queries defined. After temporary table is filled, if this is not EXPLAIN,
192
    then the entire unit / node is deleted. unit is deleted if UNION is used
193
    for derived table and node is deleted is it is a  simple SELECT.
194
    If you use this function, make sure it's not called at prepare.
195
    Due to evaluation of LIMIT clause it can not be used at prepared stage.
196
197
  RETURN
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
198
    false  OK
199
    true   Error
1 by brian
clean slate
200
*/
201
202
bool mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
203
{
204
  TABLE *table= orig_table_list->table;
205
  SELECT_LEX_UNIT *unit= orig_table_list->derived;
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
206
  bool res= false;
1 by brian
clean slate
207
208
  /*check that table creation pass without problem and it is derived table */
209
  if (table && unit)
210
  {
211
    SELECT_LEX *first_select= unit->first_select();
212
    select_union *derived_result= orig_table_list->derived_result;
213
    SELECT_LEX *save_current_select= lex->current_select;
214
    if (unit->is_union())
215
    {
216
      // execute union without clean up
217
      res= unit->exec();
218
    }
219
    else
220
    {
221
      unit->set_limit(first_select);
222
      if (unit->select_limit_cnt == HA_POS_ERROR)
223
	first_select->options&= ~OPTION_FOUND_ROWS;
224
225
      lex->current_select= 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 |
236
			 SELECT_NO_UNLOCK),
237
			derived_result, unit, first_select);
238
    }
239
240
    if (!res)
241
    {
242
      /*
243
        Here we entirely fix both TABLE_LIST and list of SELECT's as
244
        there were no derived tables
245
      */
246
      if (derived_result->flush())
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
247
        res= true;
1 by brian
clean slate
248
249
      if (!lex->describe)
250
        unit->cleanup();
251
    }
252
    else
253
      unit->cleanup();
254
    lex->current_select= save_current_select;
255
  }
256
  return res;
257
}