mirror of
				https://github.com/MariaDB/server.git
				synced 2025-10-31 02:46:29 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			5995 lines
		
	
	
	
		
			217 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			5995 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 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),
 | |
|     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
 | |
|   {
 | |
|     /* after reading the row vcol value is already in the buffer */
 | |
|     return vcol_type == VCOL_GENERATED_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(const Copy_field *copy);
 | |
|   static void do_field_int(const Copy_field *copy);
 | |
|   static void do_field_real(const Copy_field *copy);
 | |
|   static void do_field_string(const Copy_field *copy);
 | |
|   static void do_field_date(const Copy_field *copy);
 | |
|   static void do_field_temporal(const Copy_field *copy, date_mode_t fuzzydate);
 | |
|   static void do_field_datetime(const Copy_field *copy);
 | |
|   static void do_field_timestamp(const Copy_field *copy);
 | |
|   static void do_field_decimal(const 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(const 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_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);
 | |
| 
 | |
|   /*
 | |
|     Copy the Field::val_str() value to MEM_ROOT as a 0x00-teminated string.
 | |
| 
 | |
|     @param    mem_root   The memory root to put the value to.
 | |
|     @returns             {NULL,0} in case of EOM, or the field value otherwise.
 | |
| 
 | |
|     Only one 0x00 terminating byte is put in the end, even in case
 | |
|     of complex character sets like UCS2/UTF16/UTF32.
 | |
|     This is OK, since this method is used to read system tables,
 | |
|     which are in utf8.
 | |
|   */
 | |
|   LEX_STRING val_lex_string_strmake(MEM_ROOT *mem_root);
 | |
| 
 | |
|   /*
 | |
|     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() const
 | |
|   {
 | |
|     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->is_stored(); }
 | |
|   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(const 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(const Copy_field *copy);
 | |
|   static void do_conv_blob(const 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(const 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(Sql_used *used,
 | |
|                                   const Charset_collation_map_st &map,
 | |
|                                   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->is_stored(); }
 | |
| 
 | |
|   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(Sql_used *used,
 | |
|                                    const Charset_collation_map_st &map, const
 | |
|                                    Lex_column_charset_collation_attrs_st &lc)
 | |
|   {
 | |
|     charset= lc.charset_info(used, map);
 | |
|     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
 | |
| {
 | |
|   const 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();
 | |
|   }
 | |
|   const Qualified_column_ident *column_type_ref() const
 | |
|   {
 | |
|     return m_column_type_ref;
 | |
|   }
 | |
|   void set_column_type_ref(const 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;
 | |
|   mutable 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)(const Copy_field *);
 | |
|   void (*do_copy2)(const 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 */
 | 
