~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/table_list.cc

  • Committer: Stewart Smith
  • Date: 2008-07-13 06:56:15 UTC
  • mto: (210.1.1 drizzle)
  • mto: This revision was merged to the branch mainline in revision 211.
  • Revision ID: stewart@flamingspork.com-20080713065615-vzok75kgnnviokl9
Move MD5() into a UDF

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 
16
 
#include "config.h"
17
 
 
18
 
#include <string>
19
 
 
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"
27
 
#include "drizzled/strfunc.h"
28
 
 
29
 
using namespace std;
30
 
 
31
 
namespace drizzled
32
 
{
33
 
 
34
 
class Item;
35
 
class Item_field;
36
 
 
37
 
uint32_t TableList::create_table_def_key(char *key)
38
 
{
39
 
  return TableShare::createKey(key, db, table_name);
40
 
}
41
 
 
42
 
bool TableList::set_insert_values(memory::Root *mem_root)
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
 
{
71
 
  return derived || (create && !table->getDBStat()) || !table;
72
 
}
73
 
 
74
 
/*
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
 
 */
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
 
/*
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
 
 */
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
 
      }
299
 
      str->append_identifier(table_name, table_name_length);
300
 
      cmp_name= table_name;
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
 
}
331
 
 
332
 
} /* namespace drizzled */