1
/* Copyright (C) 2009 Sun Microsystems, Inc.
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.
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.
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 */
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>
37
bool TableList::set_insert_values(memory::Root *)
41
table->insert_values.resize(table->getShare()->rec_buff_length);
47
bool TableList::is_leaf_for_name_resolution()
49
return (is_natural_join || is_join_columns_complete || !nested_join);
52
TableList *TableList::find_underlying_table(Table *table_to_find)
54
/* is this real table and table which we are looking for? */
55
if (table == table_to_find)
61
bool TableList::isCartesian() const
66
bool TableList::placeholder()
68
return derived || (create && !table->getDBStat()) || !table;
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
76
TableList *TableList::last_leaf_for_name_resolution()
78
TableList *cur_table_ref= this;
79
NestedJoin *cur_nested_join;
81
if (is_leaf_for_name_resolution())
85
for (cur_nested_join= nested_join;
87
cur_nested_join= cur_table_ref->nested_join)
89
cur_table_ref= cur_nested_join->join_list.head();
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
95
if ((cur_table_ref->outer_join & JOIN_TYPE_RIGHT))
97
List<TableList>::iterator it(cur_nested_join->join_list.begin());
103
if (cur_table_ref->is_leaf_for_name_resolution())
106
return cur_table_ref;
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
114
TableList *TableList::first_leaf_for_name_resolution()
116
TableList *cur_table_ref= NULL;
117
NestedJoin *cur_nested_join;
119
if (is_leaf_for_name_resolution())
123
for (cur_nested_join= nested_join;
125
cur_nested_join= cur_table_ref->nested_join)
127
List<TableList>::iterator it(cur_nested_join->join_list.begin());
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.
135
if (!(cur_table_ref->outer_join & JOIN_TYPE_RIGHT))
141
if (cur_table_ref->is_leaf_for_name_resolution())
144
return cur_table_ref;
147
Item_subselect *TableList::containing_subselect()
149
return (select_lex ? select_lex->master_unit()->item : 0);
152
bool TableList::process_index_hints(Table *tbl)
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;
158
/* index hint list processing */
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];
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());
170
/* initialize temporary variables used to collect hints of each kind */
171
for (type= INDEX_HINT_IGNORE; type <= INDEX_HINT_FORCE; type++)
173
index_join[type].reset();
174
index_order[type].reset();
175
index_group[type].reset();
178
/* iterate over the hints list */
179
while ((hint= iter++))
183
/* process empty USE INDEX () */
184
if (hint->type == INDEX_HINT_USE && !hint->key_name.str)
186
if (hint->clause & INDEX_HINT_MASK_JOIN)
188
index_join[hint->type].reset();
189
have_empty_use_join= true;
191
if (hint->clause & INDEX_HINT_MASK_ORDER)
193
index_order[hint->type].reset();
194
have_empty_use_order= true;
196
if (hint->clause & INDEX_HINT_MASK_GROUP)
198
index_group[hint->type].reset();
199
have_empty_use_group= true;
205
Check if an index with the given name exists and get his offset in
206
the keys bitmask for the table
208
if (not tbl->getShare()->doesKeyNameExist(hint->key_name.str, hint->key_name.length, pos))
210
my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), hint->key_name.str, alias);
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);
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))
230
my_error(ER_WRONG_USAGE, MYF(0), index_hint_type_name[INDEX_HINT_USE],
231
index_hint_type_name[INDEX_HINT_FORCE]);
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())
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];
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];
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]);
260
/* make sure covering_keys don't include indexes disabled with a hint */
261
tbl->covering_keys&= tbl->keys_in_use_for_query;
265
void TableList::print(Session *session, String *str, enum_query_type query_type)
270
print_join(session, str, &nested_join->join_list, query_type);
275
const char *cmp_name; // Name to compare with alias
280
derived->print(str, query_type);
282
cmp_name= ""; // Force printing of alias
288
str->append_identifier(db, db_length);
291
str->append_identifier(table_name, table_name_length);
292
cmp_name= table_name;
294
if (my_strcasecmp(table_alias_charset, cmp_name, alias))
297
if (alias && alias[0])
301
string t_alias(alias);
302
transform(t_alias.begin(), t_alias.end(),
303
t_alias.begin(), ::tolower);
305
str->append_identifier(t_alias.c_str(), t_alias.length());
312
List<Index_hint>::iterator it(index_hints->begin());
317
str->append (STRING_WITH_LEN(" "));
318
hint->print (session, str);
324
} /* namespace drizzled */