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