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
if ((place != IN_HAVING ||
189
(!select->with_sum_func &&
190
select->group_list.elements == 0)))
193
In case of view, find_field_in_tables() write pointer to view
194
field expression to 'reference', i.e. it substitute that
195
expression instead of this Item_ref
197
from_field= find_field_in_tables(session, this,
199
first_name_resolution_table,
201
last_name_resolution_table,
203
IGNORE_EXCEPT_NON_UNIQUE, true);
206
if (from_field == view_ref_found)
208
Item::Type refer_type= (*reference)->type();
209
prev_subselect_item->used_tables_cache|=
210
(*reference)->used_tables();
211
prev_subselect_item->const_item_cache&=
212
(*reference)->const_item();
213
assert((*reference)->type() == REF_ITEM);
214
mark_as_dependent(session, last_checked_context->select_lex,
215
context->select_lex, this,
216
((refer_type == REF_ITEM ||
217
refer_type == FIELD_ITEM) ?
218
(Item_ident*) (*reference) :
221
view reference found, we substituted it instead of this
226
if (from_field != not_found_field)
228
if (cached_table && cached_table->select_lex &&
229
outer_context->select_lex &&
230
cached_table->select_lex != outer_context->select_lex)
233
Due to cache, find_field_in_tables() can return field which
234
doesn't belong to provided outer_context. In this case we have
235
to find proper field context in order to fix field correcly.
239
outer_context= outer_context->outer_context;
240
select= outer_context->select_lex;
242
last_checked_context->select_lex->master_unit()->item;
243
last_checked_context= outer_context;
244
} while (outer_context && outer_context->select_lex &&
245
cached_table->select_lex != outer_context->select_lex);
247
prev_subselect_item->used_tables_cache|= from_field->table->map;
248
prev_subselect_item->const_item_cache= 0;
252
assert(from_field == not_found_field);
254
/* Reference is not found => depend on outer (or just error). */
255
prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
256
prev_subselect_item->const_item_cache= 0;
258
outer_context= outer_context->outer_context;
259
} while (outer_context);
261
assert(from_field != 0 && from_field != view_ref_found);
262
if (from_field != not_found_field)
265
if (!(fld= new Item_field(from_field)))
267
session->change_item_tree(reference, fld);
268
mark_as_dependent(session, last_checked_context->select_lex,
269
session->lex->current_select, this, fld);
271
A reference is resolved to a nest level that's outer or the same as
272
the nest level of the enclosing set function : adjust the value of
273
max_arg_level for the function if it's needed.
275
if (session->lex->in_sum_func &&
276
session->lex->in_sum_func->nest_level >=
277
last_checked_context->select_lex->nest_level)
278
set_if_bigger(session->lex->in_sum_func->max_arg_level,
279
last_checked_context->select_lex->nest_level);
284
/* The item was not a table field and not a reference */
285
my_error(ER_BAD_FIELD_ERROR, MYF(0),
286
this->full_name(), current_session->where);
289
/* Should be checked in resolve_ref_in_select_and_group(). */
290
assert(*ref && (*ref)->fixed);
291
mark_as_dependent(session, last_checked_context->select_lex,
292
context->select_lex, this, this);
294
A reference is resolved to a nest level that's outer or the same as
295
the nest level of the enclosing set function : adjust the value of
296
max_arg_level for the function if it's needed.
298
if (session->lex->in_sum_func &&
299
session->lex->in_sum_func->nest_level >=
300
last_checked_context->select_lex->nest_level)
301
set_if_bigger(session->lex->in_sum_func->max_arg_level,
302
last_checked_context->select_lex->nest_level);
308
Check if this is an incorrect reference in a group function or forward
309
reference. Do not issue an error if this is:
310
1. outer reference (will be fixed later by the fix_inner_refs function);
311
2. an unnamed reference inside an aggregate function.
313
if (!((*ref)->type() == REF_ITEM &&
314
((Item_ref *)(*ref))->ref_type() == OUTER_REF) &&
315
(((*ref)->with_sum_func && name &&
316
!(current_sel->linkage != GLOBAL_OPTIONS_TYPE &&
317
current_sel->having_fix_field)) ||
320
my_error(ER_ILLEGAL_REFERENCE, MYF(0),
321
name, ((*ref)->with_sum_func?
322
"reference to group function":
323
"forward reference in item list"));
329
if ((*ref)->check_cols(1))
334
context->process_error(session);
339
void Item_ref::set_properties()
341
max_length= (*ref)->max_length;
342
maybe_null= (*ref)->maybe_null;
343
decimals= (*ref)->decimals;
344
collation.set((*ref)->collation);
346
We have to remember if we refer to a sum function, to ensure that
347
split_sum_func() doesn't try to change the reference.
349
with_sum_func= (*ref)->with_sum_func;
350
unsigned_flag= (*ref)->unsigned_flag;
354
if ((*ref)->type() == FIELD_ITEM)
355
alias_name_used= ((Item_ident *) (*ref))->alias_name_used;
357
alias_name_used= true; // it is not field, so it is was resolved by alias
361
void Item_ref::cleanup()
363
Item_ident::cleanup();
369
void Item_ref::print(String *str, enum_query_type query_type)
373
if ((*ref)->type() != Item::CACHE_ITEM &&
374
!table_name && name && alias_name_used)
376
str->append_identifier(name, (uint32_t) strlen(name));
379
(*ref)->print(str, query_type);
382
Item_ident::print(str, query_type);
386
bool Item_ref::send(plugin::Client *client, String *tmp)
389
return client->store(result_field);
390
return (*ref)->send(client, tmp);
394
double Item_ref::val_result()
398
if ((null_value= result_field->is_null()))
400
return result_field->val_real();
406
int64_t Item_ref::val_int_result()
410
if ((null_value= result_field->is_null()))
412
return result_field->val_int();
418
String *Item_ref::str_result(String* str)
422
if ((null_value= result_field->is_null()))
424
str->set_charset(str_value.charset());
425
return result_field->val_str(str, &str_value);
431
my_decimal *Item_ref::val_decimal_result(my_decimal *decimal_value)
435
if ((null_value= result_field->is_null()))
437
return result_field->val_decimal(decimal_value);
439
return val_decimal(decimal_value);
443
bool Item_ref::val_bool_result()
447
if ((null_value= result_field->is_null()))
449
switch (result_field->result_type()) {
451
return result_field->val_int() != 0;
454
my_decimal decimal_value;
455
my_decimal *val= result_field->val_decimal(&decimal_value);
457
return !my_decimal_is_zero(val);
462
return result_field->val_real() != 0.0;
472
double Item_ref::val_real()
475
double tmp=(*ref)->val_result();
476
null_value=(*ref)->null_value;
481
int64_t Item_ref::val_int()
484
int64_t tmp=(*ref)->val_int_result();
485
null_value=(*ref)->null_value;
490
bool Item_ref::val_bool()
493
bool tmp= (*ref)->val_bool_result();
494
null_value= (*ref)->null_value;
499
String *Item_ref::val_str(String* tmp)
502
tmp=(*ref)->str_result(tmp);
503
null_value=(*ref)->null_value;
508
bool Item_ref::is_null()
511
return (*ref)->is_null();
515
bool Item_ref::get_date(DRIZZLE_TIME *ltime,uint32_t fuzzydate)
517
return (null_value=(*ref)->get_date_result(ltime,fuzzydate));
521
my_decimal *Item_ref::val_decimal(my_decimal *decimal_value)
523
my_decimal *val= (*ref)->val_decimal_result(decimal_value);
524
null_value= (*ref)->null_value;
528
int Item_ref::save_in_field(Field *to, bool no_conversions)
531
assert(!result_field);
532
res= (*ref)->save_in_field(to, no_conversions);
533
null_value= (*ref)->null_value;
538
void Item_ref::save_org_in_field(Field *field)
540
(*ref)->save_org_in_field(field);
544
void Item_ref::make_field(SendField *field)
546
(*ref)->make_field(field);
547
/* Non-zero in case of a view */
549
field->col_name= name;
551
field->table_name= table_name;
553
field->db_name= db_name;
557
Item *Item_ref::get_tmp_table_item(Session *session)
560
return (*ref)->get_tmp_table_item(session);
562
Item_field *item= new Item_field(result_field);
565
item->table_name= table_name;
566
item->db_name= db_name;
571
void Item_ref::fix_after_pullout(Select_Lex *new_parent, Item **)
573
if (depended_from == new_parent)
575
(*ref)->fix_after_pullout(new_parent, ref);
580
} /* namespace drizzled */