sql_select.h 24.6 KB
Newer Older
1
/* Copyright (C) 2000-2006 MySQL AB
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3 4
   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
5
   the Free Software Foundation; version 2 of the License.
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
6

bk@work.mysql.com's avatar
bk@work.mysql.com committed
7 8 9 10
   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.
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
11

bk@work.mysql.com's avatar
bk@work.mysql.com committed
12 13 14 15 16
   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 */


17 18 19 20 21 22
/**
  @file

  @brief
  classes to use when handling where clause
*/
bk@work.mysql.com's avatar
bk@work.mysql.com committed
23

24
#ifdef USE_PRAGMA_INTERFACE
bk@work.mysql.com's avatar
bk@work.mysql.com committed
25 26 27 28 29 30 31 32
#pragma interface			/* gcc class implementation */
#endif

#include "procedure.h"
#include <myisam.h>

typedef struct keyuse_t {
  TABLE *table;
33
  Item	*val;				/**< or value if no field */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
34
  table_map used_tables;
35
  uint	key, keypart, optimize;
36 37
  key_part_map keypart_map;
  ha_rows      ref_table_rows;
38
  /**
39 40 41 42
    If true, the comparison this value was created from will not be
    satisfied if val has NULL 'value'.
  */
  bool null_rejecting;
43 44 45 46 47 48 49 50 51 52 53
  /*
    !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;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
54 55 56 57 58 59 60
} KEYUSE;

class store_key;

typedef struct st_table_ref
{
  bool		key_err;
61 62 63 64 65
  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
bk@work.mysql.com's avatar
bk@work.mysql.com committed
66
  store_key     **key_copy;               //
67
  Item          **items;                  ///< val()'s for each keypart
68 69 70 71 72 73 74 75 76 77 78 79
  /*  
    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;
80
  /**
81 82 83 84
    (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;
85
  table_map	depend_map;		  ///< Table depends on these tables.
86
  /* null byte position in the key_buf. Used for REF_OR_NULL optimization */
87
  uchar          *null_ref_key;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
88 89
} TABLE_REF;

90

91
/**
92 93
  CACHE_FIELD and JOIN_CACHE is used on full join to cache records in outer
  table
bk@work.mysql.com's avatar
bk@work.mysql.com committed
94 95 96
*/

typedef struct st_cache_field {
97 98
  uchar *str;
  uint length, blob_length;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
99 100 101 102 103 104 105 106 107 108 109 110 111 112
  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;


/*
113
  The structs which holds the join connections and join states
bk@work.mysql.com's avatar
bk@work.mysql.com committed
114 115
*/
enum join_type { JT_UNKNOWN,JT_SYSTEM,JT_CONST,JT_EQ_REF,JT_REF,JT_MAYBE_REF,
116
		 JT_ALL, JT_RANGE, JT_NEXT, JT_FT, JT_REF_OR_NULL,
117
		 JT_UNIQUE_SUBQUERY, JT_INDEX_SUBQUERY, JT_INDEX_MERGE};
bk@work.mysql.com's avatar
bk@work.mysql.com committed
118 119 120

class JOIN;

121 122 123 124 125 126 127
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
};

128 129 130 131 132 133 134

/* 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

135 136
typedef enum_nested_loop_state
(*Next_select_func)(JOIN *, struct st_join_table *, bool);
137
typedef int (*Read_record_func)(struct st_join_table *tab);
138
Next_select_func setup_end_select_func(JOIN *join);
139

140

bk@work.mysql.com's avatar
bk@work.mysql.com committed
141
typedef struct st_join_table {
142
  st_join_table() {}                          /* Remove gcc warning */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
143
  TABLE		*table;
144
  KEYUSE	*keyuse;			/**< pointer to first used key */
monty@tramp.mysql.fi's avatar
monty@tramp.mysql.fi committed
145 146
  SQL_SELECT	*select;
  COND		*select_cond;
147
  QUICK_SELECT_I *quick;
148 149 150 151 152 153 154 155
  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     */
156 157
  
  /* Special content for EXPLAIN 'Extra' column or NULL if none */
monty@tramp.mysql.fi's avatar
monty@tramp.mysql.fi committed
158
  const char	*info;
159 160 161 162 163 164
  /* 
    Bitmap of TAB_INFO_* bits that encodes special line for EXPLAIN 'Extra'
    column, or 0 if there is no info.
  */
  uint          packed_info;

165 166
  Read_record_func read_first_record;
  Next_select_func next_select;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
167
  READ_RECORD	read_record;
168 169 170 171 172 173 174
  /* 
    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_func save_read_first_record;/* to save read_first_record */ 
  int (*save_read_record) (READ_RECORD *);/* to save read_record.read_record */
monty@tramp.mysql.fi's avatar
monty@tramp.mysql.fi committed
175
  double	worst_seeks;
176 177
  key_map	const_keys;			/**< Keys with constant part */
  key_map	checked_keys;			/**< Keys checked in find_best */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
178
  key_map	needed_reg;
179
  key_map       keys;                           /**< all keys with can be used */
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194

  /* 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;
  
bk@work.mysql.com's avatar
bk@work.mysql.com committed
195 196
  table_map	dependent,key_dependent;
  uint		use_quick,index;
197
  uint		status;				///< Save status for cache
bk@work.mysql.com's avatar
bk@work.mysql.com committed
198
  uint		used_fields,used_fieldlength,used_blobs;
monty@tramp.mysql.fi's avatar
monty@tramp.mysql.fi committed
199 200
  enum join_type type;
  bool		cached_eq_ref_table,eq_ref_table,not_used_in_distinct;
201
  bool		sorted;
igor@olga.mysql.com's avatar
igor@olga.mysql.com committed
202 203 204 205 206 207
  /* 
    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; 
bk@work.mysql.com's avatar
bk@work.mysql.com committed
208
  TABLE_REF	ref;
monty@tramp.mysql.fi's avatar
monty@tramp.mysql.fi committed
209
  JOIN_CACHE	cache;
210
  JOIN		*join;
211
  /** Bitmap of nested joins this table is part of */
212
  nested_join_map embedding_map;
213

214
  void cleanup();
215 216 217 218 219 220
  inline bool is_using_loose_index_scan()
  {
    return (select && select->quick &&
            (select->quick->get_type() ==
             QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX));
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
221 222
} JOIN_TAB;

223 224 225 226 227
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);

228
/**
229 230 231 232
  Information about a position of table within a join order. Used in join
  optimization.
*/
typedef struct st_position
233
{
234 235 236 237 238
  /*
    The "fanout": number of output rows that will be produced (after
    pushed down selection condition is applied) per each row combination of
    previous tables.
  */
monty@tramp.mysql.fi's avatar
monty@tramp.mysql.fi committed
239
  double records_read;
240

241 242 243 244 245
  /* 
    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.
  */
246
  double read_time;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
247
  JOIN_TAB *table;
248 249 250 251 252

  /*
    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}
  */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
253
  KEYUSE *key;
254 255 256

  /* If ref-based access is used: bitmap of tables this table depends on  */
  table_map ref_depend_map;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
257 258
} POSITION;

259

260 261 262 263
typedef struct st_rollup
{
  enum State { STATE_NONE, STATE_INITED, STATE_READY };
  State state;
264
  Item_null_result **null_items;
265 266 267 268
  Item ***ref_pointer_arrays;
  List<Item> *fields;
} ROLLUP;

bk@work.mysql.com's avatar
bk@work.mysql.com committed
269

270 271
class JOIN :public Sql_alloc
{
272 273
  JOIN(const JOIN &rhs);                        /**< not implemented */
  JOIN& operator=(const JOIN &rhs);             /**< not implemented */
konstantin@mysql.com's avatar
konstantin@mysql.com committed
274
public:
275
  JOIN_TAB *join_tab,**best_ref;
276 277
  JOIN_TAB **map2table;    ///< mapping between table indexes and JOIN_TABs
  JOIN_TAB *join_tab_save; ///< saved join_tab for subquery reexecution
bk@work.mysql.com's avatar
bk@work.mysql.com committed
278 279 280 281
  TABLE    **table,**all_tables,*sort_by_table;
  uint	   tables,const_tables;
  uint	   send_group_parts;
  bool	   sort_and_group,first_record,full_join,group, no_field_update;
282
  bool	   do_send_rows;
283
  /**
284 285 286 287
    TRUE when we want to resume nested loop iterations when
    fetching data from a cursor
  */
  bool     resume_nested_loop;
288 289 290 291 292
  table_map const_table_map,found_const_table_map;
  /*
     Bitmap of all inner tables from outer joins
  */
  table_map outer_join;
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
293
  ha_rows  send_records,found_records,examined_rows,row_limit, select_limit;
294
  /**
serg@serg.mylan's avatar
serg@serg.mylan committed
295
    Used to fetch no more than given amount of rows per one
296 297 298 299 300 301 302 303
    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;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
304
  POSITION positions[MAX_TABLES+1],best_positions[MAX_TABLES+1];
305
  
306
  /* *
307 308 309 310 311
    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;

bk@work.mysql.com's avatar
bk@work.mysql.com committed
312 313
  double   best_read;
  List<Item> *fields;
serg@serg.mylan's avatar
serg@serg.mylan committed
314
  List<Cached_item> group_fields, group_fields_cache;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
315
  TABLE    *tmp_table;
316
  /// used to store 2 possible tmp table of SELECT
317
  TABLE    *exec_tmp_table1, *exec_tmp_table2;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
318
  THD	   *thd;
319
  Item_sum  **sum_funcs, ***sum_funcs_end;
320
  /** second copy of sumfuncs (for queries with 2 temporary tables */
321
  Item_sum  **sum_funcs2, ***sum_funcs_end2;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
322 323
  Procedure *procedure;
  Item	    *having;
324 325
  Item      *tmp_having; ///< To store having when processed temporary table
  Item      *having_history; ///< Store having for explain
326
  ulonglong  select_options;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
327 328 329
  select_result *result;
  TMP_TABLE_PARAM tmp_table_param;
  MYSQL_LOCK *lock;
330
  /// unit structure (with global parameters) for this select
331
  SELECT_LEX_UNIT *unit;
332
  /// select that processed
333
  SELECT_LEX *select_lex;
334
  /** 
335 336 337 338 339 340 341
    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; 
342
  
343 344
  JOIN *tmp_join; ///< copy of this JOIN to be used with temporary tables
  ROLLUP rollup;				///< Used with rollup
345

346 347
  bool select_distinct;				///< Set if SELECT DISTINCT
  /**
348 349 350 351 352 353 354
    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;
monty@mysql.com's avatar
monty@mysql.com committed
355 356 357 358 359 360 361

  /*
    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.
  */
  bool simple_order, simple_group;
362
  /**
monty@mysql.com's avatar
monty@mysql.com committed
363 364 365 366
    Is set only in case if we have a GROUP BY clause
    and no ORDER BY after constant elimination of 'order'.
  */
  bool no_order;
367
  /** Is set if we have a GROUP BY and we have ORDER BY on a constant. */
monty@mysql.com's avatar
monty@mysql.com committed
368 369
  bool          skip_sort_order;

370
  bool need_tmp, hidden_group_fields;
371
  DYNAMIC_ARRAY keyuse;
372
  Item::cond_result cond_value, having_value;
373 374
  List<Item> all_fields; ///< to store all fields that used in query
  ///Above list changed to use temporary table
375
  List<Item> tmp_all_fields1, tmp_all_fields2, tmp_all_fields3;
376
  ///Part, shared with list above, emulate following list
377
  List<Item> tmp_fields_list1, tmp_fields_list2, tmp_fields_list3;
378
  List<Item> &fields_list; ///< hold field list passed to mysql_select
379
  List<Item> procedure_fields_list;
380 381 382 383
  int error;

  ORDER *order, *group_list, *proc_param; //hold parameters of mysql_select
  COND *conds;                            // ---"---
384
  Item *conds_history;                    // store WHERE for explain
385 386
  TABLE_LIST *tables_list;           ///<hold 'tables' parameter of mysql_select
  List<TABLE_LIST> *join_list;       ///< list of joined tables in reverse order
387
  COND_EQUAL *cond_equal;
388 389 390
  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
391
  // Copy of above to be used with different lists
392
  Item **items0, **items1, **items2, **items3, **current_ref_pointer_array;
393 394
  uint ref_pointer_array_size; ///< size of above in bytes
  const char *zero_result_cause; ///< not 0 if exec must return zero result
395
  
396 397
  bool union_part; ///< this subselect is part of union 
  bool optimized; ///< flag to avoid double optimization in EXPLAIN
398

399 400 401 402 403 404
  /* 
    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.
405 406 407
    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.
408 409
  */  
  SORT_FIELD *sortorder;                        // make_unireg_sortorder()
410
  TABLE *table_reexec[1];                       // make_simple_join()
411
  JOIN_TAB *join_tab_reexec;                    // make_simple_join()
412 413
  /* end of allocation caching storage */

414
  JOIN(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
415
       select_result *result_arg)
416
    :fields_list(fields_arg)
417
  {
418
    init(thd_arg, fields_arg, select_options_arg, result_arg);
419
  }
420

421
  void init(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
422 423
       select_result *result_arg)
  {
424
    join_tab= join_tab_save= 0;
425 426 427
    table= 0;
    tables= 0;
    const_tables= 0;
428
    join_list= 0;
429 430 431
    sort_and_group= 0;
    first_record= 0;
    do_send_rows= 1;
432
    resume_nested_loop= FALSE;
433 434
    send_records= 0;
    found_records= 0;
435
    fetch_limit= HA_POS_ERROR;
436 437 438
    examined_rows= 0;
    exec_tmp_table1= 0;
    exec_tmp_table2= 0;
439
    sortorder= 0;
440
    table_reexec[0]= 0;
441
    join_tab_reexec= 0;
442
    thd= thd_arg;
bell@sanja.is.com.ua's avatar
merge  
bell@sanja.is.com.ua committed
443
    sum_funcs= sum_funcs2= 0;
444
    procedure= 0;
445
    having= tmp_having= having_history= 0;
446 447 448 449 450 451 452 453 454 455 456 457 458 459
    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;
460
    return_tab= 0;
461 462 463 464
    ref_pointer_array= items0= items1= items2= items3= 0;
    ref_pointer_array_size= 0;
    zero_result_cause= 0;
    optimized= 0;
465
    cond_equal= 0;
466
    group_optimized_away= 0;
467

468
    all_fields= fields_arg;
469
    fields_list= fields_arg;
470
    bzero((char*) &keyuse,sizeof(keyuse));
471
    tmp_table_param.init();
472
    tmp_table_param.end_write_records= HA_POS_ERROR;
473
    rollup.state= ROLLUP::STATE_NONE;
474 475

    no_const_tables= FALSE;
476
  }
477

478 479 480
  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,
481
	      SELECT_LEX_UNIT *unit);
482
  int optimize();
483
  int reinit();
484
  void exec();
485
  int destroy();
486
  void restore_tmp();
487 488
  bool alloc_func_list();
  bool make_sum_func_list(List<Item> &all_fields, List<Item> &send_fields,
489
			  bool before_group_by, bool recompute= FALSE);
490

491 492 493 494 495
  inline void set_items_ref_array(Item **ptr)
  {
    memcpy((char*) ref_pointer_array, (char*) ptr, ref_pointer_array_size);
    current_ref_pointer_array= ptr;
  }
496 497 498 499
  inline void init_items_ref_array()
  {
    items0= ref_pointer_array + all_fields.elements;
    memcpy(items0, ref_pointer_array, ref_pointer_array_size);
500
    current_ref_pointer_array= items0;
501
  }
502 503 504 505

  bool rollup_init();
  bool rollup_make_fields(List<Item> &all_fields, List<Item> &fields,
			  Item_sum ***func);
506
  int rollup_send_data(uint idx);
507
  int rollup_write_data(uint idx, TABLE *table);
508
  void remove_subq_pushed_predicates(Item **where);
509
  /**
510 511 512 513 514
    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.
  */
515
  void join_free();
516
  /** Cleanup this JOIN, possibly for reuse */
517
  void cleanup(bool full);
518
  void clear();
519
  bool save_join_tab();
gkodinov/kgeorge@magare.gmz's avatar
gkodinov/kgeorge@magare.gmz committed
520
  bool init_save_join_tab();
521 522 523
  bool send_row_on_empty_set()
  {
    return (do_send_rows && tmp_table_param.sum_func_count != 0 &&
524
	    !group_list && having_value != Item::COND_FALSE);
525
  }
526
  bool change_result(select_result *result);
527 528 529 530 531
  bool is_top_level_join() const
  {
    return (unit == &thd->lex->unit && (unit->fake_select_lex == 0 ||
                                        select_lex == unit->fake_select_lex));
  }
532 533
private:
  bool make_simple_join(JOIN *join, TABLE *tmp_table);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
534 535 536 537 538 539 540 541 542 543 544
};


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 */
igor@rurik.mysql.com's avatar
igor@rurik.mysql.com committed
545
bool store_val_in_field(Field *field, Item *val, enum_check_fields check_flag);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
546 547
TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
			ORDER *group, bool distinct, bool save_sum_fields,
548
			ulonglong select_options, ha_rows rows_limit,
549
			char* alias);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
550
void free_tmp_table(THD *thd, TABLE *entry);
551 552
void count_field_types(SELECT_LEX *select_lex, TMP_TABLE_PARAM *param, 
                       List<Item> &fields, bool reset_with_sum_func);
553 554 555 556
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);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
557
void copy_fields(TMP_TABLE_PARAM *param);
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
558
void copy_funcs(Item **func_ptr);
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
559 560
bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
			     int error, bool ignore_last_dupp_error);
sergefp@mysql.com's avatar
sergefp@mysql.com committed
561
uint find_shortest_key(TABLE *table, const key_map *usable_keys);
562
Field* create_tmp_field_from_field(THD *thd, Field* org_field,
ramil@mysql.com's avatar
ramil@mysql.com committed
563 564 565
                                   const char *name, TABLE *table,
                                   Item_field *item, uint convert_blob_length);
                                                                      
bk@work.mysql.com's avatar
bk@work.mysql.com committed
566
/* functions from opt_sum.cc */
567
bool simple_pred(Item_func *func_item, Item **args, bool *inv_order);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
568 569
int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds);

570
/* from sql_delete.cc, used by opt_range.cc */
571
extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b);
572

573
/** class to copying an field/item to a key struct */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
574 575 576

class store_key :public Sql_alloc
{
577 578
public:
  bool null_key; /* TRUE <=> the value of the key has a null part */
579
  enum store_key_result { STORE_KEY_OK, STORE_KEY_FATAL, STORE_KEY_CONV };
580
  store_key(THD *thd, Field *field_arg, uchar *ptr, uchar *null, uint length)
581
    :null_key(0), null_ptr(null), err(0)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
582
  {
583 584
    if (field_arg->type() == MYSQL_TYPE_BLOB
        || field_arg->type() == MYSQL_TYPE_GEOMETRY)
585
    {
586 587 588 589
      /* 
        Key segments are always packed with a 2 byte length prefix.
        See mi_rkey for details.
      */
590
      to_field= new Field_varstring(ptr, length, 2, null, 1, 
591 592 593
                                    Field::NONE, field_arg->field_name,
                                    field_arg->table->s, field_arg->charset());
      to_field->init(field_arg->table);
594
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
595
    else
monty@mysql.com's avatar
monty@mysql.com committed
596
      to_field=field_arg->new_key_field(thd->mem_root, field_arg->table,
597
                                        ptr, null, 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
598
  }
599
  virtual ~store_key() {}			/** Not actually needed */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
600
  virtual const char *name() const=0;
601 602 603 604 605 606 607 608 609 610

  /**
    @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;
611 612 613 614
    THD *thd= to_field->table->in_use;
    enum_check_fields saved_count_cuted_fields= thd->count_cuted_fields;
    ulong sql_mode= thd->variables.sql_mode;
    thd->variables.sql_mode&= ~(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE);
615

616
    thd->count_cuted_fields= CHECK_FIELD_IGNORE;
617 618 619

    result= copy_inner();

620 621
    thd->count_cuted_fields= saved_count_cuted_fields;
    thd->variables.sql_mode= sql_mode;
622 623 624 625 626 627

    return result;
  }

 protected:
  Field *to_field;				// Store data here
628 629
  uchar *null_ptr;
  uchar err;
630 631

  virtual enum store_key_result copy_inner()=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
632 633 634 635 636 637 638 639
};


class store_key_field: public store_key
{
  Copy_field copy_field;
  const char *field_name;
 public:
640 641
  store_key_field(THD *thd, Field *to_field_arg, uchar *ptr,
                  uchar *null_ptr_arg,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
642
		  uint length, Field *from_field, const char *name_arg)
643
    :store_key(thd, to_field_arg,ptr,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
644
	       null_ptr_arg ? null_ptr_arg : from_field->maybe_null() ? &err
645
	       : (uchar*) 0, length), field_name(name_arg)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
646 647 648 649 650 651
  {
    if (to_field)
    {
      copy_field.set(to_field,from_field,0);
    }
  }
652 653 654 655
  const char *name() const { return field_name; }

 protected: 
  enum store_key_result copy_inner()
656
  {
657 658 659
    TABLE *table= copy_field.to_field->table;
    my_bitmap_map *old_map= dbug_tmp_use_all_columns(table,
                                                     table->write_set);
660
    copy_field.do_copy(&copy_field);
661
    dbug_tmp_restore_column_map(table->write_set, old_map);
662
    null_key= to_field->is_null();
663
    return err != 0 ? STORE_KEY_FATAL : STORE_KEY_OK;
664
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
665 666 667 668 669 670 671 672
};


class store_key_item :public store_key
{
 protected:
  Item *item;
public:
673 674 675
  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,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
676
	       null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ?
677
	       &err : (uchar*) 0, length), item(item_arg)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
678
  {}
679 680 681 682
  const char *name() const { return "func"; }

 protected:  
  enum store_key_result copy_inner()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
683
  {
684 685 686
    TABLE *table= to_field->table;
    my_bitmap_map *old_map= dbug_tmp_use_all_columns(table,
                                                     table->write_set);
687
    int res= item->save_in_field(to_field, 1);
688
    dbug_tmp_restore_column_map(table->write_set, old_map);
689
    null_key= to_field->is_null() || item->null_value;
690
    return (err != 0 || res > 2 ? STORE_KEY_FATAL : (store_key_result) res); 
bk@work.mysql.com's avatar
bk@work.mysql.com committed
691 692 693 694 695 696 697 698
  }
};


class store_key_const_item :public store_key_item
{
  bool inited;
public:
699 700
  store_key_const_item(THD *thd, Field *to_field_arg, uchar *ptr,
		       uchar *null_ptr_arg, uint length,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
701
		       Item *item_arg)
702
    :store_key_item(thd, to_field_arg,ptr,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
703
		    null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ?
704
		    &err : (uchar*) 0, length, item_arg), inited(0)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
705 706
  {
  }
707 708 709 710
  const char *name() const { return "const"; }

protected:  
  enum store_key_result copy_inner()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
711
  {
712
    int res;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
713 714 715
    if (!inited)
    {
      inited=1;
716 717 718 719 720
      if ((res= item->save_in_field(to_field, 1)))
      {       
        if (!err)
          err= res;
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
721
    }
722
    null_key= to_field->is_null() || item->null_value;
723
    return (err > 2 ?  STORE_KEY_FATAL : (store_key_result) err);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
724 725 726
  }
};

727
bool cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref);
728
bool error_if_full_join(JOIN *join);
729
int report_error(TABLE *table, int error);
730
int safe_index_read(JOIN_TAB *tab);
731
COND *remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value);
732 733 734 735 736 737

inline bool optimizer_flag(THD *thd, uint flag)
{ 
  return (thd->variables.optimizer_switch & flag);
}