Drizzled Public API Documentation

field.cc
00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008 Sun Microsystems, Inc.
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; version 2 of the License.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  */
00019 
00020 #include <config.h>
00021 
00022 #include <drizzled/session.h>
00023 #include <drizzled/table.h>
00024 #include <drizzled/error.h>
00025 #include <drizzled/join.h>
00026 #include <drizzled/sql_base.h>
00027 #include <drizzled/sql_select.h>
00028 #include <drizzled/item/cmpfunc.h>
00029 #include <drizzled/item/field.h>
00030 #include <drizzled/item/outer_ref.h>
00031 #include <drizzled/plugin/client.h>
00032 #include <drizzled/item/subselect.h>
00033 #include <drizzled/sql_lex.h>
00034 
00035 #include <boost/dynamic_bitset.hpp>
00036 
00037 namespace drizzled {
00038 
00057 bool Item_field::collect_item_field_processor(unsigned char *arg)
00058 {
00059   List<Item_field> *item_list= (List<Item_field>*) arg;
00060   List<Item_field>::iterator item_list_it(item_list->begin());
00061   while (Item_field* curr_item= item_list_it++)
00062   {
00063     if (curr_item->eq(this, 1))
00064       return false; /* Already in the set. */
00065   }
00066   item_list->push_back(this);
00067   return false;
00068 }
00069 
00070 
00087 bool Item_field::find_item_in_field_list_processor(unsigned char *arg)
00088 {
00089   KeyPartInfo *first_non_group_part= *((KeyPartInfo **) arg);
00090   KeyPartInfo *last_part= *(((KeyPartInfo **) arg) + 1);
00091 
00092   for (KeyPartInfo* cur_part= first_non_group_part; cur_part != last_part; cur_part++)
00093   {
00094     if (field->eq(cur_part->field))
00095       return true;
00096   }
00097   return false;
00098 }
00099 
00100 
00101 /*
00102   Mark field in read_map
00103 
00104   NOTES
00105     This is used by filesort to register used fields in a a temporary
00106     column read set or to register used fields in a view
00107 */
00108 
00109 bool Item_field::register_field_in_read_map(unsigned char *arg)
00110 {
00111   Table *table= (Table *) arg;
00112   if (field->getTable() == table || !table)
00113     field->getTable()->setReadSet(field->position());
00114 
00115   return 0;
00116 }
00117 
00118 
00119 Item_field::Item_field(Field *f)
00120   :Item_ident(0, NULL, f->getTable()->getAlias(), f->field_name),
00121    item_equal(0), no_const_subst(0),
00122    have_privileges(0), any_privileges(0)
00123 {
00124   set_field(f);
00125   /*
00126     field_name and table_name should not point to garbage
00127     if this item is to be reused
00128   */
00129   orig_table_name= orig_field_name= "";
00130 }
00131 
00132 
00140 Item_field::Item_field(Session *,
00141                        Name_resolution_context *context_arg,
00142                        Field *f) :
00143   Item_ident(context_arg,
00144              f->getTable()->getShare()->getSchemaName(),
00145              f->getTable()->getAlias(),
00146              f->field_name),
00147    item_equal(0),
00148    no_const_subst(0),
00149    have_privileges(0),
00150    any_privileges(0)
00151 {
00152   set_field(f);
00153 }
00154 
00155 
00156 Item_field::Item_field(Name_resolution_context *context_arg,
00157                        const char *db_arg,const char *table_name_arg,
00158                        const char *field_name_arg) :
00159   Item_ident(context_arg, db_arg,table_name_arg,field_name_arg),
00160    field(0),
00161    result_field(0),
00162    item_equal(0),
00163    no_const_subst(0),
00164    have_privileges(0),
00165    any_privileges(0)
00166 {
00167   Select_Lex *select= getSession().lex().current_select;
00168   collation.set(DERIVATION_IMPLICIT);
00169 
00170   if (select && select->parsing_place != IN_HAVING)
00171       select->select_n_where_fields++;
00172 }
00173 
00178 Item_field::Item_field(Session *session, Item_field *item) :
00179   Item_ident(session, item),
00180   field(item->field),
00181   result_field(item->result_field),
00182   item_equal(item->item_equal),
00183   no_const_subst(item->no_const_subst),
00184   have_privileges(item->have_privileges),
00185   any_privileges(item->any_privileges)
00186 {
00187   collation.set(DERIVATION_IMPLICIT);
00188 }
00189 
00190 void Item_field::set_field(Field *field_par)
00191 {
00192   field=result_field=field_par;     // for easy coding with fields
00193   maybe_null=field->maybe_null();
00194   decimals= field->decimals();
00195   max_length= field_par->max_display_length();
00196   table_name= field_par->getTable()->getAlias();
00197   field_name= field_par->field_name;
00198   db_name= field_par->getTable()->getShare()->getSchemaName();
00199   alias_name_used= field_par->getTable()->alias_name_used;
00200   unsigned_flag=test(field_par->flags & UNSIGNED_FLAG);
00201   collation.set(field_par->charset(), field_par->derivation());
00202   fixed= 1;
00203 }
00204 
00205 
00212 void Item_field::reset_field(Field *f)
00213 {
00214   set_field(f);
00215   /* 'name' is pointing at field->field_name of old field */
00216   name= f->field_name;
00217 }
00218 
00219 /* ARGSUSED */
00220 String *Item_field::val_str(String *str)
00221 {
00222   assert(fixed == 1);
00223   if ((null_value=field->is_null()))
00224     return 0;
00225   str->set_charset(str_value.charset());
00226   return field->val_str(str,&str_value);
00227 }
00228 
00229 
00230 double Item_field::val_real()
00231 {
00232   assert(fixed == 1);
00233   if ((null_value=field->is_null()))
00234     return 0.0;
00235   return field->val_real();
00236 }
00237 
00238 
00239 int64_t Item_field::val_int()
00240 {
00241   assert(fixed == 1);
00242   if ((null_value=field->is_null()))
00243     return 0;
00244   return field->val_int();
00245 }
00246 
00247 
00248 type::Decimal *Item_field::val_decimal(type::Decimal *decimal_value)
00249 {
00250   if ((null_value= field->is_null()))
00251     return 0;
00252   return field->val_decimal(decimal_value);
00253 }
00254 
00255 
00256 String *Item_field::str_result(String *str)
00257 {
00258   if ((null_value=result_field->is_null()))
00259     return 0;
00260   str->set_charset(str_value.charset());
00261   return result_field->val_str(str,&str_value);
00262 }
00263 
00264 bool Item_field::get_date(type::Time &ltime,uint32_t fuzzydate)
00265 {
00266   if ((null_value=field->is_null()) || field->get_date(ltime,fuzzydate))
00267   {
00268     ltime.reset();
00269     return 1;
00270   }
00271   return 0;
00272 }
00273 
00274 bool Item_field::get_date_result(type::Time &ltime,uint32_t fuzzydate)
00275 {
00276   if ((null_value=result_field->is_null()) ||
00277       result_field->get_date(ltime,fuzzydate))
00278   {
00279     ltime.reset();
00280     return 1;
00281   }
00282   return 0;
00283 }
00284 
00285 bool Item_field::get_time(type::Time &ltime)
00286 {
00287   if ((null_value=field->is_null()) || field->get_time(ltime))
00288   {
00289     ltime.reset();
00290     return 1;
00291   }
00292   return 0;
00293 }
00294 
00295 double Item_field::val_result()
00296 {
00297   if ((null_value=result_field->is_null()))
00298     return 0.0;
00299   return result_field->val_real();
00300 }
00301 
00302 int64_t Item_field::val_int_result()
00303 {
00304   if ((null_value=result_field->is_null()))
00305     return 0;
00306   return result_field->val_int();
00307 }
00308 
00309 
00310 type::Decimal *Item_field::val_decimal_result(type::Decimal *decimal_value)
00311 {
00312   if ((null_value= result_field->is_null()))
00313     return 0;
00314   return result_field->val_decimal(decimal_value);
00315 }
00316 
00317 
00318 bool Item_field::val_bool_result()
00319 {
00320   if ((null_value= result_field->is_null()))
00321   {
00322     return false;
00323   }
00324 
00325   switch (result_field->result_type()) 
00326   {
00327   case INT_RESULT:
00328     return result_field->val_int() != 0;
00329 
00330   case DECIMAL_RESULT:
00331     {
00332       type::Decimal decimal_value;
00333       type::Decimal *val= result_field->val_decimal(&decimal_value);
00334       if (val)
00335         return not val->isZero();
00336       return 0;
00337     }
00338 
00339   case REAL_RESULT:
00340   case STRING_RESULT:
00341     return result_field->val_real() != 0.0;
00342 
00343   case ROW_RESULT:
00344     assert(false);
00345     return 0;
00346   }
00347 
00348   assert(false);
00349   return 0;
00350 }
00351 
00352 
00353 bool Item_field::eq(const Item *item, bool) const
00354 {
00355   const Item *item_ptr= item->real_item();
00356   if (item_ptr->type() != FIELD_ITEM)
00357     return 0;
00358 
00359   const Item_field *item_field= static_cast<const Item_field *>(item_ptr);
00360   if (item_field->field && field)
00361     return item_field->field == field;
00362   /*
00363     We may come here when we are trying to find a function in a GROUP BY
00364     clause from the select list.
00365     In this case the '100 % correct' way to do this would be to first
00366     run fix_fields() on the GROUP BY item and then retry this function, but
00367     I think it's better to relax the checking a bit as we will in
00368     most cases do the correct thing by just checking the field name.
00369     (In cases where we would choose wrong we would have to generate a
00370     ER_NON_UNIQ_ERROR).
00371   */
00372   return (not system_charset_info->strcasecmp(item_field->name, field_name) &&
00373           (not item_field->table_name || not table_name ||
00374            (not table_alias_charset->strcasecmp(item_field->table_name, table_name) &&
00375             (not item_field->db_name || not db_name ||
00376              (item_field->db_name && not system_charset_info->strcasecmp(item_field->db_name, db_name))))));
00377 }
00378 
00379 
00380 table_map Item_field::used_tables() const
00381 {
00382   if (field->getTable()->const_table)
00383   {
00384     return 0;         // const item
00385   }
00386 
00387   return depended_from ? OUTER_REF_TABLE_BIT : field->getTable()->map;
00388 }
00389 
00390 enum Item_result Item_field::result_type () const
00391 {
00392   return field->result_type();
00393 }
00394 
00395 
00396 Item_result Item_field::cast_to_int_type() const
00397 {
00398   return field->cast_to_int_type();
00399 }
00400 
00401 
00402 enum_field_types Item_field::field_type() const
00403 {
00404   return field->type();
00405 }
00406 
00407 
00408 void Item_field::fix_after_pullout(Select_Lex *new_parent, Item **)
00409 {
00410   if (new_parent == depended_from)
00411     depended_from= NULL;
00412   Name_resolution_context *ctx= new Name_resolution_context();
00413   ctx->outer_context= NULL; // We don't build a complete name resolver
00414   ctx->select_lex= new_parent;
00415   ctx->first_name_resolution_table= context->first_name_resolution_table;
00416   ctx->last_name_resolution_table=  context->last_name_resolution_table;
00417   this->context=ctx;
00418 }
00419 
00420 
00421 bool Item_field::is_null()
00422 {
00423   return field->is_null();
00424 }
00425 
00426 
00427 Item *Item_field::get_tmp_table_item(Session *session)
00428 {
00429   Item_field *new_item= new Item_field(session, this);
00430   new_item->field= new_item->result_field;
00431   return new_item;
00432 }
00433 
00434 int64_t Item_field::val_int_endpoint(bool, bool *)
00435 {
00436   int64_t res= val_int();
00437   return null_value? INT64_MIN : res;
00438 }
00439 
00440 
00480 int
00481 Item_field::fix_outer_field(Session *session, Field **from_field, Item **reference)
00482 {
00483   enum_parsing_place place= NO_MATTER;
00484   bool field_found= (*from_field != not_found_field);
00485   bool upward_lookup= false;
00486 
00487   /*
00488     If there are outer contexts (outer selects, but current select is
00489     not derived table or view) try to resolve this reference in the
00490     outer contexts.
00491 
00492     We treat each subselect as a separate namespace, so that different
00493     subselects may contain columns with the same names. The subselects
00494     are searched starting from the innermost.
00495   */
00496   Name_resolution_context *last_checked_context= context;
00497   Item **ref= (Item **) not_found_item;
00498   Select_Lex *current_sel= (Select_Lex *) session->lex().current_select;
00499   Name_resolution_context *outer_context= 0;
00500   Select_Lex *select= 0;
00501   /* Currently derived tables cannot be correlated */
00502   if (current_sel->master_unit()->first_select()->linkage !=
00503       DERIVED_TABLE_TYPE)
00504     outer_context= context->outer_context;
00505   for (;
00506        outer_context;
00507        outer_context= outer_context->outer_context)
00508   {
00509     select= outer_context->select_lex;
00510     Item_subselect *prev_subselect_item=
00511       last_checked_context->select_lex->master_unit()->item;
00512     last_checked_context= outer_context;
00513     upward_lookup= true;
00514 
00515     place= prev_subselect_item->parsing_place;
00516     /*
00517       If outer_field is set, field was already found by first call
00518       to find_field_in_tables(). Only need to find appropriate context.
00519     */
00520     if (field_found && outer_context->select_lex !=
00521         cached_table->select_lex)
00522       continue;
00523     /*
00524       In case of a view, find_field_in_tables() writes the pointer to
00525       the found view field into '*reference', in other words, it
00526       substitutes this Item_field with the found expression.
00527     */
00528     if (field_found || (*from_field= find_field_in_tables(session, this,
00529                                           outer_context->
00530                                             first_name_resolution_table,
00531                                           outer_context->
00532                                             last_name_resolution_table,
00533                                           reference,
00534                                           IGNORE_EXCEPT_NON_UNIQUE,
00535                                           true)) !=
00536         not_found_field)
00537     {
00538       if (*from_field)
00539       {
00540         if (*from_field != view_ref_found)
00541         {
00542           prev_subselect_item->used_tables_cache|= (*from_field)->getTable()->map;
00543           prev_subselect_item->const_item_cache= false;
00544           set_field(*from_field);
00545           if (!last_checked_context->select_lex->having_fix_field &&
00546               select->group_list.elements &&
00547               (place == SELECT_LIST || place == IN_HAVING))
00548           {
00549             /*
00550               If an outer field is resolved in a grouping select then it
00551               is replaced for an Item_outer_ref object. Otherwise an
00552               Item_field object is used.
00553               The new Item_outer_ref object is saved in the inner_refs_list of
00554               the outer select. Here it is only created. It can be fixed only
00555               after the original field has been fixed and this is done in the
00556               fix_inner_refs() function.
00557             */
00558             Item_outer_ref* rf= new Item_outer_ref(context, this);
00559             *reference= rf;
00560             select->inner_refs_list.push_back(rf);
00561             rf->in_sum_func= session->lex().in_sum_func;
00562           }
00563           /*
00564             A reference is resolved to a nest level that's outer or the same as
00565             the nest level of the enclosing set function : adjust the value of
00566             max_arg_level for the function if it's needed.
00567           */
00568           if (session->lex().in_sum_func &&
00569               session->lex().in_sum_func->nest_level >= select->nest_level)
00570           {
00571             Item::Type ref_type= (*reference)->type();
00572             set_if_bigger(session->lex().in_sum_func->max_arg_level,
00573                           select->nest_level);
00574             set_field(*from_field);
00575             fixed= 1;
00576             mark_as_dependent(session, last_checked_context->select_lex,
00577                               context->select_lex, this,
00578                               ((ref_type == REF_ITEM ||
00579                                 ref_type == FIELD_ITEM) ?
00580                                (Item_ident*) (*reference) : 0));
00581             return 0;
00582           }
00583         }
00584         else
00585         {
00586           Item::Type ref_type= (*reference)->type();
00587           prev_subselect_item->used_tables_cache|= (*reference)->used_tables();
00588           prev_subselect_item->const_item_cache&= (*reference)->const_item();
00589           mark_as_dependent(session, last_checked_context->select_lex,
00590             context->select_lex, this, ((ref_type == REF_ITEM || ref_type == FIELD_ITEM) ? (Item_ident*) (*reference) : 0));
00591           /*
00592             A reference to a view field had been found and we
00593             substituted it instead of this Item (find_field_in_tables
00594             does it by assigning the new value to *reference), so now
00595             we can return from this function.
00596           */
00597           return 0;
00598         }
00599       }
00600       break;
00601     }
00602 
00603     /* Search in SELECT and GROUP lists of the outer select. */
00604     if (place != IN_WHERE && place != IN_ON)
00605     {
00606       if (!(ref= resolve_ref_in_select_and_group(session, this, select)))
00607         return -1; /* Some error occurred (e.g. ambiguous names). */
00608       if (ref != not_found_item)
00609       {
00610         assert(*ref && (*ref)->fixed);
00611         prev_subselect_item->used_tables_cache|= (*ref)->used_tables();
00612         prev_subselect_item->const_item_cache&= (*ref)->const_item();
00613         break;
00614       }
00615     }
00616 
00617     /*
00618       Reference is not found in this select => this subquery depend on
00619       outer select (or we just trying to find wrong identifier, in this
00620       case it does not matter which used tables bits we set)
00621     */
00622     prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
00623     prev_subselect_item->const_item_cache= false;
00624   }
00625 
00626   assert(ref != 0);
00627   if (!*from_field)
00628     return -1;
00629   if (ref == not_found_item && *from_field == not_found_field)
00630   {
00631     if (upward_lookup)
00632     {
00633       // We can't say exactly what absent table or field
00634       my_error(ER_BAD_FIELD_ERROR, MYF(0), full_name(), session->where());
00635     }
00636     else
00637     {
00638       /* Call find_field_in_tables only to report the error */
00639       find_field_in_tables(session, this,
00640                            context->first_name_resolution_table,
00641                            context->last_name_resolution_table,
00642                            reference, REPORT_ALL_ERRORS, true);
00643     }
00644     return -1;
00645   }
00646   else if (ref != not_found_item)
00647   {
00648     /* Should have been checked in resolve_ref_in_select_and_group(). */
00649     assert(*ref && (*ref)->fixed);
00650     /*
00651       Here, a subset of actions performed by Item_ref::set_properties
00652       is not enough. So we pass ptr to NULL into Item_[direct]_ref
00653       constructor, so no initialization is performed, and call
00654       fix_fields() below.
00655     */
00656     Item* save= *ref;
00657     *ref= NULL;                             // Don't call set_properties()
00658     Item_ref* rf= (place == IN_HAVING ?
00659          new Item_ref(context, ref, table_name, field_name, alias_name_used) :
00660          (!select->group_list.elements ?
00661          new Item_direct_ref(context, ref, table_name, field_name, alias_name_used) :
00662          new Item_outer_ref(context, ref, table_name, field_name, alias_name_used)));
00663     *ref= save;
00664     if (!rf)
00665       return -1;
00666 
00667     if (place != IN_HAVING && select->group_list.elements)
00668     {
00669       outer_context->select_lex->inner_refs_list.push_back((Item_outer_ref*)rf);
00670       ((Item_outer_ref*)rf)->in_sum_func= session->lex().in_sum_func;
00671     }
00672     *reference= rf;
00673     /*
00674       rf is Item_ref => never substitute other items (in this case)
00675       during fix_fields() => we can use rf after fix_fields()
00676     */
00677     assert(!rf->fixed);                // Assured by Item_ref()
00678     if (rf->fix_fields(session, reference) || rf->check_cols(1))
00679       return -1;
00680 
00681     mark_as_dependent(session, last_checked_context->select_lex, context->select_lex, this, rf);
00682     return 0;
00683   }
00684   else
00685   {
00686     mark_as_dependent(session, last_checked_context->select_lex, context->select_lex, this, (Item_ident*)*reference);
00687     if (last_checked_context->select_lex->having_fix_field)
00688     {
00689       Item_ref* rf= new Item_ref(context, (cached_table->getSchemaName()[0] ? cached_table->getSchemaName() : 0), cached_table->alias, field_name);
00690       *reference= rf;
00691       /*
00692         rf is Item_ref => never substitute other items (in this case)
00693         during fix_fields() => we can use rf after fix_fields()
00694       */
00695       assert(!rf->fixed);                // Assured by Item_ref()
00696       if (rf->fix_fields(session, reference) || rf->check_cols(1))
00697         return -1;
00698       return 0;
00699     }
00700   }
00701   return 1;
00702 }
00703 
00704 
00750 bool Item_field::fix_fields(Session *session, Item **reference)
00751 {
00752   assert(fixed == 0);
00753   Field *from_field= (Field *)not_found_field;
00754   bool outer_fixed= false;
00755 
00756   if (!field)         // If field is not checked
00757   {
00758     /*
00759       In case of view, find_field_in_tables() write pointer to view field
00760       expression to 'reference', i.e. it substitute that expression instead
00761       of this Item_field
00762     */
00763     if ((from_field= find_field_in_tables(session, this,
00764                                           context->first_name_resolution_table,
00765                                           context->last_name_resolution_table,
00766                                           reference,
00767                                           session->lex().use_only_table_context ?
00768                                             REPORT_ALL_ERRORS :
00769                                             IGNORE_EXCEPT_NON_UNIQUE, true)) ==
00770         not_found_field)
00771     {
00772       int ret;
00773       /* Look up in current select's item_list to find aliased fields */
00774       if (session->lex().current_select->is_item_list_lookup)
00775       {
00776         uint32_t counter;
00777         enum_resolution_type resolution;
00778         Item** res= find_item_in_list(session,
00779                                       this, session->lex().current_select->item_list,
00780                                       &counter, REPORT_EXCEPT_NOT_FOUND,
00781                                       &resolution);
00782         if (!res)
00783           return 1;
00784         if (resolution == RESOLVED_AGAINST_ALIAS)
00785           alias_name_used= true;
00786         if (res != (Item **)not_found_item)
00787         {
00788           if ((*res)->type() == Item::FIELD_ITEM)
00789           {
00790             /*
00791               It's an Item_field referencing another Item_field in the select
00792               list.
00793               Use the field from the Item_field in the select list and leave
00794               the Item_field instance in place.
00795             */
00796 
00797             Field *new_field= (*((Item_field**)res))->field;
00798 
00799             if (new_field == NULL)
00800             {
00801               /* The column to which we link isn't valid. */
00802               my_error(ER_BAD_FIELD_ERROR, MYF(0), (*res)->name,
00803                        session->where());
00804               return 1;
00805             }
00806 
00807             set_field(new_field);
00808             return 0;
00809           }
00810           else
00811           {
00812             /*
00813               It's not an Item_field in the select list so we must make a new
00814               Item_ref to point to the Item in the select list and replace the
00815               Item_field created by the parser with the new Item_ref.
00816             */
00817             Item_ref *rf= new Item_ref(context, db_name,table_name,field_name);
00818             *reference= rf;
00819             /*
00820               Because Item_ref never substitutes itself with other items
00821               in Item_ref::fix_fields(), we can safely use the original
00822               pointer to it even after fix_fields()
00823              */
00824             return rf->fix_fields(session, reference) ||  rf->check_cols(1);
00825           }
00826         }
00827       }
00828       if ((ret= fix_outer_field(session, &from_field, reference)) < 0)
00829         return true;
00830       outer_fixed= true;
00831       if (!ret)
00832         goto mark_non_agg_field;
00833     }
00834     else if (!from_field)
00835       return true;
00836 
00837     if (!outer_fixed && cached_table && cached_table->select_lex &&
00838         context->select_lex &&
00839         cached_table->select_lex != context->select_lex)
00840     {
00841       int ret;
00842       if ((ret= fix_outer_field(session, &from_field, reference)) < 0)
00843         return true;
00844       outer_fixed= 1;
00845       if (!ret)
00846         goto mark_non_agg_field;
00847     }
00848 
00849     /*
00850       if it is not expression from merged VIEW we will set this field.
00851 
00852       We can leave expression substituted from view for next PS/SP rexecution
00853       (i.e. do not register this substitution for reverting on cleanup()
00854       (register_item_tree_changing())), because this subtree will be
00855       fix_field'ed during setup_tables()->setup_underlying() (i.e. before
00856       all other expressions of query, and references on tables which do
00857       not present in query will not make problems.
00858 
00859       Also we suppose that view can't be changed during PS/SP life.
00860     */
00861     if (from_field == view_ref_found)
00862       return false;
00863 
00864     set_field(from_field);
00865     if (session->lex().in_sum_func &&
00866         session->lex().in_sum_func->nest_level ==
00867         session->lex().current_select->nest_level)
00868     {
00869       set_if_bigger(session->lex().in_sum_func->max_arg_level,
00870                     session->lex().current_select->nest_level);
00871     }
00872   }
00873   else if (session->mark_used_columns != MARK_COLUMNS_NONE)
00874   {
00875     Table *table= field->getTable();
00876     boost::dynamic_bitset<> *current_bitmap, *other_bitmap;
00877     if (session->mark_used_columns == MARK_COLUMNS_READ)
00878     {
00879       current_bitmap= table->read_set;
00880       other_bitmap=   table->write_set;
00881     }
00882     else
00883     {
00884       current_bitmap= table->write_set;
00885       other_bitmap=   table->read_set;
00886     }
00887     //if (! current_bitmap->testAndSet(field->position()))
00888     if (! current_bitmap->test(field->position()))
00889     {
00890       if (! other_bitmap->test(field->position()))
00891       {
00892         /* First usage of column */
00893         table->used_fields++;                     // Used to optimize loops
00894         table->covering_keys&= field->part_of_key;
00895       }
00896     }
00897   }
00898   fixed= 1;
00899 mark_non_agg_field:
00900   return false;
00901 }
00902 
00903 Item *Item_field::safe_charset_converter(const charset_info_st * const tocs)
00904 {
00905   no_const_subst= 1;
00906   return Item::safe_charset_converter(tocs);
00907 }
00908 
00909 
00910 void Item_field::cleanup()
00911 {
00912   Item_ident::cleanup();
00913   /*
00914     Even if this object was created by direct link to field in setup_wild()
00915     it will be linked correctly next time by name of field and table alias.
00916     I.e. we can drop 'field'.
00917    */
00918   field= result_field= 0;
00919   null_value= false;
00920 }
00921 
00922 
00923 bool Item_field::result_as_int64_t()
00924 {
00925   return field->can_be_compared_as_int64_t();
00926 }
00927 
00928 
00947 Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal)
00948 {
00949   while (cond_equal)
00950   {
00951     List<Item_equal>::iterator li(cond_equal->current_level.begin());
00952     while (Item_equal* item= li++)
00953     {
00954       if (item->contains(field))
00955         return item;
00956     }
00957     /*
00958       The field is not found in any of the multiple equalities
00959       of the current level. Look for it in upper levels
00960     */
00961     cond_equal= cond_equal->upper_levels;
00962   }
00963   return 0;
00964 }
00965 
00966 
00997 bool Item_field::subst_argument_checker(unsigned char **arg)
00998 {
00999   return (result_type() != STRING_RESULT) || (*arg);
01000 }
01001 
01002 
01027 Item *Item_field::equal_fields_propagator(unsigned char *arg)
01028 {
01029   if (no_const_subst)
01030     return this;
01031   item_equal= find_item_equal((COND_EQUAL *) arg);
01032   Item *item= 0;
01033   if (item_equal)
01034     item= item_equal->get_const();
01035   /*
01036     Disable const propagation for items used in different comparison contexts.
01037     This must be done because, for example, Item_hex_string->val_int() is not
01038     the same as (Item_hex_string->val_str() in BINARY column)->val_int().
01039     We cannot simply disable the replacement in a particular context (
01040     e.g. <bin_col> = <int_col> AND <bin_col> = <hex_string>) since
01041     Items don't know the context they are in and there are functions like
01042     IF (<hex_string>, 'yes', 'no').
01043     The same problem occurs when comparing a DATE/TIME field with a
01044     DATE/TIME represented as an int and as a string.
01045   */
01046   if (!item ||
01047       (cmp_context != (Item_result)-1 && item->cmp_context != cmp_context))
01048     item= this;
01049 
01050   return item;
01051 }
01052 
01053 
01060 bool Item_field::set_no_const_sub(unsigned char *)
01061 {
01062   if (field->charset() != &my_charset_bin)
01063     no_const_subst=1;
01064   return false;
01065 }
01066 
01067 
01093 Item *Item_field::replace_equal_field(unsigned char *)
01094 {
01095   if (item_equal)
01096   {
01097     Item *const_item_ptr= item_equal->get_const();
01098     if (const_item_ptr)
01099     {
01100       if (cmp_context != (Item_result)-1 &&
01101           const_item_ptr->cmp_context != cmp_context)
01102         return this;
01103       return const_item_ptr;
01104     }
01105     Item_field *subst= item_equal->get_first();
01106     if (subst && !field->eq(subst->field))
01107       return subst;
01108   }
01109   return this;
01110 }
01111 
01112 
01113 uint32_t Item_field::max_disp_length()
01114 {
01115   return field->max_display_length();
01116 }
01117 
01118 
01119 /* ARGSUSED */
01120 void Item_field::make_field(SendField *tmp_field)
01121 {
01122   field->make_field(tmp_field);
01123   assert(tmp_field->table_name != 0);
01124   if (name)
01125     tmp_field->col_name=name;     // Use user supplied name
01126   if (table_name)
01127     tmp_field->table_name= table_name;
01128   if (db_name)
01129     tmp_field->db_name= db_name;
01130 }
01131 
01132 
01137 void Item_field::save_org_in_field(Field *to)
01138 {
01139   if (field->is_null())
01140   {
01141     null_value=1;
01142     set_field_to_null_with_conversions(to, 1);
01143   }
01144   else
01145   {
01146     to->set_notnull();
01147     field_conv(to,field);
01148     null_value=0;
01149   }
01150 }
01151 
01152 int Item_field::save_in_field(Field *to, bool no_conversions)
01153 {
01154   int res;
01155   if (result_field->is_null())
01156   {
01157     null_value=1;
01158     res= set_field_to_null_with_conversions(to, no_conversions);
01159   }
01160   else
01161   {
01162     to->set_notnull();
01163     res= field_conv(to,result_field);
01164     null_value=0;
01165   }
01166   return res;
01167 }
01168 
01169 
01170 void Item_field::send(plugin::Client *client, String *)
01171 {
01172   client->store(result_field);
01173 }
01174 
01175 
01176 void Item_field::update_null_value()
01177 {
01178   /*
01179     need to set no_errors to prevent warnings about type conversion
01180     popping up.
01181   */
01182   Session *session= field->getTable()->in_use;
01183   int no_errors= session->no_errors;
01184   session->no_errors= 1;
01185   Item::update_null_value();
01186   session->no_errors= no_errors;
01187 }
01188 
01189 
01190 /*
01191   Add the field to the select list and substitute it for the reference to
01192   the field.
01193 
01194   SYNOPSIS
01195     Item_field::update_value_transformer()
01196     select_arg      current select
01197 
01198   DESCRIPTION
01199     If the field doesn't belong to the table being inserted into then it is
01200     added to the select list, pointer to it is stored in the ref_pointer_array
01201     of the select and the field itself is substituted for the Item_ref object.
01202     This is done in order to get correct values from update fields that
01203     belongs to the SELECT part in the INSERT .. SELECT .. ON DUPLICATE KEY
01204     UPDATE statement.
01205 
01206   RETURN
01207     0             if error occured
01208     ref           if all conditions are met
01209     this field    otherwise
01210 */
01211 
01212 Item *Item_field::update_value_transformer(unsigned char *select_arg)
01213 {
01214   Select_Lex *select= (Select_Lex*)select_arg;
01215   assert(fixed);
01216 
01217   if (field->getTable() != select->context.table_list->table)
01218   {
01219     List<Item> *all_fields= &select->join->all_fields;
01220     Item **ref_pointer_array= select->ref_pointer_array;
01221     int el= all_fields->size();
01222     ref_pointer_array[el]= (Item*)this;
01223     all_fields->push_front((Item*)this);
01224     Item_ref* ref= new Item_ref(&select->context, ref_pointer_array + el, table_name, field_name);
01225     return ref;
01226   }
01227   return this;
01228 }
01229 
01230 
01231 void Item_field::print(String *str)
01232 {
01233   if (field && field->getTable()->const_table)
01234   {
01235     char buff[MAX_FIELD_WIDTH];
01236     String tmp(buff,sizeof(buff),str->charset());
01237     field->val_str_internal(&tmp);
01238     if (field->is_null())  {
01239       str->append("NULL");
01240     }
01241     else {
01242       str->append('\'');
01243       str->append(tmp);
01244       str->append('\'');
01245     }
01246     return;
01247   }
01248   Item_ident::print(str);
01249 }
01250 
01251 
01252 } /* namespace drizzled */