mirror of
				https://github.com/MariaDB/server.git
				synced 2025-10-31 02:46:29 +01:00 
			
		
		
		
	 9020baf126
			
		
	
	
	9020baf126
	
	
	
		
			
			Discovered this while working on MDEV-34720: test_if_cheaper_ordering() uses rec_per_key, while the original estimate for the access method is produced in best_access_path() by using actual_rec_per_key(). Make test_if_cheaper_ordering() also use actual_rec_per_key(). Also make several getter function "const" to make this compile. Also adjusted the testcase to handle this (the change backported from 11.0)
		
			
				
	
	
		
			923 lines
		
	
	
	
		
			26 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			923 lines
		
	
	
	
		
			26 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #ifndef STRUCTS_INCLUDED
 | |
| #define STRUCTS_INCLUDED
 | |
| 
 | |
| /* Copyright (c) 2000, 2010, Oracle and/or its affiliates.
 | |
|    Copyright (c) 2009, 2019, 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 */
 | |
| 
 | |
| 
 | |
| 
 | |
| /* The old structures from unireg */
 | |
| 
 | |
| #include "sql_plugin.h"                         /* plugin_ref */
 | |
| #include "sql_const.h"                          /* MAX_REFLENGTH */
 | |
| #include "my_time.h"                   /* enum_mysql_timestamp_type */
 | |
| #include "thr_lock.h"                  /* thr_lock_type */
 | |
| #include "my_base.h"                   /* ha_rows, ha_key_alg */
 | |
| #include <mysql_com.h>                  /* USERNAME_LENGTH */
 | |
| #include "sql_bitmap.h"
 | |
| 
 | |
| struct TABLE;
 | |
| class Type_handler;
 | |
| class Field;
 | |
| class Index_statistics;
 | |
| struct Lex_ident_cli_st;
 | |
| 
 | |
| class THD;
 | |
| 
 | |
| /* Array index type for table.field[] */
 | |
| typedef uint16 field_index_t;
 | |
| 
 | |
| typedef struct st_date_time_format {
 | |
|   uchar positions[8];
 | |
|   char  time_separator;			/* Separator between hour and minute */
 | |
|   uint flag;				/* For future */
 | |
|   LEX_CSTRING format;
 | |
| } DATE_TIME_FORMAT;
 | |
| 
 | |
| 
 | |
| typedef struct st_keyfile_info {	/* used with ha_info() */
 | |
|   uchar ref[MAX_REFLENGTH];		/* Pointer to current row */
 | |
|   uchar dupp_ref[MAX_REFLENGTH];	/* Pointer to dupp row */
 | |
|   uint ref_length;			/* Length of ref (1-8) */
 | |
|   uint block_size;			/* index block size */
 | |
|   File filenr;				/* (uniq) filenr for table */
 | |
|   ha_rows records;			/* Records i datafilen */
 | |
|   ha_rows deleted;			/* Deleted records */
 | |
|   ulonglong data_file_length;		/* Length off data file */
 | |
|   ulonglong max_data_file_length;	/* Length off data file */
 | |
|   ulonglong index_file_length;
 | |
|   ulonglong max_index_file_length;
 | |
|   ulonglong delete_length;		/* Free bytes */
 | |
|   ulonglong auto_increment_value;
 | |
|   int errkey,sortkey;			/* Last errorkey and sorted by */
 | |
|   time_t create_time;			/* When table was created */
 | |
|   time_t check_time;
 | |
|   time_t update_time;
 | |
|   ulong mean_rec_length;		/* physical reclength */
 | |
| } KEYFILE_INFO;
 | |
| 
 | |
| 
 | |
| typedef struct st_key_part_info {	/* Info about a key part */
 | |
|   Field *field;                         /* the Field object for the indexed
 | |
|                                            prefix of the original table Field.
 | |
|                                            NOT necessarily the original Field */
 | |
|   uint  offset;                         /* Offset in record (from 0) */
 | |
|   uint  null_offset;                    /* Offset to null_bit in record */
 | |
|   /* Length of key part in bytes, excluding NULL flag and length bytes */
 | |
|   uint length;
 | |
|   /* 
 | |
|     Number of bytes required to store the keypart value. This may be
 | |
|     different from the "length" field as it also counts
 | |
|      - possible NULL-flag byte (see HA_KEY_NULL_LENGTH)
 | |
|      - possible HA_KEY_BLOB_LENGTH bytes needed to store actual value length.
 | |
|   */
 | |
|   uint store_length;
 | |
|   uint16 key_type;
 | |
|   field_index_t fieldnr;                /* Fieldnr begins counting from 1 */
 | |
|   uint16 key_part_flag;                 /* 0 or HA_REVERSE_SORT */
 | |
|   uint8 type;
 | |
|   uint8 null_bit;                       /* Position to null_bit */
 | |
| } KEY_PART_INFO ;
 | |
| 
 | |
| class engine_option_value;
 | |
| struct ha_index_option_struct;
 | |
| 
 | |
| typedef struct st_key {
 | |
|   uint  key_length;                /* total length of user defined key parts  */
 | |
|   ulong flags;                     /* dupp key and pack flags */
 | |
|   uint  user_defined_key_parts;    /* How many key_parts */
 | |
|   uint  usable_key_parts; /* Should normally be = user_defined_key_parts */
 | |
|   uint  ext_key_parts;             /* Number of key parts in extended key */
 | |
|   ulong ext_key_flags;             /* Flags for extended key              */
 | |
|   /*
 | |
|     Parts of primary key that are in the extension of this index. 
 | |
| 
 | |
|     Example: if this structure describes idx1, which is defined as 
 | |
|       INDEX idx1 (pk2, col2)
 | |
|     and pk is defined as:
 | |
|       PRIMARY KEY (pk1, pk2)
 | |
|     then 
 | |
|       pk1 is in the extension idx1, ext_key_part_map.is_set(0) == true
 | |
|       pk2 is explicitly present in idx1, it is not in the extension, so
 | |
|       ext_key_part_map.is_set(1) == false
 | |
|   */
 | |
|   key_part_map ext_key_part_map;
 | |
|   /*
 | |
|     Bitmap of indexes having common parts with this index
 | |
|     (only key parts from key definitions are taken into account)
 | |
|   */
 | |
|   key_map overlapped;
 | |
|   /* Set of keys constraint correlated with this key */
 | |
|   key_map constraint_correlated;
 | |
|   LEX_CSTRING name;
 | |
|   uint  block_size;
 | |
|   enum  ha_key_alg algorithm;
 | |
|   /* 
 | |
|     The flag is on if statistical data for the index prefixes
 | |
|     has to be taken from the system statistical tables.
 | |
|   */
 | |
|   bool is_statistics_from_stat_tables;
 | |
|   /*
 | |
|     Note that parser is used when the table is opened for use, and
 | |
|     parser_name is used when the table is being created.
 | |
|   */
 | |
|   union
 | |
|   {
 | |
|     plugin_ref parser;                  /* Fulltext [pre]parser */
 | |
|     LEX_CSTRING *parser_name;           /* Fulltext [pre]parser name */
 | |
|   };
 | |
|   KEY_PART_INFO *key_part;
 | |
|   /* Unique name for cache;  db + \0 + table_name + \0 + key_name + \0 */
 | |
|   uchar *cache_name;
 | |
|   /*
 | |
|     Array of AVG(#records with the same field value) for 1st ... Nth key part.
 | |
|     0 means 'not known'.
 | |
|     For temporary heap tables this member is NULL.
 | |
|   */
 | |
|   ulong *rec_per_key;
 | |
| 
 | |
|   /*
 | |
|     This structure is used for statistical data on the index
 | |
|     that has been read from the statistical table index_stat
 | |
|   */ 
 | |
|   Index_statistics *read_stats;
 | |
|   /*
 | |
|     This structure is used for statistical data on the index that
 | |
|     is collected by the function collect_statistics_for_table
 | |
|   */
 | |
|   Index_statistics *collected_stats;
 | |
|  
 | |
|   TABLE *table;
 | |
|   LEX_CSTRING comment;
 | |
|   /** reference to the list of options or NULL */
 | |
|   engine_option_value *option_list;
 | |
|   ha_index_option_struct *option_struct;                  /* structure with parsed options */
 | |
| 
 | |
|   double actual_rec_per_key(uint i) const;
 | |
| 
 | |
|   bool without_overlaps;
 | |
|   /*
 | |
|     TRUE if index needs to be ignored
 | |
|   */
 | |
|   bool is_ignored;
 | |
| } KEY;
 | |
| 
 | |
| 
 | |
| struct st_join_table;
 | |
| 
 | |
| typedef struct st_reginfo {		/* Extra info about reg */
 | |
|   struct st_join_table *join_tab;	/* Used by SELECT() */
 | |
|   enum thr_lock_type lock_type;		/* How database is used */
 | |
|   bool skip_locked;
 | |
|   bool not_exists_optimize;
 | |
|   /*
 | |
|     TRUE <=> range optimizer found that there is no rows satisfying
 | |
|     table conditions.
 | |
|   */
 | |
|   bool impossible_range;
 | |
| } REGINFO;
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Originally MySQL used MYSQL_TIME structure inside server only, but since
 | |
|   4.1 it's exported to user in the new client API. Define aliases for
 | |
|   new names to keep existing code simple.
 | |
| */
 | |
| 
 | |
| typedef enum enum_mysql_timestamp_type timestamp_type;
 | |
| 
 | |
| 
 | |
| typedef struct {
 | |
|   ulong year,month,day,hour;
 | |
|   ulonglong minute,second,second_part;
 | |
|   bool neg;
 | |
| } INTERVAL;
 | |
| 
 | |
| 
 | |
| typedef struct st_known_date_time_format {
 | |
|   const char *format_name;
 | |
|   const char *date_format;
 | |
|   const char *datetime_format;
 | |
|   const char *time_format;
 | |
| } KNOWN_DATE_TIME_FORMAT;
 | |
| 
 | |
| extern const char *show_comp_option_name[];
 | |
| 
 | |
| typedef int *(*update_var)(THD *, struct st_mysql_show_var *);
 | |
| 
 | |
| struct USER_AUTH : public Sql_alloc
 | |
| {
 | |
|   LEX_CSTRING plugin, auth_str, pwtext;
 | |
|   USER_AUTH *next;
 | |
|   USER_AUTH() : next(NULL)
 | |
|   {
 | |
|     plugin.str= auth_str.str= "";
 | |
|     pwtext.str= NULL;
 | |
|     plugin.length= auth_str.length= pwtext.length= 0;
 | |
|   }
 | |
| };
 | |
| 
 | |
| struct AUTHID
 | |
| {
 | |
|   LEX_CSTRING user, host;
 | |
|   void init() { memset(this, 0, sizeof(*this)); }
 | |
|   void copy(MEM_ROOT *root, const LEX_CSTRING *usr, const LEX_CSTRING *host);
 | |
|   bool is_role() const { return user.str[0] && !host.str[0]; }
 | |
|   void set_lex_string(LEX_CSTRING *l, char *buf)
 | |
|   {
 | |
|     if (is_role())
 | |
|       *l= user;
 | |
|     else
 | |
|     {
 | |
|       l->str= buf;
 | |
|       l->length= strxmov(buf, user.str, "@", host.str, NullS) - buf;
 | |
|     }
 | |
|   }
 | |
|   void parse(const char *str, size_t length);
 | |
|   bool read_from_mysql_proc_row(THD *thd, TABLE *table);
 | |
| };
 | |
| 
 | |
| 
 | |
| struct LEX_USER: public AUTHID
 | |
| {
 | |
|   USER_AUTH *auth;
 | |
|   bool has_auth()
 | |
|   {
 | |
|     return auth && (auth->plugin.length || auth->auth_str.length || auth->pwtext.length);
 | |
|   }
 | |
| };
 | |
| 
 | |
| /*
 | |
|   This structure specifies the maximum amount of resources which
 | |
|   can be consumed by each account. Zero value of a member means
 | |
|   there is no limit.
 | |
| */
 | |
| typedef struct user_resources {
 | |
|   /* Maximum number of queries/statements per hour. */
 | |
|   uint questions;
 | |
|   /*
 | |
|      Maximum number of updating statements per hour (which statements are
 | |
|      updating is defined by sql_command_flags array).
 | |
|   */
 | |
|   uint updates;
 | |
|   /* Maximum number of connections established per hour. */
 | |
|   uint conn_per_hour;
 | |
|   /*
 | |
|     Maximum number of concurrent connections. If -1 then no new
 | |
|     connections allowed
 | |
|   */
 | |
|   int user_conn;
 | |
|   /* Max query timeout */
 | |
|   double max_statement_time;
 | |
| 
 | |
|   /*
 | |
|      Values of this enum and specified_limits member are used by the
 | |
|      parser to store which user limits were specified in GRANT statement.
 | |
|   */
 | |
|   enum {QUERIES_PER_HOUR= 1, UPDATES_PER_HOUR= 2, CONNECTIONS_PER_HOUR= 4,
 | |
|         USER_CONNECTIONS= 8, MAX_STATEMENT_TIME= 16};
 | |
|   uint specified_limits;
 | |
| } USER_RESOURCES;
 | |
| 
 | |
| 
 | |
| /*
 | |
|   This structure is used for counting resources consumed and for checking
 | |
|   them against specified user limits.
 | |
| */
 | |
| typedef struct  user_conn {
 | |
|   /*
 | |
|      Pointer to user+host key (pair separated by '\0') defining the entity
 | |
|      for which resources are counted (By default it is user account thus
 | |
|      priv_user/priv_host pair is used. If --old-style-user-limits option
 | |
|      is enabled, resources are counted for each user+host separately).
 | |
|   */
 | |
|   char *user;
 | |
|   /* Pointer to host part of the key. */
 | |
|   char *host;
 | |
|   /**
 | |
|      The moment of time when per hour counters were reset last time
 | |
|      (i.e. start of "hour" for conn_per_hour, updates, questions counters).
 | |
|   */
 | |
|   ulonglong reset_utime;
 | |
|   /* Total length of the key. */
 | |
|   uint len;
 | |
|   /* Current amount of concurrent connections for this account. */
 | |
|   int connections;
 | |
|   /*
 | |
|      Current number of connections per hour, number of updating statements
 | |
|      per hour and total number of statements per hour for this account.
 | |
|   */
 | |
|   uint conn_per_hour, updates, questions;
 | |
|   /* Maximum amount of resources which account is allowed to consume. */
 | |
|   USER_RESOURCES user_resources;
 | |
| } USER_CONN;
 | |
| 
 | |
| typedef struct st_user_stats
 | |
| {
 | |
|   char user[MY_MAX(USERNAME_LENGTH, LIST_PROCESS_HOST_LEN) + 1];
 | |
|   // Account name the user is mapped to when this is a user from mapped_user.
 | |
|   // Otherwise, the same value as user.
 | |
|   char priv_user[MY_MAX(USERNAME_LENGTH, LIST_PROCESS_HOST_LEN) + 1];
 | |
|   uint user_name_length;
 | |
|   uint total_connections;
 | |
|   uint total_ssl_connections;
 | |
|   uint concurrent_connections;
 | |
|   time_t connected_time;  // in seconds
 | |
|   ha_rows rows_read, rows_sent;
 | |
|   ha_rows rows_updated, rows_deleted, rows_inserted;
 | |
|   ulonglong bytes_received;
 | |
|   ulonglong bytes_sent;
 | |
|   ulonglong binlog_bytes_written;
 | |
|   ulonglong select_commands, update_commands, other_commands;
 | |
|   ulonglong commit_trans, rollback_trans;
 | |
|   ulonglong denied_connections, lost_connections, max_statement_time_exceeded;
 | |
|   ulonglong access_denied_errors;
 | |
|   ulonglong empty_queries;
 | |
|   double busy_time;       // in seconds
 | |
|   double cpu_time;        // in seconds
 | |
| } USER_STATS;
 | |
| 
 | |
| typedef struct st_table_stats
 | |
| {
 | |
|   char table[NAME_LEN * 2 + 2];  // [db] + '\0' + [table] + '\0'
 | |
|   size_t table_name_length;
 | |
|   ulonglong rows_read, rows_changed;
 | |
|   ulonglong rows_changed_x_indexes;
 | |
|   /* Stores enum db_type, but forward declarations cannot be done */
 | |
|   int engine_type;
 | |
| } TABLE_STATS;
 | |
| 
 | |
| typedef struct st_index_stats
 | |
| {
 | |
|   // [db] + '\0' + [table] + '\0' + [index] + '\0'
 | |
|   char index[NAME_LEN * 3 + 3];
 | |
|   size_t index_name_length;                       /* Length of 'index' */
 | |
|   ulonglong rows_read;
 | |
| } INDEX_STATS;
 | |
| 
 | |
| 
 | |
| 	/* Bits in form->update */
 | |
| #define REG_MAKE_DUPP		1U	/* Make a copy of record when read */
 | |
| #define REG_NEW_RECORD		2U	/* Write a new record if not found */
 | |
| #define REG_UPDATE		4U	/* Uppdate record */
 | |
| #define REG_DELETE		8U	/* Delete found record */
 | |
| #define REG_PROG		16U	/* User is updating database */
 | |
| #define REG_CLEAR_AFTER_WRITE	32U
 | |
| #define REG_MAY_BE_UPDATED	64U
 | |
| #define REG_AUTO_UPDATE		64U	/* Used in D-forms for scroll-tables */
 | |
| #define REG_OVERWRITE		128U
 | |
| #define REG_SKIP_DUP		256U
 | |
| 
 | |
| 	/* Bits in form->status */
 | |
| #define STATUS_NO_RECORD	(1U+2U)	/* Record isn't usable */
 | |
| #define STATUS_GARBAGE		1U
 | |
| #define STATUS_NOT_FOUND	2U	/* No record in database when needed */
 | |
| #define STATUS_NO_PARENT	4U	/* Parent record wasn't found */
 | |
| #define STATUS_NOT_READ		8U	/* Record isn't read */
 | |
| #define STATUS_UPDATED		16U	/* Record is updated by formula */
 | |
| #define STATUS_NULL_ROW		32U	/* table->null_row is set */
 | |
| #define STATUS_DELETED		64U
 | |
| 
 | |
| /*
 | |
|   Such interval is "discrete": it is the set of
 | |
|   { auto_inc_interval_min + k * increment,
 | |
|     0 <= k <= (auto_inc_interval_values-1) }
 | |
|   Where "increment" is maintained separately by the user of this class (and is
 | |
|   currently only thd->variables.auto_increment_increment).
 | |
|   It mustn't derive from Sql_alloc, because SET INSERT_ID needs to
 | |
|   allocate memory which must stay allocated for use by the next statement.
 | |
| */
 | |
| class Discrete_interval {
 | |
| private:
 | |
|   ulonglong interval_min;
 | |
|   ulonglong interval_values;
 | |
|   ulonglong  interval_max;    // excluded bound. Redundant.
 | |
| public:
 | |
|   Discrete_interval *next;    // used when linked into Discrete_intervals_list
 | |
|   void replace(ulonglong start, ulonglong val, ulonglong incr)
 | |
|   {
 | |
|     interval_min=    start;
 | |
|     interval_values= val;
 | |
|     interval_max=    (val == ULONGLONG_MAX) ? val : start + val * incr;
 | |
|   }
 | |
|   Discrete_interval(ulonglong start, ulonglong val, ulonglong incr) :
 | |
|     next(NULL) { replace(start, val, incr); };
 | |
|   Discrete_interval() : next(NULL) { replace(0, 0, 0); };
 | |
|   ulonglong minimum() const { return interval_min;    };
 | |
|   ulonglong values()  const { return interval_values; };
 | |
|   ulonglong maximum() const { return interval_max;    };
 | |
|   /*
 | |
|     If appending [3,5] to [1,2], we merge both in [1,5] (they should have the
 | |
|     same increment for that, user of the class has to ensure that). That is
 | |
|     just a space optimization. Returns 0 if merge succeeded.
 | |
|   */
 | |
|   bool merge_if_contiguous(ulonglong start, ulonglong val, ulonglong incr)
 | |
|   {
 | |
|     if (interval_max == start)
 | |
|     {
 | |
|       if (val == ULONGLONG_MAX)
 | |
|       {
 | |
|         interval_values=   interval_max= val;
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         interval_values+=  val;
 | |
|         interval_max=      start + val * incr;
 | |
|       }
 | |
|       return 0;
 | |
|     }
 | |
|     return 1;
 | |
|   };
 | |
| };
 | |
| 
 | |
| /* List of Discrete_interval objects */
 | |
| class Discrete_intervals_list {
 | |
| private:
 | |
|   Discrete_interval        *head;
 | |
|   Discrete_interval        *tail;
 | |
|   /*
 | |
|     When many intervals are provided at the beginning of the execution of a
 | |
|     statement (in a replication slave or SET INSERT_ID), "current" points to
 | |
|     the interval being consumed by the thread now (so "current" goes from
 | |
|     "head" to "tail" then to NULL).
 | |
|   */
 | |
|   Discrete_interval        *current;
 | |
|   uint                  elements; // number of elements
 | |
|   void set_members(Discrete_interval *h, Discrete_interval *t,
 | |
|                    Discrete_interval *c, uint el)
 | |
|   {  
 | |
|     head= h;
 | |
|     tail= t;
 | |
|     current= c;
 | |
|     elements= el;
 | |
|   }
 | |
|   void operator=(Discrete_intervals_list &);  /* prevent use of these */
 | |
|   Discrete_intervals_list(const Discrete_intervals_list &);
 | |
| 
 | |
| public:
 | |
|   Discrete_intervals_list() : head(NULL), current(NULL), elements(0) {};
 | |
|   void empty_no_free()
 | |
|   {
 | |
|     set_members(NULL, NULL, NULL, 0);
 | |
|   }
 | |
|   void empty()
 | |
|   {
 | |
|     for (Discrete_interval *i= head; i;)
 | |
|     {
 | |
|       Discrete_interval *next= i->next;
 | |
|       delete i;
 | |
|       i= next;
 | |
|     }
 | |
|     empty_no_free();
 | |
|   }
 | |
|   void copy_shallow(const Discrete_intervals_list * dli)
 | |
|   {
 | |
|     head= dli->get_head();
 | |
|     tail= dli->get_tail();
 | |
|     current= dli->get_current();
 | |
|     elements= dli->nb_elements();
 | |
|   }
 | |
|   void swap (Discrete_intervals_list * dli)
 | |
|   {
 | |
|     Discrete_interval *h, *t, *c;
 | |
|     uint el;
 | |
|     h= dli->get_head();
 | |
|     t= dli->get_tail();
 | |
|     c= dli->get_current();
 | |
|     el= dli->nb_elements();
 | |
|     dli->copy_shallow(this);
 | |
|     set_members(h, t, c, el);
 | |
|   }
 | |
|   const Discrete_interval* get_next()
 | |
|   {
 | |
|     Discrete_interval *tmp= current;
 | |
|     if (current != NULL)
 | |
|       current= current->next;
 | |
|     return tmp;
 | |
|   }
 | |
|   ~Discrete_intervals_list() { empty(); };
 | |
|   bool append(ulonglong start, ulonglong val, ulonglong incr);
 | |
|   bool append(Discrete_interval *interval);
 | |
|   ulonglong minimum()     const { return (head ? head->minimum() : 0); };
 | |
|   ulonglong maximum()     const { return (head ? tail->maximum() : 0); };
 | |
|   uint      nb_elements() const { return elements; }
 | |
|   Discrete_interval* get_head() const { return head; };
 | |
|   Discrete_interval* get_tail() const { return tail; };
 | |
|   Discrete_interval* get_current() const { return current; };
 | |
| };
 | |
| 
 | |
| 
 | |
| /*
 | |
|   DDL options:
 | |
|   - CREATE IF NOT EXISTS
 | |
|   - DROP IF EXISTS
 | |
|   - CREATE LIKE
 | |
|   - REPLACE
 | |
| */
 | |
| struct DDL_options_st
 | |
| {
 | |
| public:
 | |
|   enum Options
 | |
|   {
 | |
|     OPT_NONE= 0,
 | |
|     OPT_IF_NOT_EXISTS= 2,              // CREATE TABLE IF NOT EXISTS
 | |
|     OPT_LIKE= 4,                       // CREATE TABLE LIKE
 | |
|     OPT_OR_REPLACE= 16,                // CREATE OR REPLACE TABLE
 | |
|     OPT_OR_REPLACE_SLAVE_GENERATED= 32,// REPLACE was added on slave, it was
 | |
|                                        // not in the original query on master.
 | |
|     OPT_IF_EXISTS= 64,
 | |
|     OPT_CREATE_SELECT= 128             // CREATE ... SELECT
 | |
|   };
 | |
| 
 | |
| private:
 | |
|   Options m_options;
 | |
| 
 | |
| public:
 | |
|   Options create_like_options() const
 | |
|   {
 | |
|     return (DDL_options_st::Options)
 | |
|            (((uint) m_options) & (OPT_IF_NOT_EXISTS | OPT_OR_REPLACE));
 | |
|   }
 | |
|   void init() { m_options= OPT_NONE; }
 | |
|   void init(Options options) { m_options= options; }
 | |
|   void set(Options other)
 | |
|   {
 | |
|     m_options= other;
 | |
|   }
 | |
|   void set(const DDL_options_st other)
 | |
|   {
 | |
|     m_options= other.m_options;
 | |
|   }
 | |
|   bool if_not_exists() const { return m_options & OPT_IF_NOT_EXISTS; }
 | |
|   bool or_replace() const { return m_options & OPT_OR_REPLACE; }
 | |
|   bool or_replace_slave_generated() const
 | |
|   { return m_options & OPT_OR_REPLACE_SLAVE_GENERATED; }
 | |
|   bool like() const { return m_options & OPT_LIKE; }
 | |
|   bool if_exists() const { return m_options & OPT_IF_EXISTS; }
 | |
|   bool is_create_select() const { return m_options & OPT_CREATE_SELECT; }
 | |
| 
 | |
|   void add(const DDL_options_st::Options other)
 | |
|   {
 | |
|     m_options= (Options) ((uint) m_options | (uint) other);
 | |
|   }
 | |
|   void add(const DDL_options_st &other)
 | |
|   {
 | |
|     add(other.m_options);
 | |
|   }
 | |
|   DDL_options_st operator|(const DDL_options_st &other)
 | |
|   {
 | |
|     add(other.m_options);
 | |
|     return *this;
 | |
|   }
 | |
|   DDL_options_st operator|=(DDL_options_st::Options other)
 | |
|   {
 | |
|     add(other);
 | |
|     return *this;
 | |
|   }
 | |
| };
 | |
| 
 | |
| 
 | |
| class DDL_options: public DDL_options_st
 | |
| {
 | |
| public:
 | |
|   DDL_options() { init(); }
 | |
|   DDL_options(Options options) { init(options); }
 | |
|   DDL_options(const DDL_options_st &options)
 | |
|   { DDL_options_st::operator=(options); }
 | |
| };
 | |
| 
 | |
| 
 | |
| struct Lex_length_and_dec_st
 | |
| {
 | |
| private:
 | |
|   const char *m_length;
 | |
|   const char *m_dec;
 | |
| public:
 | |
|   void set(const char *length, const char *dec)
 | |
|   {
 | |
|     m_length= length;
 | |
|     m_dec= dec;
 | |
|   }
 | |
|   const char *length() const { return m_length; }
 | |
|   const char *dec() const { return m_dec; }
 | |
| };
 | |
| 
 | |
| 
 | |
| struct Lex_field_type_st: public Lex_length_and_dec_st
 | |
| {
 | |
| private:
 | |
|   const Type_handler *m_handler;
 | |
|   void set(const Type_handler *handler, const char *length, const char *dec)
 | |
|   {
 | |
|     m_handler= handler;
 | |
|     Lex_length_and_dec_st::set(length, dec);
 | |
|   }
 | |
| public:
 | |
|   void set(const Type_handler *handler, Lex_length_and_dec_st length_and_dec)
 | |
|   {
 | |
|     m_handler= handler;
 | |
|     Lex_length_and_dec_st::operator=(length_and_dec);
 | |
|   }
 | |
|   void set_handler_length_flags(const Type_handler *handler, const char *length,
 | |
|                                 uint32 flags);
 | |
|   void set(const Type_handler *handler, const char *length)
 | |
|   {
 | |
|     set(handler, length, 0);
 | |
|   }
 | |
|   void set(const Type_handler *handler)
 | |
|   {
 | |
|     set(handler, 0, 0);
 | |
|   }
 | |
|   void set_handler(const Type_handler *handler)
 | |
|   {
 | |
|     m_handler= handler;
 | |
|   }
 | |
|   const Type_handler *type_handler() const { return m_handler; }
 | |
| };
 | |
| 
 | |
| 
 | |
| struct Lex_dyncol_type_st: public Lex_length_and_dec_st
 | |
| {
 | |
| private:
 | |
|   int m_type; // enum_dynamic_column_type is not visible here, so use int
 | |
| public:
 | |
|   void set(int type, const char *length, const char *dec)
 | |
|   {
 | |
|     m_type= type;
 | |
|     Lex_length_and_dec_st::set(length, dec);
 | |
|   }
 | |
|   void set(int type, Lex_length_and_dec_st length_and_dec)
 | |
|   {
 | |
|     m_type= type;
 | |
|     Lex_length_and_dec_st::operator=(length_and_dec);
 | |
|   }
 | |
|   void set(int type, const char *length)
 | |
|   {
 | |
|     set(type, length, 0);
 | |
|   }
 | |
|   void set(int type)
 | |
|   {
 | |
|     set(type, 0, 0);
 | |
|   }
 | |
|   int dyncol_type() const { return m_type; }
 | |
| };
 | |
| 
 | |
| 
 | |
| struct Lex_spblock_handlers_st
 | |
| {
 | |
| public:
 | |
|   int hndlrs;
 | |
|   void init(int count) { hndlrs= count; }
 | |
| };
 | |
| 
 | |
| 
 | |
| struct Lex_spblock_st: public Lex_spblock_handlers_st
 | |
| {
 | |
| public:
 | |
|   int vars;
 | |
|   int conds;
 | |
|   int curs;
 | |
|   void init()
 | |
|   {
 | |
|     vars= conds= hndlrs= curs= 0;
 | |
|   }
 | |
|   void init_using_vars(uint nvars)
 | |
|   {
 | |
|     vars= nvars;
 | |
|     conds= hndlrs= curs= 0;
 | |
|   }
 | |
|   void join(const Lex_spblock_st &b1, const Lex_spblock_st &b2)
 | |
|   {
 | |
|     vars= b1.vars + b2.vars;
 | |
|     conds= b1.conds + b2.conds;
 | |
|     hndlrs= b1.hndlrs + b2.hndlrs;
 | |
|     curs= b1.curs + b2.curs;
 | |
|   }
 | |
| };
 | |
| 
 | |
| 
 | |
| class Lex_spblock: public Lex_spblock_st
 | |
| {
 | |
| public:
 | |
|   Lex_spblock() { init(); }
 | |
|   Lex_spblock(const Lex_spblock_handlers_st &other)
 | |
|   {
 | |
|     vars= conds= curs= 0;
 | |
|     hndlrs= other.hndlrs;
 | |
|   }
 | |
| };
 | |
| 
 | |
| 
 | |
| struct Lex_for_loop_bounds_st
 | |
| {
 | |
| public:
 | |
|   class sp_assignment_lex *m_index;  // The first iteration value (or cursor)
 | |
|   class sp_assignment_lex *m_target_bound; // The last iteration value
 | |
|   int8 m_direction;
 | |
|   bool m_implicit_cursor;
 | |
|   bool is_for_loop_cursor() const { return m_target_bound == NULL; }
 | |
| };
 | |
| 
 | |
| 
 | |
| class Lex_for_loop_bounds_intrange: public Lex_for_loop_bounds_st
 | |
| {
 | |
| public:
 | |
|   Lex_for_loop_bounds_intrange(int8 direction,
 | |
|                                class sp_assignment_lex *left_expr,
 | |
|                                class sp_assignment_lex *right_expr)
 | |
|   {
 | |
|     m_direction= direction;
 | |
|     m_index=        direction > 0 ? left_expr  : right_expr;
 | |
|     m_target_bound= direction > 0 ? right_expr : left_expr;
 | |
|     m_implicit_cursor= false;
 | |
|   }
 | |
| };
 | |
| 
 | |
| 
 | |
| struct Lex_for_loop_st
 | |
| {
 | |
| public:
 | |
|   class sp_variable *m_index;  // The first iteration value (or cursor)
 | |
|   class sp_variable *m_target_bound; // The last iteration value
 | |
|   int m_cursor_offset;
 | |
|   int8 m_direction;
 | |
|   bool m_implicit_cursor;
 | |
|   void init()
 | |
|   {
 | |
|     m_index= 0;
 | |
|     m_target_bound= 0;
 | |
|     m_cursor_offset= 0;
 | |
|     m_direction= 0;
 | |
|     m_implicit_cursor= false;
 | |
|   }
 | |
|   bool is_for_loop_cursor() const { return m_target_bound == NULL; }
 | |
|   bool is_for_loop_explicit_cursor() const
 | |
|   {
 | |
|     return is_for_loop_cursor() && !m_implicit_cursor;
 | |
|   }
 | |
| };
 | |
| 
 | |
| 
 | |
| enum trim_spec { TRIM_LEADING, TRIM_TRAILING, TRIM_BOTH };
 | |
| 
 | |
| struct Lex_trim_st
 | |
| {
 | |
|   Item *m_remove;
 | |
|   Item *m_source;
 | |
|   trim_spec m_spec;
 | |
| public:
 | |
|   void set(trim_spec spec, Item *remove, Item *source)
 | |
|   {
 | |
|     m_spec= spec;
 | |
|     m_remove= remove;
 | |
|     m_source= source;
 | |
|   }
 | |
|   void set(trim_spec spec, Item *source)
 | |
|   {
 | |
|     set(spec, NULL, source);
 | |
|   }
 | |
|   Item *make_item_func_trim_std(THD *thd) const;
 | |
|   Item *make_item_func_trim_oracle(THD *thd) const;
 | |
| };
 | |
| 
 | |
| 
 | |
| class Lex_trim: public Lex_trim_st
 | |
| {
 | |
| public:
 | |
|   Lex_trim(trim_spec spec, Item *source) { set(spec, source); }
 | |
| };
 | |
| 
 | |
| 
 | |
| class Lex_substring_spec_st
 | |
| {
 | |
| public:
 | |
|   Item *m_subject;
 | |
|   Item *m_from;
 | |
|   Item *m_for;
 | |
|   static Lex_substring_spec_st init(Item *subject,
 | |
|                                     Item *from,
 | |
|                                     Item *xfor= NULL)
 | |
|   {
 | |
|     Lex_substring_spec_st res;
 | |
|     res.m_subject= subject;
 | |
|     res.m_from= from;
 | |
|     res.m_for= xfor;
 | |
|     return res;
 | |
|   }
 | |
| };
 | |
| 
 | |
| 
 | |
| class st_select_lex;
 | |
| 
 | |
| class Lex_select_lock
 | |
| {
 | |
| public:
 | |
|   struct
 | |
|   {
 | |
|     uint defined_lock:1;
 | |
|     uint update_lock:1;
 | |
|     uint defined_timeout:1;
 | |
|     uint skip_locked:1;
 | |
|   };
 | |
|   ulong timeout;
 | |
| 
 | |
| 
 | |
|   void empty()
 | |
|   {
 | |
|     defined_lock= update_lock= defined_timeout= skip_locked= FALSE;
 | |
|     timeout= 0;
 | |
|   }
 | |
|   void set_to(st_select_lex *sel);
 | |
| };
 | |
| 
 | |
| class Lex_select_limit
 | |
| {
 | |
| public:
 | |
|   /* explicit LIMIT clause was used */
 | |
|   bool explicit_limit;
 | |
|   bool with_ties;
 | |
|   Item *select_limit, *offset_limit;
 | |
| 
 | |
|   void clear()
 | |
|   {
 | |
|     explicit_limit= FALSE;    // No explicit limit given by user
 | |
|     with_ties= FALSE;         // No use of WITH TIES operator
 | |
|     select_limit= NULL;       // denotes the default limit = HA_POS_ERROR
 | |
|     offset_limit= NULL;       // denotes the default offset = 0
 | |
|   }
 | |
| };
 | |
| 
 | |
| struct st_order;
 | |
| 
 | |
| class Load_data_param
 | |
| {
 | |
| protected:
 | |
|   CHARSET_INFO *m_charset;   // Character set of the file
 | |
|   ulonglong m_fixed_length;  // Sum of target field lengths for fixed format
 | |
|   bool m_is_fixed_length;
 | |
|   bool m_use_blobs;
 | |
| public:
 | |
|   Load_data_param(CHARSET_INFO *cs, bool is_fixed_length):
 | |
|     m_charset(cs),
 | |
|     m_fixed_length(0),
 | |
|     m_is_fixed_length(is_fixed_length),
 | |
|     m_use_blobs(false)
 | |
|   { }
 | |
|   bool add_outvar_field(THD *thd, const Field *field);
 | |
|   bool add_outvar_user_var(THD *thd);
 | |
|   CHARSET_INFO *charset() const { return m_charset; }
 | |
|   bool is_fixed_length() const { return m_is_fixed_length; }
 | |
|   bool use_blobs() const { return m_use_blobs; }
 | |
| };
 | |
| 
 | |
| 
 | |
| class Load_data_outvar
 | |
| {
 | |
| public:
 | |
|   virtual ~Load_data_outvar() = default;
 | |
|   virtual bool load_data_set_null(THD *thd, const Load_data_param *param)= 0;
 | |
|   virtual bool load_data_set_value(THD *thd, const char *pos, uint length,
 | |
|                                    const Load_data_param *param)= 0;
 | |
|   virtual bool load_data_set_no_data(THD *thd, const Load_data_param *param)= 0;
 | |
|   virtual void load_data_print_for_log_event(THD *thd, class String *to) const= 0;
 | |
|   virtual bool load_data_add_outvar(THD *thd, Load_data_param *param) const= 0;
 | |
|   virtual uint load_data_fixed_length() const= 0;
 | |
| };
 | |
| 
 | |
| 
 | |
| class Timeval: public timeval
 | |
| {
 | |
| protected:
 | |
|   Timeval() = default;
 | |
| public:
 | |
|   Timeval(my_time_t sec, ulong usec)
 | |
|   {
 | |
|     tv_sec= sec;
 | |
|     /*
 | |
|       Since tv_usec is not always of type ulong, cast usec parameter
 | |
|       explicitly to uint to avoid compiler warnings about losing
 | |
|       integer precision.
 | |
|     */
 | |
|     DBUG_ASSERT(usec < 1000000);
 | |
|     tv_usec= (uint)usec;
 | |
|   }
 | |
|   explicit Timeval(const timeval &tv)
 | |
|    :timeval(tv)
 | |
|   { }
 | |
| };
 | |
| 
 | |
| 
 | |
| #endif /* STRUCTS_INCLUDED */
 |