sql_select.h 22.5 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 17 18
   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 */


/* classes to use when handling where clause */

19
#ifdef USE_PRAGMA_INTERFACE
bk@work.mysql.com's avatar
bk@work.mysql.com committed
20 21 22 23 24 25 26 27 28 29
#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;
30
  uint	key, keypart, optimize;
31 32
  key_part_map keypart_map;
  ha_rows      ref_table_rows;
33 34 35 36 37
  /* 
    If true, the comparison this value was created from will not be
    satisfied if val has NULL 'value'.
  */
  bool null_rejecting;
38 39 40 41 42 43 44 45 46 47 48
  /*
    !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
49 50 51 52 53 54 55 56 57 58 59 60 61 62
} KEYUSE;

class store_key;

typedef struct st_table_ref
{
  bool		key_err;
  uint          key_parts;                // num of ...
  uint          key_length;               // length of key_buff
  int           key;                      // key no
  byte          *key_buff;                // value to look for with key
  byte          *key_buff2;               // key_buff+key_length
  store_key     **key_copy;               //
  Item          **items;                  // val()'s for each keypart
63 64 65 66 67 68 69 70 71 72 73 74
  /*  
    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;
75 76 77 78 79
  /*
    (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;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
80
  table_map	depend_map;		  // Table depends on these tables.
81 82
  /* null byte position in the key_buf. Used for REF_OR_NULL optimization */
  byte          *null_ref_key;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
83 84
} TABLE_REF;

85

bk@work.mysql.com's avatar
bk@work.mysql.com committed
86
/*
87 88
  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
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
*/

typedef struct st_cache_field {
  char *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;


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

class JOIN;

116 117 118 119 120 121 122
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
};

123 124 125 126 127 128 129

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

130 131
typedef enum_nested_loop_state
(*Next_select_func)(JOIN *, struct st_join_table *, bool);
132
typedef int (*Read_record_func)(struct st_join_table *tab);
133
Next_select_func setup_end_select_func(JOIN *join);
134

135

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

160 161
  Read_record_func read_first_record;
  Next_select_func next_select;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
162
  READ_RECORD	read_record;
monty@tramp.mysql.fi's avatar
monty@tramp.mysql.fi committed
163
  double	worst_seeks;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
164 165 166
  key_map	const_keys;			/* Keys with constant part */
  key_map	checked_keys;			/* Keys checked in find_best */
  key_map	needed_reg;
167
  key_map       keys;                           /* all keys with can be used */
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182

  /* 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
183 184 185 186
  table_map	dependent,key_dependent;
  uint		use_quick,index;
  uint		status;				// Save status for cache
  uint		used_fields,used_fieldlength,used_blobs;
monty@tramp.mysql.fi's avatar
monty@tramp.mysql.fi committed
187 188
  enum join_type type;
  bool		cached_eq_ref_table,eq_ref_table,not_used_in_distinct;
189
  bool		sorted;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
190
  TABLE_REF	ref;
monty@tramp.mysql.fi's avatar
monty@tramp.mysql.fi committed
191
  JOIN_CACHE	cache;
192
  JOIN		*join;
193 194
  /* Bitmap of nested joins this table is part of */
  nested_join_map embedding_map;
195

196
  void cleanup();
197 198 199 200 201 202
  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
203 204
} JOIN_TAB;

205 206 207 208 209
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);

210 211 212 213 214
/*
  Information about a position of table within a join order. Used in join
  optimization.
*/
typedef struct st_position
215
{
216 217 218 219 220
  /*
    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
221
  double records_read;
222

223 224 225 226 227
  /* 
    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.
  */
228
  double read_time;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
229
  JOIN_TAB *table;
230 231 232 233 234

  /*
    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
235
  KEYUSE *key;
236 237 238

  /* 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
239 240
} POSITION;

241

242 243 244 245
typedef struct st_rollup
{
  enum State { STATE_NONE, STATE_INITED, STATE_READY };
  State state;
246
  Item_null_result **null_items;
247 248 249 250
  Item ***ref_pointer_arrays;
  List<Item> *fields;
} ROLLUP;

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

252 253
class JOIN :public Sql_alloc
{
konstantin@mysql.com's avatar
konstantin@mysql.com committed
254 255 256
  JOIN(const JOIN &rhs);                        /* not implemented */
  JOIN& operator=(const JOIN &rhs);             /* not implemented */
public:
257 258 259
  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
bk@work.mysql.com's avatar
bk@work.mysql.com committed
260 261 262 263
  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;
264
  bool	   do_send_rows;
265 266 267 268 269
  /*
    TRUE when we want to resume nested loop iterations when
    fetching data from a cursor
  */
  bool     resume_nested_loop;
270
  table_map const_table_map,found_const_table_map,outer_join;
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
271
  ha_rows  send_records,found_records,examined_rows,row_limit, select_limit;
272
  /*
serg@serg.mylan's avatar
serg@serg.mylan committed
273
    Used to fetch no more than given amount of rows per one
274 275 276 277 278 279 280 281
    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
282
  POSITION positions[MAX_TABLES+1],best_positions[MAX_TABLES+1];
283 284 285 286 287 288 289
  
  /* 
    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
290 291
  double   best_read;
  List<Item> *fields;
serg@serg.mylan's avatar
serg@serg.mylan committed
292
  List<Cached_item> group_fields, group_fields_cache;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
293
  TABLE    *tmp_table;
294 295
  // used to store 2 possible tmp table of SELECT
  TABLE    *exec_tmp_table1, *exec_tmp_table2;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
296
  THD	   *thd;
297
  Item_sum  **sum_funcs, ***sum_funcs_end;
298 299
  /* second copy of sumfuncs (for queries with 2 temporary tables */
  Item_sum  **sum_funcs2, ***sum_funcs_end2;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
300 301
  Procedure *procedure;
  Item	    *having;
302 303
  Item      *tmp_having; // To store having when processed temporary table
  Item      *having_history; // Store having for explain
304
  ulonglong  select_options;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
305 306 307
  select_result *result;
  TMP_TABLE_PARAM tmp_table_param;
  MYSQL_LOCK *lock;
308 309
  // unit structure (with global parameters) for this select
  SELECT_LEX_UNIT *unit;
310 311
  // select that processed
  SELECT_LEX *select_lex;
312 313
  
  JOIN *tmp_join; // copy of this JOIN to be used with temporary tables
314
  ROLLUP rollup;				// Used with rollup
315

monty@mysql.com's avatar
monty@mysql.com committed
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
  bool select_distinct;				// Set if SELECT DISTINCT

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

332
  bool need_tmp, hidden_group_fields;
333
  DYNAMIC_ARRAY keyuse;
334
  Item::cond_result cond_value, having_value;
335 336 337 338 339
  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;
340
  List<Item> &fields_list; // hold field list passed to mysql_select
341
  List<Item> procedure_fields_list;
342 343 344 345
  int error;

  ORDER *order, *group_list, *proc_param; //hold parameters of mysql_select
  COND *conds;                            // ---"---
346
  Item *conds_history;                    // store WHERE for explain
347 348
  TABLE_LIST *tables_list;           //hold 'tables' parameter of mysql_select
  List<TABLE_LIST> *join_list;       // list of joined tables in reverse order
349
  COND_EQUAL *cond_equal;
350
  SQL_SELECT *select;                //created in optimisation phase
351
  JOIN_TAB *return_tab;              //used only for outer joins
352 353
  Item **ref_pointer_array; //used pointer reference for this select
  // Copy of above to be used with different lists
354
  Item **items0, **items1, **items2, **items3, **current_ref_pointer_array;
355
  uint ref_pointer_array_size; // size of above in bytes
356
  const char *zero_result_cause; // not 0 if exec must return zero result
357
  
358 359
  bool union_part; // this subselect is part of union 
  bool optimized; // flag to avoid double optimization in EXPLAIN
360

361 362 363 364 365 366 367 368
  /* 
    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.
  */  
  SORT_FIELD *sortorder;                        // make_unireg_sortorder()
369 370
  TABLE **table_reexec;                         // make_simple_join()
  JOIN_TAB *join_tab_reexec;                    // make_simple_join()
371 372
  /* end of allocation caching storage */

373
  JOIN(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
374
       select_result *result_arg)
375
    :fields_list(fields_arg)
376
  {
377
    init(thd_arg, fields_arg, select_options_arg, result_arg);
378
  }
379

380
  void init(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
381 382
       select_result *result_arg)
  {
383
    join_tab= join_tab_save= 0;
384 385 386
    table= 0;
    tables= 0;
    const_tables= 0;
387
    join_list= 0;
388 389 390
    sort_and_group= 0;
    first_record= 0;
    do_send_rows= 1;
391
    resume_nested_loop= FALSE;
392 393
    send_records= 0;
    found_records= 0;
394
    fetch_limit= HA_POS_ERROR;
395 396 397
    examined_rows= 0;
    exec_tmp_table1= 0;
    exec_tmp_table2= 0;
398
    sortorder= 0;
399 400
    table_reexec= 0;
    join_tab_reexec= 0;
401
    thd= thd_arg;
bell@sanja.is.com.ua's avatar
merge  
bell@sanja.is.com.ua committed
402
    sum_funcs= sum_funcs2= 0;
403
    procedure= 0;
404
    having= tmp_having= having_history= 0;
405 406 407 408 409 410 411 412 413 414 415 416 417 418
    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;
419
    return_tab= 0;
420 421 422 423
    ref_pointer_array= items0= items1= items2= items3= 0;
    ref_pointer_array_size= 0;
    zero_result_cause= 0;
    optimized= 0;
424
    cond_equal= 0;
425

426
    all_fields= fields_arg;
427
    fields_list= fields_arg;
428
    bzero((char*) &keyuse,sizeof(keyuse));
429
    tmp_table_param.init();
430
    tmp_table_param.end_write_records= HA_POS_ERROR;
431
    rollup.state= ROLLUP::STATE_NONE;
432
  }
433

434 435 436
  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,
437
	      SELECT_LEX_UNIT *unit);
438
  int optimize();
439
  int reinit();
440
  void exec();
441
  int destroy();
442
  void restore_tmp();
443 444
  bool alloc_func_list();
  bool make_sum_func_list(List<Item> &all_fields, List<Item> &send_fields,
445
			  bool before_group_by, bool recompute= FALSE);
446

447 448 449 450 451
  inline void set_items_ref_array(Item **ptr)
  {
    memcpy((char*) ref_pointer_array, (char*) ptr, ref_pointer_array_size);
    current_ref_pointer_array= ptr;
  }
452 453 454 455
  inline void init_items_ref_array()
  {
    items0= ref_pointer_array + all_fields.elements;
    memcpy(items0, ref_pointer_array, ref_pointer_array_size);
456
    current_ref_pointer_array= items0;
457
  }
458 459 460 461

  bool rollup_init();
  bool rollup_make_fields(List<Item> &all_fields, List<Item> &fields,
			  Item_sum ***func);
462
  int rollup_send_data(uint idx);
463
  int rollup_write_data(uint idx, TABLE *table);
464
  void remove_subq_pushed_predicates(Item **where);
465 466 467 468 469 470
  /*
    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.
  */
471
  void join_free();
472 473
  /* Cleanup this JOIN, possibly for reuse */
  void cleanup(bool full);
474
  void clear();
475
  bool save_join_tab();
476 477 478 479 480
  bool send_row_on_empty_set()
  {
    return (do_send_rows && tmp_table_param.sum_func_count != 0 &&
	    !group_list);
  }
481
  bool change_result(select_result *result);
482 483 484 485 486
  bool is_top_level_join() const
  {
    return (unit == &thd->lex->unit && (unit->fake_select_lex == 0 ||
                                        select_lex == unit->fake_select_lex));
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
487 488 489 490 491 492 493 494 495 496 497
};


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
498
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
499 500
TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
			ORDER *group, bool distinct, bool save_sum_fields,
501
			ulonglong select_options, ha_rows rows_limit,
502
			char* alias);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
503
void free_tmp_table(THD *thd, TABLE *entry);
504 505
void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
		       bool reset_with_sum_func);
506 507 508 509
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
510
void copy_fields(TMP_TABLE_PARAM *param);
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
511
void copy_funcs(Item **func_ptr);
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
512 513
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
514
uint find_shortest_key(TABLE *table, const key_map *usable_keys);
515
Field* create_tmp_field_from_field(THD *thd, Field* org_field,
ramil@mysql.com's avatar
ramil@mysql.com committed
516 517 518
                                   const char *name, TABLE *table,
                                   Item_field *item, uint convert_blob_length);
                                                                      
bk@work.mysql.com's avatar
bk@work.mysql.com committed
519
/* functions from opt_sum.cc */
520
bool simple_pred(Item_func *func_item, Item **args, bool *inv_order);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
521 522
int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds);

523
/* from sql_delete.cc, used by opt_range.cc */
524
extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b);
525

bk@work.mysql.com's avatar
bk@work.mysql.com committed
526 527 528 529
/* class to copying an field/item to a key struct */

class store_key :public Sql_alloc
{
530 531
public:
  bool null_key; /* TRUE <=> the value of the key has a null part */
532
  enum store_key_result { STORE_KEY_OK, STORE_KEY_FATAL, STORE_KEY_CONV };
533
  store_key(THD *thd, Field *field_arg, char *ptr, char *null, uint length)
534
    :null_key(0), null_ptr(null), err(0)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
535
  {
536
    if (field_arg->type() == MYSQL_TYPE_BLOB)
537
    {
538 539 540 541 542
        /* Key segments are always packed with a 2 byte length prefix */
      to_field= new Field_varstring(ptr, length, 2, (uchar*) null, 1, 
                                    Field::NONE, field_arg->field_name,
                                    field_arg->table->s, field_arg->charset());
      to_field->init(field_arg->table);
543
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
544
    else
monty@mysql.com's avatar
monty@mysql.com committed
545 546
      to_field=field_arg->new_key_field(thd->mem_root, field_arg->table,
                                        ptr, (uchar*) null, 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
547 548 549
  }
  virtual ~store_key() {}			/* Not actually needed */
  virtual const char *name() const=0;
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577

  /**
    @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;
    enum_check_fields saved_count_cuted_fields= 
      to_field->table->in_use->count_cuted_fields;

    to_field->table->in_use->count_cuted_fields= CHECK_FIELD_IGNORE;

    result= copy_inner();

    to_field->table->in_use->count_cuted_fields= saved_count_cuted_fields;

    return result;
  }

 protected:
  Field *to_field;				// Store data here
  char *null_ptr;
  char err;

  virtual enum store_key_result copy_inner()=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
578 579 580 581 582 583 584 585
};


class store_key_field: public store_key
{
  Copy_field copy_field;
  const char *field_name;
 public:
586
  store_key_field(THD *thd, Field *to_field_arg, char *ptr, char *null_ptr_arg,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
587
		  uint length, Field *from_field, const char *name_arg)
588
    :store_key(thd, to_field_arg,ptr,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
589 590 591 592 593 594 595 596
	       null_ptr_arg ? null_ptr_arg : from_field->maybe_null() ? &err
	       : NullS,length), field_name(name_arg)
  {
    if (to_field)
    {
      copy_field.set(to_field,from_field,0);
    }
  }
597 598 599 600
  const char *name() const { return field_name; }

 protected: 
  enum store_key_result copy_inner()
601
  {
602 603 604
    TABLE *table= copy_field.to_field->table;
    my_bitmap_map *old_map= dbug_tmp_use_all_columns(table,
                                                     table->write_set);
605
    copy_field.do_copy(&copy_field);
606
    dbug_tmp_restore_column_map(table->write_set, old_map);
607
    null_key= to_field->is_null();
608
    return err != 0 ? STORE_KEY_FATAL : STORE_KEY_OK;
609
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
610 611 612 613 614 615 616 617
};


class store_key_item :public store_key
{
 protected:
  Item *item;
public:
618
  store_key_item(THD *thd, Field *to_field_arg, char *ptr, char *null_ptr_arg,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
619
		 uint length, Item *item_arg)
620
    :store_key(thd, to_field_arg,ptr,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
621 622 623
	       null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ?
	       &err : NullS, length), item(item_arg)
  {}
624 625 626 627
  const char *name() const { return "func"; }

 protected:  
  enum store_key_result copy_inner()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
628
  {
629 630 631
    TABLE *table= to_field->table;
    my_bitmap_map *old_map= dbug_tmp_use_all_columns(table,
                                                     table->write_set);
632
    int res= item->save_in_field(to_field, 1);
633
    dbug_tmp_restore_column_map(table->write_set, old_map);
634
    null_key= to_field->is_null() || item->null_value;
635
    return (err != 0 || res > 2 ? STORE_KEY_FATAL : (store_key_result) res); 
bk@work.mysql.com's avatar
bk@work.mysql.com committed
636 637 638 639 640 641 642 643
  }
};


class store_key_const_item :public store_key_item
{
  bool inited;
public:
644
  store_key_const_item(THD *thd, Field *to_field_arg, char *ptr,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
645 646
		       char *null_ptr_arg, uint length,
		       Item *item_arg)
647
    :store_key_item(thd, to_field_arg,ptr,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
648 649 650 651
		    null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ?
		    &err : NullS, length, item_arg), inited(0)
  {
  }
652 653 654 655
  const char *name() const { return "const"; }

protected:  
  enum store_key_result copy_inner()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
656
  {
657
    int res;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
658 659 660
    if (!inited)
    {
      inited=1;
661 662 663 664 665
      if ((res= item->save_in_field(to_field, 1)))
      {       
        if (!err)
          err= res;
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
666
    }
667
    null_key= to_field->is_null() || item->null_value;
668
    return (err > 2 ?  STORE_KEY_FATAL : (store_key_result) err);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
669 670 671
  }
};

672
bool cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref);
673
bool error_if_full_join(JOIN *join);
674
int report_error(TABLE *table, int error);
675
int safe_index_read(JOIN_TAB *tab);
676
COND *remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value);