mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-03 14:33:32 +03:00 
			
		
		
		
	Bug#16565 mysqld --help --verbose does not order variablesBug#20413 sql_slave_skip_counter is not shown in show variables Bug#20415 Output of mysqld --help --verbose is incomplete Bug#25430 variable not found in SELECT @@global.ft_max_word_len; Bug#32902 plugin variables don't know their names Bug#34599 MySQLD Option and Variable Reference need to be consistent in formatting! Bug#34829 No default value for variable and setting default does not raise error Bug#34834 ? Is accepted as a valid sql mode Bug#34878 Few variables have default value according to documentation but error occurs Bug#34883 ft_boolean_syntax cant be assigned from user variable to global var. Bug#37187 `INFORMATION_SCHEMA`.`GLOBAL_VARIABLES`: inconsistent status Bug#40988 log_output_basic.test succeeded though syntactically false. Bug#41010 enum-style command-line options are not honoured (maria.maria-recover fails) Bug#42103 Setting key_buffer_size to a negative value may lead to very large allocations Bug#44691 Some plugins configured as MYSQL_PLUGIN_MANDATORY in can be disabled Bug#44797 plugins w/o command-line options have no disabling option in --help Bug#46314 string system variables don't support expressions Bug#46470 sys_vars.max_binlog_cache_size_basic_32 is broken Bug#46586 When using the plugin interface the type "set" for options caused a crash. Bug#47212 Crash in DBUG_PRINT in mysqltest.cc when trying to print octal number Bug#48758 mysqltest crashes on sys_vars.collation_server_basic in gcov builds Bug#49417 some complaints about mysqld --help --verbose output Bug#49540 DEFAULT value of binlog_format isn't the default value Bug#49640 ambiguous option '--skip-skip-myisam' (double skip prefix) Bug#49644 init_connect and \0 Bug#49645 init_slave and multi-byte characters Bug#49646 mysql --show-warnings crashes when server dies
		
			
				
	
	
		
			773 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			773 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#ifndef SQL_SELECT_INCLUDED
 | 
						|
#define SQL_SELECT_INCLUDED
 | 
						|
 | 
						|
/* Copyright (C) 2000-2006 MySQL AB
 | 
						|
 | 
						|
   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  @file
 | 
						|
 | 
						|
  @brief
 | 
						|
  classes to use when handling where clause
 | 
						|
*/
 | 
						|
 | 
						|
#ifdef USE_PRAGMA_INTERFACE
 | 
						|
#pragma interface			/* gcc class implementation */
 | 
						|
#endif
 | 
						|
 | 
						|
#include "procedure.h"
 | 
						|
#include <myisam.h>
 | 
						|
 | 
						|
typedef struct keyuse_t {
 | 
						|
  TABLE *table;
 | 
						|
  Item	*val;				/**< or value if no field */
 | 
						|
  table_map used_tables;
 | 
						|
  uint	key, keypart, optimize;
 | 
						|
  key_part_map keypart_map;
 | 
						|
  ha_rows      ref_table_rows;
 | 
						|
  /**
 | 
						|
    If true, the comparison this value was created from will not be
 | 
						|
    satisfied if val has NULL 'value'.
 | 
						|
  */
 | 
						|
  bool null_rejecting;
 | 
						|
  /*
 | 
						|
    !NULL - This KEYUSE was created from an equality that was wrapped into
 | 
						|
            an Item_func_trig_cond. This means the equality (and validity of 
 | 
						|
            this KEYUSE element) can be turned on and off. The on/off state 
 | 
						|
            is indicted by the pointed value:
 | 
						|
              *cond_guard == TRUE <=> equality condition is on
 | 
						|
              *cond_guard == FALSE <=> equality condition is off
 | 
						|
 | 
						|
    NULL  - Otherwise (the source equality can't be turned off)
 | 
						|
  */
 | 
						|
  bool *cond_guard;
 | 
						|
} KEYUSE;
 | 
						|
 | 
						|
class store_key;
 | 
						|
 | 
						|
typedef struct st_table_ref
 | 
						|
{
 | 
						|
  bool		key_err;
 | 
						|
  /** True if something was read into buffer in join_read_key.  */
 | 
						|
  bool          has_record;
 | 
						|
  uint          key_parts;                ///< num of ...
 | 
						|
  uint          key_length;               ///< length of key_buff
 | 
						|
  int           key;                      ///< key no
 | 
						|
  uchar         *key_buff;                ///< value to look for with key
 | 
						|
  uchar         *key_buff2;               ///< key_buff+key_length
 | 
						|
  store_key     **key_copy;               //
 | 
						|
  Item          **items;                  ///< val()'s for each keypart
 | 
						|
  /*  
 | 
						|
    Array of pointers to trigger variables. Some/all of the pointers may be
 | 
						|
    NULL.  The ref access can be used iff
 | 
						|
    
 | 
						|
      for each used key part i, (!cond_guards[i] || *cond_guards[i]) 
 | 
						|
 | 
						|
    This array is used by subquery code. The subquery code may inject
 | 
						|
    triggered conditions, i.e. conditions that can be 'switched off'. A ref 
 | 
						|
    access created from such condition is not valid when at least one of the 
 | 
						|
    underlying conditions is switched off (see subquery code for more details)
 | 
						|
  */
 | 
						|
  bool          **cond_guards;
 | 
						|
  /**
 | 
						|
    (null_rejecting & (1<<i)) means the condition is '=' and no matching
 | 
						|
    rows will be produced if items[i] IS NULL (see add_not_null_conds())
 | 
						|
  */
 | 
						|
  key_part_map  null_rejecting;
 | 
						|
  table_map	depend_map;		  ///< Table depends on these tables.
 | 
						|
  /* null byte position in the key_buf. Used for REF_OR_NULL optimization */
 | 
						|
  uchar          *null_ref_key;
 | 
						|
  /*
 | 
						|
    The number of times the record associated with this key was used
 | 
						|
    in the join.
 | 
						|
  */
 | 
						|
  ha_rows       use_count;
 | 
						|
} TABLE_REF;
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  CACHE_FIELD and JOIN_CACHE is used on full join to cache records in outer
 | 
						|
  table
 | 
						|
*/
 | 
						|
 | 
						|
typedef struct st_cache_field {
 | 
						|
  uchar *str;
 | 
						|
  uint length, blob_length;
 | 
						|
  Field_blob *blob_field;
 | 
						|
  bool strip;
 | 
						|
} CACHE_FIELD;
 | 
						|
 | 
						|
 | 
						|
typedef struct st_join_cache {
 | 
						|
  uchar *buff,*pos,*end;
 | 
						|
  uint records,record_nr,ptr_record,fields,length,blobs;
 | 
						|
  CACHE_FIELD *field,**blob_ptr;
 | 
						|
  SQL_SELECT *select;
 | 
						|
} JOIN_CACHE;
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
  The structs which holds the join connections and join states
 | 
						|
*/
 | 
						|
enum join_type { JT_UNKNOWN,JT_SYSTEM,JT_CONST,JT_EQ_REF,JT_REF,JT_MAYBE_REF,
 | 
						|
		 JT_ALL, JT_RANGE, JT_NEXT, JT_FT, JT_REF_OR_NULL,
 | 
						|
		 JT_UNIQUE_SUBQUERY, JT_INDEX_SUBQUERY, JT_INDEX_MERGE};
 | 
						|
 | 
						|
class JOIN;
 | 
						|
 | 
						|
enum enum_nested_loop_state
 | 
						|
{
 | 
						|
  NESTED_LOOP_KILLED= -2, NESTED_LOOP_ERROR= -1,
 | 
						|
  NESTED_LOOP_OK= 0, NESTED_LOOP_NO_MORE_ROWS= 1,
 | 
						|
  NESTED_LOOP_QUERY_LIMIT= 3, NESTED_LOOP_CURSOR_LIMIT= 4
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/* Values for JOIN_TAB::packed_info */
 | 
						|
#define TAB_INFO_HAVE_VALUE 1
 | 
						|
#define TAB_INFO_USING_INDEX 2
 | 
						|
#define TAB_INFO_USING_WHERE 4
 | 
						|
#define TAB_INFO_FULL_SCAN_ON_NULL 8
 | 
						|
 | 
						|
typedef enum_nested_loop_state
 | 
						|
(*Next_select_func)(JOIN *, struct st_join_table *, bool);
 | 
						|
Next_select_func setup_end_select_func(JOIN *join);
 | 
						|
 | 
						|
 | 
						|
typedef struct st_join_table {
 | 
						|
  st_join_table() {}                          /* Remove gcc warning */
 | 
						|
  TABLE		*table;
 | 
						|
  KEYUSE	*keyuse;			/**< pointer to first used key */
 | 
						|
  SQL_SELECT	*select;
 | 
						|
  COND		*select_cond;
 | 
						|
  QUICK_SELECT_I *quick;
 | 
						|
  Item	       **on_expr_ref;   /**< pointer to the associated on expression   */
 | 
						|
  COND_EQUAL    *cond_equal;    /**< multiple equalities for the on expression */
 | 
						|
  st_join_table *first_inner;   /**< first inner table for including outerjoin */
 | 
						|
  bool           found;         /**< true after all matches or null complement */
 | 
						|
  bool           not_null_compl;/**< true before null complement is added      */
 | 
						|
  st_join_table *last_inner;    /**< last table table for embedding outer join */
 | 
						|
  st_join_table *first_upper;  /**< first inner table for embedding outer join */
 | 
						|
  st_join_table *first_unmatched; /**< used for optimization purposes only     */
 | 
						|
  
 | 
						|
  /* Special content for EXPLAIN 'Extra' column or NULL if none */
 | 
						|
  const char	*info;
 | 
						|
  /* 
 | 
						|
    Bitmap of TAB_INFO_* bits that encodes special line for EXPLAIN 'Extra'
 | 
						|
    column, or 0 if there is no info.
 | 
						|
  */
 | 
						|
  uint          packed_info;
 | 
						|
 | 
						|
  READ_RECORD::Setup_func read_first_record;
 | 
						|
  Next_select_func next_select;
 | 
						|
  READ_RECORD	read_record;
 | 
						|
  /* 
 | 
						|
    Currently the following two fields are used only for a [NOT] IN subquery
 | 
						|
    if it is executed by an alternative full table scan when the left operand of
 | 
						|
    the subquery predicate is evaluated to NULL.
 | 
						|
  */  
 | 
						|
  READ_RECORD::Setup_func save_read_first_record;/* to save read_first_record */
 | 
						|
  READ_RECORD::Read_func save_read_record;/* to save read_record.read_record */
 | 
						|
  double	worst_seeks;
 | 
						|
  key_map	const_keys;			/**< Keys with constant part */
 | 
						|
  key_map	checked_keys;			/**< Keys checked in find_best */
 | 
						|
  key_map	needed_reg;
 | 
						|
  key_map       keys;                           /**< all keys with can be used */
 | 
						|
 | 
						|
  /* Either #rows in the table or 1 for const table.  */
 | 
						|
  ha_rows	records;
 | 
						|
  /*
 | 
						|
    Number of records that will be scanned (yes scanned, not returned) by the
 | 
						|
    best 'independent' access method, i.e. table scan or QUICK_*_SELECT)
 | 
						|
  */
 | 
						|
  ha_rows       found_records;
 | 
						|
  /*
 | 
						|
    Cost of accessing the table using "ALL" or range/index_merge access
 | 
						|
    method (but not 'index' for some reason), i.e. this matches method which
 | 
						|
    E(#records) is in found_records.
 | 
						|
  */
 | 
						|
  ha_rows       read_time;
 | 
						|
  
 | 
						|
  table_map	dependent,key_dependent;
 | 
						|
  uint		use_quick,index;
 | 
						|
  uint		status;				///< Save status for cache
 | 
						|
  uint		used_fields,used_fieldlength,used_blobs;
 | 
						|
  enum join_type type;
 | 
						|
  bool		cached_eq_ref_table,eq_ref_table,not_used_in_distinct;
 | 
						|
  bool		sorted;
 | 
						|
  /* 
 | 
						|
    If it's not 0 the number stored this field indicates that the index
 | 
						|
    scan has been chosen to access the table data and we expect to scan 
 | 
						|
    this number of rows for the table.
 | 
						|
  */ 
 | 
						|
  ha_rows       limit; 
 | 
						|
  TABLE_REF	ref;
 | 
						|
  JOIN_CACHE	cache;
 | 
						|
  JOIN		*join;
 | 
						|
  /** Bitmap of nested joins this table is part of */
 | 
						|
  nested_join_map embedding_map;
 | 
						|
 | 
						|
  void cleanup();
 | 
						|
  inline bool is_using_loose_index_scan()
 | 
						|
  {
 | 
						|
    return (select && select->quick &&
 | 
						|
            (select->quick->get_type() ==
 | 
						|
             QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX));
 | 
						|
  }
 | 
						|
  bool is_using_agg_loose_index_scan ()
 | 
						|
  {
 | 
						|
    return (is_using_loose_index_scan() &&
 | 
						|
            ((QUICK_GROUP_MIN_MAX_SELECT *)select->quick)->is_agg_distinct());
 | 
						|
  }
 | 
						|
} JOIN_TAB;
 | 
						|
 | 
						|
enum_nested_loop_state sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool
 | 
						|
                                        end_of_records);
 | 
						|
enum_nested_loop_state sub_select(JOIN *join,JOIN_TAB *join_tab, bool
 | 
						|
                                  end_of_records);
 | 
						|
 | 
						|
/**
 | 
						|
  Information about a position of table within a join order. Used in join
 | 
						|
  optimization.
 | 
						|
*/
 | 
						|
typedef struct st_position
 | 
						|
{
 | 
						|
  /*
 | 
						|
    The "fanout": number of output rows that will be produced (after
 | 
						|
    pushed down selection condition is applied) per each row combination of
 | 
						|
    previous tables.
 | 
						|
  */
 | 
						|
  double records_read;
 | 
						|
 | 
						|
  /* 
 | 
						|
    Cost accessing the table in course of the entire complete join execution,
 | 
						|
    i.e. cost of one access method use (e.g. 'range' or 'ref' scan ) times 
 | 
						|
    number the access method will be invoked.
 | 
						|
  */
 | 
						|
  double read_time;
 | 
						|
  JOIN_TAB *table;
 | 
						|
 | 
						|
  /*
 | 
						|
    NULL  -  'index' or 'range' or 'index_merge' or 'ALL' access is used.
 | 
						|
    Other - [eq_]ref[_or_null] access is used. Pointer to {t.keypart1 = expr}
 | 
						|
  */
 | 
						|
  KEYUSE *key;
 | 
						|
 | 
						|
  /* If ref-based access is used: bitmap of tables this table depends on  */
 | 
						|
  table_map ref_depend_map;
 | 
						|
} POSITION;
 | 
						|
 | 
						|
 | 
						|
typedef struct st_rollup
 | 
						|
{
 | 
						|
  enum State { STATE_NONE, STATE_INITED, STATE_READY };
 | 
						|
  State state;
 | 
						|
  Item_null_result **null_items;
 | 
						|
  Item ***ref_pointer_arrays;
 | 
						|
  List<Item> *fields;
 | 
						|
} ROLLUP;
 | 
						|
 | 
						|
 | 
						|
class JOIN :public Sql_alloc
 | 
						|
{
 | 
						|
  JOIN(const JOIN &rhs);                        /**< not implemented */
 | 
						|
  JOIN& operator=(const JOIN &rhs);             /**< not implemented */
 | 
						|
public:
 | 
						|
  JOIN_TAB *join_tab,**best_ref;
 | 
						|
  JOIN_TAB **map2table;    ///< mapping between table indexes and JOIN_TABs
 | 
						|
  JOIN_TAB *join_tab_save; ///< saved join_tab for subquery reexecution
 | 
						|
  TABLE    **all_tables,*sort_by_table;
 | 
						|
  uint	   tables,const_tables;
 | 
						|
  uint	   send_group_parts;
 | 
						|
  /**
 | 
						|
    Indicates that grouping will be performed on the result set during
 | 
						|
    query execution. This field belongs to query execution.
 | 
						|
 | 
						|
    @see make_group_fields, alloc_group_fields, JOIN::exec
 | 
						|
  */
 | 
						|
  bool     sort_and_group; 
 | 
						|
  bool     first_record,full_join,group, no_field_update;
 | 
						|
  bool	   do_send_rows;
 | 
						|
  /**
 | 
						|
    TRUE when we want to resume nested loop iterations when
 | 
						|
    fetching data from a cursor
 | 
						|
  */
 | 
						|
  bool     resume_nested_loop;
 | 
						|
  table_map const_table_map,found_const_table_map;
 | 
						|
  /*
 | 
						|
     Bitmap of all inner tables from outer joins
 | 
						|
  */
 | 
						|
  table_map outer_join;
 | 
						|
  ha_rows  send_records,found_records,examined_rows,row_limit, select_limit;
 | 
						|
  /**
 | 
						|
    Used to fetch no more than given amount of rows per one
 | 
						|
    fetch operation of server side cursor.
 | 
						|
    The value is checked in end_send and end_send_group in fashion, similar
 | 
						|
    to offset_limit_cnt:
 | 
						|
      - fetch_limit= HA_POS_ERROR if there is no cursor.
 | 
						|
      - when we open a cursor, we set fetch_limit to 0,
 | 
						|
      - on each fetch iteration we add num_rows to fetch to fetch_limit
 | 
						|
  */
 | 
						|
  ha_rows  fetch_limit;
 | 
						|
  POSITION positions[MAX_TABLES+1],best_positions[MAX_TABLES+1];
 | 
						|
  
 | 
						|
  /* *
 | 
						|
    Bitmap of nested joins embedding the position at the end of the current 
 | 
						|
    partial join (valid only during join optimizer run).
 | 
						|
  */
 | 
						|
  nested_join_map cur_embedding_map;
 | 
						|
 | 
						|
  double   best_read;
 | 
						|
  List<Item> *fields;
 | 
						|
  List<Cached_item> group_fields, group_fields_cache;
 | 
						|
  TABLE    *tmp_table;
 | 
						|
  /// used to store 2 possible tmp table of SELECT
 | 
						|
  TABLE    *exec_tmp_table1, *exec_tmp_table2;
 | 
						|
  THD	   *thd;
 | 
						|
  Item_sum  **sum_funcs, ***sum_funcs_end;
 | 
						|
  /** second copy of sumfuncs (for queries with 2 temporary tables */
 | 
						|
  Item_sum  **sum_funcs2, ***sum_funcs_end2;
 | 
						|
  Procedure *procedure;
 | 
						|
  Item	    *having;
 | 
						|
  Item      *tmp_having; ///< To store having when processed temporary table
 | 
						|
  Item      *having_history; ///< Store having for explain
 | 
						|
  ulonglong  select_options;
 | 
						|
  select_result *result;
 | 
						|
  TMP_TABLE_PARAM tmp_table_param;
 | 
						|
  MYSQL_LOCK *lock;
 | 
						|
  /// unit structure (with global parameters) for this select
 | 
						|
  SELECT_LEX_UNIT *unit;
 | 
						|
  /// select that processed
 | 
						|
  SELECT_LEX *select_lex;
 | 
						|
  /** 
 | 
						|
    TRUE <=> optimizer must not mark any table as a constant table.
 | 
						|
    This is needed for subqueries in form "a IN (SELECT .. UNION SELECT ..):
 | 
						|
    when we optimize the select that reads the results of the union from a
 | 
						|
    temporary table, we must not mark the temp. table as constant because
 | 
						|
    the number of rows in it may vary from one subquery execution to another.
 | 
						|
  */
 | 
						|
  bool no_const_tables; 
 | 
						|
  
 | 
						|
  JOIN *tmp_join; ///< copy of this JOIN to be used with temporary tables
 | 
						|
  ROLLUP rollup;				///< Used with rollup
 | 
						|
 | 
						|
  bool select_distinct;				///< Set if SELECT DISTINCT
 | 
						|
  /**
 | 
						|
    If we have the GROUP BY statement in the query,
 | 
						|
    but the group_list was emptied by optimizer, this
 | 
						|
    flag is TRUE.
 | 
						|
    It happens when fields in the GROUP BY are from
 | 
						|
    constant table
 | 
						|
  */
 | 
						|
  bool group_optimized_away;
 | 
						|
 | 
						|
  /*
 | 
						|
    simple_xxxxx is set if ORDER/GROUP BY doesn't include any references
 | 
						|
    to other tables than the first non-constant table in the JOIN.
 | 
						|
    It's also set if ORDER/GROUP BY is empty.
 | 
						|
    Used for deciding for or against using a temporary table to compute 
 | 
						|
    GROUP/ORDER BY.
 | 
						|
  */
 | 
						|
  bool simple_order, simple_group;
 | 
						|
  /**
 | 
						|
    Is set only in case if we have a GROUP BY clause
 | 
						|
    and no ORDER BY after constant elimination of 'order'.
 | 
						|
  */
 | 
						|
  bool no_order;
 | 
						|
  /** Is set if we have a GROUP BY and we have ORDER BY on a constant. */
 | 
						|
  bool          skip_sort_order;
 | 
						|
 | 
						|
  bool need_tmp, hidden_group_fields;
 | 
						|
  DYNAMIC_ARRAY keyuse;
 | 
						|
  Item::cond_result cond_value, having_value;
 | 
						|
  List<Item> all_fields; ///< to store all fields that used in query
 | 
						|
  ///Above list changed to use temporary table
 | 
						|
  List<Item> tmp_all_fields1, tmp_all_fields2, tmp_all_fields3;
 | 
						|
  ///Part, shared with list above, emulate following list
 | 
						|
  List<Item> tmp_fields_list1, tmp_fields_list2, tmp_fields_list3;
 | 
						|
  List<Item> &fields_list; ///< hold field list passed to mysql_select
 | 
						|
  List<Item> procedure_fields_list;
 | 
						|
  int error;
 | 
						|
 | 
						|
  ORDER *order, *group_list, *proc_param; //hold parameters of mysql_select
 | 
						|
  COND *conds;                            // ---"---
 | 
						|
  Item *conds_history;                    // store WHERE for explain
 | 
						|
  TABLE_LIST *tables_list;           ///<hold 'tables' parameter of mysql_select
 | 
						|
  List<TABLE_LIST> *join_list;       ///< list of joined tables in reverse order
 | 
						|
  COND_EQUAL *cond_equal;
 | 
						|
  SQL_SELECT *select;                ///<created in optimisation phase
 | 
						|
  JOIN_TAB *return_tab;              ///<used only for outer joins
 | 
						|
  Item **ref_pointer_array; ///<used pointer reference for this select
 | 
						|
  // Copy of above to be used with different lists
 | 
						|
  Item **items0, **items1, **items2, **items3, **current_ref_pointer_array;
 | 
						|
  uint ref_pointer_array_size; ///< size of above in bytes
 | 
						|
  const char *zero_result_cause; ///< not 0 if exec must return zero result
 | 
						|
  
 | 
						|
  bool union_part; ///< this subselect is part of union 
 | 
						|
  bool optimized; ///< flag to avoid double optimization in EXPLAIN
 | 
						|
 | 
						|
  /* 
 | 
						|
    storage for caching buffers allocated during query execution. 
 | 
						|
    These buffers allocations need to be cached as the thread memory pool is
 | 
						|
    cleared only at the end of the execution of the whole query and not caching
 | 
						|
    allocations that occur in repetition at execution time will result in 
 | 
						|
    excessive memory usage.
 | 
						|
    Note: make_simple_join always creates an execution plan that accesses
 | 
						|
    a single table, thus it is sufficient to have a one-element array for
 | 
						|
    table_reexec.
 | 
						|
  */  
 | 
						|
  SORT_FIELD *sortorder;                        // make_unireg_sortorder()
 | 
						|
  TABLE *table_reexec[1];                       // make_simple_join()
 | 
						|
  JOIN_TAB *join_tab_reexec;                    // make_simple_join()
 | 
						|
  /* end of allocation caching storage */
 | 
						|
 | 
						|
  JOIN(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
 | 
						|
       select_result *result_arg)
 | 
						|
    :fields_list(fields_arg)
 | 
						|
  {
 | 
						|
    init(thd_arg, fields_arg, select_options_arg, result_arg);
 | 
						|
  }
 | 
						|
 | 
						|
  void init(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
 | 
						|
       select_result *result_arg)
 | 
						|
  {
 | 
						|
    join_tab= join_tab_save= 0;
 | 
						|
    all_tables= 0;
 | 
						|
    tables= 0;
 | 
						|
    const_tables= 0;
 | 
						|
    join_list= 0;
 | 
						|
    implicit_grouping= FALSE;
 | 
						|
    sort_and_group= 0;
 | 
						|
    first_record= 0;
 | 
						|
    do_send_rows= 1;
 | 
						|
    resume_nested_loop= FALSE;
 | 
						|
    send_records= 0;
 | 
						|
    found_records= 0;
 | 
						|
    fetch_limit= HA_POS_ERROR;
 | 
						|
    examined_rows= 0;
 | 
						|
    exec_tmp_table1= 0;
 | 
						|
    exec_tmp_table2= 0;
 | 
						|
    sortorder= 0;
 | 
						|
    table_reexec[0]= 0;
 | 
						|
    join_tab_reexec= 0;
 | 
						|
    thd= thd_arg;
 | 
						|
    sum_funcs= sum_funcs2= 0;
 | 
						|
    procedure= 0;
 | 
						|
    having= tmp_having= having_history= 0;
 | 
						|
    select_options= select_options_arg;
 | 
						|
    result= result_arg;
 | 
						|
    lock= thd_arg->lock;
 | 
						|
    select_lex= 0; //for safety
 | 
						|
    tmp_join= 0;
 | 
						|
    select_distinct= test(select_options & SELECT_DISTINCT);
 | 
						|
    no_order= 0;
 | 
						|
    simple_order= 0;
 | 
						|
    simple_group= 0;
 | 
						|
    skip_sort_order= 0;
 | 
						|
    need_tmp= 0;
 | 
						|
    hidden_group_fields= 0; /*safety*/
 | 
						|
    error= 0;
 | 
						|
    select= 0;
 | 
						|
    return_tab= 0;
 | 
						|
    ref_pointer_array= items0= items1= items2= items3= 0;
 | 
						|
    ref_pointer_array_size= 0;
 | 
						|
    zero_result_cause= 0;
 | 
						|
    optimized= 0;
 | 
						|
    cond_equal= 0;
 | 
						|
    group_optimized_away= 0;
 | 
						|
 | 
						|
    all_fields= fields_arg;
 | 
						|
    if (&fields_list != &fields_arg)      /* Avoid valgrind-warning */
 | 
						|
      fields_list= fields_arg;
 | 
						|
    bzero((char*) &keyuse,sizeof(keyuse));
 | 
						|
    tmp_table_param.init();
 | 
						|
    tmp_table_param.end_write_records= HA_POS_ERROR;
 | 
						|
    rollup.state= ROLLUP::STATE_NONE;
 | 
						|
 | 
						|
    no_const_tables= FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num,
 | 
						|
	      COND *conds, uint og_num, ORDER *order, ORDER *group,
 | 
						|
	      Item *having, ORDER *proc_param, SELECT_LEX *select,
 | 
						|
	      SELECT_LEX_UNIT *unit);
 | 
						|
  int optimize();
 | 
						|
  int reinit();
 | 
						|
  void exec();
 | 
						|
  int destroy();
 | 
						|
  void restore_tmp();
 | 
						|
  bool alloc_func_list();
 | 
						|
  bool make_sum_func_list(List<Item> &all_fields, List<Item> &send_fields,
 | 
						|
			  bool before_group_by, bool recompute= FALSE);
 | 
						|
 | 
						|
  inline void set_items_ref_array(Item **ptr)
 | 
						|
  {
 | 
						|
    memcpy((char*) ref_pointer_array, (char*) ptr, ref_pointer_array_size);
 | 
						|
    current_ref_pointer_array= ptr;
 | 
						|
  }
 | 
						|
  inline void init_items_ref_array()
 | 
						|
  {
 | 
						|
    items0= ref_pointer_array + all_fields.elements;
 | 
						|
    memcpy(items0, ref_pointer_array, ref_pointer_array_size);
 | 
						|
    current_ref_pointer_array= items0;
 | 
						|
  }
 | 
						|
 | 
						|
  bool rollup_init();
 | 
						|
  bool rollup_process_const_fields();
 | 
						|
  bool rollup_make_fields(List<Item> &all_fields, List<Item> &fields,
 | 
						|
			  Item_sum ***func);
 | 
						|
  int rollup_send_data(uint idx);
 | 
						|
  int rollup_write_data(uint idx, TABLE *table);
 | 
						|
  void remove_subq_pushed_predicates(Item **where);
 | 
						|
  /**
 | 
						|
    Release memory and, if possible, the open tables held by this execution
 | 
						|
    plan (and nested plans). It's used to release some tables before
 | 
						|
    the end of execution in order to increase concurrency and reduce
 | 
						|
    memory consumption.
 | 
						|
  */
 | 
						|
  void join_free();
 | 
						|
  /** Cleanup this JOIN, possibly for reuse */
 | 
						|
  void cleanup(bool full);
 | 
						|
  void clear();
 | 
						|
  bool save_join_tab();
 | 
						|
  bool init_save_join_tab();
 | 
						|
  bool send_row_on_empty_set()
 | 
						|
  {
 | 
						|
    return (do_send_rows && tmp_table_param.sum_func_count != 0 &&
 | 
						|
	    !group_list && having_value != Item::COND_FALSE);
 | 
						|
  }
 | 
						|
  bool change_result(select_result *result);
 | 
						|
  bool is_top_level_join() const
 | 
						|
  {
 | 
						|
    return (unit == &thd->lex->unit && (unit->fake_select_lex == 0 ||
 | 
						|
                                        select_lex == unit->fake_select_lex));
 | 
						|
  }
 | 
						|
  void cache_const_exprs();
 | 
						|
private:
 | 
						|
  /**
 | 
						|
    TRUE if the query contains an aggregate function but has no GROUP
 | 
						|
    BY clause. 
 | 
						|
  */
 | 
						|
  bool implicit_grouping; 
 | 
						|
  bool make_simple_join(JOIN *join, TABLE *tmp_table);
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
typedef struct st_select_check {
 | 
						|
  uint const_ref,reg_ref;
 | 
						|
} SELECT_CHECK;
 | 
						|
 | 
						|
extern const char *join_type_str[];
 | 
						|
void TEST_join(JOIN *join);
 | 
						|
 | 
						|
/* Extern functions in sql_select.cc */
 | 
						|
bool store_val_in_field(Field *field, Item *val, enum_check_fields check_flag);
 | 
						|
TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
 | 
						|
			ORDER *group, bool distinct, bool save_sum_fields,
 | 
						|
			ulonglong select_options, ha_rows rows_limit,
 | 
						|
			const char* alias);
 | 
						|
void free_tmp_table(THD *thd, TABLE *entry);
 | 
						|
void count_field_types(SELECT_LEX *select_lex, TMP_TABLE_PARAM *param, 
 | 
						|
                       List<Item> &fields, bool reset_with_sum_func);
 | 
						|
bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
 | 
						|
		       Item **ref_pointer_array,
 | 
						|
		       List<Item> &new_list1, List<Item> &new_list2,
 | 
						|
		       uint elements, List<Item> &fields);
 | 
						|
void copy_fields(TMP_TABLE_PARAM *param);
 | 
						|
void copy_funcs(Item **func_ptr);
 | 
						|
bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
 | 
						|
			     int error, bool ignore_last_dupp_error);
 | 
						|
uint find_shortest_key(TABLE *table, const key_map *usable_keys);
 | 
						|
Field* create_tmp_field_from_field(THD *thd, Field* org_field,
 | 
						|
                                   const char *name, TABLE *table,
 | 
						|
                                   Item_field *item, uint convert_blob_length);
 | 
						|
                                                                      
 | 
						|
bool is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args);
 | 
						|
 | 
						|
/* functions from opt_sum.cc */
 | 
						|
bool simple_pred(Item_func *func_item, Item **args, bool *inv_order);
 | 
						|
int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds);
 | 
						|
 | 
						|
/* from sql_delete.cc, used by opt_range.cc */
 | 
						|
extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b);
 | 
						|
 | 
						|
/** class to copying an field/item to a key struct */
 | 
						|
 | 
						|
class store_key :public Sql_alloc
 | 
						|
{
 | 
						|
public:
 | 
						|
  bool null_key; /* TRUE <=> the value of the key has a null part */
 | 
						|
  enum store_key_result { STORE_KEY_OK, STORE_KEY_FATAL, STORE_KEY_CONV };
 | 
						|
  store_key(THD *thd, Field *field_arg, uchar *ptr, uchar *null, uint length)
 | 
						|
    :null_key(0), null_ptr(null), err(0)
 | 
						|
  {
 | 
						|
    if (field_arg->type() == MYSQL_TYPE_BLOB
 | 
						|
        || field_arg->type() == MYSQL_TYPE_GEOMETRY)
 | 
						|
    {
 | 
						|
      /* 
 | 
						|
        Key segments are always packed with a 2 byte length prefix.
 | 
						|
        See mi_rkey for details.
 | 
						|
      */
 | 
						|
      to_field= new Field_varstring(ptr, length, 2, null, 1, 
 | 
						|
                                    Field::NONE, field_arg->field_name,
 | 
						|
                                    field_arg->table->s, field_arg->charset());
 | 
						|
      to_field->init(field_arg->table);
 | 
						|
    }
 | 
						|
    else
 | 
						|
      to_field=field_arg->new_key_field(thd->mem_root, field_arg->table,
 | 
						|
                                        ptr, null, 1);
 | 
						|
  }
 | 
						|
  virtual ~store_key() {}			/** Not actually needed */
 | 
						|
  virtual const char *name() const=0;
 | 
						|
 | 
						|
  /**
 | 
						|
    @brief sets ignore truncation warnings mode and calls the real copy method
 | 
						|
 | 
						|
    @details this function makes sure truncation warnings when preparing the
 | 
						|
    key buffers don't end up as errors (because of an enclosing INSERT/UPDATE).
 | 
						|
  */
 | 
						|
  enum store_key_result copy()
 | 
						|
  {
 | 
						|
    enum store_key_result result;
 | 
						|
    THD *thd= to_field->table->in_use;
 | 
						|
    enum_check_fields saved_count_cuted_fields= thd->count_cuted_fields;
 | 
						|
    ulonglong sql_mode= thd->variables.sql_mode;
 | 
						|
    thd->variables.sql_mode&= ~(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE);
 | 
						|
 | 
						|
    thd->count_cuted_fields= CHECK_FIELD_IGNORE;
 | 
						|
 | 
						|
    result= copy_inner();
 | 
						|
 | 
						|
    thd->count_cuted_fields= saved_count_cuted_fields;
 | 
						|
    thd->variables.sql_mode= sql_mode;
 | 
						|
 | 
						|
    return result;
 | 
						|
  }
 | 
						|
 | 
						|
 protected:
 | 
						|
  Field *to_field;				// Store data here
 | 
						|
  uchar *null_ptr;
 | 
						|
  uchar err;
 | 
						|
 | 
						|
  virtual enum store_key_result copy_inner()=0;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class store_key_field: public store_key
 | 
						|
{
 | 
						|
  Copy_field copy_field;
 | 
						|
  const char *field_name;
 | 
						|
 public:
 | 
						|
  store_key_field(THD *thd, Field *to_field_arg, uchar *ptr,
 | 
						|
                  uchar *null_ptr_arg,
 | 
						|
		  uint length, Field *from_field, const char *name_arg)
 | 
						|
    :store_key(thd, to_field_arg,ptr,
 | 
						|
	       null_ptr_arg ? null_ptr_arg : from_field->maybe_null() ? &err
 | 
						|
	       : (uchar*) 0, length), field_name(name_arg)
 | 
						|
  {
 | 
						|
    if (to_field)
 | 
						|
    {
 | 
						|
      copy_field.set(to_field,from_field,0);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  const char *name() const { return field_name; }
 | 
						|
 | 
						|
 protected: 
 | 
						|
  enum store_key_result copy_inner()
 | 
						|
  {
 | 
						|
    TABLE *table= copy_field.to_field->table;
 | 
						|
    my_bitmap_map *old_map= dbug_tmp_use_all_columns(table,
 | 
						|
                                                     table->write_set);
 | 
						|
    copy_field.do_copy(©_field);
 | 
						|
    dbug_tmp_restore_column_map(table->write_set, old_map);
 | 
						|
    null_key= to_field->is_null();
 | 
						|
    return err != 0 ? STORE_KEY_FATAL : STORE_KEY_OK;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class store_key_item :public store_key
 | 
						|
{
 | 
						|
 protected:
 | 
						|
  Item *item;
 | 
						|
public:
 | 
						|
  store_key_item(THD *thd, Field *to_field_arg, uchar *ptr,
 | 
						|
                 uchar *null_ptr_arg, uint length, Item *item_arg)
 | 
						|
    :store_key(thd, to_field_arg, ptr,
 | 
						|
	       null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ?
 | 
						|
	       &err : (uchar*) 0, length), item(item_arg)
 | 
						|
  {}
 | 
						|
  const char *name() const { return "func"; }
 | 
						|
 | 
						|
 protected:  
 | 
						|
  enum store_key_result copy_inner()
 | 
						|
  {
 | 
						|
    TABLE *table= to_field->table;
 | 
						|
    my_bitmap_map *old_map= dbug_tmp_use_all_columns(table,
 | 
						|
                                                     table->write_set);
 | 
						|
    int res= item->save_in_field(to_field, 1);
 | 
						|
    dbug_tmp_restore_column_map(table->write_set, old_map);
 | 
						|
    null_key= to_field->is_null() || item->null_value;
 | 
						|
    return (err != 0 || res > 2 ? STORE_KEY_FATAL : (store_key_result) res); 
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class store_key_const_item :public store_key_item
 | 
						|
{
 | 
						|
  bool inited;
 | 
						|
public:
 | 
						|
  store_key_const_item(THD *thd, Field *to_field_arg, uchar *ptr,
 | 
						|
		       uchar *null_ptr_arg, uint length,
 | 
						|
		       Item *item_arg)
 | 
						|
    :store_key_item(thd, to_field_arg,ptr,
 | 
						|
		    null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ?
 | 
						|
		    &err : (uchar*) 0, length, item_arg), inited(0)
 | 
						|
  {
 | 
						|
  }
 | 
						|
  const char *name() const { return "const"; }
 | 
						|
 | 
						|
protected:  
 | 
						|
  enum store_key_result copy_inner()
 | 
						|
  {
 | 
						|
    int res;
 | 
						|
    if (!inited)
 | 
						|
    {
 | 
						|
      inited=1;
 | 
						|
      if ((res= item->save_in_field(to_field, 1)))
 | 
						|
      {       
 | 
						|
        if (!err)
 | 
						|
          err= res;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    null_key= to_field->is_null() || item->null_value;
 | 
						|
    return (err > 2 ?  STORE_KEY_FATAL : (store_key_result) err);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
bool cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref);
 | 
						|
bool error_if_full_join(JOIN *join);
 | 
						|
int report_error(TABLE *table, int error);
 | 
						|
int safe_index_read(JOIN_TAB *tab);
 | 
						|
COND *remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value);
 | 
						|
 | 
						|
inline bool optimizer_flag(THD *thd, uint flag)
 | 
						|
{ 
 | 
						|
  return (thd->variables.optimizer_switch & flag);
 | 
						|
}
 | 
						|
 | 
						|
#endif /* SQL_SELECT_INCLUDED */
 |