1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; version 2 of the License.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
#include "drizzled/session.h"
23
#include "drizzled/error.h"
24
#include "drizzled/show.h"
25
#include "drizzled/item/ref.h"
26
#include "drizzled/plugin/client.h"
27
#include "drizzled/item/sum.h"
32
Item_ref::Item_ref(Name_resolution_context *context_arg,
33
Item **item, const char *table_name_arg,
34
const char *field_name_arg,
35
bool alias_name_used_arg)
36
:Item_ident(context_arg, NULL, table_name_arg, field_name_arg),
37
result_field(0), ref(item)
39
alias_name_used= alias_name_used_arg;
41
This constructor used to create some internals references over fixed items
43
if (ref && *ref && (*ref)->fixed)
49
Resolve the name of a reference to a column reference.
51
The method resolves the column reference represented by 'this' as a column
52
present in one of: GROUP BY clause, SELECT clause, outer queries. It is
53
used typically for columns in the HAVING clause which are not under
57
Item_ref::ref is 0 or points to a valid item.
60
The name resolution algorithm used is (where [T_j] is an optional table
61
name that qualifies the column name):
64
resolve_extended([T_j].col_ref_i)
66
Search for a column or derived column named col_ref_i [in table T_j]
67
in the SELECT and GROUP clauses of Q.
69
if such a column is NOT found AND // Lookup in outer queries.
70
there are outer queries
72
for each outer query Q_k beginning from the inner-most one
74
Search for a column or derived column named col_ref_i
75
[in table T_j] in the SELECT and GROUP clauses of Q_k.
77
if such a column is not found AND
78
- Q_k is not a group query AND
79
- Q_k is not inside an aggregate function
81
- Q_(k-1) is not in a HAVING or SELECT clause of Q_k
83
search for a column or derived column named col_ref_i
84
[in table T_j] in the FROM clause of Q_k;
91
This procedure treats GROUP BY and SELECT clauses as one namespace for
92
column references in HAVING. Notice that compared to
93
Item_field::fix_fields, here we first search the SELECT and GROUP BY
94
clauses, and then we search the FROM clause.
96
@param[in] session current thread
97
@param[in,out] reference view column if this item was resolved to a
101
Here we could first find the field anyway, and then test this
102
condition, so that we can give a better error message -
103
ER_WRONG_FIELD_WITH_GROUP, instead of the less informative
104
ER_BAD_FIELD_ERROR which we produce now.
112
bool Item_ref::fix_fields(Session *session, Item **reference)
114
enum_parsing_place place= NO_MATTER;
116
Select_Lex *current_sel= session->lex->current_select;
118
if (!ref || ref == not_found_item)
120
if (!(ref= resolve_ref_in_select_and_group(session, this,
121
context->select_lex)))
122
goto error; /* Some error occurred (e.g. ambiguous names). */
124
if (ref == not_found_item) /* This reference was not resolved. */
126
Name_resolution_context *last_checked_context= context;
127
Name_resolution_context *outer_context= context->outer_context;
133
/* The current reference cannot be resolved in this query. */
134
my_error(ER_BAD_FIELD_ERROR,MYF(0),
135
this->full_name(), current_session->where);
140
If there is an outer context (select), and it is not a derived table
141
(which do not support the use of outer fields for now), try to
142
resolve this reference in the outer select(s).
144
We treat each subselect as a separate namespace, so that different
145
subselects may contain columns with the same names. The subselects are
146
searched starting from the innermost.
148
from_field= (Field*) not_found_field;
152
Select_Lex *select= outer_context->select_lex;
153
Item_subselect *prev_subselect_item=
154
last_checked_context->select_lex->master_unit()->item;
155
last_checked_context= outer_context;
157
/* Search in the SELECT and GROUP lists of the outer select. */
158
if (outer_context->resolve_in_select_list)
160
if (!(ref= resolve_ref_in_select_and_group(session, this, select)))
161
goto error; /* Some error occurred (e.g. ambiguous names). */
162
if (ref != not_found_item)
164
assert(*ref && (*ref)->fixed);
165
prev_subselect_item->used_tables_cache|= (*ref)->used_tables();
166
prev_subselect_item->const_item_cache&= (*ref)->const_item();
170
Set ref to 0 to ensure that we get an error in case we replaced
171
this item with another item and still use this item in some
172
other place of the parse tree.
177
place= prev_subselect_item->parsing_place;
179
Check table fields only if the subquery is used somewhere out of
180
HAVING or the outer SELECT does not use grouping (i.e. tables are
183
Here we could first find the field anyway, and then test this
184
condition, so that we can give a better error message -
185
ER_WRONG_FIELD_WITH_GROUP, instead of the less informative
186
ER_BAD_FIELD_ERROR which we produce now.
188
@todo determine if this is valid.
190
if ((place != IN_HAVING ||
191
(!select->with_sum_func &&
192
select->group_list.elements == 0)))
195
In case of view, find_field_in_tables() write pointer to view
196
field expression to 'reference', i.e. it substitute that
197
expression instead of this Item_ref
199
from_field= find_field_in_tables(session, this,
201
first_name_resolution_table,
203
last_name_resolution_table,
205
IGNORE_EXCEPT_NON_UNIQUE, true);
208
if (from_field == view_ref_found)
210
Item::Type refer_type= (*reference)->type();
211
prev_subselect_item->used_tables_cache|=
212
(*reference)->used_tables();
213
prev_subselect_item->const_item_cache&=
214
(*reference)->const_item();
215
assert((*reference)->type() == REF_ITEM);
216
mark_as_dependent(session, last_checked_context->select_lex,
217
context->select_lex, this,
218
((refer_type == REF_ITEM ||
219
refer_type == FIELD_ITEM) ?
220
(Item_ident*) (*reference) :
223
view reference found, we substituted it instead of this
228
if (from_field != not_found_field)
230
if (cached_table && cached_table->select_lex &&
231
outer_context->select_lex &&
232
cached_table->select_lex != outer_context->select_lex)
235
Due to cache, find_field_in_tables() can return field which
236
doesn't belong to provided outer_context. In this case we have
237
to find proper field context in order to fix field correcly.
241
outer_context= outer_context->outer_context;
242
select= outer_context->select_lex;
244
last_checked_context->select_lex->master_unit()->item;
245
last_checked_context= outer_context;
246
} while (outer_context && outer_context->select_lex &&
247
cached_table->select_lex != outer_context->select_lex);
249
prev_subselect_item->used_tables_cache|= from_field->getTable()->map;
250
prev_subselect_item->const_item_cache= 0;
254
assert(from_field == not_found_field);
256
/* Reference is not found => depend on outer (or just error). */
257
prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
258
prev_subselect_item->const_item_cache= 0;
260
outer_context= outer_context->outer_context;
261
} while (outer_context);
263
assert(from_field != 0 && from_field != view_ref_found);
264
if (from_field != not_found_field)
267
if (!(fld= new Item_field(from_field)))
269
session->change_item_tree(reference, fld);
270
mark_as_dependent(session, last_checked_context->select_lex,
271
session->lex->current_select, this, fld);
273
A reference is resolved to a nest level that's outer or the same as
274
the nest level of the enclosing set function : adjust the value of
275
max_arg_level for the function if it's needed.
277
if (session->lex->in_sum_func &&
278
session->lex->in_sum_func->nest_level >=
279
last_checked_context->select_lex->nest_level)
280
set_if_bigger(session->lex->in_sum_func->max_arg_level,
281
last_checked_context->select_lex->nest_level);
286
/* The item was not a table field and not a reference */
287
my_error(ER_BAD_FIELD_ERROR, MYF(0),
288
this->full_name(), current_session->where);
291
/* Should be checked in resolve_ref_in_select_and_group(). */
292
assert(*ref && (*ref)->fixed);
293
mark_as_dependent(session, last_checked_context->select_lex,
294
context->select_lex, this, this);
296
A reference is resolved to a nest level that's outer or the same as
297
the nest level of the enclosing set function : adjust the value of
298
max_arg_level for the function if it's needed.
300
if (session->lex->in_sum_func &&
301
session->lex->in_sum_func->nest_level >=
302
last_checked_context->select_lex->nest_level)
303
set_if_bigger(session->lex->in_sum_func->max_arg_level,
304
last_checked_context->select_lex->nest_level);
310
Check if this is an incorrect reference in a group function or forward
311
reference. Do not issue an error if this is:
312
1. outer reference (will be fixed later by the fix_inner_refs function);
313
2. an unnamed reference inside an aggregate function.
315
if (!((*ref)->type() == REF_ITEM &&
316
((Item_ref *)(*ref))->ref_type() == OUTER_REF) &&
317
(((*ref)->with_sum_func && name &&
318
!(current_sel->linkage != GLOBAL_OPTIONS_TYPE &&
319
current_sel->having_fix_field)) ||
322
my_error(ER_ILLEGAL_REFERENCE, MYF(0),
323
name, ((*ref)->with_sum_func?
324
"reference to group function":
325
"forward reference in item list"));
331
if ((*ref)->check_cols(1))
336
context->process_error(session);
341
void Item_ref::set_properties()
343
max_length= (*ref)->max_length;
344
maybe_null= (*ref)->maybe_null;
345
decimals= (*ref)->decimals;
346
collation.set((*ref)->collation);
348
We have to remember if we refer to a sum function, to ensure that
349
split_sum_func() doesn't try to change the reference.
351
with_sum_func= (*ref)->with_sum_func;
352
unsigned_flag= (*ref)->unsigned_flag;
356
if ((*ref)->type() == FIELD_ITEM)
357
alias_name_used= ((Item_ident *) (*ref))->alias_name_used;
359
alias_name_used= true; // it is not field, so it is was resolved by alias
363
void Item_ref::cleanup()
365
Item_ident::cleanup();
371
void Item_ref::print(String *str, enum_query_type query_type)
375
if ((*ref)->type() != Item::CACHE_ITEM &&
376
!table_name && name && alias_name_used)
378
str->append_identifier(name, (uint32_t) strlen(name));
381
(*ref)->print(str, query_type);
384
Item_ident::print(str, query_type);
388
bool Item_ref::send(plugin::Client *client, String *tmp)
391
return client->store(result_field);
392
return (*ref)->send(client, tmp);
396
double Item_ref::val_result()
400
if ((null_value= result_field->is_null()))
402
return result_field->val_real();
408
int64_t Item_ref::val_int_result()
412
if ((null_value= result_field->is_null()))
414
return result_field->val_int();
420
String *Item_ref::str_result(String* str)
424
if ((null_value= result_field->is_null()))
426
str->set_charset(str_value.charset());
427
return result_field->val_str(str, &str_value);
433
my_decimal *Item_ref::val_decimal_result(my_decimal *decimal_value)
437
if ((null_value= result_field->is_null()))
439
return result_field->val_decimal(decimal_value);
441
return val_decimal(decimal_value);
445
bool Item_ref::val_bool_result()
449
if ((null_value= result_field->is_null()))
451
switch (result_field->result_type()) {
453
return result_field->val_int() != 0;
456
my_decimal decimal_value;
457
my_decimal *val= result_field->val_decimal(&decimal_value);
459
return !my_decimal_is_zero(val);
464
return result_field->val_real() != 0.0;
474
double Item_ref::val_real()
477
double tmp=(*ref)->val_result();
478
null_value=(*ref)->null_value;
483
int64_t Item_ref::val_int()
486
int64_t tmp=(*ref)->val_int_result();
487
null_value=(*ref)->null_value;
492
bool Item_ref::val_bool()
495
bool tmp= (*ref)->val_bool_result();
496
null_value= (*ref)->null_value;
501
String *Item_ref::val_str(String* tmp)
504
tmp=(*ref)->str_result(tmp);
505
null_value=(*ref)->null_value;
510
bool Item_ref::is_null()
513
return (*ref)->is_null();
517
bool Item_ref::get_date(DRIZZLE_TIME *ltime,uint32_t fuzzydate)
519
return (null_value=(*ref)->get_date_result(ltime,fuzzydate));
523
my_decimal *Item_ref::val_decimal(my_decimal *decimal_value)
525
my_decimal *val= (*ref)->val_decimal_result(decimal_value);
526
null_value= (*ref)->null_value;
530
int Item_ref::save_in_field(Field *to, bool no_conversions)
533
assert(!result_field);
534
res= (*ref)->save_in_field(to, no_conversions);
535
null_value= (*ref)->null_value;
540
void Item_ref::save_org_in_field(Field *field)
542
(*ref)->save_org_in_field(field);
546
void Item_ref::make_field(SendField *field)
548
(*ref)->make_field(field);
549
/* Non-zero in case of a view */
551
field->col_name= name;
553
field->table_name= table_name;
555
field->db_name= db_name;
559
Item *Item_ref::get_tmp_table_item(Session *session)
562
return (*ref)->get_tmp_table_item(session);
564
Item_field *item= new Item_field(result_field);
567
item->table_name= table_name;
568
item->db_name= db_name;
573
void Item_ref::fix_after_pullout(Select_Lex *new_parent, Item **)
575
if (depended_from == new_parent)
577
(*ref)->fix_after_pullout(new_parent, ref);
582
} /* namespace drizzled */