1
/* Copyright (C) 2009 Sun Microsystems
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
uint32_t TableList::create_table_def_key(char *key)
39
return TableShare::createKey(key, db, table_name);
42
bool TableList::set_insert_values(memory::Root *mem_root)
46
if (!table->insert_values &&
47
!(table->insert_values= (unsigned char *)alloc_root(mem_root,
48
table->s->rec_buff_length)))
55
bool TableList::is_leaf_for_name_resolution()
57
return (is_natural_join || is_join_columns_complete || !nested_join);
60
TableList *TableList::find_underlying_table(Table *table_to_find)
62
/* is this real table and table which we are looking for? */
63
if (table == table_to_find)
69
bool TableList::placeholder()
71
return derived || (create && !table->getDBStat()) || !table;
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
79
TableList *TableList::last_leaf_for_name_resolution()
81
TableList *cur_table_ref= this;
82
nested_join_st *cur_nested_join;
84
if (is_leaf_for_name_resolution())
88
for (cur_nested_join= nested_join;
90
cur_nested_join= cur_table_ref->nested_join)
92
cur_table_ref= cur_nested_join->join_list.head();
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
98
if ((cur_table_ref->outer_join & JOIN_TYPE_RIGHT))
100
List_iterator_fast<TableList> it(cur_nested_join->join_list);
106
if (cur_table_ref->is_leaf_for_name_resolution())
109
return cur_table_ref;
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
117
TableList *TableList::first_leaf_for_name_resolution()
119
TableList *cur_table_ref= NULL;
120
nested_join_st *cur_nested_join;
122
if (is_leaf_for_name_resolution())
126
for (cur_nested_join= nested_join;
128
cur_nested_join= cur_table_ref->nested_join)
130
List_iterator_fast<TableList> it(cur_nested_join->join_list);
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.
138
if (!(cur_table_ref->outer_join & JOIN_TYPE_RIGHT))
144
if (cur_table_ref->is_leaf_for_name_resolution())
147
return cur_table_ref;
150
Item_subselect *TableList::containing_subselect()
152
return (select_lex ? select_lex->master_unit()->item : 0);
155
bool TableList::process_index_hints(Table *tbl)
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;
161
/* index hint list processing */
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];
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);
173
/* initialize temporary variables used to collect hints of each kind */
174
for (type= INDEX_HINT_IGNORE; type <= INDEX_HINT_FORCE; type++)
176
index_join[type].reset();
177
index_order[type].reset();
178
index_group[type].reset();
181
/* iterate over the hints list */
182
while ((hint= iter++))
186
/* process empty USE INDEX () */
187
if (hint->type == INDEX_HINT_USE && !hint->key_name.str)
189
if (hint->clause & INDEX_HINT_MASK_JOIN)
191
index_join[hint->type].reset();
192
have_empty_use_join= true;
194
if (hint->clause & INDEX_HINT_MASK_ORDER)
196
index_order[hint->type].reset();
197
have_empty_use_order= true;
199
if (hint->clause & INDEX_HINT_MASK_GROUP)
201
index_group[hint->type].reset();
202
have_empty_use_group= true;
208
Check if an index with the given name exists and get his offset in
209
the keys bitmask for the table
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)
215
my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), hint->key_name.str, alias);
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);
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))
238
my_error(ER_WRONG_USAGE, MYF(0), index_hint_type_name[INDEX_HINT_USE],
239
index_hint_type_name[INDEX_HINT_FORCE]);
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())
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];
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];
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]);
268
/* make sure covering_keys don't include indexes disabled with a hint */
269
tbl->covering_keys&= tbl->keys_in_use_for_query;
273
void TableList::print(Session *session, String *str, enum_query_type query_type)
278
print_join(session, str, &nested_join->join_list, query_type);
283
const char *cmp_name; // Name to compare with alias
288
derived->print(str, query_type);
290
cmp_name= ""; // Force printing of alias
296
str->append_identifier(db, db_length);
299
str->append_identifier(table_name, table_name_length);
300
cmp_name= table_name;
302
if (my_strcasecmp(table_alias_charset, cmp_name, alias))
305
if (alias && alias[0])
309
string t_alias(alias);
310
transform(t_alias.begin(), t_alias.end(),
311
t_alias.begin(), ::tolower);
313
str->append_identifier(t_alias.c_str(), t_alias.length());
320
List_iterator<Index_hint> it(*index_hints);
325
str->append (STRING_WITH_LEN(" "));
326
hint->print (session, str);
332
} /* namespace drizzled */