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