void Item_func_nullif::update_used_tables()
{
  if (m_cache)
  {
    used_tables_and_const_cache_init();
    used_tables_and_const_cache_update_and_join(m_cache->get_example());
    used_tables_and_const_cache_update_and_join(arg_count, args);
  }
  else
  {
    /*
      MDEV-9712 Performance degradation of nested NULLIF
      No needs to iterate through args[2] when it's just a copy of args[0].
    */
    DBUG_ASSERT(arg_count == 3);
    used_tables_and_const_cache_init();
    used_tables_and_const_cache_update_and_join(args[0] == args[2] ? 2 : 3,
                                                args);
  }
}


MDEV-26402: A SEGV in Item_field::used_tables/update_depend_map_for_order...

When doing condition pushdown from HAVING into WHERE,
Item_equal::create_pushable_equalities() calls
item->set_extraction_flag(IMMUTABLE_FL) for constant items.
Then, Item::cleanup_excluding_immutables_processor() checks for this flag
to see if it should call item->cleanup() or leave the item as-is.

The failure happens when a constant item has a non-constant one inside it,
like:

   (tbl.col=0 AND impossible_cond)

item->walk(cleanup_excluding_immutables_processor) works in a bottom-up
way so it
1. will call Item_func_eq(tbl.col=0)->cleanup()
2. will not call Item_cond_and->cleanup (as the AND is constant)

This creates an item tree where a fixed Item has an un-fixed Item inside
it which eventually causes an assertion failure.

Fixed by introducing this rule: instead of just calling

  item->set_extraction_flag(IMMUTABLE_FL);

we call Item::walk() to set the flag for all sub-items of the item.

  Item *get_copy(THD *thd)
  { return get_item_copy<Item_cache_str>(thd, this); }

MariaDB Server v10.7 and below was discovered to contain a segmentation fault via the component Item_field::used_tables/update_depend_map_for_order.


in_timestamp::in_timestamp(THD *thd, uint elements)
  :in_vector(thd, elements, sizeof(Value), (qsort2_cmp) cmp_timestamp, 0)
{}


Item *Item_equal::transform(THD *thd, Item_transformer transformer, uchar *arg)
{
  DBUG_ASSERT(!thd->stmt_arena->is_stmt_prepare());

  Item *item;
  Item_equal_fields_iterator it(*this);
  while ((item= it++))
  {
    Item *new_item= item->transform(thd, transformer, arg);
    if (!new_item)
      return 0;

    /*
      THD::change_item_tree() should be called only if the tree was
      really transformed, i.e. when a new item has been created.
      Otherwise we'll be allocating a lot of unnecessary memory for
      change records at each execution.
    */
    if (new_item != item)
      thd->change_item_tree((Item **) it.ref(), new_item);
  }
  return Item_func::transform(thd, transformer, arg);
}


  Item_trigger_field(THD *thd, Name_resolution_context *context_arg,
                     row_version_type row_ver_arg,
                     const LEX_CSTRING *field_name_arg,
                     ulong priv, const bool ro)
    :Item_field(thd, context_arg,
               (const char *)NULL, (const char *)NULL, field_name_arg),
     row_version(row_ver_arg), field_idx((uint)-1), original_privilege(priv),
     want_privilege(priv), table_grants(NULL), read_only (ro)
  {}


uchar *in_datetime::get_value(Item *item)
{
  tmp.val= item->val_datetime_packed(current_thd);
  if (item->null_value)
    return 0;
  tmp.unsigned_flag= 1L;
  return (uchar*) &tmp;
}


  Item_hex_constant(THD *thd, const char *str, size_t str_length):
    Item_literal(thd)
  {
    hex_string_init(thd, str, str_length);
  }


  Item_cache_real(THD *thd, const Type_handler *h)
   :Item_cache(thd, h),
    value(0)
  {}


static int cmp_double(void *cmp_arg, double *a,double *b)
{
  return *a < *b ? -1 : *a == *b ? 0 : 1;
}


  Item_string(THD *thd, const char *str, uint length, CHARSET_INFO *cs,
              Derivation dv, uint repertoire)
   :Item_literal(thd)
  {
    str_value.set_or_copy_aligned(str, length, cs);
    fix_and_set_name_from_value(thd, dv, Metadata(&str_value, repertoire));
  }


Item *Item_in_optimizer::transform(THD *thd, Item_transformer transformer,
                                   uchar *argument)
{
  Item *new_item;

  DBUG_ASSERT(fixed);
  DBUG_ASSERT(!thd->stmt_arena->is_stmt_prepare());
  DBUG_ASSERT(arg_count == 2);

  /* Transform the left IN operand. */
  new_item= (*args)->transform(thd, transformer, argument);
  if (!new_item)
    return 0;
  /*
    THD::change_item_tree() should be called only if the tree was
    really transformed, i.e. when a new item has been created.
    Otherwise we'll be allocating a lot of unnecessary memory for
    change records at each execution.
  */
  if ((*args) != new_item)
    thd->change_item_tree(args, new_item);

  if (invisible_mode())
  {
    /* MAX/MIN transformed => pass through */
    new_item= args[1]->transform(thd, transformer, argument);
    if (!new_item)
      return 0;
    if (args[1] != new_item)
      thd->change_item_tree(args + 1, new_item);
  }
  else
  {
    /*
      Transform the right IN operand which should be an Item_in_subselect or a
      subclass of it. The left operand of the IN must be the same as the left
      operand of this Item_in_optimizer, so in this case there is no further
      transformation, we only make both operands the same.
      TODO: is it the way it should be?
    */
    DBUG_ASSERT((args[1])->type() == Item::SUBSELECT_ITEM &&
                (((Item_subselect*)(args[1]))->substype() ==
                 Item_subselect::IN_SUBS ||
                 ((Item_subselect*)(args[1]))->substype() ==
                 Item_subselect::ALL_SUBS ||
                 ((Item_subselect*)(args[1]))->substype() ==
                 Item_subselect::ANY_SUBS));

    Item_in_subselect *in_arg= (Item_in_subselect*)args[1];
    thd->change_item_tree(&in_arg->left_expr, args[0]);
  }
  return (this->*transformer)(thd, argument);
}


  Load_data_outvar *get_load_data_outvar_or_error()
  {
    Load_data_outvar *dst= get_load_data_outvar();
    if (dst)
      return dst;
    my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), name.str);
    return NULL;
  }


  Item *get_copy(THD *thd)
  { return get_item_copy<Item_cache_float>(thd, this); }


  virtual void make_send_field(THD *thd, Send_field *field)
  { orig_item->make_send_field(thd, field); }


longlong Item_func_between::val_int_cmp_real()
{
  double value= args[0]->val_real(),a,b;
  if ((null_value=args[0]->null_value))
    return 0;					/* purecov: inspected */
  a= args[1]->val_real();
  b= args[2]->val_real();
  if (!args[1]->null_value && !args[2]->null_value)
    return (longlong) ((value >= a && value <= b) != negated);
  if (args[1]->null_value && args[2]->null_value)
    null_value= true;
  else if (args[1]->null_value)
  {
    null_value= value <= b;			// not null if false range.
  }
  else
  {
    null_value= value >= a;
  }
  return (longlong) (!null_value && negated);
}


longlong Item_func_in::val_int()
{
  DBUG_ASSERT(fixed == 1);
  if (array)
  {
    bool tmp=array->find(args[0]);
    /*
      NULL on left -> UNKNOWN.
      Found no match, and NULL on right -> UNKNOWN.
      NULL on right can never give a match, as it is not stored in
      array.
      See also the 'bisection_possible' variable in fix_length_and_dec().
    */
    null_value=args[0]->null_value || (!tmp && have_null);
    return (longlong) (!null_value && tmp != negated);
  }

  if ((null_value= args[0]->real_item()->type() == NULL_ITEM))
    return 0;

  null_value= have_null;
  uint idx;
  if (!Predicant_to_list_comparator::cmp(this, &idx, &null_value))
  {
    null_value= false;
    return (longlong) (!negated);
  }
  return (longlong) (!null_value && negated);
}


bool vcol_assignment_allowed_value() const { return vcol_assignment_ok; }


  Item *get_copy(THD *thd)
  { return get_item_copy<Item_int>(thd, this); }


bool Item_equal::count_sargable_conds(void *arg)
{
  SELECT_LEX *sel= (SELECT_LEX *) arg;
  uint m= equal_items.elements;
  sel->cond_count+= m*(m-1);
  return 0;
}


longlong Item_func_not_all::val_int()
{
  DBUG_ASSERT(fixed == 1);
  bool value= args[0]->val_bool();

  /*
    return TRUE if there was records in underlying select in max/min
    optimization (ALL subquery)
  */
  if (empty_underlying_subquery())
    return 1;

  null_value= args[0]->null_value;
  return ((!null_value && value == 0) ? 1 : 0);
}


  bool check_vcol_func_processor(void *arg)
  {
    return mark_unsupported_function("value()", arg, VCOL_IMPOSSIBLE);
  }


virtual String *val_raw(String*) { return 0; }


void Item_cond::neg_arguments(THD *thd)
{
  List_iterator<Item> li(list);
  Item *item;
  while ((item= li++))		/* Apply not transformation to the arguments */
  {
    Item *new_item= item->neg_transformer(thd);
    if (!new_item)
    {
      if (!(new_item= new (thd->mem_root) Item_func_not(thd, item)))
	return;					// Fatal OEM error
    }
    (void) li.replace(new_item);
  }
}


bool Item_cond::excl_dep_on_table(table_map tab_map)
{
  if (used_tables() & OUTER_REF_TABLE_BIT)
    return false;
  if (!(used_tables() & ~tab_map))
    return true;
  List_iterator_fast<Item> li(list);
  Item *item;
  while ((item= li++))
  {
    if (!item->excl_dep_on_table(tab_map))
      return false;
  }
  return true;
}


inline bool Virtual_column_info::is_equal(const Virtual_column_info* vcol) const
{
  return type_handler()  == vcol->type_handler()
      && stored_in_db == vcol->is_stored()
      && expr->eq(vcol->expr, true);
}


void Predicant_to_list_comparator::
       detect_unique_handlers(Type_handler_hybrid_field_type *compatible,
                              uint *unique_count,
                              uint *found_types)
{
  *unique_count= 0;
  *found_types= 0;
  for (uint i= 0; i < m_comparator_count; i++)
  {
    uint idx;
    if (find_handler(&idx, m_comparators[i].m_handler, i))
    {
      m_comparators[i].m_handler_index= i; // New unique handler
      (*unique_count)++;
      (*found_types)|= 1U << m_comparators[i].m_handler->cmp_type();
      compatible->set_handler(m_comparators[i].m_handler);
    }
    else
    {
      m_comparators[i].m_handler_index= idx; // Non-unique handler
    }
  }
}


bool Arg_comparator::set_cmp_func_time()
{
  THD *thd= current_thd;
  m_compare_collation= &my_charset_numeric;
  func= is_owner_equal_func() ? &Arg_comparator::compare_e_time :
                                &Arg_comparator::compare_time;
  a= cache_converted_constant(thd, a, &a_cache, compare_type_handler());
  b= cache_converted_constant(thd, b, &b_cache, compare_type_handler());
  return false;
}


void Item_cond_and::mark_as_condition_AND_part(TABLE_LIST *embedding)
{
  List_iterator<Item> li(list);
  Item *item;
  while ((item=li++))
  {
    item->mark_as_condition_AND_part(embedding);
  }
}


  Item_float(THD *thd, double value_par, uint decimal_par):
    Item_num(thd), presentation(0), value(value_par)
  {
    decimals= (uint8) decimal_par;
  }


  bool send(Protocol *protocol, st_value *buffer)
  {
    DBUG_ASSERT(0);
    return true;
  }


  Item *get_copy(THD *thd)
  { return get_item_copy<Item_cache_decimal>(thd, this); }


longlong Item_func_regexp_instr::val_int()
{
  DBUG_ASSERT(fixed == 1);
  if ((null_value= re.recompile(args[1])))
    return 0;

  if ((null_value= re.exec(args[0], 0, 1)))
    return 0;

  return re.match() ? re.subpattern_start(0) + 1 : 0;
}


Item** addr(uint i) { return this_item()->addr(i); }


  double val_real()
  {
    return double_from_string_with_check(&str_value);
  }


bool Item_func_case::native_op(THD *thd, Native *to)
{
  DBUG_ASSERT(fixed == 1);
  Item *item= find_item();
  if (!item)
    return (null_value= true);
  return val_native_with_conversion_from_item(thd, item, to, type_handler());
}


inline void Item_func_case::print_else_argument(String *str,
                                                enum_query_type query_type,
                                                Item *item)
{
  str->append(STRING_WITH_LEN("else "));
  item->print(str, query_type);
  str->append(' ');
}


  Item *get_copy(THD *thd)
  { return get_item_copy<Item_direct_view_ref>(thd, this); }


  Item *get_copy(THD *thd)
  { return get_item_copy<Item_string>(thd, this); }


  bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
  {
    return get_date_from_string(thd, ltime, fuzzydate);
  }


bool const_item() const { return false; }


Item_result_field *item_result_field() const { return m_item_result_field; }


bool Arg_comparator::set_cmp_func_string()
{
  THD *thd= current_thd;
  func= is_owner_equal_func() ? &Arg_comparator::compare_e_string :
                                &Arg_comparator::compare_string;
  if (compare_type() == STRING_RESULT &&
      (*a)->result_type() == STRING_RESULT &&
      (*b)->result_type() == STRING_RESULT)
  {
    /*
      We must set cmp_collation here as we may be called from for an automatic
      generated item, like in natural join
    */
    if (owner->agg_arg_charsets_for_comparison(&m_compare_collation, a, b))
      return true;

    if ((*a)->type() == Item::FUNC_ITEM &&
        ((Item_func *) (*a))->functype() == Item_func::JSON_EXTRACT_FUNC)
    {
      func= is_owner_equal_func() ? &Arg_comparator::compare_e_json_str:
                                    &Arg_comparator::compare_json_str;
      return 0;
    }
    else if ((*b)->type() == Item::FUNC_ITEM &&
             ((Item_func *) (*b))->functype() == Item_func::JSON_EXTRACT_FUNC)
    {
      func= is_owner_equal_func() ? &Arg_comparator::compare_e_json_str:
                                    &Arg_comparator::compare_str_json;
      return 0;
    }
  }

  a= cache_converted_constant(thd, a, &a_cache, compare_type_handler());
  b= cache_converted_constant(thd, b, &b_cache, compare_type_handler());
  return false;
}


double Item_func_case::real_op()
{
  DBUG_ASSERT(fixed == 1);
  Item *item= find_item();
  double res;

  if (!item)
  {
    null_value=1;
    return 0;
  }
  res= item->val_real();
  null_value=item->null_value;
  return res;
}


  virtual ~Item()
  {
#ifdef EXTRA_DEBUG
    name.str= 0;
    name.length= 0;
#endif
  }		/*lint -e1509 */


bool Item_func_between::fix_length_and_dec_temporal(THD *thd)
{
  if (!thd->lex->is_ps_or_view_context_analysis())
  {
    for (uint i= 0; i < 3; i ++)
    {
      if (args[i]->const_item() &&
          args[i]->type_handler_for_comparison() != m_comparator.type_handler())
      {
        Item_cache *cache= m_comparator.type_handler()->Item_get_cache(thd, args[i]);
        if (!cache || cache->setup(thd, args[i]))
          return true;
        thd->change_item_tree(&args[i], cache);
      }
    }
  }
  return false;
}


  void reset_buffer()
  {
    m_string.set(buffer, buffer_size, &my_charset_bin);
  }


longlong val_int() { return has_value() ? Date(this).to_longlong() : 0; }


void Item_cond::traverse_cond(Cond_traverser traverser,
                              void *arg, traverse_order order)
{
  List_iterator<Item> li(list);
  Item *item;

  switch(order) {
  case(PREFIX):
    (*traverser)(this, arg);
    while ((item= li++))
    {
      item->traverse_cond(traverser, arg, order);
    }
    (*traverser)(NULL, arg);
    break;
  case(POSTFIX):
    while ((item= li++))
    {
      item->traverse_cond(traverser, arg, order);
    }
    (*traverser)(this, arg);
  }
}


inline bool Item_sp_variable::send(Protocol *protocol, st_value *buffer)
{
  return this_item()->send(protocol, buffer);
}


  bool pushable_cond_checker_for_subquery(uchar *arg)
  {
    return excl_dep_on_in_subq_left_part((Item_in_subselect *)arg);
  }


void Item_func_decode_oracle::print(String *str, enum_query_type query_type)
{
  str->append(func_name());
  str->append('(');
  args[0]->print(str, query_type);
  for (uint i= 1, count= when_count() ; i <= count; i++)
  {
    str->append(',');
    args[i]->print(str, query_type);
    str->append(',');
    args[i+count]->print(str, query_type);
  }
  Item **else_expr= Item_func_case_simple::else_expr_addr();
  if (else_expr)
  {
    str->append(',');
    (*else_expr)->print(str, query_type);
  }
  str->append(')');
}


longlong Item_func_gt::val_int()
{
  DBUG_ASSERT(fixed == 1);
  int value= cmp.compare();
  return value > 0 ? 1 : 0;
}


Item *Item_func_lt::negated_item(THD *thd) /* a < b  ->  a >= b */
{
  return new (thd->mem_root) Item_func_ge(thd, args[0], args[1]);
}


  bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode)
  {
    return decimal_to_datetime_with_warn(thd, VDec(this).ptr(), to, mode,
                                         NULL, NULL);
  }


void in_double::set(uint pos,Item *item)
{
  ((double*) base)[pos]= item->val_real();
}


bool is_evaluable_expression() const { return false; }


  bool fix_fields(THD *thd, Item **it)
  {
    if ((*ref)->fix_fields_if_needed_for_scalar(thd, ref))
      return TRUE;
    return Item_ref::fix_fields(thd, it);
  }


cmp_item *cmp_item_time::make_same()
{
  return new cmp_item_time();
}


  bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
  {
    DBUG_ASSERT(sane());
    bool res= m_value.to_TIME(thd, ltime, fuzzydate);
    DBUG_ASSERT(!res);
    return null_value || res;
  }


const Type_handler *type_handler() const { return &type_handler_row; }


my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value)
{
  DBUG_ASSERT(fixed == 1);
  null_value= 0;
  for (uint i= 0; i < arg_count; i++)
  {
    my_decimal *res= args[i]->val_decimal(decimal_value);
    if (!args[i]->null_value)
      return res;
  }
  null_value=1;
  return 0;
}


Item_copy_timestamp(THD *thd, Item *arg): Item_copy(thd, arg) { }


  virtual bool val_bool()
  {
    return type_handler()->Item_val_bool(this);
  }


  ValueBuffer()
  {
    reset_buffer();
  }


  Item *get_copy(THD *thd)
  { return get_item_copy<Item_ref_null_helper>(thd, this); }


bool Item_func_case_searched::fix_length_and_dec()
{
  THD *thd= current_thd;
  return aggregate_then_and_else_arguments(thd, when_count());
}


Item_basic_constant(THD *thd): Item_basic_value(thd) {};


Item_bool_rowready_func2* Lt_creator::create(THD *thd, Item *a, Item *b) const
{
  return new(thd->mem_root) Item_func_lt(thd, a, b);
}


bool Item_equal::contains(Field *field)
{
  Item_equal_fields_iterator it(*this);
  while (it++)
  {
    if (field->eq(it.get_curr_field()))
        return 1;
  }
  return 0;
}


  double val_real()
  {
    return has_value() ? Datetime(this).to_double() : 0;
  }


Item *Item_func_not::neg_transformer(THD *thd)	/* NOT(x)  ->  x */
{
  return args[0];
}


bool Item_func_like::with_sargable_pattern() const
{
  if (negated)
    return false;

  if (!args[1]->const_item() || args[1]->is_expensive())
    return false;

  String* res2= args[1]->val_str((String *) &cmp_value2);
  if (!res2)
    return false;

  if (!res2->length()) // Can optimize empty wildcard: column LIKE ''
    return true;

  DBUG_ASSERT(res2->ptr());
  char first= res2->ptr()[0];
  return first != wild_many && first != wild_one;
}


virtual bool with_subquery() const { DBUG_ASSERT(is_fixed()); return false; }


bool Arg_comparator::set_cmp_func_decimal()
{
  THD *thd= current_thd;
  func= is_owner_equal_func() ? &Arg_comparator::compare_e_decimal :
                                &Arg_comparator::compare_decimal;
  a= cache_converted_constant(thd, a, &a_cache, compare_type_handler());
  b= cache_converted_constant(thd, b, &b_cache, compare_type_handler());
  return false;
}


  bool eq(const Item *item, bool binary_cmp) const
  {
    return false;
  }


bool Item_func_case_simple::fix_length_and_dec()
{
  THD *thd= current_thd;
  return (aggregate_then_and_else_arguments(thd, when_count() + 1) ||
          aggregate_switch_and_when_arguments(thd, false));
}


  my_decimal *val_decimal(my_decimal *dec)
  {
    return can_return_value() ? value.val_decimal(dec, this) : NULL;
  }


  Item_datetime_literal_for_invalid_dates(THD *thd,
                                          const Datetime *ltime, uint dec_arg)
   :Item_datetime_literal(thd, ltime, dec_arg)
  {
    maybe_null= false;
  }


bool Item_in_optimizer::is_null()
{
  val_int();
  return null_value;
}


virtual bool is_order_clause_position() const { return false; }


Item *and_expressions(THD *thd, Item *a, Item *b, Item **org_item)
{
  if (!a)
    return (*org_item= (Item*) b);
  if (a == *org_item)
  {
    Item_cond *res;
    if ((res= new (thd->mem_root) Item_cond_and(thd, a, (Item*) b)))
    {
      res->used_tables_cache= a->used_tables() | b->used_tables();
      res->not_null_tables_cache= a->not_null_tables() | b->not_null_tables();
    }
    return res;
  }
  if (((Item_cond_and*) a)->add((Item*) b, thd->mem_root))
    return 0;
  ((Item_cond_and*) a)->used_tables_cache|= b->used_tables();
  ((Item_cond_and*) a)->not_null_tables_cache|= b->not_null_tables();
  return a;
}


  bool const_item() const
  {
    return state != NO_VALUE;
  }


Item** addr(uint i) { return arg_count ? args + i : NULL; }


longlong Item_func_bit_and::val_int()
{
  DBUG_ASSERT(fixed == 1);
  ulonglong arg1= (ulonglong) args[0]->val_int();
  if (args[0]->null_value)
  {
    null_value=1; /* purecov: inspected */
    return 0; /* purecov: inspected */
  }
  ulonglong arg2= (ulonglong) args[1]->val_int();
  if (args[1]->null_value)
  {
    null_value=1; /* purecov: inspected */
    return 0; /* purecov: inspected */
  }
  null_value=0;
  return (longlong) (arg1 & arg2);
}


String *Item_func_case::str_op(String *str)
{
  DBUG_ASSERT(fixed == 1);
  String *res;
  Item *item= find_item();

  if (!item)
  {
    null_value=1;
    return 0;
  }
  null_value= 0;
  if (!(res=item->val_str(str)))
    null_value= 1;
  return res;
}


int Arg_comparator::compare_e_datetime()
{
  THD *thd= current_thd;
  longlong val1= (*a)->val_datetime_packed(thd);
  longlong val2= (*b)->val_datetime_packed(thd);
  if ((*a)->null_value || (*b)->null_value)
    return MY_TEST((*a)->null_value && (*b)->null_value);
  return MY_TEST(val1 == val2);
}


void set_default_field(Field *field) { m_default_field= field; }


bool Item_func_truth::val_bool()
{
  bool val= args[0]->val_bool();
  if (args[0]->null_value)
  {
    /*
      NULL val IS {TRUE, FALSE} --> FALSE
      NULL val IS NOT {TRUE, FALSE} --> TRUE
    */
    return (! affirmative);
  }

  if (affirmative)
  {
    /* {TRUE, FALSE} val IS {TRUE, FALSE} value */
    return (val == value);
  }

  /* {TRUE, FALSE} val IS NOT {TRUE, FALSE} value */
  return (val != value);
}


  bool alloc_and_extract_row_elements(THD *thd, const Item_args *rows, uint pos)
  {
    DBUG_ASSERT(rows->argument_count() > 0);
    DBUG_ASSERT(rows->arguments()[0]->cols() > pos);
    if (alloc_arguments(thd, rows->argument_count()))
      return true;
    for (uint i= 0; i < rows->argument_count(); i++)
    {
      DBUG_ASSERT(rows->arguments()[0]->cols() == rows->arguments()[i]->cols());
      Item *arg= rows->arguments()[i]->element_index(pos);
      add_argument(arg);
    }
    DBUG_ASSERT(argument_count() == rows->argument_count());
    return false;
  }


bool Item_func_like::fix_fields(THD *thd, Item **ref)
{
  DBUG_ASSERT(fixed == 0);
  if (Item_bool_func2::fix_fields(thd, ref) ||
      escape_item->fix_fields_if_needed_for_scalar(thd, &escape_item) ||
      fix_escape_item(thd, escape_item, &cmp_value1, escape_used_in_parsing,
                      cmp_collation.collation, &escape))
    return TRUE;

  if (escape_item->const_item())
  {
    /*
      We could also do boyer-more for non-const items, but as we would have to
      recompute the tables for each row it's not worth it.
    */
    if (args[1]->const_item() && !use_strnxfrm(collation.collation) &&
        !args[1]->is_expensive())
    {
      String* res2= args[1]->val_str(&cmp_value2);
      if (!res2)
        return FALSE;				// Null argument

      const size_t len= res2->length();

      /*
        len must be > 2 ('%pattern%')
        heuristic: only do TurboBM for pattern_len > 2
      */
      if (len <= 2)
        return FALSE;

      const char*  first= res2->ptr();
      const char*  last=  first + len - 1;

      if (len > MIN_TURBOBM_PATTERN_LEN + 2 &&
          *first == wild_many &&
          *last  == wild_many)
      {
        const char* tmp = first + 1;
        for (; *tmp != wild_many && *tmp != wild_one && *tmp != escape; tmp++) ;
        canDoTurboBM = (tmp == last) && !use_mb(args[0]->collation.collation);
      }
      if (canDoTurboBM)
      {
        pattern_len = (int) len - 2;
        pattern     = thd->strmake(first + 1, pattern_len);
        DBUG_PRINT("info", ("Initializing pattern: '%s'", first));
        int *suff = (int*) thd->alloc((int) (sizeof(int)*
                                      ((pattern_len + 1)*2+
                                      alphabet_size)));
        bmGs      = suff + pattern_len + 1;
        bmBc      = bmGs + pattern_len + 1;
        turboBM_compute_good_suffix_shifts(suff);
        turboBM_compute_bad_character_shifts();
        DBUG_PRINT("info",("done"));
      }
      use_sampling= (len > 2 && (*first == wild_many || *first == wild_one));
    }
  }
  return FALSE;
}


inline bool TABLE::mark_column_with_deps(Field *field)
{
  bool res;
  if (!(res= bitmap_fast_test_and_set(read_set, field->field_index)))
  {
    if (field->vcol_info)
      mark_virtual_column_deps(field);
  }
  return res;
}


  Field *create_field_for_schema(THD *thd, TABLE *table)
  { return tmp_table_field_from_field_type(table); }


  Item_string(THD *thd, const String *str, CHARSET_INFO *tocs, uint *conv_errors,
              Derivation dv, uint repertoire)
   :Item_literal(thd)
  {
    if (str_value.copy(str, tocs, conv_errors))
      str_value.set("", 0, tocs); // EOM ?
    str_value.mark_as_const();
    fix_and_set_name_from_value(thd, dv, Metadata(&str_value, repertoire));
  }


  Item_string(THD *thd, CHARSET_INFO *csi, const char *str_arg, uint length_arg)
   :Item_literal(thd)
  {
    collation.set(csi, DERIVATION_COERCIBLE);
    set_name(thd, NULL, 0, system_charset_info);
    decimals= NOT_FIXED_DEC;
    str_value.copy(str_arg, length_arg, csi);
    max_length= str_value.numchars() * csi->mbmaxlen;
  }


  bool val_native(THD *thd, Native *to)
  {
    return has_value() ? Time(thd, this).to_native(to, decimals) : true;
  }


  my_decimal *val_decimal_from_item(Item *item, my_decimal *decimal_value)
  {
    DBUG_ASSERT(is_fixed());
    my_decimal *value= item->val_decimal(decimal_value);
    if ((null_value= item->null_value))
      value= NULL;
    return value;
  }


  bool walk(Item_processor processor, bool walk_subquery, void *arg)
  {
    if (arg == STOP_PTR)
      return FALSE;
    if (example && example->walk(processor, walk_subquery, arg))
      return TRUE;
    return (this->*processor)(arg);
  }


void Item_in_optimizer::restore_first_argument()
{
  if (!invisible_mode())
  {
    args[0]= ((Item_in_subselect *)args[1])->left_expr;
  }
}


  Item_cache_date(THD *thd)
   :Item_cache_temporal(thd, &type_handler_newdate) { }


Item *Item_cond::propagate_equal_fields(THD *thd,
                                        const Context &ctx,
                                        COND_EQUAL *cond)
{
  DBUG_ASSERT(!thd->stmt_arena->is_stmt_prepare());
  DBUG_ASSERT(arg_count == 0);
  List_iterator<Item> li(list);
  while (li++)
  {
    /*
      The exact value of the last parameter to propagate_and_change_item_tree()
      is not important at this point. Item_func derivants will create and
      pass their own context to the arguments.
    */
    propagate_and_change_item_tree(thd, li.ref(), cond, Context_boolean());
  }
  return this;
}


longlong Item_func_interval::val_int()
{
  DBUG_ASSERT(fixed == 1);
  double value;
  my_decimal dec_buf, *dec= NULL;
  uint i;

  if (use_decimal_comparison)
  {
    dec= row->element_index(0)->val_decimal(&dec_buf);
    if (row->element_index(0)->null_value)
      return -1;
    my_decimal2double(E_DEC_FATAL_ERROR, dec, &value);
  }
  else
  {
    value= row->element_index(0)->val_real();
    if (row->element_index(0)->null_value)
      return -1;
  }

  if (intervals)
  {					// Use binary search to find interval
    uint start,end;
    start= 0;
    end=   row->cols()-2;
    while (start != end)
    {
      uint mid= (start + end + 1) / 2;
      interval_range *range= intervals + mid;
      my_bool cmp_result;
      /*
        The values in the range interval may have different types,
        Only do a decimal comparison if the first argument is a decimal
        and we are comparing against a decimal
      */
      if (dec && range->type == DECIMAL_RESULT)
        cmp_result= my_decimal_cmp(&range->dec, dec) <= 0;
      else
        cmp_result= (range->dbl <= value);
      if (cmp_result)
	start= mid;
      else
	end= mid - 1;
    }
    interval_range *range= intervals+start;
    return ((dec && range->type == DECIMAL_RESULT) ?
            my_decimal_cmp(dec, &range->dec) < 0 :
            value < range->dbl) ? 0 : start + 1;
  }

  for (i=1 ; i < row->cols() ; i++)
  {
    Item *el= row->element_index(i);
    if (use_decimal_comparison &&
        ((el->result_type() == DECIMAL_RESULT) ||
         (el->result_type() == INT_RESULT)))
    {
      VDec e_dec(el);
      /* Skip NULL ranges. */
      if (e_dec.is_null())
        continue;
      if (e_dec.cmp(dec) > 0)
        return i - 1;
    }
    else
    {
      double val= el->val_real();
      /* Skip NULL ranges. */
      if (el->null_value)
        continue;
      if (val > value)
        return i - 1;
    }
  }
  return i-1;
}


int Arg_comparator::compare_str_json()
{
  return -compare_json_str_basic(*b, *a);
}


  bool eq(const Item_args *other, bool binary_cmp) const
  {
    for (uint i= 0; i < arg_count ; i++)
    {
      if (!args[i]->eq(other->args[i], binary_cmp))
        return false;
    }
    return true;
  }


void Item_equal::merge(THD *thd, Item_equal *item)
{
  Item *c= item->get_const();
  if (c)
    item->equal_items.pop();
  equal_items.append(&item->equal_items);
  if (c)
  {
    /*
      The flag cond_false will be set to TRUE after this if
      the multiple equality already contains a constant and its
      value is not equal to the value of c.
    */
    add_const(thd, c);
  }
  cond_false|= item->cond_false;
}


  Item *get_copy(THD *thd)
  { return get_item_copy<Item_ignore_specification>(thd, this); }


  Tmp_field_src()
   :m_field(0),
    m_default_field(0),
    m_item_result_field(0)
  { }


  void set_geometry_type(uint type)
  {
    DBUG_ASSERT(0);
  }


  my_decimal *val_decimal(my_decimal *to)
  {
    return has_value() ? Time(this).to_decimal(to) : NULL;
  }


bool Item_func_truth::fix_length_and_dec()
{
  maybe_null= 0;
  null_value= 0;
  decimals= 0;
  max_length= 1;
  return FALSE;
}


const longlong *const_ptr_longlong() const { return &value; }


bool Regexp_processor_pcre::compile(String *pattern, bool send_error)
{
  const char *pcreErrorStr;
  int pcreErrorOffset;

  if (is_compiled())
  {
    if (!stringcmp(pattern, &m_prev_pattern))
      return false;
    cleanup();
    m_prev_pattern.copy(*pattern);
  }

  if (!(pattern= convert_if_needed(pattern, &pattern_converter)))
    return true;

  m_pcre= pcre_compile(pattern->c_ptr_safe(), m_library_flags,
                       &pcreErrorStr, &pcreErrorOffset, NULL);

  if (unlikely(m_pcre == NULL))
  {
    if (send_error)
    {
      char buff[MAX_FIELD_WIDTH];
      my_snprintf(buff, sizeof(buff), "%s at offset %d", pcreErrorStr, pcreErrorOffset);
      my_error(ER_REGEXP_ERROR, MYF(0), buff);
    }
    return true;
  }
  return false;
}


  bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate)
  {
    *to= ltime;
    return false;
  }


static uint collect_cmp_types(Item **items, uint nitems, bool skip_nulls= FALSE)
{
  uint i;
  uint found_types;
  Item_result left_cmp_type= items[0]->cmp_type();
  DBUG_ASSERT(nitems > 1);
  found_types= 0;
  for (i= 1; i < nitems ; i++)
  {
    if (skip_nulls && items[i]->type() == Item::NULL_ITEM)
      continue; // Skip NULL constant items
    if ((left_cmp_type == ROW_RESULT ||
         items[i]->cmp_type() == ROW_RESULT) &&
        cmp_row_type(items[0], items[i]))
      return 0;
    found_types|= 1U << (uint) item_cmp_type(left_cmp_type, items[i]);
  }
  /*
   Even if all right-hand items are NULLs and we are skipping them all, we need
   at least one type bit in the found_type bitmask.
  */
  if (skip_nulls && !found_types)
    found_types= 1U << (uint) left_cmp_type;
  return found_types;
}


longlong Item_func_between::val_int_cmp_native()
{
  THD *thd= current_thd;
  const Type_handler *h= m_comparator.type_handler();
  NativeBuffer<STRING_BUFFER_USUAL_SIZE> value, a, b;
  if (val_native_with_conversion_from_item(thd, args[0], &value, h))
    return 0;
  bool ra= args[1]->val_native_with_conversion(thd, &a, h);
  bool rb= args[2]->val_native_with_conversion(thd, &b, h);
  if (!ra && !rb)
    return (longlong)
      ((h->cmp_native(value, a) >= 0 &&
        h->cmp_native(value, b) <= 0) != negated);
  if (ra && rb)
    null_value= true;
  else if (ra)
    null_value= h->cmp_native(value, b) <= 0;
  else
    null_value= h->cmp_native(value, a) >= 0;
  return (longlong) (!null_value && negated);
}


  Item *get_copy(THD *thd)
  { return get_item_copy<Item_name_const>(thd, this); }


  double val_real()
  {
    return (double) (ulonglong) Item_hex_hybrid::val_int();
  }


  bool val_native(THD *thd, Native *to)
  {
    return Time(thd, this).to_native(to, decimals);
  }


  Item_date_literal_for_invalid_dates(THD *thd, const Date *ltime)
   :Item_date_literal(thd, ltime)
  {
    maybe_null= false;
  }


void Item_cond::fix_after_pullout(st_select_lex *new_parent, Item **ref,
                                  bool merge)
{
  List_iterator<Item> li(list);
  Item *item;

  used_tables_and_const_cache_init();

  and_tables_cache= ~(table_map) 0; // Here and below we do as fix_fields does
  not_null_tables_cache= 0;

  while ((item=li++))
  {
    table_map tmp_table_map;
    item->fix_after_pullout(new_parent, li.ref(), merge);
    item= *li.ref();
    used_tables_and_const_cache_join(item);

    if (item->const_item())
      and_tables_cache= (table_map) 0;
    else
    {
      tmp_table_map= item->not_null_tables();
      not_null_tables_cache|= tmp_table_map;
      and_tables_cache&= tmp_table_map;
      const_item_cache= FALSE;
    }
  }
}


void cmp_item_row::store_value(Item *item)
{
  DBUG_ENTER("cmp_item_row::store_value");
  DBUG_ASSERT(comparators);
  DBUG_ASSERT(n == item->cols());
  item->bring_value();
  item->null_value= 0;
  for (uint i=0; i < n; i++)
  {
    DBUG_ASSERT(comparators[i]);
    comparators[i]->store_value(item->element_index(i));
    item->null_value|= item->element_index(i)->null_value;
  }
  DBUG_VOID_RETURN;
}


  uint cols() const
  { return result_type() == ROW_RESULT ? orig_item->cols() : 1; }


TYPELIB *get_typelib() const { return NULL; }


virtual const Item_const *get_item_const() const { return NULL; }


    void swap(PValue_simple &other)
    {
      swap_variables(PValue_simple, *this, other);
    }


  Item *get_copy(THD *thd)
  { return get_item_copy<Item_cache_wrapper>(thd, this); }


void Item_func_case_searched::print(String *str, enum_query_type query_type)
{
  Item **pos;
  str->append(STRING_WITH_LEN("case "));
  print_when_then_arguments(str, query_type, &args[0], when_count());
  if ((pos= Item_func_case_searched::else_expr_addr()))
    print_else_argument(str, query_type, pos[0]);
  str->append(STRING_WITH_LEN("end"));
}


  virtual bool with_subquery() const
  {
    return (*ref)->with_subquery();
  }


Item_func_nullif::is_null()
{
  return (null_value= (!compare() ? 1 : args[2]->is_null()));
}


  Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
                             const Tmp_field_param *param)
  {
    return Item_type_holder::real_type_handler()->
           make_and_init_table_field(&name, Record_addr(maybe_null),
                                     *this, table);
  }


my_decimal *Item_func_ifnull::decimal_op(my_decimal *decimal_value)
{
  DBUG_ASSERT(fixed == 1);
  my_decimal *value= args[0]->val_decimal(decimal_value);
  if (!args[0]->null_value)
  {
    null_value= 0;
    return value;
  }
  value= args[1]->val_decimal(decimal_value);
  if ((null_value= args[1]->null_value))
    return 0;
  return value;
}


  Item *get_copy(THD *thd)
  { return get_item_copy<Item_cache_date>(thd, this); }


int cmp_item_row::cmp(Item *arg)
{
  arg->null_value= 0;
  if (arg->cols() != n)
  {
    my_error(ER_OPERAND_COLUMNS, MYF(0), n);
    return 1;
  }
  bool was_null= 0;
  arg->bring_value();
  for (uint i=0; i < n; i++)
  {
    const int rc= comparators[i]->cmp(arg->element_index(i));
    switch (rc)
    {
    case UNKNOWN:
      was_null= true;
      break;
    case TRUE:
      return TRUE;
    case FALSE:
      break;                                    // elements #i are equal
    }
    arg->null_value|= arg->element_index(i)->null_value;
  }
  return was_null ? UNKNOWN : FALSE;
}


  bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems,
                        uint flags, int item_sep)
  {
    return Type_std_attributes::agg_arg_charsets(c, func_name(),
                                                 items, nitems,
                                                 flags, item_sep);
  }


  virtual Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg)
  { return this; }


Item_num(THD *thd): Item_literal(thd) { collation.set_numeric(); }


cmp_item* cmp_item_sort_string::make_same()
{
  return new cmp_item_sort_string_in_static(cmp_charset);
}


int cmp_item_datetime::cmp_not_null(const Value *val)
{
  DBUG_ASSERT(!val->is_null());
  DBUG_ASSERT(val->is_temporal());
  return value != pack_time(&val->value.m_time);
}


Item_bool_rowready_func2* Ge_creator::create(THD *thd, Item *a, Item *b) const
{
  return new(thd->mem_root) Item_func_ge(thd, a, b);
}


void in_row::set(uint pos, Item *item)
{
  DBUG_ENTER("in_row::set");
  DBUG_PRINT("enter", ("pos: %u  item: %p", pos,item));
  ((cmp_item_row*) base)[pos].store_value_by_template(current_thd, &tmp, item);
  DBUG_VOID_RETURN;
}


int cmp_item_timestamp::cmp_not_null(const Value *val)
{
  /*
    This method will be implemented when we add this syntax:
      SELECT TIMESTAMP WITH LOCAL TIME ZONE '2001-01-01 10:20:30'
    For now TIMESTAMP is compared to non-TIMESTAMP using DATETIME.
  */
  DBUG_ASSERT(0);
  return 0;
}


Item_func_nullif::str_op(String *str)
{
  DBUG_ASSERT(fixed == 1);
  String *res;
  if (!compare())
  {
    null_value=1;
    return 0;
  }
  res= args[2]->val_str(str);
  null_value= args[2]->null_value;
  return res;
}


  String *val_str(String *to)
  {
    return update_null() ? NULL : cached_time.to_string(to, decimals);
  }


  bool val_native(THD *thd, Native *to)
  {
    return m_value.to_native(to, decimals);
  }


void Regexp_processor_pcre::fix_owner(Item_func *owner,
                                      Item *subject_arg,
                                      Item *pattern_arg)
{
  if (!is_compiled() && pattern_arg->const_item())
  {
    if (compile(pattern_arg, true))
    {
      owner->maybe_null= 1; // Will always return NULL
      return;
    }
    set_const(true);
    owner->maybe_null= subject_arg->maybe_null;
  }
  else
    owner->maybe_null= 1;
}


  Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg)
  { return convert_to_basic_const_item(thd); }


  int save_in_field(Field *field_arg, bool no_conversions)
  {
    return field_arg->save_in_field_default_value(false);
  }


longlong Item_equal::val_int()
{
  if (cond_false)
    return 0;
  if (cond_true)
    return 1;
  Item *item= get_const();
  Item_equal_fields_iterator it(*this);
  if (!item)
    item= it++;
  eval_item->store_value(item);
  if ((null_value= item->null_value))
    return 0;
  while ((item= it++))
  {
    Field *field= it.get_curr_field();
    /* Skip fields of tables that has not been read yet */
    if (!field->table->status || (field->table->status & STATUS_NULL_ROW))
    {
      const int rc= eval_item->cmp(item);
      if ((rc == TRUE) || (null_value= (rc == UNKNOWN)))
        return 0;
    }
  }
  return 1;
}


void in_string::set(uint pos,Item *item)
{
  String *str=((String*) base)+pos;
  String *res=item->val_str(str);
  if (res && res != str)
  {
    if (res->uses_buffer_owned_by(str))
      res->copy();
    if (item->type() == Item::FUNC_ITEM)
      str->copy(*res);
    else
      *str= *res;
  }
  if (!str->charset())
  {
    CHARSET_INFO *cs;
    if (!(cs= item->collation.collation))
      cs= &my_charset_bin;		// Should never happen for STR items
    str->set_charset(cs);
  }
}


  Item_string(THD *thd, CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE):
    Item_literal(thd)
  {
    collation.set(cs, dv);
    max_length= 0;
    set_name(thd, NULL, 0, system_charset_info);
    decimals= NOT_FIXED_DEC;
  }


  bool val_native(THD *thd, Native *to)
  {
    DBUG_ASSERT(sane());
    return null_value || m_value.to_native(to, decimals);
  }


Item_cache_decimal(THD *thd): Item_cache(thd, &type_handler_newdecimal) {}


  Item *get_copy(THD *thd)
  { return get_item_copy<Item_timestamp_literal>(thd, this); }


Item_func_ifnull::real_op()
{
  DBUG_ASSERT(fixed == 1);
  double value= args[0]->val_real();
  if (!args[0]->null_value)
  {
    null_value=0;
    return value;
  }
  value= args[1]->val_real();
  if ((null_value=args[1]->null_value))
    return 0.0;
  return value;
}


  virtual void unfix_fields()
  {
    DBUG_ASSERT(0);
  }


  bool table_cant_handle_bit_fields() const
  { return m_table_cant_handle_bit_fields; }


void in_time::set(uint pos,Item *item)
{
  struct packed_longlong *buff= &((packed_longlong*) base)[pos];

  buff->val= item->val_time_packed(current_thd);
  buff->unsigned_flag= 1L;
}


bool Arg_comparator::set_cmp_func_for_row_arguments()
{
  uint n= (*a)->cols();
  if (n != (*b)->cols())
  {
    my_error(ER_OPERAND_COLUMNS, MYF(0), n);
    comparators= 0;
    return true;
  }
  if (!(comparators= new Arg_comparator[n]))
    return true;
  for (uint i=0; i < n; i++)
  {
    if ((*a)->element_index(i)->cols() != (*b)->element_index(i)->cols())
    {
      my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->element_index(i)->cols());
      return true;
    }
    if (comparators[i].set_cmp_func(owner, (*a)->addr(i),
                                           (*b)->addr(i), set_null))
      return true;
  }
  return false;
}


  Item_hex_string(THD *thd, const char *str, size_t str_length):
    Item_hex_constant(thd, str, str_length) {}


uchar *in_row::get_value(Item *item)
{
  tmp.store_value(item);
  if (item->is_null())
    return 0;
  return (uchar *)&tmp;
}


  uint uint_geometry_type() const
  { return get_geometry_type(); }


  enum Type type() const
  {
    // Don't pretend to be a constant unless value for this item is set.
    switch (state) {
    case NO_VALUE:         return PARAM_ITEM;
    case NULL_VALUE:       return NULL_ITEM;
    case SHORT_DATA_VALUE: return CONST_ITEM;
    case LONG_DATA_VALUE:  return CONST_ITEM;
    case DEFAULT_VALUE:    return PARAM_ITEM;
    case IGNORE_VALUE:     return PARAM_ITEM;
    }
    DBUG_ASSERT(0);
    return PARAM_ITEM;
  }


void Item_equal::add_const(THD *thd, Item *c)
{
  if (cond_false)
    return;
  if (!with_const)
  {
    with_const= TRUE;
    equal_items.push_front(c, thd->mem_root);
    return;
  }

  /*
    Suppose we have an expression (with a string type field) like this:
      WHERE field=const1 AND field=const2 ...

    For all pairs field=constXXX we know that:

    - Item_func_eq::fix_length_and_dec() performed collation and character
    set aggregation and added character set converters when needed.
    Note, the case like:
      WHERE field=const1 COLLATE latin1_bin AND field=const2
    is not handled here, because the field would be replaced to
    Item_func_set_collation, which cannot get into Item_equal.
    So all constXXX that are handled by Item_equal
    already have compatible character sets with "field".

    - Also, Field_str::test_if_equality_guarantees_uniqueness() guarantees
    that the comparison collation of all equalities handled by Item_equal
    match the the collation of the field.

    Therefore, at Item_equal::add_const() time all constants constXXX
    should be directly comparable to each other without an additional
    character set conversion.
    It's safe to do val_str() for "const_item" and "c" and compare
    them according to the collation of the *field*.

    So in a script like this:
      CREATE TABLE t1 (a VARCHAR(10) COLLATE xxx);
      INSERT INTO t1 VALUES ('a'),('A');
      SELECT * FROM t1 WHERE a='a' AND a='A';
    Item_equal::add_const() effectively rewrites the condition to:
      SELECT * FROM t1 WHERE a='a' AND 'a' COLLATE xxx='A';
    and then to:
      SELECT * FROM t1 WHERE a='a'; // if the two constants were equal
                                    // e.g. in case of latin1_swedish_ci
    or to:
      SELECT * FROM t1 WHERE FALSE; // if the two constants were not equal
                                    // e.g. in case of latin1_bin

    Note, both "const_item" and "c" can return NULL, e.g.:
      SELECT * FROM t1 WHERE a=NULL    AND a='const';
      SELECT * FROM t1 WHERE a='const' AND a=NULL;
      SELECT * FROM t1 WHERE a='const' AND a=(SELECT MAX(a) FROM t2)
  */

  cond_false= !Item_equal::compare_type_handler()->Item_eq_value(thd, this, c,
                                                                 get_const());
  if (with_const && equal_items.elements == 1)
    cond_true= TRUE;
  if (cond_false || cond_true)
    const_item_cache= 1;
}


  void add_argument(Item *item)
  {
    args[arg_count++]= item;
  }


  DbugStringItemTypeValue(THD *thd, const Item *item)
  {
    append('(');
    append(item->type_handler()->name().ptr());
    append(')');
    const_cast<Item*>(item)->print(this, QT_EXPLAIN);
    /* Append end \0 to allow usage of c_ptr() */
    append('\0');
    str_length--;
  }


  const Type_handler *real_type_handler() const
  { return (*ref)->real_type_handler(); }


  bool get_time(THD *thd, MYSQL_TIME *ltime)
  { return get_date(thd, ltime, Time::Options(thd)); }


  Double_null to_double_null()
  {
    // val_real() must be caleed on a separate line. See to_longlong_null()
    double nr= val_real();
    return Double_null(nr, null_value);
  }


bool sane() const { return !null_value || m_value.is_zero_datetime(); }


  void update_table_bitmaps()
  {
    if (field && field->table)
    {
      TABLE *tab= field->table;
      tab->covering_keys.intersect(field->part_of_key);
      if (tab->read_set)
        tab->mark_column_with_deps(field);
    }
  }


  longlong val_datetime_packed(THD *thd)
  {
    return has_value() ? value : 0;
  }


  Field::geometry_type get_geometry_type() const
  { return Type_geometry_attributes::get_geometry_type(); };


  const longlong *const_ptr_longlong() const
  { return can_return_const_value(INT_RESULT) ? &value.integer : NULL; }


  Item *get_copy(THD *thd)
  { return get_item_copy<Item_cache_double>(thd, this); }


  Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
                             const Tmp_field_param *param)
  {
    /*
      We can get to here when using a CURSOR for a query with NAME_CONST():
        DECLARE c CURSOR FOR SELECT NAME_CONST('x','y') FROM t1;
        OPEN c;
    */
    return tmp_table_field_from_field_type_maybe_null(table, src, param,
                                              type() == Item::NULL_ITEM);
  }


bool const_is_null() const { return state == NULL_VALUE; }


double val_real() { return has_value() ? Date(this).to_double() : 0; }


bool Item_cond::walk(Item_processor processor, bool walk_subquery, void *arg)
{
  List_iterator_fast<Item> li(list);
  Item *item;
  while ((item= li++))
    if (item->walk(processor, walk_subquery, arg))
      return 1;
  return Item_func::walk(processor, walk_subquery, arg);
}


  Item_cache_double(THD *thd)
   :Item_cache_real(thd, &type_handler_double)
  { }


Item *Item_func_nop_all::neg_transformer(THD *thd)
{
  /* "NOT (e $cmp$ ANY (SELECT ...)) -> e $rev_cmp$" ALL (SELECT ...) */
  Item_func_not_all *new_item= new (thd->mem_root) Item_func_not_all(thd, args[0]);
  Item_allany_subselect *allany= (Item_allany_subselect*)args[0];
  allany->create_comp_func(FALSE);
  allany->all= !allany->all;
  allany->upper_item= new_item;
  return new_item;
}


longlong Item_in_optimizer::val_int()
{
  bool tmp;
  DBUG_ASSERT(fixed == 1);
  cache->store(args[0]);
  cache->cache_value();
  DBUG_ENTER(" Item_in_optimizer::val_int");

  if (invisible_mode())
  {
    longlong res= args[1]->val_int();
    null_value= args[1]->null_value;
    DBUG_PRINT("info", ("pass trough"));
    DBUG_RETURN(res);
  }

  if (cache->null_value_inside)
  {
     DBUG_PRINT("info", ("Left NULL..."));
    /*
      We're evaluating
      "<outer_value_list> [NOT] IN (SELECT <inner_value_list>...)"
      where one or more of the outer values is NULL.
    */
    if (((Item_in_subselect*)args[1])->is_top_level_item())
    {
      /*
        We're evaluating a top level item, e.g.
	"<outer_value_list> IN (SELECT <inner_value_list>...)",
	and in this case a NULL value in the outer_value_list means
        that the result shall be NULL/FALSE (makes no difference for
        top level items). The cached value is NULL, so just return
        NULL.
      */
      null_value= 1;
    }
    else
    {
      /*
	We're evaluating an item where a NULL value in either the
        outer or inner value list does not automatically mean that we
        can return NULL/FALSE. An example of such a query is
        "<outer_value_list> NOT IN (SELECT <inner_value_list>...)"
        The result when there is at least one NULL value is: NULL if the
        SELECT evaluated over the non-NULL values produces at least
        one row, FALSE otherwise
      */
      Item_in_subselect *item_subs=(Item_in_subselect*)args[1];
      bool all_left_cols_null= true;
      const uint ncols= cache->cols();

      /*
        Turn off the predicates that are based on column compares for
        which the left part is currently NULL
      */
      for (uint i= 0; i < ncols; i++)
      {
        if (cache->element_index(i)->null_value)
          item_subs->set_cond_guard_var(i, FALSE);
        else
          all_left_cols_null= false;
      }

      if (!item_subs->is_correlated &&
          all_left_cols_null && result_for_null_param != UNKNOWN)
      {
        /*
           This is a non-correlated subquery, all values in the outer
           value list are NULL, and we have already evaluated the
           subquery for all NULL values: Return the same result we
           did last time without evaluating the subquery.
        */
        null_value= result_for_null_param;
      }
      else
      {
        /* The subquery has to be evaluated */
        (void) item_subs->val_bool_result();
        if (item_subs->engine->no_rows())
          null_value= item_subs->null_value;
        else
          null_value= TRUE;
        if (all_left_cols_null)
          result_for_null_param= null_value;
      }

      /* Turn all predicates back on */
      for (uint i= 0; i < ncols; i++)
        item_subs->set_cond_guard_var(i, TRUE);
    }
    DBUG_RETURN(0);
  }
  tmp= args[1]->val_bool_result();
  null_value= args[1]->null_value;
  DBUG_RETURN(tmp);
}


int cmp_item_time::cmp_not_null(const Value *val)
{
  DBUG_ASSERT(!val->is_null());
  DBUG_ASSERT(val->is_temporal());
  return value != pack_time(&val->value.m_time);
}


longlong Item_func_strcmp::val_int()
{
  DBUG_ASSERT(fixed == 1);
  String *a= args[0]->val_str(&value1);
  String *b= args[1]->val_str(&value2);
  if (!a || !b)
  {
    null_value=1;
    return 0;
  }
  int value= cmp_collation.sortcmp(a, b);
  null_value=0;
  return !value ? 0 : (value < 0 ? (longlong) -1 : (longlong) 1);
}


  Item *get_copy(THD *thd)
  { return get_item_copy<Item_decimal>(thd, this); }


longlong Item_func_isnotnull::val_int()
{
  DBUG_ASSERT(fixed == 1);
  return args[0]->is_null() ? 0 : 1;
}


  const Type_handler *type_handler() const
  {
    const Type_handler *handler= field->type_handler();
    return handler->type_handler_for_item_field();
  }


  virtual longlong val_datetime_packed(THD *thd)
  {
    return Datetime(thd, this, Datetime::Options_cmp(thd)).to_packed();
  }


Item_bool_rowready_func2* Gt_creator::create_swap(THD *thd, Item *a, Item *b) const
{
  return new(thd->mem_root) Item_func_lt(thd, b, a);
}


Item *Item_equal::multiple_equality_transformer(THD *thd, uchar *arg)
{
  List<Item> equalities;
  if (create_pushable_equalities(thd, &equalities, 0, 0, false))
    return 0;

  switch (equalities.elements)
  {
  case 0:
    return 0;
  case 1:
    return equalities.head();
    break;
  default:
    return new (thd->mem_root) Item_cond_and(thd, equalities);
    break;
  }
}


String *val_str(String*) { return &str_value; }


  void copy_with_sum_func(const Item *item)
  {
    m_with_sum_func= item->with_sum_func();
  }


bool Item_func_between::count_sargable_conds(void *arg)
{
  SELECT_LEX *sel= (SELECT_LEX *) arg;
  sel->cond_count++;
  sel->between_count++;
  return 0;
}


  void set(size_t pos, size_t length)
  {
    DBUG_ASSERT(pos < UINT_MAX32);
    DBUG_ASSERT(length < UINT_MAX32);
    m_pos= (uint) pos;
    m_length= (uint) length;
  }


  void fix_charset_and_length_from_str_value(const String &str, Derivation dv)
  {
    fix_charset_and_length(str.charset(), dv, Metadata(&str));
  }


int Arg_comparator::compare_e_row()
{
  (*a)->bring_value();
  (*b)->bring_value();
  uint n= (*a)->cols();
  for (uint i= 0; i<n; i++)
  {
    if (!comparators[i].compare())
      return 0;
  }
  return 1;
}


virtual bool is_evaluable_expression() const { return true; }


  longlong val_time_packed(THD *thd)
  {
    return cached_time.valid_time_to_packed();
  }


longlong Item_func_not::val_int()
{
  DBUG_ASSERT(fixed == 1);
  bool value= args[0]->val_bool();
  null_value=args[0]->null_value;
  return ((!null_value && value == 0) ? 1 : 0);
}


bool Item_func_in::fix_length_and_dec()
{
  THD *thd= current_thd;
  uint found_types;
  m_comparator.set_handler(type_handler_varchar.type_handler_for_comparison());
  max_length= 1;

  if (prepare_predicant_and_values(thd, &found_types))
  {
    DBUG_ASSERT(thd->is_error()); // Must set error
    return TRUE;
  }

  if (arg_types_compatible) // Bisection condition #1
  {
    if (m_comparator.type_handler()->
        Item_func_in_fix_comparator_compatible_types(thd, this))
      return TRUE;
  }
  else
  {
    DBUG_ASSERT(m_comparator.cmp_type() != ROW_RESULT);
    if ( fix_for_scalar_comparison_using_cmp_items(thd, found_types))
      return TRUE;
  }

  DBUG_EXECUTE_IF("Item_func_in",
                  push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
                  ER_UNKNOWN_ERROR, "DBUG: types_compatible=%s bisect=%s",
                  arg_types_compatible ? "yes" : "no",
                  array != NULL ? "yes" : "no"););
  return FALSE;
}


  virtual longlong val_int_min() const
  {
    return LONGLONG_MIN;
  }


  longlong val_int()
  {
    DBUG_ASSERT(0); // never should be called
    null_value= true;
    return 0;
  }


  void set_value(const Timestamp_or_zero_datetime &value)
  {
    m_value= value;
  }


int Arg_comparator::compare_e_json_str()
{
  return compare_e_json_str_basic(*a, *b);
}


  Item_splocal_row_field(THD *thd,
                         const Sp_rcontext_handler *rh,
                         const LEX_CSTRING *sp_var_name,
                         const LEX_CSTRING *sp_field_name,
                         uint sp_var_idx, uint sp_field_idx,
                         const Type_handler *handler,
                         uint pos_in_q= 0, uint len_in_q= 0)
   :Item_splocal(thd, rh, sp_var_name, sp_var_idx, handler, pos_in_q, len_in_q),
    m_field_name(*sp_field_name),
    m_field_idx(sp_field_idx)
  { }


  virtual uint32 max_display_length() const
  {
    return type_handler()->max_display_length(this);
  }


bool Item_equal::fix_fields(THD *thd, Item **ref)
{
  DBUG_ASSERT(fixed == 0);
  Item_equal_fields_iterator it(*this);
  Item *item;
  Field *first_equal_field= NULL;
  Field *last_equal_field= NULL;
  Field *prev_equal_field= NULL;
  not_null_tables_cache= used_tables_cache= 0;
  const_item_cache= 0;
  while ((item= it++))
  {
    table_map tmp_table_map;
    used_tables_cache|= item->used_tables();
    tmp_table_map= item->not_null_tables();
    not_null_tables_cache|= tmp_table_map;
    DBUG_ASSERT(!item->with_sum_func() && !item->with_subquery());
    if (item->maybe_null)
      maybe_null= 1;
    if (!item->get_item_equal())
      item->set_item_equal(this);
    if (link_equal_fields && item->real_item()->type() == FIELD_ITEM)
    {
      last_equal_field= ((Item_field *) (item->real_item()))->field;
      if (!prev_equal_field)
        first_equal_field= last_equal_field;
      else
        prev_equal_field->next_equal_field= last_equal_field;
      prev_equal_field= last_equal_field;
    }
  }
  if (prev_equal_field && last_equal_field != first_equal_field)
    last_equal_field->next_equal_field= first_equal_field;
  if (fix_length_and_dec())
    return TRUE;
  fixed= 1;
  return FALSE;
}


  String *val_str(String *to)
  {
    DBUG_ASSERT(sane());
    return null_value ? NULL :
           m_value.to_datetime(current_thd).to_string(to, decimals);
  }


uint length() const { return m_length; }


Item_cond::Item_cond(THD *thd, Item_cond *item)
  :Item_bool_func(thd, item),
   abort_on_null(item->abort_on_null),
   and_tables_cache(item->and_tables_cache)
{
  /*
    item->list will be copied by copy_andor_arguments() call
  */
}


  bool save_in_param(THD *thd, Item_param *param)
  {
    param->set_default();
    return false;
  }


void Item_equal::print(String *str, enum_query_type query_type)
{
  if (cond_false)
  {
    str->append('0');
    return;
  }
  str->append(func_name());
  str->append('(');
  List_iterator_fast<Item> it(equal_items);
  Item *item;
  item= it++;
  item->print(str, query_type);
  while ((item= it++))
  {
    str->append(',');
    str->append(' ');
    item->print(str, query_type);
  }
  str->append(')');
}


  Item *get_copy(THD *thd)
  { return get_item_copy<Item_date_literal>(thd, this); }


  longlong val_int()
  {
    return longlong_from_string_with_check(&str_value);
  }


  const Type_handler *type_handler() const
  {
    if (result_field)
      return result_field->type_handler();
    return &type_handler_null;
  }


Item_func_ifnull::int_op()
{
  DBUG_ASSERT(fixed == 1);
  longlong value=args[0]->val_int();
  if (!args[0]->null_value)
  {
    null_value=0;
    return value;
  }
  value=args[1]->val_int();
  if ((null_value=args[1]->null_value))
    return 0;
  return value;
}


  virtual Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg)
  { return this; }


  With_sum_func_cache(const Item *a)
   :m_with_sum_func(a->with_sum_func())
  { }


longlong Item_is_not_null_test::val_int()
{
  DBUG_ASSERT(fixed == 1);
  DBUG_ENTER("Item_is_not_null_test::val_int");
  if (const_item() && !args[0]->maybe_null)
    DBUG_RETURN(1);
  if (args[0]->is_null())
  {
    DBUG_PRINT("info", ("null"));
    owner->was_null|= 1;
    DBUG_RETURN(0);
  }
  else
    DBUG_RETURN(1);
}


  longlong val_int()
  {
    DBUG_ASSERT(sane());
    return null_value ? 0 :
           m_value.to_datetime(current_thd).to_longlong();
  }


static inline int cmp_ulongs (ulonglong a_val, ulonglong b_val)
{
  return a_val < b_val ? -1 : a_val == b_val ? 0 : 1;
}


Item_bool_rowready_func2* Le_creator::create(THD *thd, Item *a, Item *b) const
{
  return new(thd->mem_root) Item_func_le(thd, a, b);
}


int Regexp_processor_pcre::default_regex_flags()
{
  return default_regex_flags_pcre(current_thd);
}


  bool set_limit_clause_param(longlong nr)
  {
    value.set_handler(&type_handler_longlong);
    set_int(nr, MY_INT64_NUM_DECIMAL_DIGITS);
    return !unsigned_flag && value.integer < 0;
  }


  bool is_of_type(Type t, Item_result cmp) const
  {
    return type() == t && cmp_type() == cmp;
  }


bool is_temporal() const { return m_type == DYN_COL_DATETIME; }


  Item *grouping_field_transformer_for_where(THD *thd, uchar *arg)
  { return convert_to_basic_const_item(thd); }


  int save_in_field(Field *field, bool no_conversions)
  { return save_date_in_field(field, no_conversions); }


  void join(const Item *item)
  {
    // Ignore implicit NULLs
    if (m_geometry_type == m_geometry_type_unknown)
      copy(item->type_handler(), item);
    else if (item->type_handler() == &type_handler_geometry)
    {
      m_geometry_type=
        Field_geom::geometry_type_merge((Field_geom::geometry_type)
                                         m_geometry_type,
                                        (Field_geom::geometry_type)
                                         item->uint_geometry_type());
    }
  }


  Item_string(THD *thd, const char *name_par, const char *str, size_t length,
              CHARSET_INFO *cs, Derivation dv, uint repertoire)
   :Item_literal(thd)
  {
    str_value.set_or_copy_aligned(str, length, cs);
    fix_from_value(dv, Metadata(&str_value, repertoire));
    set_name(thd, name_par, safe_strlen(name_par), system_charset_info);
  }


  bool save_in_value(THD *thd, struct st_value *value)
  {
    return type_handler()->Item_save_in_value(thd, this, value);
  }


  void share_name_with(const Item *item)
  {
    name= item->name;
    is_autogenerated_name= item->is_autogenerated_name;
  }


bool Item_func_in::fix_for_row_comparison_using_cmp_items(THD *thd)
{
  if (make_unique_cmp_items(thd, cmp_collation.collation))
    return true;
  DBUG_ASSERT(get_comparator_type_handler(0) == &type_handler_row);
  DBUG_ASSERT(get_comparator_cmp_item(0));
  cmp_item_row *cmp_row= (cmp_item_row*) get_comparator_cmp_item(0);
  return cmp_row->prepare_comparators(thd, func_name(), this, 0);
}


enum Type type() const { return CONST_ITEM; }


  Item_outer_ref(THD *thd, Name_resolution_context *context_arg, Item **item,
                 const char *table_name_arg, LEX_CSTRING *field_name_arg,
                 bool alias_name_used_arg):
    Item_direct_ref(thd, context_arg, item, table_name_arg, field_name_arg,
                    alias_name_used_arg),
    outer_ref(0), in_sum_func(0), found_in_select_list(1), found_in_group_by(0)
  {}


  bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode)
  {
    return type_handler_year.Item_get_date_with_warn(thd, this, to, mode);
  }


int Arg_comparator::compare_e_decimal()
{
  VDec val1(*a), val2(*b);
  if (val1.is_null() || val2.is_null())
    return MY_TEST(val1.is_null() && val2.is_null());
  val1.round_self_if_needed((*a)->decimals, HALF_UP);
  val2.round_self_if_needed((*b)->decimals, HALF_UP);
  return MY_TEST(val1.cmp(val2) == 0);
}


bool Item_bool_rowready_func2::fix_length_and_dec()
{
  max_length= 1;				     // Function returns 0 or 1

  /*
    As some compare functions are generated after sql_yacc,
    we have to check for out of memory conditions here
  */
  if (!args[0] || !args[1])
    return FALSE;
  return setup_args_and_comparator(current_thd, &cmp);
}


Item_bool_rowready_func2* Ge_creator::create_swap(THD *thd, Item *a, Item *b) const
{
  return new(thd->mem_root) Item_func_le(thd, b, a);
}


  With_sum_func_cache(const Item *a, const Item *b, const Item *c,
                      const Item *d, const Item *e)
   :m_with_sum_func(a->with_sum_func() || b->with_sum_func() ||
                    c->with_sum_func() || d->with_sum_func() ||
                    e->with_sum_func())
  { }


bool Item_func_case::fix_fields(THD *thd, Item **ref)
{
  bool res= Item_func::fix_fields(thd, ref);

  Item **pos= else_expr_addr();
  if (!pos || pos[0]->maybe_null)
    maybe_null= 1;
  return res;
}


Item *Item_func_ne::negated_item(THD *thd) /* a != b  ->  a = b */
{
  return new (thd->mem_root) Item_func_eq(thd, args[0], args[1]);
}


  void set_param_func(uchar **pos, ulong len)
  {
    /*
      To avoid Item_param::set_xxx() asserting on data type mismatch,
      we set the value type handler here:
      - It can not be initialized yet after Item_param::setup_conversion().
      - Also, for LIMIT clause parameters, the value type handler might have
        changed from the real type handler to type_handler_longlong.
        So here we'll restore it.
    */
    const Type_handler *h= Item_param::type_handler();
    value.set_handler(h);
    h->Item_param_set_param_func(this, pos, len);
  }


bool Predicant_to_list_comparator::alloc_comparators(THD *thd, uint nargs)
{
  size_t nbytes= sizeof(Predicant_to_value_comparator) * nargs;
  if (!(m_comparators= (Predicant_to_value_comparator *) thd->alloc(nbytes)))
    return true;
  memset(m_comparators, 0, nbytes);
  return false;
}


  Item_cache_year(THD *thd, const Type_handler *handler)
   :Item_cache_int(thd, handler) { }


Item *Item_func_case_simple::find_item()
{
  /* Compare every WHEN argument with it and return the first match */
  uint idx;
  if (!Predicant_to_list_comparator::cmp(this, &idx, NULL))
    return args[idx + when_count()];
  Item **pos= Item_func_case_simple::else_expr_addr();
  return pos ? pos[0] : 0;
}


Item_func_ifnull::str_op(String *str)
{
  DBUG_ASSERT(fixed == 1);
  String *res  =args[0]->val_str(str);
  if (!args[0]->null_value)
  {
    null_value=0;
    res->set_charset(collation.collation);
    return res;
  }
  res=args[1]->val_str(str);
  if ((null_value=args[1]->null_value))
    return 0;
  res->set_charset(collation.collation);
  return res;
}


cmp_item *cmp_item_datetime::make_same()
{
  return new cmp_item_datetime();
}


  Item_args(THD *thd, Item *a, Item *b, Item *c)
  {
    arg_count= 0;
    if (likely((args= (Item**) thd_alloc(thd, sizeof(Item*) * 3))))
    {
      arg_count= 3;
      args[0]= a; args[1]= b; args[2]= c;
    }
  }


  Item_fixed_hybrid(THD *thd): Item(thd), fixed(false)
  { }


longlong Item_func_case::int_op()
{
  DBUG_ASSERT(fixed == 1);
  Item *item= find_item();
  longlong res;

  if (!item)
  {
    null_value=1;
    return 0;
  }
  res=item->val_int();
  null_value=item->null_value;
  return res;
}


bool Regexp_processor_pcre::exec(Item *item, int offset,
                                uint n_result_offsets_to_convert)
{
  char buff[MAX_FIELD_WIDTH];
  String tmp(buff,sizeof(buff),&my_charset_bin);
  String *res= item->val_str(&tmp);
  if (item->null_value)
    return true;
  return exec(res, offset, n_result_offsets_to_convert);
}


  Item *get_copy(THD *thd)
  { return get_item_copy<Item_cache_int>(thd, this); }


  Item_direct_ref(THD *thd, Name_resolution_context *context_arg, Item **item,
                  const char *table_name_arg,
                  const LEX_CSTRING *field_name_arg,
                  bool alias_name_used_arg= FALSE):
    Item_ref(thd, context_arg, item, table_name_arg,
             field_name_arg, alias_name_used_arg)
  {}


  virtual const Type_handler *fixed_type_handler() const
  {
    return NULL;
  }


  uint divisor_precision_increment() const
  {
    return type_handler()->Item_divisor_precision_increment(this);
  }


virtual bool with_sum_func() const { return false; }


void Item_func_in::print(String *str, enum_query_type query_type)
{
  args[0]->print_parenthesised(str, query_type, precedence());
  if (negated)
    str->append(STRING_WITH_LEN(" not"));
  str->append(STRING_WITH_LEN(" in ("));
  print_args(str, 1, query_type);
  str->append(STRING_WITH_LEN(")"));
}


  Field::geometry_type get_geometry_type() const
  {
    return Type_geometry_attributes::get_geometry_type();
  }


virtual bool set_fields_as_dependent_processor(void *arg) { return 0; }


uchar *in_longlong::get_value(Item *item)
{
  tmp.val= item->val_int();
  if (item->null_value)
    return 0;
  tmp.unsigned_flag= item->unsigned_flag;
  return (uchar*) &tmp;
}


cmp_item* cmp_item_timestamp::make_same()
{
  return new cmp_item_timestamp();
}


int Arg_comparator::compare_e_string()
{
  String *res1,*res2;
  res1= (*a)->val_str(&value1);
  res2= (*b)->val_str(&value2);
  if (!res1 || !res2)
    return MY_TEST(res1 == res2);
  return MY_TEST(sortcmp(res1, res2, compare_collation()) == 0);
}


int Arg_comparator::compare_native()
{
  THD *thd= current_thd;
  if (!(*a)->val_native_with_conversion(thd, &m_native1,
                                        compare_type_handler()))
  {
    if (!(*b)->val_native_with_conversion(thd, &m_native2,
                                          compare_type_handler()))
    {
      if (set_null)
        owner->null_value= 0;
      return compare_type_handler()->cmp_native(m_native1, m_native2);
    }
  }
  if (set_null)
    owner->null_value= 1;
  return -1;
}


bool modify_item() const { return m_modify_item; }


bool in_vector::find(Item *item)
{
  uchar *result=get_value(item);
  if (!result || !used_count)
    return false;				// Null value

  uint start,end;
  start=0; end=used_count-1;
  while (start != end)
  {
    uint mid=(start+end+1)/2;
    int res;
    if ((res=(*compare)(collation, base+mid*size, result)) == 0)
      return true;
    if (res < 0)
      start=mid;
    else
      end=mid-1;
  }
  return ((*compare)(collation, base+start*size, result) == 0);
}


void Item_equal::update_used_tables()
{
  not_null_tables_cache= used_tables_cache= 0;
  if ((const_item_cache= cond_false || cond_true))
    return;
  Item_equal_fields_iterator it(*this);
  Item *item;
  const_item_cache= 1;
  while ((item= it++))
  {
    item->update_used_tables();
    used_tables_cache|= item->used_tables();
    /* see commentary at Item_equal::update_const() */
    const_item_cache&= item->const_item() && !item->is_outer_field();
  }
}


bool Item_func_equal::fix_length_and_dec()
{
  bool rc= Item_bool_rowready_func2::fix_length_and_dec();
  maybe_null=null_value=0;
  return rc;
}


  virtual void print(String *str, enum_query_type query_type)
  {
    decimal_value.to_string(&str_value);
    str->append(str_value);
  }


  longlong val_int()
  {
    return has_value() ? Time(this).to_longlong() : 0;
  }


Item *Item_in_optimizer::expr_cache_insert_transformer(THD *thd, uchar *unused)
{
  DBUG_ENTER("Item_in_optimizer::expr_cache_insert_transformer");
  DBUG_ASSERT(fixed);

  if (invisible_mode())
    DBUG_RETURN(this);

  if (expr_cache)
    DBUG_RETURN(expr_cache);

  if (args[1]->expr_cache_is_needed(thd) &&
      (expr_cache= set_expr_cache(thd)))
    DBUG_RETURN(expr_cache);

  DBUG_RETURN(this);
}


  const Type_handler *type_handler() const
  {
    return Type_handler::get_handler_by_field_type(int_field_type);
  }


bool check_partition_func_processor(void *int_arg) { return false;}


  String *val_str(String *str)
  {
    DBUG_ASSERT(0); // never should be called
    null_value= true;
    return 0;
  }


  Item_empty_string(THD *thd, const char *header,uint length,
                    CHARSET_INFO *cs= NULL):
    Item_partition_func_safe_string(thd, "", 0,
                                    cs ? cs : &my_charset_utf8_general_ci)
    {
      name.str=    header;
      name.length= strlen(name.str);
      max_length= length * collation.collation->mbmaxlen;
    }


Item* element_index(uint i) { return this_item()->element_index(i); }


int Arg_comparator::compare_e_int()
{
  longlong val1= (*a)->val_int();
  longlong val2= (*b)->val_int();
  if ((*a)->null_value || (*b)->null_value)
    return MY_TEST((*a)->null_value && (*b)->null_value);
  return MY_TEST(val1 == val2);
}


longlong Item_func_equal::val_int()
{
  DBUG_ASSERT(fixed == 1);
  return cmp.compare();
}


    Print(Item *item, enum_query_type type)
    {
      item->print(this, type);
    }


bool Item_equal::walk(Item_processor processor, bool walk_subquery, void *arg)
{
  Item *item;
  Item_equal_fields_iterator it(*this);
  while ((item= it++))
  {
    if (item->walk(processor, walk_subquery, arg))
      return 1;
  }
  return Item_func::walk(processor, walk_subquery, arg);
}


  my_decimal *val_decimal(my_decimal *to)
  {
    return has_value() ? Datetime(this).to_decimal(to) : NULL;
  }


void in_longlong::set(uint pos,Item *item)
{
  struct packed_longlong *buff= &((packed_longlong*) base)[pos];

  buff->val= item->val_int();
  buff->unsigned_flag= item->unsigned_flag;
}


  bool fix_fields_if_needed_for_order_by(THD *thd, Item **ref)
  {
    return fix_fields_if_needed_for_scalar(thd, ref);
  }


bool Item_func_in::prepare_predicant_and_values(THD *thd, uint *found_types)
{
  uint type_cnt;
  have_null= false;

  add_predicant(this, 0);
  for (uint i= 1 ; i < arg_count; i++)
  {
    if (add_value_skip_null(Item_func_in::func_name(), this, i, &have_null))
      return true;
  }
  all_values_added(&m_comparator, &type_cnt, found_types);
  arg_types_compatible= type_cnt < 2;

#ifndef DBUG_OFF
  Predicant_to_list_comparator::debug_print(thd);
#endif
  return false;
}


  bool val_native_from_item(THD *thd, Item *item, Native *to)
  {
    DBUG_ASSERT(is_fixed());
    null_value= item->val_native(thd, to);
    DBUG_ASSERT(null_value == item->null_value);
    return null_value;
  }


bool fix_escape_item(THD *thd, Item *escape_item, String *tmp_str,
                     bool escape_used_in_parsing, CHARSET_INFO *cmp_cs,
                     int *escape)
{
  /*
    ESCAPE clause accepts only constant arguments and Item_param.

    Subqueries during context_analysis_only might decide they're
    const_during_execution, but not quite const yet, not evaluate-able.
    This is fine, as most of context_analysis_only modes will never
    reach val_int(), so we won't need the value.
    CONTEXT_ANALYSIS_ONLY_DERIVED being a notable exception here.
  */
  if (!escape_item->const_during_execution() ||
     (!escape_item->const_item() &&
      !(thd->lex->context_analysis_only & ~CONTEXT_ANALYSIS_ONLY_DERIVED)))
  {
    my_error(ER_WRONG_ARGUMENTS,MYF(0),"ESCAPE");
    return TRUE;
  }

  IF_DBUG(*escape= ESCAPE_NOT_INITIALIZED,);

  if (escape_item->const_item())
  {
    /* If we are on execution stage */
    /* XXX is it safe to evaluate is_expensive() items here? */
    String *escape_str= escape_item->val_str(tmp_str);
    if (escape_str)
    {
      const char *escape_str_ptr= escape_str->ptr();
      if (escape_used_in_parsing && (
             (((thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) &&
                escape_str->numchars() != 1) ||
               escape_str->numchars() > 1)))
      {
        my_error(ER_WRONG_ARGUMENTS,MYF(0),"ESCAPE");
        return TRUE;
      }

      if (use_mb(cmp_cs))
      {
        CHARSET_INFO *cs= escape_str->charset();
        my_wc_t wc;
        int rc= cs->cset->mb_wc(cs, &wc,
                                (const uchar*) escape_str_ptr,
                                (const uchar*) escape_str_ptr +
                                escape_str->length());
        *escape= (int) (rc > 0 ? wc : '\\');
      }
      else
      {
        /*
          In the case of 8bit character set, we pass native
          code instead of Unicode code as "escape" argument.
          Convert to "cs" if charset of escape differs.
        */
        uint32 unused;
        if (escape_str->needs_conversion(escape_str->length(),
                                         escape_str->charset(),cmp_cs,&unused))
        {
          char ch;
          uint errors;
          uint32 cnvlen= copy_and_convert(&ch, 1, cmp_cs, escape_str_ptr,
                                          escape_str->length(),
                                          escape_str->charset(), &errors);
          *escape= cnvlen ? ch : '\\';
        }
        else
          *escape= escape_str_ptr ? *escape_str_ptr : '\\';
      }
    }
    else
      *escape= '\\';
  }

  return FALSE;
}


  void make_send_field(THD *thd, Send_field *)
  {
    illegal_method_call((const char*)"make_send_field");
  };


  bool vcol_assignment_allowed_value() const
  {
    switch (state) {
    case NULL_VALUE:
    case DEFAULT_VALUE:
    case IGNORE_VALUE:
      return true;
    case NO_VALUE:
    case SHORT_DATA_VALUE:
    case LONG_DATA_VALUE:
      break;
    }
    return false;
  }


virtual Item_func *get_item_func() { return NULL; }


int Arg_comparator::compare_time()
{
  THD *thd= current_thd;
  longlong val1= (*a)->val_time_packed(thd);
  if (!(*a)->null_value)
  {
    longlong val2= (*b)->val_time_packed(thd);
    if (!(*b)->null_value)
      return compare_not_null_values(val1, val2);
  }
  if (set_null)
    owner->null_value= true;
  return -1;
}


longlong Item_func_isnull::val_int()
{
  DBUG_ASSERT(fixed == 1);
  if (const_item() && !args[0]->maybe_null)
    return 0;
  return args[0]->is_null() ? 1: 0;
}


  longlong val_datetime_packed(THD *thd)
  {
    return to_datetime(current_thd).to_packed();
  }


bool cmp_item_row::alloc_comparators(THD *thd, uint cols)
{
  if (comparators)
  {
    DBUG_ASSERT(cols == n);
    return false;
  }
  return
    !(comparators= (cmp_item **) thd->calloc(sizeof(cmp_item *) * (n= cols)));
}


longlong Item_func_between::val_int_cmp_time()
{
  THD *thd= current_thd;
  longlong value= args[0]->val_time_packed(thd), a, b;
  if ((null_value= args[0]->null_value))
    return 0;
  a= args[1]->val_time_packed(thd);
  b= args[2]->val_time_packed(thd);
  return val_int_cmp_int_finalize(value, a, b);
}


int Arg_comparator::compare_e_real()
{
  double val1= (*a)->val_real();
  double val2= (*b)->val_real();
  if ((*a)->null_value || (*b)->null_value)
    return MY_TEST((*a)->null_value && (*b)->null_value);
  return MY_TEST(val1 == val2);
}


void set_with_sum_func() { m_with_sum_func= true; }


bool check_vcol_func_processor(void *arg) { return false; }


  void cleanup()
  {
    Item::cleanup();
    fixed= false;
  }


int cmp_item_timestamp::cmp(Item *arg)
{
  THD *thd= current_thd;
  Timestamp_or_zero_datetime_native_null tmp(thd, arg, true);
  return m_null_value || tmp.is_null() ? UNKNOWN :
         type_handler_timestamp2.cmp_native(m_native, tmp) != 0;
}


  ~Name_resolution_context_backup()
  {
    ctx_state.restore_state(&ctx, &table_list);
    table_list.map= save_map;
  }


  virtual uint decimal_precision() const
  {
    return type_handler()->Item_decimal_precision(this);
  }


void Item_func::convert_const_compared_to_int_field(THD *thd)
{
  DBUG_ASSERT(arg_count >= 2); // Item_func_nullif has arg_count == 3
  if (!thd->lex->is_ps_or_view_context_analysis())
  {
    int field;
    if (args[field= 0]->real_item()->type() == FIELD_ITEM ||
        args[field= 1]->real_item()->type() == FIELD_ITEM)
    {
      Item_field *field_item= (Item_field*) (args[field]->real_item());
      if (((field_item->field_type() == MYSQL_TYPE_LONGLONG &&
            field_item->type_handler() != &type_handler_vers_trx_id) ||
           field_item->field_type() ==  MYSQL_TYPE_YEAR))
        convert_const_to_int(thd, field_item, &args[!field]);
    }
  }
}


  Item *field_transformer_for_having_pushdown(THD *thd, uchar *arg)
  { return this; }


bool Item_in_optimizer::is_expensive_processor(void *arg)
{
  DBUG_ASSERT(fixed);
  return args[0]->is_expensive_processor(arg) ||
         args[1]->is_expensive_processor(arg);
}


virtual const char *full_name() const { return name.str ? name.str : "???"; }


  Item_splocal_row_field_by_name(THD *thd,
                                 const Sp_rcontext_handler *rh,
                                 const LEX_CSTRING *sp_var_name,
                                 const LEX_CSTRING *sp_field_name,
                                 uint sp_var_idx,
                                 const Type_handler *handler,
                                 uint pos_in_q= 0, uint len_in_q= 0)
   :Item_splocal_row_field(thd, rh, sp_var_name, sp_field_name,
                           sp_var_idx, 0 /* field index will be set later */,
                           handler, pos_in_q, len_in_q)
  { }


  double val_real()
  {
    DBUG_ASSERT(0); // never should be called
    null_value= true;
    return 0.0;
  }


int Arg_comparator::compare_e_real_fixed()
{
  double val1= (*a)->val_real();
  double val2= (*b)->val_real();
  if ((*a)->null_value || (*b)->null_value)
    return MY_TEST((*a)->null_value && (*b)->null_value);
  return MY_TEST(val1 == val2 || fabs(val1 - val2) < precision);
}


bool Predicant_to_list_comparator::add_value(const char *funcname,
                                             Item_args *args,
                                             uint value_index)
{
  DBUG_ASSERT(m_predicant_index < args->argument_count());
  DBUG_ASSERT(value_index < args->argument_count());
  Type_handler_hybrid_field_type tmp;
  Item *tmpargs[2];
  tmpargs[0]= args->arguments()[m_predicant_index];
  tmpargs[1]= args->arguments()[value_index];
  if (tmp.aggregate_for_comparison(funcname, tmpargs, 2, true))
  {
    DBUG_ASSERT(current_thd->is_error());
    return true;
  }
  m_comparators[m_comparator_count].m_handler= tmp.type_handler();
  m_comparators[m_comparator_count].m_arg_index= value_index;
  m_comparator_count++;
  return false;
}


  double val_real()
  {
    return can_return_value() ? value.val_real(this) : 0e0;
  }


void in_datetime::set(uint pos,Item *item)
{
  struct packed_longlong *buff= &((packed_longlong*) base)[pos];

  buff->val= item->val_datetime_packed(current_thd);
  buff->unsigned_flag= 1L;
}


virtual bool is_outer_field() const { DBUG_ASSERT(is_fixed()); return FALSE; }


bool Item_func_case::aggregate_then_and_else_arguments(THD *thd, uint start)
{
  if (aggregate_for_result(func_name(), args + start, arg_count - start, true))
    return true;

  if (fix_attributes(args + start, arg_count - start))
    return true;

  return false;
}


TYPELIB *get_typelib() const { return field->get_typelib(); }


  const Type_handler *type_handler() const
  {
    return Type_handler::blob_type_handler(max_length);
  }


Item *in_timestamp::create_item(THD *thd)
{
  return new (thd->mem_root) Item_timestamp_literal(thd);
}


Item_bool_rowready_func2::value_depends_on_sql_mode() const
{
  if (compare_collation()->state & MY_CS_NOPAD)
    return Item_func::value_depends_on_sql_mode();
  return ((args[0]->value_depends_on_sql_mode() |
           args[1]->value_depends_on_sql_mode()) &
          Sql_mode_dependency(~0, ~MODE_PAD_CHAR_TO_FULL_LENGTH)).
         soft_to_hard();
}


longlong Item_func_ne::val_int()
{
  DBUG_ASSERT(fixed == 1);
  int value= cmp.compare();
  return value != 0 && !null_value ? 1 : 0;
}


bool Regexp_processor_pcre::exec(String *str, int offset,
                                  uint n_result_offsets_to_convert)
{
  if (!(str= convert_if_needed(str, &subject_converter)))
    return true;
  m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, &m_pcre_extra,
                                      str->c_ptr_safe(), str->length(),
                                      offset, 0,
                                      m_SubStrVec, array_elements(m_SubStrVec));
  if (m_pcre_exec_rc > 0)
  {
    uint i;
    for (i= 0; i < n_result_offsets_to_convert; i++)
    {
      /*
        Convert byte offset into character offset.
      */
      m_SubStrVec[i]= (int) str->charset()->cset->numchars(str->charset(),
                                                           str->ptr(),
                                                           str->ptr() +
                                                           m_SubStrVec[i]);
    }
  }
  return false;
}


  virtual Item *multiple_equality_transformer(THD *thd, uchar *arg)
  { return this; }


  void fix_from_value(Derivation dv, const Metadata metadata)
  {
    fix_charset_and_length(str_value.charset(), dv, metadata);
  }


void Item_func_if::fix_after_pullout(st_select_lex *new_parent,
                                     Item **ref, bool merge)
{
  /* This will re-calculate attributes of the arguments */
  Item_func::fix_after_pullout(new_parent, ref, merge);
  /* Then, re-calculate not_null_tables_cache according to our special rules */
  eval_not_null_tables(NULL);
}


  void make_send_field(THD *thd, Send_field *field)
  { item->make_send_field(thd, field); }


static int cmp_decimal(void *cmp_arg, my_decimal *a, my_decimal *b)
{
  /*
    We need call of fixing buffer pointer, because fast sort just copy
    decimal buffers in memory and pointers left pointing on old buffer place
  */
  a->fix_buffer_pointer();
  b->fix_buffer_pointer();
  return my_decimal_cmp(a, b);
}


  Item_default_value(THD *thd, Name_resolution_context *context_arg, Item *a,
                     bool vcol_assignment_arg)
    :Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL,
                &null_clex_str), vcol_assignment_ok(vcol_assignment_arg),
     arg(a), cached_field(NULL) {}


  const Type_handler *type_handler_long_or_longlong() const
  {
    return Type_handler::type_handler_long_or_longlong(max_char_length());
  }


  Item_contextually_typed_value_specification(THD *thd) :Item(thd)
  { }


  Item_datetime_literal(THD *thd, const Datetime *ltime, uint dec_arg):
    Item_temporal_literal(thd, dec_arg),
    cached_time(*ltime)
  {
    DBUG_ASSERT(cached_time.is_valid_datetime());
    max_length= MAX_DATETIME_WIDTH + (decimals ? decimals + 1 : 0);
    // See the comment on maybe_null in Item_date_literal
    maybe_null= cached_time.check_date(TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE);
  }


double val_real() { return cached_time.to_double(); }


Item_func_nullif::native_op(THD *thd, Native *to)
{
  DBUG_ASSERT(fixed == 1);
  if (!compare())
    return (null_value= true);
  return val_native_with_conversion_from_item(thd, args[2], to, type_handler());
}


  Item *get_copy(THD *thd)
  { return get_item_copy<Item_null>(thd, this); }


uchar *in_double::get_value(Item *item)
{
  tmp= item->val_real();
  if (item->null_value)
    return 0;					/* purecov: inspected */
  return (uchar*) &tmp;
}


static void propagate_and_change_item_tree(THD *thd, Item **place,
                                           COND_EQUAL *cond,
                                           const Item::Context &ctx)
{
  Item *new_value= (*place)->propagate_equal_fields(thd, ctx, cond);
  if (new_value && *place != new_value)
    thd->change_item_tree(place, new_value);
}


longlong Item_func_bit_or::val_int()
{
  DBUG_ASSERT(fixed == 1);
  ulonglong arg1= (ulonglong) args[0]->val_int();
  if (args[0]->null_value)
  {
    null_value=1; /* purecov: inspected */
    return 0; /* purecov: inspected */
  }
  ulonglong arg2= (ulonglong) args[1]->val_int();
  if (args[1]->null_value)
  {
    null_value=1;
    return 0;
  }
  null_value=0;
  return (longlong) (arg1 | arg2);
}


Item *build_clone(THD *thd) { return 0; }


uint cols() const { return item_count; }


bool Item_func_case::date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
{
  DBUG_ASSERT(fixed == 1);
  Item *item= find_item();
  if (!item)
    return (null_value= true);
  Datetime_truncation_not_needed dt(thd, item, fuzzydate);
  return (null_value= dt.copy_to_mysql_time(ltime, mysql_timestamp_type()));
}


  Item *get_copy(THD *thd)
  { return get_item_copy<Item_hex_hybrid>(thd, this); }


  String *val_str_from_item(Item *item, String *str)
  {
    DBUG_ASSERT(is_fixed());
    String *res= item->val_str(str);
    if (res)
      res->set_charset(collation.collation);
    if ((null_value= item->null_value))
      res= NULL;
    return res;
  }


in_double::in_double(THD *thd, uint elements)
  :in_vector(thd, elements, sizeof(double), (qsort2_cmp) cmp_double, 0)
{}


  virtual bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
  { return false; }


String *Regexp_processor_pcre::convert_if_needed(String *str, String *converter)
{
  if (m_conversion_is_needed)
  {
    uint dummy_errors;
    if (converter->copy(str->ptr(), str->length(), str->charset(),
                        m_library_charset, &dummy_errors))
      return NULL;
    str= converter;
  }
  return str;
}


Item_func_if::fix_fields(THD *thd, Item **ref)
{
  DBUG_ASSERT(fixed == 0);
  args[0]->top_level_item();

  if (Item_func::fix_fields(thd, ref))
    return 1;

  return 0;
}


longlong Item_func_eq::val_int()
{
  DBUG_ASSERT(fixed == 1);
  int value= cmp.compare();
  return value == 0 ? 1 : 0;
}


void Item_cond::print(String *str, enum_query_type query_type)
{
  List_iterator_fast<Item> li(list);
  Item *item;
  if ((item=li++))
    item->print_parenthesised(str, query_type, precedence());
  while ((item=li++))
  {
    str->append(' ');
    str->append(func_name());
    str->append(' ');
    item->print_parenthesised(str, query_type, precedence());
  }
}


void Item_is_not_null_test::update_used_tables()
{
  if (!args[0]->maybe_null)
    used_tables_cache= 0;			/* is always true */
  else
    args[0]->update_used_tables();
}


  With_sum_func_cache(const Item *a, const Item *b, const Item *c,
                      const Item *d)
   :m_with_sum_func(a->with_sum_func() || b->with_sum_func() ||
                    c->with_sum_func() || d->with_sum_func())
  { }


Item *remove_item_direct_ref() { return this; }


const Type_handler *type_handler() const { return &type_handler_hex_hybrid; }


  bool get_date_from_item(THD *thd, Item *item,
                          MYSQL_TIME *ltime, date_mode_t fuzzydate)
  {
    bool rc= item->get_date(thd, ltime, fuzzydate);
    null_value= MY_TEST(rc || item->null_value);
    return rc;
  }


Item_cond::used_tables() const
{						// This caches used_tables
  return used_tables_cache;
}


  int save_in_field(Field *field_arg, bool no_conversions)
  {
    return field_arg->save_in_field_ignore_value(false);
  }


Item_func_nullif::fix_length_and_dec()
{
  /*
    If this is the first invocation of fix_length_and_dec(), create the
    third argument as a copy of the first. This cannot be done before
    fix_fields(), because fix_fields() might replace items,
    for exampe NOT x --> x==0, or (SELECT 1) --> 1.
    See also class Item_func_nullif declaration.
  */
  if (arg_count == 2)
    args[arg_count++]= m_arg0 ? m_arg0 : args[0];

  THD *thd= current_thd;
  /*
    At prepared statement EXECUTE time, args[0] can already
    point to a different Item, created during PREPARE time fix_length_and_dec().
    For example, if character set conversion was needed, arguments can look
    like this:

      args[0]= > Item_func_conv_charset \
                                         l_expr
      args[2]= >------------------------/

    Otherwise (during PREPARE or convensional execution),
    args[0] and args[2] should still point to the same original l_expr.
  */
  DBUG_ASSERT(args[0] == args[2] || thd->stmt_arena->is_stmt_execute());
  if (args[0]->type() == SUM_FUNC_ITEM &&
      !thd->lex->is_ps_or_view_context_analysis())
  {
    /*
      NULLIF(l_expr, r_expr)

        is calculated in the way to return a result equal to:

      CASE WHEN l_expr = r_expr THEN NULL ELSE r_expr END.

      There's nothing special with r_expr, because it's referenced
      only by args[1] and nothing else.

      l_expr needs a special treatment, as it's referenced by both
      args[0] and args[2] initially.

      args[2] is used to return the value. Afrer all transformations
      (e.g. in fix_length_and_dec(), equal field propagation, etc)
      args[2] points to a an Item which preserves the exact data type and
      attributes (e.g. collation) of the original l_expr.
      It can point:
      - to the original l_expr
      - to an Item_cache pointing to l_expr
      - to a constant of the same data type with l_expr.

      args[0] is used for comparison. It can be replaced:

      - to Item_func_conv_charset by character set aggregation routines
      - to a constant Item by equal field propagation routines
        (in case of Item_field)

      The data type and/or the attributes of args[0] can differ from
      the data type and the attributes of the original l_expr, to make
      it comparable to args[1] (which points to r_expr or its replacement).

      For aggregate functions we have to wrap the original args[0]/args[2]
      into Item_cache (see MDEV-9181). In this case the Item_cache
      instance becomes the subject to character set conversion instead of
      the original args[0]/args[2], while the original args[0]/args[2] get
      hidden inside the cache.

      Some examples of what NULLIF can end up with after argument
      substitution (we don't mention args[1] in some cases for simplicity):

      1. l_expr is not an aggregate function:

        a. No conversion happened.
           args[0] and args[2] were not replaced to something else
           (i.e. neither by character set conversion, nor by propagation):

          args[1] > r_expr
          args[0] \
                    l_expr
          args[2] /

        b. Conversion of args[0] happened:

           CREATE OR REPLACE TABLE t1 (
             a CHAR(10) CHARACTER SET latin1,
             b CHAR(10) CHARACTER SET utf8);
           SELECT * FROM t1 WHERE NULLIF(a,b);

           args[1] > r_expr                          (Item_field for t1.b)
           args[0] > Item_func_conv_charset\
                                            l_expr   (Item_field for t1.a)
           args[2] > ----------------------/

        c. Conversion of args[1] happened:

          CREATE OR REPLACE TABLE t1 (
            a CHAR(10) CHARACTER SET utf8,
            b CHAR(10) CHARACTER SET latin1);
          SELECT * FROM t1 WHERE NULLIF(a,b);

          args[1] > Item_func_conv_charset -> r_expr (Item_field for t1.b)
          args[0] \
                   l_expr                            (Item_field for t1.a)
          args[2] /

        d. Conversion of only args[0] happened (by equal field proparation):

           CREATE OR REPLACE TABLE t1 (
             a CHAR(10),
             b CHAR(10));
           SELECT * FROM t1 WHERE NULLIF(a,b) AND a='a';

           args[1] > r_expr            (Item_field for t1.b)
           args[0] > Item_string('a')  (constant replacement for t1.a)
           args[2] > l_expr            (Item_field for t1.a)

        e. Conversion of both args[0] and args[2] happened
           (by equal field propagation):

           CREATE OR REPLACE TABLE t1 (a INT,b INT);
           SELECT * FROM t1 WHERE NULLIF(a,b) AND a=5;

           args[1] > r_expr         (Item_field for "b")
           args[0] \
                    Item_int (5)    (constant replacement for "a")
           args[2] /

      2. In case if l_expr is an aggregate function:

        a. No conversion happened:

          args[0] \
                   Item_cache > l_expr
          args[2] /

        b. Conversion of args[0] happened:

          args[0] > Item_func_conv_charset \
                                            Item_cache > l_expr
          args[2] >------------------------/

        c. Conversion of both args[0] and args[2] happened.
           (e.g. by equal expression propagation)
           TODO: check if it's possible (and add an example query if so).
    */
    m_cache= args[0]->cmp_type() == STRING_RESULT ?
             new (thd->mem_root) Item_cache_str_for_nullif(thd, args[0]) :
             args[0]->get_cache(thd);
    if (!m_cache)
      return TRUE;
    m_cache->setup(thd, args[0]);
    m_cache->store(args[0]);
    m_cache->set_used_tables(args[0]->used_tables());
    thd->change_item_tree(&args[0], m_cache);
    thd->change_item_tree(&args[2], m_cache);
  }
  set_handler(args[2]->type_handler());
  collation.set(args[2]->collation);
  decimals= args[2]->decimals;
  unsigned_flag= args[2]->unsigned_flag;
  fix_char_length(args[2]->max_char_length());
  maybe_null=1;
  m_arg0= args[0];
  if (setup_args_and_comparator(thd, &cmp))
    return TRUE;
  /*
    A special code for EXECUTE..PREPARE.

    If args[0] did not change, then we don't remember it, as it can point
    to a temporary Item object which will be destroyed between PREPARE
    and EXECUTE. EXECUTE time fix_length_and_dec() will correctly set args[2]
    from args[0] again.

    If args[0] changed, then it can be Item_func_conv_charset() for the
    original args[0], which was permanently installed during PREPARE time
    into the item tree as a wrapper for args[0], using change_item_tree(), i.e.

      NULLIF(latin1_field, 'a' COLLATE utf8_bin)

    was "rewritten" to:

      CASE WHEN CONVERT(latin1_field USING utf8) = 'a' COLLATE utf8_bin
        THEN NULL
        ELSE latin1_field

    - m_args0 points to Item_field corresponding to latin1_field
    - args[0] points to Item_func_conv_charset
    - args[0]->args[0] is equal to m_args0
    - args[1] points to Item_func_set_collation
    - args[2] points is eqial to m_args0

    In this case we remember and reuse m_arg0 during EXECUTE time as args[2].

    QQ: How to make sure that m_args0 does not point
    to something temporary which will be destroyed between PREPARE and EXECUTE.
    The condition below should probably be more strict and somehow check that:
    - change_item_tree() was called for the new args[0]
    - m_args0 is referenced from inside args[0], e.g. as a function argument,
      and therefore it is also something that won't be destroyed between
      PREPARE and EXECUTE.
    Any ideas?
  */
  if (args[0] == m_arg0)
    m_arg0= NULL;
  return FALSE;
}


  bool set_fields_as_dependent_processor(void *arg)
  {
    if (!(used_tables() & OUTER_REF_TABLE_BIT))
    {
      depended_from= (st_select_lex *) arg;
      item_equal= NULL;
    }
    return 0;
  }


  Item_result_field(THD *thd, Item_result_field *item):
    Item_fixed_hybrid(thd, item), result_field(item->result_field)
  {}


bool Item_func_case::time_op(THD *thd, MYSQL_TIME *ltime)
{
  DBUG_ASSERT(fixed == 1);
  Item *item= find_item();
  if (!item)
    return (null_value= true);
  return (null_value= Time(thd, item).copy_to_mysql_time(ltime));
}


Item* element_index(uint i) { return arg_count ? args[i] : this; }


  Item_direct_view_ref(THD *thd, Name_resolution_context *context_arg,
                       Item **item,
                       const char *table_name_arg,
                       LEX_CSTRING *field_name_arg,
                       TABLE_LIST *view_arg):
    Item_direct_ref(thd, context_arg, item, table_name_arg, field_name_arg),
    item_equal(0), view(view_arg),
    null_ref_table(NULL)
  {
    if (fixed)
      set_null_ref_table();
  }


int Arg_comparator::compare_row()
{
  int res= 0;
  bool was_null= 0;
  (*a)->bring_value();
  (*b)->bring_value();

  if ((*a)->null_value || (*b)->null_value)
  {
    owner->null_value= 1;
    return -1;
  }

  uint n= (*a)->cols();
  for (uint i= 0; i<n; i++)
  {
    res= comparators[i].compare();
    /* Aggregate functions don't need special null handling. */
    if (owner->null_value && owner->type() == Item::FUNC_ITEM)
    {
      // NULL was compared
      switch (((Item_func*)owner)->functype()) {
      case Item_func::NE_FUNC:
        break; // NE never aborts on NULL even if abort_on_null is set
      case Item_func::LT_FUNC:
      case Item_func::LE_FUNC:
      case Item_func::GT_FUNC:
      case Item_func::GE_FUNC:
        return -1; // <, <=, > and >= always fail on NULL
      case Item_func::EQ_FUNC:
        if (((Item_func_eq*)owner)->abort_on_null)
          return -1; // We do not need correct NULL returning
        break;
      default:
        DBUG_ASSERT(0);
        break;
      }
      was_null= 1;
      owner->null_value= 0;
      res= 0;  // continue comparison (maybe we will meet explicit difference)
    }
    else if (res)
      return res;
  }
  if (was_null)
  {
    /*
      There was NULL(s) in comparison in some parts, but there was no
      explicit difference in other parts, so we have to return NULL.
    */
    owner->null_value= 1;
    return -1;
  }
  return 0;
}