opt_range.h 8.65 KB
Newer Older
unknown's avatar
unknown committed
1
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
unknown's avatar
unknown committed
2

unknown's avatar
unknown committed
3 4 5 6
   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; either version 2 of the License, or
   (at your option) any later version.
unknown's avatar
unknown committed
7

unknown's avatar
unknown committed
8 9 10 11
   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.
unknown's avatar
unknown committed
12

unknown's avatar
unknown committed
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
   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 */

#ifndef _opt_range_h
#define _opt_range_h

#ifdef __GNUC__
#pragma interface			/* gcc class implementation */
#endif

#define NO_MIN_RANGE	1
#define NO_MAX_RANGE	2
#define NEAR_MIN	4
#define NEAR_MAX	8
#define UNIQUE_RANGE	16
#define EQ_RANGE	32
33
#define NULL_RANGE	64
unknown's avatar
unknown committed
34 35
#define GEOM_FLAG      128

unknown's avatar
unknown committed
36 37

typedef struct st_key_part {
unknown's avatar
unknown committed
38 39 40 41
  uint16           key,part,part_length;
  uint8            null_bit;
  Field            *field;
  Field::imagetype image_type;
unknown's avatar
unknown committed
42 43
} KEY_PART;

44

unknown's avatar
unknown committed
45 46 47 48
class QUICK_RANGE :public Sql_alloc {
 public:
  char *min_key,*max_key;
  uint16 min_length,max_length,flag;
49 50 51
#ifdef HAVE_purify
  uint16 dummy;					/* Avoid warnings on 'flag' */
#endif
unknown's avatar
unknown committed
52 53 54 55 56 57
  QUICK_RANGE();				/* Full range */
  QUICK_RANGE(const char *min_key_arg,uint min_length_arg,
	      const char *max_key_arg,uint max_length_arg,
	      uint flag_arg)
    : min_key((char*) sql_memdup(min_key_arg,min_length_arg+1)),
      max_key((char*) sql_memdup(max_key_arg,max_length_arg+1)),
unknown's avatar
unknown committed
58 59 60
      min_length((uint16) min_length_arg),
      max_length((uint16) max_length_arg),
      flag((uint16) flag_arg)
61 62 63 64 65
    {
#ifdef HAVE_purify
      dummy=0;
#endif
    }
unknown's avatar
unknown committed
66 67
};

unknown's avatar
unknown committed
68
class INDEX_MERGE; 
unknown's avatar
unknown committed
69

unknown's avatar
unknown committed
70 71 72 73 74 75 76
/*
  Quick select interface. 
  This class is parent for all QUICK_*_SELECT and FT_SELECT classes.
*/

class QUICK_SELECT_I
{
unknown's avatar
unknown committed
77
public:
unknown's avatar
unknown committed
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
  ha_rows records;  /* estimate of # of records to be retrieved */
  double  read_time; /* time to perform this retrieval          */
  TABLE   *head;

  /*
    the only index this quick select uses, or MAX_KEY for 
    QUICK_INDEX_MERGE_SELECT
  */
  uint index; 
  uint max_used_key_length, used_key_parts;

  QUICK_SELECT_I();
  virtual ~QUICK_SELECT_I(){};
  virtual int  init() = 0;
  virtual void reset(void) = 0;
  virtual int  get_next() = 0;   /* get next record to retrieve */
  virtual bool reverse_sorted() = 0;
  virtual bool unique_key_range() { return false; }

  enum { 
    QS_TYPE_RANGE = 0,
    QS_TYPE_INDEX_MERGE = 1,
    QS_TYPE_RANGE_DESC = 2,
    QS_TYPE_FULLTEXT   = 3
  };

  /* Get type of this quick select - one of the QS_* values */
  virtual int get_type() = 0; 
};

struct st_qsel_param;
class SEL_ARG;

class QUICK_RANGE_SELECT : public QUICK_SELECT_I 
{
protected:
unknown's avatar
unknown committed
114
  bool next,dont_free;
unknown's avatar
unknown committed
115
public:
unknown's avatar
unknown committed
116 117 118
  int error;
  handler *file;
  byte    *record;
unknown's avatar
unknown committed
119 120
protected:
  friend void print_quick_sel_range(QUICK_RANGE_SELECT *quick,
unknown's avatar
unknown committed
121
                                    const key_map* needed_reg);
unknown's avatar
unknown committed
122
  friend QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, 
unknown's avatar
unknown committed
123 124 125 126 127 128 129 130 131 132
                                                      struct st_table_ref *ref);
  friend bool get_quick_keys(struct st_qsel_param *param,
                             QUICK_RANGE_SELECT *quick,KEY_PART *key,
                             SEL_ARG *key_tree,char *min_key,uint min_key_flag,
                             char *max_key, uint max_key_flag);
  friend QUICK_RANGE_SELECT *get_quick_select(struct st_qsel_param*,uint idx,
                                              SEL_ARG *key_tree,
                                              MEM_ROOT *alloc);
  friend class QUICK_SELECT_DESC;

unknown's avatar
unknown committed
133 134 135 136
  List<QUICK_RANGE> ranges;
  List_iterator<QUICK_RANGE> it;
  QUICK_RANGE *range;
  MEM_ROOT alloc;
unknown's avatar
unknown committed
137
  KEY_PART *key_parts;  
unknown's avatar
unknown committed
138
  int cmp_next(QUICK_RANGE *range);
unknown's avatar
unknown committed
139
public:
unknown's avatar
unknown committed
140
  QUICK_RANGE_SELECT(THD *thd, TABLE *table,uint index_arg,bool no_alloc=0,
unknown's avatar
unknown committed
141 142 143 144 145 146 147
                     MEM_ROOT *parent_alloc=NULL);
  ~QUICK_RANGE_SELECT();
  
  void reset(void) { next=0; it.rewind(); }
  int init();
  int get_next();
  bool reverse_sorted() { return 0; }
unknown's avatar
unknown committed
148
  bool unique_key_range();
unknown's avatar
unknown committed
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
  int get_type() { return QS_TYPE_RANGE; }
};

/*
  Helper class for keeping track of rows that have been passed to output 
  in index_merge access method. 

  NOTES
    Current implementation uses a temporary table to store ROWIDs of rows that
    have been passed to output. In the future it might be changed to use more 
    efficient mechanisms, like Unique class.
*/

class INDEX_MERGE
{
public:
  INDEX_MERGE(THD *thd_arg);
  ~INDEX_MERGE(); 
  
  int init(TABLE *table);
  int check_record_in();
  int start_last_quick_select();
  int error;
private:
  /* The only field in temporary table */
  class Item_rowid : public Item_str_func
  {
    TABLE *head; /* source table */
  public:
    Item_rowid(TABLE *table) : head(table) 
    {
      max_length= table->file->ref_length;
      collation.set(&my_charset_bin);
    };
    const char *func_name() const { return "rowid"; }
    bool const_item() const { return 0; }
    String *val_str(String *);
    void fix_length_and_dec()
    {}
  };

  /* Check if record has been processed and save it if it wasn't  */
  inline int put_record(); 
  
  /* Check if record has been processed without saving it         */
  inline int check_record();
  
  /* If true, check_record_in does't store ROWIDs it is passed.   */
  bool  dont_save;

  THD *thd;
  TABLE *head;                     /* source table                        */
  TABLE *temp_table;               /* temp. table used for values storage */
  TMP_TABLE_PARAM tmp_table_param; /* temp. table creation parameters     */
  Item_rowid *rowid_item;          /* the only field in temp. table       */
  List<Item> fields;               /* temp. table fields list 
                                      (the only element is rowid_item)    */
  ORDER order;                     /* key for temp. table (rowid_item)    */
unknown's avatar
unknown committed
207 208
};

unknown's avatar
unknown committed
209

unknown's avatar
unknown committed
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
/*
  Index merge quick select. 
  It is implemented as a container for several QUICK_RANGE_SELECTs.
*/

class QUICK_INDEX_MERGE_SELECT : public QUICK_SELECT_I 
{
public:
  QUICK_INDEX_MERGE_SELECT(THD *thd, TABLE *table);
  ~QUICK_INDEX_MERGE_SELECT();

  int  init();
  void reset(void);
  int  get_next();
  bool reverse_sorted() { return false; }
  bool unique_key_range() { return false; }
  int get_type() { return QS_TYPE_INDEX_MERGE; }

  bool push_quick_back(QUICK_RANGE_SELECT *quick_sel_range);

  /* range quick selects this index_merge read consists of */
  List<QUICK_RANGE_SELECT> quick_selects;
  
  /* quick select which is currently used for rows retrieval */
  List_iterator_fast<QUICK_RANGE_SELECT> cur_quick_it;
  QUICK_RANGE_SELECT* cur_quick_select;
  
  /*
    Last element in quick_selects list. 
    INDEX_MERGE::start_last_quick_select is called before retrieving
    rows for it. 
  */
  QUICK_RANGE_SELECT* last_quick_select;
  
  /*
    Used to keep track of what records have been already passed to output 
    when doing index_merge access (NULL means no index_merge) 
  */
  INDEX_MERGE index_merge;

  MEM_ROOT    alloc;
};

class QUICK_SELECT_DESC: public QUICK_RANGE_SELECT
254 255
{
public:
unknown's avatar
unknown committed
256
  QUICK_SELECT_DESC(QUICK_RANGE_SELECT *q, uint used_key_parts);
257
  int get_next();
258
  bool reverse_sorted() { return 1; }
unknown's avatar
unknown committed
259
  int get_type() { return QS_TYPE_RANGE_DESC; }
260 261 262
private:
  int cmp_prev(QUICK_RANGE *range);
  bool range_reads_after_key(QUICK_RANGE *range);
unknown's avatar
unknown committed
263
#ifdef NOT_USED
unknown's avatar
unknown committed
264
  bool test_if_null_range(QUICK_RANGE *range, uint used_key_parts);
unknown's avatar
unknown committed
265
#endif
unknown's avatar
unknown committed
266
  void reset(void) { next=0; rev_it.rewind(); }
267 268 269 270
  List<QUICK_RANGE> rev_ranges;
  List_iterator<QUICK_RANGE> rev_it;
};

271

unknown's avatar
unknown committed
272 273
class SQL_SELECT :public Sql_alloc {
 public:
unknown's avatar
unknown committed
274
  QUICK_SELECT_I *quick;	// If quick-select used
unknown's avatar
unknown committed
275 276 277 278 279 280 281 282 283 284 285 286
  COND		*cond;		// where condition
  TABLE	*head;
  IO_CACHE file;		// Positions to used records
  ha_rows records;		// Records in use if read from file
  double read_time;		// Time to read rows
  key_map quick_keys;		// Possible quick keys
  key_map needed_reg;		// Possible quick keys after prev tables.
  table_map const_tables,read_tables;
  bool	free_cond;

  SQL_SELECT();
  ~SQL_SELECT();
unknown's avatar
unknown committed
287
  bool check_quick(THD *thd, bool force_quick_range, ha_rows limit)
unknown's avatar
unknown committed
288
  { return test_quick_select(thd, key_map(~0), 0, limit, force_quick_range) < 0; }
unknown's avatar
unknown committed
289
  inline bool skipp_record() { return cond ? cond->val_int() == 0 : 0; }
290 291
  int test_quick_select(THD *thd, key_map keys, table_map prev_tables,
			ha_rows limit, bool force_quick_range=0);
unknown's avatar
unknown committed
292 293
};

294
QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
295
				       struct st_table_ref *ref);
unknown's avatar
unknown committed
296 297

#endif