~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/table_list.cc

  • Committer: Monty Taylor
  • Date: 2008-08-01 22:33:44 UTC
  • mto: (236.1.42 codestyle)
  • mto: This revision was merged to the branch mainline in revision 261.
  • Revision ID: monty@inaugust.com-20080801223344-vzhlflfmtijp1imv
First pass at gettexizing the error messages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2009 Sun Microsystems, Inc.
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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  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
 
bool TableList::set_insert_values(memory::Root *)
38
 
{
39
 
  if (table)
40
 
  {
41
 
    table->insert_values.resize(table->getShare()->rec_buff_length);
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
 
 
61
 
bool TableList::isCartesian() const
62
 
{
63
 
  return false;
64
 
}
65
 
 
66
 
bool TableList::placeholder()
67
 
{
68
 
  return derived || (create && !table->getDBStat()) || !table;
69
 
}
70
 
 
71
 
/*
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
 
 */
76
 
TableList *TableList::last_leaf_for_name_resolution()
77
 
{
78
 
  TableList *cur_table_ref= this;
79
 
  NestedJoin *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<TableList>::iterator it(cur_nested_join->join_list.begin());
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
 
/*
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
 
 */
114
 
TableList *TableList::first_leaf_for_name_resolution()
115
 
{
116
 
  TableList *cur_table_ref= NULL;
117
 
  NestedJoin *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<TableList>::iterator it(cur_nested_join->join_list.begin());
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=
156
 
    tbl->keys_in_use_for_order_by= tbl->getShare()->keys_in_use;
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->begin());
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
 
    {
181
 
      uint32_t pos= 0;
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
 
      */
208
 
      if (not tbl->getShare()->doesKeyNameExist(hint->key_name.str, hint->key_name.length, pos))
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
 
      }
291
 
      str->append_identifier(table_name, table_name_length);
292
 
      cmp_name= table_name;
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<Index_hint>::iterator it(index_hints->begin());
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
 
}
323
 
 
324
 
} /* namespace drizzled */