Drizzled Public API Documentation

ref.cc
1 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3  *
4  * Copyright (C) 2008 Sun Microsystems, Inc.
5  *
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.
9  *
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.
14  *
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
18  */
19 
20 #include <config.h>
21 
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>
28 #include <drizzled/item/subselect.h>
29 #include <drizzled/sql_lex.h>
30 
31 namespace drizzled {
32 
33 Item_ref::Item_ref(Name_resolution_context *context_arg,
34  Item **item, const char *table_name_arg,
35  const char *field_name_arg,
36  bool alias_name_used_arg)
37  :Item_ident(context_arg, NULL, table_name_arg, field_name_arg),
38  result_field(0), ref(item)
39 {
40  alias_name_used= alias_name_used_arg;
41  /*
42  This constructor used to create some internals references over fixed items
43  */
44  if (ref && *ref && (*ref)->fixed)
45  set_properties();
46 }
47 
48 
113 bool Item_ref::fix_fields(Session *session, Item **reference)
114 {
115  enum_parsing_place place= NO_MATTER;
116  assert(fixed == 0);
117  Select_Lex *current_sel= session->lex().current_select;
118 
119  if (!ref || ref == not_found_item)
120  {
121  if (!(ref= resolve_ref_in_select_and_group(session, this, context->select_lex)))
122  return true; /* Some error occurred (e.g. ambiguous names). */
123 
124  if (ref == not_found_item) /* This reference was not resolved. */
125  {
126  Name_resolution_context *last_checked_context= context;
127  Name_resolution_context *outer_context= context->outer_context;
128  Field *from_field;
129  ref= 0;
130 
131  if (!outer_context)
132  {
133  /* The current reference cannot be resolved in this query. */
134  my_error(ER_BAD_FIELD_ERROR,MYF(0), full_name(), session->where());
135  return true;
136  }
137 
138  /*
139  If there is an outer context (select), and it is not a derived table
140  (which do not support the use of outer fields for now), try to
141  resolve this reference in the outer select(s).
142 
143  We treat each subselect as a separate namespace, so that different
144  subselects may contain columns with the same names. The subselects are
145  searched starting from the innermost.
146  */
147  from_field= (Field*) not_found_field;
148 
149  do
150  {
151  Select_Lex *select= outer_context->select_lex;
152  Item_subselect *prev_subselect_item=
153  last_checked_context->select_lex->master_unit()->item;
154  last_checked_context= outer_context;
155 
156  /* Search in the SELECT and GROUP lists of the outer select. */
157  if (outer_context->resolve_in_select_list)
158  {
159  if (!(ref= resolve_ref_in_select_and_group(session, this, select)))
160  return true; /* Some error occurred (e.g. ambiguous names). */
161  if (ref != not_found_item)
162  {
163  assert(*ref && (*ref)->fixed);
164  prev_subselect_item->used_tables_cache|= (*ref)->used_tables();
165  prev_subselect_item->const_item_cache&= (*ref)->const_item();
166  break;
167  }
168  /*
169  Set ref to 0 to ensure that we get an error in case we replaced
170  this item with another item and still use this item in some
171  other place of the parse tree.
172  */
173  ref= 0;
174  }
175 
176  place= prev_subselect_item->parsing_place;
177  /*
178  Check table fields only if the subquery is used somewhere out of
179  HAVING or the outer SELECT does not use grouping (i.e. tables are
180  accessible).
181  TODO:
182  Here we could first find the field anyway, and then test this
183  condition, so that we can give a better error message -
184  ER_WRONG_FIELD_WITH_GROUP, instead of the less informative
185  ER_BAD_FIELD_ERROR which we produce now.
186 
187  @todo determine if this is valid.
188  */
189  if ((place != IN_HAVING ||
190  (!select->with_sum_func &&
191  select->group_list.elements == 0)))
192  {
193  /*
194  In case of view, find_field_in_tables() write pointer to view
195  field expression to 'reference', i.e. it substitute that
196  expression instead of this Item_ref
197  */
198  from_field= find_field_in_tables(session, this,
199  outer_context->
200  first_name_resolution_table,
201  outer_context->
202  last_name_resolution_table,
203  reference,
204  IGNORE_EXCEPT_NON_UNIQUE, true);
205  if (! from_field)
206  return true;
207  if (from_field == view_ref_found)
208  {
209  Item::Type refer_type= (*reference)->type();
210  prev_subselect_item->used_tables_cache|=
211  (*reference)->used_tables();
212  prev_subselect_item->const_item_cache&=
213  (*reference)->const_item();
214  assert((*reference)->type() == REF_ITEM);
215  mark_as_dependent(session, last_checked_context->select_lex,
216  context->select_lex, this,
217  ((refer_type == REF_ITEM ||
218  refer_type == FIELD_ITEM) ?
219  (Item_ident*) (*reference) :
220  0));
221  /*
222  view reference found, we substituted it instead of this
223  Item, so can quit
224  */
225  return false;
226  }
227  if (from_field != not_found_field)
228  {
229  if (cached_table && cached_table->select_lex &&
230  outer_context->select_lex &&
231  cached_table->select_lex != outer_context->select_lex)
232  {
233  /*
234  Due to cache, find_field_in_tables() can return field which
235  doesn't belong to provided outer_context. In this case we have
236  to find proper field context in order to fix field correcly.
237  */
238  do
239  {
240  outer_context= outer_context->outer_context;
241  select= outer_context->select_lex;
242  prev_subselect_item=
243  last_checked_context->select_lex->master_unit()->item;
244  last_checked_context= outer_context;
245  } while (outer_context && outer_context->select_lex &&
246  cached_table->select_lex != outer_context->select_lex);
247  }
248  prev_subselect_item->used_tables_cache|= from_field->getTable()->map;
249  prev_subselect_item->const_item_cache= false;
250  break;
251  }
252  }
253  assert(from_field == not_found_field);
254 
255  /* Reference is not found => depend on outer (or just error). */
256  prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
257  prev_subselect_item->const_item_cache= false;
258 
259  outer_context= outer_context->outer_context;
260  } while (outer_context);
261 
262  assert(from_field != 0 && from_field != view_ref_found);
263  if (from_field != not_found_field)
264  {
265  Item_field* fld;
266  fld= new Item_field(from_field);
267  *reference= fld;
268  mark_as_dependent(session, last_checked_context->select_lex,
269  session->lex().current_select, this, fld);
270  /*
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.
274  */
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);
280  return false;
281  }
282  if (ref == 0)
283  {
284  /* The item was not a table field and not a reference */
285  my_error(ER_BAD_FIELD_ERROR, MYF(0), full_name(), session->where());
286  return true;
287  }
288  /* Should be checked in resolve_ref_in_select_and_group(). */
289  assert(*ref && (*ref)->fixed);
290  mark_as_dependent(session, last_checked_context->select_lex,
291  context->select_lex, this, this);
292  /*
293  A reference is resolved to a nest level that's outer or the same as
294  the nest level of the enclosing set function : adjust the value of
295  max_arg_level for the function if it's needed.
296  */
297  if (session->lex().in_sum_func &&
298  session->lex().in_sum_func->nest_level >=
299  last_checked_context->select_lex->nest_level)
300  set_if_bigger(session->lex().in_sum_func->max_arg_level,
301  last_checked_context->select_lex->nest_level);
302  }
303  }
304 
305  assert(*ref);
306  /*
307  Check if this is an incorrect reference in a group function or forward
308  reference. Do not issue an error if this is:
309  1. outer reference (will be fixed later by the fix_inner_refs function);
310  2. an unnamed reference inside an aggregate function.
311  */
312  if (!((*ref)->type() == REF_ITEM &&
313  ((Item_ref *)(*ref))->ref_type() == OUTER_REF) &&
314  (((*ref)->with_sum_func && name &&
315  !(current_sel->linkage != GLOBAL_OPTIONS_TYPE &&
316  current_sel->having_fix_field)) ||
317  !(*ref)->fixed))
318  {
319  my_error(ER_ILLEGAL_REFERENCE, MYF(0), name, ((*ref)->with_sum_func ? "reference to group function" : "forward reference in item list"));
320  return true;
321  }
322 
323  set_properties();
324 
325  if ((*ref)->check_cols(1))
326  return true;
327  return false;
328 }
329 
330 
331 void Item_ref::set_properties()
332 {
333  max_length= (*ref)->max_length;
334  maybe_null= (*ref)->maybe_null;
335  decimals= (*ref)->decimals;
336  collation.set((*ref)->collation);
337  /*
338  We have to remember if we refer to a sum function, to ensure that
339  split_sum_func() doesn't try to change the reference.
340  */
341  with_sum_func= (*ref)->with_sum_func;
342  unsigned_flag= (*ref)->unsigned_flag;
343  fixed= 1;
344  if (alias_name_used)
345  return;
346  if ((*ref)->type() == FIELD_ITEM)
347  alias_name_used= ((Item_ident *) (*ref))->alias_name_used;
348  else
349  alias_name_used= true; // it is not field, so it is was resolved by alias
350 }
351 
352 
353 void Item_ref::cleanup()
354 {
355  Item_ident::cleanup();
356  result_field= 0;
357  return;
358 }
359 
360 
362 {
363  if (ref)
364  {
365  if ((*ref)->type() != Item::CACHE_ITEM &&
366  !table_name && name && alias_name_used)
367  {
368  str->append_identifier(str_ref(name));
369  }
370  else
371  (*ref)->print(str);
372  }
373  else
374  Item_ident::print(str);
375 }
376 
377 
379 {
380  if (result_field)
381  {
382  client->store(result_field);
383  return;
384  }
385  return (*ref)->send(client, tmp);
386 }
387 
388 
389 double Item_ref::val_result()
390 {
391  if (result_field)
392  {
393  if ((null_value= result_field->is_null()))
394  return 0.0;
395  return result_field->val_real();
396  }
397  return val_real();
398 }
399 
400 
401 int64_t Item_ref::val_int_result()
402 {
403  if (result_field)
404  {
405  if ((null_value= result_field->is_null()))
406  return 0;
407  return result_field->val_int();
408  }
409  return val_int();
410 }
411 
412 
413 String *Item_ref::str_result(String* str)
414 {
415  if (result_field)
416  {
417  if ((null_value= result_field->is_null()))
418  return 0;
419  str->set_charset(str_value.charset());
420  return result_field->val_str(str, &str_value);
421  }
422  return val_str(str);
423 }
424 
425 
426 type::Decimal *Item_ref::val_decimal_result(type::Decimal *decimal_value)
427 {
428  if (result_field)
429  {
430  if ((null_value= result_field->is_null()))
431  return 0;
432  return result_field->val_decimal(decimal_value);
433  }
434  return val_decimal(decimal_value);
435 }
436 
437 
438 bool Item_ref::val_bool_result()
439 {
440  if (result_field)
441  {
442  if ((null_value= result_field->is_null()))
443  return 0;
444  switch (result_field->result_type()) {
445  case INT_RESULT:
446  return result_field->val_int() != 0;
447 
448  case DECIMAL_RESULT:
449  {
450  type::Decimal decimal_value;
451  type::Decimal *val= result_field->val_decimal(&decimal_value);
452  if (val)
453  return not val->isZero();
454  return 0;
455  }
456 
457  case REAL_RESULT:
458  case STRING_RESULT:
459  return result_field->val_real() != 0.0;
460 
461  case ROW_RESULT:
462  assert(0);
463  }
464  }
465 
466  return val_bool();
467 }
468 
469 
471 {
472  assert(fixed);
473  double tmp=(*ref)->val_result();
474  null_value=(*ref)->null_value;
475  return tmp;
476 }
477 
478 
480 {
481  assert(fixed);
482  int64_t tmp=(*ref)->val_int_result();
483  null_value=(*ref)->null_value;
484  return tmp;
485 }
486 
487 
489 {
490  assert(fixed);
491  bool tmp= (*ref)->val_bool_result();
492  null_value= (*ref)->null_value;
493  return tmp;
494 }
495 
496 
498 {
499  assert(fixed);
500  tmp=(*ref)->str_result(tmp);
501  null_value=(*ref)->null_value;
502  return tmp;
503 }
504 
505 
507 {
508  assert(fixed);
509  return (*ref)->is_null();
510 }
511 
512 
513 bool Item_ref::get_date(type::Time &ltime,uint32_t fuzzydate)
514 {
515  return (null_value=(*ref)->get_date_result(ltime,fuzzydate));
516 }
517 
518 
520 {
521  type::Decimal *val= (*ref)->val_decimal_result(decimal_value);
522  null_value= (*ref)->null_value;
523  return val;
524 }
525 
526 int Item_ref::save_in_field(Field *to, bool no_conversions)
527 {
528  int res;
529  assert(!result_field);
530  res= (*ref)->save_in_field(to, no_conversions);
531  null_value= (*ref)->null_value;
532  return res;
533 }
534 
535 
536 void Item_ref::save_org_in_field(Field *field)
537 {
538  (*ref)->save_org_in_field(field);
539 }
540 
541 
542 void Item_ref::make_field(SendField *field)
543 {
544  (*ref)->make_field(field);
545  /* Non-zero in case of a view */
546  if (name)
547  field->col_name= name;
548  if (table_name)
549  field->table_name= table_name;
550  if (db_name)
551  field->db_name= db_name;
552 }
553 
554 
555 Item *Item_ref::get_tmp_table_item(Session *session)
556 {
557  if (!result_field)
558  return (*ref)->get_tmp_table_item(session);
559 
560  Item_field *item= new Item_field(result_field);
561  if (item)
562  {
563  item->table_name= table_name;
564  item->db_name= db_name;
565  }
566  return item;
567 }
568 
569 void Item_ref::fix_after_pullout(Select_Lex *new_parent, Item **)
570 {
571  if (depended_from == new_parent)
572  {
573  (*ref)->fix_after_pullout(new_parent, ref);
574  depended_from= NULL;
575  }
576 }
577 
578 } /* namespace drizzled */
const char * name
Definition: item.h:110
bool is_null()
Definition: ref.cc:506
int64_t val_int()
Definition: ref.cc:479
Select_Lex * select_lex
Definition: table_list.h:208
table_map map
ID bit of table (1,2,4,8,16...)
Definition: table.h:270
bool val_bool()
Definition: ref.cc:488
virtual void print(String *str)
Definition: ident.cc:103
Item ** resolve_ref_in_select_and_group(Session *session, Item_ident *ref, Select_Lex *select)
Definition: item.cc:940
bool fixed
Definition: item.h:120
TODO: Rename this file - func.h is stupid.
virtual void print(String *str)
Definition: ref.cc:361
bool fix_fields(Session *, Item **)
Definition: ref.cc:113
bool null_value
Definition: item.h:122
Definition: wakeup.h:27
bool maybe_null
Definition: item.h:121
double val_real()
Definition: ref.cc:470
type::Decimal * val_decimal(type::Decimal *)
Definition: ref.cc:519
void mark_as_dependent(Session *session, Select_Lex *last, Select_Lex *current, Item_ident *resolved_item, Item_ident *mark_item)
Definition: item.cc:772
void fix_after_pullout(Select_Lex *new_parent, Item **ref)
Definition: ref.cc:569
void send(plugin::Client *client, String *tmp)
Definition: ref.cc:378
String * val_str(String *tmp)
Definition: ref.cc:497
bool get_date(type::Time &ltime, uint32_t fuzzydate)
Definition: ref.cc:513
String str_value
Definition: item.h:107
Name_resolution_context * outer_context