~drizzle-trunk/drizzle/development

1054.1.7 by Brian Aker
Refactor TableList methods.
1
/* Copyright (C) 2009 Sun Microsystems
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
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
14
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
1054.1.7 by Brian Aker
Refactor TableList methods.
15
1241.9.36 by Monty Taylor
ZOMG. I deleted drizzled/server_includes.h.
16
#include "config.h"
1054.1.7 by Brian Aker
Refactor TableList methods.
17
18
#include <string>
19
1122.2.13 by Monty Taylor
Header cleanup.
20
#include "drizzled/error.h"
21
#include "drizzled/table_list.h"
22
#include "drizzled/item.h"
23
#include "drizzled/item/field.h"
24
#include "drizzled/nested_join.h"
25
#include "drizzled/sql_lex.h"
26
#include "drizzled/sql_select.h"
1241.9.12 by Monty Taylor
Trims more out of server_includes.h.
27
#include "drizzled/strfunc.h"
1122.2.13 by Monty Taylor
Header cleanup.
28
1054.1.7 by Brian Aker
Refactor TableList methods.
29
using namespace std;
30
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
31
namespace drizzled
32
{
33
1054.1.7 by Brian Aker
Refactor TableList methods.
34
class Item;
35
class Item_field;
36
1672.3.5 by Brian Aker
This replaces the allocation we do for insert/update.
37
bool TableList::set_insert_values(memory::Root *)
1054.1.7 by Brian Aker
Refactor TableList methods.
38
{
39
  if (table)
40
  {
1672.3.5 by Brian Aker
This replaces the allocation we do for insert/update.
41
    table->insert_values.resize(table->getShare()->rec_buff_length);
1054.1.7 by Brian Aker
Refactor TableList methods.
42
  }
43
44
  return false;
45
}
46
47
bool TableList::is_leaf_for_name_resolution()
48
{
49
  return (is_natural_join || is_join_columns_complete || !nested_join);
50
}
51
52
TableList *TableList::find_underlying_table(Table *table_to_find)
53
{
54
  /* is this real table and table which we are looking for? */
55
  if (table == table_to_find)
56
    return this;
57
58
  return NULL;
59
}
60
1637.1.3 by Brian Aker
This fixes the parser to no longer do the bad syntax around the cross join
61
bool TableList::isCartesian() const
62
{
63
  return false;
64
}
65
1054.1.7 by Brian Aker
Refactor TableList methods.
66
bool TableList::placeholder()
67
{
1225.1.20 by Padraig O'Sullivan
Removed all remnants of schema_table from the TableList class. This cleans up a bunch of code.
68
  return derived || (create && !table->getDBStat()) || !table;
1054.1.7 by Brian Aker
Refactor TableList methods.
69
}
70
71
/*
1188.1.2 by Jay Pipes
Style and doxygen cleanup ONLY. Moves method documentation from source into header files. Removes TAB characters and cleans up indentation.
72
 * The right-most child of a nested table reference is the first
73
 * element in the list of children because the children are inserted
74
 * in reverse order.
75
 */
1054.1.7 by Brian Aker
Refactor TableList methods.
76
TableList *TableList::last_leaf_for_name_resolution()
77
{
78
  TableList *cur_table_ref= this;
79
  nested_join_st *cur_nested_join;
80
81
  if (is_leaf_for_name_resolution())
82
    return this;
83
  assert(nested_join);
84
85
  for (cur_nested_join= nested_join;
86
       cur_nested_join;
87
       cur_nested_join= cur_table_ref->nested_join)
88
  {
89
    cur_table_ref= cur_nested_join->join_list.head();
90
    /*
91
      If the current nested is a RIGHT JOIN, the operands in
92
      'join_list' are in reverse order, thus the last operand is in the
93
      end of the list.
94
    */
95
    if ((cur_table_ref->outer_join & JOIN_TYPE_RIGHT))
96
    {
97
      List_iterator_fast<TableList> it(cur_nested_join->join_list);
98
      TableList *next;
99
      cur_table_ref= it++;
100
      while ((next= it++))
101
        cur_table_ref= next;
102
    }
103
    if (cur_table_ref->is_leaf_for_name_resolution())
104
      break;
105
  }
106
  return cur_table_ref;
107
}
108
109
/*
1188.1.2 by Jay Pipes
Style and doxygen cleanup ONLY. Moves method documentation from source into header files. Removes TAB characters and cleans up indentation.
110
 * The left-most child of a nested table reference is the last element
111
 * in the list of children because the children are inserted in
112
 * reverse order.
113
 */
1054.1.7 by Brian Aker
Refactor TableList methods.
114
TableList *TableList::first_leaf_for_name_resolution()
115
{
116
  TableList *cur_table_ref= NULL;
117
  nested_join_st *cur_nested_join;
118
119
  if (is_leaf_for_name_resolution())
120
    return this;
121
  assert(nested_join);
122
123
  for (cur_nested_join= nested_join;
124
       cur_nested_join;
125
       cur_nested_join= cur_table_ref->nested_join)
126
  {
127
    List_iterator_fast<TableList> it(cur_nested_join->join_list);
128
    cur_table_ref= it++;
129
    /*
130
      If the current nested join is a RIGHT JOIN, the operands in
131
      'join_list' are in reverse order, thus the first operand is
132
      already at the front of the list. Otherwise the first operand
133
      is in the end of the list of join operands.
134
    */
135
    if (!(cur_table_ref->outer_join & JOIN_TYPE_RIGHT))
136
    {
137
      TableList *next;
138
      while ((next= it++))
139
        cur_table_ref= next;
140
    }
141
    if (cur_table_ref->is_leaf_for_name_resolution())
142
      break;
143
  }
144
  return cur_table_ref;
145
}
146
147
Item_subselect *TableList::containing_subselect()
148
{
149
  return (select_lex ? select_lex->master_unit()->item : 0);
150
}
151
152
bool TableList::process_index_hints(Table *tbl)
153
{
154
  /* initialize the result variables */
155
  tbl->keys_in_use_for_query= tbl->keys_in_use_for_group_by=
1574 by Brian Aker
Rollup patch for hiding tableshare.
156
    tbl->keys_in_use_for_order_by= tbl->getShare()->keys_in_use;
1054.1.7 by Brian Aker
Refactor TableList methods.
157
158
  /* index hint list processing */
159
  if (index_hints)
160
  {
161
    key_map index_join[INDEX_HINT_FORCE + 1];
162
    key_map index_order[INDEX_HINT_FORCE + 1];
163
    key_map index_group[INDEX_HINT_FORCE + 1];
164
    Index_hint *hint;
165
    int type;
166
    bool have_empty_use_join= false, have_empty_use_order= false,
167
         have_empty_use_group= false;
168
    List_iterator <Index_hint> iter(*index_hints);
169
170
    /* initialize temporary variables used to collect hints of each kind */
171
    for (type= INDEX_HINT_IGNORE; type <= INDEX_HINT_FORCE; type++)
172
    {
173
      index_join[type].reset();
174
      index_order[type].reset();
175
      index_group[type].reset();
176
    }
177
178
    /* iterate over the hints list */
179
    while ((hint= iter++))
180
    {
1527.1.3 by Brian Aker
This is:
181
      uint32_t pos= 0;
1054.1.7 by Brian Aker
Refactor TableList methods.
182
183
      /* process empty USE INDEX () */
184
      if (hint->type == INDEX_HINT_USE && !hint->key_name.str)
185
      {
186
        if (hint->clause & INDEX_HINT_MASK_JOIN)
187
        {
188
          index_join[hint->type].reset();
189
          have_empty_use_join= true;
190
        }
191
        if (hint->clause & INDEX_HINT_MASK_ORDER)
192
        {
193
          index_order[hint->type].reset();
194
          have_empty_use_order= true;
195
        }
196
        if (hint->clause & INDEX_HINT_MASK_GROUP)
197
        {
198
          index_group[hint->type].reset();
199
          have_empty_use_group= true;
200
        }
201
        continue;
202
      }
203
204
      /*
205
        Check if an index with the given name exists and get his offset in
206
        the keys bitmask for the table
207
      */
1574 by Brian Aker
Rollup patch for hiding tableshare.
208
      if (not tbl->getShare()->doesKeyNameExist(hint->key_name.str, hint->key_name.length, pos))
1054.1.7 by Brian Aker
Refactor TableList methods.
209
      {
210
        my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), hint->key_name.str, alias);
211
        return 1;
212
      }
213
      /* add to the appropriate clause mask */
214
      if (hint->clause & INDEX_HINT_MASK_JOIN)
215
        index_join[hint->type].set(pos);
216
      if (hint->clause & INDEX_HINT_MASK_ORDER)
217
        index_order[hint->type].set(pos);
218
      if (hint->clause & INDEX_HINT_MASK_GROUP)
219
        index_group[hint->type].set(pos);
220
    }
221
222
    /* cannot mix USE INDEX and FORCE INDEX */
223
    if ((index_join[INDEX_HINT_FORCE].any() ||
224
         index_order[INDEX_HINT_FORCE].any() ||
225
         index_group[INDEX_HINT_FORCE].any()) &&
226
        (index_join[INDEX_HINT_USE].any() ||  have_empty_use_join ||
227
         index_order[INDEX_HINT_USE].any() || have_empty_use_order ||
228
         index_group[INDEX_HINT_USE].any() || have_empty_use_group))
229
    {
230
      my_error(ER_WRONG_USAGE, MYF(0), index_hint_type_name[INDEX_HINT_USE],
231
               index_hint_type_name[INDEX_HINT_FORCE]);
232
      return 1;
233
    }
234
235
    /* process FORCE INDEX as USE INDEX with a flag */
236
    if (index_join[INDEX_HINT_FORCE].any() ||
237
        index_order[INDEX_HINT_FORCE].any() ||
238
        index_group[INDEX_HINT_FORCE].any())
239
    {
240
      tbl->force_index= true;
241
      index_join[INDEX_HINT_USE]|= index_join[INDEX_HINT_FORCE];
242
      index_order[INDEX_HINT_USE]|= index_order[INDEX_HINT_FORCE];
243
      index_group[INDEX_HINT_USE]|= index_group[INDEX_HINT_FORCE];
244
    }
245
246
    /* apply USE INDEX */
247
    if (index_join[INDEX_HINT_USE].any() || have_empty_use_join)
248
      tbl->keys_in_use_for_query&= index_join[INDEX_HINT_USE];
249
    if (index_order[INDEX_HINT_USE].any() || have_empty_use_order)
250
      tbl->keys_in_use_for_order_by&= index_order[INDEX_HINT_USE];
251
    if (index_group[INDEX_HINT_USE].any() || have_empty_use_group)
252
      tbl->keys_in_use_for_group_by&= index_group[INDEX_HINT_USE];
253
254
    /* apply IGNORE INDEX */
255
    key_map_subtract(tbl->keys_in_use_for_query, index_join[INDEX_HINT_IGNORE]);
256
    key_map_subtract(tbl->keys_in_use_for_order_by, index_order[INDEX_HINT_IGNORE]);
257
    key_map_subtract(tbl->keys_in_use_for_group_by, index_group[INDEX_HINT_IGNORE]);
258
  }
259
260
  /* make sure covering_keys don't include indexes disabled with a hint */
261
  tbl->covering_keys&= tbl->keys_in_use_for_query;
262
  return 0;
263
}
264
265
void TableList::print(Session *session, String *str, enum_query_type query_type)
266
{
267
  if (nested_join)
268
  {
269
    str->append('(');
270
    print_join(session, str, &nested_join->join_list, query_type);
271
    str->append(')');
272
  }
273
  else
274
  {
275
    const char *cmp_name;                         // Name to compare with alias
276
    if (derived)
277
    {
278
      // A derived table
279
      str->append('(');
280
      derived->print(str, query_type);
281
      str->append(')');
282
      cmp_name= "";                               // Force printing of alias
283
    }
284
    else
285
    {
286
      // A normal table
287
      {
288
        str->append_identifier(db, db_length);
289
        str->append('.');
290
      }
1225.1.20 by Padraig O'Sullivan
Removed all remnants of schema_table from the TableList class. This cleans up a bunch of code.
291
      str->append_identifier(table_name, table_name_length);
292
      cmp_name= table_name;
1054.1.7 by Brian Aker
Refactor TableList methods.
293
    }
294
    if (my_strcasecmp(table_alias_charset, cmp_name, alias))
295
    {
296
297
      if (alias && alias[0])
298
      {
299
        str->append(' ');
300
301
        string t_alias(alias);
302
        transform(t_alias.begin(), t_alias.end(),
303
                  t_alias.begin(), ::tolower);
304
305
        str->append_identifier(t_alias.c_str(), t_alias.length());
306
      }
307
308
    }
309
310
    if (index_hints)
311
    {
312
      List_iterator<Index_hint> it(*index_hints);
313
      Index_hint *hint;
314
315
      while ((hint= it++))
316
      {
317
        str->append (STRING_WITH_LEN(" "));
318
        hint->print (session, str);
319
      }
320
    }
321
  }
322
}
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
323
324
} /* namespace drizzled */