Item *Field_new_decimal::get_equal_const_item(THD *thd, const Context &ctx,
                                              Item *const_item)
{
  if (flags & ZEROFILL_FLAG)
    return Field_num::get_equal_zerofill_const_item(thd, ctx, const_item);
  switch (ctx.subst_constraint()) {
  case IDENTITY_SUBST:
    if (const_item->field_type() != MYSQL_TYPE_NEWDECIMAL ||
        const_item->decimal_scale() != decimals())
    {
      my_decimal *val, val_buffer, val_buffer2;
      if (!(val= const_item->val_decimal(&val_buffer)))
      {
        DBUG_ASSERT(0);
        return const_item;
      }
      /*
        Truncate or extend the decimal value to the scale of the field.
        See comments about truncation in the same place in
        Field_time::get_equal_const_item().
      */
      my_decimal_round(E_DEC_FATAL_ERROR, val, decimals(), true, &val_buffer2);
      return new (thd->mem_root) Item_decimal(thd, field_name.str,
                                              &val_buffer2,
                                              decimals(), field_length);
    }
    break;
  case ANY_SUBST:
    break;
  }
  return const_item;
}


longlong val_int(void) { return val_int_from_real(false); }


uint Field_str::is_equal(Create_field *new_field)
{
  return new_field->type_handler() == type_handler() &&
         new_field->charset == field_charset &&
         new_field->length == max_display_length();
}


int Field_bit_as_char::store(const char *from, size_t length, CHARSET_INFO *cs)
{
  ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
  int delta;
  uchar bits= (uchar) (field_length & 7);

  for (; length && !*from; from++, length--)          // skip left 0's
    ;
  delta= (int)(bytes_in_rec - length);

  if (delta < 0 ||
      (delta == 0 && bits && (uint) (uchar) *from >= (uint) (1 << bits)))
  {
    memset(ptr, 0xff, bytes_in_rec);
    if (bits)
      *ptr&= ((1 << bits) - 1); /* set first uchar */
    if (get_thd()->really_abort_on_warning())
      set_warning(ER_DATA_TOO_LONG, 1);
    else
      set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1);
    return 1;
  }
  bzero(ptr, delta);
  memcpy(ptr + delta, from, length);
  return 0;
}


bool Field_temporal::can_optimize_group_min_max(const Item_bool_func *cond,
                                                const Item *const_item) const
{
  return true; // Field is of TIME_RESULT, which supersedes everything else.
}


int Field_varstring_compressed::store(const char *from, size_t length,
                                      CHARSET_INFO *cs)
{
  ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
  uint compressed_length;
  int rc= compress((char*) get_data(), field_length, from, (uint) length,
                   Field_varstring_compressed::max_display_length(),
                   &compressed_length, cs,
                   Field_varstring_compressed::char_length());
  store_length(compressed_length);
  return rc;
}


    information_schema_numeric_attributes() const
  {
    return dec == NOT_FIXED_DEC ?
                  Information_schema_numeric_attributes(field_length) :
                  Information_schema_numeric_attributes(field_length, dec);
  }


  bool eq(Field *field)
  {
    return (Field::eq(field) &&
            bit_ptr == ((Field_bit *)field)->bit_ptr &&
            bit_ofs == ((Field_bit *)field)->bit_ofs);
  }


  Field_time_hires(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
             enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
             uint dec_arg)
    :Field_time_with_dec(ptr_arg, null_ptr_arg,
                         null_bit_arg, unireg_check_arg, field_name_arg,
                         dec_arg)
  {
    DBUG_ASSERT(dec);
    zero_point= sec_part_shift(
                   ((TIME_MAX_VALUE_SECONDS+1LL)*TIME_SECOND_PART_FACTOR), dec);
  }


  const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end,
                      uint param_data __attribute__((unused)))
  {
    return unpack_int64(to, from, from_end);
  }


bool Field_geom::load_data_set_null(THD *thd)
{
  Field_blob::reset();
  if (!maybe_null())
  {
    my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field_name.str,
             thd->get_stmt_da()->current_row_for_warning());
    return true;
  }
  set_null();
  set_has_explicit_value(); // Do not auto-update this field
  return false;
}


Field_varstring::unpack(uchar *to, const uchar *from, const uchar *from_end,
                        uint param_data)
{
  uint length;
  uint l_bytes= (param_data && (param_data < field_length)) ?
                (param_data <= 255) ? 1 : 2 : length_bytes;

  if (from + l_bytes > from_end)
    return 0;                                 // Error in data

  if (l_bytes == 1)
  {
    to[0]= *from++;
    length= to[0];
    if (length_bytes == 2)
      to[1]= 0;
  }
  else /* l_bytes == 2 */
  {
    length= uint2korr(from);
    to[0]= *from++;
    to[1]= *from++;
  }
  if (length)
  {
    if (from + length > from_end || length > field_length)
      return 0;                                 // Error in data
    memcpy(to+ length_bytes, from, length);
  }
  return from+length;
}


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


double Field_tiny::val_real(void)
{
  ASSERT_COLUMN_MARKED_FOR_READ;
  int tmp= unsigned_flag ? (int) ptr[0] :
    (int) ((signed char*) ptr)[0];
  return (double) tmp;
}


  bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
  {
    return get_date(ltime, fuzzydate, (ulonglong) val_int());
  }


int Field_float::store(double nr)
{
  ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
  int error= truncate_double(&nr, field_length,
                             not_fixed ? NOT_FIXED_DEC : dec,
                             unsigned_flag, FLT_MAX);
  if (unlikely(error))
  {
    set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1);
    if (error < 0)                                // Wrong double value
    {
      error= 1;
      set_null();
    }
  }
  float j= (float)nr;

  float4store(ptr,j);
  return error;
}


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


  uchar *pack_int(uchar *to, const uchar *from, size_t size)
  {
    memcpy(to, from, size);
    return to + size;
  }


longlong Field_longlong::val_int(void)
{
  ASSERT_COLUMN_MARKED_FOR_READ;
  longlong j;
  j=sint8korr(ptr);
  return j;
}


bool Field_float::send_binary(Protocol *protocol)
{
  ASSERT_COLUMN_MARKED_FOR_READ;
  return protocol->store((float) Field_float::val_real(), dec, (String*) 0);
}


Field *Field::make_new_field(MEM_ROOT *root, TABLE *new_table,
                             bool keep_type __attribute__((unused)))
{
  Field *tmp;
  if (!(tmp= (Field*) memdup_root(root,(char*) this,size_of())))
    return 0;

  if (tmp->table->maybe_null)
    tmp->flags&= ~NOT_NULL_FLAG;
  tmp->table= new_table;
  tmp->key_start.init(0);
  tmp->part_of_key.init(0);
  tmp->part_of_sortkey.init(0);
  /*
    TODO: it is not clear why this method needs to reset unireg_check.
    Try not to reset it, or explain why it needs to be reset.
  */
  tmp->unireg_check= Field::NONE;
  tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG |
                ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG |
                VERS_ROW_START | VERS_ROW_END |
                VERS_UPDATE_UNVERSIONED_FLAG);
  tmp->reset_fields();
  tmp->invisible= VISIBLE;
  return tmp;
}


virtual uint32 key_length() const { return pack_length(); }


  const Type_limits_int *type_limits_int() const
  {
    return type_handler_longlong.type_limits_int_by_unsigned_flag(is_unsigned());
  }


bool Field_datetime_with_dec::send_binary(Protocol *protocol)
{
  MYSQL_TIME ltime;
  get_date(&ltime, 0);
  return protocol->store(&ltime, dec);
}


double result() const { return m_result; }


bool Field_time_hires::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
  if (check_zero_in_date_with_warn(fuzzydate))
    return true;
  uint32 len= pack_length();
  longlong packed= read_bigendian(ptr, len);

  packed= sec_part_unshift(packed - zero_point, dec);

  unpack_time(packed, ltime, MYSQL_TIMESTAMP_TIME);
  return false;
}


    Converter_double_to_longlong_with_warn(THD *thd, double nr,
                                           bool unsigned_flag)
      :Converter_double_to_longlong(nr, unsigned_flag)
    {
      if (m_error)
        push_warning(thd, nr, unsigned_flag);
    }


int Field_bit::store(longlong nr, bool unsigned_val)
{
  char buf[8];

  mi_int8store(buf, nr);
  return store(buf, 8, NULL);
}


  void set_cursor_rowtype_ref(uint offset)
  {
    set_handler(&type_handler_row);
    m_cursor_rowtype_ref= true;
    m_cursor_rowtype_offset= offset;
  }


bool TABLE::vcol_fix_expr(THD *thd)
{
  if (pos_in_table_list->placeholder() || vcol_refix_list.is_empty())
    return false;

  if (!thd->stmt_arena->is_conventional() &&
      vcol_refix_list.head()->expr->fixed)
  {
    /* NOTE: Under trigger we already have fixed expressions */
    return false;
  }

  Vcol_expr_context expr_ctx(thd, this);
  if (expr_ctx.init())
    return true;

  List_iterator_fast<Virtual_column_info> it(vcol_refix_list);
  while (Virtual_column_info *vcol= it++)
    if (vcol->fix_session_expr(thd))
      goto error;

  return false;

error:
  DBUG_ASSERT(thd->get_stmt_da()->is_error());
  return true;
}


longlong Field_decimal::val_int(void)
{
  ASSERT_COLUMN_MARKED_FOR_READ;
  int not_used;
  if (unsigned_flag)
    return my_strntoull(&my_charset_bin, (char*) ptr, field_length, 10, NULL,
			&not_used);
  return my_strntoll(&my_charset_bin, (char*) ptr, field_length, 10, NULL,
                     &not_used);
}


int Field_date::cmp(const uchar *a_ptr, const uchar *b_ptr)
{
  int32 a,b;
  a=sint4korr(a_ptr);
  b=sint4korr(b_ptr);
  return ((uint32) a < (uint32) b) ? -1 : ((uint32) a > (uint32) b) ? 1 : 0;
}


  int check_int(CHARSET_INFO *cs, const char *str, size_t length,
                const char *int_end, int error)
  {
    return check_edom_and_truncation("integer",
                                     error == MY_ERRNO_EDOM || str == int_end,
                                     cs, str, length, int_end);
  }


int Field_datetime::set_time()
{
  THD *thd= table->in_use;
  MYSQL_TIME now_time;
  thd->variables.time_zone->gmt_sec_to_TIME(&now_time, thd->query_start());
  now_time.second_part= thd->query_start_sec_part();
  set_notnull();
  store_TIME(&now_time);
  thd->time_zone_used= 1;
  return 0;
}


Field_timestamp::validate_value_in_record(THD *thd, const uchar *record) const
{
  DBUG_ASSERT(!is_null_in_record(record));
  ulong sec_part;
  return !get_timestamp(ptr_in_record(record), &sec_part) && !sec_part &&
         (sql_mode_for_dates(thd) & TIME_NO_ZERO_DATE) != 0;
}


  int cmp(const uchar *a_ptr, const uchar *b_ptr)
  {
    return memcmp(a_ptr, b_ptr, pack_length());
  }


longlong Field_varstring::val_int(void)
{
  ASSERT_COLUMN_MARKED_FOR_READ;
  THD *thd= get_thd();
  return Converter_strntoll_with_warn(thd, Warn_filter(thd),
                                      Field_varstring::charset(),
                                      (const char *) get_data(),
                                      get_length()).result();
}


int Field_blob::copy_value(Field_blob *from)
{
  DBUG_ASSERT(field_charset == from->charset());
  DBUG_ASSERT(!compression_method() == !from->compression_method());
  int rc= 0;
  uint32 length= from->get_length();
  uchar *data= from->get_ptr();
  if (packlength < from->packlength)
  {
    set_if_smaller(length, Field_blob::max_data_length());
    length= (uint32) Well_formed_prefix(field_charset,
                                        (const char *) data, length).length();
    rc= report_if_important_data((const char *) data + length,
                                 (const char *) data + from->get_length(),
                                 true);
  }
  store_length(length);
  bmove(ptr + packlength, (uchar*) &data, sizeof(char*));
  return rc;
}


  virtual int key_cmp(const uchar *str, uint length)
  { return cmp(ptr,str); }


String *Field_varstring::val_str(String *val_buffer __attribute__((unused)),
				 String *val_ptr)
{
  ASSERT_COLUMN_MARKED_FOR_READ;
  val_ptr->set((const char*) get_data(), get_length(), field_charset);
  return val_ptr;
}


int Field_datetime::cmp(const uchar *a_ptr, const uchar *b_ptr)
{
  longlong a,b;
  a=sint8korr(a_ptr);
  b=sint8korr(b_ptr);
  return ((ulonglong) a < (ulonglong) b) ? -1 :
    ((ulonglong) a > (ulonglong) b) ? 1 : 0;
}


  Field_time_with_dec(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
                      enum utype unireg_check_arg,
                      const LEX_CSTRING *field_name_arg,
                      uint dec_arg)
    :Field_time(ptr_arg, MIN_TIME_WIDTH + dec_arg + MY_TEST(dec_arg),
                null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg),
     dec(dec_arg)
  {
    DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
  }


  uint32 pack_length_no_ptr() const
  { return (uint32) (packlength); }


bool check_expression(Virtual_column_info *vcol, LEX_CSTRING *name,
                      enum_vcol_info_type type)

{
  bool ret;
  Item::vcol_func_processor_result res;

  if (!vcol->name.length)
    vcol->name= *name;

  /*
    Walk through the Item tree checking if all items are valid
    to be part of the virtual column
  */
  res.errors= 0;
  ret= vcol->expr->walk(&Item::check_vcol_func_processor, 0, &res);
  vcol->flags= res.errors;

  uint filter= VCOL_IMPOSSIBLE;
  if (type != VCOL_GENERATED_VIRTUAL && type != VCOL_DEFAULT)
    filter|= VCOL_NOT_STRICTLY_DETERMINISTIC;
  if (type == VCOL_GENERATED_VIRTUAL)
    filter|= VCOL_NOT_VIRTUAL;

  if (unlikely(ret || (res.errors & filter)))
  {
    my_error(ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0), res.name,
             vcol_type_name(type), name->str);
    return TRUE;
  }
  /*
    Safe to call before fix_fields as long as vcol's don't include sub
    queries (which is now checked in check_vcol_func_processor)
  */
  if (vcol->expr->check_cols(1))
    return TRUE;
  return FALSE;
}


copy_or_convert_to_datetime(THD *thd, const MYSQL_TIME *from, MYSQL_TIME *to)
{
  if (from->time_type == MYSQL_TIMESTAMP_TIME)
    return time_to_datetime(thd, from, to);
  *to= *from;
  return false;
}


int Field_string::store(const char *from, size_t length,CHARSET_INFO *cs)
{
  ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
  uint copy_length;
  int rc;

  /* See the comment for Field_long::store(long long) */
  DBUG_ASSERT(!table || table->in_use == current_thd);

  rc= well_formed_copy_with_check((char*) ptr, field_length,
                                  cs, from, length,
                                  field_length / field_charset->mbmaxlen,
                                  false, &copy_length);

  /* Append spaces if the string was shorter than the field. */
  if (copy_length < field_length)
    field_charset->cset->fill(field_charset,(char*) ptr+copy_length,
                              field_length-copy_length,
                              field_charset->pad_char);

  return rc;
}


int reset(void) { bzero(ptr, packlength+sizeof(uchar*)); return 0; }


  uchar *pack_int32(uchar *to, const uchar *from)
  { return pack_int(to, from, 4); }


inline ulonglong char_prefix_to_ulonglong(uchar *src)
{
  uint sz= sizeof(ulonglong);
  for (uint i= 0; i < sz/2; i++)
  {
    uchar tmp= src[i];
    src[i]= src[sz-1-i];
    src[sz-1-i]= tmp;
  }
  return uint8korr(src);
}


  uint get_length() const
  {
    return length_bytes == 1 ? (uint) *ptr : uint2korr(ptr);
  }


void Field_varstring::sql_type(String &res) const
{
  THD *thd= table->in_use;
  CHARSET_INFO *cs=res.charset();
  size_t length;

  length= cs->cset->snprintf(cs,(char*) res.ptr(),
                             res.alloced_length(), "%s(%u)",
                              (has_charset() ? "varchar" : "varbinary"),
                              (uint) char_length());
  res.length(length);
  if ((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) &&
      has_charset() && (charset()->state & MY_CS_BINSORT))
    res.append(STRING_WITH_LEN(" binary"));
}


int Field_bit::cmp_offset(uint row_offset)
{
  if (bit_len)
  {
    int flag;
    uchar bits_a= get_rec_bits(bit_ptr, bit_ofs, bit_len);
    uchar bits_b= get_rec_bits(bit_ptr + row_offset, bit_ofs, bit_len);
    if ((flag= (int) (bits_a - bits_b)))
      return flag;
  }
  return memcmp(ptr, ptr + row_offset, bytes_in_rec);
}


int Field_time::store_time_dec(const MYSQL_TIME *ltime, uint dec)
{
  MYSQL_TIME l_time= *ltime;
  ErrConvTime str(ltime);
  int was_cut= 0;

  if (curdays && l_time.time_type != MYSQL_TIMESTAMP_TIME)
    calc_datetime_days_diff(&l_time, curdays);

  int have_smth_to_conv= !check_time_range(&l_time, decimals(), &was_cut);
  return store_TIME_with_warning(&l_time, &str, was_cut, have_smth_to_conv);
}


my_decimal *Field::val_decimal(my_decimal *decimal)
{
  /* This never have to be called */
  DBUG_ASSERT(0);
  return 0;
}


  const uchar *unpack_int(uchar* to, const uchar *from,
                          const uchar *from_end, size_t size)
  {
    if (from + size > from_end)
      return 0;
    memcpy(to, from, size);
    return from + size;
  }


longlong Field_timestamp::val_int(void)
{
  MYSQL_TIME ltime;
  if (get_date(&ltime, TIME_NO_ZERO_DATE))
    return 0;

  return ltime.year * 10000000000LL + ltime.month * 100000000LL +
         ltime.day * 1000000L + ltime.hour * 10000L +
         ltime.minute * 100 + ltime.second;
}


  int store(longlong nr, bool unsigned_val)
  { return Field_bit::store(nr, unsigned_val); }


double Field_medium::val_real(void)
{
  ASSERT_COLUMN_MARKED_FOR_READ;
  long j= unsigned_flag ? (long) uint3korr(ptr) : sint3korr(ptr);
  return (double) j;
}


  Field_decimal(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
		uchar null_bit_arg,
		enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
		uint8 dec_arg,bool zero_arg,bool unsigned_arg)
    :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
                unireg_check_arg, field_name_arg,
                dec_arg, zero_arg, unsigned_arg)
    {}


Field_temporal_with_date::validate_value_in_record(THD *thd,
                                                   const uchar *record) const
{
  DBUG_ASSERT(!is_null_in_record(record));
  MYSQL_TIME ltime;
  return get_TIME(&ltime, ptr_in_record(record), sql_mode_for_dates(thd));
}


bool Field_short::send_binary(Protocol *protocol)
{
  return protocol->store_short(Field_short::val_int());
}


bool TABLE::vcol_cleanup_expr(THD *thd)
{
  if (vcol_refix_list.is_empty())
    return false;

  List_iterator<Virtual_column_info> it(vcol_refix_list);
  bool result= false;

  while (Virtual_column_info *vcol= it++)
    result|= vcol->cleanup_session_expr();

  DBUG_ASSERT(!result || thd->get_stmt_da()->is_error());
  return result;
}


int Field_time_hires::cmp(const uchar *a_ptr, const uchar *b_ptr)
{
  ulonglong a=read_bigendian(a_ptr, Field_time_hires::pack_length());
  ulonglong b=read_bigendian(b_ptr, Field_time_hires::pack_length());
  return (a < b) ? -1 : (a > b) ? 1 : 0;
}


  ha_storage_media field_storage_type() const
  {
    return (ha_storage_media)
      ((flags >> FIELD_FLAGS_STORAGE_MEDIA) & 3);
  }


virtual TYPELIB *get_typelib() const { return NULL; }


  bool can_optimize_outer_join_table_elimination(const Item_bool_func *cond,
                                                 const Item *item) const
  {
    // Exactly the same rules with REF access
    return can_optimize_keypart_ref(cond, item);
  }


  void set_ptr_offset(my_ptrdiff_t ptr_diff, uint32 length, const uchar *data)
  {
    uchar *ptr_ofs= ADD_TO_PTR(ptr,ptr_diff,uchar*);
    store_length(ptr_ofs, packlength, length);
    memcpy(ptr_ofs+packlength, &data, sizeof(char*));
  }


Column_definition::set_compressed_deprecated_column_attribute(THD *thd,
                                                              const char *pos,
                                                              const char *method)
{
  if (compression_method_ptr)
  {
    /*
      Compression method has already been set, e.g.:
        a VARCHAR(10) COMPRESSED DEFAULT 10 COMPRESSED
    */
    thd->parse_error(ER_SYNTAX_ERROR, pos);
    return true;
  }
  enum enum_field_types sql_type= real_field_type();
  /* We can't use f_is_blob here as pack_flag is not yet set */
  if (sql_type == MYSQL_TYPE_VARCHAR || sql_type == MYSQL_TYPE_TINY_BLOB ||
      sql_type == MYSQL_TYPE_BLOB || sql_type == MYSQL_TYPE_MEDIUM_BLOB ||
      sql_type == MYSQL_TYPE_LONG_BLOB)
    return set_compressed_deprecated(thd, method);
  else
    my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name.str);
  return true;
}


uint Field_blob::packed_col_length(const uchar *data_ptr, uint length)
{
  if (length > 255)
    return uint2korr(data_ptr)+2;
  return (uint) *data_ptr + 1;
}


void Field_varstring::mark_unused_memory_as_defined()
{
  uint used_length __attribute__((unused)) = get_length();
  MEM_MAKE_DEFINED(get_data() + used_length, field_length - used_length);
}


  Field_string(uchar *ptr_arg, uint32 len_arg,uchar *null_ptr_arg,
	       uchar null_bit_arg,
	       enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
	       const DTCollation &collation)
    :Field_longstr(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
                   unireg_check_arg, field_name_arg, collation),
     can_alter_field_type(1) {};


bool Field_int::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate)
{
  ASSERT_COLUMN_MARKED_FOR_READ;
  longlong nr= val_int();
  bool neg= !(flags & UNSIGNED_FLAG) && nr < 0;
  return int_to_datetime_with_warn(neg, neg ? -nr : nr, ltime, fuzzydate,
                                   table->s, field_name.str);
}


Field_longstr::cmp_to_string_with_same_collation(const Item_bool_func *cond,
                                                 const Item *item) const
{
  return item->cmp_type() == STRING_RESULT &&
         charset() == cond->compare_collation();
}


void Field::error_generated_column_function_is_not_allowed(THD *thd,
                                                           bool error) const
{
  StringBuffer<64> tmp;
  vcol_info->expr->print(&tmp, (enum_query_type)
                               (QT_TO_SYSTEM_CHARSET |
                                QT_ITEM_IDENT_SKIP_DB_NAMES |
                                QT_ITEM_IDENT_SKIP_TABLE_NAMES));
  my_error(ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED,
           MYF(error ? 0 : ME_JUST_WARNING),
           tmp.c_ptr_safe(), vcol_info->get_vcol_type_name(),
           const_cast<const char*>(field_name.str));
}


void Field_time::store_TIME(const MYSQL_TIME *ltime)
{
  DBUG_ASSERT(ltime->year == 0);
  DBUG_ASSERT(ltime->month == 0);
  long tmp= (ltime->day*24L+ltime->hour)*10000L +
            (ltime->minute*100+ltime->second);
  if (ltime->neg)
    tmp= -tmp;
  int3store(ptr,tmp);
}


String *Field_new_decimal::val_str(String *val_buffer,
                                   String *val_ptr __attribute__((unused)))
{
  ASSERT_COLUMN_MARKED_FOR_READ;
  my_decimal decimal_value;
  uint fixed_precision= zerofill ? precision : 0;
  my_decimal2string(E_DEC_FATAL_ERROR, val_decimal(&decimal_value),
                    fixed_precision, dec, '0', val_buffer);
  val_buffer->set_charset(&my_charset_numeric);
  return val_buffer;
}


  Copy_func *get_copy_func(const Field *from) const
  {
    return do_field_real;
  }


  void create_length_to_internal_length_null()
  {
    DBUG_ASSERT(length == 0);
    key_length= pack_length= 0;
  }


  virtual uint pack_length_from_metadata(uint field_metadata)
  {
    DBUG_ENTER("Field::pack_length_from_metadata");
    DBUG_RETURN(field_metadata);
  }


int Field_string::cmp(const uchar *a_ptr, const uchar *b_ptr)
{
  size_t a_len, b_len;

  if (field_charset->mbmaxlen != 1)
  {
    size_t char_len= field_length/field_charset->mbmaxlen;
    a_len= my_charpos(field_charset, a_ptr, a_ptr + field_length, char_len);
    b_len= my_charpos(field_charset, b_ptr, b_ptr + field_length, char_len);
  }
  else
    a_len= b_len= field_length;
  /*
    We have to remove end space to be able to compare multi-byte-characters
    like in latin_de 'ae' and 0xe4
  */
  return field_charset->coll->strnncollsp(field_charset,
                                          a_ptr, a_len,
                                          b_ptr, b_len);
}


Field *Field::clone(MEM_ROOT *root, TABLE *new_table)
{
  Field *tmp;
  if ((tmp= (Field*) memdup_root(root,(char*) this,size_of())))
  {
    tmp->init(new_table);
    tmp->move_field_offset((my_ptrdiff_t) (new_table->record[0] -
                                           new_table->s->default_values));
  }
  return tmp;
}


bool Field::eq_def(const Field *field) const
{
  if (real_type() != field->real_type() || charset() != field->charset() ||
      pack_length() != field->pack_length())
    return 0;
  return 1;
}


uint32 max_display_length() const { return field_length; }


virtual bool str_needs_quotes() { return TRUE; }


  void set_vcol_type(enum_vcol_info_type v_type)
  {
    vcol_type= v_type;
  }


longlong Field_medium::val_int(void)
{
  ASSERT_COLUMN_MARKED_FOR_READ;
  long j= unsigned_flag ? (long) uint3korr(ptr) : sint3korr(ptr);
  return (longlong) j;
}


  inline void set_null(my_ptrdiff_t row_offset= 0)
    { if (null_ptr) null_ptr[row_offset]|= null_bit; }


my_decimal* Field_int::val_decimal(my_decimal *decimal_value)
{
  ASSERT_COLUMN_MARKED_FOR_READ;
  longlong nr= val_int();
  int2my_decimal(E_DEC_FATAL_ERROR, nr, unsigned_flag, decimal_value);
  return decimal_value;
}


bool Column_definition::fix_attributes_int(uint default_length)
{
  if (length)
    return check_length(ER_TOO_BIG_DISPLAYWIDTH, MAX_FIELD_CHARLENGTH);
  length= default_length;
  return false;
}


Field *Field_enum::make_new_field(MEM_ROOT *root, TABLE *new_table,
                                  bool keep_type)
{
  Field_enum *res= (Field_enum*) Field::make_new_field(root, new_table,
                                                       keep_type);
  if (res)
    res->typelib= copy_typelib(root, typelib);
  return res;
}


    my_bool is_active()
    {
      return (all.ha_list != NULL);
    }


void append_unescaped(String *res, const char *pos, uint length)
{
  const char *end= pos+length;
  res->append('\'');

  for (; pos != end ; pos++)
  {
#if defined(USE_MB) && MYSQL_VERSION_ID < 40100
    uint mblen;
    if (use_mb(default_charset_info) &&
        (mblen= my_ismbchar(default_charset_info, pos, end)))
    {
      res->append(pos, mblen);
      pos+= mblen;
      continue;
    }
#endif

    switch (*pos) {
    case 0:				/* Must be escaped for 'mysql' */
      res->append('\\');
      res->append('0');
      break;
    case '\n':				/* Must be escaped for logs */
      res->append('\\');
      res->append('n');
      break;
    case '\r':
      res->append('\\');		/* This gives better readability */
      res->append('r');
      break;
    case '\\':
      res->append('\\');		/* Because of the sql syntax */
      res->append('\\');
      break;
    case '\'':
      res->append('\'');		/* Because of the sql syntax */
      res->append('\'');
      break;
    default:
      res->append(*pos);
      break;
    }
  }
  res->append('\'');
}


  const char *get_proc_info() const
  { return proc_info; }


  ~Check_level_instant_set()
  {
    m_thd->count_cuted_fields= m_check_level;
  }


  Key(enum Keytype type_par, const LEX_STRING &name_arg,
      KEY_CREATE_INFO *key_info_arg,
      bool generated_arg, List<Key_part_spec> &cols,
      engine_option_value *create_opt, DDL_options_st ddl_options)
    :DDL_options(ddl_options),
     type(type_par), key_create_info(*key_info_arg), columns(cols),
    name(name_arg), option_list(create_opt), generated(generated_arg)
  {}


  inline void set_binlog_format_stmt()
  {
    DBUG_ENTER("set_binlog_format_stmt");
    variables.binlog_format=    BINLOG_FORMAT_STMT;
    current_stmt_binlog_format= BINLOG_FORMAT_STMT;
    DBUG_VOID_RETURN;
  }


  void add_status_to_global()
  {
    DBUG_ASSERT(status_in_global == 0);
    mysql_mutex_lock(&LOCK_status);
    add_to_status(&global_status_var, &status_var);
    /* Mark that this THD status has already been added in global status */
    status_var.global_memory_used= 0;
    status_in_global= 1;
    mysql_mutex_unlock(&LOCK_status);
  }


  void set_thd(THD *thd_arg)
  {
    /*
      Only called for top-level select_results, usually select_send,
      and for the results of subquery engines
      (select_<something>_subselect).
    */
    DBUG_ASSERT(false); /* purecov: inspected */
  }


  void set_bulk_execution(void *bulk)
  {
    bulk_param= bulk;
    m_stmt_da->set_bulk_execution(MY_TEST(bulk));
  }


  select_to_file(THD *thd_arg, sql_exchange *ex):
    select_result_interceptor(thd_arg), exchange(ex), file(-1),row_count(0L)
  { path[0]=0; }


const char *Natural_join_column::db_name()
{
  if (view_field)
    return table_ref->view_db.str;

  /*
    Test that TABLE_LIST::db is the same as TABLE_SHARE::db to
    ensure consistency. An exception are I_S schema tables, which
    are inconsistent in this respect.
  */
  DBUG_ASSERT(!strcmp(table_ref->db,
                      table_ref->table->s->db.str) ||
              (table_ref->schema_table &&
               is_infoschema_db(table_ref->table->s->db.str,
                                table_ref->table->s->db.length)) ||
               table_ref->is_materialized_derived());
  return table_ref->db;
}


TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings)
{
  TYPELIB *result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB));
  if (!result)
    return 0;
  result->count=strings.elements;
  result->name="";
  uint nbytes= (sizeof(char*) + sizeof(uint)) * (result->count + 1);
  if (!(result->type_names= (const char**) alloc_root(mem_root, nbytes)))
    return 0;
  result->type_lengths= (uint*) (result->type_names + result->count + 1);
  List_iterator<String> it(strings);
  String *tmp;
  for (uint i=0; (tmp=it++) ; i++)
  {
    result->type_names[i]= tmp->ptr();
    result->type_lengths[i]= tmp->length();
  }
  result->type_names[result->count]= 0;		// End marker
  result->type_lengths[result->count]= 0;
  return result;
}


  inline ulong wsrep_binlog_format() const
  {
    return WSREP_FORMAT(variables.binlog_format);
  }


  inline void set_time()
  {
    set_start_time();
    start_utime= utime_after_lock= microsecond_interval_timer();
  }


  select_send(THD *thd_arg):
    select_result(thd_arg), is_result_set_started(FALSE) {}


  inline void cleanup(void)
  {
    if (copy_field)				/* Fix for Intel compiler */
    {
      delete [] copy_field;
      copy_field= NULL;
      copy_field_end= NULL;
    }
  }


select_send_analyze(THD *thd_arg): select_send(thd_arg) {}


  select_union_direct(THD *thd_arg, select_result *result_arg,
                      SELECT_LEX *last_select_lex_arg):
  select_union(thd_arg), result(result_arg),
    last_select_lex(last_select_lex_arg),
    done_send_result_set_metadata(false), done_initialize_tables(false),
    limit_found_rows(0)
    { send_records= 0; }


  inline Table_ident(SELECT_LEX_UNIT *s) : sel(s)
  {
    /* We must have a table name here as this is used with add_table_to_list */
    db.str= empty_c_string;                    /* a subject to casedn_str */
    db.length= 0;
    table.str= internal_table_name;
    table.length=1;
  }


  void update_charset(CHARSET_INFO *character_set_client,
                      CHARSET_INFO *collation_connection)
  {
    variables.character_set_client= character_set_client;
    variables.collation_connection= collation_connection;
    update_charset();
  }


int TABLE_LIST::fetch_number_of_rows()
{
  int error= 0;
  if (jtbm_subselect)
  {
    if (jtbm_subselect->is_jtbm_merged)
    {
      table->file->stats.records= (ha_rows)jtbm_subselect->jtbm_record_count;
      set_if_bigger(table->file->stats.records, 2);
      table->used_stat_records= table->file->stats.records;
    }
    return 0;
  }
  if (is_materialized_derived() && !fill_me)

  {
    table->file->stats.records= ((select_union*)derived->result)->records;
    set_if_bigger(table->file->stats.records, 2);
    table->used_stat_records= table->file->stats.records;
  }
  else
    error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
  return error;
}


  Switch_to_definer_security_ctx(THD *thd, TABLE_LIST *table) :
    m_thd(thd), m_sctx(thd->security_ctx)
  {
    if (table->security_ctx)
      thd->security_ctx= table->security_ctx;
  }


  select_singlerow_subselect(THD *thd_arg, Item_subselect *item_arg):
    select_subselect(thd_arg, item_arg)
  {}


int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
{
  DBUG_ENTER("TABLE::update_virtual_fields");
  DBUG_PRINT("enter", ("update_mode: %d", update_mode));
  Field **vfield_ptr, *vf;
  Query_arena backup_arena;
  Turn_errors_to_warnings_handler Suppress_errors;
  int error;
  bool handler_pushed= 0, update_all_columns= 1;
  DBUG_ASSERT(vfield);

  if (h->keyread_enabled())
    DBUG_RETURN(0);

  error= 0;
  in_use->set_n_backup_active_arena(expr_arena, &backup_arena);

  /* When reading or deleting row, ignore errors from virtual columns */
  if (update_mode == VCOL_UPDATE_FOR_READ ||
      update_mode == VCOL_UPDATE_FOR_DELETE ||
      update_mode == VCOL_UPDATE_INDEXED)
  {
    in_use->push_internal_handler(&Suppress_errors);
    handler_pushed= 1;
  }
  else if (update_mode == VCOL_UPDATE_FOR_REPLACE &&
           in_use->is_current_stmt_binlog_format_row() &&
           in_use->variables.binlog_row_image != BINLOG_ROW_IMAGE_MINIMAL)
  {
    /*
      If we are doing a replace with not minimal binary logging, we have to
      calculate all virtual columns.
    */
    update_all_columns= 1;
  }

  /* Iterate over virtual fields in the table */
  for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++)
  {
    vf= (*vfield_ptr);
    Virtual_column_info *vcol_info= vf->vcol_info;
    DBUG_ASSERT(vcol_info);
    DBUG_ASSERT(vcol_info->expr);

    bool update= 0, swap_values= 0;
    switch (update_mode) {
    case VCOL_UPDATE_FOR_READ:
      update= (!vcol_info->stored_in_db &&
               bitmap_is_set(vcol_set, vf->field_index));
      swap_values= 1;
      break;
    case VCOL_UPDATE_FOR_DELETE:
    case VCOL_UPDATE_FOR_WRITE:
      update= bitmap_is_set(vcol_set, vf->field_index);
      break;
    case VCOL_UPDATE_FOR_REPLACE:
      update= ((!vcol_info->stored_in_db &&
                (vf->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG)) &&
                bitmap_is_set(vcol_set, vf->field_index)) ||
               update_all_columns);
      if (update && (vf->flags & BLOB_FLAG))
      {
        /*
          The row has been read into record[1] and Field_blob::value
          contains the value for record[0].  Swap value and read_value
          to ensure that the virtual column data for the read row will
          be in read_value at the end of this function
        */
        ((Field_blob*) vf)->swap_value_and_read_value();
        /* Ensure we call swap_value_and_read_value() after update */
        swap_values= 1;
      }
      break;
    case VCOL_UPDATE_INDEXED:
    case VCOL_UPDATE_INDEXED_FOR_UPDATE:
      /* Read indexed fields that was not updated in VCOL_UPDATE_FOR_READ */
      update= (!vcol_info->stored_in_db &&
               (vf->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG)) &&
               !bitmap_is_set(vcol_set, vf->field_index));
      swap_values= 1;
      break;
    }

    if (update)
    {
      int field_error __attribute__((unused)) = 0;
      /* Compute the actual value of the virtual fields */
      if (vcol_info->expr->save_in_field(vf, 0))
        field_error= error= 1;
      DBUG_PRINT("info", ("field '%s' - updated  error: %d",
                          vf->field_name, field_error));
      if (swap_values && (vf->flags & BLOB_FLAG))
      {
        /*
          Remember the read value to allow other update_virtual_field() calls
          for the same blob field for the row to be updated.
          Field_blob->read_value always contains the virtual column data for
          any read row.
        */
        ((Field_blob*) vf)->swap_value_and_read_value();
      }
    }
    else
    {
      DBUG_PRINT("info", ("field '%s' - skipped", vf->field_name));
    }
  }
  if (handler_pushed)
    in_use->pop_internal_handler();
  in_use->restore_active_arena(expr_arena, &backup_arena);

  /* Return 1 only of we got a fatal error, not a warning */
  DBUG_RETURN(in_use->is_error());
}


View_creation_ctx * View_creation_ctx::create(THD *thd,
                                              TABLE_LIST *view)
{
  View_creation_ctx *ctx= new (thd->mem_root) View_creation_ctx(thd);

  /* Throw a warning if there is NULL cs name. */

  if (!view->view_client_cs_name.str ||
      !view->view_connection_cl_name.str)
  {
    push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
                        ER_VIEW_NO_CREATION_CTX,
                        ER_THD(thd, ER_VIEW_NO_CREATION_CTX),
                        (const char *) view->db,
                        (const char *) view->table_name);

    ctx->m_client_cs= system_charset_info;
    ctx->m_connection_cl= system_charset_info;

    return ctx;
  }

  /* Resolve cs names. Throw a warning if there is unknown cs name. */

  bool invalid_creation_ctx;

  invalid_creation_ctx= resolve_charset(view->view_client_cs_name.str,
                                        system_charset_info,
                                        &ctx->m_client_cs);

  invalid_creation_ctx= resolve_collation(view->view_connection_cl_name.str,
                                          system_charset_info,
                                          &ctx->m_connection_cl) ||
                        invalid_creation_ctx;

  if (invalid_creation_ctx)
  {
    sql_print_warning("View '%s'.'%s': there is unknown charset/collation "
                      "names (client: '%s'; connection: '%s').",
                      (const char *) view->db,
                      (const char *) view->table_name,
                      (const char *) view->view_client_cs_name.str,
                      (const char *) view->view_connection_cl_name.str);

    push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
                        ER_VIEW_INVALID_CREATION_CTX,
                        ER_THD(thd, ER_VIEW_INVALID_CREATION_CTX),
                        (const char *) view->db,
                        (const char *) view->table_name);
  }

  return ctx;
}


  inline bool check_killed()
  {
    if (killed)
      return TRUE;
    if (apc_target.have_apc_requests())
      apc_target.process_apc_requests();
    return FALSE;
  }


void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table)
{
  TABLE_SHARE *share= table->s;
  DBUG_ENTER("update_create_info_from_table");

  create_info->max_rows= share->max_rows;
  create_info->min_rows= share->min_rows;
  create_info->table_options= share->db_create_options;
  create_info->avg_row_length= share->avg_row_length;
  create_info->row_type= share->row_type;
  create_info->key_block_size= share->key_block_size;
  create_info->default_table_charset= share->table_charset;
  create_info->table_charset= 0;
  create_info->comment= share->comment;
  create_info->transactional= share->transactional;
  create_info->page_checksum= share->page_checksum;
  create_info->option_list= share->option_list;

  DBUG_VOID_RETURN;
}


  Key_part_spec *clone(MEM_ROOT *mem_root) const
  { return new (mem_root) Key_part_spec(*this); }


  CSET_STRING(char *str_arg, size_t length_arg, CHARSET_INFO *cs_arg) :
  cs(cs_arg)
  {
    DBUG_ASSERT(cs_arg != NULL);
    string.str= str_arg;
    string.length= length_arg;
  }


Dummy_error_handler() {}                    /* Remove gcc warning */


select_result_interceptor *result_interceptor() { return this; }


inline char *query() const { return query_string.str(); }


LEX_STRING get_invoker_host() { return invoker_host; }


void TABLE::mark_columns_needed_for_update()
{
  DBUG_ENTER("TABLE::mark_columns_needed_for_update");
  bool need_signal= false;

  mark_columns_per_binlog_row_image();

  if (triggers)
    triggers->mark_fields_used(TRG_EVENT_UPDATE);
  if (default_field)
    mark_default_fields_for_write(FALSE);
  if (vfield)
    need_signal|= mark_virtual_columns_for_write(FALSE);
  if (file->ha_table_flags() & HA_REQUIRES_KEY_COLUMNS_FOR_DELETE)
  {
    KEY *end= key_info + s->keys;
    for (KEY *k= key_info; k < end; k++)
    {
      KEY_PART_INFO *kpend= k->key_part + k->ext_key_parts;
      bool any_written= false, all_read= true;
      for (KEY_PART_INFO *kp= k->key_part; kp < kpend; kp++)
      {
        int idx= kp->fieldnr - 1;
        any_written|= bitmap_is_set(write_set, idx);
        all_read&= bitmap_is_set(read_set, idx);
      }
      if (any_written && !all_read)
      {
        for (KEY_PART_INFO *kp= k->key_part; kp < kpend; kp++)
        {
          int idx= kp->fieldnr - 1;
          if (bitmap_fast_test_and_set(read_set, idx))
            continue;
          if (field[idx]->vcol_info)
            mark_virtual_col(field[idx]);
        }
      }
    }
    need_signal= true;
  }
  else
  {
    if (found_next_number_field)
      mark_auto_increment_column();
  }

  if (file->ha_table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_DELETE)
  {
    /*
      If the handler has no cursor capabilites, we have to read either
      the primary key, the hidden primary key or all columns to be
      able to do an update
    */
    if (s->primary_key == MAX_KEY)
      file->use_hidden_primary_key();
    else
    {
      mark_index_columns_for_read(s->primary_key);
      need_signal= true;
    }
  }
  if (check_constraints)
  {
    mark_check_constraint_columns_for_read();
    need_signal= true;
  }

  /*
    If a timestamp field settable on UPDATE is present then to avoid wrong
    update force the table handler to retrieve write-only fields to be able
    to compare records and detect data change.
  */
  if ((file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) &&
      default_field && s->has_update_default_function)
  {
    bitmap_union(read_set, write_set);
    need_signal= true;
  }
  if (need_signal)
    file->column_bitmaps_signal();
  DBUG_VOID_RETURN;
}


  int wait_for_prior_commit()
  {
    if (wait_for_commit_ptr)
      return wait_for_commit_ptr->wait_for_prior_commit(this);
    return 0;
  }


bool TABLE_LIST::prep_where(THD *thd, Item **conds,
                               bool no_where_clause)
{
  DBUG_ENTER("TABLE_LIST::prep_where");
  bool res= FALSE;

  for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local)
  {
    if (tbl->is_view_or_derived() &&
        tbl->prep_where(thd, conds, no_where_clause))
    {
      DBUG_RETURN(TRUE);
    }
  }

  if (where)
  {
    if (where->fixed)
      where->update_used_tables();
    if (!where->fixed && where->fix_fields(thd, &where))
    {
      DBUG_RETURN(TRUE);
    }

    /*
      check that it is not VIEW in which we insert with INSERT SELECT
      (in this case we can't add view WHERE condition to main SELECT_LEX)
    */
    if (!no_where_clause && !where_processed)
    {
      TABLE_LIST *tbl= this;
      Query_arena *arena= thd->stmt_arena, backup;
      arena= thd->activate_stmt_arena_if_needed(&backup);  // For easier test

      /* Go up to join tree and try to find left join */
      for (; tbl; tbl= tbl->embedding)
      {
        if (tbl->outer_join)
        {
          /*
            Store WHERE condition to ON expression for outer join, because
            we can't use WHERE to correctly execute left joins on VIEWs and
            this expression will not be moved to WHERE condition (i.e. will
            be clean correctly for PS/SP)
          */
          tbl->on_expr= and_conds(thd, tbl->on_expr,
                                  where->copy_andor_structure(thd));
          break;
        }
      }
      if (tbl == 0)
      {
        if (*conds && !(*conds)->fixed)
          res= (*conds)->fix_fields(thd, conds);
        if (!res)
          *conds= and_conds(thd, *conds, where->copy_andor_structure(thd));
        if (*conds && !(*conds)->fixed && !res)
          res= (*conds)->fix_fields(thd, conds);
      }
      if (arena)
        thd->restore_active_arena(arena, &backup);
      where_processed= TRUE;
    }
  }

  DBUG_RETURN(res);
}


  inline bool is_strict_mode() const
  {
    return (bool) (variables.sql_mode & (MODE_STRICT_TRANS_TABLES |
                                         MODE_STRICT_ALL_TABLES));
  }


  select_union(THD *thd_arg):
    select_result_interceptor(thd_arg), write_err(0), table(0), records(0)
  { tmp_table_param.init(); }


  inline void change_db(char *db_name)
  {
    db.str= db_name; db.length= (uint) strlen(db_name);
  }


  select_materialize_with_stats(THD *thd_arg): select_union(thd_arg)
  { tmp_table_param.init(); }


  const Diagnostics_area *get_stmt_da() const
  { return m_stmt_da; }


inline uint tmp_table_max_key_parts() { return maria_max_key_segments(); }


CHARSET_INFO *query_charset() const { return query_string.charset(); }


  inline void fatal_error()
  {
    DBUG_ASSERT(get_stmt_da()->is_error() || killed);
    is_fatal_error= 1;
    DBUG_PRINT("error",("Fatal error set"));
  }


TABLE_LIST *locked_tables() { return m_locked_tables; }


enum need_invoker need_binlog_invoker() { return m_binlog_invoker; }


  Query_arena(MEM_ROOT *mem_root_arg, enum enum_state state_arg) :
    free_list(0), mem_root(mem_root_arg), state(state_arg)
  { INIT_ARENA_DBUG_INFO; }


static bool fix_vcol_expr(THD *thd, Virtual_column_info *vcol)
{
  DBUG_ENTER("fix_vcol_expr");

  const enum enum_mark_columns save_mark_used_columns= thd->mark_used_columns;
  thd->mark_used_columns= MARK_COLUMNS_NONE;

  int error= vcol->expr->fix_fields(thd, &vcol->expr);

  thd->mark_used_columns= save_mark_used_columns;

  if (unlikely(error))
  {
    StringBuffer<MAX_FIELD_WIDTH> str;
    vcol->print(&str);
    my_error(ER_ERROR_EVALUATING_EXPRESSION, MYF(0), str.c_ptr_safe());
    DBUG_RETURN(1);
  }

  DBUG_RETURN(0);
}


  inline void reset_kill_query()
  {
    if (killed < KILL_CONNECTION)
    {
      reset_killed();
      mysys_var->abort= 0;
    }
  }


Item *Natural_join_column::create_item(THD *thd)
{
  if (view_field)
  {
    DBUG_ASSERT(table_field == NULL);
    return create_view_field(thd, table_ref, &view_field->item,
                             view_field->name);
  }
  return table_field;
}


  inline void get_binlog_format(enum_binlog_format *format,
                                enum_binlog_format *current_format)
  {
    *format= (enum_binlog_format) variables.binlog_format;
    *current_format= current_stmt_binlog_format;
  }


  inline uint tmpkeyval(TMP_TABLE_SHARE *share)
  {
    return uint4korr(share->table_cache_key.str +
                     share->table_cache_key.length - 4);
  }


bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
                     bool *error_reported, vcol_init_mode mode)
{
  CHARSET_INFO *save_character_set_client= thd->variables.character_set_client;
  CHARSET_INFO *save_collation= thd->variables.collation_connection;
  Query_arena  *backup_stmt_arena_ptr= thd->stmt_arena;
  const uchar *pos= table->s->vcol_defs.str;
  const uchar *end= pos + table->s->vcol_defs.length;
  Field **field_ptr= table->field - 1;
  Field **vfield_ptr= table->vfield;
  Field **dfield_ptr= table->default_field;
  Virtual_column_info **check_constraint_ptr= table->check_constraints;
  sql_mode_t saved_mode= thd->variables.sql_mode;
  Query_arena backup_arena;
  Virtual_column_info *vcol= 0;
  StringBuffer<MAX_FIELD_WIDTH> expr_str;
  bool res= 1;
  DBUG_ENTER("parse_vcol_defs");

  if (check_constraint_ptr)
    memcpy(table->check_constraints + table->s->field_check_constraints,
           table->s->check_constraints,
           table->s->table_check_constraints * sizeof(Virtual_column_info*));

  DBUG_ASSERT(table->expr_arena == NULL);
  /*
    We need to use CONVENTIONAL_EXECUTION here to ensure that
    any new items created by fix_fields() are not reverted.
  */
  table->expr_arena= new (alloc_root(mem_root, sizeof(Query_arena)))
                        Query_arena(mem_root,
                                    Query_arena::STMT_CONVENTIONAL_EXECUTION);
  if (!table->expr_arena)
    DBUG_RETURN(1);

  thd->set_n_backup_active_arena(table->expr_arena, &backup_arena);
  thd->stmt_arena= table->expr_arena;
  thd->update_charset(&my_charset_utf8mb4_general_ci, table->s->table_charset);
  expr_str.append(&parse_vcol_keyword);
  thd->variables.sql_mode &= ~MODE_NO_BACKSLASH_ESCAPES;

  while (pos < end)
  {
    uint type, expr_length;
    if (table->s->frm_version >= FRM_VER_EXPRESSSIONS)
    {
      uint field_nr, name_length;
      /* see pack_expression() for how data is stored */
      type= pos[0];
      field_nr= uint2korr(pos+1);
      expr_length= uint2korr(pos+3);
      name_length= pos[5];
      pos+= FRM_VCOL_NEW_HEADER_SIZE + name_length;
      field_ptr= table->field + field_nr;
    }
    else
    {
      /*
        see below in ::init_from_binary_frm_image for how data is stored
        in versions below 10.2 (that includes 5.7 too)
      */
      while (*++field_ptr && !(*field_ptr)->vcol_info) /* no-op */;
      if (!*field_ptr)
      {
        open_table_error(table->s, OPEN_FRM_CORRUPTED, 1);
        goto end;
      }
      type= (*field_ptr)->vcol_info->stored_in_db
            ? VCOL_GENERATED_STORED : VCOL_GENERATED_VIRTUAL;
      expr_length= uint2korr(pos+1);
      if (table->s->mysql_version > 50700 && table->s->mysql_version < 100000)
        pos+= 4;                        // MySQL from 5.7
      else
        pos+= pos[0] == 2 ? 4 : 3;      // MariaDB from 5.2 to 10.1
    }

    expr_str.length(parse_vcol_keyword.length);
    expr_str.append((char*)pos, expr_length);
    thd->where= vcol_type_name(static_cast<enum_vcol_info_type>(type));

    switch (type) {
    case VCOL_GENERATED_VIRTUAL:
    case VCOL_GENERATED_STORED:
      vcol= unpack_vcol_info_from_frm(thd, mem_root, table, &expr_str,
                                    &((*field_ptr)->vcol_info), error_reported);
      *(vfield_ptr++)= *field_ptr;
      if (vcol && field_ptr[0]->check_vcol_sql_mode_dependency(thd, mode))
      {
        DBUG_ASSERT(thd->is_error());
        *error_reported= true;
        goto end;
      }
      break;
    case VCOL_DEFAULT:
      vcol= unpack_vcol_info_from_frm(thd, mem_root, table, &expr_str,
                                      &((*field_ptr)->default_value),
                                      error_reported);
      *(dfield_ptr++)= *field_ptr;
      if (vcol && (vcol->flags & (VCOL_NON_DETERMINISTIC | VCOL_SESSION_FUNC)))
        table->s->non_determinstic_insert= true;
      break;
    case VCOL_CHECK_FIELD:
      vcol= unpack_vcol_info_from_frm(thd, mem_root, table, &expr_str,
                                      &((*field_ptr)->check_constraint),
                                      error_reported);
      *check_constraint_ptr++= (*field_ptr)->check_constraint;
      break;
    case VCOL_CHECK_TABLE:
      vcol= unpack_vcol_info_from_frm(thd, mem_root, table, &expr_str,
                                      check_constraint_ptr, error_reported);
      check_constraint_ptr++;
      break;
    }
    if (!vcol)
      goto end;
    pos+= expr_length;
  }

  /* Now, initialize CURRENT_TIMESTAMP fields */
  for (field_ptr= table->field; *field_ptr; field_ptr++)
  {
    Field *field= *field_ptr;
    if (field->has_default_now_unireg_check())
    {
      expr_str.length(parse_vcol_keyword.length);
      expr_str.append(STRING_WITH_LEN("current_timestamp("));
      expr_str.append_ulonglong(field->decimals());
      expr_str.append(')');
      vcol= unpack_vcol_info_from_frm(thd, mem_root, table, &expr_str,
                                      &((*field_ptr)->default_value),
                                      error_reported);
      *(dfield_ptr++)= *field_ptr;
      if (!field->default_value->expr)
        goto end;
    }
    else if (field->has_update_default_function() && !field->default_value)
      *(dfield_ptr++)= *field_ptr;
  }

  if (vfield_ptr)
    *vfield_ptr= 0;

  if (dfield_ptr)
    *dfield_ptr= 0;

  if (check_constraint_ptr)
    *check_constraint_ptr= 0;

  /* Check that expressions aren't referring to not yet initialized fields */
  for (field_ptr= table->field; *field_ptr; field_ptr++)
  {
    Field *field= *field_ptr;
    if (check_vcol_forward_refs(field, field->vcol_info) ||
        check_vcol_forward_refs(field, field->check_constraint) ||
        check_vcol_forward_refs(field, field->default_value))
    {
      *error_reported= true;
      goto end;
    }
  }

  res=0;
end:
  thd->restore_active_arena(table->expr_arena, &backup_arena);
  thd->stmt_arena= backup_stmt_arena_ptr;
  if (save_character_set_client)
    thd->update_charset(save_character_set_client, save_collation);
  thd->variables.sql_mode= saved_mode;
  DBUG_RETURN(res);
}


  ha_rows get_min_null_of_col(uint idx)
  {
    DBUG_ASSERT(idx < table->s->fields);
    return col_stat[idx].min_null_row;
  }


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


bool Item_singlerow_subselect::fix_length_and_dec()
{
  if ((max_columns= engine->cols()) == 1)
  {
    if (engine->fix_length_and_dec(row= &value))
      return TRUE;
  }
  else
  {
    if (!(row= (Item_cache**) current_thd->alloc(sizeof(Item_cache*) *
                                                 max_columns)) ||
        engine->fix_length_and_dec(row))
      return TRUE;
    value= *row;
  }
  unsigned_flag= value->unsigned_flag;
  /*
    If the subquery has no tables (1) and is not a UNION (2), like:

      (SELECT subq_value)

    then its NULLability is the same as subq_value's NULLability.

    (1): A subquery that uses a table will return NULL when the table is empty.
    (2): A UNION subquery will return NULL if it produces a "Subquery returns
         more than one row" error.
  */
  if (engine->no_tables() &&
      engine->engine_type() != subselect_engine::UNION_ENGINE)
    maybe_null= engine->may_be_null();
  else
  {
    for (uint i= 0; i < max_columns; i++)
      row[i]->maybe_null= TRUE;
  }
  return FALSE;
}


Item_subselect::select_transformer(JOIN *join)
{
  DBUG_ENTER("Item_subselect::select_transformer");
  DBUG_ASSERT(thd == join->thd);
  DBUG_RETURN(false);
}


void subselect_engine::set_thd(THD *thd_arg)
{
  thd= thd_arg;
  if (result)
    result->set_thd(thd_arg);
}


void subselect_single_select_engine::print(String *str,
                                           enum_query_type query_type)
{
  With_clause* with_clause= select_lex->get_with_clause();
  if (with_clause)
    with_clause->print(str, query_type);
  select_lex->print(get_thd(), str, query_type);
}


bool subselect_single_select_engine::fix_length_and_dec(Item_cache **row)
{
  DBUG_ASSERT(row || select_lex->item_list.elements==1);
  if (set_row(select_lex->item_list, row))
    return TRUE;
  item->collation.set(row[0]->collation);
  if (cols() != 1)
    maybe_null= 0;
  return FALSE;
}


uint Item_singlerow_subselect::cols()
{
  return engine->cols();
}


static bool find_inner_outer_equalities(Item **conds,
                                        Dynamic_array<EQ_FIELD_OUTER> &result)
{
  bool found=  FALSE;
  EQ_FIELD_OUTER element;
  if (is_cond_and(*conds))
  {
    List_iterator<Item> li(*((Item_cond*)*conds)->argument_list());
    Item *item;
    bool allow_subselect= true;
    while ((item= li++))
    {
      if (item->type() == Item::FUNC_ITEM &&
          check_equality_for_exist2in((Item_func *)item,
                                      allow_subselect,
                                      &element.local_field,
                                      &element.outer_exp))
      {
        found= TRUE;
        allow_subselect= false;
        element.eq_ref= li.ref();
        if (result.append(element))
          goto alloc_err;
      }
    }
  }
  else if ((*conds)->type() == Item::FUNC_ITEM &&
           check_equality_for_exist2in((Item_func *)*conds,
                                       true,
                                       &element.local_field,
                                       &element.outer_exp))
  {
    found= TRUE;
    element.eq_ref= conds;
    if (result.append(element))
      goto alloc_err;
  }

  return !found;
alloc_err:
  return TRUE;
}


my_decimal *Item_in_subselect::val_decimal(my_decimal *decimal_value)
{
  /*
    As far as Item_in_subselect called only from Item_in_optimizer this
    method should not be used
  */
  DBUG_ASSERT(0);
  if (forced_const)
    goto value_is_ready;
  DBUG_ASSERT((engine->uncacheable() & ~UNCACHEABLE_EXPLAIN) ||
              ! engine->is_executed());
  null_value= was_null= FALSE;
  DBUG_ASSERT(fixed == 1);
  if (exec())
  {
    reset();
    return 0;
  }
  if (was_null && !value)
    null_value= TRUE;
value_is_ready:
  int2my_decimal(E_DEC_FATAL_ERROR, value, 0, decimal_value);
  return decimal_value;
}


double Item_singlerow_subselect::val_real()
{
  DBUG_ASSERT(fixed == 1);
  if (forced_const)
    return value->val_real();
  if (!exec() && !value->null_value)
  {
    null_value= FALSE;
    return value->val_real();
  }
  else
  {
    reset();
    return 0;
  }
}


Item* Item_exists_subselect::expr_cache_insert_transformer(THD *tmp_thd,
                                                           uchar *unused)
{
  DBUG_ENTER("Item_exists_subselect::expr_cache_insert_transformer");
  DBUG_ASSERT(thd == tmp_thd);

  if (expr_cache)
    DBUG_RETURN(expr_cache);

  if (substype() == EXISTS_SUBS && expr_cache_is_needed(tmp_thd) &&
      (expr_cache= set_expr_cache(tmp_thd)))
  {
    init_expr_cache_tracker(tmp_thd);
    DBUG_RETURN(expr_cache);
  }
  DBUG_RETURN(this);
}


void subselect_union_engine::force_reexecution()
{
  unit->executed= false;
}


double get_fanout_with_deps(JOIN *join, table_map tset)
{
  /* Handle the case of "Impossible WHERE" */
  if (join->table_count == 0)
    return 0.0;

  /* First, recursively get all tables we depend on */
  table_map deps_to_check= tset;
  table_map checked_deps= 0;
  table_map further_deps;
  do
  {
    further_deps= 0;
    Table_map_iterator tm_it(deps_to_check);
    int tableno;
    while ((tableno = tm_it.next_bit()) != Table_map_iterator::BITMAP_END)
    {
      /* get tableno's dependency tables that are not in needed_set */
      further_deps |= join->map2table[tableno]->ref.depend_map & ~checked_deps;
    }

    checked_deps |= deps_to_check;
    deps_to_check= further_deps;
  } while (further_deps != 0);

  /* Now, walk the join order and calculate the fanout */
  double fanout= 1;
  for (JOIN_TAB *tab= first_top_level_tab(join, WITHOUT_CONST_TABLES); tab;
       tab= next_top_level_tab(join, tab))
  {
    /*
      Ignore SJM nests. They have tab->table==NULL. There is no point to walk
      inside them, because GROUP BY clause cannot refer to tables from within
      subquery.
    */
    if (!tab->is_sjm_nest() && (tab->table->map & checked_deps) &&
        !tab->emb_sj_nest &&
        tab->records_read != 0)
    {
      fanout *= tab->records_read;
    }
  }
  return fanout;
}


Item_subselect::get_select_lex()
{
  return unit->first_select();
}


bool Item_in_subselect::fix_having(Item *having, SELECT_LEX *select_lex)
{
  bool fix_res= 0;
  DBUG_ASSERT(thd);
  if (!having->fixed)
  {
    select_lex->having_fix_field= 1;
    fix_res= having->fix_fields(thd, 0);
    select_lex->having_fix_field= 0;
  }
  return fix_res;
}


bool Item_subselect::mark_as_dependent(THD *thd, st_select_lex *select,
                                       Item *item)
{
  if (inside_first_fix_fields)
  {
    is_correlated= TRUE;
    Ref_to_outside *upper;
    if (!(upper= new (thd->stmt_arena->mem_root) Ref_to_outside()))
      return TRUE;
    upper->select= select;
    upper->item= item;
    if (upper_refs.push_back(upper, thd->stmt_arena->mem_root))
      return TRUE;
  }
  return FALSE;
}


bool Item_exists_subselect::exists2in_processor(void *opt_arg)
{
  THD *thd= (THD *)opt_arg;
  SELECT_LEX *first_select=unit->first_select(), *save_select;
  JOIN *join= first_select->join;
  Item **eq_ref= NULL;
  Item_ident *local_field= NULL;
  Item *outer_exp= NULL;
  Item *left_exp= NULL; Item_in_subselect *in_subs;
  Query_arena *arena= NULL, backup;
  int res= FALSE;
  List<Item> outer;
  Dynamic_array<EQ_FIELD_OUTER> eqs(5, 5);
  bool will_be_correlated;
  DBUG_ENTER("Item_exists_subselect::exists2in_processor");

  if (!optimizer ||
      !optimizer_flag(thd, OPTIMIZER_SWITCH_EXISTS_TO_IN) ||
      (!is_top_level_item() && (!upper_not ||
                                !upper_not->is_top_level_item())) ||
      first_select->is_part_of_union() ||
      first_select->group_list.elements ||
      first_select->order_list.elements ||
      join->having ||
      first_select->with_sum_func ||
      !first_select->leaf_tables.elements||
      !join->conds ||
      with_recursive_reference)
    DBUG_RETURN(FALSE);

  DBUG_ASSERT(first_select->order_list.elements == 0 &&
              first_select->group_list.elements == 0 &&
              first_select->having == NULL);

  if (find_inner_outer_equalities(&join->conds, eqs))
    DBUG_RETURN(FALSE);

  DBUG_ASSERT(eqs.elements() != 0);

  save_select= thd->lex->current_select;
  thd->lex->current_select= first_select;

  /* check that the subquery has only dependencies we are going pull out */
  {
    List<Item> unused;
    Collect_deps_prm prm= {&unused,          // parameters
      unit->first_select()->nest_level_base, // nest_level_base
      0,                                     // count
      unit->first_select()->nest_level,      // nest_level
      FALSE                                  // collect
    };
    walk(&Item::collect_outer_ref_processor, TRUE, &prm);
    DBUG_ASSERT(prm.count > 0);
    DBUG_ASSERT(prm.count >= (uint)eqs.elements());
    will_be_correlated= prm.count > (uint)eqs.elements();
    if (upper_not && will_be_correlated)
      goto out;
  }

  if ((uint)eqs.elements() > (first_select->item_list.elements +
                              first_select->select_n_reserved))
    goto out;
  /* It is simple query */
  DBUG_ASSERT(first_select->join->all_fields.elements ==
              first_select->item_list.elements);

  arena= thd->activate_stmt_arena_if_needed(&backup);

  while (first_select->item_list.elements > (uint)eqs.elements())
  {
    first_select->item_list.pop();
    first_select->join->all_fields.elements--;
  }
  {
    List_iterator<Item> it(first_select->item_list);

    for (uint i= 0; i < (uint)eqs.elements(); i++)
    {
      Item *item= it++;
      eq_ref= eqs.at(i).eq_ref;
      local_field= eqs.at(i).local_field;
      outer_exp= eqs.at(i).outer_exp;
      /* Add the field to the SELECT_LIST */
      if (item)
        it.replace(local_field);
      else
      {
        first_select->item_list.push_back(local_field, thd->mem_root);
        first_select->join->all_fields.elements++;
      }
      first_select->ref_pointer_array[i]= (Item *)local_field;

      /* remove the parts from condition */
      if (!upper_not || !local_field->maybe_null)
        *eq_ref= new (thd->mem_root) Item_int(thd, 1);
      else
      {
        *eq_ref= new (thd->mem_root)
          Item_func_isnotnull(thd,
                              new (thd->mem_root)
                              Item_field(thd,
                                         ((Item_field*)(local_field->
                                                        real_item()))->context,
                                         ((Item_field*)(local_field->
                                                        real_item()))->field));
        if((*eq_ref)->fix_fields(thd, (Item **)eq_ref))
        {
          res= TRUE;
          goto out;
        }
      }
      outer_exp->fix_after_pullout(unit->outer_select(), &outer_exp, FALSE);
      outer_exp->update_used_tables();
      outer.push_back(outer_exp, thd->mem_root);
    }
  }

  join->conds->update_used_tables();

  /* make IN SUBQUERY and put outer_exp as left part */
  if (eqs.elements() == 1)
    left_exp= outer_exp;
  else
  {
    if (!(left_exp= new (thd->mem_root) Item_row(thd, outer)))
    {
      res= TRUE;
      goto out;
    }
  }

  /* make EXISTS->IN permanet (see Item_subselect::init()) */
  set_exists_transformed();

  first_select->select_limit= NULL;
  if (!(in_subs= new (thd->mem_root) Item_in_subselect(thd, left_exp,
                                                         first_select)))
  {
    res= TRUE;
    goto out;
  }
  in_subs->set_exists_transformed();
  optimizer->arguments()[0]= left_exp;
  optimizer->arguments()[1]= in_subs;
  in_subs->optimizer= optimizer;
  DBUG_ASSERT(is_top_level_item() ||
              (upper_not && upper_not->is_top_level_item()));
  in_subs->top_level_item();
  {
    SELECT_LEX *current= thd->lex->current_select;
    optimizer->reset_cache(); // renew cache, and we will not keep it
    thd->lex->current_select= unit->outer_select();
    DBUG_ASSERT(optimizer);
    if (optimizer->fix_left(thd))
    {
      res= TRUE;
      /*
        We should not restore thd->lex->current_select because it will be
        reset on exit from this procedure
      */
      goto out;
    }
    /*
      As far as  Item_ref_in_optimizer do not substitute itself on fix_fields
      we can use same item for all selects.
    */
    in_subs->expr= new (thd->mem_root)
      Item_direct_ref(thd, &first_select->context,
                      (Item**)optimizer->get_cache(),
                      (char *)"<no matter>",
                      (char *)in_left_expr_name);
    if (in_subs->fix_fields(thd, optimizer->arguments() + 1))
    {
      res= TRUE;
      /*
        We should not restore thd->lex->current_select because it will be
        reset on exit from this procedure
      */
      goto out;
    }
    {
      /* Move dependence list */
      List_iterator_fast<Ref_to_outside> it(upper_refs);
      Ref_to_outside *upper;
      while ((upper= it++))
      {
        uint i;
        for (i= 0; i < (uint)eqs.elements(); i++)
          if (eqs.at(i).outer_exp->
              walk(&Item::find_item_processor, TRUE, upper->item))
            break;
        if (i == (uint)eqs.elements() &&
            (in_subs->upper_refs.push_back(upper, thd->stmt_arena->mem_root)))
          goto out;
      }
    }
    in_subs->update_used_tables();
    /*
      The engine of the subquery is fixed so above fix_fields() is not
      complete and should be fixed
    */
    in_subs->upper_refs= upper_refs;
    upper_refs.empty();
    thd->lex->current_select= current;
  }

  DBUG_ASSERT(unit->item == in_subs);
  DBUG_ASSERT(join == first_select->join);
  /*
    Fix dependency info
  */
  in_subs->is_correlated= will_be_correlated;
  if (!will_be_correlated)
  {
    first_select->uncacheable&= ~UNCACHEABLE_DEPENDENT_GENERATED;
    unit->uncacheable&= ~UNCACHEABLE_DEPENDENT_GENERATED;
  }
  /*
    set possible optimization strategies
  */
  in_subs->emb_on_expr_nest= emb_on_expr_nest;
  res= check_and_do_in_subquery_rewrites(join);
  first_select->join->prepare_stage2();

  first_select->fix_prepare_information(thd, &join->conds, &join->having);

  if (upper_not)
  {
    Item *exp;
    if (eqs.elements() == 1)
    {
      exp= (optimizer->arguments()[0]->maybe_null ?
            (Item*) new (thd->mem_root)
            Item_cond_and(thd,
                          new (thd->mem_root)
                          Item_func_isnotnull(thd,
                                              new (thd->mem_root)
                                              Item_direct_ref(thd,
                                                              &unit->outer_select()->context,
                                                              optimizer->arguments(),
                                                              (char *)"<no matter>",
                                                              (char *)exists_outer_expr_name)),
                          optimizer) :
            (Item *)optimizer);
    }
    else
    {
      List<Item> *and_list= new List<Item>;
      if (!and_list)
      {
        res= TRUE;
        goto out;
      }
      for (size_t i= 0; i < eqs.elements(); i++)
      {
        if (optimizer->arguments()[0]->maybe_null)
        {
          and_list->
            push_front(new (thd->mem_root)
                       Item_func_isnotnull(thd,
                                           new (thd->mem_root)
                                           Item_direct_ref(thd,
                                                           &unit->outer_select()->context,
                                                           optimizer->arguments()[0]->addr(i),
                                                           (char *)"<no matter>",
                                                           (char *)exists_outer_expr_name)),
                       thd->mem_root);
        }
      }
      if (and_list->elements > 0)
      {
        and_list->push_front(optimizer, thd->mem_root);
        exp= new (thd->mem_root) Item_cond_and(thd, *and_list);
      }
      else
        exp= optimizer;
    }
    upper_not->arguments()[0]= exp;
    if (!exp->fixed && exp->fix_fields(thd, upper_not->arguments()))
    {
      res= TRUE;
      goto out;
    }
  }

out:
  thd->lex->current_select= save_select;
  if (arena)
    thd->restore_active_arena(arena, &backup);
  DBUG_RETURN(res);
}


void Item_exists_subselect::init_length_and_dec()
{
  decimals= 0;
  max_length= 1;
  max_columns= engine->cols();
}


Item_exists_subselect::Item_exists_subselect(THD *thd,
                                             st_select_lex *select_lex):
  Item_subselect(thd), upper_not(NULL), abort_on_null(0),
  emb_on_expr_nest(NULL), optimizer(0), exists_transformed(0)
{
  DBUG_ENTER("Item_exists_subselect::Item_exists_subselect");
  init(select_lex, new (thd->mem_root) select_exists_subselect(thd, this));
  max_columns= UINT_MAX;
  null_value= FALSE; //can't be NULL
  maybe_null= 0; //can't be NULL
  value= 0;
  DBUG_VOID_RETURN;
}


Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
                                             chooser_compare_func_creator fc,
					     st_select_lex *select_lex,
					     bool all_arg):
  Item_in_subselect(thd), func_creator(fc), all(all_arg)
{
  DBUG_ENTER("Item_allany_subselect::Item_allany_subselect");
  left_expr_orig= left_expr= left_exp;
  /* prepare to possible disassembling the item in convert_subq_to_sj() */
  if (left_exp->type() == Item::ROW_ITEM)
    left_expr_orig= new (thd->mem_root)
      Item_row(thd, static_cast<Item_row*>(left_exp));
  func= func_creator(all_arg);
  init(select_lex, new (thd->mem_root) select_exists_subselect(thd, this));
  max_columns= 1;
  abort_on_null= 0;
  reset();
  //if test_limit will fail then error will be reported to client
  test_limit(select_lex->master_unit());
  DBUG_VOID_RETURN;
}


void Item_maxmin_subselect::print(String *str, enum_query_type query_type)
{
  str->append(max?"<max>":"<min>", 5);
  Item_singlerow_subselect::print(str, query_type);
}


bool subselect_hash_sj_engine::no_tables()
{
  DBUG_ASSERT(FALSE);
  return FALSE;
}


bool subselect_union_engine::is_executed() const
{
  return unit->executed;
}


longlong Item_in_subselect::val_int()
{
  /*
    As far as Item_in_subselect called only from Item_in_optimizer this
    method should not be used
  */
  DBUG_ASSERT(0);
  DBUG_ASSERT(fixed == 1);
  if (forced_const)
    return value;
  DBUG_ASSERT((engine->uncacheable() & ~UNCACHEABLE_EXPLAIN) ||
              ! engine->is_executed());
  null_value= was_null= FALSE;
  if (exec())
  {
    reset();
    return 0;
  }
  if (was_null && !value)
    null_value= TRUE;
  return value;
}


void Item_allany_subselect::cleanup()
{
  /*
    The MAX/MIN transformation through injection is reverted through the
    change_item_tree() mechanism. Revert the select_lex object of the
    query to its initial state.
  */
  for (SELECT_LEX *sl= unit->first_select();
       sl; sl= sl->next_select())
    if (test_set_strategy(SUBS_MAXMIN_INJECTED))
      sl->with_sum_func= false;
  Item_in_subselect::cleanup();
}


bool subselect_engine::set_row(List<Item> &item_list, Item_cache **row)
{
  Item *sel_item;
  List_iterator_fast<Item> li(item_list);
  cmp_type= res_type= STRING_RESULT;
  res_field_type= MYSQL_TYPE_VAR_STRING;
  for (uint i= 0; (sel_item= li++); i++)
  {
    item->max_length= sel_item->max_length;
    res_type= sel_item->result_type();
    cmp_type= sel_item->cmp_type();
    res_field_type= sel_item->field_type();
    item->decimals= sel_item->decimals;
    item->unsigned_flag= sel_item->unsigned_flag;
    maybe_null= sel_item->maybe_null;
    if (!(row[i]= Item_cache::get_cache(thd, sel_item, sel_item->cmp_type())))
      return TRUE;
    row[i]->setup(thd, sel_item);
 //psergey-backport-timours:   row[i]->store(sel_item);
  }
  if (item_list.elements > 1)
    cmp_type= res_type= ROW_RESULT;
  return FALSE;
}


void subselect_hash_sj_engine::exclude()
{
  DBUG_ASSERT(FALSE);
}


void Item_subselect::init(st_select_lex *select_lex,
			  select_result_interceptor *result)
{
  /*
    Please see Item_singlerow_subselect::invalidate_and_restore_select_lex(),
    which depends on alterations to the parse tree implemented here.
  */

  DBUG_ENTER("Item_subselect::init");
  DBUG_PRINT("enter", ("select_lex: %p  this: %p",
                       select_lex, this));
  unit= select_lex->master_unit();

  if (unit->item)
  {
    engine= unit->item->engine;
    parsing_place= unit->item->parsing_place;
    if (unit->item->substype() == EXISTS_SUBS &&
        ((Item_exists_subselect *)unit->item)->exists_transformed)
    {
      /* it is permanent transformation of EXISTS to IN */
      unit->item= this;
      engine->change_result(this, result, FALSE);
    }
    else
    {
      /*
        Item can be changed in JOIN::prepare while engine in JOIN::optimize
        => we do not copy old_engine here
      */
      unit->thd->change_item_tree((Item**)&unit->item, this);
      engine->change_result(this, result, TRUE);
    }
  }
  else
  {
    SELECT_LEX *outer_select= unit->outer_select();
    /*
      do not take into account expression inside aggregate functions because
      they can access original table fields
    */
    parsing_place= (outer_select->in_sum_expr ? NO_MATTER
                                              : outer_select->parsing_place);
    if (unit->is_union())
      engine= new subselect_union_engine(unit, result, this);
    else
      engine= new subselect_single_select_engine(select_lex, result, this);
  }
  {
    SELECT_LEX *upper= unit->outer_select();
    if (upper->parsing_place == IN_HAVING)
      upper->subquery_in_having= 1;
    /* The subquery is an expression cache candidate */
    upper->expr_cache_may_be_used[upper->parsing_place]= TRUE;
  }
  DBUG_PRINT("info", ("engine: %p", engine));
  DBUG_VOID_RETURN;
}


bool Ordered_key::lookup()
{
  DBUG_ASSERT(key_buff_elements);

  ha_rows lo= 0;
  ha_rows hi= key_buff_elements - 1;
  ha_rows mid;
  int cmp_res;

  while (lo <= hi)
  {
    mid= lo + (hi - lo) / 2;
    cmp_res= cmp_key_with_search_key(key_buff[mid]);
    /*
      In order to find the minimum match, check if the pevious element is
      equal or smaller than the found one. If equal, we need to search further
      to the left.
    */
    if (!cmp_res && mid > 0)
      cmp_res= !cmp_key_with_search_key(key_buff[mid - 1]) ? 1 : 0;

    if (cmp_res == -1)
    {
      /* row[mid] < search_key */
      lo= mid + 1;
    }
    else if (cmp_res == 1)
    {
      /* row[mid] > search_key */
      if (!mid)
        goto not_found;
      hi= mid - 1;
    }
    else
    {
      /* row[mid] == search_key */
      cur_key_idx= mid;
      return TRUE;
    }
  }
not_found:
  cur_key_idx= HA_POS_ERROR;
  return FALSE;
}


bool subselect_single_select_engine::no_tables()
{
  return(select_lex->table_list.elements == 0);
}


Item *Item_field::derived_grouping_field_transformer_for_where(THD *thd,
                                                               uchar *arg)
{
  st_select_lex *sel= (st_select_lex *)arg;
  Grouping_tmp_field *gr_field= find_matching_grouping_field(this, sel);
  if (gr_field)
  {
    Item *producing_clone=
            gr_field->producing_item->build_clone(thd, thd->mem_root);
    if (producing_clone)
      producing_clone->marker|= SUBSTITUTION_FL;
    return producing_clone;
  }
  return this;
}


bool Item_cache_row::setup(THD *thd, Item *item)
{
  example= item;
  null_value= true;

  if (!values && allocate(thd, item->cols()))
    return 1;
  for (uint i= 0; i < item_count; i++)
  {
    Item *el= item->element_index(i);
    Item_cache *tmp;
    if (!(tmp= values[i]= Item_cache::get_cache(thd, el)))
      return 1;
    tmp->setup(thd, el);
  }
  return 0;
}


Field *Item_type_holder::make_field_by_type(TABLE *table)
{
  /*
    The field functions defines a field to be not null if null_ptr is not 0
  */
  uchar *null_ptr= maybe_null ? (uchar*) "" : 0;
  Field *field;

  switch (Item_type_holder::real_field_type()) {
  case MYSQL_TYPE_ENUM:
    DBUG_ASSERT(enum_set_typelib);
    field= new Field_enum((uchar *) 0, max_length, null_ptr, 0,
                          Field::NONE, name,
                          get_enum_pack_length(enum_set_typelib->count),
                          enum_set_typelib, collation.collation);
    if (field)
      field->init(table);
    return field;
  case MYSQL_TYPE_SET:
    DBUG_ASSERT(enum_set_typelib);
    field= new Field_set((uchar *) 0, max_length, null_ptr, 0,
                         Field::NONE, name,
                         get_set_pack_length(enum_set_typelib->count),
                         enum_set_typelib, collation.collation);
    if (field)
      field->init(table);
    return field;
  case MYSQL_TYPE_NULL:
    return make_string_field(table);
  default:
    break;
  }
  return tmp_table_field_from_field_type(table, false, true);
}


Item_param::set_param_type_and_swap_value(Item_param *src)
{
  Type_std_attributes::set(src);
  set_handler(src->type_handler());
  set_param_func= src->set_param_func;
  item_type= src->item_type;

  maybe_null= src->maybe_null;
  null_value= src->null_value;
  state= src->state;
  fixed= src->fixed;
  value= src->value;

  decimal_value.swap(src->decimal_value);
  str_value.swap(src->str_value);
  str_value_ptr.swap(src->str_value_ptr);
}


bool Item_default_value::send(Protocol *protocol, String *buffer)
{
  calculate();
  return Item_field::send(protocol, buffer);
}


enum_field_types Item_type_holder::get_real_type(Item *item)
{
  if (item->type() == REF_ITEM)
    item= item->real_item();
  switch(item->type())
  {
  case FIELD_ITEM:
  {
    /*
      Item_field::field_type ask Field_type() but sometimes field return
      a different type, like for enum/set, so we need to ask real type.
    */
    Field *field= ((Item_field *) item)->field;
    enum_field_types type= field->real_type();
    if (field->is_created_from_null_item)
      return MYSQL_TYPE_NULL;
    /* work around about varchar type field detection */
    if (type == MYSQL_TYPE_STRING && field->type() == MYSQL_TYPE_VAR_STRING)
      return MYSQL_TYPE_VAR_STRING;
    return type;
  }
  case SUM_FUNC_ITEM:
  {
    /*
      Argument of aggregate function sometimes should be asked about field
      type
    */
    Item_sum *item_sum= (Item_sum *) item;
    if (item_sum->keep_field_type())
      return get_real_type(item_sum->get_arg(0));
    break;
  }
  case FUNC_ITEM:
    if (((Item_func *) item)->functype() == Item_func::GUSERVAR_FUNC)
    {
      /*
        There are work around of problem with changing variable type on the
        fly and variable always report "string" as field type to get
        acceptable information for client in send_field, so we make field
        type from expression type.
      */
      switch (item->result_type()) {
      case STRING_RESULT:
        return MYSQL_TYPE_VARCHAR;
      case INT_RESULT:
        return MYSQL_TYPE_LONGLONG;
      case REAL_RESULT:
        return MYSQL_TYPE_DOUBLE;
      case DECIMAL_RESULT:
        return MYSQL_TYPE_NEWDECIMAL;
      case ROW_RESULT:
      case TIME_RESULT:
        DBUG_ASSERT(0);
        return MYSQL_TYPE_VARCHAR;
      }
    }
    break;
  case TYPE_HOLDER:
    /*
      Item_type_holder and Item_blob should not appear in this context.
      In case they for some reasons do, returning field_type() is wrong anyway.
      They must return Item_type_holder::real_field_type() instead, to make
      the code in sql_type.cc and sql_type.h happy, as it expectes
      Field::real_type()-compatible rather than Field::field_type()-compatible
      valies in some places, and may in the future add some asserts preventing
      use of field_type() instead of real_type() and the other way around.
    */
    DBUG_ASSERT(0);
  default:
    break;
  }
  return item->field_type();
}


Item *Item_decimal::neg(THD *thd)
{
  my_decimal_neg(&decimal_value);
  unsigned_flag= 0;
  name= 0;
  max_length= my_decimal_precision_to_length_no_truncation(
                      decimal_value.intg + decimals, decimals, unsigned_flag);
  return this;
}


Item *get_field_item_for_having(THD *thd, Item *item, st_select_lex *sel)
{
  DBUG_ASSERT(item->type() == Item::FIELD_ITEM ||
              (item->type() == Item::REF_ITEM &&
               ((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF));
  Item_field *field_item= NULL;
  table_map map= sel->master_unit()->derived->table->map;
  Item_equal *item_equal= item->get_item_equal();
  if (!item_equal)
    field_item= (Item_field *)(item->real_item());
  else
  {
    Item_equal_fields_iterator li(*item_equal);
    Item *equal_item;
    while ((equal_item= li++))
    {
      if (equal_item->used_tables() == map)
      {
        field_item= (Item_field *)(equal_item->real_item());
	break;
      }
    }
  }
  if (field_item)
  {
    Item_ref *ref= new (thd->mem_root) Item_ref(thd, &sel->context,
                                                NullS, NullS,
                                                field_item->field_name);
    return ref;
  }
  DBUG_ASSERT(0);
  return NULL;
}


void Item::split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array,
                           List<Item> &fields, Item **ref,
                           uint split_flags)
{
  if (unlikely(type() == SUM_FUNC_ITEM))
  {
    /* An item of type Item_sum is registered if ref_by != 0 */
    if ((split_flags & SPLIT_SUM_SKIP_REGISTERED) &&
        ((Item_sum *) this)->ref_by)
      return;
  }
  else if (type() == WINDOW_FUNC_ITEM || with_window_func)
  {
    /*
      Skip the else part, window functions are very special functions:
      they need to have their own fields in the temp. table, but they
      need to be proceessed differently than regular aggregate functions

      Call split_sum_func here so that each argument gets its fields to
      point to the temporary table.
    */
    split_sum_func(thd, ref_pointer_array, fields, split_flags);
    if (type() == FUNC_ITEM) {
      return;
    }
  }
  else
  {
    /* Not a SUM() function */
    if (unlikely((!with_sum_func && !(split_flags & SPLIT_SUM_SELECT))))
    {
      /*
        This is not a SUM function and there are no SUM functions inside.
        Nothing more to do.
      */
      return;
    }
    if (likely(with_sum_func ||
               (type() == FUNC_ITEM &&
                (((Item_func *) this)->functype() ==
                 Item_func::ISNOTNULLTEST_FUNC ||
                 ((Item_func *) this)->functype() ==
                 Item_func::TRIG_COND_FUNC))))
    {
      /* Will call split_sum_func2() for all items */
      split_sum_func(thd, ref_pointer_array, fields, split_flags);
      return;
    }

    if (unlikely((!(used_tables() & ~PARAM_TABLE_BIT) ||
                  (type() == REF_ITEM &&
                   ((Item_ref*)this)->ref_type() != Item_ref::VIEW_REF))))
        return;
  }

  /*
    Replace item with a reference so that we can easily calculate
    it (in case of sum functions) or copy it (in case of fields)

    The test above is to ensure we don't do a reference for things
    that are constants (PARAM_TABLE_BIT is in effect a constant)
    or already referenced (for example an item in HAVING)
    Exception is Item_direct_view_ref which we need to convert to
    Item_ref to allow fields from view being stored in tmp table.
  */
  Item_ref *item_ref;
  uint el= fields.elements;
  /*
    If this is an item_ref, get the original item
    This is a safety measure if this is called for things that is
    already a reference.
  */
  Item *real_itm= real_item();

  ref_pointer_array[el]= real_itm;
  if (type() == WINDOW_FUNC_ITEM)
  {
    if (!(item_ref= (new (thd->mem_root)
                     Item_direct_ref(thd,
                                        &thd->lex->current_select->context,
                                        &ref_pointer_array[el], 0, name))))
      return;                                   // fatal_error is set
  }
  else
  {
    if (!(item_ref= (new (thd->mem_root)
                     Item_aggregate_ref(thd,
                                        &thd->lex->current_select->context,
                                        &ref_pointer_array[el], 0, name))))
      return;                                   // fatal_error is set
  }
  if (type() == SUM_FUNC_ITEM)
    item_ref->depended_from= ((Item_sum *) this)->depended_from();
  fields.push_front(real_itm);
  thd->change_item_tree(ref, item_ref);
}


Item* Item::set_expr_cache(THD *thd)
{
  DBUG_ENTER("Item::set_expr_cache");
  Item_cache_wrapper *wrapper;
  if ((wrapper= new (thd->mem_root) Item_cache_wrapper(thd, this)) &&
      !wrapper->fix_fields(thd, (Item**)&wrapper))
  {
    if (wrapper->set_cache(thd))
      DBUG_RETURN(NULL);
    DBUG_RETURN(wrapper);
  }
  DBUG_RETURN(NULL);
}


const String *Item_param::query_val_str(THD *thd, String* str) const
{
  // There's no "default". See comments in Item_param::save_in_field().
  switch (state) {
  case INT_VALUE:
    str->set_int(value.integer, unsigned_flag, &my_charset_bin);
    return str;
  case REAL_VALUE:
    str->set_real(value.real, NOT_FIXED_DEC, &my_charset_bin);
    return str;
  case DECIMAL_VALUE:
    if (my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value,
                          0, 0, 0, str) > 1)
      return &my_null_string;
    return str;
  case TIME_VALUE:
    {
      static const uint32 typelen= 9; // "TIMESTAMP" is the longest type name
      char *buf, *ptr;
      str->length(0);
      /*
        TODO: in case of error we need to notify replication
        that binary log contains wrong statement
      */
      if (str->reserve(MAX_DATE_STRING_REP_LENGTH + 3 + typelen))
        break;

      /* Create date string inplace */
      switch (value.time.time_type) {
      case MYSQL_TIMESTAMP_DATE:
        str->append(C_STRING_WITH_LEN("DATE"));
        break;
      case MYSQL_TIMESTAMP_TIME:
        str->append(C_STRING_WITH_LEN("TIME"));
        break;
      case MYSQL_TIMESTAMP_DATETIME:
        str->append(C_STRING_WITH_LEN("TIMESTAMP"));
        break;
      case MYSQL_TIMESTAMP_ERROR:
      case MYSQL_TIMESTAMP_NONE:
        break;
      }
      DBUG_ASSERT(str->length() <= typelen);
      buf= str->c_ptr_quick();
      ptr= buf + str->length();
      *ptr++= '\'';
      ptr+= (uint) my_TIME_to_str(&value.time, ptr, decimals);
      *ptr++= '\'';
      str->length((uint32) (ptr - buf));
      return str;
    }
  case STRING_VALUE:
  case LONG_DATA_VALUE:
    {
      str->length(0);
      append_query_string(value.cs_info.character_set_client, str,
                          str_value.ptr(), str_value.length(),
                          thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES);
      return str;
    }
  case IGNORE_VALUE:
  case DEFAULT_VALUE:
    return &my_default_string;
  case NULL_VALUE:
    return &my_null_string;
  case NO_VALUE:
    DBUG_ASSERT(0); // Should not be possible
    return NULL;
  }
  DBUG_ASSERT(0); // Garbage
  return NULL;
}


table_map Item_default_value::used_tables() const
{
  if (!field || !field->default_value)
    return static_cast<table_map>(0);
  if (!field->default_value->expr)                      // not fully parsed field
    return static_cast<table_map>(RAND_TABLE_BIT);
  return field->default_value->expr->used_tables();
}


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


Item *Item_bool_rowready_func2::negated_item(THD *thd)
{
  DBUG_ASSERT(0);
  return 0;
}


  Item_cache_str(THD *thd, const Item *item):
    Item_cache(thd, item->type_handler()), value(0),
    is_varbinary(item->type() == FIELD_ITEM &&
                 Item_cache_str::field_type() == MYSQL_TYPE_VARCHAR &&
                 !((const Item_field *) item)->field->has_charset())
  {
    collation.set(const_cast<DTCollation&>(item->collation));
  }


bool Item_func_regex::fix_fields(THD *thd, Item **ref)
{
  re.set_recursion_limit(thd);
  return Item_bool_func::fix_fields(thd, ref);
}


  bool check_cols(uint c)
  {
    if (cols() != c)
    {
      my_error(ER_OPERAND_COLUMNS, MYF(0), c);
      return true;
    }
    return false;
  }


  inline void append(const char *str, uint length)
  {
    str_value.append(str, length);
    max_length= str_value.numchars() * collation.collation->mbmaxlen;
  }


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


  longlong val_int_from_real()
  {
    DBUG_ASSERT(is_fixed());
    return Converter_double_to_longlong_with_warn(val_real(), false).result();
  }


  const char *field_name_or_null()
  { return real_item()->type() == Item::FIELD_ITEM ? name.str : NULL; }


  enum_field_types field_type() const
  {
    return type_handler()->field_type();
  }


void Item_func_in::mark_as_condition_AND_part(TABLE_LIST *embedding)
{
  THD *thd= current_thd;

  Query_arena *arena, backup;
  arena= thd->activate_stmt_arena_if_needed(&backup);

  if (!transform_into_subq_checked)
  {
    if ((transform_into_subq= to_be_transformed_into_in_subq(thd)))
      thd->lex->current_select->in_funcs.push_back(this, thd->mem_root);
    transform_into_subq_checked= true;
  }

  if (arena)
    thd->restore_active_arena(arena, &backup);

  emb_on_expr_nest= embedding;
}


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


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


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


virtual bool is_bool_literal() const { return false; }


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);
}


  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;
  }


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


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


  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);
  }


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


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;
}


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;
}


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;
}


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


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


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);
}


  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;
  }


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;
}


  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);
  }


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