mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-04 04:46:15 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			5987 lines
		
	
	
	
		
			217 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			5987 lines
		
	
	
	
		
			217 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#ifndef FIELD_INCLUDED
 | 
						|
#define FIELD_INCLUDED
 | 
						|
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
 | 
						|
   Copyright (c) 2008, 2021, MariaDB Corporation.
 | 
						|
 | 
						|
   This program is free software; you can redistribute it and/or modify
 | 
						|
   it under the terms of the GNU General Public License as published by
 | 
						|
   the Free Software Foundation; version 2 of the License.
 | 
						|
 | 
						|
   This program is distributed in the hope that it will be useful,
 | 
						|
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
   GNU General Public License for more details.
 | 
						|
 | 
						|
   You should have received a copy of the GNU General Public License
 | 
						|
   along with this program; if not, write to the Free Software
 | 
						|
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335  USA */
 | 
						|
 | 
						|
/*
 | 
						|
  Because of the function make_new_field() all field classes that have static
 | 
						|
  variables must declare the size_of() member function.
 | 
						|
*/
 | 
						|
 | 
						|
#ifdef USE_PRAGMA_INTERFACE
 | 
						|
#pragma interface			/* gcc class implementation */
 | 
						|
#endif
 | 
						|
 | 
						|
#include "mysqld.h"                             /* system_charset_info */
 | 
						|
#include "table.h"                              /* TABLE */
 | 
						|
#include "sql_string.h"                         /* String */
 | 
						|
#include "my_decimal.h"                         /* my_decimal */
 | 
						|
#include "sql_error.h"                          /* Sql_condition */
 | 
						|
#include "compat56.h"
 | 
						|
#include "sql_type.h"                           /* Type_std_attributes */
 | 
						|
#include "field_comp.h"
 | 
						|
 | 
						|
class Send_field;
 | 
						|
class Copy_field;
 | 
						|
class Protocol;
 | 
						|
class Protocol_text;
 | 
						|
class Create_field;
 | 
						|
class Relay_log_info;
 | 
						|
class Field;
 | 
						|
class Column_statistics;
 | 
						|
class Column_statistics_collected;
 | 
						|
class Item_func;
 | 
						|
class Item_bool_func;
 | 
						|
class Item_equal;
 | 
						|
class Virtual_tmp_table;
 | 
						|
class Qualified_column_ident;
 | 
						|
class Table_ident;
 | 
						|
class SEL_ARG;
 | 
						|
class RANGE_OPT_PARAM;
 | 
						|
struct KEY_PART;
 | 
						|
struct SORT_FIELD;
 | 
						|
struct SORT_FIELD_ATTR;
 | 
						|
 | 
						|
enum enum_check_fields
 | 
						|
{
 | 
						|
  CHECK_FIELD_IGNORE,
 | 
						|
  CHECK_FIELD_EXPRESSION,
 | 
						|
  CHECK_FIELD_WARN,
 | 
						|
  CHECK_FIELD_ERROR_FOR_NULL,
 | 
						|
};
 | 
						|
 | 
						|
enum ignore_value_reaction
 | 
						|
{
 | 
						|
  IGNORE_MEANS_ERROR,
 | 
						|
  IGNORE_MEANS_DEFAULT,
 | 
						|
  IGNORE_MEANS_FIELD_VALUE
 | 
						|
};
 | 
						|
 | 
						|
ignore_value_reaction find_ignore_reaction(THD *thd);
 | 
						|
 | 
						|
 | 
						|
enum enum_conv_type
 | 
						|
{
 | 
						|
  CONV_TYPE_PRECISE,
 | 
						|
  CONV_TYPE_VARIANT,
 | 
						|
  CONV_TYPE_SUBSET_TO_SUPERSET,
 | 
						|
  CONV_TYPE_SUPERSET_TO_SUBSET,
 | 
						|
  CONV_TYPE_IMPOSSIBLE
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Conv_param
 | 
						|
{
 | 
						|
  uint16 m_table_def_flags;
 | 
						|
public:
 | 
						|
  Conv_param(uint16 table_def_flags)
 | 
						|
   :m_table_def_flags(table_def_flags)
 | 
						|
  { }
 | 
						|
  uint16 table_def_flags() const { return m_table_def_flags; }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Conv_source: public Type_handler_hybrid_field_type
 | 
						|
{
 | 
						|
  uint16 m_metadata;
 | 
						|
  CHARSET_INFO *m_cs;
 | 
						|
public:
 | 
						|
  Conv_source(const Type_handler *h, uint16 metadata, CHARSET_INFO *cs)
 | 
						|
   :Type_handler_hybrid_field_type(h),
 | 
						|
    m_metadata(metadata),
 | 
						|
    m_cs(cs)
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(cs);
 | 
						|
  }
 | 
						|
  uint16 metadata() const { return m_metadata; }
 | 
						|
  uint mbmaxlen() const { return m_cs->mbmaxlen; }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
  Common declarations for Field and Item
 | 
						|
*/
 | 
						|
class Value_source
 | 
						|
{
 | 
						|
protected:
 | 
						|
 | 
						|
  // Parameters for warning and note generation
 | 
						|
  class Warn_filter
 | 
						|
  {
 | 
						|
    bool m_want_warning_edom;
 | 
						|
    bool m_want_note_truncated_spaces;
 | 
						|
  public:
 | 
						|
    Warn_filter(bool want_warning_edom, bool want_note_truncated_spaces) :
 | 
						|
     m_want_warning_edom(want_warning_edom),
 | 
						|
     m_want_note_truncated_spaces(want_note_truncated_spaces)
 | 
						|
    { }
 | 
						|
    Warn_filter(const THD *thd);
 | 
						|
    bool want_warning_edom() const
 | 
						|
    { return m_want_warning_edom; }
 | 
						|
    bool want_note_truncated_spaces() const
 | 
						|
    { return m_want_note_truncated_spaces; }
 | 
						|
  };
 | 
						|
  class Warn_filter_all: public Warn_filter
 | 
						|
  {
 | 
						|
  public:
 | 
						|
    Warn_filter_all() :Warn_filter(true, true) { }
 | 
						|
  };
 | 
						|
 | 
						|
  class Converter_double_to_longlong
 | 
						|
  {
 | 
						|
  protected:
 | 
						|
    bool m_error;
 | 
						|
    longlong m_result;
 | 
						|
  public:
 | 
						|
    Converter_double_to_longlong(double nr, bool unsigned_flag);
 | 
						|
    longlong result() const { return m_result; }
 | 
						|
    bool error() const { return m_error; }
 | 
						|
    void push_warning(THD *thd, double nr, bool unsigned_flag);
 | 
						|
  };
 | 
						|
  class Converter_double_to_longlong_with_warn:
 | 
						|
    public Converter_double_to_longlong
 | 
						|
  {
 | 
						|
  public:
 | 
						|
    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);
 | 
						|
    }
 | 
						|
    Converter_double_to_longlong_with_warn(double nr, bool unsigned_flag)
 | 
						|
      :Converter_double_to_longlong(nr, unsigned_flag)
 | 
						|
    {
 | 
						|
      if (m_error)
 | 
						|
        push_warning(current_thd, nr, unsigned_flag);
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  // String-to-number converters
 | 
						|
  class Converter_string_to_number
 | 
						|
  {
 | 
						|
  protected:
 | 
						|
    char *m_end_of_num; // Where the low-level conversion routine stopped
 | 
						|
    int m_error;        // The error code returned by the low-level routine
 | 
						|
    bool m_edom;        // If EDOM-alike error happened during conversion
 | 
						|
    /**
 | 
						|
      Check string-to-number conversion and produce a warning if
 | 
						|
      - could not convert any digits (EDOM-alike error)
 | 
						|
      - found garbage at the end of the string
 | 
						|
      - found extra spaces at the end (a note)
 | 
						|
      See also Field_num::check_edom_and_truncation() for a similar function.
 | 
						|
 | 
						|
      @param thd         - the thread that will be used to generate warnings.
 | 
						|
                           Can be NULL (which means current_thd will be used
 | 
						|
                           if a warning is really necessary).
 | 
						|
      @param type        - name of the data type
 | 
						|
                           (e.g. "INTEGER", "DECIMAL", "DOUBLE")
 | 
						|
      @param cs          - character set of the original string
 | 
						|
      @param str         - the original string
 | 
						|
      @param end         - the end of the string
 | 
						|
      @param allow_notes - tells if trailing space notes should be displayed
 | 
						|
                           or suppressed.
 | 
						|
 | 
						|
      Unlike Field_num::check_edom_and_truncation(), this function does not
 | 
						|
      distinguish between EDOM and truncation and reports the same warning for
 | 
						|
      both cases. Perhaps we should eventually print different warnings,
 | 
						|
      to make the explicit CAST work closer to the implicit cast in
 | 
						|
      Field_xxx::store().
 | 
						|
    */
 | 
						|
    void check_edom_and_truncation(THD *thd, Warn_filter filter,
 | 
						|
                                   const char *type,
 | 
						|
                                   CHARSET_INFO *cs,
 | 
						|
                                   const char *str,
 | 
						|
                                   size_t length) const;
 | 
						|
  public:
 | 
						|
    int error() const { return m_error; }
 | 
						|
  };
 | 
						|
 | 
						|
  class Converter_strntod: public Converter_string_to_number
 | 
						|
  {
 | 
						|
    double m_result;
 | 
						|
  public:
 | 
						|
    Converter_strntod(CHARSET_INFO *cs, const char *str, size_t length)
 | 
						|
    {
 | 
						|
      m_result= cs->strntod((char *) str, length, &m_end_of_num, &m_error);
 | 
						|
      // strntod() does not set an error if the input string was empty
 | 
						|
      m_edom= m_error !=0 || str == m_end_of_num;
 | 
						|
    }
 | 
						|
    double result() const { return m_result; }
 | 
						|
  };
 | 
						|
 | 
						|
  class Converter_string_to_longlong: public Converter_string_to_number
 | 
						|
  {
 | 
						|
  protected:
 | 
						|
    longlong m_result;
 | 
						|
  public:
 | 
						|
    longlong result() const { return m_result; }
 | 
						|
  };
 | 
						|
 | 
						|
  class Converter_strntoll: public Converter_string_to_longlong
 | 
						|
  {
 | 
						|
  public:
 | 
						|
    Converter_strntoll(CHARSET_INFO *cs, const char *str, size_t length)
 | 
						|
    {
 | 
						|
      m_result= cs->strntoll(str, length, 10, &m_end_of_num, &m_error);
 | 
						|
      /*
 | 
						|
         All non-zero errors means EDOM error.
 | 
						|
         strntoll() does not set an error if the input string was empty.
 | 
						|
         Check it here.
 | 
						|
         Notice the different with the same condition in Converter_strntoll10.
 | 
						|
      */
 | 
						|
      m_edom= m_error != 0 || str == m_end_of_num;
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  class Converter_strtoll10: public Converter_string_to_longlong
 | 
						|
  {
 | 
						|
  public:
 | 
						|
    Converter_strtoll10(CHARSET_INFO *cs, const char *str, size_t length)
 | 
						|
    {
 | 
						|
      m_end_of_num= (char *) str + length;
 | 
						|
      m_result= cs->strtoll10(str, &m_end_of_num, &m_error);
 | 
						|
      /*
 | 
						|
        Negative error means "good negative number".
 | 
						|
        Only a positive m_error value means a real error.
 | 
						|
        strtoll10() sets error to MY_ERRNO_EDOM in case of an empty string,
 | 
						|
        so we don't have to additionally catch empty strings here.
 | 
						|
      */
 | 
						|
      m_edom= m_error > 0;
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  class Converter_str2my_decimal: public Converter_string_to_number
 | 
						|
  {
 | 
						|
  public:
 | 
						|
    Converter_str2my_decimal(uint mask,
 | 
						|
                             CHARSET_INFO *cs, const char *str, size_t length,
 | 
						|
                             my_decimal *buf)
 | 
						|
    {
 | 
						|
      DBUG_ASSERT(length < UINT_MAX32);
 | 
						|
      m_error= str2my_decimal(mask, str, length, cs,
 | 
						|
                              buf, (const char **) &m_end_of_num);
 | 
						|
      // E_DEC_TRUNCATED means a very minor truncation: '1e-100' -> 0
 | 
						|
      m_edom= m_error && m_error != E_DEC_TRUNCATED;
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
 | 
						|
  // String-to-number converters with automatic warning generation
 | 
						|
  class Converter_strntod_with_warn: public Converter_strntod
 | 
						|
  {
 | 
						|
  public:
 | 
						|
    Converter_strntod_with_warn(THD *thd, Warn_filter filter,
 | 
						|
                                CHARSET_INFO *cs,
 | 
						|
                                const char *str, size_t length)
 | 
						|
      :Converter_strntod(cs, str, length)
 | 
						|
    {
 | 
						|
      check_edom_and_truncation(thd, filter, "DOUBLE", cs, str, length);
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  class Converter_strntoll_with_warn: public Converter_strntoll
 | 
						|
  {
 | 
						|
  public:
 | 
						|
    Converter_strntoll_with_warn(THD *thd, Warn_filter filter,
 | 
						|
                                 CHARSET_INFO *cs,
 | 
						|
                                 const char *str, size_t length)
 | 
						|
      :Converter_strntoll(cs, str, length)
 | 
						|
    {
 | 
						|
      check_edom_and_truncation(thd, filter, "INTEGER", cs, str, length);
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  class Converter_strtoll10_with_warn: public Converter_strtoll10
 | 
						|
  {
 | 
						|
  public:
 | 
						|
    Converter_strtoll10_with_warn(THD *thd, Warn_filter filter,
 | 
						|
                                 CHARSET_INFO *cs,
 | 
						|
                                 const char *str, size_t length)
 | 
						|
      :Converter_strtoll10(cs, str, length)
 | 
						|
    {
 | 
						|
      check_edom_and_truncation(thd, filter, "INTEGER", cs, str, length);
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  class Converter_str2my_decimal_with_warn: public Converter_str2my_decimal
 | 
						|
  {
 | 
						|
  public:
 | 
						|
    Converter_str2my_decimal_with_warn(THD *thd, Warn_filter filter,
 | 
						|
                                       uint mask, CHARSET_INFO *cs,
 | 
						|
                                       const char *str, size_t length,
 | 
						|
                                       my_decimal *buf)
 | 
						|
     :Converter_str2my_decimal(mask, cs, str, length, buf)
 | 
						|
    {
 | 
						|
      check_edom_and_truncation(thd, filter, "DECIMAL", cs, str, length);
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
 | 
						|
  // String-to-number conversion methods for the old code compatibility
 | 
						|
  longlong longlong_from_string_with_check(CHARSET_INFO *cs, const char *cptr,
 | 
						|
                                           const char *end) const
 | 
						|
  {
 | 
						|
    /*
 | 
						|
      TODO: Give error if we wanted a signed integer and we got an unsigned
 | 
						|
      one
 | 
						|
 | 
						|
      Notice, longlong_from_string_with_check() honors thd->no_error, because
 | 
						|
      it's used to handle queries like this:
 | 
						|
        SELECT COUNT(@@basedir);
 | 
						|
      and is called when Item_func_get_system_var::update_null_value()
 | 
						|
      suppresses warnings and then calls val_int().
 | 
						|
      The other methods {double|decimal}_from_string_with_check() ignore
 | 
						|
      thd->no_errors, because they are not used for update_null_value()
 | 
						|
      and they always allow all kind of warnings.
 | 
						|
    */
 | 
						|
    THD *thd= current_thd;
 | 
						|
    return Converter_strtoll10_with_warn(thd, Warn_filter(thd),
 | 
						|
                                         cs, cptr, end - cptr).result();
 | 
						|
  }
 | 
						|
 | 
						|
  double double_from_string_with_check(CHARSET_INFO *cs, const char *cptr,
 | 
						|
                                       const char *end) const
 | 
						|
  {
 | 
						|
    return Converter_strntod_with_warn(NULL, Warn_filter_all(),
 | 
						|
                                       cs, cptr, end - cptr).result();
 | 
						|
  }
 | 
						|
  my_decimal *decimal_from_string_with_check(my_decimal *decimal_value,
 | 
						|
                                             CHARSET_INFO *cs,
 | 
						|
                                             const char *cptr,
 | 
						|
                                             const char *end)
 | 
						|
  {
 | 
						|
    Converter_str2my_decimal_with_warn(NULL, Warn_filter_all(),
 | 
						|
                                       E_DEC_FATAL_ERROR & ~E_DEC_BAD_NUM,
 | 
						|
                                       cs, cptr, end - cptr, decimal_value);
 | 
						|
    return decimal_value;
 | 
						|
  }
 | 
						|
 | 
						|
  longlong longlong_from_hex_hybrid(const char *str, size_t length)
 | 
						|
  {
 | 
						|
    const char *end= str + length;
 | 
						|
    const char *ptr= end - MY_MIN(length, sizeof(longlong));
 | 
						|
    ulonglong value= 0;
 | 
						|
    for ( ; ptr != end ; ptr++)
 | 
						|
      value= (value << 8) + (ulonglong) (uchar) *ptr;
 | 
						|
    return (longlong) value;
 | 
						|
  }
 | 
						|
 | 
						|
  longlong longlong_from_string_with_check(const String *str) const
 | 
						|
  {
 | 
						|
    return longlong_from_string_with_check(str->charset(),
 | 
						|
                                           str->ptr(), str->end());
 | 
						|
  }
 | 
						|
  double double_from_string_with_check(const String *str) const
 | 
						|
  {
 | 
						|
    return double_from_string_with_check(str->charset(),
 | 
						|
                                         str->ptr(), str->end());
 | 
						|
  }
 | 
						|
  my_decimal *decimal_from_string_with_check(my_decimal *decimal_value,
 | 
						|
                                             const String *str)
 | 
						|
  {
 | 
						|
    return decimal_from_string_with_check(decimal_value, str->charset(),
 | 
						|
                                          str->ptr(), str->end());
 | 
						|
  }
 | 
						|
  // End of String-to-number conversion methods
 | 
						|
 | 
						|
public:
 | 
						|
  /*
 | 
						|
    The enumeration Subst_constraint is currently used only in implementations
 | 
						|
    of the virtual function subst_argument_checker.
 | 
						|
  */
 | 
						|
  enum Subst_constraint
 | 
						|
  {
 | 
						|
    ANY_SUBST,           /* Any substitution for a field is allowed  */
 | 
						|
    IDENTITY_SUBST       /* Substitution for a field is allowed if any two
 | 
						|
                            different values of the field type are not equal */
 | 
						|
  };
 | 
						|
  /*
 | 
						|
    Item context attributes.
 | 
						|
    Comparison functions pass their attributes to propagate_equal_fields().
 | 
						|
    For example, for string comparison, the collation of the comparison
 | 
						|
    operation is important inside propagate_equal_fields().
 | 
						|
  */
 | 
						|
  class Context
 | 
						|
  {
 | 
						|
    /*
 | 
						|
      Which type of propagation is allowed:
 | 
						|
      - ANY_SUBST (loose equality, according to the collation), or
 | 
						|
      - IDENTITY_SUBST (strict binary equality).
 | 
						|
    */
 | 
						|
    Subst_constraint m_subst_constraint;
 | 
						|
    /*
 | 
						|
      Comparison type.
 | 
						|
      Important only when ANY_SUBSTS.
 | 
						|
    */
 | 
						|
    const Type_handler *m_compare_handler;
 | 
						|
    /*
 | 
						|
      Collation of the comparison operation.
 | 
						|
      Important only when ANY_SUBST.
 | 
						|
    */
 | 
						|
    CHARSET_INFO *m_compare_collation;
 | 
						|
  public:
 | 
						|
    Context(Subst_constraint subst, const Type_handler *h, CHARSET_INFO *cs)
 | 
						|
      :m_subst_constraint(subst),
 | 
						|
       m_compare_handler(h),
 | 
						|
       m_compare_collation(cs)
 | 
						|
    { DBUG_ASSERT(h == h->type_handler_for_comparison()); }
 | 
						|
    Subst_constraint subst_constraint() const { return m_subst_constraint; }
 | 
						|
    const Type_handler *compare_type_handler() const
 | 
						|
    {
 | 
						|
      DBUG_ASSERT(m_subst_constraint == ANY_SUBST);
 | 
						|
      return m_compare_handler;
 | 
						|
    }
 | 
						|
    CHARSET_INFO *compare_collation() const
 | 
						|
    {
 | 
						|
      DBUG_ASSERT(m_subst_constraint == ANY_SUBST);
 | 
						|
      return m_compare_collation;
 | 
						|
    }
 | 
						|
  };
 | 
						|
  class Context_identity: public Context
 | 
						|
  { // Use this to request only exact value, no invariants.
 | 
						|
  public:
 | 
						|
     Context_identity()
 | 
						|
      :Context(IDENTITY_SUBST, &type_handler_long_blob, &my_charset_bin) { }
 | 
						|
  };
 | 
						|
  class Context_boolean: public Context
 | 
						|
  { // Use this when an item is [a part of] a boolean expression
 | 
						|
  public:
 | 
						|
    Context_boolean()
 | 
						|
      :Context(ANY_SUBST, &type_handler_slonglong, &my_charset_bin) { }
 | 
						|
  };
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
#define STORAGE_TYPE_MASK 7
 | 
						|
#define COLUMN_FORMAT_MASK 7
 | 
						|
#define COLUMN_FORMAT_SHIFT 3
 | 
						|
 | 
						|
/* The length of the header part for each virtual column in the .frm file */
 | 
						|
#define FRM_VCOL_OLD_HEADER_SIZE(b) (3 + MY_TEST(b))
 | 
						|
#define FRM_VCOL_NEW_BASE_SIZE 16
 | 
						|
#define FRM_VCOL_NEW_HEADER_SIZE 6
 | 
						|
 | 
						|
class Count_distinct_field;
 | 
						|
 | 
						|
struct ha_field_option_struct;
 | 
						|
 | 
						|
struct st_cache_field;
 | 
						|
int field_conv(Field *to,Field *from);
 | 
						|
int truncate_double(double *nr, uint field_length, decimal_digits_t dec,
 | 
						|
                    bool unsigned_flag, double max_value);
 | 
						|
 | 
						|
inline uint get_enum_pack_length(int elements)
 | 
						|
{
 | 
						|
  return elements < 256 ? 1 : 2;
 | 
						|
}
 | 
						|
 | 
						|
inline uint get_set_pack_length(int elements)
 | 
						|
{
 | 
						|
  uint len= (elements + 7) / 8;
 | 
						|
  return len > 4 ? 8 : len;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Tests if field type is temporal and has date part,
 | 
						|
  i.e. represents DATE, DATETIME or TIMESTAMP types in SQL.
 | 
						|
 | 
						|
  @param type    Field type, as returned by field->type().
 | 
						|
  @retval true   If field type is temporal type with date part.
 | 
						|
  @retval false  If field type is not temporal type with date part.
 | 
						|
*/
 | 
						|
inline bool is_temporal_type_with_date(enum_field_types type)
 | 
						|
{
 | 
						|
  switch (type)
 | 
						|
  {
 | 
						|
  case MYSQL_TYPE_DATE:
 | 
						|
  case MYSQL_TYPE_DATETIME:
 | 
						|
  case MYSQL_TYPE_TIMESTAMP:
 | 
						|
    return true;
 | 
						|
  case MYSQL_TYPE_DATETIME2:
 | 
						|
  case MYSQL_TYPE_TIMESTAMP2:
 | 
						|
    DBUG_ASSERT(0); // field->real_type() should not get to here.
 | 
						|
    return false;
 | 
						|
  default:
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
enum enum_vcol_info_type
 | 
						|
{
 | 
						|
  VCOL_GENERATED_VIRTUAL, VCOL_GENERATED_STORED,
 | 
						|
  VCOL_DEFAULT, VCOL_CHECK_FIELD, VCOL_CHECK_TABLE,
 | 
						|
  VCOL_USING_HASH,
 | 
						|
  /* Additional types should be added here */
 | 
						|
 | 
						|
  VCOL_GENERATED_VIRTUAL_INDEXED, // this is never written in .frm
 | 
						|
  /* Following is the highest value last   */
 | 
						|
  VCOL_TYPE_NONE = 127 // Since the 0 value is already in use
 | 
						|
};
 | 
						|
 | 
						|
static inline const char *vcol_type_name(enum_vcol_info_type type)
 | 
						|
{
 | 
						|
  switch (type)
 | 
						|
  {
 | 
						|
  case VCOL_GENERATED_VIRTUAL:
 | 
						|
  case VCOL_GENERATED_VIRTUAL_INDEXED:
 | 
						|
  case VCOL_GENERATED_STORED:
 | 
						|
    return "GENERATED ALWAYS AS";
 | 
						|
  case VCOL_DEFAULT:
 | 
						|
    return "DEFAULT";
 | 
						|
  case VCOL_CHECK_FIELD:
 | 
						|
  case VCOL_CHECK_TABLE:
 | 
						|
    return "CHECK";
 | 
						|
  case VCOL_USING_HASH:
 | 
						|
    return "USING HASH";
 | 
						|
  case VCOL_TYPE_NONE:
 | 
						|
    return "UNTYPED";
 | 
						|
  }
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
  Flags for Virtual_column_info. If none is set, the expression must be
 | 
						|
  a constant with no side-effects, so it's calculated at CREATE TABLE time,
 | 
						|
  stored in table->record[2], and not recalculated for every statement.
 | 
						|
*/
 | 
						|
#define VCOL_FIELD_REF         1
 | 
						|
#define VCOL_NON_DETERMINISTIC 2
 | 
						|
#define VCOL_SESSION_FUNC      4  /* uses session data, e.g. USER or DAYNAME */
 | 
						|
#define VCOL_TIME_FUNC         8  /* safe for SBR */
 | 
						|
#define VCOL_AUTO_INC         16
 | 
						|
#define VCOL_IMPOSSIBLE       32
 | 
						|
#define VCOL_NEXTVAL          64  /* NEXTVAL is not implemented for vcols */
 | 
						|
 | 
						|
#define VCOL_NOT_STRICTLY_DETERMINISTIC                       \
 | 
						|
  (VCOL_NON_DETERMINISTIC | VCOL_TIME_FUNC | VCOL_SESSION_FUNC)
 | 
						|
 | 
						|
/*
 | 
						|
  Virtual_column_info is the class to contain additional
 | 
						|
  characteristics that is specific for a virtual/computed
 | 
						|
  field such as:
 | 
						|
   - the defining expression that is evaluated to compute the value
 | 
						|
  of the field 
 | 
						|
  - whether the field is to be stored in the database
 | 
						|
  - whether the field is used in a partitioning expression
 | 
						|
*/
 | 
						|
 | 
						|
class Virtual_column_info: public Sql_alloc,
 | 
						|
                           private Type_handler_hybrid_field_type
 | 
						|
{
 | 
						|
private:
 | 
						|
  enum_vcol_info_type vcol_type; /* Virtual column expression type */
 | 
						|
  /*
 | 
						|
    The following data is only updated by the parser and read
 | 
						|
    when a Create_field object is created/initialized.
 | 
						|
  */
 | 
						|
  /* Flag indicating that the field used in a partitioning expression */
 | 
						|
  bool in_partitioning_expr;
 | 
						|
 | 
						|
public:
 | 
						|
  /* Flag indicating  that the field is physically stored in the database */
 | 
						|
  bool stored_in_db;
 | 
						|
  bool utf8;                                    /* Already in utf8 */
 | 
						|
  bool automatic_name;
 | 
						|
  bool if_not_exists;
 | 
						|
  Item *expr;
 | 
						|
  Lex_ident name;                               /* Name of constraint */
 | 
						|
  /* see VCOL_* (VCOL_FIELD_REF, ...) */
 | 
						|
  uint flags;
 | 
						|
 | 
						|
  Virtual_column_info()
 | 
						|
   :Type_handler_hybrid_field_type(&type_handler_null),
 | 
						|
    vcol_type((enum_vcol_info_type)VCOL_TYPE_NONE),
 | 
						|
    in_partitioning_expr(FALSE), stored_in_db(FALSE),
 | 
						|
    utf8(TRUE), automatic_name(FALSE), expr(NULL), flags(0)
 | 
						|
  {
 | 
						|
    name.str= NULL;
 | 
						|
    name.length= 0;
 | 
						|
  };
 | 
						|
  Virtual_column_info* clone(THD *thd);
 | 
						|
  ~Virtual_column_info() = default;
 | 
						|
  enum_vcol_info_type get_vcol_type() const
 | 
						|
  {
 | 
						|
    return vcol_type;
 | 
						|
  }
 | 
						|
  void set_vcol_type(enum_vcol_info_type v_type)
 | 
						|
  {
 | 
						|
    vcol_type= v_type;
 | 
						|
  }
 | 
						|
  const char *get_vcol_type_name() const
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(vcol_type != VCOL_TYPE_NONE);
 | 
						|
    return vcol_type_name(vcol_type);
 | 
						|
  }
 | 
						|
  void set_handler(const Type_handler *handler)
 | 
						|
  {
 | 
						|
    /* Calling this function can only be done once. */
 | 
						|
    DBUG_ASSERT(type_handler() == &type_handler_null);
 | 
						|
    Type_handler_hybrid_field_type::set_handler(handler);
 | 
						|
  }
 | 
						|
  bool is_stored() const
 | 
						|
  {
 | 
						|
    return stored_in_db;
 | 
						|
  }
 | 
						|
  void set_stored_in_db_flag(bool stored)
 | 
						|
  {
 | 
						|
    stored_in_db= stored;
 | 
						|
  }
 | 
						|
  bool is_in_partitioning_expr() const
 | 
						|
  {
 | 
						|
    return in_partitioning_expr;
 | 
						|
  }
 | 
						|
  void mark_as_in_partitioning_expr()
 | 
						|
  {
 | 
						|
    in_partitioning_expr= TRUE;
 | 
						|
  }
 | 
						|
  bool need_refix() const
 | 
						|
  {
 | 
						|
    return flags & VCOL_SESSION_FUNC;
 | 
						|
  }
 | 
						|
  bool fix_expr(THD *thd);
 | 
						|
  bool fix_session_expr(THD *thd);
 | 
						|
  bool cleanup_session_expr();
 | 
						|
  bool fix_and_check_expr(THD *thd, TABLE *table);
 | 
						|
  inline bool is_equal(const Virtual_column_info* vcol) const;
 | 
						|
  /* Same as is_equal() but for comparing with different table */
 | 
						|
  bool is_equivalent(THD *thd, TABLE_SHARE *share, TABLE_SHARE *vcol_share,
 | 
						|
                            const Virtual_column_info* vcol, bool &error) const;
 | 
						|
  inline void print(String*);
 | 
						|
};
 | 
						|
 | 
						|
class Binlog_type_info
 | 
						|
{
 | 
						|
public:
 | 
						|
   enum binlog_sign_t
 | 
						|
   {
 | 
						|
     SIGN_SIGNED,
 | 
						|
     SIGN_UNSIGNED,
 | 
						|
     SIGN_NOT_APPLICABLE // for non-numeric types
 | 
						|
   };
 | 
						|
  /**
 | 
						|
     Retrieve the field metadata for fields.
 | 
						|
  */
 | 
						|
   CHARSET_INFO *m_cs; // NULL if not relevant
 | 
						|
   TYPELIB *m_enum_typelib; // NULL if not relevant
 | 
						|
   TYPELIB *m_set_typelib; // NULL if not relevant
 | 
						|
   binlog_sign_t m_signedness;
 | 
						|
   uint16 m_metadata;
 | 
						|
   uint8 m_metadata_size;
 | 
						|
   uchar m_type_code;     // according to Field::binlog_type()
 | 
						|
   uchar m_geom_type; // Non-geometry fields can return 0
 | 
						|
 | 
						|
   Binlog_type_info(uchar type_code,
 | 
						|
                    uint16 metadata,
 | 
						|
                    uint8 metadata_size)
 | 
						|
    :m_cs(NULL),
 | 
						|
     m_enum_typelib(NULL),
 | 
						|
     m_set_typelib(NULL),
 | 
						|
     m_signedness(SIGN_NOT_APPLICABLE),
 | 
						|
     m_metadata(metadata),
 | 
						|
     m_metadata_size(metadata_size),
 | 
						|
     m_type_code(type_code),
 | 
						|
     m_geom_type(0)
 | 
						|
    {};
 | 
						|
   Binlog_type_info(uchar type_code, uint16 metadata,
 | 
						|
                   uint8 metadata_size,
 | 
						|
                   binlog_sign_t signedness)
 | 
						|
    : m_cs(NULL),
 | 
						|
     m_enum_typelib(NULL),
 | 
						|
     m_set_typelib(NULL),
 | 
						|
     m_signedness(signedness),
 | 
						|
     m_metadata(metadata),
 | 
						|
     m_metadata_size(metadata_size),
 | 
						|
     m_type_code(type_code),
 | 
						|
     m_geom_type(0)
 | 
						|
    {};
 | 
						|
   Binlog_type_info(uchar type_code, uint16 metadata,
 | 
						|
                   uint8 metadata_size, CHARSET_INFO *cs)
 | 
						|
    :m_cs(cs),
 | 
						|
     m_enum_typelib(NULL),
 | 
						|
     m_set_typelib(NULL),
 | 
						|
     m_signedness(SIGN_NOT_APPLICABLE),
 | 
						|
     m_metadata(metadata),
 | 
						|
     m_metadata_size(metadata_size),
 | 
						|
     m_type_code(type_code),
 | 
						|
     m_geom_type(0)
 | 
						|
    {};
 | 
						|
   Binlog_type_info(uchar type_code, uint16 metadata,
 | 
						|
                   uint8 metadata_size,
 | 
						|
                   CHARSET_INFO *cs,
 | 
						|
                   TYPELIB *t_enum, TYPELIB *t_set)
 | 
						|
    :m_cs(cs),
 | 
						|
     m_enum_typelib(t_enum),
 | 
						|
     m_set_typelib(t_set),
 | 
						|
     m_signedness(SIGN_NOT_APPLICABLE),
 | 
						|
     m_metadata(metadata),
 | 
						|
     m_metadata_size(metadata_size),
 | 
						|
     m_type_code(type_code),
 | 
						|
     m_geom_type(0)
 | 
						|
    {};
 | 
						|
   Binlog_type_info(uchar type_code, uint16 metadata,
 | 
						|
                   uint8 metadata_size, CHARSET_INFO *cs,
 | 
						|
                   uchar geom_type)
 | 
						|
    :m_cs(cs),
 | 
						|
     m_enum_typelib(NULL),
 | 
						|
     m_set_typelib(NULL),
 | 
						|
     m_signedness(SIGN_NOT_APPLICABLE),
 | 
						|
     m_metadata(metadata),
 | 
						|
     m_metadata_size(metadata_size),
 | 
						|
     m_type_code(type_code),
 | 
						|
     m_geom_type(geom_type)
 | 
						|
    {};
 | 
						|
  static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
 | 
						|
  { return alloc_root(mem_root, size); }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Binlog_type_info_fixed_string: public Binlog_type_info
 | 
						|
{
 | 
						|
public:
 | 
						|
  Binlog_type_info_fixed_string(uchar type_code,
 | 
						|
                                uint32 octet_length,
 | 
						|
                                CHARSET_INFO *cs);
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field: public Value_source
 | 
						|
{
 | 
						|
  Field(const Item &);				/* Prevent use of these */
 | 
						|
  void operator=(Field &);
 | 
						|
protected:
 | 
						|
  int save_in_field_str(Field *to)
 | 
						|
  {
 | 
						|
    StringBuffer<MAX_FIELD_WIDTH> result(charset());
 | 
						|
    val_str(&result);
 | 
						|
    return to->store(result.ptr(), result.length(), charset());
 | 
						|
  }
 | 
						|
  void error_generated_column_function_is_not_allowed(THD *thd, bool error)
 | 
						|
                                                      const;
 | 
						|
  static void do_field_eq(Copy_field *copy);
 | 
						|
  static void do_field_int(Copy_field *copy);
 | 
						|
  static void do_field_real(Copy_field *copy);
 | 
						|
  static void do_field_string(Copy_field *copy);
 | 
						|
  static void do_field_date(Copy_field *copy);
 | 
						|
  static void do_field_temporal(Copy_field *copy, date_mode_t fuzzydate);
 | 
						|
  static void do_field_datetime(Copy_field *copy);
 | 
						|
  static void do_field_timestamp(Copy_field *copy);
 | 
						|
  static void do_field_decimal(Copy_field *copy);
 | 
						|
public:
 | 
						|
  static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
 | 
						|
  { return alloc_root(mem_root, size); }
 | 
						|
  static void *operator new(size_t size) throw ()
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(size < UINT_MAX32);
 | 
						|
    return thd_alloc(current_thd, (uint) size);
 | 
						|
  }
 | 
						|
  static void operator delete(void *ptr_arg, size_t size) { TRASH_FREE(ptr_arg, size); }
 | 
						|
  static void operator delete(void *ptr, MEM_ROOT *mem_root)
 | 
						|
  { DBUG_ASSERT(0); }
 | 
						|
 | 
						|
  bool marked_for_read() const;
 | 
						|
  bool marked_for_write_or_computed() const;
 | 
						|
 | 
						|
  /**
 | 
						|
     Used by System Versioning.
 | 
						|
   */
 | 
						|
  virtual void set_max()
 | 
						|
  { DBUG_ASSERT(0); }
 | 
						|
  virtual bool is_max()
 | 
						|
  { DBUG_ASSERT(0); return false; }
 | 
						|
 | 
						|
  uchar		*ptr;			// Position to field in record
 | 
						|
 | 
						|
  /**
 | 
						|
     Byte where the @c NULL bit is stored inside a record. If this Field is a
 | 
						|
     @c NOT @c NULL field, this member is @c NULL.
 | 
						|
  */
 | 
						|
  uchar		*null_ptr;
 | 
						|
  /*
 | 
						|
    Note that you can use table->in_use as replacement for current_thd member
 | 
						|
    only inside of val_*() and store() members (e.g. you can't use it in cons)
 | 
						|
  */
 | 
						|
  TABLE *table;                                 // Pointer for table
 | 
						|
  TABLE *orig_table;                            // Pointer to original table
 | 
						|
  const char * const *table_name;               // Pointer to alias in TABLE
 | 
						|
  LEX_CSTRING field_name;
 | 
						|
  LEX_CSTRING comment;
 | 
						|
  /** reference to the list of options or NULL */
 | 
						|
  engine_option_value *option_list;
 | 
						|
  ha_field_option_struct *option_struct;   /* structure with parsed options */
 | 
						|
  /* Field is part of the following keys */
 | 
						|
  key_map	key_start, part_of_key, part_of_key_not_clustered;
 | 
						|
 | 
						|
  /*
 | 
						|
    Bitmap of indexes that have records ordered by col1, ... this_field, ...
 | 
						|
 | 
						|
    For example, INDEX (col(prefix_n)) is not present in col.part_of_sortkey.
 | 
						|
  */
 | 
						|
  key_map       part_of_sortkey;
 | 
						|
  /*
 | 
						|
    We use three additional unireg types for TIMESTAMP to overcome limitation
 | 
						|
    of current binary format of .frm file. We'd like to be able to support
 | 
						|
    NOW() as default and on update value for such fields but unable to hold
 | 
						|
    this info anywhere except unireg_check field. This issue will be resolved
 | 
						|
    in more clean way with transition to new text based .frm format.
 | 
						|
    See also comment for Field_timestamp::Field_timestamp().
 | 
						|
  */
 | 
						|
  enum __attribute__((packed)) utype  {
 | 
						|
    NONE=0,
 | 
						|
    NEXT_NUMBER=15,             // AUTO_INCREMENT
 | 
						|
    TIMESTAMP_OLD_FIELD=18,     // TIMESTAMP created before 4.1.3
 | 
						|
    TIMESTAMP_DN_FIELD=21,      // TIMESTAMP DEFAULT NOW()
 | 
						|
    TIMESTAMP_UN_FIELD=22,      // TIMESTAMP ON UPDATE NOW()
 | 
						|
    TIMESTAMP_DNUN_FIELD=23,    // TIMESTAMP DEFAULT NOW() ON UPDATE NOW()
 | 
						|
    TMYSQL_COMPRESSED= 24,      // Compatibility with TMySQL
 | 
						|
    };
 | 
						|
  enum imagetype { itRAW, itMBR};
 | 
						|
 | 
						|
  utype	unireg_check;
 | 
						|
  field_visibility_t invisible;
 | 
						|
  uint32        field_length;          // Length of field
 | 
						|
  uint32        flags;
 | 
						|
  field_index_t field_index;           // field number in fields array
 | 
						|
  uchar null_bit;                      // Bit used to test null bit
 | 
						|
 | 
						|
  /**
 | 
						|
     If true, this field was created in create_tmp_field_from_item from a NULL
 | 
						|
     value. This means that the type of the field is just a guess, and the type
 | 
						|
     may be freely coerced to another type.
 | 
						|
 | 
						|
     @see create_tmp_field_from_item
 | 
						|
     @see Item_type_holder::get_real_type
 | 
						|
 | 
						|
   */
 | 
						|
  bool is_created_from_null_item;
 | 
						|
 | 
						|
  /* 
 | 
						|
    Selectivity of the range condition over this field.
 | 
						|
    When calculating this selectivity a range predicate
 | 
						|
    is taken into account only if:
 | 
						|
    - it is extracted from the WHERE clause
 | 
						|
    - it depends only on the table the field belongs to 
 | 
						|
  */
 | 
						|
  double cond_selectivity;
 | 
						|
 | 
						|
  /* 
 | 
						|
    The next field in the class of equal fields at the top AND level
 | 
						|
    of the WHERE clause
 | 
						|
  */ 
 | 
						|
  Field *next_equal_field;
 | 
						|
 | 
						|
  /*
 | 
						|
    This structure is used for statistical data on the column
 | 
						|
    that has been read from the statistical table column_stat
 | 
						|
  */ 
 | 
						|
  Column_statistics *read_stats;
 | 
						|
  /*
 | 
						|
    This structure is used for statistical data on the column that
 | 
						|
    is collected by the function collect_statistics_for_table
 | 
						|
  */
 | 
						|
  Column_statistics_collected *collected_stats;
 | 
						|
 | 
						|
  /* 
 | 
						|
    This is additional data provided for any computed(virtual) field,
 | 
						|
    default function or check constraint.
 | 
						|
    In particular it includes a pointer to the item by which this field
 | 
						|
    can be computed from other fields.
 | 
						|
  */
 | 
						|
  Virtual_column_info *vcol_info, *check_constraint, *default_value;
 | 
						|
 | 
						|
  Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
 | 
						|
        uchar null_bit_arg, utype unireg_check_arg,
 | 
						|
        const LEX_CSTRING *field_name_arg);
 | 
						|
  virtual ~Field() = default;
 | 
						|
 | 
						|
  virtual Type_numeric_attributes type_numeric_attributes() const
 | 
						|
  {
 | 
						|
    return Type_numeric_attributes(field_length, decimals(), is_unsigned());
 | 
						|
  }
 | 
						|
  Type_std_attributes type_std_attributes() const
 | 
						|
  {
 | 
						|
    return Type_std_attributes(type_numeric_attributes(), dtcollation());
 | 
						|
  }
 | 
						|
 | 
						|
  bool is_unsigned() const { return flags & UNSIGNED_FLAG; }
 | 
						|
 | 
						|
  bool check_assignability_from(const Type_handler *from, bool ignore) const;
 | 
						|
  bool check_assignability_from(const Field *from, bool ignore) const
 | 
						|
  {
 | 
						|
    return check_assignability_from(from->type_handler(), ignore);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
    Convenience definition of a copy function returned by
 | 
						|
    Field::get_copy_func()
 | 
						|
  */
 | 
						|
  typedef void Copy_func(Copy_field*);
 | 
						|
  virtual Copy_func *get_copy_func(const Field *from) const= 0;
 | 
						|
  virtual Copy_func *get_copy_func_to(const Field *to) const
 | 
						|
  {
 | 
						|
    return to->get_copy_func(this);
 | 
						|
  }
 | 
						|
  /* Store functions returns 1 on overflow and -1 on fatal error */
 | 
						|
  virtual int  store_field(Field *from) { return from->save_in_field(this); }
 | 
						|
  virtual int  save_in_field(Field *to)= 0;
 | 
						|
  /**
 | 
						|
    Check if it is possible just copy the value
 | 
						|
    of the field 'from' to the field 'this', e.g. for
 | 
						|
      INSERT INTO t1 (field1) SELECT field2 FROM t2;
 | 
						|
    @param from   - The field to copy from
 | 
						|
    @retval true  - it is possible to just copy value of 'from' to 'this'
 | 
						|
    @retval false - conversion is needed
 | 
						|
  */
 | 
						|
  virtual bool memcpy_field_possible(const Field *from) const= 0;
 | 
						|
  virtual bool make_empty_rec_store_default_value(THD *thd, Item *item);
 | 
						|
  virtual void make_empty_rec_reset(THD *thd)
 | 
						|
  {
 | 
						|
    reset();
 | 
						|
  }
 | 
						|
  virtual int  store(const char *to, size_t length,CHARSET_INFO *cs)=0;
 | 
						|
  /*
 | 
						|
    This is used by engines like CSV and Federated to signal the field
 | 
						|
    that the data is going to be in text (rather than binary) representation,
 | 
						|
    even if cs points to &my_charset_bin.
 | 
						|
 | 
						|
    If a Field distinguishes between text and binary formats (e.g. INET6),
 | 
						|
    we cannot call store(str,length,&my_charset_bin),
 | 
						|
    to avoid "field" mis-interpreting the data format as binary.
 | 
						|
  */
 | 
						|
  virtual int  store_text(const char *to, size_t length, CHARSET_INFO *cs)
 | 
						|
  {
 | 
						|
    return store(to, length, cs);
 | 
						|
  }
 | 
						|
  virtual int  store_binary(const char *to, size_t length)
 | 
						|
  {
 | 
						|
    return store(to, length, &my_charset_bin);
 | 
						|
  }
 | 
						|
  virtual int  store_hex_hybrid(const char *str, size_t length);
 | 
						|
  virtual int  store(double nr)=0;
 | 
						|
  virtual int  store(longlong nr, bool unsigned_val)=0;
 | 
						|
  virtual int  store_decimal(const my_decimal *d)=0;
 | 
						|
  virtual int  store_time_dec(const MYSQL_TIME *ltime, uint dec);
 | 
						|
  virtual int  store_timestamp_dec(const timeval &ts, uint dec);
 | 
						|
  int store_timestamp(my_time_t timestamp, ulong sec_part)
 | 
						|
  {
 | 
						|
    return store_timestamp_dec(Timeval(timestamp, sec_part),
 | 
						|
                               TIME_SECOND_PART_DIGITS);
 | 
						|
  }
 | 
						|
  /**
 | 
						|
    Store a value represented in native format
 | 
						|
  */
 | 
						|
  virtual int store_native(const Native &value)
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(0);
 | 
						|
    reset();
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
  int store_time(const MYSQL_TIME *ltime)
 | 
						|
  { return store_time_dec(ltime, TIME_SECOND_PART_DIGITS); }
 | 
						|
  int store(const char *to, size_t length, CHARSET_INFO *cs,
 | 
						|
            enum_check_fields check_level);
 | 
						|
  int store_text(const char *to, size_t length, CHARSET_INFO *cs,
 | 
						|
                 enum_check_fields check_level);
 | 
						|
  int store(const LEX_STRING *ls, CHARSET_INFO *cs)
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(ls->length < UINT_MAX32);
 | 
						|
    return store(ls->str, (uint) ls->length, cs);
 | 
						|
  }
 | 
						|
  int store(const LEX_CSTRING *ls, CHARSET_INFO *cs)
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(ls->length < UINT_MAX32);
 | 
						|
    return store(ls->str, (uint) ls->length, cs);
 | 
						|
  }
 | 
						|
  int store(const LEX_CSTRING &ls, CHARSET_INFO *cs)
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(ls.length < UINT_MAX32);
 | 
						|
    return store(ls.str, (uint) ls.length, cs);
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
    @brief
 | 
						|
      Store minimum/maximum value of a column in the statistics table.
 | 
						|
    @param
 | 
						|
      field                  statistical table field
 | 
						|
      str                    value buffer
 | 
						|
  */
 | 
						|
  virtual int store_to_statistical_minmax_field(Field *field, String *str);
 | 
						|
 | 
						|
  /*
 | 
						|
    @brief
 | 
						|
      Store minimum/maximum value of a column from the statistical table.
 | 
						|
    @param
 | 
						|
      field                  statistical table field
 | 
						|
      str                    value buffer
 | 
						|
  */
 | 
						|
  virtual int store_from_statistical_minmax_field(Field *field, String *str,
 | 
						|
                                                  MEM_ROOT *mem);
 | 
						|
 | 
						|
#ifdef HAVE_MEM_CHECK
 | 
						|
  /**
 | 
						|
    Mark unused memory in the field as defined. Mainly used to ensure
 | 
						|
    that if we write full field to disk (for example in
 | 
						|
    Count_distinct_field::add(), we don't write unitalized data to
 | 
						|
    disk which would confuse valgrind or MSAN.
 | 
						|
  */
 | 
						|
  virtual void mark_unused_memory_as_defined() {}
 | 
						|
#else
 | 
						|
  void mark_unused_memory_as_defined() {}
 | 
						|
#endif
 | 
						|
 | 
						|
  virtual double val_real()=0;
 | 
						|
  virtual longlong val_int()=0;
 | 
						|
  /*
 | 
						|
    Get ulonglong representation.
 | 
						|
    Negative values are truncated to 0.
 | 
						|
  */
 | 
						|
  virtual ulonglong val_uint(void)
 | 
						|
  {
 | 
						|
    longlong nr= val_int();
 | 
						|
    return nr < 0 ? 0 : (ulonglong) nr;
 | 
						|
  }
 | 
						|
  virtual bool val_bool()= 0;
 | 
						|
  virtual my_decimal *val_decimal(my_decimal *)=0;
 | 
						|
  inline String *val_str(String *str) { return val_str(str, str); }
 | 
						|
  /*
 | 
						|
     val_str(buf1, buf2) gets two buffers and should use them as follows:
 | 
						|
     if it needs a temp buffer to convert result to string - use buf1
 | 
						|
       example Field_tiny::val_str()
 | 
						|
     if the value exists as a string already - use buf2
 | 
						|
       example Field_string::val_str()
 | 
						|
     consequently, buf2 may be created as 'String buf;' - no memory
 | 
						|
     will be allocated for it. buf1 will be allocated to hold a
 | 
						|
     value if it's too small. Using allocated buffer for buf2 may result in
 | 
						|
     an unnecessary free (and later, may be an alloc).
 | 
						|
     This trickery is used to decrease a number of malloc calls.
 | 
						|
  */
 | 
						|
  virtual String *val_str(String*,String *)=0;
 | 
						|
  virtual bool val_native(Native *to)
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(!is_null());
 | 
						|
    return to->copy((const char *) ptr, pack_length());
 | 
						|
  }
 | 
						|
  String *val_int_as_str(String *val_buffer, bool unsigned_flag);
 | 
						|
  /*
 | 
						|
    Return the field value as a LEX_CSTRING, without padding to full length
 | 
						|
    (MODE_PAD_CHAR_TO_FULL_LENGTH is temporarily suppressed during the call).
 | 
						|
 | 
						|
    In case of an empty value, to[0] is assigned to empty_clex_string,
 | 
						|
    memory is not allocated.
 | 
						|
    In case of a non-empty value, the memory is allocated on mem_root.
 | 
						|
    In case of a memory allocation failure, to[0] is assigned to {NULL,0}.
 | 
						|
 | 
						|
    @param  [IN] mem_root  store non-empty values here
 | 
						|
    @param  [OUT to        return the string here
 | 
						|
    @retval                false (success)
 | 
						|
    @retval                true  (EOM)
 | 
						|
  */
 | 
						|
  bool val_str_nopad(MEM_ROOT *mem_root, LEX_CSTRING *to);
 | 
						|
  fast_field_copier get_fast_field_copier(const Field *from);
 | 
						|
  /*
 | 
						|
   str_needs_quotes() returns TRUE if the value returned by val_str() needs
 | 
						|
   to be quoted when used in constructing an SQL query.
 | 
						|
  */
 | 
						|
  virtual bool str_needs_quotes() const { return false; }
 | 
						|
  const Type_handler *type_handler_for_comparison() const
 | 
						|
  {
 | 
						|
    return type_handler()->type_handler_for_comparison();
 | 
						|
  }
 | 
						|
  Item_result result_type () const
 | 
						|
  {
 | 
						|
    return type_handler()->result_type();
 | 
						|
  }
 | 
						|
  Item_result cmp_type () const
 | 
						|
  {
 | 
						|
    return type_handler()->cmp_type();
 | 
						|
  }
 | 
						|
  virtual bool eq(Field *field)
 | 
						|
  {
 | 
						|
    return (ptr == field->ptr && null_ptr == field->null_ptr &&
 | 
						|
            null_bit == field->null_bit && field->type() == type());
 | 
						|
  }
 | 
						|
  virtual bool eq_def(const Field *field) const;
 | 
						|
  
 | 
						|
  /*
 | 
						|
    pack_length() returns size (in bytes) used to store field data in memory
 | 
						|
    (i.e. it returns the maximum size of the field in a row of the table,
 | 
						|
    which is located in RAM).
 | 
						|
  */
 | 
						|
  virtual uint32 pack_length() const { return (uint32) field_length; }
 | 
						|
 | 
						|
  /*
 | 
						|
    pack_length_in_rec() returns size (in bytes) used to store field data on
 | 
						|
    storage (i.e. it returns the maximal size of the field in a row of the
 | 
						|
    table, which is located on disk).
 | 
						|
  */
 | 
						|
  virtual uint32 pack_length_in_rec() const { return pack_length(); }
 | 
						|
  virtual bool compatible_field_size(uint metadata, const Relay_log_info *rli,
 | 
						|
                                     uint16 mflags, int *order) const;
 | 
						|
  virtual uint pack_length_from_metadata(uint field_metadata) const
 | 
						|
  {
 | 
						|
    DBUG_ENTER("Field::pack_length_from_metadata");
 | 
						|
    DBUG_RETURN(field_metadata);
 | 
						|
  }
 | 
						|
  virtual uint row_pack_length() const { return 0; }
 | 
						|
 | 
						|
  /*
 | 
						|
    data_length() return the "real size" of the data in memory.
 | 
						|
  */
 | 
						|
  virtual uint32 data_length() { return pack_length(); }
 | 
						|
  virtual uint32 sort_length() const { return pack_length(); }
 | 
						|
 | 
						|
  /*
 | 
						|
    sort_suffix_length() return the length bytes needed to store the length
 | 
						|
    for binary charset
 | 
						|
  */
 | 
						|
  virtual uint32 sort_suffix_length() const { return 0; }
 | 
						|
 | 
						|
  /* 
 | 
						|
    Get the number bytes occupied by the value in the field.
 | 
						|
    CHAR values are stripped of trailing spaces.
 | 
						|
    Flexible values are stripped of their length.
 | 
						|
  */
 | 
						|
  virtual uint32 value_length()
 | 
						|
  {
 | 
						|
    uint len;
 | 
						|
    if (!zero_pack() &&
 | 
						|
	(type() == MYSQL_TYPE_STRING &&
 | 
						|
        (len= pack_length()) >= 4 && len < 256))
 | 
						|
    {
 | 
						|
      uchar *str, *end;
 | 
						|
      for (str= ptr, end= str+len; end > str && end[-1] == ' '; end--) {}
 | 
						|
      len=(uint) (end-str); 
 | 
						|
      return len;
 | 
						|
    } 
 | 
						|
    return data_length();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
     Get the maximum size of the data in packed format.
 | 
						|
 | 
						|
     @return Maximum data length of the field when packed using the
 | 
						|
     Field::pack() function.
 | 
						|
   */
 | 
						|
  virtual uint32 max_data_length() const {
 | 
						|
    return pack_length();
 | 
						|
  };
 | 
						|
 | 
						|
  virtual int reset() { bzero(ptr,pack_length()); return 0; }
 | 
						|
  virtual void reset_fields() {}
 | 
						|
  const uchar *ptr_in_record(const uchar *record) const
 | 
						|
  {
 | 
						|
    my_ptrdiff_t l_offset= (my_ptrdiff_t) (ptr -  table->record[0]);
 | 
						|
    DBUG_ASSERT(l_offset >= 0 && table->s->rec_buff_length - l_offset > 0);
 | 
						|
    return record + l_offset;
 | 
						|
  }
 | 
						|
  virtual int set_default();
 | 
						|
 | 
						|
  bool has_update_default_function() const
 | 
						|
  {
 | 
						|
    return flags & ON_UPDATE_NOW_FLAG;
 | 
						|
  }
 | 
						|
  bool has_default_now_unireg_check() const
 | 
						|
  {
 | 
						|
    return unireg_check == TIMESTAMP_DN_FIELD
 | 
						|
        || unireg_check == TIMESTAMP_DNUN_FIELD;
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
    Mark the field as having a value supplied by the client, thus it should
 | 
						|
    not be auto-updated.
 | 
						|
  */
 | 
						|
  void set_has_explicit_value()
 | 
						|
  {
 | 
						|
    bitmap_set_bit(&table->has_value_set, field_index);
 | 
						|
  }
 | 
						|
  bool has_explicit_value()
 | 
						|
  {
 | 
						|
    return bitmap_is_set(&table->has_value_set, field_index);
 | 
						|
  }
 | 
						|
  void clear_has_explicit_value()
 | 
						|
  {
 | 
						|
    bitmap_clear_bit(&table->has_value_set, field_index);
 | 
						|
  }
 | 
						|
 | 
						|
  virtual my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const
 | 
						|
  { DBUG_ASSERT(0); return 0; }
 | 
						|
  my_time_t get_timestamp(ulong *sec_part) const
 | 
						|
  {
 | 
						|
    return get_timestamp(ptr, sec_part);
 | 
						|
  }
 | 
						|
 | 
						|
  virtual bool binary() const { return 1; }
 | 
						|
  virtual bool zero_pack() const { return 1; }
 | 
						|
  virtual enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
 | 
						|
  virtual uint16 key_part_flag() const { return 0; }
 | 
						|
  virtual uint16 key_part_length_bytes() const { return 0; }
 | 
						|
  virtual uint32 key_length() const { return pack_length(); }
 | 
						|
  virtual const Type_handler *type_handler() const = 0;
 | 
						|
  virtual enum_field_types type() const
 | 
						|
  {
 | 
						|
    return type_handler()->field_type();
 | 
						|
  }
 | 
						|
  virtual enum_field_types real_type() const
 | 
						|
  {
 | 
						|
    return type_handler()->real_field_type();
 | 
						|
  }
 | 
						|
  virtual enum_field_types binlog_type() const
 | 
						|
  {
 | 
						|
    /*
 | 
						|
      Binlog stores field->type() as type code by default. For example,
 | 
						|
      it puts MYSQL_TYPE_STRING in case of CHAR, VARCHAR, SET and ENUM,
 | 
						|
      with extra data type details put into metadata.
 | 
						|
 | 
						|
      Binlog behaviour slightly differs between various MySQL and MariaDB
 | 
						|
      versions for the temporal data types TIME, DATETIME and TIMESTAMP.
 | 
						|
 | 
						|
      MySQL prior to 5.6 uses MYSQL_TYPE_TIME, MYSQL_TYPE_DATETIME 
 | 
						|
      and MYSQL_TYPE_TIMESTAMP type codes in binlog and stores no 
 | 
						|
      additional metadata.
 | 
						|
 | 
						|
      MariaDB-5.3 implements new versions for TIME, DATATIME, TIMESTAMP
 | 
						|
      with fractional second precision, but uses the old format for the
 | 
						|
      types TIME(0), DATETIME(0), TIMESTAMP(0), and it still stores
 | 
						|
      MYSQL_TYPE_TIME, MYSQL_TYPE_DATETIME and MYSQL_TYPE_TIMESTAMP in binlog,
 | 
						|
      with no additional metadata.
 | 
						|
      So row-based replication between temporal data types of
 | 
						|
      different precision is not possible in MariaDB.
 | 
						|
 | 
						|
      MySQL-5.6 also implements a new version of TIME, DATETIME, TIMESTAMP
 | 
						|
      which support fractional second precision 0..6, and use the new
 | 
						|
      format even for the types TIME(0), DATETIME(0), TIMESTAMP(0).
 | 
						|
      For these new data types, MySQL-5.6 stores new type codes 
 | 
						|
      MYSQL_TYPE_TIME2, MYSQL_TYPE_DATETIME2, MYSQL_TYPE_TIMESTAMP2 in binlog,
 | 
						|
      with fractional precision 0..6 put into metadata.
 | 
						|
      This makes it in theory possible to do row-based replication between
 | 
						|
      columns of different fractional precision (e.g. from TIME(1) on master
 | 
						|
      to TIME(6) on slave). However, it's not currently fully implemented yet.
 | 
						|
      MySQL-5.6 can only do row-based replication from the old types
 | 
						|
      TIME, DATETIME, TIMESTAMP (represented by MYSQL_TYPE_TIME,
 | 
						|
      MYSQL_TYPE_DATETIME and MYSQL_TYPE_TIMESTAMP type codes in binlog)
 | 
						|
      to the new corresponding types TIME(0), DATETIME(0), TIMESTAMP(0).
 | 
						|
 | 
						|
      Note: MariaDB starting from the version 10.0 understands the new
 | 
						|
      MySQL-5.6 type codes MYSQL_TYPE_TIME2, MYSQL_TYPE_DATETIME2,
 | 
						|
      MYSQL_TYPE_TIMESTAMP2. When started over MySQL-5.6 tables both on
 | 
						|
      master and on slave, MariaDB-10.0 can also do row-based replication
 | 
						|
      from the old types TIME, DATETIME, TIMESTAMP to the new MySQL-5.6
 | 
						|
      types TIME(0), DATETIME(0), TIMESTAMP(0).
 | 
						|
 | 
						|
      Note: perhaps binlog should eventually be modified to store
 | 
						|
      real_type() instead of type() for all column types.
 | 
						|
    */
 | 
						|
    return type();
 | 
						|
  }
 | 
						|
  virtual Binlog_type_info binlog_type_info() const
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(Field::type() == binlog_type());
 | 
						|
    return Binlog_type_info(Field::type(), 0, 0);
 | 
						|
  }
 | 
						|
  virtual en_fieldtype tmp_engine_column_type(bool use_packed_rows) const
 | 
						|
  {
 | 
						|
    return FIELD_NORMAL;
 | 
						|
  }
 | 
						|
  /*
 | 
						|
    Conversion type for from the source to the current field.
 | 
						|
  */
 | 
						|
  virtual enum_conv_type rpl_conv_type_from(const Conv_source &source,
 | 
						|
                                            const Relay_log_info *rli,
 | 
						|
                                            const Conv_param ¶m)
 | 
						|
                                            const= 0;
 | 
						|
  enum_conv_type rpl_conv_type_from_same_data_type(uint16 metadata,
 | 
						|
                                                   const Relay_log_info *rli,
 | 
						|
                                                   const Conv_param ¶m)
 | 
						|
                                                   const;
 | 
						|
  inline  int cmp(const uchar *str) const { return cmp(ptr,str); }
 | 
						|
  /*
 | 
						|
    The following method is used for comparing prefix keys.
 | 
						|
    Currently it's only used in partitioning.
 | 
						|
  */
 | 
						|
  virtual int cmp_prefix(const uchar *a, const uchar *b,
 | 
						|
                         size_t prefix_char_len) const
 | 
						|
  { return cmp(a, b); }
 | 
						|
  virtual int cmp(const uchar *,const uchar *) const=0;
 | 
						|
  virtual int cmp_binary(const uchar *a,const uchar *b, uint32 max_length=~0U) const
 | 
						|
  { return memcmp(a,b,pack_length()); }
 | 
						|
  virtual int cmp_offset(my_ptrdiff_t row_offset)
 | 
						|
  { return cmp(ptr,ptr+row_offset); }
 | 
						|
  virtual int cmp_binary_offset(uint row_offset)
 | 
						|
  { return cmp_binary(ptr, ptr+row_offset); };
 | 
						|
  virtual int key_cmp(const uchar *a,const uchar *b) const
 | 
						|
  { return cmp(a, b); }
 | 
						|
  virtual int key_cmp(const uchar *str, uint length) const
 | 
						|
  { return cmp(ptr,str); }
 | 
						|
  /*
 | 
						|
    Update the value m of the 'min_val' field with the current value v
 | 
						|
    of this field if force_update is set to TRUE or if v < m.
 | 
						|
    Return TRUE if the value has been updated.
 | 
						|
  */  
 | 
						|
  virtual bool update_min(Field *min_val, bool force_update)
 | 
						|
  { 
 | 
						|
    bool update_fl= force_update || cmp(ptr, min_val->ptr) < 0;
 | 
						|
    if (update_fl)
 | 
						|
    {
 | 
						|
      min_val->set_notnull();
 | 
						|
      memcpy(min_val->ptr, ptr, pack_length());
 | 
						|
    }
 | 
						|
    return update_fl;
 | 
						|
  }
 | 
						|
  /*
 | 
						|
    Update the value m of the 'max_val' field with the current value v
 | 
						|
    of this field if force_update is set to TRUE or if v > m.
 | 
						|
    Return TRUE if the value has been updated.
 | 
						|
  */  
 | 
						|
  virtual bool update_max(Field *max_val, bool force_update)
 | 
						|
  { 
 | 
						|
    bool update_fl= force_update || cmp(ptr, max_val->ptr) > 0;
 | 
						|
    if (update_fl)
 | 
						|
    {
 | 
						|
      max_val->set_notnull();
 | 
						|
      memcpy(max_val->ptr, ptr, pack_length());
 | 
						|
    }
 | 
						|
    return update_fl;
 | 
						|
  }
 | 
						|
  virtual void store_field_value(uchar *val, uint len)
 | 
						|
  {
 | 
						|
     memcpy(ptr, val, len);
 | 
						|
  }
 | 
						|
  virtual decimal_digits_t decimals() const { return 0; }
 | 
						|
  virtual Information_schema_numeric_attributes
 | 
						|
            information_schema_numeric_attributes() const
 | 
						|
  {
 | 
						|
    return Information_schema_numeric_attributes();
 | 
						|
  }
 | 
						|
  virtual Information_schema_character_attributes
 | 
						|
            information_schema_character_attributes() const
 | 
						|
  {
 | 
						|
    return Information_schema_character_attributes();
 | 
						|
  }
 | 
						|
  virtual void update_data_type_statistics(Data_type_statistics *st) const
 | 
						|
  { }
 | 
						|
  /*
 | 
						|
    Caller beware: sql_type can change str.Ptr, so check
 | 
						|
    ptr() to see if it changed if you are using your own buffer
 | 
						|
    in str and restore it with set() if needed
 | 
						|
  */
 | 
						|
  virtual void sql_type(String &str) const =0;
 | 
						|
  virtual void sql_rpl_type(String *str) const { sql_type(*str); }
 | 
						|
  virtual uint size_of() const =0;		// For new field
 | 
						|
  inline bool is_null(my_ptrdiff_t row_offset= 0) const
 | 
						|
  {
 | 
						|
    /*
 | 
						|
      The table may have been marked as containing only NULL values
 | 
						|
      for all fields if it is a NULL-complemented row of an OUTER JOIN
 | 
						|
      or if the query is an implicitly grouped query (has aggregate
 | 
						|
      functions but no GROUP BY clause) with no qualifying rows. If
 | 
						|
      this is the case (in which TABLE::null_row is true), the field
 | 
						|
      is considered to be NULL.
 | 
						|
 | 
						|
      Note that if a table->null_row is set then also all null_bits are
 | 
						|
      set for the row.
 | 
						|
 | 
						|
      In the case of the 'result_field' for GROUP BY, table->null_row might
 | 
						|
      refer to the *next* row in the table (when the algorithm is: read the
 | 
						|
      next row, see if any of group column values have changed, send the
 | 
						|
      result - grouped - row to the client if yes). So, table->null_row might
 | 
						|
      be wrong, but such a result_field is always nullable (that's defined by
 | 
						|
      original_field->maybe_null()) and we trust its null bit.
 | 
						|
    */
 | 
						|
    return null_ptr ? null_ptr[row_offset] & null_bit : table->null_row;
 | 
						|
  }
 | 
						|
  inline bool is_real_null(my_ptrdiff_t row_offset= 0) const
 | 
						|
    { return null_ptr && (null_ptr[row_offset] & null_bit); }
 | 
						|
  inline bool is_null_in_record(const uchar *record) const
 | 
						|
  {
 | 
						|
    if (maybe_null_in_table())
 | 
						|
      return record[(uint) (null_ptr - table->record[0])] & null_bit;
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
  inline void set_null(my_ptrdiff_t row_offset= 0)
 | 
						|
    { if (null_ptr) null_ptr[row_offset]|= null_bit; }
 | 
						|
  inline void set_notnull(my_ptrdiff_t row_offset= 0)
 | 
						|
    { if (null_ptr) null_ptr[row_offset]&= (uchar) ~null_bit; }
 | 
						|
  inline bool maybe_null(void) const
 | 
						|
  { return null_ptr != 0 || table->maybe_null; }
 | 
						|
  // Set to NULL on LOAD DATA or LOAD XML
 | 
						|
  virtual bool load_data_set_null(THD *thd);
 | 
						|
  // Reset when a LOAD DATA file ended unexpectedly
 | 
						|
  virtual bool load_data_set_no_data(THD *thd, bool fixed_format);
 | 
						|
  void load_data_set_value(const char *pos, uint length, CHARSET_INFO *cs);
 | 
						|
 | 
						|
  /* @return true if this field is NULL-able (even if temporarily) */
 | 
						|
  inline bool real_maybe_null() const { return null_ptr != 0; }
 | 
						|
  uint null_offset(const uchar *record) const
 | 
						|
  { return (uint) (null_ptr - record); }
 | 
						|
  /*
 | 
						|
    For a NULL-able field (that can actually store a NULL value in a table)
 | 
						|
    null_ptr points to the "null bitmap" in the table->record[0] header. For
 | 
						|
    NOT NULL fields it is either 0 or points outside table->record[0] into the
 | 
						|
    table->triggers->extra_null_bitmap (so that the field can store a NULL
 | 
						|
    value temporarily, only in memory)
 | 
						|
  */
 | 
						|
  bool maybe_null_in_table() const
 | 
						|
  { return null_ptr >= table->record[0] && null_ptr <= ptr; }
 | 
						|
 | 
						|
  uint null_offset() const
 | 
						|
  { return null_offset(table->record[0]); }
 | 
						|
  void set_null_ptr(uchar *p_null_ptr, uint p_null_bit)
 | 
						|
  {
 | 
						|
    null_ptr= p_null_ptr;
 | 
						|
    null_bit= static_cast<uchar>(p_null_bit);
 | 
						|
  }
 | 
						|
 | 
						|
  bool stored_in_db() const { return !vcol_info || vcol_info->stored_in_db; }
 | 
						|
  bool check_vcol_sql_mode_dependency(THD *, vcol_init_mode mode) const;
 | 
						|
 | 
						|
  virtual sql_mode_t value_depends_on_sql_mode() const
 | 
						|
  {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
  virtual sql_mode_t conversion_depends_on_sql_mode(THD *thd,
 | 
						|
                                                    Item *expr) const
 | 
						|
  {
 | 
						|
    return (sql_mode_t) 0;
 | 
						|
  }
 | 
						|
  virtual sql_mode_t can_handle_sql_mode_dependency_on_store() const
 | 
						|
  {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  inline THD *get_thd() const
 | 
						|
  { return likely(table) ? table->in_use : current_thd; }
 | 
						|
 | 
						|
  enum {
 | 
						|
    LAST_NULL_BYTE_UNDEF= 0
 | 
						|
  };
 | 
						|
 | 
						|
  /*
 | 
						|
    Find the position of the last null byte for the field.
 | 
						|
 | 
						|
    SYNOPSIS
 | 
						|
      last_null_byte()
 | 
						|
 | 
						|
    DESCRIPTION
 | 
						|
      Return a pointer to the last byte of the null bytes where the
 | 
						|
      field conceptually is placed.
 | 
						|
 | 
						|
    RETURN VALUE
 | 
						|
      The position of the last null byte relative to the beginning of
 | 
						|
      the record. If the field does not use any bits of the null
 | 
						|
      bytes, the value 0 (LAST_NULL_BYTE_UNDEF) is returned.
 | 
						|
   */
 | 
						|
  size_t last_null_byte() const {
 | 
						|
    size_t bytes= do_last_null_byte();
 | 
						|
    DBUG_PRINT("debug", ("last_null_byte() ==> %ld", (long) bytes));
 | 
						|
    DBUG_ASSERT(bytes <= table->s->null_bytes);
 | 
						|
    return bytes;
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
    Create mem-comparable sort key part for a sort key
 | 
						|
  */
 | 
						|
  void make_sort_key_part(uchar *buff, uint length);
 | 
						|
 | 
						|
  /*
 | 
						|
    create a compact sort key which can be compared with a comparison
 | 
						|
    function. They are called packed sort keys
 | 
						|
  */
 | 
						|
  virtual uint make_packed_sort_key_part(uchar *buff,
 | 
						|
                                         const SORT_FIELD_ATTR *sort_field);
 | 
						|
 | 
						|
  virtual void make_send_field(Send_field *);
 | 
						|
 | 
						|
  /*
 | 
						|
    Some implementations actually may write up to 8 bytes regardless of what
 | 
						|
    size was requested. This is due to the minimum value of the system variable
 | 
						|
    max_sort_length.
 | 
						|
  */
 | 
						|
 | 
						|
  virtual void sort_string(uchar *buff,uint length)=0;
 | 
						|
  virtual bool optimize_range(uint idx, uint part) const;
 | 
						|
  virtual void free() {}
 | 
						|
  virtual Field *make_new_field(MEM_ROOT *root, TABLE *new_table,
 | 
						|
                                bool keep_type);
 | 
						|
  virtual Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
 | 
						|
                               uchar *new_ptr, uint32 length,
 | 
						|
                               uchar *new_null_ptr, uint new_null_bit);
 | 
						|
  Field *create_tmp_field(MEM_ROOT *root, TABLE *new_table,
 | 
						|
                          bool maybe_null_arg);
 | 
						|
  Field *create_tmp_field(MEM_ROOT *root, TABLE *new_table)
 | 
						|
  {
 | 
						|
    return create_tmp_field(root, new_table, maybe_null());
 | 
						|
  }
 | 
						|
  Field *clone(MEM_ROOT *mem_root, TABLE *new_table);
 | 
						|
  Field *clone(MEM_ROOT *mem_root, TABLE *new_table, my_ptrdiff_t diff);
 | 
						|
  inline void move_field(uchar *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg)
 | 
						|
  {
 | 
						|
    ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg;
 | 
						|
  }
 | 
						|
  inline void move_field(uchar *ptr_arg) { ptr=ptr_arg; }
 | 
						|
  inline uchar *record_ptr() // record[0] or wherever the field was moved to
 | 
						|
  {
 | 
						|
    my_ptrdiff_t offset= table->s->field[field_index]->ptr - table->s->default_values;
 | 
						|
    return ptr - offset;
 | 
						|
  }
 | 
						|
  virtual void move_field_offset(my_ptrdiff_t ptr_diff)
 | 
						|
  {
 | 
						|
    ptr=ADD_TO_PTR(ptr,ptr_diff, uchar*);
 | 
						|
    if (null_ptr)
 | 
						|
      null_ptr=ADD_TO_PTR(null_ptr,ptr_diff,uchar*);
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
    Copy the Field's value to buff. The value will be in table->record[]
 | 
						|
    format.
 | 
						|
  */
 | 
						|
  void get_image(uchar *buff, uint length, CHARSET_INFO *cs) const
 | 
						|
  { get_image(buff, length, ptr, cs); }
 | 
						|
  virtual void get_image(uchar *buff, uint length,
 | 
						|
                         const uchar *ptr_arg, CHARSET_INFO *cs) const
 | 
						|
    { memcpy(buff,ptr_arg,length); }
 | 
						|
 | 
						|
  /*
 | 
						|
    Set Field's value to the value in *buf.
 | 
						|
  */
 | 
						|
  virtual void set_image(const uchar *buff,uint length, CHARSET_INFO *cs)
 | 
						|
    { memcpy(ptr,buff,length); }
 | 
						|
 | 
						|
 | 
						|
  /*
 | 
						|
    Copy a field part into an output buffer.
 | 
						|
 | 
						|
    SYNOPSIS
 | 
						|
      Field::get_key_image()
 | 
						|
      buff   [out] output buffer
 | 
						|
      length       output buffer size
 | 
						|
      type         itMBR for geometry blobs, otherwise itRAW
 | 
						|
 | 
						|
    DESCRIPTION
 | 
						|
      This function makes a copy of field part of size equal to or
 | 
						|
      less than "length" parameter value.
 | 
						|
      For fields of string types (CHAR, VARCHAR, TEXT) the rest of buffer
 | 
						|
      is padded by zero byte.
 | 
						|
 | 
						|
    NOTES
 | 
						|
      For variable length character fields (i.e. UTF-8) the "length"
 | 
						|
      parameter means a number of output buffer bytes as if all field
 | 
						|
      characters have maximal possible size (mbmaxlen). In the other words,
 | 
						|
      "length" parameter is a number of characters multiplied by
 | 
						|
      field_charset->mbmaxlen.
 | 
						|
 | 
						|
    RETURN
 | 
						|
      Number of copied bytes (excluding padded zero bytes -- see above).
 | 
						|
  */
 | 
						|
 | 
						|
  uint get_key_image(uchar *buff, uint length, imagetype type_arg) const
 | 
						|
  { return get_key_image(buff, length, ptr, type_arg); }
 | 
						|
  virtual uint get_key_image(uchar *buff, uint length, const uchar *ptr_arg, imagetype type_arg) const
 | 
						|
  {
 | 
						|
    get_image(buff, length, ptr_arg, &my_charset_bin);
 | 
						|
    return length;
 | 
						|
  }
 | 
						|
  virtual void set_key_image(const uchar *buff,uint length)
 | 
						|
    { set_image(buff,length, &my_charset_bin); }
 | 
						|
  inline longlong val_int_offset(uint row_offset)
 | 
						|
    {
 | 
						|
      ptr+=row_offset;
 | 
						|
      longlong tmp=val_int();
 | 
						|
      ptr-=row_offset;
 | 
						|
      return tmp;
 | 
						|
    }
 | 
						|
  inline longlong val_int(const uchar *new_ptr)
 | 
						|
  {
 | 
						|
    uchar *old_ptr= ptr;
 | 
						|
    longlong return_value;
 | 
						|
    ptr= (uchar*) new_ptr;
 | 
						|
    return_value= val_int();
 | 
						|
    ptr= old_ptr;
 | 
						|
    return return_value;
 | 
						|
  }
 | 
						|
  inline String *val_str(String *str, const uchar *new_ptr)
 | 
						|
  {
 | 
						|
    uchar *old_ptr= ptr;
 | 
						|
    ptr= (uchar*) new_ptr;
 | 
						|
    val_str(str);
 | 
						|
    ptr= old_ptr;
 | 
						|
    return str;
 | 
						|
  }
 | 
						|
  virtual bool send(Protocol *protocol);
 | 
						|
 | 
						|
  virtual uchar *pack(uchar *to, const uchar *from, uint max_length);
 | 
						|
  /**
 | 
						|
     @overload Field::pack(uchar*, const uchar*, uint, bool)
 | 
						|
  */
 | 
						|
  uchar *pack(uchar *to, const uchar *from)
 | 
						|
  {
 | 
						|
    DBUG_ENTER("Field::pack");
 | 
						|
    uchar *result= this->pack(to, from, UINT_MAX);
 | 
						|
    DBUG_RETURN(result);
 | 
						|
  }
 | 
						|
 | 
						|
  virtual const uchar *unpack(uchar* to, const uchar *from,
 | 
						|
                              const uchar *from_end, uint param_data=0);
 | 
						|
 | 
						|
  virtual uint packed_col_length(const uchar *to, uint length)
 | 
						|
  { return length;}
 | 
						|
  virtual uint max_packed_col_length(uint max_length)
 | 
						|
  { return max_length;}
 | 
						|
  virtual bool is_packable() const { return false; }
 | 
						|
 | 
						|
  uint offset(const uchar *record) const
 | 
						|
  {
 | 
						|
    return (uint) (ptr - record);
 | 
						|
  }
 | 
						|
  void copy_from_tmp(int offset);
 | 
						|
  uint fill_cache_field(struct st_cache_field *copy);
 | 
						|
  virtual bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate);
 | 
						|
  virtual longlong val_datetime_packed(THD *thd);
 | 
						|
  virtual longlong val_time_packed(THD *thd);
 | 
						|
  virtual const TYPELIB *get_typelib() const { return NULL; }
 | 
						|
  virtual CHARSET_INFO *charset() const= 0;
 | 
						|
  /* returns TRUE if the new charset differs. */
 | 
						|
  virtual void change_charset(const DTCollation &new_cs) {}
 | 
						|
  virtual const DTCollation &dtcollation() const= 0;
 | 
						|
  virtual CHARSET_INFO *charset_for_protocol(void) const
 | 
						|
  { return binary() ? &my_charset_bin : charset(); }
 | 
						|
  virtual CHARSET_INFO *sort_charset(void) const { return charset(); }
 | 
						|
  virtual bool has_charset(void) const { return FALSE; }
 | 
						|
  virtual int set_time() { return 1; }
 | 
						|
  bool set_warning(Sql_condition::enum_warning_level, unsigned int code,
 | 
						|
                   int cuted_increment, ulong current_row=0) const;
 | 
						|
  virtual void print_key_value(String *out, uint32 length);
 | 
						|
  void print_key_part_value(String *out, const uchar *key, uint32 length);
 | 
						|
  void print_key_value_binary(String *out, const uchar* key, uint32 length);
 | 
						|
  void raise_note_cannot_use_key_part(THD *thd, uint keynr, uint part,
 | 
						|
                                      const LEX_CSTRING &op,
 | 
						|
                                      CHARSET_INFO *op_collation,
 | 
						|
                                      Item *value,
 | 
						|
                                      const Data_type_compatibility reason)
 | 
						|
                                      const;
 | 
						|
  void raise_note_key_become_unused(THD *thd, const String &expr) const;
 | 
						|
protected:
 | 
						|
  bool set_warning(unsigned int code, int cuted_increment) const
 | 
						|
  {
 | 
						|
    return set_warning(Sql_condition::WARN_LEVEL_WARN, code, cuted_increment);
 | 
						|
  }
 | 
						|
  bool set_note(unsigned int code, int cuted_increment) const
 | 
						|
  {
 | 
						|
    return set_warning(Sql_condition::WARN_LEVEL_NOTE, code, cuted_increment);
 | 
						|
  }
 | 
						|
  void set_datetime_warning(Sql_condition::enum_warning_level, uint code,
 | 
						|
                            const ErrConv *str, const char *typestr,
 | 
						|
                            int cuted_increment) const;
 | 
						|
  void set_datetime_warning(uint code,
 | 
						|
                            const ErrConv *str, const char *typestr,
 | 
						|
                            int cuted_increment) const
 | 
						|
  {
 | 
						|
    set_datetime_warning(Sql_condition::WARN_LEVEL_WARN, code, str, typestr,
 | 
						|
                         cuted_increment);
 | 
						|
  }
 | 
						|
  void set_warning_truncated_wrong_value(const char *type, const char *value);
 | 
						|
  inline bool check_overflow(int op_result)
 | 
						|
  {
 | 
						|
    return (op_result == E_DEC_OVERFLOW);
 | 
						|
  }
 | 
						|
  int warn_if_overflow(int op_result);
 | 
						|
  Copy_func *get_identical_copy_func() const;
 | 
						|
  bool cmp_is_done_using_type_handler_of_this(const Item_bool_func *cond,
 | 
						|
                                              const Item *item) const;
 | 
						|
  Data_type_compatibility can_optimize_scalar_range(
 | 
						|
                                 const RANGE_OPT_PARAM *param,
 | 
						|
                                 const KEY_PART *key_part,
 | 
						|
                                 const Item_bool_func *cond,
 | 
						|
                                 scalar_comparison_op op,
 | 
						|
                                 Item *value) const;
 | 
						|
  uchar *make_key_image(MEM_ROOT *mem_root, const KEY_PART *key_part);
 | 
						|
  SEL_ARG *get_mm_leaf_int(RANGE_OPT_PARAM *param, KEY_PART *key_part,
 | 
						|
                           const Item_bool_func *cond,
 | 
						|
                           scalar_comparison_op op, Item *value,
 | 
						|
                           bool unsigned_field);
 | 
						|
  /*
 | 
						|
    Make a leaf tree for the cases when the value was stored
 | 
						|
    to the field exactly, without any truncation, rounding or adjustments.
 | 
						|
    For example, if we stored an INT value into an INT column,
 | 
						|
    and value->save_in_field_no_warnings() returned 0,
 | 
						|
    we know that the value was stored exactly.
 | 
						|
  */
 | 
						|
  SEL_ARG *stored_field_make_mm_leaf_exact(RANGE_OPT_PARAM *param,
 | 
						|
                                           KEY_PART *key_part,
 | 
						|
                                           scalar_comparison_op op,
 | 
						|
                                           Item *value);
 | 
						|
  /*
 | 
						|
    Make a leaf tree for the cases when we don't know if
 | 
						|
    the value was stored to the field without any data loss,
 | 
						|
    or was modified to a smaller or a greater value.
 | 
						|
    Used for the data types whose methods Field::store*()
 | 
						|
    silently adjust the value. This is the most typical case.
 | 
						|
  */
 | 
						|
  SEL_ARG *stored_field_make_mm_leaf(RANGE_OPT_PARAM *param,
 | 
						|
                                     KEY_PART *key_part,
 | 
						|
                                     scalar_comparison_op op, Item *value);
 | 
						|
  /*
 | 
						|
    Make a leaf tree when an INT value was stored into a field of INT type,
 | 
						|
    and some truncation happened. Tries to adjust the range search condition
 | 
						|
    when possible, e.g. "tinytint < 300" -> "tinyint <= 127".
 | 
						|
    Can also return SEL_ARG_IMPOSSIBLE(), and NULL (not sargable).
 | 
						|
  */
 | 
						|
  SEL_ARG *stored_field_make_mm_leaf_bounded_int(RANGE_OPT_PARAM *param,
 | 
						|
                                                 KEY_PART *key_part,
 | 
						|
                                                 scalar_comparison_op op,
 | 
						|
                                                 Item *value,
 | 
						|
                                                 bool unsigned_field);
 | 
						|
  /*
 | 
						|
    Make a leaf tree when some truncation happened during
 | 
						|
    value->save_in_field_no_warning(this), and we cannot yet adjust the range
 | 
						|
    search condition for the current combination of the field and the value
 | 
						|
    data types.
 | 
						|
    Returns SEL_ARG_IMPOSSIBLE() for "=" and "<=>".
 | 
						|
    Returns NULL (not sargable) for other comparison operations.
 | 
						|
  */
 | 
						|
  SEL_ARG *stored_field_make_mm_leaf_truncated(RANGE_OPT_PARAM *prm,
 | 
						|
                                               scalar_comparison_op,
 | 
						|
                                               Item *value);
 | 
						|
public:
 | 
						|
  void set_table_name(String *alias)
 | 
						|
  {
 | 
						|
    table_name= &alias->Ptr;
 | 
						|
  }
 | 
						|
  void init(TABLE *table_arg)
 | 
						|
  {
 | 
						|
    orig_table= table= table_arg;
 | 
						|
    set_table_name(&table_arg->alias);
 | 
						|
  }
 | 
						|
  virtual void init_for_tmp_table(Field *org_field, TABLE *new_table)
 | 
						|
  {
 | 
						|
    init(new_table);
 | 
						|
    orig_table= org_field->orig_table;
 | 
						|
    vcol_info= 0;
 | 
						|
    cond_selectivity= 1.0;
 | 
						|
    next_equal_field= NULL;
 | 
						|
    option_list= NULL;
 | 
						|
    option_struct= NULL;
 | 
						|
    if (org_field->type() == MYSQL_TYPE_VAR_STRING ||
 | 
						|
        org_field->type() == MYSQL_TYPE_VARCHAR)
 | 
						|
      new_table->s->db_create_options|= HA_OPTION_PACK_RECORD;
 | 
						|
  }
 | 
						|
  void init_for_make_new_field(TABLE *new_table_arg, TABLE *orig_table_arg)
 | 
						|
  {
 | 
						|
    init(new_table_arg);
 | 
						|
    /*
 | 
						|
      Normally orig_table is different from table only if field was
 | 
						|
      created via ::make_new_field.  Here we alter the type of field,
 | 
						|
      so ::make_new_field is not applicable. But we still need to
 | 
						|
      preserve the original field metadata for the client-server
 | 
						|
      protocol.
 | 
						|
    */
 | 
						|
    orig_table= orig_table_arg;
 | 
						|
  }
 | 
						|
 | 
						|
  /* maximum possible display length */
 | 
						|
  virtual uint32 max_display_length() const= 0;
 | 
						|
  /**
 | 
						|
    Whether a field being created has the samle type.
 | 
						|
    Used by the ALTER TABLE
 | 
						|
  */
 | 
						|
  virtual bool is_equal(const Column_definition &new_field) const= 0;
 | 
						|
  /* convert decimal to longlong with overflow check */
 | 
						|
  longlong convert_decimal2longlong(const my_decimal *val, bool unsigned_flag,
 | 
						|
                                    int *err);
 | 
						|
  /*
 | 
						|
    Maximum number of bytes in character representation.
 | 
						|
    - For string types it is equal to the field capacity, in bytes.
 | 
						|
    - For non-string types it represents the longest possible string length
 | 
						|
      after conversion to string.
 | 
						|
  */
 | 
						|
  virtual uint32 character_octet_length() const
 | 
						|
  {
 | 
						|
    return field_length;
 | 
						|
  }
 | 
						|
  /* The max. number of characters */
 | 
						|
  virtual uint32 char_length() const
 | 
						|
  {
 | 
						|
    return field_length / charset()->mbmaxlen;
 | 
						|
  }
 | 
						|
 | 
						|
  ha_storage_media field_storage_type() const
 | 
						|
  {
 | 
						|
    return (ha_storage_media)
 | 
						|
      ((flags >> FIELD_FLAGS_STORAGE_MEDIA) & 3);
 | 
						|
  }
 | 
						|
 | 
						|
  void set_storage_type(ha_storage_media storage_type_arg)
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(field_storage_type() == HA_SM_DEFAULT);
 | 
						|
    flags |= static_cast<uint32>(storage_type_arg) <<
 | 
						|
      FIELD_FLAGS_STORAGE_MEDIA;
 | 
						|
  }
 | 
						|
 | 
						|
  column_format_type column_format() const
 | 
						|
  {
 | 
						|
    return (column_format_type)
 | 
						|
      ((flags >> FIELD_FLAGS_COLUMN_FORMAT) & 3);
 | 
						|
  }
 | 
						|
 | 
						|
  void set_column_format(column_format_type column_format_arg)
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(column_format() == COLUMN_FORMAT_TYPE_DEFAULT);
 | 
						|
    flags |= static_cast<uint32>(column_format_arg) <<
 | 
						|
      FIELD_FLAGS_COLUMN_FORMAT;
 | 
						|
  }
 | 
						|
 | 
						|
  bool vers_sys_field() const
 | 
						|
  {
 | 
						|
    return flags & (VERS_ROW_START | VERS_ROW_END);
 | 
						|
  }
 | 
						|
 | 
						|
  bool vers_sys_start() const
 | 
						|
  {
 | 
						|
    return flags & VERS_ROW_START;
 | 
						|
  }
 | 
						|
 | 
						|
  bool vers_sys_end() const
 | 
						|
  {
 | 
						|
    return flags & VERS_ROW_END;
 | 
						|
  }
 | 
						|
 | 
						|
  bool vers_update_unversioned() const
 | 
						|
  {
 | 
						|
    return flags & VERS_UPDATE_UNVERSIONED_FLAG;
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
    Validate a non-null field value stored in the given record
 | 
						|
    according to the current thread settings, e.g. sql_mode.
 | 
						|
    @param thd     - the thread
 | 
						|
    @param record  - the record to check in
 | 
						|
  */
 | 
						|
  virtual bool validate_value_in_record(THD *thd, const uchar *record) const
 | 
						|
  { return false; }
 | 
						|
  bool validate_value_in_record_with_warn(THD *thd, const uchar *record);
 | 
						|
  key_map get_possible_keys();
 | 
						|
 | 
						|
  /* Hash value */
 | 
						|
  void hash(Hasher *hasher)
 | 
						|
  {
 | 
						|
    if (is_null())
 | 
						|
      hasher->add_null();
 | 
						|
    else
 | 
						|
      hash_not_null(hasher);
 | 
						|
  }
 | 
						|
  virtual void hash_not_null(Hasher *hasher);
 | 
						|
 | 
						|
  /**
 | 
						|
    Get the upper limit of the MySQL integral and floating-point type.
 | 
						|
 | 
						|
    @return maximum allowed value for the field
 | 
						|
  */
 | 
						|
  virtual ulonglong get_max_int_value() const
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(false);
 | 
						|
    return 0ULL;
 | 
						|
  }
 | 
						|
 | 
						|
/**
 | 
						|
  Checks whether a string field is part of write_set.
 | 
						|
 | 
						|
  @return
 | 
						|
    FALSE  - If field is not char/varchar/....
 | 
						|
           - If field is char/varchar/.. and is not part of write set.
 | 
						|
    TRUE   - If field is char/varchar/.. and is part of write set.
 | 
						|
*/
 | 
						|
  virtual bool is_varchar_and_in_write_set() const { return FALSE; }
 | 
						|
 | 
						|
  /* Check whether the field can be used as a join attribute in hash join */
 | 
						|
  virtual bool hash_join_is_possible() { return TRUE; }
 | 
						|
  virtual bool eq_cmp_as_binary() { return TRUE; }
 | 
						|
 | 
						|
  /* Position of the field value within the interval of [min, max] */
 | 
						|
  virtual double pos_in_interval(Field *min, Field *max)
 | 
						|
  {
 | 
						|
    return (double) 0.5; 
 | 
						|
  }
 | 
						|
  virtual bool pos_through_val_str() { return false;}
 | 
						|
 | 
						|
  /*
 | 
						|
    Check if comparison between the field and an item unambiguously
 | 
						|
    identifies a distinct field value.
 | 
						|
 | 
						|
    Example1: SELECT * FROM t1 WHERE int_column=10;
 | 
						|
              This example returns distinct integer value of 10.
 | 
						|
 | 
						|
    Example2: SELECT * FROM t1 WHERE varchar_column=DATE'2001-01-01'
 | 
						|
              This example returns non-distinct values.
 | 
						|
              Comparison as DATE will return '2001-01-01' and '2001-01-01x',
 | 
						|
              but these two values are not equal to each other as VARCHARs.
 | 
						|
    See also the function with the same name in sql_select.cc.
 | 
						|
  */
 | 
						|
  virtual bool test_if_equality_guarantees_uniqueness(const Item *const_item)
 | 
						|
                                                      const;
 | 
						|
  virtual bool can_be_substituted_to_equal_item(const Context &ctx,
 | 
						|
                                        const Item_equal *item);
 | 
						|
  virtual Item *get_equal_const_item(THD *thd, const Context &ctx,
 | 
						|
                                     Item *const_item)
 | 
						|
  {
 | 
						|
    return const_item;
 | 
						|
  }
 | 
						|
  virtual Data_type_compatibility can_optimize_keypart_ref(
 | 
						|
                                        const Item_bool_func *cond,
 | 
						|
                                        const Item *item) const;
 | 
						|
  virtual Data_type_compatibility can_optimize_hash_join(
 | 
						|
                                      const Item_bool_func *cond,
 | 
						|
                                      const Item *item) const
 | 
						|
  {
 | 
						|
    return can_optimize_keypart_ref(cond, item);
 | 
						|
  }
 | 
						|
  virtual Data_type_compatibility can_optimize_group_min_max(
 | 
						|
                                          const Item_bool_func *cond,
 | 
						|
                                          const Item *const_item) const;
 | 
						|
  /**
 | 
						|
    Test if Field can use range optimizer for a standard comparison operation:
 | 
						|
      <=, <, =, <=>, >, >=
 | 
						|
    Note, this method does not cover spatial operations.
 | 
						|
  */
 | 
						|
  virtual Data_type_compatibility can_optimize_range(const Item_bool_func *cond,
 | 
						|
                                                     const Item *item,
 | 
						|
                                                     bool is_eq_func) const;
 | 
						|
 | 
						|
  virtual SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part,
 | 
						|
                               const Item_bool_func *cond,
 | 
						|
                               scalar_comparison_op op, Item *value)= 0;
 | 
						|
 | 
						|
  Data_type_compatibility 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);
 | 
						|
  }
 | 
						|
 | 
						|
  bool save_in_field_default_value(bool view_eror_processing);
 | 
						|
  bool save_in_field_ignore_value(bool view_error_processing);
 | 
						|
 | 
						|
  /* Mark field in read map. Updates also virtual fields */
 | 
						|
  void register_field_in_read_map();
 | 
						|
 | 
						|
  virtual Compression_method *compression_method() const { return 0; }
 | 
						|
 | 
						|
  virtual Virtual_tmp_table **virtual_tmp_table_addr()
 | 
						|
  {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
  virtual bool sp_prepare_and_store_item(THD *thd, Item **value);
 | 
						|
 | 
						|
  friend int cre_myisam(char * name, TABLE *form, uint options,
 | 
						|
			ulonglong auto_increment_value);
 | 
						|
  friend class Copy_field;
 | 
						|
  friend class Item_avg_field;
 | 
						|
  friend class Item_std_field;
 | 
						|
  friend class Item_sum_num;
 | 
						|
  friend class Item_sum_sum;
 | 
						|
  friend class Item_sum_count;
 | 
						|
  friend class Item_sum_avg;
 | 
						|
  friend class Item_sum_std;
 | 
						|
  friend class Item_sum_min;
 | 
						|
  friend class Item_sum_max;
 | 
						|
  friend class Item_func_group_concat;
 | 
						|
 | 
						|
private:
 | 
						|
  /*
 | 
						|
    Primitive for implementing last_null_byte().
 | 
						|
 | 
						|
    SYNOPSIS
 | 
						|
      do_last_null_byte()
 | 
						|
 | 
						|
    DESCRIPTION
 | 
						|
      Primitive for the implementation of the last_null_byte()
 | 
						|
      function. This represents the inheritance interface and can be
 | 
						|
      overridden by subclasses.
 | 
						|
   */
 | 
						|
  virtual size_t do_last_null_byte() const;
 | 
						|
 | 
						|
protected:
 | 
						|
  uchar *pack_int(uchar *to, const uchar *from, size_t size)
 | 
						|
  {
 | 
						|
    memcpy(to, from, size);
 | 
						|
    return to + size;
 | 
						|
  }
 | 
						|
 | 
						|
  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;
 | 
						|
  }
 | 
						|
 | 
						|
  uchar *pack_int16(uchar *to, const uchar *from)
 | 
						|
  { return pack_int(to, from, 2); }
 | 
						|
  const uchar *unpack_int16(uchar* to, const uchar *from, const uchar *from_end)
 | 
						|
  { return unpack_int(to, from, from_end, 2); }
 | 
						|
  uchar *pack_int24(uchar *to, const uchar *from)
 | 
						|
  { return pack_int(to, from, 3); }
 | 
						|
  const uchar *unpack_int24(uchar* to, const uchar *from, const uchar *from_end)
 | 
						|
  { return unpack_int(to, from, from_end, 3); }
 | 
						|
  uchar *pack_int32(uchar *to, const uchar *from)
 | 
						|
  { return pack_int(to, from, 4); }
 | 
						|
  const uchar *unpack_int32(uchar* to, const uchar *from, const uchar *from_end)
 | 
						|
  { return unpack_int(to, from, from_end, 4); }
 | 
						|
  uchar *pack_int64(uchar* to, const uchar *from)
 | 
						|
  { return pack_int(to, from, 8); }
 | 
						|
  const uchar *unpack_int64(uchar* to, const uchar *from,  const uchar *from_end)
 | 
						|
  { return unpack_int(to, from, from_end, 8); }
 | 
						|
 | 
						|
  double pos_in_interval_val_real(Field *min, Field *max);
 | 
						|
  double pos_in_interval_val_str(Field *min, Field *max, uint data_offset);
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_num :public Field {
 | 
						|
protected:
 | 
						|
  int check_edom_and_important_data_truncation(const char *type, bool edom,
 | 
						|
                                               CHARSET_INFO *cs,
 | 
						|
                                               const char *str, size_t length,
 | 
						|
                                               const char *end_of_num);
 | 
						|
  int check_edom_and_truncation(const char *type, bool edom,
 | 
						|
                                CHARSET_INFO *cs,
 | 
						|
                                const char *str, size_t length,
 | 
						|
                                const char *end_of_num);
 | 
						|
  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);
 | 
						|
  }
 | 
						|
  bool get_int(CHARSET_INFO *cs, const char *from, size_t len,
 | 
						|
               longlong *rnd, ulonglong unsigned_max,
 | 
						|
               longlong signed_min, longlong signed_max);
 | 
						|
  void prepend_zeros(String *value) const;
 | 
						|
  Item *get_equal_zerofill_const_item(THD *thd, const Context &ctx,
 | 
						|
                                      Item *const_item);
 | 
						|
  Binlog_type_info::binlog_sign_t binlog_signedness() const
 | 
						|
  {
 | 
						|
    return (flags & UNSIGNED_FLAG) ? Binlog_type_info::SIGN_UNSIGNED :
 | 
						|
                                     Binlog_type_info::SIGN_SIGNED;
 | 
						|
  }
 | 
						|
  bool send_numeric_zerofill_str(Protocol_text *protocol,
 | 
						|
                                 protocol_send_type_t send_type);
 | 
						|
 | 
						|
public:
 | 
						|
  const decimal_digits_t dec;
 | 
						|
  bool zerofill,unsigned_flag;	// Purify cannot handle bit fields
 | 
						|
  Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
 | 
						|
	    uchar null_bit_arg, utype unireg_check_arg,
 | 
						|
	    const LEX_CSTRING *field_name_arg,
 | 
						|
            decimal_digits_t dec_arg, bool zero_arg, bool unsigned_arg);
 | 
						|
  CHARSET_INFO *charset() const override
 | 
						|
  {
 | 
						|
    return DTCollation_numeric::singleton().collation;
 | 
						|
  }
 | 
						|
  const DTCollation &dtcollation() const override
 | 
						|
  {
 | 
						|
    return DTCollation_numeric::singleton();
 | 
						|
  }
 | 
						|
  sql_mode_t can_handle_sql_mode_dependency_on_store() const override;
 | 
						|
  Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item)
 | 
						|
    override
 | 
						|
  {
 | 
						|
    return (flags & ZEROFILL_FLAG) ?
 | 
						|
           get_equal_zerofill_const_item(thd, ctx, const_item) :
 | 
						|
           const_item;
 | 
						|
  }
 | 
						|
  void add_zerofill_and_unsigned(String &res) const;
 | 
						|
  friend class Create_field;
 | 
						|
  void make_send_field(Send_field *) override;
 | 
						|
  decimal_digits_t decimals() const override { return dec; }
 | 
						|
  uint size_of() const override { return sizeof(*this); }
 | 
						|
  bool eq_def(const Field *field) const override;
 | 
						|
  Copy_func *get_copy_func(const Field *from) const override
 | 
						|
  {
 | 
						|
    if (unsigned_flag && from->cmp_type() == DECIMAL_RESULT)
 | 
						|
      return do_field_decimal;
 | 
						|
    return do_field_int;
 | 
						|
  }
 | 
						|
  int save_in_field(Field *to) override
 | 
						|
  {
 | 
						|
    return to->store(val_int(), MY_TEST(flags & UNSIGNED_FLAG));
 | 
						|
  }
 | 
						|
  bool is_equal(const Column_definition &new_field) const override;
 | 
						|
  uint row_pack_length() const override { return pack_length(); }
 | 
						|
  uint32 pack_length_from_metadata(uint field_metadata) const override
 | 
						|
  {
 | 
						|
    uint32 length= pack_length();
 | 
						|
    DBUG_PRINT("result", ("pack_length_from_metadata(%d): %u",
 | 
						|
                          field_metadata, length));
 | 
						|
    return length;
 | 
						|
  }
 | 
						|
  double pos_in_interval(Field *min, Field *max) override
 | 
						|
  {
 | 
						|
    return pos_in_interval_val_real(min, max);
 | 
						|
  }
 | 
						|
  SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part,
 | 
						|
                       const Item_bool_func *cond,
 | 
						|
                       scalar_comparison_op op, Item *value) override;
 | 
						|
  Binlog_type_info binlog_type_info() const override
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(Field_num::type() == binlog_type());
 | 
						|
    return Binlog_type_info(Field_num::type(), 0, 0, binlog_signedness());
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_str :public Field {
 | 
						|
protected:
 | 
						|
  DTCollation m_collation;
 | 
						|
  // A short alias for m_collation.collation with non-virtual linkage
 | 
						|
  const CHARSET_INFO *field_charset() const { return m_collation.collation; }
 | 
						|
  uint mbmaxlen() const { return m_collation.collation->mbmaxlen; }
 | 
						|
public:
 | 
						|
  bool can_be_substituted_to_equal_item(const Context &ctx,
 | 
						|
                                        const Item_equal *item_equal) override;
 | 
						|
  Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
 | 
						|
	    uchar null_bit_arg, utype unireg_check_arg,
 | 
						|
	    const LEX_CSTRING *field_name_arg,
 | 
						|
	    const DTCollation &collation);
 | 
						|
  decimal_digits_t decimals() const override
 | 
						|
  { return is_created_from_null_item ? 0 : DECIMAL_NOT_SPECIFIED; }
 | 
						|
  int  save_in_field(Field *to) override { return save_in_field_str(to); }
 | 
						|
  bool memcpy_field_possible(const Field *from) const override
 | 
						|
  {
 | 
						|
    return real_type() == from->real_type() &&
 | 
						|
           pack_length() == from->pack_length() &&
 | 
						|
           charset() == from->charset();
 | 
						|
  }
 | 
						|
  int  store(double nr) override;
 | 
						|
  int  store(longlong nr, bool unsigned_val) override;
 | 
						|
  int  store_decimal(const my_decimal *) override;
 | 
						|
  int  store(const char *to,size_t length,CHARSET_INFO *cs) override=0;
 | 
						|
  int  store_hex_hybrid(const char *str, size_t length) override
 | 
						|
  {
 | 
						|
    return store(str, length, &my_charset_bin);
 | 
						|
  }
 | 
						|
  CHARSET_INFO *charset() const override { return m_collation.collation; }
 | 
						|
  const DTCollation &dtcollation() const override
 | 
						|
  {
 | 
						|
    return m_collation;
 | 
						|
  }
 | 
						|
  void change_charset(const DTCollation &new_cs) override;
 | 
						|
  bool binary() const override { return field_charset() == &my_charset_bin; }
 | 
						|
  uint32 max_display_length() const override { return field_length; }
 | 
						|
  uint32 character_octet_length() const override { return field_length; }
 | 
						|
  uint32 char_length() const override
 | 
						|
  {
 | 
						|
    return field_length / mbmaxlen();
 | 
						|
  }
 | 
						|
  Information_schema_character_attributes
 | 
						|
    information_schema_character_attributes() const override
 | 
						|
  {
 | 
						|
    return Information_schema_character_attributes(max_display_length(),
 | 
						|
                                                   char_length());
 | 
						|
  }
 | 
						|
  friend class Create_field;
 | 
						|
  my_decimal *val_decimal(my_decimal *) override;
 | 
						|
  bool val_bool() override { return val_real() != 0e0; }
 | 
						|
  bool str_needs_quotes() const override { return true; }
 | 
						|
  bool eq_cmp_as_binary() override { return MY_TEST(flags & BINARY_FLAG); }
 | 
						|
  virtual uint length_size() const { return 0; }
 | 
						|
  double pos_in_interval(Field *min, Field *max) override
 | 
						|
  {
 | 
						|
    return pos_in_interval_val_str(min, max, length_size());
 | 
						|
  }
 | 
						|
  bool pos_through_val_str() override {return true;}
 | 
						|
 | 
						|
  bool test_if_equality_guarantees_uniqueness(const Item *const_item) const
 | 
						|
    override;
 | 
						|
  SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part,
 | 
						|
                       const Item_bool_func *cond,
 | 
						|
                       scalar_comparison_op op, Item *value) override;
 | 
						|
  Binlog_type_info binlog_type_info() const override
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(Field_str::type() == binlog_type());
 | 
						|
    return Binlog_type_info(Field_str::type(), 0, 0, charset());
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
/* base class for Field_string, Field_varstring and Field_blob */
 | 
						|
 | 
						|
class Field_longstr :public Field_str
 | 
						|
{
 | 
						|
protected:
 | 
						|
  int report_if_important_data(const char *ptr, const char *end,
 | 
						|
                               bool count_spaces);
 | 
						|
  bool check_string_copy_error(const String_copier *copier,
 | 
						|
                               const char *end, CHARSET_INFO *cs);
 | 
						|
  int check_conversion_status(const String_copier *copier,
 | 
						|
                              const char *end, CHARSET_INFO *cs,
 | 
						|
                              bool count_spaces)
 | 
						|
  {
 | 
						|
    if (check_string_copy_error(copier, end, cs))
 | 
						|
      return 2;
 | 
						|
    return report_if_important_data(copier->source_end_pos(),
 | 
						|
                                    end, count_spaces);
 | 
						|
  }
 | 
						|
  int well_formed_copy_with_check(char *to, size_t to_length,
 | 
						|
                                  CHARSET_INFO *from_cs,
 | 
						|
                                  const char *from, size_t from_length,
 | 
						|
                                  size_t nchars, bool count_spaces,
 | 
						|
                                  uint *copy_length)
 | 
						|
  {
 | 
						|
    String_copier copier;
 | 
						|
 | 
						|
    *copy_length= copier.well_formed_copy(field_charset(), to, to_length,
 | 
						|
                                          from_cs, from, from_length,
 | 
						|
                                          nchars);
 | 
						|
 | 
						|
    return check_conversion_status(&copier, from + from_length, from_cs, count_spaces);
 | 
						|
  }
 | 
						|
  Data_type_compatibility cmp_to_string_with_same_collation(
 | 
						|
                                         const Item_bool_func *cond,
 | 
						|
                                         const Item *item) const;
 | 
						|
  Data_type_compatibility cmp_to_string_with_stricter_collation(
 | 
						|
                                             const Item_bool_func *cond,
 | 
						|
                                             const Item *item) const;
 | 
						|
  int compress(char *to, uint to_length,
 | 
						|
               const char *from, uint length,
 | 
						|
               uint max_length,
 | 
						|
               uint *out_length,
 | 
						|
               CHARSET_INFO *cs, size_t nchars);
 | 
						|
  String *uncompress(String *val_buffer, String *val_ptr,
 | 
						|
                     const uchar *from, uint from_length) const;
 | 
						|
public:
 | 
						|
  Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
 | 
						|
                uchar null_bit_arg, utype unireg_check_arg,
 | 
						|
                const LEX_CSTRING *field_name_arg,
 | 
						|
                const DTCollation &collation)
 | 
						|
    :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
 | 
						|
               field_name_arg, collation)
 | 
						|
    {}
 | 
						|
  enum_conv_type rpl_conv_type_from(const Conv_source &source,
 | 
						|
                                    const Relay_log_info *rli,
 | 
						|
                                    const Conv_param ¶m) const override;
 | 
						|
  int store_decimal(const my_decimal *d) override;
 | 
						|
  uint32 max_data_length() const override;
 | 
						|
  void make_send_field(Send_field *) override;
 | 
						|
  bool send(Protocol *protocol) override;
 | 
						|
 | 
						|
  bool is_varchar_and_in_write_set() const override
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(table && table->write_set);
 | 
						|
    return bitmap_is_set(table->write_set, field_index);
 | 
						|
  }
 | 
						|
  bool match_collation_to_optimize_range() const { return true; }
 | 
						|
 | 
						|
  Data_type_compatibility can_optimize_keypart_ref(const Item_bool_func *cond,
 | 
						|
                                                   const Item *item)
 | 
						|
                                                   const override;
 | 
						|
  Data_type_compatibility can_optimize_hash_join(const Item_bool_func *cond,
 | 
						|
                                                 const Item *item)
 | 
						|
                                                 const override;
 | 
						|
  Data_type_compatibility can_optimize_group_min_max(const Item_bool_func *cond,
 | 
						|
                                                     const Item *const_item)
 | 
						|
                                                     const override;
 | 
						|
  Data_type_compatibility can_optimize_range(const Item_bool_func *cond,
 | 
						|
                                             const Item *item,
 | 
						|
                                             bool is_eq_func) const override;
 | 
						|
  bool is_packable() const override { return true; }
 | 
						|
  uint make_packed_sort_key_part(uchar *buff,
 | 
						|
                                 const SORT_FIELD_ATTR *sort_field)override;
 | 
						|
  uchar* pack_sort_string(uchar *to, const SORT_FIELD_ATTR *sort_field);
 | 
						|
};
 | 
						|
 | 
						|
/* base class for float and double and decimal (old one) */
 | 
						|
class Field_real :public Field_num {
 | 
						|
protected:
 | 
						|
  double get_double(const char *str, size_t length, CHARSET_INFO *cs, int *err);
 | 
						|
public:
 | 
						|
  bool not_fixed;
 | 
						|
 | 
						|
  Field_real(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
 | 
						|
             uchar null_bit_arg, utype unireg_check_arg,
 | 
						|
             const LEX_CSTRING *field_name_arg,
 | 
						|
             decimal_digits_t dec_arg, bool zero_arg, bool unsigned_arg)
 | 
						|
    :Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
 | 
						|
               field_name_arg, dec_arg, zero_arg, unsigned_arg),
 | 
						|
    not_fixed(dec_arg >= FLOATING_POINT_DECIMALS)
 | 
						|
    {}
 | 
						|
  Copy_func *get_copy_func(const Field *from) const override
 | 
						|
  {
 | 
						|
    return do_field_real;
 | 
						|
  }
 | 
						|
  enum_conv_type rpl_conv_type_from(const Conv_source &source,
 | 
						|
                                    const Relay_log_info *rli,
 | 
						|
                                    const Conv_param ¶m) const override;
 | 
						|
  Information_schema_numeric_attributes
 | 
						|
    information_schema_numeric_attributes() const override
 | 
						|
  {
 | 
						|
    return dec == DECIMAL_NOT_SPECIFIED ?
 | 
						|
                  Information_schema_numeric_attributes(field_length) :
 | 
						|
                  Information_schema_numeric_attributes(field_length, dec);
 | 
						|
  }
 | 
						|
  void sql_type(String &str) const override;
 | 
						|
  int save_in_field(Field *to) override { return to->store(val_real()); }
 | 
						|
  bool memcpy_field_possible(const Field *from) const override
 | 
						|
  {
 | 
						|
    /*
 | 
						|
      Cannot do memcpy from a longer field to a shorter field,
 | 
						|
      e.g. a DOUBLE(53,10) into a DOUBLE(10,10).
 | 
						|
      But it should be OK the other way around.
 | 
						|
    */
 | 
						|
    return real_type() == from->real_type() &&
 | 
						|
           pack_length() == from->pack_length() &&
 | 
						|
           is_unsigned() <= from->is_unsigned() &&
 | 
						|
           decimals() == from->decimals() &&
 | 
						|
           field_length >= from->field_length;
 | 
						|
  }
 | 
						|
  int store_decimal(const my_decimal *dec) override
 | 
						|
  { return store(dec->to_double()); }
 | 
						|
  int  store_time_dec(const MYSQL_TIME *ltime, uint dec) override;
 | 
						|
  bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override;
 | 
						|
  my_decimal *val_decimal(my_decimal *) override;
 | 
						|
  bool val_bool() override { return val_real() != 0e0; }
 | 
						|
  uint32 max_display_length() const override { return field_length; }
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
  Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item)
 | 
						|
    override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_decimal final  :public Field_real {
 | 
						|
public:
 | 
						|
  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,
 | 
						|
		decimal_digits_t 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 *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type)
 | 
						|
    override;
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return &type_handler_olddecimal; }
 | 
						|
  enum ha_base_keytype key_type() const override
 | 
						|
  { return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; }
 | 
						|
  Information_schema_numeric_attributes
 | 
						|
    information_schema_numeric_attributes() const override
 | 
						|
  {
 | 
						|
    uint tmp= dec ? 2 : 1; // The sign and the decimal point
 | 
						|
    return Information_schema_numeric_attributes(field_length - tmp, dec);
 | 
						|
  }
 | 
						|
  Copy_func *get_copy_func(const Field *from) const override
 | 
						|
  {
 | 
						|
    return eq_def(from) ? get_identical_copy_func() : do_field_string;
 | 
						|
  }
 | 
						|
  int reset() override;
 | 
						|
  int store(const char *to,size_t length,CHARSET_INFO *charset) override;
 | 
						|
  int store(double nr) override;
 | 
						|
  int store(longlong nr, bool unsigned_val) override;
 | 
						|
  double val_real() override;
 | 
						|
  longlong val_int() override;
 | 
						|
  String *val_str(String *, String *) override;
 | 
						|
  int cmp(const uchar *,const uchar *) const override;
 | 
						|
  void sort_string(uchar *buff,uint length) override;
 | 
						|
  void overflow(bool negative);
 | 
						|
  bool zero_pack() const override { return false; }
 | 
						|
  void sql_type(String &str) const override;
 | 
						|
  uchar *pack(uchar* to, const uchar *from, uint max_length) override
 | 
						|
  {
 | 
						|
    return Field::pack(to, from, max_length);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/* New decimal/numeric field which use fixed point arithmetic */
 | 
						|
class Field_new_decimal final :public Field_num {
 | 
						|
public:
 | 
						|
  /* The maximum number of decimal digits can be stored */
 | 
						|
  decimal_digits_t precision;
 | 
						|
  uint32 bin_size;
 | 
						|
  /*
 | 
						|
    Constructors take max_length of the field as a parameter - not the
 | 
						|
    precision as the number of decimal digits allowed.
 | 
						|
    So for example we need to count length from precision handling
 | 
						|
    CREATE TABLE ( DECIMAL(x,y)) 
 | 
						|
  */
 | 
						|
  Field_new_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,
 | 
						|
                    decimal_digits_t dec_arg, bool zero_arg, bool unsigned_arg);
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return &type_handler_newdecimal; }
 | 
						|
  enum ha_base_keytype key_type() const override { return HA_KEYTYPE_BINARY; }
 | 
						|
  Copy_func *get_copy_func(const Field *from) const override
 | 
						|
  {
 | 
						|
    //  if (from->real_type() == MYSQL_TYPE_BIT) // QQ: why?
 | 
						|
    //    return do_field_int;
 | 
						|
    return do_field_decimal;
 | 
						|
  }
 | 
						|
  int save_in_field(Field *to) override
 | 
						|
  {
 | 
						|
    my_decimal tmp(ptr, precision, dec);
 | 
						|
    return to->store_decimal(&tmp);
 | 
						|
  }
 | 
						|
  bool memcpy_field_possible(const Field *from) const override
 | 
						|
  {
 | 
						|
    return real_type() == from->real_type() &&
 | 
						|
           pack_length() == from->pack_length() &&
 | 
						|
           is_unsigned() <= from->is_unsigned() &&
 | 
						|
           decimals() == from->decimals() &&
 | 
						|
           field_length == from->field_length;
 | 
						|
  }
 | 
						|
  enum_conv_type rpl_conv_type_from(const Conv_source &source,
 | 
						|
                                    const Relay_log_info *rli,
 | 
						|
                                    const Conv_param ¶m) const override;
 | 
						|
  int  reset() override;
 | 
						|
  bool store_value(const my_decimal *decimal_value);
 | 
						|
  bool store_value(const my_decimal *decimal_value, int *native_error);
 | 
						|
  void set_value_on_overflow(my_decimal *decimal_value, bool sign);
 | 
						|
  int  store(const char *to, size_t length, CHARSET_INFO *charset) override;
 | 
						|
  int  store(double nr) override;
 | 
						|
  int  store(longlong nr, bool unsigned_val) override;
 | 
						|
  int  store_time_dec(const MYSQL_TIME *ltime, uint dec) override;
 | 
						|
  int  store_decimal(const my_decimal *) override;
 | 
						|
  double val_real() override
 | 
						|
  {
 | 
						|
    return my_decimal(ptr, precision, dec).to_double();
 | 
						|
  }
 | 
						|
  longlong val_int() override
 | 
						|
  {
 | 
						|
    return my_decimal(ptr, precision, dec).to_longlong(unsigned_flag);
 | 
						|
  }
 | 
						|
  ulonglong val_uint() override
 | 
						|
  {
 | 
						|
    return (ulonglong) my_decimal(ptr, precision, dec).to_longlong(true);
 | 
						|
  }
 | 
						|
  my_decimal *val_decimal(my_decimal *) override;
 | 
						|
  String *val_str(String *val_buffer, String *) override
 | 
						|
  {
 | 
						|
    uint fixed_precision= zerofill ? precision : 0;
 | 
						|
    return my_decimal(ptr, precision, dec).
 | 
						|
             to_string(val_buffer, fixed_precision, dec, '0');
 | 
						|
  }
 | 
						|
  bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override
 | 
						|
  {
 | 
						|
    my_decimal nr(ptr, precision, dec);
 | 
						|
    return decimal_to_datetime_with_warn(get_thd(), &nr, ltime,
 | 
						|
                                         fuzzydate, table->s, field_name.str);
 | 
						|
  }
 | 
						|
  bool val_bool() override
 | 
						|
  {
 | 
						|
    return my_decimal(ptr, precision, dec).to_bool();
 | 
						|
  }
 | 
						|
  int cmp(const uchar *, const uchar *) const override;
 | 
						|
  void sort_string(uchar *buff, uint length) override;
 | 
						|
  bool zero_pack() const override { return false; }
 | 
						|
  void sql_type(String &str) const override;
 | 
						|
  uint32 max_display_length() const override { return field_length; }
 | 
						|
  Information_schema_numeric_attributes
 | 
						|
    information_schema_numeric_attributes() const override
 | 
						|
  {
 | 
						|
    return Information_schema_numeric_attributes(precision, dec);
 | 
						|
  }
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
  uint32 pack_length() const override { return bin_size; }
 | 
						|
  uint pack_length_from_metadata(uint field_metadata) const override;
 | 
						|
  uint row_pack_length() const override { return pack_length(); }
 | 
						|
  bool compatible_field_size(uint field_metadata, const Relay_log_info *rli,
 | 
						|
                             uint16 mflags, int *order_var) const override;
 | 
						|
  bool is_equal(const Column_definition &new_field) const override;
 | 
						|
  const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end,
 | 
						|
                      uint param_data) override;
 | 
						|
  Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item)
 | 
						|
    override;
 | 
						|
  Binlog_type_info binlog_type_info() const override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_int :public Field_num
 | 
						|
{
 | 
						|
protected:
 | 
						|
  String *val_str_from_long(String *val_buffer, uint max_char_length,
 | 
						|
                            int radix, long nr);
 | 
						|
public:
 | 
						|
  Field_int(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, bool zero_arg, bool unsigned_arg)
 | 
						|
    :Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
 | 
						|
               unireg_check_arg, field_name_arg, 0, zero_arg, unsigned_arg)
 | 
						|
    {}
 | 
						|
  enum_conv_type rpl_conv_type_from(const Conv_source &source,
 | 
						|
                                    const Relay_log_info *rli,
 | 
						|
                                    const Conv_param ¶m) const override;
 | 
						|
  bool memcpy_field_possible(const Field *from) const override
 | 
						|
  {
 | 
						|
    return real_type() == from->real_type() &&
 | 
						|
           pack_length() == from->pack_length() &&
 | 
						|
           is_unsigned() == from->is_unsigned();
 | 
						|
  }
 | 
						|
  int store_decimal(const my_decimal *) override;
 | 
						|
  my_decimal *val_decimal(my_decimal *) override;
 | 
						|
  bool val_bool() override { return val_int() != 0; }
 | 
						|
  ulonglong val_uint() override
 | 
						|
  {
 | 
						|
    longlong nr= val_int();
 | 
						|
    return nr < 0 && !unsigned_flag ? 0 : (ulonglong) nr;
 | 
						|
  }
 | 
						|
  int  store_time_dec(const MYSQL_TIME *ltime, uint dec) override;
 | 
						|
  bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override;
 | 
						|
  virtual const Type_limits_int *type_limits_int() const= 0;
 | 
						|
  uint32 max_display_length() const override
 | 
						|
  {
 | 
						|
    return type_limits_int()->char_length();
 | 
						|
  }
 | 
						|
  Type_numeric_attributes type_numeric_attributes() const override
 | 
						|
  {
 | 
						|
    /*
 | 
						|
      For integer data types, the user-specified length does not constrain the
 | 
						|
      supported range, so e.g. a column of the INT(1) data type supports the
 | 
						|
      full integer range anyway.
 | 
						|
      Choose the maximum from the user-specified length and the maximum
 | 
						|
      possible length determined by the data type capacity:
 | 
						|
        INT(1)  -> 11
 | 
						|
        INT(10) -> 11
 | 
						|
        INT(40) -> 40
 | 
						|
    */
 | 
						|
    uint32 length1= max_display_length();
 | 
						|
    uint32 length2= field_length;
 | 
						|
    return Type_numeric_attributes(MY_MAX(length1, length2),
 | 
						|
                                   decimals(), is_unsigned());
 | 
						|
  }
 | 
						|
  Information_schema_numeric_attributes
 | 
						|
    information_schema_numeric_attributes() const override
 | 
						|
  {
 | 
						|
    uint32 prec= type_limits_int()->precision();
 | 
						|
    return Information_schema_numeric_attributes(prec, 0);
 | 
						|
  }
 | 
						|
  void sql_type(String &str) const override;
 | 
						|
  SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part,
 | 
						|
                       const Item_bool_func *cond,
 | 
						|
                       scalar_comparison_op op, Item *value) override
 | 
						|
  {
 | 
						|
    return get_mm_leaf_int(param, key_part, cond, op, value, unsigned_flag);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_tiny :public Field_int
 | 
						|
{
 | 
						|
  const Type_handler_general_purpose_int *type_handler_priv() const
 | 
						|
  {
 | 
						|
    if (is_unsigned())
 | 
						|
      return &type_handler_utiny;
 | 
						|
    return &type_handler_stiny;
 | 
						|
  }
 | 
						|
public:
 | 
						|
  Field_tiny(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,
 | 
						|
	     bool zero_arg, bool unsigned_arg)
 | 
						|
    :Field_int(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
 | 
						|
               unireg_check_arg, field_name_arg, zero_arg, unsigned_arg)
 | 
						|
    {}
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
    { return type_handler_priv(); }
 | 
						|
  enum ha_base_keytype key_type() const override
 | 
						|
    { return unsigned_flag ? HA_KEYTYPE_BINARY : HA_KEYTYPE_INT8; }
 | 
						|
  int store(const char *to,size_t length,CHARSET_INFO *charset) override;
 | 
						|
  int store(double nr) override;
 | 
						|
  int store(longlong nr, bool unsigned_val) override;
 | 
						|
  int reset() override { ptr[0]=0; return 0; }
 | 
						|
  double val_real() override;
 | 
						|
  longlong val_int() override;
 | 
						|
  String *val_str(String *, String *) override;
 | 
						|
  bool send(Protocol *protocol) override;
 | 
						|
  int cmp(const uchar *,const uchar *) const override;
 | 
						|
  void sort_string(uchar *buff,uint length) override;
 | 
						|
  uint32 pack_length() const override { return 1; }
 | 
						|
  const Type_limits_int *type_limits_int() const override
 | 
						|
  {
 | 
						|
    return type_handler_priv()->type_limits_int();
 | 
						|
  }
 | 
						|
 | 
						|
  uchar *pack(uchar* to, const uchar *from, uint max_length) override
 | 
						|
  {
 | 
						|
    *to= *from;
 | 
						|
    return to + 1;
 | 
						|
  }
 | 
						|
 | 
						|
  const uchar *unpack(uchar* to, const uchar *from,
 | 
						|
		      const uchar *from_end, uint param_data) override
 | 
						|
  {
 | 
						|
    if (from == from_end)
 | 
						|
      return 0;
 | 
						|
    *to= *from;
 | 
						|
    return from + 1;
 | 
						|
  }
 | 
						|
  ulonglong get_max_int_value() const override
 | 
						|
  {
 | 
						|
    return unsigned_flag ? 0xFFULL : 0x7FULL;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_short final :public Field_int
 | 
						|
{
 | 
						|
  const Type_handler_general_purpose_int *type_handler_priv() const
 | 
						|
  {
 | 
						|
    if (is_unsigned())
 | 
						|
      return &type_handler_ushort;
 | 
						|
    return &type_handler_sshort;
 | 
						|
  }
 | 
						|
public:
 | 
						|
  Field_short(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,
 | 
						|
	      bool zero_arg, bool unsigned_arg)
 | 
						|
    :Field_int(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
 | 
						|
               unireg_check_arg, field_name_arg, zero_arg, unsigned_arg)
 | 
						|
    {}
 | 
						|
  Field_short(uint32 len_arg,bool maybe_null_arg,
 | 
						|
              const LEX_CSTRING *field_name_arg,
 | 
						|
	      bool unsigned_arg)
 | 
						|
    :Field_int((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0,
 | 
						|
               NONE, field_name_arg, 0, unsigned_arg)
 | 
						|
    {}
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return type_handler_priv(); }
 | 
						|
  enum ha_base_keytype key_type() const override
 | 
						|
    { return unsigned_flag ? HA_KEYTYPE_USHORT_INT : HA_KEYTYPE_SHORT_INT;}
 | 
						|
  int store(const char *to,size_t length,CHARSET_INFO *charset) override;
 | 
						|
  int store(double nr) override;
 | 
						|
  int store(longlong nr, bool unsigned_val) override;
 | 
						|
  int reset() override { ptr[0]=ptr[1]=0; return 0; }
 | 
						|
  double val_real() override;
 | 
						|
  longlong val_int() override;
 | 
						|
  String *val_str(String *, String *) override;
 | 
						|
  bool send(Protocol *protocol) override;
 | 
						|
  int cmp(const uchar *,const uchar *) const override;
 | 
						|
  void sort_string(uchar *buff,uint length) override;
 | 
						|
  uint32 pack_length() const override { return 2; }
 | 
						|
  const Type_limits_int *type_limits_int() const override
 | 
						|
  {
 | 
						|
    return type_handler_priv()->type_limits_int();
 | 
						|
  }
 | 
						|
  uchar *pack(uchar* to, const uchar *from, uint) override
 | 
						|
  { return pack_int16(to, from); }
 | 
						|
 | 
						|
  const uchar *unpack(uchar* to, const uchar *from,
 | 
						|
                      const uchar *from_end, uint) override
 | 
						|
  { return unpack_int16(to, from, from_end); }
 | 
						|
  ulonglong get_max_int_value() const override
 | 
						|
  {
 | 
						|
    return unsigned_flag ? 0xFFFFULL : 0x7FFFULL;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class Field_medium final :public Field_int
 | 
						|
{
 | 
						|
  const Type_handler_general_purpose_int *type_handler_priv() const
 | 
						|
  {
 | 
						|
    if (is_unsigned())
 | 
						|
      return &type_handler_uint24;
 | 
						|
    return &type_handler_sint24;
 | 
						|
  }
 | 
						|
public:
 | 
						|
  Field_medium(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,
 | 
						|
	      bool zero_arg, bool unsigned_arg)
 | 
						|
    :Field_int(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
 | 
						|
               unireg_check_arg, field_name_arg, zero_arg, unsigned_arg)
 | 
						|
    {}
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return type_handler_priv(); }
 | 
						|
  enum ha_base_keytype key_type() const override
 | 
						|
    { return unsigned_flag ? HA_KEYTYPE_UINT24 : HA_KEYTYPE_INT24; }
 | 
						|
  int store(const char *to,size_t length,CHARSET_INFO *charset) override;
 | 
						|
  int store(double nr) override;
 | 
						|
  int store(longlong nr, bool unsigned_val) override;
 | 
						|
  int reset() override { ptr[0]=ptr[1]=ptr[2]=0; return 0; }
 | 
						|
  double val_real() override;
 | 
						|
  longlong val_int() override;
 | 
						|
  String *val_str(String *, String *) override;
 | 
						|
  bool send(Protocol *protocol) override;
 | 
						|
  int cmp(const uchar *,const uchar *) const override;
 | 
						|
  void sort_string(uchar *buff,uint length) override;
 | 
						|
  uint32 pack_length() const override { return 3; }
 | 
						|
  const Type_limits_int *type_limits_int() const override
 | 
						|
  {
 | 
						|
    return type_handler_priv()->type_limits_int();
 | 
						|
  }
 | 
						|
  uchar *pack(uchar* to, const uchar *from, uint max_length) override
 | 
						|
  {
 | 
						|
    return Field::pack(to, from, max_length);
 | 
						|
  }
 | 
						|
  ulonglong get_max_int_value() const override
 | 
						|
  {
 | 
						|
    return unsigned_flag ? 0xFFFFFFULL : 0x7FFFFFULL;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_long final :public Field_int
 | 
						|
{
 | 
						|
  const Type_handler_general_purpose_int *type_handler_priv() const
 | 
						|
  {
 | 
						|
    if (is_unsigned())
 | 
						|
      return &type_handler_ulong;
 | 
						|
    return &type_handler_slong;
 | 
						|
  }
 | 
						|
public:
 | 
						|
  Field_long(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,
 | 
						|
	     bool zero_arg, bool unsigned_arg)
 | 
						|
    :Field_int(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
 | 
						|
               unireg_check_arg, field_name_arg, zero_arg, unsigned_arg)
 | 
						|
    {}
 | 
						|
  Field_long(uint32 len_arg,bool maybe_null_arg,
 | 
						|
             const LEX_CSTRING *field_name_arg,
 | 
						|
	     bool unsigned_arg)
 | 
						|
    :Field_int((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0,
 | 
						|
               NONE, field_name_arg, 0, unsigned_arg)
 | 
						|
    {}
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return type_handler_priv(); }
 | 
						|
  enum ha_base_keytype key_type() const override
 | 
						|
    { return unsigned_flag ? HA_KEYTYPE_ULONG_INT : HA_KEYTYPE_LONG_INT; }
 | 
						|
  int store(const char *to,size_t length,CHARSET_INFO *charset) override;
 | 
						|
  int store(double nr) override;
 | 
						|
  int store(longlong nr, bool unsigned_val) override;
 | 
						|
  int reset() override { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; }
 | 
						|
  double val_real() override;
 | 
						|
  longlong val_int() override;
 | 
						|
  bool send(Protocol *protocol) override;
 | 
						|
  String *val_str(String *, String *) override;
 | 
						|
  int cmp(const uchar *,const uchar *) const override;
 | 
						|
  void sort_string(uchar *buff,uint length) override;
 | 
						|
  uint32 pack_length() const override { return 4; }
 | 
						|
  const Type_limits_int *type_limits_int() const override
 | 
						|
  {
 | 
						|
    return type_handler_priv()->type_limits_int();
 | 
						|
  }
 | 
						|
  uchar *pack(uchar* to, const uchar *from, uint) override
 | 
						|
  {
 | 
						|
    return pack_int32(to, from);
 | 
						|
  }
 | 
						|
  const uchar *unpack(uchar* to, const uchar *from,
 | 
						|
                      const uchar *from_end, uint) override
 | 
						|
  {
 | 
						|
    return unpack_int32(to, from, from_end);
 | 
						|
  }
 | 
						|
  ulonglong get_max_int_value() const override
 | 
						|
  {
 | 
						|
    return unsigned_flag ? 0xFFFFFFFFULL : 0x7FFFFFFFULL;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_longlong :public Field_int
 | 
						|
{
 | 
						|
  const Type_handler_general_purpose_int *type_handler_priv() const
 | 
						|
  {
 | 
						|
    if (is_unsigned())
 | 
						|
      return &type_handler_ulonglong;
 | 
						|
    return &type_handler_slonglong;
 | 
						|
  }
 | 
						|
public:
 | 
						|
  Field_longlong(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,
 | 
						|
	      bool zero_arg, bool unsigned_arg)
 | 
						|
    :Field_int(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
 | 
						|
               unireg_check_arg, field_name_arg, zero_arg, unsigned_arg)
 | 
						|
    {}
 | 
						|
  Field_longlong(uint32 len_arg,bool maybe_null_arg,
 | 
						|
		 const LEX_CSTRING *field_name_arg,
 | 
						|
                 bool unsigned_arg)
 | 
						|
    :Field_int((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0,
 | 
						|
                NONE, field_name_arg, 0, unsigned_arg)
 | 
						|
    {}
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return type_handler_priv(); }
 | 
						|
  enum ha_base_keytype key_type() const override
 | 
						|
  { return unsigned_flag ? HA_KEYTYPE_ULONGLONG : HA_KEYTYPE_LONGLONG; }
 | 
						|
  int store(const char *to,size_t length,CHARSET_INFO *charset) override;
 | 
						|
  int store(double nr) override;
 | 
						|
  int store(longlong nr, bool unsigned_val) override;
 | 
						|
  int reset() override
 | 
						|
  {
 | 
						|
    ptr[0]=ptr[1]=ptr[2]=ptr[3]=ptr[4]=ptr[5]=ptr[6]=ptr[7]=0;
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
  double val_real() override;
 | 
						|
  longlong val_int() override;
 | 
						|
  String *val_str(String *, String *) override;
 | 
						|
  bool send(Protocol *protocol) override;
 | 
						|
  int cmp(const uchar *,const uchar *) const override;
 | 
						|
  void sort_string(uchar *buff,uint length) override;
 | 
						|
  uint32 pack_length() const override { return 8; }
 | 
						|
  const Type_limits_int *type_limits_int() const override
 | 
						|
  {
 | 
						|
    return type_handler_priv()->type_limits_int();
 | 
						|
  }
 | 
						|
  uchar *pack(uchar* to, const uchar *from, uint) override
 | 
						|
  {
 | 
						|
    return pack_int64(to, from);
 | 
						|
  }
 | 
						|
  const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end,
 | 
						|
		      uint) override
 | 
						|
  {
 | 
						|
    return unpack_int64(to, from, from_end);
 | 
						|
  }
 | 
						|
  void set_max() override;
 | 
						|
  bool is_max() override;
 | 
						|
  ulonglong get_max_int_value() const override
 | 
						|
  {
 | 
						|
    return unsigned_flag ? 0xFFFFFFFFFFFFFFFFULL : 0x7FFFFFFFFFFFFFFFULL;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_vers_trx_id :public Field_longlong {
 | 
						|
  MYSQL_TIME cache;
 | 
						|
  ulonglong cached;
 | 
						|
public:
 | 
						|
  Field_vers_trx_id(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, bool zero_arg,
 | 
						|
                    bool unsigned_arg)
 | 
						|
      : Field_longlong(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
 | 
						|
                       unireg_check_arg, field_name_arg, zero_arg,
 | 
						|
                       unsigned_arg),
 | 
						|
        cached(0)
 | 
						|
  {}
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return &type_handler_vers_trx_id; }
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
  bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate, ulonglong trx_id);
 | 
						|
  bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override
 | 
						|
  {
 | 
						|
    return get_date(ltime, fuzzydate, (ulonglong) val_int());
 | 
						|
  }
 | 
						|
  bool test_if_equality_guarantees_uniqueness(const Item *item) const override;
 | 
						|
  Data_type_compatibility can_optimize_keypart_ref(const Item_bool_func *,
 | 
						|
                                                   const Item *)
 | 
						|
    const override
 | 
						|
  {
 | 
						|
    return Data_type_compatibility::OK;
 | 
						|
  }
 | 
						|
 | 
						|
  Data_type_compatibility can_optimize_group_min_max(const Item_bool_func *,
 | 
						|
                                                     const Item *)
 | 
						|
    const override
 | 
						|
  {
 | 
						|
    return Data_type_compatibility::OK;
 | 
						|
  }
 | 
						|
  Data_type_compatibility can_optimize_range(const Item_bool_func *,
 | 
						|
                                             const Item *, bool is_eq_func)
 | 
						|
    const override
 | 
						|
  {
 | 
						|
    return Data_type_compatibility::OK;
 | 
						|
  }
 | 
						|
  /* cmp_type() cannot be TIME_RESULT, because we want to compare this field against
 | 
						|
     integers. But in all other cases we treat it as TIME_RESULT! */
 | 
						|
};
 | 
						|
 | 
						|
static inline decimal_digits_t fix_dec_arg(decimal_digits_t dec_arg)
 | 
						|
{ return dec_arg >= FLOATING_POINT_DECIMALS ? DECIMAL_NOT_SPECIFIED : dec_arg; }
 | 
						|
 | 
						|
class Field_float final :public Field_real {
 | 
						|
public:
 | 
						|
  Field_float(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,
 | 
						|
              decimal_digits_t 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,
 | 
						|
                fix_dec_arg(dec_arg), zero_arg, unsigned_arg)
 | 
						|
    { }
 | 
						|
  Field_float(uint32 len_arg, bool maybe_null_arg,
 | 
						|
              const LEX_CSTRING *field_name_arg, decimal_digits_t dec_arg)
 | 
						|
    :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0,
 | 
						|
                NONE, field_name_arg, fix_dec_arg(dec_arg), 0, 0)
 | 
						|
    { }
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return &type_handler_float; }
 | 
						|
  enum ha_base_keytype key_type() const override { return HA_KEYTYPE_FLOAT; }
 | 
						|
  int store(const char *to,size_t length,CHARSET_INFO *charset) override;
 | 
						|
  int store(double nr) override;
 | 
						|
  int store(longlong nr, bool unsigned_val) override;
 | 
						|
  int reset() override { bzero(ptr,sizeof(float)); return 0; }
 | 
						|
  double val_real() override;
 | 
						|
  longlong val_int() override;
 | 
						|
  String *val_str(String *, String *) override;
 | 
						|
  bool send(Protocol *protocol) override;
 | 
						|
  int cmp(const uchar *,const uchar *) const override;
 | 
						|
  void sort_string(uchar *buff, uint length) override;
 | 
						|
  uint32 pack_length() const override { return sizeof(float); }
 | 
						|
  uint row_pack_length() const override { return pack_length(); }
 | 
						|
  ulonglong get_max_int_value() const override
 | 
						|
  {
 | 
						|
    /*
 | 
						|
      We use the maximum as per IEEE754-2008 standard, 2^24
 | 
						|
    */
 | 
						|
    return 0x1000000ULL;
 | 
						|
  }
 | 
						|
  Binlog_type_info binlog_type_info() const override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_double :public Field_real {
 | 
						|
  longlong val_int_from_real(bool want_unsigned_result);
 | 
						|
public:
 | 
						|
  Field_double(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,
 | 
						|
	       decimal_digits_t 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,
 | 
						|
                fix_dec_arg(dec_arg), zero_arg, unsigned_arg)
 | 
						|
    { }
 | 
						|
  Field_double(uint32 len_arg, bool maybe_null_arg,
 | 
						|
               const LEX_CSTRING *field_name_arg, decimal_digits_t dec_arg)
 | 
						|
    :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0,
 | 
						|
                NONE, field_name_arg, fix_dec_arg(dec_arg), 0, 0)
 | 
						|
    { }
 | 
						|
  Field_double(uint32 len_arg, bool maybe_null_arg,
 | 
						|
               const LEX_CSTRING *field_name_arg,
 | 
						|
	       decimal_digits_t dec_arg, bool not_fixed_arg)
 | 
						|
    :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0,
 | 
						|
                NONE, field_name_arg, fix_dec_arg(dec_arg), 0, 0)
 | 
						|
    {
 | 
						|
      not_fixed= not_fixed_arg;
 | 
						|
    }
 | 
						|
  void init_for_tmp_table(Field *org_field, TABLE *new_table) override
 | 
						|
  {
 | 
						|
    Field::init_for_tmp_table(org_field, new_table);
 | 
						|
    not_fixed= true;
 | 
						|
  }
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return &type_handler_double; }
 | 
						|
  enum ha_base_keytype key_type() const override final { return HA_KEYTYPE_DOUBLE; }
 | 
						|
  int  store(const char *to,size_t length,CHARSET_INFO *charset) override final;
 | 
						|
  int  store(double nr) override final;
 | 
						|
  int  store(longlong nr, bool unsigned_val) override final;
 | 
						|
  int reset() override final { bzero(ptr,sizeof(double)); return 0; }
 | 
						|
  double val_real() override final;
 | 
						|
  longlong val_int() override final { return val_int_from_real(false); }
 | 
						|
  ulonglong val_uint() override final { return (ulonglong) val_int_from_real(true); }
 | 
						|
  String *val_str(String *, String *) override final;
 | 
						|
  bool send(Protocol *protocol) override;
 | 
						|
  int cmp(const uchar *,const uchar *) const override final;
 | 
						|
  void sort_string(uchar *buff, uint length) override final;
 | 
						|
  uint32 pack_length() const override final { return sizeof(double); }
 | 
						|
  uint row_pack_length() const override final { return pack_length(); }
 | 
						|
  ulonglong get_max_int_value() const override final
 | 
						|
  {
 | 
						|
    /*
 | 
						|
      We use the maximum as per IEEE754-2008 standard, 2^53
 | 
						|
    */
 | 
						|
    return 0x20000000000000ULL;
 | 
						|
  }
 | 
						|
  Binlog_type_info binlog_type_info() const override final;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/* Everything saved in this will disappear. It will always return NULL */
 | 
						|
 | 
						|
class Field_null :public Field_str {
 | 
						|
  static uchar null[1];
 | 
						|
public:
 | 
						|
  Field_null(uchar *ptr_arg, uint32 len_arg,
 | 
						|
	     enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
 | 
						|
	     const DTCollation &collation)
 | 
						|
    :Field_str(ptr_arg, len_arg, null, 1,
 | 
						|
	       unireg_check_arg, field_name_arg, collation)
 | 
						|
    {}
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return &type_handler_null; }
 | 
						|
  enum_conv_type rpl_conv_type_from(const Conv_source &source,
 | 
						|
                                    const Relay_log_info *rli,
 | 
						|
                                    const Conv_param ¶m) const override;
 | 
						|
  Information_schema_character_attributes
 | 
						|
    information_schema_character_attributes() const override
 | 
						|
  {
 | 
						|
    return Information_schema_character_attributes();
 | 
						|
  }
 | 
						|
  Copy_func *get_copy_func(const Field *from) const override
 | 
						|
  {
 | 
						|
    return do_field_string;
 | 
						|
  }
 | 
						|
  int  store(const char *to, size_t length, CHARSET_INFO *cs) override final
 | 
						|
  { null[0]=1; return 0; }
 | 
						|
  int store(double nr) override final { null[0]=1; return 0; }
 | 
						|
  int store(longlong nr, bool unsigned_val) override final { null[0]=1; return 0; }
 | 
						|
  int store_decimal(const my_decimal *d) override final { null[0]=1; return 0; }
 | 
						|
  int reset() override final { return 0; }
 | 
						|
  double val_real() override final { return 0.0;}
 | 
						|
  longlong val_int() override final { return 0;}
 | 
						|
  bool val_bool() override final { return false; }
 | 
						|
  my_decimal *val_decimal(my_decimal *) override final { return 0; }
 | 
						|
  String *val_str(String *value,String *value2) override final
 | 
						|
  { value2->length(0); return value2;}
 | 
						|
  bool is_equal(const Column_definition &new_field) const override final;
 | 
						|
  int cmp(const uchar *a, const uchar *b) const override final { return 0;}
 | 
						|
  void sort_string(uchar *buff, uint length) override final {}
 | 
						|
  uint32 pack_length() const override final { return 0; }
 | 
						|
  void sql_type(String &str) const override final;
 | 
						|
  uint size_of() const override final { return sizeof *this; }
 | 
						|
  uint32 max_display_length() const override final { return 4; }
 | 
						|
  void move_field_offset(my_ptrdiff_t ptr_diff) override final {}
 | 
						|
  Data_type_compatibility can_optimize_keypart_ref(const Item_bool_func *cond,
 | 
						|
                                                   const Item *item)
 | 
						|
                                                   const override final
 | 
						|
  {
 | 
						|
    return Data_type_compatibility::INCOMPATIBLE_DATA_TYPE;
 | 
						|
  }
 | 
						|
  Data_type_compatibility can_optimize_group_min_max(const Item_bool_func *cond,
 | 
						|
                                                     const Item *const_item)
 | 
						|
                                                     const override final
 | 
						|
  {
 | 
						|
    return Data_type_compatibility::INCOMPATIBLE_DATA_TYPE;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_temporal :public Field {
 | 
						|
protected:
 | 
						|
  Item *get_equal_const_item_datetime(THD *thd, const Context &ctx,
 | 
						|
                                      Item *const_item);
 | 
						|
  void set_warnings(Sql_condition::enum_warning_level trunc_level,
 | 
						|
                    const ErrConv *str, int was_cut, const char *typestr);
 | 
						|
  int store_TIME_return_code_with_warnings(int warn, const ErrConv *str,
 | 
						|
                                           const char *typestr)
 | 
						|
  {
 | 
						|
    if (!MYSQL_TIME_WARN_HAVE_WARNINGS(warn) &&
 | 
						|
        MYSQL_TIME_WARN_HAVE_NOTES(warn))
 | 
						|
    {
 | 
						|
      set_warnings(Sql_condition::WARN_LEVEL_NOTE, str,
 | 
						|
                   warn | MYSQL_TIME_WARN_TRUNCATED, typestr);
 | 
						|
      return 3;
 | 
						|
    }
 | 
						|
    set_warnings(Sql_condition::WARN_LEVEL_WARN, str, warn, typestr);
 | 
						|
    return warn ? 2 : 0;
 | 
						|
  }
 | 
						|
  int store_invalid_with_warning(const ErrConv *str, int was_cut,
 | 
						|
                                 const char *typestr)
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(was_cut);
 | 
						|
    reset();
 | 
						|
    Sql_condition::enum_warning_level level= Sql_condition::WARN_LEVEL_WARN;
 | 
						|
    if (was_cut & MYSQL_TIME_WARN_ZERO_DATE)
 | 
						|
    {
 | 
						|
      set_warnings(level, str, MYSQL_TIME_WARN_OUT_OF_RANGE, typestr);
 | 
						|
      return 2;
 | 
						|
    }
 | 
						|
    set_warnings(level, str, MYSQL_TIME_WARN_TRUNCATED, typestr);
 | 
						|
    return 1;
 | 
						|
  }
 | 
						|
  void sql_type_comment(String &str,
 | 
						|
                        const Name &name,
 | 
						|
                        const Name &comment) const;
 | 
						|
  void sql_type_dec_comment(String &str,
 | 
						|
                            const Name &name, uint dec,
 | 
						|
                            const Name &comment) const;
 | 
						|
  void sql_type_opt_dec_comment(String &str,
 | 
						|
                                const Name &name, uint dec,
 | 
						|
                                const Name &comment) const
 | 
						|
  {
 | 
						|
    if (dec)
 | 
						|
      sql_type_dec_comment(str, name, dec, comment);
 | 
						|
    else
 | 
						|
      sql_type_comment(str, name, comment);
 | 
						|
  }
 | 
						|
  static const Name &type_version_mysql56();
 | 
						|
public:
 | 
						|
  Field_temporal(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
 | 
						|
                 uchar null_bit_arg, utype unireg_check_arg,
 | 
						|
                 const LEX_CSTRING *field_name_arg)
 | 
						|
    :Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
 | 
						|
               field_name_arg)
 | 
						|
    { flags|= BINARY_FLAG; }
 | 
						|
  int  store_hex_hybrid(const char *str, size_t length) override
 | 
						|
  {
 | 
						|
    return store(str, length, &my_charset_bin);
 | 
						|
  }
 | 
						|
  sql_mode_t can_handle_sql_mode_dependency_on_store() const override;
 | 
						|
  Copy_func *get_copy_func(const Field *from) const override;
 | 
						|
  int save_in_field(Field *to) override
 | 
						|
  {
 | 
						|
    MYSQL_TIME ltime;
 | 
						|
    // For temporal types no truncation needed. Rounding mode is not important.
 | 
						|
    if (get_date(<ime, TIME_CONV_NONE | TIME_FRAC_NONE))
 | 
						|
      return to->reset();
 | 
						|
    return to->store_time_dec(<ime, decimals());
 | 
						|
  }
 | 
						|
  bool memcpy_field_possible(const Field *from) const override;
 | 
						|
  uint32 max_display_length() const override { return field_length; }
 | 
						|
  bool str_needs_quotes() const override { return true; }
 | 
						|
  CHARSET_INFO *charset() const override
 | 
						|
  {
 | 
						|
    return DTCollation_numeric::singleton().collation;
 | 
						|
  }
 | 
						|
  const DTCollation &dtcollation() const override
 | 
						|
  {
 | 
						|
    return DTCollation_numeric::singleton();
 | 
						|
  }
 | 
						|
  CHARSET_INFO *sort_charset() const override { return &my_charset_bin; }
 | 
						|
  bool binary() const override { return true; }
 | 
						|
  bool val_bool() override { return val_real() != 0e0; }
 | 
						|
  bool is_equal(const Column_definition &new_field) const override;
 | 
						|
  bool eq_def(const Field *field) const override
 | 
						|
  {
 | 
						|
    return (Field::eq_def(field) && decimals() == field->decimals());
 | 
						|
  }
 | 
						|
  my_decimal *val_decimal(my_decimal*) override;
 | 
						|
  double pos_in_interval(Field *min, Field *max) override
 | 
						|
  {
 | 
						|
    return pos_in_interval_val_real(min, max);
 | 
						|
  }
 | 
						|
  Data_type_compatibility can_optimize_keypart_ref(const Item_bool_func *cond,
 | 
						|
                                                   const Item *item)
 | 
						|
                                                   const override;
 | 
						|
  Data_type_compatibility can_optimize_group_min_max(const Item_bool_func *cond,
 | 
						|
                                                     const Item *const_item)
 | 
						|
                                                     const override;
 | 
						|
  Data_type_compatibility can_optimize_range(const Item_bool_func *cond,
 | 
						|
                                             const Item *item,
 | 
						|
                                             bool is_eq_func) const override
 | 
						|
  {
 | 
						|
    return Data_type_compatibility::OK;
 | 
						|
  }
 | 
						|
  SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part,
 | 
						|
                       const Item_bool_func *cond,
 | 
						|
                       scalar_comparison_op op, Item *value) override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Abstract class for:
 | 
						|
  - DATE
 | 
						|
  - DATETIME
 | 
						|
  - DATETIME(1..6)
 | 
						|
  - DATETIME(0..6) - MySQL56 version
 | 
						|
*/
 | 
						|
class Field_temporal_with_date :public Field_temporal {
 | 
						|
protected:
 | 
						|
  virtual void store_TIME(const MYSQL_TIME *ltime) = 0;
 | 
						|
  void store_datetime(const Datetime &dt)
 | 
						|
  {
 | 
						|
    return store_TIME(dt.get_mysql_time());
 | 
						|
  }
 | 
						|
  virtual bool get_TIME(MYSQL_TIME *ltime, const uchar *pos,
 | 
						|
                        date_mode_t fuzzydate) const = 0;
 | 
						|
  bool validate_MMDD(bool not_zero_date, uint month, uint day,
 | 
						|
                     date_mode_t fuzzydate) const
 | 
						|
  {
 | 
						|
    if (!not_zero_date)
 | 
						|
      return bool(fuzzydate & TIME_NO_ZERO_DATE);
 | 
						|
    if (!month || !day)
 | 
						|
      return bool(fuzzydate & TIME_NO_ZERO_IN_DATE);
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
public:
 | 
						|
  Field_temporal_with_date(uchar *ptr_arg, uint32 len_arg,
 | 
						|
                           uchar *null_ptr_arg, uchar null_bit_arg,
 | 
						|
                           utype unireg_check_arg,
 | 
						|
                           const LEX_CSTRING *field_name_arg)
 | 
						|
    :Field_temporal(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
 | 
						|
                    unireg_check_arg, field_name_arg)
 | 
						|
    {}
 | 
						|
  bool validate_value_in_record(THD *thd, const uchar *record) const override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_timestamp :public Field_temporal {
 | 
						|
protected:
 | 
						|
  int store_TIME_with_warning(THD *, const Datetime *,
 | 
						|
                              const ErrConv *, int warn);
 | 
						|
  virtual void store_TIMEVAL(const timeval &tv)= 0;
 | 
						|
  void store_TIMESTAMP(const Timestamp &ts)
 | 
						|
  {
 | 
						|
    store_TIMEVAL(ts.tv());
 | 
						|
  }
 | 
						|
  int zero_time_stored_return_code_with_warning();
 | 
						|
public:
 | 
						|
  Field_timestamp(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,
 | 
						|
		  TABLE_SHARE *share);
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return &type_handler_timestamp; }
 | 
						|
  enum_conv_type rpl_conv_type_from(const Conv_source &source,
 | 
						|
                                    const Relay_log_info *rli,
 | 
						|
                                    const Conv_param ¶m) const override;
 | 
						|
  Copy_func *get_copy_func(const Field *from) const override;
 | 
						|
  sql_mode_t conversion_depends_on_sql_mode(THD *, Item *) const override;
 | 
						|
  int  store(const char *to,size_t length,CHARSET_INFO *charset) override;
 | 
						|
  int  store(double nr) override;
 | 
						|
  int  store(longlong nr, bool unsigned_val) override;
 | 
						|
  int  store_time_dec(const MYSQL_TIME *ltime, uint dec) override;
 | 
						|
  int  store_decimal(const my_decimal *) override;
 | 
						|
  int  store_timestamp_dec(const timeval &ts, uint dec) override;
 | 
						|
  int  save_in_field(Field *to) override;
 | 
						|
  longlong val_int() override;
 | 
						|
  String *val_str(String *, String *) override;
 | 
						|
  bool zero_pack() const override { return false; }
 | 
						|
  /*
 | 
						|
    This method is used by storage/perfschema and
 | 
						|
    Item_func_now_local::save_in_field().
 | 
						|
  */
 | 
						|
  void store_TIME(my_time_t ts, ulong sec_part)
 | 
						|
  {
 | 
						|
    int warn;
 | 
						|
    time_round_mode_t mode= Datetime::default_round_mode(get_thd());
 | 
						|
    store_TIMESTAMP(Timestamp(ts, sec_part).round(decimals(), mode, &warn));
 | 
						|
  }
 | 
						|
  bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override;
 | 
						|
  int store_native(const Native &value) override;
 | 
						|
  bool validate_value_in_record(THD *thd, const uchar *record) const override;
 | 
						|
  Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item)
 | 
						|
    override
 | 
						|
  {
 | 
						|
    return get_equal_const_item_datetime(thd, ctx, const_item);
 | 
						|
  }
 | 
						|
  bool load_data_set_null(THD *thd) override;
 | 
						|
  bool load_data_set_no_data(THD *thd, bool fixed_format) override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_timestamp0 :public Field_timestamp
 | 
						|
{
 | 
						|
  void store_TIMEVAL(const timeval &tv) override
 | 
						|
  {
 | 
						|
    int4store(ptr, tv.tv_sec);
 | 
						|
  }
 | 
						|
public:
 | 
						|
  Field_timestamp0(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,
 | 
						|
		   TABLE_SHARE *share)
 | 
						|
   :Field_timestamp(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
 | 
						|
                    unireg_check_arg, field_name_arg, share)
 | 
						|
  { }
 | 
						|
  enum ha_base_keytype key_type() const override
 | 
						|
  { return HA_KEYTYPE_ULONG_INT; }
 | 
						|
  void sql_type(String &str) const override
 | 
						|
  {
 | 
						|
    sql_type_comment(str, Field_timestamp0::type_handler()->name(),
 | 
						|
                     Type_handler::version_mariadb53());
 | 
						|
  }
 | 
						|
  double val_real() override
 | 
						|
  {
 | 
						|
    return (double) Field_timestamp0::val_int();
 | 
						|
  }
 | 
						|
  bool send(Protocol *protocol) override;
 | 
						|
  int cmp(const uchar *,const uchar *) const override;
 | 
						|
  void sort_string(uchar *buff,uint length) override;
 | 
						|
  uint32 pack_length() const override { return 4; }
 | 
						|
  int set_time() override;
 | 
						|
  /* Get TIMESTAMP field value as seconds since begging of Unix Epoch */
 | 
						|
  my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const override;
 | 
						|
  bool val_native(Native *to) override;
 | 
						|
  uchar *pack(uchar *to, const uchar *from, uint) override
 | 
						|
  {
 | 
						|
    return pack_int32(to, from);
 | 
						|
  }
 | 
						|
  const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end,
 | 
						|
                      uint) override
 | 
						|
  {
 | 
						|
    return unpack_int32(to, from, from_end);
 | 
						|
  }
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Abstract class for:
 | 
						|
  - TIMESTAMP(1..6)
 | 
						|
  - TIMESTAMP(0..6) - MySQL56 version
 | 
						|
*/
 | 
						|
class Field_timestamp_with_dec :public Field_timestamp {
 | 
						|
protected:
 | 
						|
  decimal_digits_t dec;
 | 
						|
public:
 | 
						|
  Field_timestamp_with_dec(uchar *ptr_arg,
 | 
						|
                           uchar *null_ptr_arg, uchar null_bit_arg,
 | 
						|
                           enum utype unireg_check_arg,
 | 
						|
                           const LEX_CSTRING *field_name_arg,
 | 
						|
                           TABLE_SHARE *share, decimal_digits_t dec_arg) :
 | 
						|
  Field_timestamp(ptr_arg,
 | 
						|
                  MAX_DATETIME_WIDTH + dec_arg + MY_TEST(dec_arg),
 | 
						|
                  null_ptr_arg,
 | 
						|
                  null_bit_arg, unireg_check_arg, field_name_arg, share),
 | 
						|
  dec(dec_arg)
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
 | 
						|
  }
 | 
						|
  decimal_digits_t decimals() const override { return dec; }
 | 
						|
  enum ha_base_keytype key_type() const override { return HA_KEYTYPE_BINARY; }
 | 
						|
  uchar *pack(uchar *to, const uchar *from, uint max_length) override
 | 
						|
  { return Field::pack(to, from, max_length); }
 | 
						|
  const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end,
 | 
						|
                      uint param_data) override
 | 
						|
  { return Field::unpack(to, from, from_end, param_data); }
 | 
						|
  void make_send_field(Send_field *field) override;
 | 
						|
  void sort_string(uchar *to, uint length) override
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(length == pack_length());
 | 
						|
    memcpy(to, ptr, length);
 | 
						|
  }
 | 
						|
  bool send(Protocol *protocol) override;
 | 
						|
  double val_real() override;
 | 
						|
  my_decimal* val_decimal(my_decimal*) override;
 | 
						|
  int set_time() override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_timestamp_hires :public Field_timestamp_with_dec {
 | 
						|
  uint sec_part_bytes(uint dec) const
 | 
						|
  {
 | 
						|
    return Type_handler_timestamp::sec_part_bytes(dec);
 | 
						|
  }
 | 
						|
  void store_TIMEVAL(const timeval &tv) override;
 | 
						|
public:
 | 
						|
  Field_timestamp_hires(uchar *ptr_arg,
 | 
						|
                        uchar *null_ptr_arg, uchar null_bit_arg,
 | 
						|
                        enum utype unireg_check_arg,
 | 
						|
                        const LEX_CSTRING *field_name_arg,
 | 
						|
                        TABLE_SHARE *share, decimal_digits_t dec_arg) :
 | 
						|
  Field_timestamp_with_dec(ptr_arg, null_ptr_arg, null_bit_arg,
 | 
						|
                           unireg_check_arg, field_name_arg, share, dec_arg)
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(dec);
 | 
						|
  }
 | 
						|
  void sql_type(String &str) const override
 | 
						|
  {
 | 
						|
    sql_type_dec_comment(str, Field_timestamp_hires::type_handler()->name(),
 | 
						|
                         dec, Type_handler::version_mariadb53());
 | 
						|
  }
 | 
						|
  bool val_native(Native *to) override;
 | 
						|
  my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const override;
 | 
						|
  int cmp(const uchar *,const uchar *) const override;
 | 
						|
  uint32 pack_length() const override { return 4 + sec_part_bytes(dec); }
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  TIMESTAMP(0..6) - MySQL56 version
 | 
						|
*/
 | 
						|
class Field_timestampf :public Field_timestamp_with_dec {
 | 
						|
  void store_TIMEVAL(const timeval &tv) override;
 | 
						|
public:
 | 
						|
  Field_timestampf(uchar *ptr_arg,
 | 
						|
                   uchar *null_ptr_arg, uchar null_bit_arg,
 | 
						|
                   enum utype unireg_check_arg,
 | 
						|
                   const LEX_CSTRING *field_name_arg,
 | 
						|
                   TABLE_SHARE *share, decimal_digits_t dec_arg) :
 | 
						|
    Field_timestamp_with_dec(ptr_arg, null_ptr_arg, null_bit_arg,
 | 
						|
                             unireg_check_arg, field_name_arg, share, dec_arg)
 | 
						|
    {}
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return &type_handler_timestamp2; }
 | 
						|
  enum_field_types binlog_type() const override
 | 
						|
  { return MYSQL_TYPE_TIMESTAMP2; }
 | 
						|
  void sql_type(String &str) const override
 | 
						|
  {
 | 
						|
    sql_type_opt_dec_comment(str, Field_timestampf::type_handler()->name(),
 | 
						|
                             dec, type_version_mysql56());
 | 
						|
 | 
						|
  }
 | 
						|
  enum_conv_type rpl_conv_type_from(const Conv_source &source,
 | 
						|
                                    const Relay_log_info *rli,
 | 
						|
                                    const Conv_param ¶m) const override;
 | 
						|
  uint32 pack_length() const override
 | 
						|
  {
 | 
						|
    return my_timestamp_binary_length(dec);
 | 
						|
  }
 | 
						|
  uint row_pack_length() const override { return pack_length(); }
 | 
						|
  uint pack_length_from_metadata(uint field_metadata) const override
 | 
						|
  {
 | 
						|
    DBUG_ENTER("Field_timestampf::pack_length_from_metadata");
 | 
						|
    uint tmp= my_timestamp_binary_length(field_metadata);
 | 
						|
    DBUG_RETURN(tmp);
 | 
						|
  }
 | 
						|
  int cmp(const uchar *a_ptr,const uchar *b_ptr) const override
 | 
						|
  {
 | 
						|
    return memcmp(a_ptr, b_ptr, pack_length());
 | 
						|
  }
 | 
						|
  void set_max() override;
 | 
						|
  bool is_max() override;
 | 
						|
  my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const override;
 | 
						|
  bool val_native(Native *to) override;
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
  Binlog_type_info binlog_type_info() const override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_year final :public Field_tiny {
 | 
						|
public:
 | 
						|
  Field_year(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)
 | 
						|
    :Field_tiny(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
 | 
						|
		unireg_check_arg, field_name_arg, 1, 1)
 | 
						|
    {}
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  {
 | 
						|
    return field_length == 2 ? &type_handler_year2 : &type_handler_year;
 | 
						|
  }
 | 
						|
  enum_conv_type rpl_conv_type_from(const Conv_source &source,
 | 
						|
                                    const Relay_log_info *rli,
 | 
						|
                                    const Conv_param ¶m) const override;
 | 
						|
  Copy_func *get_copy_func(const Field *from) const override
 | 
						|
  {
 | 
						|
    if (eq_def(from))
 | 
						|
      return get_identical_copy_func();
 | 
						|
    switch (from->cmp_type()) {
 | 
						|
    case STRING_RESULT:
 | 
						|
    {
 | 
						|
      const Type_handler *handler= from->type_handler();
 | 
						|
      if (handler == &type_handler_enum || handler == &type_handler_set)
 | 
						|
        return do_field_int;
 | 
						|
      return do_field_string;
 | 
						|
    }
 | 
						|
    case TIME_RESULT:
 | 
						|
      return do_field_date;
 | 
						|
    case DECIMAL_RESULT:
 | 
						|
      return do_field_decimal;
 | 
						|
    case REAL_RESULT:
 | 
						|
      return do_field_real;
 | 
						|
    case INT_RESULT:
 | 
						|
      break;
 | 
						|
    case ROW_RESULT:
 | 
						|
    default:
 | 
						|
      DBUG_ASSERT(0);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    return do_field_int;
 | 
						|
  }
 | 
						|
  int  store(const char *to,size_t length,CHARSET_INFO *charset) override;
 | 
						|
  int  store(double nr) override;
 | 
						|
  int  store(longlong nr, bool unsigned_val) override;
 | 
						|
  int  store_time_dec(const MYSQL_TIME *ltime, uint dec) override;
 | 
						|
  double val_real() override;
 | 
						|
  longlong val_int() override;
 | 
						|
  String *val_str(String *, String *) override;
 | 
						|
  bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override;
 | 
						|
  bool send(Protocol *protocol) override;
 | 
						|
  Information_schema_numeric_attributes
 | 
						|
    information_schema_numeric_attributes() const override
 | 
						|
  {
 | 
						|
    return Information_schema_numeric_attributes();
 | 
						|
  }
 | 
						|
  uint32 max_display_length() const override { return field_length; }
 | 
						|
  void sql_type(String &str) const override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_date_common :public Field_temporal_with_date
 | 
						|
{
 | 
						|
protected:
 | 
						|
  int store_TIME_with_warning(const Datetime *ltime, const ErrConv *str,
 | 
						|
                              int was_cut);
 | 
						|
public:
 | 
						|
  Field_date_common(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
 | 
						|
                    enum utype unireg_check_arg,
 | 
						|
                    const LEX_CSTRING *field_name_arg)
 | 
						|
    :Field_temporal_with_date(ptr_arg, MAX_DATE_WIDTH,
 | 
						|
                              null_ptr_arg, null_bit_arg,
 | 
						|
                              unireg_check_arg, field_name_arg)
 | 
						|
  {}
 | 
						|
  Copy_func *get_copy_func(const Field *from) const override;
 | 
						|
  SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part,
 | 
						|
                       const Item_bool_func *cond,
 | 
						|
                       scalar_comparison_op op, Item *value) override;
 | 
						|
  int  store(const char *to, size_t length, CHARSET_INFO *charset) override;
 | 
						|
  int  store(double nr) override;
 | 
						|
  int  store(longlong nr, bool unsigned_val) override;
 | 
						|
  int  store_time_dec(const MYSQL_TIME *ltime, uint dec) override;
 | 
						|
  int  store_decimal(const my_decimal *) override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_date final :public Field_date_common
 | 
						|
{
 | 
						|
  void store_TIME(const MYSQL_TIME *ltime) override;
 | 
						|
  bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, date_mode_t fuzzydate)
 | 
						|
    const override;
 | 
						|
public:
 | 
						|
  Field_date(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
 | 
						|
	     enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg)
 | 
						|
    :Field_date_common(ptr_arg, null_ptr_arg, null_bit_arg,
 | 
						|
                       unireg_check_arg, field_name_arg) {}
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return &type_handler_date; }
 | 
						|
  enum ha_base_keytype key_type() const override
 | 
						|
  { return HA_KEYTYPE_ULONG_INT; }
 | 
						|
  enum_conv_type rpl_conv_type_from(const Conv_source &source,
 | 
						|
                                    const Relay_log_info *rli,
 | 
						|
                                    const Conv_param ¶m) const override;
 | 
						|
  int reset() override { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; }
 | 
						|
  bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override
 | 
						|
  { return Field_date::get_TIME(ltime, ptr, fuzzydate); }
 | 
						|
  double val_real() override;
 | 
						|
  longlong val_int() override;
 | 
						|
  String *val_str(String *, String *) override;
 | 
						|
  bool send(Protocol *protocol) override;
 | 
						|
  int cmp(const uchar *,const uchar *) const override;
 | 
						|
  void sort_string(uchar *buff,uint length) override;
 | 
						|
  uint32 pack_length() const override { return 4; }
 | 
						|
  void sql_type(String &str) const override;
 | 
						|
  uchar *pack(uchar* to, const uchar *from, uint) override
 | 
						|
  {
 | 
						|
    return pack_int32(to, from);
 | 
						|
  }
 | 
						|
  const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end,
 | 
						|
                      uint) override
 | 
						|
  {
 | 
						|
    return unpack_int32(to, from, from_end);
 | 
						|
  }
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_newdate final :public Field_date_common
 | 
						|
{
 | 
						|
  void store_TIME(const MYSQL_TIME *ltime) override;
 | 
						|
  bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, date_mode_t fuzzydate)
 | 
						|
    const override;
 | 
						|
public:
 | 
						|
  Field_newdate(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
 | 
						|
		enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg)
 | 
						|
    :Field_date_common(ptr_arg, null_ptr_arg, null_bit_arg,
 | 
						|
                       unireg_check_arg, field_name_arg)
 | 
						|
    {}
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return &type_handler_newdate; }
 | 
						|
  enum ha_base_keytype key_type() const override { return HA_KEYTYPE_UINT24; }
 | 
						|
  enum_conv_type rpl_conv_type_from(const Conv_source &source,
 | 
						|
                                    const Relay_log_info *rli,
 | 
						|
                                    const Conv_param ¶m) const override;
 | 
						|
  int reset() override { ptr[0]=ptr[1]=ptr[2]=0; return 0; }
 | 
						|
  double val_real() override;
 | 
						|
  longlong val_int() override;
 | 
						|
  String *val_str(String *, String *) override;
 | 
						|
  bool send(Protocol *protocol) override;
 | 
						|
  int cmp(const uchar *,const uchar *) const override;
 | 
						|
  void sort_string(uchar *buff,uint length) override;
 | 
						|
  uint32 pack_length() const override { return 3; }
 | 
						|
  void sql_type(String &str) const override;
 | 
						|
  bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override
 | 
						|
  { return Field_newdate::get_TIME(ltime, ptr, fuzzydate); }
 | 
						|
  longlong val_datetime_packed(THD *thd) override;
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
  Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item)
 | 
						|
    override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_time :public Field_temporal {
 | 
						|
  /*
 | 
						|
    when this Field_time instance is used for storing values for index lookups
 | 
						|
    (see class store_key, Field::new_key_field(), etc), the following
 | 
						|
    might be set to TO_DAYS(CURDATE()). See also Field_time::store_time_dec()
 | 
						|
  */
 | 
						|
  long curdays;
 | 
						|
protected:
 | 
						|
  virtual void store_TIME(const MYSQL_TIME *ltime)= 0;
 | 
						|
  void store_TIME(const Time &t) { return store_TIME(t.get_mysql_time()); }
 | 
						|
  int store_TIME_with_warning(const Time *ltime, const ErrConv *str, int warn);
 | 
						|
  bool check_zero_in_date_with_warn(date_mode_t fuzzydate);
 | 
						|
  static void do_field_time(Copy_field *copy);
 | 
						|
public:
 | 
						|
  Field_time(uchar *ptr_arg, uint length_arg, uchar *null_ptr_arg,
 | 
						|
             uchar null_bit_arg, enum utype unireg_check_arg,
 | 
						|
             const LEX_CSTRING *field_name_arg)
 | 
						|
    :Field_temporal(ptr_arg, length_arg, null_ptr_arg, null_bit_arg,
 | 
						|
                    unireg_check_arg, field_name_arg), curdays(0)
 | 
						|
    {}
 | 
						|
  bool can_be_substituted_to_equal_item(const Context &ctx,
 | 
						|
                                        const Item_equal *item_equal) override;
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return &type_handler_time; }
 | 
						|
  enum_conv_type rpl_conv_type_from(const Conv_source &source,
 | 
						|
                                    const Relay_log_info *rli,
 | 
						|
                                    const Conv_param ¶m) const override;
 | 
						|
  Copy_func *get_copy_func(const Field *from) const override
 | 
						|
  {
 | 
						|
    return from->cmp_type() == REAL_RESULT ? do_field_string : // MDEV-9344
 | 
						|
           from->type() == MYSQL_TYPE_YEAR ? do_field_int :
 | 
						|
           from->type() == MYSQL_TYPE_BIT  ? do_field_int :
 | 
						|
           eq_def(from)                    ? get_identical_copy_func() :
 | 
						|
                                             do_field_time;
 | 
						|
  }
 | 
						|
  bool memcpy_field_possible(const Field *from) const override
 | 
						|
  {
 | 
						|
    return real_type() == from->real_type() &&
 | 
						|
           decimals() == from->decimals();
 | 
						|
  }
 | 
						|
  sql_mode_t conversion_depends_on_sql_mode(THD *, Item *) const override;
 | 
						|
  int store_native(const Native &value) override;
 | 
						|
  bool val_native(Native *to) override;
 | 
						|
  int store_time_dec(const MYSQL_TIME *ltime, uint dec) override;
 | 
						|
  int store(const char *to,size_t length,CHARSET_INFO *charset) override;
 | 
						|
  int store(double nr) override;
 | 
						|
  int store(longlong nr, bool unsigned_val) override;
 | 
						|
  int  store_decimal(const my_decimal *) override;
 | 
						|
  String *val_str(String *, String *) override;
 | 
						|
  bool send(Protocol *protocol) override;
 | 
						|
  void set_curdays(THD *thd);
 | 
						|
  Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
 | 
						|
                       uchar *new_ptr, uint32 length,
 | 
						|
                       uchar *new_null_ptr, uint new_null_bit) override;
 | 
						|
  Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item)
 | 
						|
    override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_time0 final :public Field_time
 | 
						|
{
 | 
						|
protected:
 | 
						|
  void store_TIME(const MYSQL_TIME *ltime) override;
 | 
						|
public:
 | 
						|
  Field_time0(uchar *ptr_arg, uint length_arg, uchar *null_ptr_arg,
 | 
						|
             uchar null_bit_arg, enum utype unireg_check_arg,
 | 
						|
             const LEX_CSTRING *field_name_arg)
 | 
						|
    :Field_time(ptr_arg, length_arg, null_ptr_arg, null_bit_arg,
 | 
						|
                unireg_check_arg, field_name_arg)
 | 
						|
  { }
 | 
						|
  enum ha_base_keytype key_type() const override { return HA_KEYTYPE_INT24; }
 | 
						|
  void sql_type(String &str) const override
 | 
						|
  {
 | 
						|
    sql_type_comment(str, Field_time0::type_handler()->name(),
 | 
						|
                     Type_handler::version_mariadb53());
 | 
						|
  }
 | 
						|
  double val_real() override;
 | 
						|
  longlong val_int() override;
 | 
						|
  bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override;
 | 
						|
  int cmp(const uchar *,const uchar *) const override;
 | 
						|
  void sort_string(uchar *buff,uint length) override;
 | 
						|
  uint32 pack_length() const override { return 3; }
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Abstract class for:
 | 
						|
  - TIME(1..6)
 | 
						|
  - TIME(0..6) - MySQL56 version
 | 
						|
*/
 | 
						|
class Field_time_with_dec :public Field_time {
 | 
						|
protected:
 | 
						|
  decimal_digits_t dec;
 | 
						|
public:
 | 
						|
  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,
 | 
						|
                      decimal_digits_t 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);
 | 
						|
  }
 | 
						|
  decimal_digits_t decimals() const override { return dec; }
 | 
						|
  enum ha_base_keytype key_type() const override { return HA_KEYTYPE_BINARY; }
 | 
						|
  longlong val_int() override;
 | 
						|
  double val_real() override;
 | 
						|
  void make_send_field(Send_field *) override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  TIME(1..6)
 | 
						|
*/
 | 
						|
class Field_time_hires final :public Field_time_with_dec {
 | 
						|
  longlong zero_point;
 | 
						|
  void store_TIME(const MYSQL_TIME *) override;
 | 
						|
public:
 | 
						|
  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,
 | 
						|
                   decimal_digits_t 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);
 | 
						|
  }
 | 
						|
  void sql_type(String &str) const override
 | 
						|
  {
 | 
						|
    sql_type_dec_comment(str, Field_time_hires::type_handler()->name(),
 | 
						|
                         dec, Type_handler::version_mariadb53());
 | 
						|
  }
 | 
						|
  int reset() override;
 | 
						|
  bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override;
 | 
						|
  int cmp(const uchar *,const uchar *) const override;
 | 
						|
  void sort_string(uchar *buff,uint length) override;
 | 
						|
  uint32 pack_length() const override
 | 
						|
  { return Type_handler_time::hires_bytes(dec); }
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  TIME(0..6) - MySQL56 version
 | 
						|
*/
 | 
						|
class Field_timef final :public Field_time_with_dec {
 | 
						|
  void store_TIME(const MYSQL_TIME *ltime) override;
 | 
						|
public:
 | 
						|
  Field_timef(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
 | 
						|
              enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
 | 
						|
              decimal_digits_t 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 <= TIME_SECOND_PART_DIGITS);
 | 
						|
  }
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return &type_handler_time2; }
 | 
						|
  enum_field_types binlog_type() const override { return MYSQL_TYPE_TIME2; }
 | 
						|
  void sql_type(String &str) const override
 | 
						|
  {
 | 
						|
    sql_type_opt_dec_comment(str, Field_timef::type_handler()->name(),
 | 
						|
                             dec, type_version_mysql56());
 | 
						|
  }
 | 
						|
  enum_conv_type rpl_conv_type_from(const Conv_source &source,
 | 
						|
                                    const Relay_log_info *rli,
 | 
						|
                                    const Conv_param ¶m) const override;
 | 
						|
  uint32 pack_length() const override
 | 
						|
  {
 | 
						|
    return my_time_binary_length(dec);
 | 
						|
  }
 | 
						|
  uint row_pack_length() const override { return pack_length(); }
 | 
						|
  uint pack_length_from_metadata(uint field_metadata) const override
 | 
						|
  {
 | 
						|
    DBUG_ENTER("Field_timef::pack_length_from_metadata");
 | 
						|
    uint tmp= my_time_binary_length(field_metadata);
 | 
						|
    DBUG_RETURN(tmp);
 | 
						|
  }
 | 
						|
  void sort_string(uchar *to, uint length) override
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(length == Field_timef::pack_length());
 | 
						|
    memcpy(to, ptr, length);
 | 
						|
  }
 | 
						|
  int cmp(const uchar *a_ptr, const uchar *b_ptr) const override
 | 
						|
  {
 | 
						|
    return memcmp(a_ptr, b_ptr, pack_length());
 | 
						|
  }
 | 
						|
  int reset() override;
 | 
						|
  bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override;
 | 
						|
  longlong val_time_packed(THD *thd) override;
 | 
						|
  int store_native(const Native &value) override;
 | 
						|
  bool val_native(Native *to) override;
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
  Binlog_type_info binlog_type_info() const override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_datetime :public Field_temporal_with_date {
 | 
						|
protected:
 | 
						|
  int store_TIME_with_warning(const Datetime *ltime, const ErrConv *str,
 | 
						|
                              int was_cut);
 | 
						|
public:
 | 
						|
  Field_datetime(uchar *ptr_arg, uint length_arg, uchar *null_ptr_arg,
 | 
						|
                 uchar null_bit_arg, enum utype unireg_check_arg,
 | 
						|
                 const LEX_CSTRING *field_name_arg)
 | 
						|
    :Field_temporal_with_date(ptr_arg, length_arg, null_ptr_arg, null_bit_arg,
 | 
						|
                              unireg_check_arg, field_name_arg)
 | 
						|
    {
 | 
						|
      if (unireg_check == TIMESTAMP_UN_FIELD ||
 | 
						|
          unireg_check == TIMESTAMP_DNUN_FIELD)
 | 
						|
        flags|= ON_UPDATE_NOW_FLAG;
 | 
						|
    }
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return &type_handler_datetime; }
 | 
						|
  sql_mode_t conversion_depends_on_sql_mode(THD *, Item *) const override;
 | 
						|
  enum_conv_type rpl_conv_type_from(const Conv_source &source,
 | 
						|
                                    const Relay_log_info *rli,
 | 
						|
                                    const Conv_param ¶m) const override;
 | 
						|
  int  store(const char *to, size_t length, CHARSET_INFO *charset) override;
 | 
						|
  int  store(double nr) override;
 | 
						|
  int  store(longlong nr, bool unsigned_val) override;
 | 
						|
  int  store_time_dec(const MYSQL_TIME *ltime, uint dec) override;
 | 
						|
  int  store_decimal(const my_decimal *) override;
 | 
						|
  int set_time() override;
 | 
						|
  Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item)
 | 
						|
    override
 | 
						|
  {
 | 
						|
    return get_equal_const_item_datetime(thd, ctx, const_item);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
  Stored as a 8 byte unsigned int. Should sometimes be change to a 6 byte
 | 
						|
*/
 | 
						|
 | 
						|
class Field_datetime0 final :public Field_datetime
 | 
						|
{
 | 
						|
  void store_TIME(const MYSQL_TIME *ltime) override;
 | 
						|
  bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, date_mode_t fuzzydate)
 | 
						|
    const override;
 | 
						|
public:
 | 
						|
  Field_datetime0(uchar *ptr_arg, uint length_arg, uchar *null_ptr_arg,
 | 
						|
                 uchar null_bit_arg, enum utype unireg_check_arg,
 | 
						|
                 const LEX_CSTRING *field_name_arg)
 | 
						|
    :Field_datetime(ptr_arg, length_arg, null_ptr_arg, null_bit_arg,
 | 
						|
                    unireg_check_arg, field_name_arg)
 | 
						|
  {}
 | 
						|
  enum ha_base_keytype key_type() const override
 | 
						|
  { return HA_KEYTYPE_ULONGLONG; }
 | 
						|
  void sql_type(String &str) const override
 | 
						|
  {
 | 
						|
    sql_type_comment(str, Field_datetime0::type_handler()->name(),
 | 
						|
                     Type_handler::version_mariadb53());
 | 
						|
  }
 | 
						|
  double val_real() override
 | 
						|
  {
 | 
						|
    return (double) Field_datetime0::val_int();
 | 
						|
  }
 | 
						|
  longlong val_int() override;
 | 
						|
  String *val_str(String *, String *) override;
 | 
						|
  bool send(Protocol *protocol) override;
 | 
						|
  int cmp(const uchar *,const uchar *) const override;
 | 
						|
  void sort_string(uchar *buff,uint length) override;
 | 
						|
  uint32 pack_length() const override { return 8; }
 | 
						|
  bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override
 | 
						|
  { return Field_datetime0::get_TIME(ltime, ptr, fuzzydate); }
 | 
						|
  uchar *pack(uchar* to, const uchar *from, uint) override
 | 
						|
  {
 | 
						|
    return pack_int64(to, from);
 | 
						|
  }
 | 
						|
  const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end,
 | 
						|
		      uint) override
 | 
						|
  {
 | 
						|
    return unpack_int64(to, from, from_end);
 | 
						|
  }
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Abstract class for:
 | 
						|
  - DATETIME(1..6)
 | 
						|
  - DATETIME(0..6) - MySQL56 version
 | 
						|
*/
 | 
						|
class Field_datetime_with_dec :public Field_datetime {
 | 
						|
protected:
 | 
						|
  decimal_digits_t dec;
 | 
						|
public:
 | 
						|
  Field_datetime_with_dec(uchar *ptr_arg, uchar *null_ptr_arg,
 | 
						|
                          uchar null_bit_arg, enum utype unireg_check_arg,
 | 
						|
                          const LEX_CSTRING *field_name_arg, decimal_digits_t dec_arg)
 | 
						|
    :Field_datetime(ptr_arg, MAX_DATETIME_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);
 | 
						|
  }
 | 
						|
  decimal_digits_t decimals() const override final { return dec; }
 | 
						|
  enum ha_base_keytype key_type() const override final { return HA_KEYTYPE_BINARY; }
 | 
						|
  void make_send_field(Send_field *field) override final;
 | 
						|
  bool send(Protocol *protocol) override final;
 | 
						|
  uchar *pack(uchar *to, const uchar *from, uint max_length) override final
 | 
						|
  { return Field::pack(to, from, max_length); }
 | 
						|
  const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end,
 | 
						|
                      uint param_data) override final
 | 
						|
  { return Field::unpack(to, from, from_end, param_data); }
 | 
						|
  void sort_string(uchar *to, uint length) override final
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(length == pack_length());
 | 
						|
    memcpy(to, ptr, length);
 | 
						|
  }
 | 
						|
  double val_real() override final;
 | 
						|
  longlong val_int() override final;
 | 
						|
  String *val_str(String *, String *) override final;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  DATETIME(1..6)
 | 
						|
*/
 | 
						|
class Field_datetime_hires final :public Field_datetime_with_dec {
 | 
						|
  void store_TIME(const MYSQL_TIME *ltime) override;
 | 
						|
  bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, date_mode_t fuzzydate)
 | 
						|
    const override;
 | 
						|
public:
 | 
						|
  Field_datetime_hires(uchar *ptr_arg, uchar *null_ptr_arg,
 | 
						|
                       uchar null_bit_arg, enum utype unireg_check_arg,
 | 
						|
                       const LEX_CSTRING *field_name_arg, decimal_digits_t dec_arg)
 | 
						|
    :Field_datetime_with_dec(ptr_arg, null_ptr_arg, null_bit_arg,
 | 
						|
                             unireg_check_arg, field_name_arg, dec_arg)
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(dec);
 | 
						|
  }
 | 
						|
  void sql_type(String &str) const override
 | 
						|
  {
 | 
						|
    sql_type_dec_comment(str, Field_datetime_hires::type_handler()->name(),
 | 
						|
                         dec, Type_handler::version_mariadb53());
 | 
						|
  }
 | 
						|
  int cmp(const uchar *,const uchar *) const override;
 | 
						|
  uint32 pack_length() const override
 | 
						|
  { return Type_handler_datetime::hires_bytes(dec); }
 | 
						|
  bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override
 | 
						|
  { return Field_datetime_hires::get_TIME(ltime, ptr, fuzzydate); }
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  DATETIME(0..6) - MySQL56 version
 | 
						|
*/
 | 
						|
 | 
						|
class Field_datetimef final :public Field_datetime_with_dec {
 | 
						|
  void store_TIME(const MYSQL_TIME *ltime) override;
 | 
						|
  bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, date_mode_t fuzzydate)
 | 
						|
    const override;
 | 
						|
public:
 | 
						|
  Field_datetimef(uchar *ptr_arg, uchar *null_ptr_arg,
 | 
						|
                  uchar null_bit_arg, enum utype unireg_check_arg,
 | 
						|
                  const LEX_CSTRING *field_name_arg,  decimal_digits_t dec_arg)
 | 
						|
    :Field_datetime_with_dec(ptr_arg, null_ptr_arg, null_bit_arg,
 | 
						|
                             unireg_check_arg, field_name_arg, dec_arg)
 | 
						|
  {}
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return &type_handler_datetime2; }
 | 
						|
  enum_field_types binlog_type() const override
 | 
						|
  { return MYSQL_TYPE_DATETIME2; }
 | 
						|
  void sql_type(String &str) const override
 | 
						|
  {
 | 
						|
    sql_type_opt_dec_comment(str, Field_datetimef::type_handler()->name(),
 | 
						|
                             dec, type_version_mysql56());
 | 
						|
  }
 | 
						|
  enum_conv_type rpl_conv_type_from(const Conv_source &source,
 | 
						|
                                    const Relay_log_info *rli,
 | 
						|
                                    const Conv_param ¶m) const override;
 | 
						|
  uint32 pack_length() const override
 | 
						|
  {
 | 
						|
    return my_datetime_binary_length(dec);
 | 
						|
  }
 | 
						|
  uint row_pack_length() const override { return pack_length(); }
 | 
						|
  uint pack_length_from_metadata(uint field_metadata) const override
 | 
						|
  {
 | 
						|
    DBUG_ENTER("Field_datetimef::pack_length_from_metadata");
 | 
						|
    uint tmp= my_datetime_binary_length(field_metadata);
 | 
						|
    DBUG_RETURN(tmp);
 | 
						|
  }
 | 
						|
  int cmp(const uchar *a_ptr, const uchar *b_ptr) const override
 | 
						|
  {
 | 
						|
    return memcmp(a_ptr, b_ptr, pack_length());
 | 
						|
  }
 | 
						|
  int reset() override;
 | 
						|
  bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override
 | 
						|
  { return Field_datetimef::get_TIME(ltime, ptr, fuzzydate); }
 | 
						|
  longlong val_datetime_packed(THD *thd) override;
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
  Binlog_type_info binlog_type_info() const override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
static inline Field_timestamp *
 | 
						|
new_Field_timestamp(MEM_ROOT *root,uchar *ptr, uchar *null_ptr, uchar null_bit,
 | 
						|
                    enum Field::utype unireg_check,
 | 
						|
                    const LEX_CSTRING *field_name,
 | 
						|
                    TABLE_SHARE *share, decimal_digits_t dec)
 | 
						|
{
 | 
						|
  if (dec==0)
 | 
						|
    return new (root)
 | 
						|
      Field_timestamp0(ptr, MAX_DATETIME_WIDTH, null_ptr,
 | 
						|
                       null_bit, unireg_check, field_name, share);
 | 
						|
  if (dec >= FLOATING_POINT_DECIMALS)
 | 
						|
    dec= MAX_DATETIME_PRECISION;
 | 
						|
  return new (root)
 | 
						|
    Field_timestamp_hires(ptr, null_ptr, null_bit, unireg_check,
 | 
						|
                          field_name, share, dec);
 | 
						|
}
 | 
						|
 | 
						|
static inline Field_time *
 | 
						|
new_Field_time(MEM_ROOT *root, uchar *ptr, uchar *null_ptr, uchar null_bit,
 | 
						|
               enum Field::utype unireg_check, const LEX_CSTRING *field_name,
 | 
						|
               decimal_digits_t dec)
 | 
						|
{
 | 
						|
  if (dec == 0)
 | 
						|
    return new (root)
 | 
						|
      Field_time0(ptr, MIN_TIME_WIDTH, null_ptr, null_bit, unireg_check,
 | 
						|
                  field_name);
 | 
						|
  if (dec >= FLOATING_POINT_DECIMALS)
 | 
						|
    dec= MAX_DATETIME_PRECISION;
 | 
						|
  return new (root)
 | 
						|
    Field_time_hires(ptr, null_ptr, null_bit, unireg_check, field_name, dec);
 | 
						|
}
 | 
						|
 | 
						|
static inline Field_datetime *
 | 
						|
new_Field_datetime(MEM_ROOT *root, uchar *ptr, uchar *null_ptr, uchar null_bit,
 | 
						|
                   enum Field::utype unireg_check,
 | 
						|
                   const LEX_CSTRING *field_name, decimal_digits_t dec)
 | 
						|
{
 | 
						|
  if (dec == 0)
 | 
						|
    return new (root)
 | 
						|
      Field_datetime0(ptr, MAX_DATETIME_WIDTH, null_ptr, null_bit,
 | 
						|
                      unireg_check, field_name);
 | 
						|
  if (dec >= FLOATING_POINT_DECIMALS)
 | 
						|
    dec= MAX_DATETIME_PRECISION;
 | 
						|
  return new (root)
 | 
						|
    Field_datetime_hires(ptr, null_ptr, null_bit,
 | 
						|
                         unireg_check, field_name, dec);
 | 
						|
}
 | 
						|
 | 
						|
class Field_string final :public Field_longstr {
 | 
						|
  class Warn_filter_string: public Warn_filter
 | 
						|
  {
 | 
						|
  public:
 | 
						|
    Warn_filter_string(const THD *thd, const Field_string *field);
 | 
						|
  };
 | 
						|
  bool is_var_string() const
 | 
						|
  {
 | 
						|
    return can_alter_field_type &&
 | 
						|
           orig_table &&
 | 
						|
           (orig_table->s->db_create_options & HA_OPTION_PACK_RECORD) &&
 | 
						|
           field_length >= 4 &&
 | 
						|
           orig_table->s->frm_version < FRM_VER_TRUE_VARCHAR;
 | 
						|
  }
 | 
						|
  LEX_CSTRING to_lex_cstring() const;
 | 
						|
public:
 | 
						|
  bool can_alter_field_type;
 | 
						|
  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) {};
 | 
						|
  Field_string(uint32 len_arg,bool maybe_null_arg,
 | 
						|
               const LEX_CSTRING *field_name_arg,
 | 
						|
               const DTCollation &collation)
 | 
						|
    :Field_longstr((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0,
 | 
						|
                   NONE, field_name_arg, collation),
 | 
						|
     can_alter_field_type(1) {};
 | 
						|
 | 
						|
  const Type_handler *type_handler() const override;
 | 
						|
  enum ha_base_keytype key_type() const override
 | 
						|
    { return binary() ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; }
 | 
						|
  en_fieldtype tmp_engine_column_type(bool use_packed_rows) const override;
 | 
						|
  bool zero_pack() const override { return false; }
 | 
						|
  Copy_func *get_copy_func(const Field *from) const override;
 | 
						|
  int reset() override
 | 
						|
  {
 | 
						|
    charset()->fill((char*) ptr, field_length, (has_charset() ? ' ' : 0));
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
  int store(const char *to,size_t length,CHARSET_INFO *charset) override;
 | 
						|
  using Field_str::store;
 | 
						|
  double val_real() override;
 | 
						|
  longlong val_int() override;
 | 
						|
  String *val_str(String *, String *) override;
 | 
						|
  my_decimal *val_decimal(my_decimal *) override;
 | 
						|
  int cmp(const uchar *,const uchar *) const override;
 | 
						|
  int cmp_prefix(const uchar *a, const uchar *b, size_t prefix_char_len) const
 | 
						|
    override;
 | 
						|
  void sort_string(uchar *buff,uint length) override;
 | 
						|
  void update_data_type_statistics(Data_type_statistics *st) const override
 | 
						|
  {
 | 
						|
    st->m_fixed_string_count++;
 | 
						|
    st->m_fixed_string_total_length+= pack_length();
 | 
						|
  }
 | 
						|
  void sql_type(String &str) const override;
 | 
						|
  void sql_rpl_type(String*) const override;
 | 
						|
  bool is_equal(const Column_definition &new_field) const override;
 | 
						|
  uchar *pack(uchar *to, const uchar *from, uint max_length) override;
 | 
						|
  const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end,
 | 
						|
                      uint param_data) override;
 | 
						|
  uint pack_length_from_metadata(uint field_metadata) const override
 | 
						|
  {
 | 
						|
    DBUG_PRINT("debug", ("field_metadata: 0x%04x", field_metadata));
 | 
						|
    if (field_metadata == 0)
 | 
						|
      return row_pack_length();
 | 
						|
    return (((field_metadata >> 4) & 0x300) ^ 0x300) + (field_metadata & 0x00ff);
 | 
						|
  }
 | 
						|
  bool compatible_field_size(uint field_metadata, const Relay_log_info *rli,
 | 
						|
                             uint16 mflags, int *order_var) const override;
 | 
						|
  uint row_pack_length() const override { return field_length; }
 | 
						|
  uint packed_col_length(const uchar *to, uint length) override;
 | 
						|
  uint max_packed_col_length(uint max_length) override;
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
  bool has_charset() const override { return charset() != &my_charset_bin; }
 | 
						|
  Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type)
 | 
						|
    override;
 | 
						|
  uint get_key_image(uchar *buff, uint length,
 | 
						|
                     const uchar *ptr_arg, imagetype type) const override;
 | 
						|
  sql_mode_t value_depends_on_sql_mode() const override;
 | 
						|
  sql_mode_t can_handle_sql_mode_dependency_on_store() const override;
 | 
						|
  void print_key_value(String *out, uint32 length) override;
 | 
						|
  Binlog_type_info binlog_type_info() const override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_varstring :public Field_longstr {
 | 
						|
public:
 | 
						|
  const uchar *get_data() const
 | 
						|
  {
 | 
						|
    return get_data(ptr);
 | 
						|
  }
 | 
						|
  const uchar *get_data(const uchar *ptr_arg) const
 | 
						|
  {
 | 
						|
    return ptr_arg + length_bytes;
 | 
						|
  }
 | 
						|
  uint get_length() const
 | 
						|
  {
 | 
						|
    return get_length(ptr);
 | 
						|
  }
 | 
						|
  uint get_length(const uchar *ptr_arg) const
 | 
						|
  {
 | 
						|
    return length_bytes == 1 ? (uint) *ptr_arg : uint2korr(ptr_arg);
 | 
						|
  }
 | 
						|
protected:
 | 
						|
  void store_length(uint32 number)
 | 
						|
  {
 | 
						|
    if (length_bytes == 1)
 | 
						|
      *ptr= (uchar) number;
 | 
						|
    else
 | 
						|
      int2store(ptr, number);
 | 
						|
  }
 | 
						|
  virtual void val_str_from_ptr(String *val, const uchar *ptr) const;
 | 
						|
public:
 | 
						|
  /*
 | 
						|
    The maximum space available in a Field_varstring, in bytes. See
 | 
						|
    length_bytes.
 | 
						|
  */
 | 
						|
  static const uint MAX_SIZE;
 | 
						|
  /* Store number of bytes used to store length (1 or 2) */
 | 
						|
  uint32 length_bytes;
 | 
						|
  Field_varstring(uchar *ptr_arg,
 | 
						|
                  uint32 len_arg, uint length_bytes_arg,
 | 
						|
                  uchar *null_ptr_arg, uchar null_bit_arg,
 | 
						|
		  enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
 | 
						|
		  TABLE_SHARE *share, const DTCollation &collation)
 | 
						|
    :Field_longstr(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
 | 
						|
                   unireg_check_arg, field_name_arg, collation),
 | 
						|
     length_bytes(length_bytes_arg)
 | 
						|
  {
 | 
						|
    share->varchar_fields++;
 | 
						|
  }
 | 
						|
  Field_varstring(uint32 len_arg,bool maybe_null_arg,
 | 
						|
                  const LEX_CSTRING *field_name_arg,
 | 
						|
                  TABLE_SHARE *share, const DTCollation &collation)
 | 
						|
    :Field_longstr((uchar*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0,
 | 
						|
                   NONE, field_name_arg, collation),
 | 
						|
     length_bytes(len_arg < 256 ? 1 :2)
 | 
						|
  {
 | 
						|
    share->varchar_fields++;
 | 
						|
  }
 | 
						|
 | 
						|
  const Type_handler *type_handler() const override;
 | 
						|
  en_fieldtype tmp_engine_column_type(bool use_packed_rows) const override
 | 
						|
  {
 | 
						|
    return FIELD_VARCHAR;
 | 
						|
  }
 | 
						|
  enum ha_base_keytype key_type() const override;
 | 
						|
  uint16 key_part_flag() const override { return HA_VAR_LENGTH_PART; }
 | 
						|
  uint16 key_part_length_bytes() const override { return HA_KEY_BLOB_LENGTH; }
 | 
						|
  uint row_pack_length() const override { return field_length; }
 | 
						|
  bool zero_pack() const override { return false; }
 | 
						|
  int  reset() override { bzero(ptr,field_length+length_bytes); return 0; }
 | 
						|
  uint32 pack_length() const override
 | 
						|
  { return (uint32) field_length+length_bytes; }
 | 
						|
  uint32 key_length() const override { return (uint32) field_length; }
 | 
						|
  uint32 sort_length() const override
 | 
						|
  {
 | 
						|
    return (uint32) field_length + sort_suffix_length();
 | 
						|
  }
 | 
						|
  uint32 sort_suffix_length() const override
 | 
						|
  {
 | 
						|
    return (field_charset() == &my_charset_bin ? length_bytes : 0);
 | 
						|
  }
 | 
						|
  Copy_func *get_copy_func(const Field *from) const override;
 | 
						|
  bool memcpy_field_possible(const Field *from) const override;
 | 
						|
  void update_data_type_statistics(Data_type_statistics *st) const override
 | 
						|
  {
 | 
						|
    st->m_variable_string_count++;
 | 
						|
    st->m_variable_string_total_length+= pack_length();
 | 
						|
  }
 | 
						|
  int  store(const char *to,size_t length,CHARSET_INFO *charset) override;
 | 
						|
  using Field_str::store;
 | 
						|
#ifdef HAVE_MEM_CHECK
 | 
						|
  void mark_unused_memory_as_defined() override;
 | 
						|
#endif
 | 
						|
  double val_real() override;
 | 
						|
  longlong val_int() override;
 | 
						|
  String *val_str(String *, String *) override;
 | 
						|
  my_decimal *val_decimal(my_decimal *) override;
 | 
						|
  bool send(Protocol *protocol) override;
 | 
						|
  int cmp(const uchar *a,const uchar *b) const override;
 | 
						|
  int cmp_prefix(const uchar *a, const uchar *b, size_t prefix_char_len) const
 | 
						|
    override;
 | 
						|
  void sort_string(uchar *buff,uint length) override;
 | 
						|
  uint get_key_image(uchar *buff, uint length,
 | 
						|
                     const uchar *ptr_arg, imagetype type) const override;
 | 
						|
  void set_key_image(const uchar *buff,uint length) override;
 | 
						|
  void sql_type(String &str) const override;
 | 
						|
  void sql_rpl_type(String*) const override;
 | 
						|
  uchar *pack(uchar *to, const uchar *from, uint max_length) override;
 | 
						|
  const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end,
 | 
						|
                      uint param_data) override;
 | 
						|
  int cmp_binary(const uchar *a,const uchar *b, uint32 max_length=~0U) const
 | 
						|
    override;
 | 
						|
  int key_cmp(const uchar *,const uchar*) const override;
 | 
						|
  int key_cmp(const uchar *str, uint length) const override;
 | 
						|
  uint packed_col_length(const uchar *to, uint length) override;
 | 
						|
  uint max_packed_col_length(uint max_length) override;
 | 
						|
  uint32 data_length() override;
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
  bool has_charset() const override
 | 
						|
  { return charset() == &my_charset_bin ? FALSE : TRUE; }
 | 
						|
  Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type)
 | 
						|
    override;
 | 
						|
  Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
 | 
						|
                       uchar *new_ptr, uint32 length,
 | 
						|
                       uchar *new_null_ptr, uint new_null_bit) override;
 | 
						|
  bool is_equal(const Column_definition &new_field) const override;
 | 
						|
  void hash_not_null(Hasher *hasher) override;
 | 
						|
  uint length_size() const override { return length_bytes; }
 | 
						|
  void print_key_value(String *out, uint32 length) override;
 | 
						|
  Binlog_type_info binlog_type_info() const override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_varstring_compressed final :public Field_varstring {
 | 
						|
public:
 | 
						|
  Field_varstring_compressed(uchar *ptr_arg,
 | 
						|
                             uint32 len_arg, uint length_bytes_arg,
 | 
						|
                             uchar *null_ptr_arg, uchar null_bit_arg,
 | 
						|
                             enum utype unireg_check_arg,
 | 
						|
                             const LEX_CSTRING *field_name_arg,
 | 
						|
                             TABLE_SHARE *share, const DTCollation &collation,
 | 
						|
                             Compression_method *compression_method_arg):
 | 
						|
    Field_varstring(ptr_arg, len_arg, length_bytes_arg, null_ptr_arg,
 | 
						|
                    null_bit_arg, unireg_check_arg, field_name_arg,
 | 
						|
                    share, collation),
 | 
						|
    compression_method_ptr(compression_method_arg) { DBUG_ASSERT(len_arg > 0); }
 | 
						|
  Compression_method *compression_method() const override
 | 
						|
  { return compression_method_ptr; }
 | 
						|
private:
 | 
						|
  Compression_method *compression_method_ptr;
 | 
						|
  void val_str_from_ptr(String *val, const uchar *ptr) const override;
 | 
						|
  int store(const char *to, size_t length, CHARSET_INFO *charset) override;
 | 
						|
  using Field_str::store;
 | 
						|
  String *val_str(String *, String *) override;
 | 
						|
  double val_real() override;
 | 
						|
  longlong val_int() override;
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
  /*
 | 
						|
    We use the default Field::send() implementation,
 | 
						|
    because the derived optimized version (from Field_longstr)
 | 
						|
    is not suitable for compressed fields.
 | 
						|
  */
 | 
						|
  bool send(Protocol *protocol) override
 | 
						|
  {
 | 
						|
    return Field::send(protocol);
 | 
						|
  }
 | 
						|
  enum_field_types binlog_type() const override
 | 
						|
  { return MYSQL_TYPE_VARCHAR_COMPRESSED; }
 | 
						|
  void sql_type(String &str) const override
 | 
						|
  {
 | 
						|
    Field_varstring::sql_type(str);
 | 
						|
    str.append(STRING_WITH_LEN(" /*M!100301 COMPRESSED*/"));
 | 
						|
  }
 | 
						|
  uint32 max_display_length() const override { return field_length - 1; }
 | 
						|
  uint32 character_octet_length() const override { return field_length - 1; }
 | 
						|
  uint32 char_length() const override
 | 
						|
  {
 | 
						|
    return (field_length - 1) / mbmaxlen();
 | 
						|
  }
 | 
						|
  int cmp(const uchar *a_ptr, const uchar *b_ptr) const override;
 | 
						|
 | 
						|
  /*
 | 
						|
    Compressed fields can't have keys as two rows may have different
 | 
						|
    compression methods or compression levels.
 | 
						|
  */
 | 
						|
 | 
						|
  int key_cmp(const uchar *str, uint length) const override
 | 
						|
  { DBUG_ASSERT(0); return 0; }
 | 
						|
  using Field_varstring::key_cmp;
 | 
						|
  Binlog_type_info binlog_type_info() const override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
static inline uint8 number_storage_requirement(uint32 n)
 | 
						|
{
 | 
						|
  return n < 256 ? 1 : n < 65536 ? 2 : n < 16777216 ? 3 : 4;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static inline void store_bigendian(ulonglong num, uchar *to, uint bytes)
 | 
						|
{
 | 
						|
  switch(bytes) {
 | 
						|
  case 1: mi_int1store(to, num); break;
 | 
						|
  case 2: mi_int2store(to, num); break;
 | 
						|
  case 3: mi_int3store(to, num); break;
 | 
						|
  case 4: mi_int4store(to, num); break;
 | 
						|
  case 5: mi_int5store(to, num); break;
 | 
						|
  case 6: mi_int6store(to, num); break;
 | 
						|
  case 7: mi_int7store(to, num); break;
 | 
						|
  case 8: mi_int8store(to, num); break;
 | 
						|
  default: DBUG_ASSERT(0);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static inline longlong read_bigendian(const uchar *from, uint bytes)
 | 
						|
{
 | 
						|
  switch(bytes) {
 | 
						|
  case 1: return mi_uint1korr(from);
 | 
						|
  case 2: return mi_uint2korr(from);
 | 
						|
  case 3: return mi_uint3korr(from);
 | 
						|
  case 4: return mi_uint4korr(from);
 | 
						|
  case 5: return mi_uint5korr(from);
 | 
						|
  case 6: return mi_uint6korr(from);
 | 
						|
  case 7: return mi_uint7korr(from);
 | 
						|
  case 8: return mi_sint8korr(from);
 | 
						|
  default: DBUG_ASSERT(0); return 0;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
static inline void store_lowendian(ulonglong num, uchar *to, uint bytes)
 | 
						|
{
 | 
						|
  switch(bytes) {
 | 
						|
  case 1: *to= (uchar)num;    break;
 | 
						|
  case 2: int2store(to, num); break;
 | 
						|
  case 3: int3store(to, num); break;
 | 
						|
  case 4: int4store(to, num); break;
 | 
						|
  case 8: int8store(to, num); break;
 | 
						|
  default: DBUG_ASSERT(0);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
static inline longlong read_lowendian(const uchar *from, uint bytes)
 | 
						|
{
 | 
						|
  switch(bytes) {
 | 
						|
  case 1: return from[0];
 | 
						|
  case 2: return uint2korr(from);
 | 
						|
  case 3: return uint3korr(from);
 | 
						|
  case 4: return uint4korr(from);
 | 
						|
  case 8: return sint8korr(from);
 | 
						|
  default: DBUG_ASSERT(0); return 0;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
extern LEX_CSTRING temp_lex_str;
 | 
						|
 | 
						|
class Field_blob :public Field_longstr {
 | 
						|
protected:
 | 
						|
  /**
 | 
						|
    The number of bytes used to represent the length of the blob.
 | 
						|
  */
 | 
						|
  uint packlength;
 | 
						|
  
 | 
						|
  /**
 | 
						|
    The 'value'-object is a cache fronting the storage engine.
 | 
						|
  */
 | 
						|
  String value;
 | 
						|
  /**
 | 
						|
     Cache for blob values when reading a row with a virtual blob
 | 
						|
     field. This is needed to not destroy the old cached value when
 | 
						|
     updating the blob with a new value when creating the new row.
 | 
						|
  */
 | 
						|
  String read_value;
 | 
						|
 | 
						|
  static void do_copy_blob(Copy_field *copy);
 | 
						|
  static void do_conv_blob(Copy_field *copy);
 | 
						|
  uint get_key_image_itRAW(const uchar *ptr_arg, uchar *buff, uint length) const;
 | 
						|
public:
 | 
						|
  Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
 | 
						|
	     enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
 | 
						|
	     TABLE_SHARE *share, uint blob_pack_length,
 | 
						|
	     const DTCollation &collation);
 | 
						|
  Field_blob(uint32 len_arg,bool maybe_null_arg, const LEX_CSTRING *field_name_arg,
 | 
						|
             const DTCollation &collation)
 | 
						|
    :Field_longstr((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0,
 | 
						|
                   NONE, field_name_arg, collation),
 | 
						|
    packlength(4)
 | 
						|
  {
 | 
						|
    flags|= BLOB_FLAG;
 | 
						|
  }
 | 
						|
  Field_blob(uint32 len_arg,bool maybe_null_arg,
 | 
						|
             const LEX_CSTRING *field_name_arg,
 | 
						|
             const DTCollation &collation, bool set_packlength)
 | 
						|
    :Field_longstr((uchar*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0,
 | 
						|
                   NONE, field_name_arg, collation)
 | 
						|
  {
 | 
						|
    flags|= BLOB_FLAG;
 | 
						|
    packlength= set_packlength ? number_storage_requirement(len_arg) : 4;
 | 
						|
  }
 | 
						|
  Field_blob(uint32 packlength_arg)
 | 
						|
    :Field_longstr((uchar*) 0, 0, (uchar*) "", 0, NONE, &temp_lex_str,
 | 
						|
                   system_charset_info),
 | 
						|
    packlength(packlength_arg) {}
 | 
						|
  const Type_handler *type_handler() const override;
 | 
						|
  /* Note that the default copy constructor is used, in clone() */
 | 
						|
  enum_field_types type() const override
 | 
						|
  {
 | 
						|
    /*
 | 
						|
      We cannot return type_handler()->field_type() here.
 | 
						|
      Some pieces of the code (e.g. in engines) rely on the fact
 | 
						|
      that Field::type(), Field::real_type() and Item_field::field_type()
 | 
						|
      return MYSQL_TYPE_BLOB for all blob variants.
 | 
						|
      We should eventually fix all such code pieces to expect
 | 
						|
      all BLOB type codes.
 | 
						|
    */
 | 
						|
    return MYSQL_TYPE_BLOB;
 | 
						|
  }
 | 
						|
  enum_field_types real_type() const override
 | 
						|
  {
 | 
						|
    return MYSQL_TYPE_BLOB;
 | 
						|
  }
 | 
						|
  enum ha_base_keytype key_type() const override
 | 
						|
    { return binary() ? HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2; }
 | 
						|
  uint16 key_part_flag() const override { return HA_BLOB_PART; }
 | 
						|
  uint16 key_part_length_bytes() const override { return HA_KEY_BLOB_LENGTH; }
 | 
						|
  en_fieldtype tmp_engine_column_type(bool use_packed_rows) const override
 | 
						|
  {
 | 
						|
    return FIELD_BLOB;
 | 
						|
  }
 | 
						|
  Type_numeric_attributes type_numeric_attributes() const override
 | 
						|
  {
 | 
						|
    return Type_numeric_attributes(Field_blob::max_display_length(),
 | 
						|
                                   decimals(), is_unsigned());
 | 
						|
  }
 | 
						|
  Information_schema_character_attributes
 | 
						|
    information_schema_character_attributes() const override
 | 
						|
  {
 | 
						|
    uint32 octets= Field_blob::character_octet_length();
 | 
						|
    uint32 chars= octets / field_charset()->mbminlen;
 | 
						|
    return Information_schema_character_attributes(octets, chars);
 | 
						|
  }
 | 
						|
  void update_data_type_statistics(Data_type_statistics *st) const override
 | 
						|
  {
 | 
						|
    st->m_blob_count++;
 | 
						|
  }
 | 
						|
  void make_send_field(Send_field *) override;
 | 
						|
  Copy_func *get_copy_func(const Field *from) const override
 | 
						|
  {
 | 
						|
    /*
 | 
						|
    TODO: MDEV-9331
 | 
						|
    if (from->type() == MYSQL_TYPE_BIT)
 | 
						|
      return do_field_int;
 | 
						|
    */
 | 
						|
    if (!(from->flags & BLOB_FLAG) || from->charset() != charset() ||
 | 
						|
        !from->compression_method() != !compression_method())
 | 
						|
      return do_conv_blob;
 | 
						|
    if (from->pack_length() != Field_blob::pack_length())
 | 
						|
      return do_copy_blob;
 | 
						|
    return get_identical_copy_func();
 | 
						|
  }
 | 
						|
  int  store_field(Field *from) override
 | 
						|
  {                                             // Be sure the value is stored
 | 
						|
    if (field_charset() == &my_charset_bin &&
 | 
						|
        from->type_handler()->convert_to_binary_using_val_native())
 | 
						|
    {
 | 
						|
      NativeBuffer<64> tmp;
 | 
						|
      from->val_native(&tmp);
 | 
						|
      value.copy(tmp.ptr(), tmp.length(), &my_charset_bin);
 | 
						|
      return store(value.ptr(), value.length(), &my_charset_bin);
 | 
						|
    }
 | 
						|
    from->val_str(&value);
 | 
						|
    if (table->copy_blobs ||
 | 
						|
        (!value.is_alloced() && from->is_varchar_and_in_write_set()))
 | 
						|
      value.copy();
 | 
						|
    return store(value.ptr(), value.length(), from->charset());
 | 
						|
  }
 | 
						|
  bool memcpy_field_possible(const Field *from) const override
 | 
						|
  {
 | 
						|
    return Field_str::memcpy_field_possible(from) &&
 | 
						|
           !compression_method() == !from->compression_method() &&
 | 
						|
           !table->copy_blobs;
 | 
						|
  }
 | 
						|
  bool make_empty_rec_store_default_value(THD *thd, Item *item) override;
 | 
						|
  int store(const char *to, size_t length, CHARSET_INFO *charset) override;
 | 
						|
  int store_from_statistical_minmax_field(Field *stat_field, String *str,
 | 
						|
                                          MEM_ROOT *mem) override;
 | 
						|
  using Field_str::store;
 | 
						|
  void hash_not_null(Hasher *hasher) override;
 | 
						|
  double val_real() override;
 | 
						|
  longlong val_int() override;
 | 
						|
  String *val_str(String *, String *) override;
 | 
						|
  my_decimal *val_decimal(my_decimal *) override;
 | 
						|
  int cmp(const uchar *a, const uchar *b) const override;
 | 
						|
  int cmp_prefix(const uchar *a, const uchar *b, size_t prefix_char_len) const
 | 
						|
    override;
 | 
						|
  int cmp(const uchar *a, uint32 a_length, const uchar *b, uint32 b_length)
 | 
						|
    const;
 | 
						|
  int cmp_binary(const uchar *a,const uchar *b, uint32 max_length=~0U) const
 | 
						|
     override;
 | 
						|
  int key_cmp(const uchar *,const uchar*) const override;
 | 
						|
  int key_cmp(const uchar *str, uint length) const override;
 | 
						|
  /* Never update the value of min_val for a blob field */
 | 
						|
  bool update_min(Field *min_val, bool force_update) override { return false; }
 | 
						|
  /* Never update the value of max_val for a blob field */
 | 
						|
  bool update_max(Field *max_val, bool force_update) override { return false; }
 | 
						|
  uint32 key_length() const override { return 0; }
 | 
						|
  void sort_string(uchar *buff,uint length) override;
 | 
						|
  uint32 pack_length() const override
 | 
						|
  { return (uint32) (packlength + portable_sizeof_char_ptr); }
 | 
						|
 | 
						|
  /**
 | 
						|
     Return the packed length without the pointer size added. 
 | 
						|
 | 
						|
     This is used to determine the size of the actual data in the row
 | 
						|
     buffer.
 | 
						|
 | 
						|
     @returns The length of the raw data itself without the pointer.
 | 
						|
  */
 | 
						|
  uint32 pack_length_no_ptr() const
 | 
						|
  { return (uint32) (packlength); }
 | 
						|
  uint row_pack_length() const override { return pack_length_no_ptr(); }
 | 
						|
  uint32 sort_length() const override;
 | 
						|
  uint32 sort_suffix_length() const override;
 | 
						|
  uint32 value_length() override { return get_length(); }
 | 
						|
  uint32 max_data_length() const override
 | 
						|
  {
 | 
						|
    return (uint32) (((ulonglong) 1 << (packlength*8)) -1);
 | 
						|
  }
 | 
						|
  int reset() override { bzero(ptr, packlength+sizeof(uchar*)); return 0; }
 | 
						|
  void reset_fields() override
 | 
						|
  {
 | 
						|
    bzero((uchar*) &value, sizeof value);
 | 
						|
    bzero((uchar*) &read_value, sizeof read_value);
 | 
						|
  }
 | 
						|
  uint32 get_field_buffer_size() { return value.alloced_length(); }
 | 
						|
  void store_length(uchar *i_ptr, uint i_packlength, uint32 i_number);
 | 
						|
  void store_length(size_t number)
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(number < UINT_MAX32);
 | 
						|
    store_length(ptr, packlength, (uint32)number);
 | 
						|
  }
 | 
						|
  inline uint32 get_length(my_ptrdiff_t row_offset= 0) const
 | 
						|
  { return get_length(ptr+row_offset, this->packlength); }
 | 
						|
  uint32 get_length(const uchar *ptr, uint packlength) const;
 | 
						|
  uint32 get_length(const uchar *ptr_arg) const
 | 
						|
  { return get_length(ptr_arg, this->packlength); }
 | 
						|
  inline uchar *get_ptr() const { return get_ptr(ptr); }
 | 
						|
  inline uchar *get_ptr(const uchar *ptr_arg) const
 | 
						|
  {
 | 
						|
    uchar *s;
 | 
						|
    memcpy(&s, ptr_arg + packlength, sizeof(uchar*));
 | 
						|
    return s;
 | 
						|
  }
 | 
						|
  inline void set_ptr(uchar *length, uchar *data)
 | 
						|
  {
 | 
						|
    memcpy(ptr,length,packlength);
 | 
						|
    memcpy(ptr+packlength, &data,sizeof(char*));
 | 
						|
  }
 | 
						|
  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*));
 | 
						|
  }
 | 
						|
  inline void set_ptr(uint32 length, uchar *data)
 | 
						|
  {
 | 
						|
    set_ptr_offset(0, length, data);
 | 
						|
  }
 | 
						|
  int copy_value(Field_blob *from);
 | 
						|
  uint get_key_image(uchar *buff, uint length,
 | 
						|
                     const uchar *ptr_arg, imagetype type) const override
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(type == itRAW);
 | 
						|
    return get_key_image_itRAW(ptr_arg, buff, length);
 | 
						|
  }
 | 
						|
  void set_key_image(const uchar *buff,uint length) override;
 | 
						|
  Field *make_new_field(MEM_ROOT *, TABLE *new_table, bool keep_type) override;
 | 
						|
  Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
 | 
						|
                       uchar *new_ptr, uint32 length,
 | 
						|
                       uchar *new_null_ptr, uint new_null_bit) override;
 | 
						|
  void sql_type(String &str) const override;
 | 
						|
  /**
 | 
						|
     Copy blob buffer into internal storage "value" and update record pointer.
 | 
						|
 | 
						|
     @retval true     Memory allocation error
 | 
						|
     @retval false    Success
 | 
						|
  */
 | 
						|
  bool copy()
 | 
						|
  {
 | 
						|
    uchar *tmp= get_ptr();
 | 
						|
    if (value.copy((char*) tmp, get_length(), charset()))
 | 
						|
    {
 | 
						|
      Field_blob::reset();
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
    tmp=(uchar*) value.ptr();
 | 
						|
    memcpy(ptr+packlength, &tmp, sizeof(char*));
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
  void swap(String &inout, bool set_read_value)
 | 
						|
  {
 | 
						|
    if (set_read_value)
 | 
						|
      read_value.swap(inout);
 | 
						|
    else
 | 
						|
      value.swap(inout);
 | 
						|
  }
 | 
						|
  /**
 | 
						|
     Return pointer to blob cache or NULL if not cached.
 | 
						|
  */
 | 
						|
  String * cached(bool *set_read_value)
 | 
						|
  {
 | 
						|
    char *tmp= (char *) get_ptr();
 | 
						|
    if (!value.is_empty() && tmp == value.ptr())
 | 
						|
    {
 | 
						|
      *set_read_value= false;
 | 
						|
      return &value;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!read_value.is_empty() && tmp == read_value.ptr())
 | 
						|
    {
 | 
						|
      *set_read_value= true;
 | 
						|
      return &read_value;
 | 
						|
    }
 | 
						|
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
  /* store value for the duration of the current read record */
 | 
						|
  inline void swap_value_and_read_value()
 | 
						|
  {
 | 
						|
    read_value.swap(value);
 | 
						|
  }
 | 
						|
  inline void set_value(uchar *data)
 | 
						|
  {
 | 
						|
    /* Set value pointer. Lengths are not important */
 | 
						|
    value.reset((char*) data, 1, 1, &my_charset_bin);
 | 
						|
  }
 | 
						|
  uchar *pack(uchar *to, const uchar *from, uint max_length) override;
 | 
						|
  const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end,
 | 
						|
                      uint param_data) override;
 | 
						|
  uint packed_col_length(const uchar *col_ptr, uint length) override;
 | 
						|
  uint max_packed_col_length(uint max_length) override;
 | 
						|
  void free() override
 | 
						|
  {
 | 
						|
    value.free();
 | 
						|
    read_value.free();
 | 
						|
  }
 | 
						|
  inline void clear_temporary()
 | 
						|
  {
 | 
						|
    uchar *tmp= get_ptr();
 | 
						|
    if (likely(value.ptr() == (char*) tmp))
 | 
						|
      bzero((uchar*) &value, sizeof(value));
 | 
						|
    else
 | 
						|
    {
 | 
						|
      /*
 | 
						|
        Currently read_value should never point to tmp, the following code
 | 
						|
        is mainly here to make things future proof.
 | 
						|
      */
 | 
						|
      if (unlikely(read_value.ptr() == (char*) tmp))
 | 
						|
        bzero((uchar*) &read_value, sizeof(read_value));
 | 
						|
    }
 | 
						|
  }
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
  bool has_charset() const override { return charset() != &my_charset_bin; }
 | 
						|
  uint32 max_display_length() const override;
 | 
						|
  uint32 char_length() const override;
 | 
						|
  uint32 character_octet_length() const override;
 | 
						|
  bool is_equal(const Column_definition &new_field) const override;
 | 
						|
  void print_key_value(String *out, uint32 length) override;
 | 
						|
  Binlog_type_info binlog_type_info() const override;
 | 
						|
 | 
						|
  friend void TABLE::remember_blob_values(String *blob_storage);
 | 
						|
  friend void TABLE::restore_blob_values(String *blob_storage);
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_blob_compressed final :public Field_blob {
 | 
						|
public:
 | 
						|
  Field_blob_compressed(uchar *ptr_arg, uchar *null_ptr_arg,
 | 
						|
                        uchar null_bit_arg, enum utype unireg_check_arg,
 | 
						|
                        const LEX_CSTRING *field_name_arg, TABLE_SHARE *share,
 | 
						|
                        uint blob_pack_length, const DTCollation &collation,
 | 
						|
                        Compression_method *compression_method_arg):
 | 
						|
    Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
 | 
						|
               field_name_arg, share, blob_pack_length, collation),
 | 
						|
    compression_method_ptr(compression_method_arg) {}
 | 
						|
  Compression_method *compression_method() const override
 | 
						|
  { return compression_method_ptr; }
 | 
						|
private:
 | 
						|
  Compression_method *compression_method_ptr;
 | 
						|
  int store(const char *to, size_t length, CHARSET_INFO *charset) override;
 | 
						|
  using Field_str::store;
 | 
						|
  String *val_str(String *, String *) override;
 | 
						|
  double val_real() override;
 | 
						|
  longlong val_int() override;
 | 
						|
  /*
 | 
						|
    We use the default Field::send() implementation,
 | 
						|
    because the derived optimized version (from Field_longstr)
 | 
						|
    is not suitable for compressed fields.
 | 
						|
  */
 | 
						|
  bool send(Protocol *protocol) override
 | 
						|
  {
 | 
						|
    return Field::send(protocol);
 | 
						|
  }
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
  enum_field_types binlog_type() const override
 | 
						|
  { return MYSQL_TYPE_BLOB_COMPRESSED; }
 | 
						|
  void sql_type(String &str) const override
 | 
						|
  {
 | 
						|
    Field_blob::sql_type(str);
 | 
						|
    str.append(STRING_WITH_LEN(" /*M!100301 COMPRESSED*/"));
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
    Compressed fields can't have keys as two rows may have different
 | 
						|
    compression methods or compression levels.
 | 
						|
  */
 | 
						|
 | 
						|
  uint get_key_image(uchar *buff, uint length,
 | 
						|
                     const uchar *ptr_arg, imagetype type_arg) const override
 | 
						|
  { DBUG_ASSERT(0); return 0; }
 | 
						|
  void set_key_image(const uchar *, uint) override
 | 
						|
  { DBUG_ASSERT(0); }
 | 
						|
  int key_cmp(const uchar *, const uchar *) const override
 | 
						|
  { DBUG_ASSERT(0); return 0; }
 | 
						|
  int key_cmp(const uchar *, uint) const override
 | 
						|
  { DBUG_ASSERT(0); return 0; }
 | 
						|
  Field *new_key_field(MEM_ROOT *, TABLE *, uchar *, uint32, uchar *, uint)
 | 
						|
    override
 | 
						|
  { DBUG_ASSERT(0); return 0; }
 | 
						|
  Binlog_type_info binlog_type_info() const override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_enum :public Field_str {
 | 
						|
  static void do_field_enum(Copy_field *copy_field);
 | 
						|
  longlong val_int(const uchar *) const;
 | 
						|
  Data_type_compatibility can_optimize_range_or_keypart_ref(
 | 
						|
                                         const Item_bool_func *cond,
 | 
						|
                                         const Item *item) const;
 | 
						|
protected:
 | 
						|
  uint packlength;
 | 
						|
public:
 | 
						|
  const TYPELIB *typelib;
 | 
						|
  Field_enum(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,
 | 
						|
             uint packlength_arg,
 | 
						|
             const TYPELIB *typelib_arg,
 | 
						|
             const DTCollation &collation)
 | 
						|
    :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
 | 
						|
	       unireg_check_arg, field_name_arg, collation),
 | 
						|
    packlength(packlength_arg),typelib(typelib_arg)
 | 
						|
  {
 | 
						|
      flags|=ENUM_FLAG;
 | 
						|
  }
 | 
						|
  Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type)
 | 
						|
    override;
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return &type_handler_enum; }
 | 
						|
  enum ha_base_keytype key_type() const override;
 | 
						|
  sql_mode_t can_handle_sql_mode_dependency_on_store() const override;
 | 
						|
  enum_conv_type rpl_conv_type_from(const Conv_source &source,
 | 
						|
                                    const Relay_log_info *rli,
 | 
						|
                                    const Conv_param ¶m) const override;
 | 
						|
  Copy_func *get_copy_func(const Field *from) const override
 | 
						|
  {
 | 
						|
    if (eq_def(from))
 | 
						|
      return get_identical_copy_func();
 | 
						|
    if (real_type() == MYSQL_TYPE_ENUM &&
 | 
						|
        from->real_type() == MYSQL_TYPE_ENUM)
 | 
						|
      return do_field_enum;
 | 
						|
    if (from->result_type() == STRING_RESULT)
 | 
						|
      return do_field_string;
 | 
						|
    return do_field_int;
 | 
						|
  }
 | 
						|
  int store_field(Field *from) override
 | 
						|
  {
 | 
						|
    if (from->real_type() == MYSQL_TYPE_ENUM && from->val_int() == 0)
 | 
						|
    {
 | 
						|
      store_type(0);
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
    return from->save_in_field(this);
 | 
						|
  }
 | 
						|
  int save_in_field(Field *to) override
 | 
						|
  {
 | 
						|
    if (to->result_type() != STRING_RESULT)
 | 
						|
      return to->store(val_int(), 0);
 | 
						|
    return save_in_field_str(to);
 | 
						|
  }
 | 
						|
  bool memcpy_field_possible(const Field *from) const override
 | 
						|
  { return false; }
 | 
						|
  void make_empty_rec_reset(THD *) override
 | 
						|
  {
 | 
						|
    if (flags & NOT_NULL_FLAG)
 | 
						|
    {
 | 
						|
      set_notnull();
 | 
						|
      store((longlong) 1, true);
 | 
						|
    }
 | 
						|
    else
 | 
						|
      reset();
 | 
						|
  }
 | 
						|
  int  store(const char *to,size_t length,CHARSET_INFO *charset) override;
 | 
						|
  int  store(double nr) override;
 | 
						|
  int  store(longlong nr, bool unsigned_val) override;
 | 
						|
  double val_real() override;
 | 
						|
  longlong val_int() override;
 | 
						|
  String *val_str(String *, String *) override;
 | 
						|
  int cmp(const uchar *,const uchar *) const override;
 | 
						|
  void sort_string(uchar *buff,uint length) override;
 | 
						|
  uint32 pack_length() const override { return (uint32) packlength; }
 | 
						|
  void store_type(ulonglong value);
 | 
						|
  void sql_type(String &str) const override;
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
  uint pack_length_from_metadata(uint field_metadata) const override
 | 
						|
  { return (field_metadata & 0x00ff); }
 | 
						|
  uint row_pack_length() const override { return pack_length(); }
 | 
						|
  bool zero_pack() const override { return false; }
 | 
						|
  bool optimize_range(uint, uint) const override { return false; }
 | 
						|
  bool eq_def(const Field *field) const override;
 | 
						|
  bool has_charset() const override { return true; }
 | 
						|
  /* enum and set are sorted as integers */
 | 
						|
  CHARSET_INFO *sort_charset() const override { return &my_charset_bin; }
 | 
						|
  decimal_digits_t decimals() const override { return 0; }
 | 
						|
  const TYPELIB *get_typelib() const override { return typelib; }
 | 
						|
 | 
						|
  uchar *pack(uchar *to, const uchar *from, uint max_length) override;
 | 
						|
  const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end,
 | 
						|
                      uint param_data) override;
 | 
						|
 | 
						|
  Data_type_compatibility can_optimize_keypart_ref(const Item_bool_func *cond,
 | 
						|
                                                   const Item *item)
 | 
						|
                                                   const override
 | 
						|
  {
 | 
						|
    return can_optimize_range_or_keypart_ref(cond, item);
 | 
						|
  }
 | 
						|
  Data_type_compatibility can_optimize_group_min_max(const Item_bool_func *cond,
 | 
						|
                                                     const Item *const_item)
 | 
						|
                                                     const override
 | 
						|
  {
 | 
						|
    /*
 | 
						|
      Can't use GROUP_MIN_MAX optimization for ENUM and SET,
 | 
						|
      because the values are stored as numbers in index,
 | 
						|
      while MIN() and MAX() work as strings.
 | 
						|
      It would return the records with min and max enum numeric indexes.
 | 
						|
     "Bug#45300 MAX() and ENUM type" should be fixed first.
 | 
						|
    */
 | 
						|
    return Data_type_compatibility::INCOMPATIBLE_DATA_TYPE;
 | 
						|
  }
 | 
						|
  Data_type_compatibility can_optimize_range(const Item_bool_func *cond,
 | 
						|
                                             const Item *item,
 | 
						|
                                             bool is_eq_func) const override
 | 
						|
  {
 | 
						|
    return can_optimize_range_or_keypart_ref(cond, item);
 | 
						|
  }
 | 
						|
  Binlog_type_info binlog_type_info() const override;
 | 
						|
private:
 | 
						|
  bool is_equal(const Column_definition &new_field) const override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_set final :public Field_enum {
 | 
						|
public:
 | 
						|
  Field_set(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, uint32 packlength_arg,
 | 
						|
	    const TYPELIB *typelib_arg, const DTCollation &collation)
 | 
						|
    :Field_enum(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
 | 
						|
                field_name_arg, packlength_arg, typelib_arg, collation)
 | 
						|
    {
 | 
						|
      flags=(flags & ~ENUM_FLAG) | SET_FLAG;
 | 
						|
    }
 | 
						|
  void make_empty_rec_reset(THD *thd) override
 | 
						|
  {
 | 
						|
    Field::make_empty_rec_reset(thd);
 | 
						|
  }
 | 
						|
 | 
						|
  int  store_field(Field *from) override { return from->save_in_field(this); }
 | 
						|
  int  store(const char *to,size_t length,CHARSET_INFO *charset) override;
 | 
						|
  int  store(double nr) override
 | 
						|
  { return Field_set::store((longlong) nr, FALSE); }
 | 
						|
  int  store(longlong nr, bool unsigned_val) override;
 | 
						|
 | 
						|
  bool zero_pack() const override { return true; }
 | 
						|
  String *val_str(String *, String *) override;
 | 
						|
  void sql_type(String &str) const override;
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return &type_handler_set; }
 | 
						|
  bool has_charset() const override { return true; }
 | 
						|
  Binlog_type_info binlog_type_info() const override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
  Note:
 | 
						|
    To use Field_bit::cmp_binary() you need to copy the bits stored in
 | 
						|
    the beginning of the record (the NULL bytes) to each memory you
 | 
						|
    want to compare (where the arguments point).
 | 
						|
 | 
						|
    This is the reason:
 | 
						|
    - Field_bit::cmp_binary() is only implemented in the base class
 | 
						|
      (Field::cmp_binary()).
 | 
						|
    - Field::cmp_binary() currently uses pack_length() to calculate how
 | 
						|
      long the data is.
 | 
						|
    - pack_length() includes size of the bits stored in the NULL bytes
 | 
						|
      of the record.
 | 
						|
*/
 | 
						|
class Field_bit :public Field {
 | 
						|
public:
 | 
						|
  uchar *bit_ptr;     // position in record where 'uneven' bits store
 | 
						|
  uchar bit_ofs;      // offset to 'uneven' high bits
 | 
						|
  uint bit_len;       // number of 'uneven' high bits
 | 
						|
  uint bytes_in_rec;
 | 
						|
  Field_bit(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
 | 
						|
            uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg,
 | 
						|
            enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg);
 | 
						|
  const Type_handler *type_handler() const override
 | 
						|
  { return &type_handler_bit; }
 | 
						|
  enum ha_base_keytype key_type() const override { return HA_KEYTYPE_BIT; }
 | 
						|
  uint16 key_part_flag() const override { return HA_BIT_PART; }
 | 
						|
  uint32 key_length() const override
 | 
						|
  { return (uint32) (field_length + 7) / 8; }
 | 
						|
  uint32 max_data_length() const override { return key_length(); }
 | 
						|
  uint32 max_display_length() const override { return field_length; }
 | 
						|
  enum_conv_type rpl_conv_type_from(const Conv_source &source,
 | 
						|
                                    const Relay_log_info *rli,
 | 
						|
                                    const Conv_param ¶m) const override;
 | 
						|
  CHARSET_INFO *charset() const override { return &my_charset_bin; }
 | 
						|
  const DTCollation & dtcollation() const override;
 | 
						|
  Information_schema_numeric_attributes
 | 
						|
    information_schema_numeric_attributes() const override
 | 
						|
  {
 | 
						|
    return Information_schema_numeric_attributes(field_length);
 | 
						|
  }
 | 
						|
  void update_data_type_statistics(Data_type_statistics *st) const override
 | 
						|
  {
 | 
						|
    st->m_uneven_bit_length+= field_length & 7;
 | 
						|
  }
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
  int reset() override
 | 
						|
  {
 | 
						|
    bzero(ptr, bytes_in_rec); 
 | 
						|
    if (bit_ptr && (bit_len > 0))  // reset odd bits among null bits
 | 
						|
      clr_rec_bits(bit_ptr, bit_ofs, bit_len);
 | 
						|
    return 0; 
 | 
						|
  }
 | 
						|
  Copy_func *get_copy_func(const Field *from) const override
 | 
						|
  {
 | 
						|
    if (from->cmp_type() == DECIMAL_RESULT)
 | 
						|
      return do_field_decimal;
 | 
						|
    return do_field_int;
 | 
						|
  }
 | 
						|
  int save_in_field(Field *to) override { return to->store(val_int(), true); }
 | 
						|
  bool memcpy_field_possible(const Field *from) const override{ return false; }
 | 
						|
  int store(const char *to, size_t length, CHARSET_INFO *charset) override;
 | 
						|
  int store(double nr) override;
 | 
						|
  int store(longlong nr, bool unsigned_val) override;
 | 
						|
  int store_decimal(const my_decimal *) override;
 | 
						|
  double val_real() override;
 | 
						|
  longlong val_int() override;
 | 
						|
  String *val_str(String*, String *) override;
 | 
						|
  bool str_needs_quotes() const override { return true; }
 | 
						|
  my_decimal *val_decimal(my_decimal *) override;
 | 
						|
  bool val_bool() override { return val_int() != 0; }
 | 
						|
  int cmp(const uchar *a, const uchar *b) const override
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(ptr == a || ptr == b);
 | 
						|
    if (ptr == a)
 | 
						|
      return Field_bit::key_cmp(b, bytes_in_rec + MY_TEST(bit_len));
 | 
						|
    else
 | 
						|
      return Field_bit::key_cmp(a, bytes_in_rec + MY_TEST(bit_len)) * -1;
 | 
						|
  }
 | 
						|
  int cmp_binary_offset(uint row_offset) override
 | 
						|
  { return cmp_offset(row_offset); }
 | 
						|
  int cmp_prefix(const uchar *a, const uchar *b,
 | 
						|
                 size_t  prefix_char_length) const override;
 | 
						|
  int key_cmp(const uchar *a, const uchar *b) const override
 | 
						|
  { return cmp_binary((uchar *) a, (uchar *) b); }
 | 
						|
  int key_cmp(const uchar *str, uint length) const override;
 | 
						|
  int cmp_offset(my_ptrdiff_t row_offset) override;
 | 
						|
  bool update_min(Field *min_val, bool force_update) override
 | 
						|
  {
 | 
						|
    longlong val= val_int();
 | 
						|
    bool update_fl= force_update || val < min_val->val_int();
 | 
						|
    if (update_fl)
 | 
						|
    {
 | 
						|
      min_val->set_notnull();
 | 
						|
      min_val->store(val, FALSE);
 | 
						|
    }
 | 
						|
    return update_fl;
 | 
						|
  }
 | 
						|
  bool update_max(Field *max_val, bool force_update) override
 | 
						|
  {
 | 
						|
    longlong val= val_int();
 | 
						|
    bool update_fl= force_update || val > max_val->val_int();
 | 
						|
    if (update_fl)
 | 
						|
    {
 | 
						|
      max_val->set_notnull();
 | 
						|
      max_val->store(val, FALSE);
 | 
						|
    }
 | 
						|
    return update_fl;
 | 
						|
  }
 | 
						|
  void store_field_value(uchar *val, uint) override
 | 
						|
  {
 | 
						|
    store(*((longlong *)val), TRUE);
 | 
						|
  }
 | 
						|
  double pos_in_interval(Field *min, Field *max) override
 | 
						|
  {
 | 
						|
    return pos_in_interval_val_real(min, max);
 | 
						|
  }
 | 
						|
  void get_image(uchar *buff, uint length,
 | 
						|
                 const uchar *ptr_arg, CHARSET_INFO *cs) const override
 | 
						|
  { get_key_image(buff, length, ptr_arg, itRAW); }
 | 
						|
  void set_image(const uchar *buff,uint length, CHARSET_INFO *cs) override
 | 
						|
  { Field_bit::store((char *) buff, length, cs); }
 | 
						|
  uint get_key_image(uchar *buff, uint length,
 | 
						|
                     const uchar *ptr_arg, imagetype type) const override;
 | 
						|
  void set_key_image(const uchar *buff, uint length) override
 | 
						|
  { Field_bit::store((char*) buff, length, &my_charset_bin); }
 | 
						|
  void sort_string(uchar *buff, uint length) override
 | 
						|
  { get_key_image(buff, length, ptr, itRAW); }
 | 
						|
  uint32 pack_length() const override
 | 
						|
  { return (uint32) (field_length + 7) / 8; }
 | 
						|
  uint32 pack_length_in_rec() const override { return bytes_in_rec; }
 | 
						|
  uint pack_length_from_metadata(uint field_metadata) const override;
 | 
						|
  uint row_pack_length() const override
 | 
						|
  { return (bytes_in_rec + ((bit_len > 0) ? 1 : 0)); }
 | 
						|
  bool compatible_field_size(uint metadata, const Relay_log_info *rli,
 | 
						|
                             uint16 mflags, int *order_var) const override;
 | 
						|
  void sql_type(String &str) const override;
 | 
						|
  uchar *pack(uchar *to, const uchar *from, uint max_length) override;
 | 
						|
  const uchar *unpack(uchar *to, const uchar *from,
 | 
						|
                      const uchar *from_end, uint param_data) override;
 | 
						|
  int set_default() override;
 | 
						|
 | 
						|
  Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
 | 
						|
                       uchar *new_ptr, uint32 length,
 | 
						|
                       uchar *new_null_ptr, uint new_null_bit) override;
 | 
						|
  void set_bit_ptr(uchar *bit_ptr_arg, uchar bit_ofs_arg)
 | 
						|
  {
 | 
						|
    bit_ptr= bit_ptr_arg;
 | 
						|
    bit_ofs= bit_ofs_arg;
 | 
						|
  }
 | 
						|
  bool eq(Field *field) override
 | 
						|
  {
 | 
						|
    return (Field::eq(field) &&
 | 
						|
            bit_ptr == ((Field_bit *)field)->bit_ptr &&
 | 
						|
            bit_ofs == ((Field_bit *)field)->bit_ofs);
 | 
						|
  }
 | 
						|
  bool is_equal(const Column_definition &new_field) const override;
 | 
						|
  void move_field_offset(my_ptrdiff_t ptr_diff) override
 | 
						|
  {
 | 
						|
    Field::move_field_offset(ptr_diff);
 | 
						|
 | 
						|
    /*
 | 
						|
      clang does not like when things are added to a null pointer, even if
 | 
						|
      it is never referenced.
 | 
						|
    */
 | 
						|
    if (bit_ptr)
 | 
						|
      bit_ptr= ADD_TO_PTR(bit_ptr, ptr_diff, uchar*);
 | 
						|
  }
 | 
						|
  void hash_not_null(Hasher *hasher) override;
 | 
						|
 | 
						|
  SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part,
 | 
						|
                       const Item_bool_func *cond,
 | 
						|
                       scalar_comparison_op op, Item *value) override
 | 
						|
  {
 | 
						|
    return get_mm_leaf_int(param, key_part, cond, op, value, true);
 | 
						|
  }
 | 
						|
  void print_key_value(String *out, uint32 length) override
 | 
						|
  {
 | 
						|
    val_int_as_str(out, 1);
 | 
						|
  }
 | 
						|
  /**
 | 
						|
     Save the field metadata for bit fields.
 | 
						|
     Saves the bit length in the first byte and bytes in record in the
 | 
						|
     second byte of the field metadata array at index of *metadata_ptr and
 | 
						|
     *(metadata_ptr + 1).
 | 
						|
 | 
						|
     @param   metadata_ptr   First byte of field metadata
 | 
						|
 | 
						|
     @returns number of bytes written to metadata_ptr
 | 
						|
  */
 | 
						|
  Binlog_type_info binlog_type_info() const override
 | 
						|
  {
 | 
						|
    DBUG_PRINT("debug", ("bit_len: %d, bytes_in_rec: %d",
 | 
						|
                       bit_len, bytes_in_rec));
 | 
						|
    /*
 | 
						|
      Since this class and Field_bit_as_char have different ideas of
 | 
						|
      what should be stored here, we compute the values of the metadata
 | 
						|
      explicitly using the field_length.
 | 
						|
    */
 | 
						|
    return Binlog_type_info(type(),
 | 
						|
                            static_cast<uint16>((field_length & 7) |
 | 
						|
                                                ((field_length / 8) << 8)), 2);
 | 
						|
  }
 | 
						|
 | 
						|
private:
 | 
						|
  size_t do_last_null_byte() const override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  BIT field represented as chars for non-MyISAM tables.
 | 
						|
 | 
						|
  @todo The inheritance relationship is backwards since Field_bit is
 | 
						|
  an extended version of Field_bit_as_char and not the other way
 | 
						|
  around. Hence, we should refactor it to fix the hierarchy order.
 | 
						|
 */
 | 
						|
class Field_bit_as_char final :public Field_bit {
 | 
						|
public:
 | 
						|
  Field_bit_as_char(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);
 | 
						|
  enum ha_base_keytype key_type() const override { return HA_KEYTYPE_BINARY; }
 | 
						|
  uint size_of() const override { return sizeof *this; }
 | 
						|
  int store(const char *to, size_t length, CHARSET_INFO *charset) override;
 | 
						|
  int store(double nr) override { return Field_bit::store(nr); }
 | 
						|
  int store(longlong nr, bool unsigned_val) override
 | 
						|
  { return Field_bit::store(nr, unsigned_val); }
 | 
						|
  void sql_type(String &str) const override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class Field_row final :public Field_null
 | 
						|
{
 | 
						|
  class Virtual_tmp_table *m_table;
 | 
						|
public:
 | 
						|
  Field_row(uchar *ptr_arg, const LEX_CSTRING *field_name_arg)
 | 
						|
    :Field_null(ptr_arg, 0, Field::NONE, field_name_arg, &my_charset_bin),
 | 
						|
     m_table(NULL)
 | 
						|
    {}
 | 
						|
  ~Field_row();
 | 
						|
  en_fieldtype tmp_engine_column_type(bool use_packed_rows) const override
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(0);
 | 
						|
    return Field::tmp_engine_column_type(use_packed_rows);
 | 
						|
  }
 | 
						|
  enum_conv_type rpl_conv_type_from(const Conv_source &source,
 | 
						|
                                    const Relay_log_info *rli,
 | 
						|
                                    const Conv_param ¶m) const override
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(0);
 | 
						|
    return CONV_TYPE_IMPOSSIBLE;
 | 
						|
  }
 | 
						|
  Virtual_tmp_table **virtual_tmp_table_addr() override { return &m_table; }
 | 
						|
  bool sp_prepare_and_store_item(THD *thd, Item **value) override;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
extern const LEX_CSTRING null_clex_str;
 | 
						|
 | 
						|
class Column_definition_attributes
 | 
						|
{
 | 
						|
public:
 | 
						|
  /*
 | 
						|
    At various stages in execution this can be length of field in bytes or
 | 
						|
    max number of characters.
 | 
						|
  */
 | 
						|
  ulonglong length;
 | 
						|
  const TYPELIB *interval;
 | 
						|
  CHARSET_INFO *charset;
 | 
						|
  uint32 srid;
 | 
						|
  uint32 pack_flag;
 | 
						|
  decimal_digits_t decimals;
 | 
						|
  Field::utype unireg_check;
 | 
						|
  Column_definition_attributes()
 | 
						|
   :length(0),
 | 
						|
    interval(NULL),
 | 
						|
    charset(&my_charset_bin),
 | 
						|
    srid(0),
 | 
						|
    pack_flag(0),
 | 
						|
    decimals(0),
 | 
						|
    unireg_check(Field::NONE)
 | 
						|
  { }
 | 
						|
  Column_definition_attributes(const Field *field);
 | 
						|
  Column_definition_attributes(const Type_all_attributes &attr);
 | 
						|
  Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root,
 | 
						|
                    const Record_addr *rec,
 | 
						|
                    const Type_handler *handler,
 | 
						|
                    const LEX_CSTRING *field_name,
 | 
						|
                    uint32 flags) const;
 | 
						|
  uint temporal_dec(uint intlen) const
 | 
						|
  {
 | 
						|
    return (uint) (length > intlen ? length - intlen - 1 : 0);
 | 
						|
  }
 | 
						|
  uint pack_flag_to_pack_length() const;
 | 
						|
  void frm_pack_basic(uchar *buff) const;
 | 
						|
  void frm_pack_charset(uchar *buff) const;
 | 
						|
  void frm_pack_numeric_with_dec(uchar *buff) const;
 | 
						|
  void frm_unpack_basic(const uchar *buff);
 | 
						|
  bool frm_unpack_charset(TABLE_SHARE *share, const uchar *buff);
 | 
						|
  bool frm_unpack_numeric_with_dec(TABLE_SHARE *share, const uchar *buff);
 | 
						|
  bool frm_unpack_temporal_with_dec(TABLE_SHARE *share, uint intlen,
 | 
						|
                                    const uchar *buff);
 | 
						|
  void set_length_and_dec(const Lex_length_and_dec_st &attr);
 | 
						|
  CHARSET_INFO *explicit_or_derived_charset(const Column_derived_attributes
 | 
						|
                                                  *derived_attr) const
 | 
						|
  {
 | 
						|
    return charset ? charset : derived_attr->charset();
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
  Create field class for CREATE TABLE
 | 
						|
*/
 | 
						|
class Column_definition: public Sql_alloc,
 | 
						|
                         public Type_handler_hybrid_field_type,
 | 
						|
                         public Column_definition_attributes
 | 
						|
{
 | 
						|
  /**
 | 
						|
    Create "interval" from "interval_list".
 | 
						|
    @param mem_root                   - memory root to create the TYPELIB
 | 
						|
                                        instance and its values on
 | 
						|
    @param reuse_interval_list_values - determines if TYPELIB can reuse strings
 | 
						|
                                        from interval_list, or should always
 | 
						|
                                        allocate a copy on mem_root, even if
 | 
						|
                                        character set conversion is not needed
 | 
						|
    @retval false on success
 | 
						|
    @retval true  on error (bad values, or EOM)
 | 
						|
  */
 | 
						|
  bool create_interval_from_interval_list(MEM_ROOT *mem_root,
 | 
						|
                                          bool reuse_interval_list_values);
 | 
						|
 | 
						|
  /*
 | 
						|
    Calculate TYPELIB (set or enum) max and total lengths
 | 
						|
 | 
						|
    @param  cs            charset+collation pair of the interval
 | 
						|
    @param  max_length    length of the longest item
 | 
						|
    @param  tot_length    sum of the item lengths
 | 
						|
 | 
						|
    After this method call:
 | 
						|
    - ENUM uses max_length
 | 
						|
    - SET uses tot_length.
 | 
						|
  */
 | 
						|
  void calculate_interval_lengths(uint32 *max_length, uint32 *tot_length)
 | 
						|
  {
 | 
						|
    const char **pos;
 | 
						|
    uint *len;
 | 
						|
    *max_length= *tot_length= 0;
 | 
						|
    for (pos= interval->type_names, len= interval->type_lengths;
 | 
						|
         *pos ; pos++, len++)
 | 
						|
    {
 | 
						|
      size_t length= charset->numchars(*pos, *pos + *len);
 | 
						|
      DBUG_ASSERT(length < UINT_MAX32);
 | 
						|
      *tot_length+= (uint) length;
 | 
						|
      set_if_bigger(*max_length, (uint32)length);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  bool prepare_stage1_check_typelib_default();
 | 
						|
  bool prepare_stage1_convert_default(THD *, MEM_ROOT *, CHARSET_INFO *to);
 | 
						|
  const Type_handler *field_type() const; // Prevent using this
 | 
						|
  Compression_method *compression_method_ptr;
 | 
						|
public:
 | 
						|
  Lex_ident   field_name;
 | 
						|
  LEX_CSTRING comment;			// Comment for field
 | 
						|
  enum enum_column_versioning
 | 
						|
  {
 | 
						|
    VERSIONING_NOT_SET,
 | 
						|
    WITH_VERSIONING,
 | 
						|
    WITHOUT_VERSIONING
 | 
						|
  };
 | 
						|
  Item *on_update;		        // ON UPDATE NOW()
 | 
						|
  field_visibility_t invisible;
 | 
						|
  /*
 | 
						|
    The value of `length' as set by parser: is the number of characters
 | 
						|
    for most of the types, or of bytes for BLOBs or numeric types.
 | 
						|
  */
 | 
						|
  uint32 char_length;
 | 
						|
  uint  flags, pack_length;
 | 
						|
  List<String> interval_list;
 | 
						|
  engine_option_value *option_list;
 | 
						|
  bool explicitly_nullable;
 | 
						|
 | 
						|
  /*
 | 
						|
    This is additinal data provided for any computed(virtual) field.
 | 
						|
    In particular it includes a pointer to the item by  which this field
 | 
						|
    can be computed from other fields.
 | 
						|
  */
 | 
						|
  Virtual_column_info
 | 
						|
    *vcol_info,                      // Virtual field
 | 
						|
    *default_value,                  // Default value
 | 
						|
    *check_constraint;               // Check constraint
 | 
						|
 | 
						|
  enum_column_versioning versioning;
 | 
						|
 | 
						|
  Table_period_info *period;
 | 
						|
 | 
						|
  Column_definition()
 | 
						|
   :Type_handler_hybrid_field_type(&type_handler_null),
 | 
						|
    compression_method_ptr(0),
 | 
						|
    comment(null_clex_str),
 | 
						|
    on_update(NULL), invisible(VISIBLE), char_length(0),
 | 
						|
    flags(0), pack_length(0),
 | 
						|
    option_list(NULL), explicitly_nullable(false),
 | 
						|
    vcol_info(0), default_value(0), check_constraint(0),
 | 
						|
    versioning(VERSIONING_NOT_SET), period(NULL)
 | 
						|
  {
 | 
						|
    interval_list.empty();
 | 
						|
  }
 | 
						|
 | 
						|
  Column_definition(THD *thd, Field *field, Field *orig_field);
 | 
						|
  bool set_attributes(THD *thd,
 | 
						|
                      const Lex_field_type_st &attr,
 | 
						|
                      column_definition_type_t type);
 | 
						|
  void create_length_to_internal_length_null()
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(length == 0);
 | 
						|
    pack_length= 0;
 | 
						|
  }
 | 
						|
  void create_length_to_internal_length_simple()
 | 
						|
  {
 | 
						|
    pack_length= type_handler()->calc_pack_length((uint32) length);
 | 
						|
  }
 | 
						|
  void create_length_to_internal_length_string()
 | 
						|
  {
 | 
						|
    length*= charset->mbmaxlen;
 | 
						|
    if (real_field_type() == MYSQL_TYPE_VARCHAR && compression_method())
 | 
						|
      length++;
 | 
						|
    set_if_smaller(length, UINT_MAX32);
 | 
						|
    pack_length= type_handler()->calc_pack_length((uint32) length);
 | 
						|
  }
 | 
						|
  void create_length_to_internal_length_typelib()
 | 
						|
  {
 | 
						|
    /* Pack_length already calculated in sql_parse.cc */
 | 
						|
    length*= charset->mbmaxlen;
 | 
						|
  }
 | 
						|
  bool vers_sys_field() const
 | 
						|
  {
 | 
						|
    return flags & (VERS_ROW_START | VERS_ROW_END);
 | 
						|
  }
 | 
						|
  void create_length_to_internal_length_bit();
 | 
						|
  void create_length_to_internal_length_newdecimal();
 | 
						|
 | 
						|
  /*
 | 
						|
    Prepare the "charset" member for string data types,
 | 
						|
    such as CHAR, VARCHAR, TEXT, ENUM, SET:
 | 
						|
    - derive the charset if not specified explicitly
 | 
						|
    - find a _bin collation if the BINARY comparison style was specified, e.g.:
 | 
						|
       CREATE TABLE t1 (a VARCHAR(10) BINARY) CHARSET utf8;
 | 
						|
  */
 | 
						|
  bool prepare_charset_for_string(const Column_derived_attributes *dattr);
 | 
						|
 | 
						|
  /**
 | 
						|
    Prepare a SET/ENUM field.
 | 
						|
    Create "interval" from "interval_list" if needed, and adjust "length".
 | 
						|
    @param mem_root                   - Memory root to allocate TYPELIB and
 | 
						|
                                        its values on
 | 
						|
    @param reuse_interval_list_values - determines if TYPELIB can reuse value
 | 
						|
                                        buffers from interval_list, or should
 | 
						|
                                        always allocate a copy on mem_root,
 | 
						|
                                        even if character set conversion
 | 
						|
                                        is not needed
 | 
						|
  */
 | 
						|
  bool prepare_interval_field(MEM_ROOT *mem_root,
 | 
						|
                              bool reuse_interval_list_values);
 | 
						|
 | 
						|
  void prepare_interval_field_calc_length()
 | 
						|
  {
 | 
						|
    uint32 field_length, dummy;
 | 
						|
    if (real_field_type() == MYSQL_TYPE_SET)
 | 
						|
    {
 | 
						|
      calculate_interval_lengths(&dummy, &field_length);
 | 
						|
      length= field_length + (interval->count - 1);
 | 
						|
    }
 | 
						|
    else /* MYSQL_TYPE_ENUM */
 | 
						|
    {
 | 
						|
      calculate_interval_lengths(&field_length, &dummy);
 | 
						|
      length= field_length;
 | 
						|
    }
 | 
						|
    set_if_smaller(length, MAX_FIELD_WIDTH - 1);
 | 
						|
  }
 | 
						|
 | 
						|
  bool prepare_blob_field(THD *thd);
 | 
						|
 | 
						|
  bool sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root);
 | 
						|
 | 
						|
  bool prepare_stage1(THD *thd, MEM_ROOT *mem_root,
 | 
						|
                      column_definition_type_t type,
 | 
						|
                      const Column_derived_attributes *derived_attr);
 | 
						|
  void prepare_stage1_simple(CHARSET_INFO *cs)
 | 
						|
  {
 | 
						|
    charset= cs;
 | 
						|
    create_length_to_internal_length_simple();
 | 
						|
  }
 | 
						|
  bool prepare_stage1_typelib(THD *thd, MEM_ROOT *mem_root,
 | 
						|
                              column_definition_type_t deftype);
 | 
						|
  bool prepare_stage1_string(THD *thd, MEM_ROOT *mem_root);
 | 
						|
  bool prepare_stage1_bit(THD *thd, MEM_ROOT *mem_root);
 | 
						|
 | 
						|
  bool bulk_alter(const Column_derived_attributes *derived_attr,
 | 
						|
                  const Column_bulk_alter_attributes *bulk_attr)
 | 
						|
  {
 | 
						|
    return type_handler()->Column_definition_bulk_alter(this,
 | 
						|
                                                        derived_attr,
 | 
						|
                                                        bulk_attr);
 | 
						|
  }
 | 
						|
  void redefine_stage1_common(const Column_definition *dup_field,
 | 
						|
                              const handler *file);
 | 
						|
  bool redefine_stage1(const Column_definition *dup_field, const handler *file)
 | 
						|
  {
 | 
						|
    const Type_handler *handler= dup_field->type_handler();
 | 
						|
    return handler->Column_definition_redefine_stage1(this, dup_field, file);
 | 
						|
  }
 | 
						|
  bool prepare_stage2(handler *handler, ulonglong table_flags);
 | 
						|
  bool prepare_stage2_blob(handler *handler,
 | 
						|
                           ulonglong table_flags, uint field_flags);
 | 
						|
  bool prepare_stage2_varchar(ulonglong table_flags);
 | 
						|
  bool prepare_stage2_typelib(const char *type_name, uint field_flags,
 | 
						|
                              uint *dup_val_count);
 | 
						|
  uint pack_flag_numeric() const;
 | 
						|
  uint sign_length() const { return flags & UNSIGNED_FLAG ? 0 : 1; }
 | 
						|
  bool check_length(uint mysql_errno, uint max_allowed_length) const;
 | 
						|
  bool fix_attributes_real(uint default_length);
 | 
						|
  bool fix_attributes_int(uint default_length);
 | 
						|
  bool fix_attributes_decimal();
 | 
						|
  bool fix_attributes_temporal_with_time(uint int_part_length);
 | 
						|
  bool fix_attributes_bit();
 | 
						|
 | 
						|
  bool check(THD *thd);
 | 
						|
  bool validate_check_constraint(THD *thd);
 | 
						|
 | 
						|
  bool stored_in_db() const { return !vcol_info || vcol_info->stored_in_db; }
 | 
						|
 | 
						|
  ha_storage_media field_storage_type() const
 | 
						|
  {
 | 
						|
    return (ha_storage_media)
 | 
						|
      ((flags >> FIELD_FLAGS_STORAGE_MEDIA) & 3);
 | 
						|
  }
 | 
						|
 | 
						|
  column_format_type column_format() const
 | 
						|
  {
 | 
						|
    return (column_format_type)
 | 
						|
      ((flags >> FIELD_FLAGS_COLUMN_FORMAT) & 3);
 | 
						|
  }
 | 
						|
 | 
						|
  bool has_default_function() const
 | 
						|
  {
 | 
						|
    return unireg_check != Field::NONE;
 | 
						|
  }
 | 
						|
 | 
						|
  Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root,
 | 
						|
                    const Record_addr *addr,
 | 
						|
                    const LEX_CSTRING *field_name_arg) const
 | 
						|
  {
 | 
						|
    return Column_definition_attributes::make_field(share, mem_root, addr,
 | 
						|
                                                    type_handler(),
 | 
						|
                                                    field_name_arg, flags);
 | 
						|
  }
 | 
						|
  Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root,
 | 
						|
                    const LEX_CSTRING *field_name_arg) const
 | 
						|
  {
 | 
						|
    Record_addr addr(true);
 | 
						|
    return make_field(share, mem_root, &addr, field_name_arg);
 | 
						|
  }
 | 
						|
  /* Return true if default is an expression that must be saved explicitly */
 | 
						|
  bool has_default_expression();
 | 
						|
 | 
						|
  bool has_default_now_unireg_check() const
 | 
						|
  {
 | 
						|
    return unireg_check == Field::TIMESTAMP_DN_FIELD
 | 
						|
        || unireg_check == Field::TIMESTAMP_DNUN_FIELD;
 | 
						|
  }
 | 
						|
 | 
						|
  void set_type(const Column_definition &other)
 | 
						|
  {
 | 
						|
    set_handler(other.type_handler());
 | 
						|
    length= other.length;
 | 
						|
    char_length= other.char_length;
 | 
						|
    decimals= other.decimals;
 | 
						|
    flags= other.flags;
 | 
						|
    pack_length= other.pack_length;
 | 
						|
    unireg_check= other.unireg_check;
 | 
						|
    interval= other.interval;
 | 
						|
    charset= other.charset;
 | 
						|
    srid= other.srid;
 | 
						|
    pack_flag= other.pack_flag;
 | 
						|
  }
 | 
						|
 | 
						|
  // Replace the entire value by another definition
 | 
						|
  void set_column_definition(const Column_definition *def)
 | 
						|
  {
 | 
						|
    *this= *def;
 | 
						|
  }
 | 
						|
  bool set_compressed(const char *method);
 | 
						|
  bool set_compressed_deprecated(THD *thd, const char *method);
 | 
						|
  bool set_compressed_deprecated_column_attribute(THD *thd,
 | 
						|
                                                  const char *pos,
 | 
						|
                                                  const char *method);
 | 
						|
  void set_compression_method(Compression_method *compression_method_arg)
 | 
						|
  { compression_method_ptr= compression_method_arg; }
 | 
						|
  Compression_method *compression_method() const
 | 
						|
  { return compression_method_ptr; }
 | 
						|
 | 
						|
  bool check_vcol_for_key(THD *thd) const;
 | 
						|
 | 
						|
  void set_charset_collation_attrs(const
 | 
						|
                                   Lex_column_charset_collation_attrs_st &lc)
 | 
						|
  {
 | 
						|
    charset= lc.charset_info();
 | 
						|
    if (lc.is_contextually_typed_collation())
 | 
						|
      flags|= CONTEXT_COLLATION_FLAG;
 | 
						|
    else
 | 
						|
      flags&= ~CONTEXT_COLLATION_FLAG;
 | 
						|
  }
 | 
						|
  Lex_column_charset_collation_attrs charset_collation_attrs() const
 | 
						|
  {
 | 
						|
    if (!charset)
 | 
						|
      return Lex_column_charset_collation_attrs();
 | 
						|
    if (flags & CONTEXT_COLLATION_FLAG)
 | 
						|
      return Lex_column_charset_collation_attrs(Lex_context_collation(charset));
 | 
						|
    return Lex_column_charset_collation_attrs(Lex_exact_collation(charset));
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  List of ROW element definitions, e.g.:
 | 
						|
    DECLARE a ROW(a INT,b VARCHAR(10))
 | 
						|
*/
 | 
						|
class Row_definition_list: public List<class Spvar_definition>
 | 
						|
{
 | 
						|
public:
 | 
						|
  inline bool eq_name(const Spvar_definition *def, const LEX_CSTRING *name) const;
 | 
						|
  /**
 | 
						|
    Find a ROW field by name.
 | 
						|
    @param [IN]  name   - the name
 | 
						|
    @param [OUT] offset - if the ROW field found, its offset it returned here
 | 
						|
    @retval NULL        - the ROW field was not found
 | 
						|
    @retval !NULL       - the pointer to the found ROW field
 | 
						|
  */
 | 
						|
  Spvar_definition *find_row_field_by_name(const LEX_CSTRING *name, uint *offset) const
 | 
						|
  {
 | 
						|
    // Cast-off the "const" qualifier
 | 
						|
    List_iterator<Spvar_definition> it(*((List<Spvar_definition>*)this));
 | 
						|
    Spvar_definition *def;
 | 
						|
    for (*offset= 0; (def= it++); (*offset)++)
 | 
						|
    {
 | 
						|
      if (eq_name(def, name))
 | 
						|
        return def;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
  static Row_definition_list *make(MEM_ROOT *mem_root, Spvar_definition *var)
 | 
						|
  {
 | 
						|
    Row_definition_list *list;
 | 
						|
    if (!(list= new (mem_root) Row_definition_list()))
 | 
						|
      return NULL;
 | 
						|
    return list->push_back(var, mem_root) ? NULL : list;
 | 
						|
  }
 | 
						|
  bool append_uniq(MEM_ROOT *thd, Spvar_definition *var);
 | 
						|
  bool adjust_formal_params_to_actual_params(THD *thd, List<Item> *args);
 | 
						|
  bool adjust_formal_params_to_actual_params(THD *thd,
 | 
						|
                                             Item **args, uint arg_count);
 | 
						|
  bool resolve_type_refs(THD *);
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  This class is used during a stored routine or a trigger execution,
 | 
						|
  at sp_rcontext::create() time.
 | 
						|
  Currently it can represent:
 | 
						|
  - variables with explicit data types:   DECLARE a INT;
 | 
						|
  - variables with data type references:  DECLARE a t1.a%TYPE;
 | 
						|
  - ROW type variables
 | 
						|
 | 
						|
  Notes:
 | 
						|
  - Scalar variables have m_field_definitions==NULL.
 | 
						|
  - ROW variables are defined as having MYSQL_TYPE_NULL,
 | 
						|
    with a non-empty m_field_definitions.
 | 
						|
 | 
						|
  Data type references to other object types will be added soon, e.g.:
 | 
						|
  - DECLARE a table_name%ROWTYPE;
 | 
						|
  - DECLARE a cursor_name%ROWTYPE;
 | 
						|
  - DECLARE a record_name%TYPE;
 | 
						|
  - DECLARE a variable_name%TYPE;
 | 
						|
*/
 | 
						|
class Spvar_definition: public Column_definition
 | 
						|
{
 | 
						|
  Qualified_column_ident *m_column_type_ref; // for %TYPE
 | 
						|
  Table_ident *m_table_rowtype_ref;          // for table%ROWTYPE
 | 
						|
  bool m_cursor_rowtype_ref;                       // for cursor%ROWTYPE
 | 
						|
  uint m_cursor_rowtype_offset;                    // for cursor%ROWTYPE
 | 
						|
  Row_definition_list *m_row_field_definitions;    // for ROW
 | 
						|
public:
 | 
						|
  Spvar_definition()
 | 
						|
   :m_column_type_ref(NULL),
 | 
						|
    m_table_rowtype_ref(NULL),
 | 
						|
    m_cursor_rowtype_ref(false),
 | 
						|
    m_cursor_rowtype_offset(0),
 | 
						|
    m_row_field_definitions(NULL)
 | 
						|
  { }
 | 
						|
  Spvar_definition(THD *thd, Field *field)
 | 
						|
   :Column_definition(thd, field, NULL),
 | 
						|
    m_column_type_ref(NULL),
 | 
						|
    m_table_rowtype_ref(NULL),
 | 
						|
    m_cursor_rowtype_ref(false),
 | 
						|
    m_cursor_rowtype_offset(0),
 | 
						|
    m_row_field_definitions(NULL)
 | 
						|
  { }
 | 
						|
  const Type_handler *type_handler() const
 | 
						|
  {
 | 
						|
    return Type_handler_hybrid_field_type::type_handler();
 | 
						|
  }
 | 
						|
  bool is_column_type_ref() const { return m_column_type_ref != 0; }
 | 
						|
  bool is_table_rowtype_ref() const { return m_table_rowtype_ref != 0; }
 | 
						|
  bool is_cursor_rowtype_ref() const { return m_cursor_rowtype_ref; }
 | 
						|
  bool is_explicit_data_type() const
 | 
						|
  {
 | 
						|
    return !is_column_type_ref() &&
 | 
						|
           !is_table_rowtype_ref() &&
 | 
						|
           !is_cursor_rowtype_ref();
 | 
						|
  }
 | 
						|
  Qualified_column_ident *column_type_ref() const
 | 
						|
  {
 | 
						|
    return m_column_type_ref;
 | 
						|
  }
 | 
						|
  void set_column_type_ref(Qualified_column_ident *ref)
 | 
						|
  {
 | 
						|
    m_column_type_ref= ref;
 | 
						|
  }
 | 
						|
 | 
						|
  Table_ident *table_rowtype_ref() const
 | 
						|
  {
 | 
						|
    return m_table_rowtype_ref;
 | 
						|
  }
 | 
						|
  void set_table_rowtype_ref(Table_ident *ref)
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(ref);
 | 
						|
    set_handler(&type_handler_row);
 | 
						|
    m_table_rowtype_ref= ref;
 | 
						|
  }
 | 
						|
 | 
						|
  uint cursor_rowtype_offset() const
 | 
						|
  {
 | 
						|
    return m_cursor_rowtype_offset;
 | 
						|
  }
 | 
						|
  void set_cursor_rowtype_ref(uint offset)
 | 
						|
  {
 | 
						|
    set_handler(&type_handler_row);
 | 
						|
    m_cursor_rowtype_ref= true;
 | 
						|
    m_cursor_rowtype_offset= offset;
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
    Find a ROW field by name.
 | 
						|
    See Row_field_list::find_row_field_by_name() for details.
 | 
						|
  */
 | 
						|
  Spvar_definition *find_row_field_by_name(const LEX_CSTRING *name, uint *offset) const
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(m_row_field_definitions);
 | 
						|
    return m_row_field_definitions->find_row_field_by_name(name, offset);
 | 
						|
  }
 | 
						|
  uint is_row() const
 | 
						|
  {
 | 
						|
    return m_row_field_definitions != NULL;
 | 
						|
  }
 | 
						|
  // Check if "this" defines a ROW variable with n elements
 | 
						|
  uint is_row(uint n) const
 | 
						|
  {
 | 
						|
    return m_row_field_definitions != NULL &&
 | 
						|
           m_row_field_definitions->elements == n;
 | 
						|
  }
 | 
						|
  Row_definition_list *row_field_definitions() const
 | 
						|
  {
 | 
						|
    return m_row_field_definitions;
 | 
						|
  }
 | 
						|
  void set_row_field_definitions(Row_definition_list *list)
 | 
						|
  {
 | 
						|
    DBUG_ASSERT(list);
 | 
						|
    set_handler(&type_handler_row);
 | 
						|
    m_row_field_definitions= list;
 | 
						|
  }
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
inline bool Row_definition_list::eq_name(const Spvar_definition *def,
 | 
						|
                                         const LEX_CSTRING *name) const
 | 
						|
{
 | 
						|
  return def->field_name.length == name->length && my_strcasecmp(system_charset_info, def->field_name.str, name->str) == 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
class Create_field :public Column_definition
 | 
						|
{
 | 
						|
public:
 | 
						|
  LEX_CSTRING change;			// Old column name if column is renamed by ALTER
 | 
						|
  LEX_CSTRING after;			// Put column after this one
 | 
						|
  Field *field;				// For alter table
 | 
						|
  const TYPELIB *save_interval;         // Temporary copy for the above
 | 
						|
                                        // Used only for UCS2 intervals
 | 
						|
 | 
						|
  /** structure with parsed options (for comparing fields in ALTER TABLE) */
 | 
						|
  ha_field_option_struct *option_struct;
 | 
						|
  uint	offset;
 | 
						|
  uint8 interval_id;
 | 
						|
  bool create_if_not_exists;            // Used in ALTER TABLE IF NOT EXISTS
 | 
						|
 | 
						|
  Create_field():
 | 
						|
    Column_definition(),
 | 
						|
    field(0), option_struct(NULL),
 | 
						|
    create_if_not_exists(false)
 | 
						|
  {
 | 
						|
    change= after= null_clex_str;
 | 
						|
  }
 | 
						|
  Create_field(THD *thd, Field *old_field, Field *orig_field):
 | 
						|
    Column_definition(thd, old_field, orig_field),
 | 
						|
    change(old_field->field_name),
 | 
						|
    field(old_field), option_struct(old_field->option_struct),
 | 
						|
    create_if_not_exists(false)
 | 
						|
  {
 | 
						|
    after= null_clex_str;
 | 
						|
  }
 | 
						|
  /* Used to make a clone of this object for ALTER/CREATE TABLE */
 | 
						|
  Create_field *clone(MEM_ROOT *mem_root) const;
 | 
						|
  static void upgrade_data_types(List<Create_field> &list)
 | 
						|
  {
 | 
						|
    List_iterator<Create_field> it(list);
 | 
						|
    while (Create_field *f= it++)
 | 
						|
      f->type_handler()->type_handler_for_implicit_upgrade()->
 | 
						|
                           Column_definition_implicit_upgrade_to_this(f);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
  A class for sending info to the client
 | 
						|
*/
 | 
						|
 | 
						|
class Send_field :public Sql_alloc,
 | 
						|
                  public Type_handler_hybrid_field_type,
 | 
						|
                  public Send_field_extended_metadata
 | 
						|
{
 | 
						|
public:
 | 
						|
  LEX_CSTRING db_name;
 | 
						|
  LEX_CSTRING table_name, org_table_name;
 | 
						|
  LEX_CSTRING col_name, org_col_name;
 | 
						|
  ulong length;
 | 
						|
  uint flags;
 | 
						|
  decimal_digits_t decimals;
 | 
						|
  Send_field(Field *field)
 | 
						|
  {
 | 
						|
    field->make_send_field(this);
 | 
						|
    DBUG_ASSERT(table_name.str != 0);
 | 
						|
    normalize();
 | 
						|
  }
 | 
						|
  Send_field(THD *thd, Item *item);
 | 
						|
  Send_field(Field *field,
 | 
						|
             const LEX_CSTRING &db_name_arg,
 | 
						|
             const LEX_CSTRING &table_name_arg)
 | 
						|
   :Type_handler_hybrid_field_type(field->type_handler()),
 | 
						|
    db_name(db_name_arg),
 | 
						|
    table_name(table_name_arg),
 | 
						|
    org_table_name(table_name_arg),
 | 
						|
    col_name(field->field_name),
 | 
						|
    org_col_name(field->field_name),
 | 
						|
    length(field->field_length),
 | 
						|
    flags(field->table->maybe_null ?
 | 
						|
          (field->flags & ~NOT_NULL_FLAG) : field->flags),
 | 
						|
    decimals(field->decimals())
 | 
						|
  {
 | 
						|
    normalize();
 | 
						|
  }
 | 
						|
 | 
						|
private:
 | 
						|
  void normalize()
 | 
						|
  {
 | 
						|
    /* limit number of decimals for float and double */
 | 
						|
    if (type_handler()->field_type() == MYSQL_TYPE_FLOAT ||
 | 
						|
        type_handler()->field_type() == MYSQL_TYPE_DOUBLE)
 | 
						|
      set_if_smaller(decimals, FLOATING_POINT_DECIMALS);
 | 
						|
  }
 | 
						|
public:
 | 
						|
  // This should move to Type_handler eventually
 | 
						|
  uint32 max_char_length(CHARSET_INFO *cs) const
 | 
						|
  {
 | 
						|
    return type_handler()->field_type() >= MYSQL_TYPE_TINY_BLOB &&
 | 
						|
           type_handler()->field_type() <= MYSQL_TYPE_BLOB
 | 
						|
      ? static_cast<uint32>(length / cs->mbminlen)
 | 
						|
      : static_cast<uint32>(length / cs->mbmaxlen);
 | 
						|
  }
 | 
						|
  uint32 max_octet_length(CHARSET_INFO *from, CHARSET_INFO *to) const
 | 
						|
  {
 | 
						|
    /*
 | 
						|
      For TEXT/BLOB columns, field_length describes the maximum data
 | 
						|
      length in bytes. There is no limit to the number of characters
 | 
						|
      that a TEXT column can store, as long as the data fits into
 | 
						|
      the designated space.
 | 
						|
      For the rest of textual columns, field_length is evaluated as
 | 
						|
      char_count * mbmaxlen, where character count is taken from the
 | 
						|
      definition of the column. In other words, the maximum number
 | 
						|
      of characters here is limited by the column definition.
 | 
						|
 | 
						|
      When one has a LONG TEXT column with a single-byte
 | 
						|
      character set, and the connection character set is multi-byte, the
 | 
						|
      client may get fields longer than UINT_MAX32, due to
 | 
						|
      <character set column> -> <character set connection> conversion.
 | 
						|
      In that case column max length would not fit into the 4 bytes
 | 
						|
      reserved for it in the protocol. So we cut it here to UINT_MAX32.
 | 
						|
    */
 | 
						|
    return char_to_byte_length_safe(max_char_length(from), to->mbmaxlen);
 | 
						|
  }
 | 
						|
 | 
						|
  // This should move to Type_handler eventually
 | 
						|
  bool is_sane_float() const
 | 
						|
  {
 | 
						|
    return (decimals <= FLOATING_POINT_DECIMALS ||
 | 
						|
            (type_handler()->field_type() != MYSQL_TYPE_FLOAT &&
 | 
						|
             type_handler()->field_type() != MYSQL_TYPE_DOUBLE));
 | 
						|
  }
 | 
						|
  bool is_sane_signess() const
 | 
						|
  {
 | 
						|
    if (type_handler() == type_handler()->type_handler_signed() &&
 | 
						|
        type_handler() == type_handler()->type_handler_unsigned())
 | 
						|
      return true; // Any signess is allowed, e.g. DOUBLE, DECIMAL
 | 
						|
    /*
 | 
						|
      We are here e.g. in case of INT data type.
 | 
						|
      The UNSIGNED_FLAG bit must match in flags and in the type handler.
 | 
						|
    */
 | 
						|
    return ((bool) (flags & UNSIGNED_FLAG)) == type_handler()->is_unsigned();
 | 
						|
  }
 | 
						|
  bool is_sane() const
 | 
						|
  {
 | 
						|
    return is_sane_float() && is_sane_signess();
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
  A class for quick copying data to fields
 | 
						|
*/
 | 
						|
 | 
						|
class Copy_field :public Sql_alloc {
 | 
						|
public:
 | 
						|
  uchar *from_ptr,*to_ptr;
 | 
						|
  uchar *from_null_ptr,*to_null_ptr;
 | 
						|
  bool *null_row;
 | 
						|
  uint	from_bit,to_bit;
 | 
						|
  /**
 | 
						|
    Number of bytes in the fields pointed to by 'from_ptr' and
 | 
						|
    'to_ptr'. Usually this is the number of bytes that are copied from
 | 
						|
    'from_ptr' to 'to_ptr'.
 | 
						|
 | 
						|
    For variable-length fields (VARCHAR), the first byte(s) describe
 | 
						|
    the actual length of the text. For VARCHARs with length 
 | 
						|
       < 256 there is 1 length byte 
 | 
						|
       >= 256 there is 2 length bytes
 | 
						|
    Thus, if from_field is VARCHAR(10), from_length (and in most cases
 | 
						|
    to_length) is 11. For VARCHAR(1024), the length is 1026. @see
 | 
						|
    Field_varstring::length_bytes
 | 
						|
 | 
						|
    Note that for VARCHARs, do_copy() will be do_varstring*() which
 | 
						|
    only copies the length-bytes (1 or 2) + the actual length of the
 | 
						|
    text instead of from/to_length bytes.
 | 
						|
  */
 | 
						|
  uint from_length,to_length;
 | 
						|
  Field *from_field,*to_field;
 | 
						|
  String tmp;					// For items
 | 
						|
 | 
						|
  Copy_field() = default;
 | 
						|
  ~Copy_field() = default;
 | 
						|
  void set(Field *to,Field *from,bool save);	// Field to field 
 | 
						|
  void set(uchar *to,Field *from);		// Field to string
 | 
						|
  void (*do_copy)(Copy_field *);
 | 
						|
  void (*do_copy2)(Copy_field *);		// Used to handle null values
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
uint pack_length_to_packflag(uint type);
 | 
						|
enum_field_types get_blob_type_from_length(ulong length);
 | 
						|
int set_field_to_null(Field *field);
 | 
						|
int set_field_to_null_with_conversions(Field *field, bool no_conversions);
 | 
						|
int convert_null_to_field_value_or_error(Field *field, uint err);
 | 
						|
bool check_expression(Virtual_column_info *vcol, const LEX_CSTRING *name,
 | 
						|
                      enum_vcol_info_type type, Alter_info *alter_info= NULL);
 | 
						|
 | 
						|
/*
 | 
						|
  The following are for the interface with the .frm file
 | 
						|
*/
 | 
						|
 | 
						|
#define FIELDFLAG_DECIMAL		1U
 | 
						|
#define FIELDFLAG_BINARY		1U	// Shares same flag
 | 
						|
#define FIELDFLAG_NUMBER		2U
 | 
						|
#define FIELDFLAG_ZEROFILL		4U
 | 
						|
#define FIELDFLAG_PACK			120U	// Bits used for packing
 | 
						|
#define FIELDFLAG_INTERVAL		256U    // mangled with decimals!
 | 
						|
#define FIELDFLAG_BITFIELD		512U	// mangled with decimals!
 | 
						|
#define FIELDFLAG_BLOB			1024U	// mangled with decimals!
 | 
						|
#define FIELDFLAG_GEOM			2048U   // mangled with decimals!
 | 
						|
 | 
						|
#define FIELDFLAG_TREAT_BIT_AS_CHAR     4096U   /* use Field_bit_as_char */
 | 
						|
#define FIELDFLAG_LONG_DECIMAL          8192U
 | 
						|
#define FIELDFLAG_NO_DEFAULT		16384U  /* sql */
 | 
						|
#define FIELDFLAG_MAYBE_NULL		32768U	// sql
 | 
						|
#define FIELDFLAG_HEX_ESCAPE		0x10000U
 | 
						|
#define FIELDFLAG_PACK_SHIFT		3
 | 
						|
#define FIELDFLAG_DEC_SHIFT		8
 | 
						|
#define FIELDFLAG_MAX_DEC               63U
 | 
						|
 | 
						|
#define FIELDFLAG_DEC_MASK              0x3F00U
 | 
						|
 | 
						|
#define MTYP_TYPENR(type) ((type) & 127U) // Remove bits from type
 | 
						|
 | 
						|
#define f_is_dec(x)		((x) & FIELDFLAG_DECIMAL)
 | 
						|
#define f_is_num(x)		((x) & FIELDFLAG_NUMBER)
 | 
						|
#define f_is_zerofill(x)	((x) & FIELDFLAG_ZEROFILL)
 | 
						|
#define f_is_packed(x)		((x) & FIELDFLAG_PACK)
 | 
						|
#define f_packtype(x)		(((x) >> FIELDFLAG_PACK_SHIFT) & 15)
 | 
						|
#define f_decimals(x)		((uint8) (((x) >> FIELDFLAG_DEC_SHIFT) & FIELDFLAG_MAX_DEC))
 | 
						|
#define f_is_alpha(x)		(!f_is_num(x))
 | 
						|
#define f_is_binary(x)          ((x) & FIELDFLAG_BINARY) // 4.0- compatibility
 | 
						|
#define f_is_enum(x)            (((x) & (FIELDFLAG_INTERVAL | FIELDFLAG_NUMBER)) == FIELDFLAG_INTERVAL)
 | 
						|
#define f_is_bitfield(x)        (((x) & (FIELDFLAG_BITFIELD | FIELDFLAG_NUMBER)) == FIELDFLAG_BITFIELD)
 | 
						|
#define f_is_blob(x)		(((x) & (FIELDFLAG_BLOB | FIELDFLAG_NUMBER)) == FIELDFLAG_BLOB)
 | 
						|
#define f_is_geom(x)		(((x) & (FIELDFLAG_GEOM | FIELDFLAG_NUMBER)) == FIELDFLAG_GEOM)
 | 
						|
#define f_settype(x)		(((uint) (x)) << FIELDFLAG_PACK_SHIFT)
 | 
						|
#define f_maybe_null(x)		((x) & FIELDFLAG_MAYBE_NULL)
 | 
						|
#define f_no_default(x)		((x) & FIELDFLAG_NO_DEFAULT)
 | 
						|
#define f_bit_as_char(x)        ((x) & FIELDFLAG_TREAT_BIT_AS_CHAR)
 | 
						|
#define f_is_hex_escape(x)      ((x) & FIELDFLAG_HEX_ESCAPE)
 | 
						|
#define f_visibility(x)         (static_cast<field_visibility_t> ((x) & INVISIBLE_MAX_BITS))
 | 
						|
 | 
						|
inline
 | 
						|
ulonglong TABLE::vers_end_id() const
 | 
						|
{
 | 
						|
  DBUG_ASSERT(versioned(VERS_TRX_ID));
 | 
						|
  return static_cast<ulonglong>(vers_end_field()->val_int());
 | 
						|
}
 | 
						|
 | 
						|
inline
 | 
						|
ulonglong TABLE::vers_start_id() const
 | 
						|
{
 | 
						|
  DBUG_ASSERT(versioned(VERS_TRX_ID));
 | 
						|
  return static_cast<ulonglong>(vers_start_field()->val_int());
 | 
						|
}
 | 
						|
 | 
						|
double pos_in_interval_for_string(CHARSET_INFO *cset,
 | 
						|
                                  const uchar *midp_val, uint32 midp_len,
 | 
						|
                                  const uchar *min_val,  uint32 min_len,
 | 
						|
                                  const uchar *max_val,  uint32 max_len);
 | 
						|
 | 
						|
double pos_in_interval_for_double(double midp_val,
 | 
						|
                                  double min_val, double max_val);
 | 
						|
 | 
						|
#endif /* FIELD_INCLUDED */
 |