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
20
#include <drizzled/server_includes.h>
22
#include <drizzled/session.h>
23
#include <drizzled/error.h>
24
#include <drizzled/show.h>
25
#include <drizzled/item/ref.h>
27
Item_ref::Item_ref(Name_resolution_context *context_arg,
28
Item **item, const char *table_name_arg,
29
const char *field_name_arg,
30
bool alias_name_used_arg)
31
:Item_ident(context_arg, NULL, table_name_arg, field_name_arg),
32
result_field(0), ref(item)
34
alias_name_used= alias_name_used_arg;
36
This constructor used to create some internals references over fixed items
38
if (ref && *ref && (*ref)->fixed)
44
Resolve the name of a reference to a column reference.
46
The method resolves the column reference represented by 'this' as a column
47
present in one of: GROUP BY clause, SELECT clause, outer queries. It is
48
used typically for columns in the HAVING clause which are not under
52
Item_ref::ref is 0 or points to a valid item.
55
The name resolution algorithm used is (where [T_j] is an optional table
56
name that qualifies the column name):
59
resolve_extended([T_j].col_ref_i)
61
Search for a column or derived column named col_ref_i [in table T_j]
62
in the SELECT and GROUP clauses of Q.
64
if such a column is NOT found AND // Lookup in outer queries.
65
there are outer queries
67
for each outer query Q_k beginning from the inner-most one
69
Search for a column or derived column named col_ref_i
70
[in table T_j] in the SELECT and GROUP clauses of Q_k.
72
if such a column is not found AND
73
- Q_k is not a group query AND
74
- Q_k is not inside an aggregate function
76
- Q_(k-1) is not in a HAVING or SELECT clause of Q_k
78
search for a column or derived column named col_ref_i
79
[in table T_j] in the FROM clause of Q_k;
86
This procedure treats GROUP BY and SELECT clauses as one namespace for
87
column references in HAVING. Notice that compared to
88
Item_field::fix_fields, here we first search the SELECT and GROUP BY
89
clauses, and then we search the FROM clause.
91
@param[in] session current thread
92
@param[in,out] reference view column if this item was resolved to a
96
Here we could first find the field anyway, and then test this
97
condition, so that we can give a better error message -
98
ER_WRONG_FIELD_WITH_GROUP, instead of the less informative
99
ER_BAD_FIELD_ERROR which we produce now.
107
bool Item_ref::fix_fields(Session *session, Item **reference)
109
enum_parsing_place place= NO_MATTER;
111
SELECT_LEX *current_sel= session->lex->current_select;
113
if (!ref || ref == not_found_item)
115
if (!(ref= resolve_ref_in_select_and_group(session, this,
116
context->select_lex)))
117
goto error; /* Some error occurred (e.g. ambiguous names). */
119
if (ref == not_found_item) /* This reference was not resolved. */
121
Name_resolution_context *last_checked_context= context;
122
Name_resolution_context *outer_context= context->outer_context;
128
/* The current reference cannot be resolved in this query. */
129
my_error(ER_BAD_FIELD_ERROR,MYF(0),
130
this->full_name(), current_session->where);
135
If there is an outer context (select), and it is not a derived table
136
(which do not support the use of outer fields for now), try to
137
resolve this reference in the outer select(s).
139
We treat each subselect as a separate namespace, so that different
140
subselects may contain columns with the same names. The subselects are
141
searched starting from the innermost.
143
from_field= (Field*) not_found_field;
147
SELECT_LEX *select= outer_context->select_lex;
148
Item_subselect *prev_subselect_item=
149
last_checked_context->select_lex->master_unit()->item;
150
last_checked_context= outer_context;
152
/* Search in the SELECT and GROUP lists of the outer select. */
153
if (outer_context->resolve_in_select_list)
155
if (!(ref= resolve_ref_in_select_and_group(session, this, select)))
156
goto error; /* Some error occurred (e.g. ambiguous names). */
157
if (ref != not_found_item)
159
assert(*ref && (*ref)->fixed);
160
prev_subselect_item->used_tables_cache|= (*ref)->used_tables();
161
prev_subselect_item->const_item_cache&= (*ref)->const_item();
165
Set ref to 0 to ensure that we get an error in case we replaced
166
this item with another item and still use this item in some
167
other place of the parse tree.
172
place= prev_subselect_item->parsing_place;
174
Check table fields only if the subquery is used somewhere out of
175
HAVING or the outer SELECT does not use grouping (i.e. tables are
178
Here we could first find the field anyway, and then test this
179
condition, so that we can give a better error message -
180
ER_WRONG_FIELD_WITH_GROUP, instead of the less informative
181
ER_BAD_FIELD_ERROR which we produce now.
183
if ((place != IN_HAVING ||
184
(!select->with_sum_func &&
185
select->group_list.elements == 0)))
188
In case of view, find_field_in_tables() write pointer to view
189
field expression to 'reference', i.e. it substitute that
190
expression instead of this Item_ref
192
from_field= find_field_in_tables(session, this,
194
first_name_resolution_table,
196
last_name_resolution_table,
198
IGNORE_EXCEPT_NON_UNIQUE,
202
if (from_field == view_ref_found)
204
Item::Type refer_type= (*reference)->type();
205
prev_subselect_item->used_tables_cache|=
206
(*reference)->used_tables();
207
prev_subselect_item->const_item_cache&=
208
(*reference)->const_item();
209
assert((*reference)->type() == REF_ITEM);
210
mark_as_dependent(session, last_checked_context->select_lex,
211
context->select_lex, this,
212
((refer_type == REF_ITEM ||
213
refer_type == FIELD_ITEM) ?
214
(Item_ident*) (*reference) :
217
view reference found, we substituted it instead of this
222
if (from_field != not_found_field)
224
if (cached_table && cached_table->select_lex &&
225
outer_context->select_lex &&
226
cached_table->select_lex != outer_context->select_lex)
229
Due to cache, find_field_in_tables() can return field which
230
doesn't belong to provided outer_context. In this case we have
231
to find proper field context in order to fix field correcly.
235
outer_context= outer_context->outer_context;
236
select= outer_context->select_lex;
238
last_checked_context->select_lex->master_unit()->item;
239
last_checked_context= outer_context;
240
} while (outer_context && outer_context->select_lex &&
241
cached_table->select_lex != outer_context->select_lex);
243
prev_subselect_item->used_tables_cache|= from_field->table->map;
244
prev_subselect_item->const_item_cache= 0;
248
assert(from_field == not_found_field);
250
/* Reference is not found => depend on outer (or just error). */
251
prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
252
prev_subselect_item->const_item_cache= 0;
254
outer_context= outer_context->outer_context;
255
} while (outer_context);
257
assert(from_field != 0 && from_field != view_ref_found);
258
if (from_field != not_found_field)
261
if (!(fld= new Item_field(from_field)))
263
session->change_item_tree(reference, fld);
264
mark_as_dependent(session, last_checked_context->select_lex,
265
session->lex->current_select, this, fld);
267
A reference is resolved to a nest level that's outer or the same as
268
the nest level of the enclosing set function : adjust the value of
269
max_arg_level for the function if it's needed.
271
if (session->lex->in_sum_func &&
272
session->lex->in_sum_func->nest_level >=
273
last_checked_context->select_lex->nest_level)
274
set_if_bigger(session->lex->in_sum_func->max_arg_level,
275
last_checked_context->select_lex->nest_level);
280
/* The item was not a table field and not a reference */
281
my_error(ER_BAD_FIELD_ERROR, MYF(0),
282
this->full_name(), current_session->where);
285
/* Should be checked in resolve_ref_in_select_and_group(). */
286
assert(*ref && (*ref)->fixed);
287
mark_as_dependent(session, last_checked_context->select_lex,
288
context->select_lex, this, this);
290
A reference is resolved to a nest level that's outer or the same as
291
the nest level of the enclosing set function : adjust the value of
292
max_arg_level for the function if it's needed.
294
if (session->lex->in_sum_func &&
295
session->lex->in_sum_func->nest_level >=
296
last_checked_context->select_lex->nest_level)
297
set_if_bigger(session->lex->in_sum_func->max_arg_level,
298
last_checked_context->select_lex->nest_level);
304
Check if this is an incorrect reference in a group function or forward
305
reference. Do not issue an error if this is:
306
1. outer reference (will be fixed later by the fix_inner_refs function);
307
2. an unnamed reference inside an aggregate function.
309
if (!((*ref)->type() == REF_ITEM &&
310
((Item_ref *)(*ref))->ref_type() == OUTER_REF) &&
311
(((*ref)->with_sum_func && name &&
312
!(current_sel->linkage != GLOBAL_OPTIONS_TYPE &&
313
current_sel->having_fix_field)) ||
316
my_error(ER_ILLEGAL_REFERENCE, MYF(0),
317
name, ((*ref)->with_sum_func?
318
"reference to group function":
319
"forward reference in item list"));
325
if ((*ref)->check_cols(1))
330
context->process_error(session);
335
void Item_ref::set_properties()
337
max_length= (*ref)->max_length;
338
maybe_null= (*ref)->maybe_null;
339
decimals= (*ref)->decimals;
340
collation.set((*ref)->collation);
342
We have to remember if we refer to a sum function, to ensure that
343
split_sum_func() doesn't try to change the reference.
345
with_sum_func= (*ref)->with_sum_func;
346
unsigned_flag= (*ref)->unsigned_flag;
350
if ((*ref)->type() == FIELD_ITEM)
351
alias_name_used= ((Item_ident *) (*ref))->alias_name_used;
353
alias_name_used= true; // it is not field, so it is was resolved by alias
357
void Item_ref::cleanup()
359
Item_ident::cleanup();
365
void Item_ref::print(String *str, enum_query_type query_type)
369
if ((*ref)->type() != Item::CACHE_ITEM &&
370
!table_name && name && alias_name_used)
372
Session *session= current_session;
373
append_identifier(session, str, name, (uint) strlen(name));
376
(*ref)->print(str, query_type);
379
Item_ident::print(str, query_type);
383
bool Item_ref::send(Protocol *prot, String *tmp)
386
return prot->store(result_field);
387
return (*ref)->send(prot, tmp);
391
double Item_ref::val_result()
395
if ((null_value= result_field->is_null()))
397
return result_field->val_real();
403
int64_t Item_ref::val_int_result()
407
if ((null_value= result_field->is_null()))
409
return result_field->val_int();
415
String *Item_ref::str_result(String* str)
419
if ((null_value= result_field->is_null()))
421
str->set_charset(str_value.charset());
422
return result_field->val_str(str, &str_value);
428
my_decimal *Item_ref::val_decimal_result(my_decimal *decimal_value)
432
if ((null_value= result_field->is_null()))
434
return result_field->val_decimal(decimal_value);
436
return val_decimal(decimal_value);
440
bool Item_ref::val_bool_result()
444
if ((null_value= result_field->is_null()))
446
switch (result_field->result_type()) {
448
return result_field->val_int() != 0;
451
my_decimal decimal_value;
452
my_decimal *val= result_field->val_decimal(&decimal_value);
454
return !my_decimal_is_zero(val);
459
return result_field->val_real() != 0.0;
469
double Item_ref::val_real()
472
double tmp=(*ref)->val_result();
473
null_value=(*ref)->null_value;
478
int64_t Item_ref::val_int()
481
int64_t tmp=(*ref)->val_int_result();
482
null_value=(*ref)->null_value;
487
bool Item_ref::val_bool()
490
bool tmp= (*ref)->val_bool_result();
491
null_value= (*ref)->null_value;
496
String *Item_ref::val_str(String* tmp)
499
tmp=(*ref)->str_result(tmp);
500
null_value=(*ref)->null_value;
505
bool Item_ref::is_null()
508
return (*ref)->is_null();
512
bool Item_ref::get_date(DRIZZLE_TIME *ltime,uint32_t fuzzydate)
514
return (null_value=(*ref)->get_date_result(ltime,fuzzydate));
518
my_decimal *Item_ref::val_decimal(my_decimal *decimal_value)
520
my_decimal *val= (*ref)->val_decimal_result(decimal_value);
521
null_value= (*ref)->null_value;
525
int Item_ref::save_in_field(Field *to, bool no_conversions)
528
assert(!result_field);
529
res= (*ref)->save_in_field(to, no_conversions);
530
null_value= (*ref)->null_value;
535
void Item_ref::save_org_in_field(Field *field)
537
(*ref)->save_org_in_field(field);
541
void Item_ref::make_field(Send_field *field)
543
(*ref)->make_field(field);
544
/* Non-zero in case of a view */
546
field->col_name= name;
548
field->table_name= table_name;
550
field->db_name= db_name;
554
Item *Item_ref::get_tmp_table_item(Session *session)
557
return (*ref)->get_tmp_table_item(session);
559
Item_field *item= new Item_field(result_field);
562
item->table_name= table_name;
563
item->db_name= db_name;
568
void Item_ref::fix_after_pullout(st_select_lex *new_parent, Item **)
570
if (depended_from == new_parent)
572
(*ref)->fix_after_pullout(new_parent, ref);