item_subselect.h 11.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/* Copyright (C) 2000 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; either version 2 of the License, or
   (at your option) any later version.

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

/* subselect Item */

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

unknown's avatar
unknown committed
23 24
class st_select_lex;
class st_select_lex_unit;
25 26
class JOIN;
class select_subselect;
unknown's avatar
unknown committed
27
class subselect_engine;
unknown's avatar
unknown committed
28
class Item_bool_func2;
unknown's avatar
unknown committed
29
class Statement;
unknown's avatar
unknown committed
30

unknown's avatar
unknown committed
31
/* base class for subselects */
32

unknown's avatar
unknown committed
33
class Item_subselect :public Item_result_field
34
{
unknown's avatar
unknown committed
35
  my_bool value_assigned; /* value already assigned to subselect */
36
protected:
37 38
  /* thread handler, will be assigned in fix_fields only */
  THD *thd;
unknown's avatar
unknown committed
39 40
  /* substitution instead of subselect in case of optimization */
  Item *substitution;
unknown's avatar
unknown committed
41 42
  /* unit of subquery */
  st_select_lex_unit *unit;
unknown's avatar
unknown committed
43
  /* engine that perform execution of subselect (single select or union) */
44
  subselect_engine *engine;
unknown's avatar
unknown committed
45 46
  /* old engine if engine was changed */
  subselect_engine *old_engine;
47
  /* cache of used external tables */
48
  table_map used_tables_cache;
unknown's avatar
unknown committed
49
  /* allowed number of columns (1 for single value subqueries) */
unknown's avatar
unknown committed
50
  uint max_columns;
51 52
  /* where subquery is placed */
  enum_parsing_place parsing_place;
53 54
  /* work with 'substitution' */
  bool have_to_be_excluded;
unknown's avatar
unknown committed
55
  /* cache of constant state */
56
  bool const_item_cache;
57 58

public:
59 60
  /* changed engine indicator */
  bool engine_changed;
unknown's avatar
unknown committed
61 62
  /* subquery is transformed */
  bool changed;
63

64
  enum trans_res {RES_OK, RES_REDUCE, RES_ERROR};
65
  enum subs_type {UNKNOWN_SUBS, SINGLEROW_SUBS,
66
		  EXISTS_SUBS, IN_SUBS, ALL_SUBS, ANY_SUBS};
67

68 69
  Item_subselect();

70 71
  virtual subs_type substype() { return UNKNOWN_SUBS; }

72
  /*
73 74 75 76
     We need this method, because some compilers do not allow 'this'
     pointer in constructor initialization list, but we need pass pointer
     to subselect Item class to select_subselect classes constructor.
  */
77
  virtual void init (st_select_lex *select_lex,
unknown's avatar
unknown committed
78
		     select_subselect *result);
79

unknown's avatar
unknown committed
80
  ~Item_subselect();
unknown's avatar
unknown committed
81
  void cleanup();
82
  virtual void reset()
unknown's avatar
unknown committed
83 84 85
  {
    null_value= 1;
  }
unknown's avatar
unknown committed
86
  virtual trans_res select_transformer(JOIN *join);
unknown's avatar
unknown committed
87 88
  bool assigned() { return value_assigned; }
  void assigned(bool a) { value_assigned= a; }
89
  enum Type type() const;
unknown's avatar
unknown committed
90 91 92 93 94
  bool is_null()
  {
    val_int();
    return null_value;
  }
unknown's avatar
unknown committed
95
  bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
96
  virtual bool exec();
97
  virtual void fix_length_and_dec();
unknown's avatar
unknown committed
98
  table_map used_tables() const;
99
  bool const_item() const;
100 101
  inline table_map get_used_tables_cache() { return used_tables_cache; }
  inline bool get_const_item_cache() { return const_item_cache; }
unknown's avatar
unknown committed
102
  Item *get_tmp_table_item(THD *thd);
103
  void update_used_tables();
unknown's avatar
unknown committed
104
  void print(String *str);
105 106
  bool change_engine(subselect_engine *eng)
  {
unknown's avatar
unknown committed
107
    old_engine= engine;
108 109 110 111
    engine= eng;
    engine_changed= 1;
    return eng == 0;
  }
112 113 114 115 116
  /*
    Used by max/min subquery to initialize value presence registration
    mechanism. Engine call this method before rexecution query.
  */
  virtual void reset_value_registration() {}
117 118

  friend class select_subselect;
unknown's avatar
unknown committed
119
  friend class Item_in_optimizer;
120 121
  friend bool Item_field::fix_fields(THD *, TABLE_LIST *, Item **);
  friend bool Item_ref::fix_fields(THD *, TABLE_LIST *, Item **);
122 123
};

unknown's avatar
unknown committed
124 125
/* single value subselect */

126
class Item_cache;
unknown's avatar
unknown committed
127
class Item_singlerow_subselect :public Item_subselect
unknown's avatar
unknown committed
128 129
{
protected:
130
  Item_cache *value, **row;
unknown's avatar
unknown committed
131
public:
132
  Item_singlerow_subselect(st_select_lex *select_lex);
133
  Item_singlerow_subselect() :Item_subselect(), value(0), row (0) {}
134

unknown's avatar
unknown committed
135
  void cleanup();
136 137
  subs_type substype() { return SINGLEROW_SUBS; }

138
  void reset();
unknown's avatar
unknown committed
139
  trans_res select_transformer(JOIN *join);
140
  void store(uint i, Item* item);
141
  double val();
unknown's avatar
unknown committed
142 143
  longlong val_int ();
  String *val_str (String *);
144
  enum Item_result result_type() const;
145
  void fix_length_and_dec();
unknown's avatar
unknown committed
146

147
  uint cols();
148
  Item* el(uint i) { return my_reinterpret_cast(Item*)(row[i]); }
149 150 151 152 153
  Item** addr(uint i) { return (Item**)row + i; }
  bool check_cols(uint c);
  bool null_inside();
  void bring_value();

unknown's avatar
unknown committed
154
  friend class select_singlerow_subselect;
unknown's avatar
unknown committed
155 156
};

157
/* used in static ALL/ANY optimisation */
158
class select_max_min_finder_subselect;
159
class Item_maxmin_subselect :public Item_singlerow_subselect
160
{
161
protected:
unknown's avatar
unknown committed
162
  bool max;
unknown's avatar
unknown committed
163
  bool was_values;  // Set if we have found at least one row
164
public:
165 166
  Item_maxmin_subselect(Item_subselect *parent,
			st_select_lex *select_lex, bool max);
unknown's avatar
unknown committed
167
  void print(String *str);
168 169 170 171
  void cleanup();
  bool any_value() { return was_values; }
  void register_value() { was_values= TRUE; }
  void reset_value_registration() { was_values= FALSE; }
172 173
};

unknown's avatar
unknown committed
174 175 176 177 178
/* exists subselect */

class Item_exists_subselect :public Item_subselect
{
protected:
unknown's avatar
unknown committed
179
  longlong value; /* value of this item (boolean: exists/not-exists) */
unknown's avatar
unknown committed
180 181

public:
182
  Item_exists_subselect(st_select_lex *select_lex);
unknown's avatar
unknown committed
183 184
  Item_exists_subselect(): Item_subselect() {}

185
  subs_type substype() { return EXISTS_SUBS; }
186
  void reset() 
unknown's avatar
unknown committed
187 188 189 190
  {
    value= 0;
  }

unknown's avatar
unknown committed
191 192 193 194
  enum Item_result result_type() const { return INT_RESULT;}
  longlong val_int();
  double val();
  String *val_str(String*);
195
  void fix_length_and_dec();
unknown's avatar
unknown committed
196
  void print(String *str);
197

unknown's avatar
unknown committed
198
  friend class select_exists_subselect;
199 200
  friend class subselect_uniquesubquery_engine;
  friend class subselect_indexsubquery_engine;
unknown's avatar
unknown committed
201
};
unknown's avatar
unknown committed
202

unknown's avatar
unknown committed
203 204 205 206
/* IN subselect */

class Item_in_subselect :public Item_exists_subselect
{
unknown's avatar
unknown committed
207
protected:
208
  Item *left_expr;
209
  /*
unknown's avatar
unknown committed
210
    expr & optimizer used in subselect rewriting to store Item for
211 212 213 214
    all JOIN in UNION
  */
  Item *expr;
  Item_in_optimizer *optimizer;
215
  bool was_null;
216
  bool abort_on_null;
unknown's avatar
unknown committed
217
  bool transformed;
unknown's avatar
unknown committed
218
public:
219
  Item_func_not_all *upper_item; // point on NOT/NOP before ALL/SOME subquery
220

221
  Item_in_subselect(Item * left_expr, st_select_lex *select_lex);
222
  Item_in_subselect()
223 224
    :Item_exists_subselect(), optimizer(0), abort_on_null(0), transformed(0),
     upper_item(0)
unknown's avatar
unknown committed
225
  {}
226 227

  subs_type substype() { return IN_SUBS; }
228 229 230 231 232 233
  void reset() 
  {
    value= 0;
    null_value= 0;
    was_null= 0;
  }
unknown's avatar
unknown committed
234
  trans_res select_transformer(JOIN *join);
235 236
  trans_res select_in_like_transformer(JOIN *join, Comp_creator *func);
  trans_res single_value_transformer(JOIN *join, Comp_creator *func);
unknown's avatar
unknown committed
237
  trans_res row_value_transformer(JOIN * join);
238 239 240
  longlong val_int();
  double val();
  String *val_str(String*);
241 242
  void top_level_item() { abort_on_null=1; }
  bool test_limit(st_select_lex_unit *unit);
unknown's avatar
unknown committed
243
  void print(String *str);
244 245

  friend class Item_ref_null_helper;
246
  friend class Item_is_not_null_test;
247
  friend class subselect_indexsubquery_engine;
unknown's avatar
unknown committed
248 249
};

250

unknown's avatar
unknown committed
251 252 253 254
/* ALL/ANY/SOME subselect */
class Item_allany_subselect :public Item_in_subselect
{
protected:
unknown's avatar
unknown committed
255
  Comp_creator *func;
unknown's avatar
unknown committed
256 257

public:
unknown's avatar
unknown committed
258 259
  bool all;

unknown's avatar
unknown committed
260
  Item_allany_subselect(Item * left_expr, Comp_creator *f,
unknown's avatar
unknown committed
261
		     st_select_lex *select_lex, bool all);
262

263
  // only ALL subquery has upper not
264
  subs_type substype() { return all?ALL_SUBS:ANY_SUBS; }
unknown's avatar
unknown committed
265
  trans_res select_transformer(JOIN *join);
unknown's avatar
unknown committed
266
  void print(String *str);
unknown's avatar
unknown committed
267 268
};

269

unknown's avatar
unknown committed
270
class subselect_engine: public Sql_alloc
unknown's avatar
unknown committed
271 272 273 274 275
{
protected:
  select_subselect *result; /* results storage class */
  THD *thd; /* pointer to current THD */
  Item_subselect *item; /* item, that use this engine */
276
  enum Item_result res_type; /* type of results */
unknown's avatar
unknown committed
277
  bool maybe_null; /* may be null (first item in select) */
unknown's avatar
unknown committed
278 279
public:

280 281
  subselect_engine(Item_subselect *si, select_subselect *res)
    :thd(0)
unknown's avatar
unknown committed
282 283 284
  {
    result= res;
    item= si;
285
    res_type= STRING_RESULT;
unknown's avatar
unknown committed
286
    maybe_null= 0;
unknown's avatar
unknown committed
287
  }
unknown's avatar
unknown committed
288
  virtual ~subselect_engine() {}; // to satisfy compiler
unknown's avatar
unknown committed
289
  virtual void cleanup()= 0;
290

291
  // set_thd should be called before prepare()
292
  void set_thd(THD *thd_arg) { thd= thd_arg; }
293
  THD * get_thd() { return thd; }
unknown's avatar
unknown committed
294
  virtual int prepare()= 0;
295
  virtual void fix_length_and_dec(Item_cache** row)= 0;
unknown's avatar
unknown committed
296 297
  virtual int exec()= 0;
  virtual uint cols()= 0; /* return number of columnss in select */
298
  virtual uint8 uncacheable()= 0; /* query is uncacheable */
299
  enum Item_result type() { return res_type; }
unknown's avatar
unknown committed
300
  virtual void exclude()= 0;
unknown's avatar
unknown committed
301
  bool may_be_null() { return maybe_null; };
302 303
  virtual table_map upper_select_const_tables()= 0;
  static table_map calc_const_tables(TABLE_LIST *);
unknown's avatar
unknown committed
304
  virtual void print(String *str)= 0;
305
  virtual int change_item(Item_subselect *si, select_subselect *result)= 0;
306
  virtual bool no_tables()= 0;
unknown's avatar
unknown committed
307 308
};

309

unknown's avatar
unknown committed
310 311
class subselect_single_select_engine: public subselect_engine
{
unknown's avatar
unknown committed
312
  my_bool prepared; /* simple subselect is prepared */
unknown's avatar
unknown committed
313
  my_bool optimized; /* simple subselect is optimized */
unknown's avatar
unknown committed
314
  my_bool executed; /* simple subselect is executed */
unknown's avatar
unknown committed
315 316 317
  st_select_lex *select_lex; /* corresponding select_lex */
  JOIN * join; /* corresponding JOIN structure */
public:
318
  subselect_single_select_engine(st_select_lex *select,
unknown's avatar
unknown committed
319 320
				 select_subselect *result,
				 Item_subselect *item);
unknown's avatar
unknown committed
321
  void cleanup();
unknown's avatar
unknown committed
322
  int prepare();
323
  void fix_length_and_dec(Item_cache** row);
unknown's avatar
unknown committed
324 325
  int exec();
  uint cols();
326
  uint8 uncacheable();
unknown's avatar
unknown committed
327
  void exclude();
328
  table_map upper_select_const_tables();
unknown's avatar
unknown committed
329
  void print (String *str);
330
  int change_item(Item_subselect *si, select_subselect *result);
331
  bool no_tables();
unknown's avatar
unknown committed
332 333
};

334

unknown's avatar
unknown committed
335 336 337 338
class subselect_union_engine: public subselect_engine
{
  st_select_lex_unit *unit;  /* corresponding unit structure */
public:
339
  subselect_union_engine(st_select_lex_unit *u,
unknown's avatar
unknown committed
340 341
			 select_subselect *result,
			 Item_subselect *item);
unknown's avatar
unknown committed
342
  void cleanup();
unknown's avatar
unknown committed
343
  int prepare();
344
  void fix_length_and_dec(Item_cache** row);
unknown's avatar
unknown committed
345 346
  int exec();
  uint cols();
347
  uint8 uncacheable();
unknown's avatar
unknown committed
348
  void exclude();
349
  table_map upper_select_const_tables();
unknown's avatar
unknown committed
350
  void print (String *str);
351
  int change_item(Item_subselect *si, select_subselect *result);
352
  bool no_tables();
unknown's avatar
unknown committed
353
};
354

355

356
struct st_join_table;
357
class subselect_uniquesubquery_engine: public subselect_engine
358
{
359
protected:
360 361 362 363
  st_join_table *tab;
  Item *cond;
public:

364
  // constructor can assign THD because it will be called after JOIN::prepare
365
  subselect_uniquesubquery_engine(THD *thd_arg, st_join_table *tab_arg,
366
				  Item_subselect *subs, Item *where)
367 368
    :subselect_engine(subs, 0), tab(tab_arg), cond(where)
  {
369
    set_thd(thd_arg);
370
  }
371
  ~subselect_uniquesubquery_engine();
unknown's avatar
unknown committed
372
  void cleanup();
373 374 375 376
  int prepare();
  void fix_length_and_dec(Item_cache** row);
  int exec();
  uint cols() { return 1; }
377
  uint8 uncacheable() { return UNCACHEABLE_DEPENDENT; }
378
  void exclude();
379
  table_map upper_select_const_tables() { return 0; }
unknown's avatar
unknown committed
380
  void print (String *str);
381
  int change_item(Item_subselect *si, select_subselect *result);
382
  bool no_tables();
383 384
};

385

386
class subselect_indexsubquery_engine: public subselect_uniquesubquery_engine
387
{
388
  bool check_null;
389
public:
390 391

  // constructor can assign THD because it will be called after JOIN::prepare
392 393 394 395
  subselect_indexsubquery_engine(THD *thd, st_join_table *tab_arg,
				 Item_subselect *subs, Item *where,
				 bool chk_null)
    :subselect_uniquesubquery_engine(thd, tab_arg, subs, where),
396
     check_null(chk_null)
397 398
  {}
  int exec();
unknown's avatar
unknown committed
399
  void print (String *str);
400
};