~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to server/sql_derived.cc

  • Committer: Jay Pipes
  • Date: 2008-07-17 17:54:00 UTC
  • mto: This revision was merged to the branch mainline in revision 182.
  • Revision ID: jay@mysql.com-20080717175400-xm2aazihjra8mdzq
Removal of DBUG from libdrizzle/ - Round 2

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
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 */
 
15
 
15
16
 
16
17
/*
17
18
  Derived tables
18
19
  These were introduced by Sinisa <sinisa@mysql.com>
19
20
*/
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
 
 
27
 
namespace drizzled
28
 
{
 
21
 
 
22
#include "mysql_priv.h"
 
23
#include "sql_select.h"
29
24
 
30
25
/*
31
26
  Call given derived table processor (preparing or filling tables)
32
27
 
33
28
  SYNOPSIS
34
 
    handle_derived()
 
29
    mysql_handle_derived()
35
30
    lex                 LEX for this thread
36
31
    processor           procedure of derived table processing
37
32
 
39
34
    false  OK
40
35
    true   Error
41
36
*/
42
 
bool handle_derived(LEX *lex, bool (*processor)(Session*, LEX*, TableList*))
 
37
bool
 
38
mysql_handle_derived(LEX *lex, bool (*processor)(THD*, LEX*, TABLE_LIST*))
43
39
{
44
40
  bool res= false;
45
41
  if (lex->derived_tables)
46
42
  {
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;
 
45
         sl;
 
46
         sl= sl->next_select_in_list())
49
47
    {
50
 
      for (TableList *cursor= sl->get_table_list(); cursor; cursor= cursor->next_local)
 
48
      for (TABLE_LIST *cursor= sl->get_table_list();
 
49
           cursor;
 
50
           cursor= cursor->next_local)
51
51
      {
52
 
        if ((res= (*processor)(lex->session, lex, cursor)))
53
 
          goto out;
 
52
        if ((res= (*processor)(lex->thd, lex, cursor)))
 
53
          goto out;
54
54
      }
55
55
      if (lex->describe)
56
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);
 
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
63
      }
64
64
    }
65
65
  }
66
66
out:
67
 
  lex->session->derived_tables_processing= false;
 
67
  lex->thd->derived_tables_processing= false;
68
68
  return res;
69
69
}
70
70
 
 
71
 
71
72
/*
72
73
  Create temporary table structure (but do not fill it)
73
74
 
74
75
  SYNOPSIS
75
 
    derived_prepare()
76
 
    session                     Thread handle
 
76
    mysql_derived_prepare()
 
77
    thd                 Thread handle
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
79
80
 
80
81
  IMPLEMENTATION
81
82
    Derived table is resolved with temporary table.
82
83
 
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.
84
85
 
85
86
    This function is called before any command containing derived table
86
87
    is executed.
87
88
 
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()
90
91
 
91
92
  RETURN
92
93
    false  OK
93
94
    true   Error
94
95
*/
95
 
bool derived_prepare(Session *session, LEX *, TableList *orig_table_list)
 
96
 
 
97
bool mysql_derived_prepare(THD *thd, LEX *lex __attribute__((__unused__)),
 
98
                           TABLE_LIST *orig_table_list)
96
99
{
97
 
  Select_Lex_Unit *unit= orig_table_list->derived;
 
100
  SELECT_LEX_UNIT *unit= orig_table_list->derived;
98
101
  uint64_t create_options;
99
102
  bool res= false;
100
103
  if (unit)
101
104
  {
102
 
    Select_Lex *first_select= unit->first_select();
103
 
    Table *table= 0;
 
105
    SELECT_LEX *first_select= unit->first_select();
 
106
    TABLE *table= 0;
104
107
    select_union *derived_result;
105
108
 
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;
109
112
 
110
113
    if (!(derived_result= new select_union))
111
114
      return(true); // out of memory
112
115
 
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)))
115
118
      goto exit;
116
119
 
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);
118
122
    /*
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 
120
124
      processed
121
125
 
122
126
      As 'distinct' parameter we always pass false (0), because underlying
125
129
      !unit->union_distinct->next_select() (i.e. it is union and last distinct
126
130
      SELECT is last SELECT of UNION).
127
131
    */
128
 
    if ((res= derived_result->create_result_table(session, &unit->types, false,
 
132
    if ((res= derived_result->create_result_table(thd, &unit->types, false,
129
133
                                                  create_options,
130
 
                                                  orig_table_list->alias)))
 
134
                                                  orig_table_list->alias,
 
135
                                                  false)))
131
136
      goto exit;
132
137
 
133
138
    table= derived_result->table;
141
146
    if (res)
142
147
    {
143
148
      if (table)
144
 
      {
145
 
        table= 0;
146
 
      }
 
149
        free_tmp_table(thd, table);
147
150
      delete derived_result;
148
151
    }
149
152
    else
150
153
    {
 
154
      if (!thd->fill_derived_tables())
 
155
      {
 
156
        delete derived_result;
 
157
        derived_result= NULL;
 
158
      }
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;
163
172
    }
164
173
  }
165
174
 
166
175
  return(res);
167
176
}
168
177
 
 
178
 
169
179
/*
170
180
  fill derived table
171
181
 
172
182
  SYNOPSIS
173
 
    derived_filling()
174
 
    session                     Thread handle
 
183
    mysql_derived_filling()
 
184
    thd                 Thread handle
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
178
188
 
179
189
  IMPLEMENTATION
180
190
    Derived table is resolved with temporary table. It is created based on the
188
198
    false  OK
189
199
    true   Error
190
200
*/
191
 
bool derived_filling(Session *session, LEX *lex, TableList *orig_table_list)
 
201
 
 
202
bool mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
192
203
{
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;
195
206
  bool res= false;
196
207
 
197
208
  /*check that table creation pass without problem and it is derived table */
198
209
  if (table && unit)
199
210
  {
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())
204
215
    {
205
 
      /* execute union without clean up */
 
216
      // execute union without clean up
206
217
      res= unit->exec();
207
218
    }
208
219
    else
209
220
    {
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;
213
224
 
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 |
 
236
                         SELECT_NO_UNLOCK),
 
237
                        derived_result, unit, first_select);
226
238
    }
227
239
 
228
 
    if (! res)
 
240
    if (!res)
229
241
    {
230
242
      /*
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
233
245
      */
234
246
      if (derived_result->flush())
235
247
        res= true;
236
248
 
237
 
      if (! lex->describe)
 
249
      if (!lex->describe)
238
250
        unit->cleanup();
239
251
    }
240
252
    else
243
255
  }
244
256
  return res;
245
257
}
246
 
 
247
 
} /* namespace drizzled */