mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 21:42:35 +01:00
bb2d3eaa30
BitKeeper/etc/ignore: auto-union BitKeeper/etc/logging_ok: auto-union Build-tools/Do-compile: Auto merged VC++Files/sql/mysqld.dsp: Auto merged client/Makefile.am: Auto merged client/mysql.cc: Auto merged BitKeeper/deleted/.del-acinclude.m4~f4ab416bac5003: Auto merged client/mysqltest.c: Auto merged include/my_base.h: Auto merged innobase/dict/dict0dict.c: Auto merged innobase/dict/dict0load.c: Auto merged innobase/include/dict0dict.h: Auto merged innobase/include/row0mysql.h: Auto merged innobase/os/os0file.c: Auto merged innobase/srv/srv0srv.c: Auto merged libmysql/libmysql.c: Auto merged myisam/mi_check.c: Auto merged myisam/mi_rnext_same.c: Auto merged myisam/mi_write.c: Auto merged myisam/sort.c: Auto merged mysql-test/mysql-test-run.sh: Auto merged mysql-test/r/ctype_ucs.result: Auto merged mysql-test/r/ctype_ujis.result: Auto merged mysql-test/r/gis-rtree.result: Auto merged mysql-test/r/group_by.result: Auto merged mysql-test/r/merge.result: Auto merged mysql-test/r/metadata.result: Auto merged mysql-test/r/ndb_alter_table.result: Auto merged mysql-test/r/ps_1general.result: Auto merged mysql-test/r/insert_update.result: Auto merged mysql-test/r/timezone2.result: Auto merged mysql-test/r/type_enum.result: Auto merged mysql-test/r/variables.result: Auto merged mysql-test/t/ctype_ucs.test: Auto merged mysql-test/t/merge.test: Auto merged mysql-test/t/ps_1general.test: Auto merged mysql-test/t/subselect.test: Auto merged mysql-test/t/system_mysql_db_fix.test: Auto merged mysql-test/t/variables.test: Auto merged ndb/include/ndbapi/NdbConnection.hpp: Auto merged ndb/include/ndbapi/NdbDictionary.hpp: Auto merged ndb/src/common/util/version.c: Auto merged ndb/src/kernel/blocks/dbacc/DbaccInit.cpp: Auto merged ndb/src/kernel/blocks/dbacc/Makefile.am: Auto merged ndb/src/kernel/blocks/dbdict/Dbdict.cpp: Auto merged ndb/src/kernel/blocks/dbdih/DbdihMain.cpp: Auto merged ndb/src/kernel/blocks/dblqh/DblqhInit.cpp: Auto merged ndb/src/kernel/blocks/dbtc/DbtcMain.cpp: Auto merged ndb/src/kernel/blocks/dbtux/Dbtux.hpp: Auto merged ndb/src/ndbapi/NdbBlob.cpp: Auto merged ndb/src/ndbapi/NdbConnection.cpp: Auto merged ndb/src/ndbapi/NdbDictionary.cpp: Auto merged ndb/src/ndbapi/NdbDictionaryImpl.cpp: Auto merged ndb/src/ndbapi/NdbDictionaryImpl.hpp: Auto merged ndb/src/ndbapi/NdbOperationExec.cpp: Auto merged ndb/src/ndbapi/NdbScanOperation.cpp: Auto merged ndb/test/ndbapi/Makefile.am: Auto merged scripts/make_win_src_distribution.sh: Auto merged scripts/mysql_install_db.sh: Auto merged sql/field.cc: Auto merged sql/ha_innodb.cc: Auto merged sql/ha_ndbcluster.cc: Auto merged sql/ha_ndbcluster.h: Auto merged sql/handler.cc: Auto merged sql/item_cmpfunc.cc: Auto merged sql/item_create.h: Auto merged sql/item_func.cc: Auto merged sql/item_geofunc.cc: Auto merged sql/item_row.cc: Auto merged sql/item_strfunc.cc: Auto merged sql/item_strfunc.h: Auto merged sql/item_sum.cc: Auto merged sql/item_sum.h: Auto merged sql/log.cc: Auto merged sql/log_event.cc: Auto merged sql/mysqld.cc: Auto merged sql/net_serv.cc: Auto merged sql/password.c: Auto merged sql/protocol.cc: Auto merged sql/repl_failsafe.cc: Auto merged sql/set_var.cc: Auto merged sql/slave.cc: Auto merged sql/sql_acl.cc: Auto merged sql/sql_cache.cc: Auto merged sql/sql_class.cc: Auto merged sql/sql_derived.cc: Auto merged sql/sql_do.cc: Auto merged sql/sql_handler.cc: Auto merged sql/sql_help.cc: Auto merged sql/sql_lex.cc: Auto merged sql/sql_lex.h: Auto merged sql/sql_repl.cc: Auto merged sql/sql_show.cc: Auto merged sql/sql_union.cc: Auto merged sql/examples/ha_archive.cc: Auto merged sql/strfunc.cc: Auto merged sql/table.cc: Auto merged sql/table.h: Auto merged sql/tztime.h: Auto merged sql/udf_example.cc: Auto merged sql/unireg.cc: Auto merged Makefile.am: Simple merge client/mysqldump.c: Simple merge configure.in: Simple merge libmysqld/lib_sql.cc: Automatic merge mysql-test/r/func_str.result: Automatic merge mysql-test/r/grant.result: simple merge mysql-test/r/multi_update.result: automatc merge mysql-test/r/ps.result: automatic merge mysql-test/r/ps_2myisam.result: Automatic merge mysql-test/r/ps_3innodb.result: Automatic merge mysql-test/r/ps_4heap.result: Automatic merge mysql-test/r/ps_5merge.result: Automatic merge mysql-test/r/ps_6bdb.result: Automatic merge mysql-test/r/ps_7ndb.result: Automatic merge mysql-test/r/show_check.result: Automatic merge mysql-test/r/subselect.result: Automatic merge mysql-test/t/grant.test: Automatic merge mysql-test/t/multi_update.test: Automatic merge mysql-test/t/ps.test: Automatic merge mysql-test/t/show_check.test: Automatic merge ndb/docs/wl2077.txt: merge ndb/src/mgmsrv/main.cpp: merge scripts/mysql_fix_privilege_tables.sh: merge sql/item.cc: Merge (difficult) sql/item.h: simple merge sql/item_cmpfunc.h: Automatic merge sql/item_subselect.cc: Simple merge sql/item_subselect.h: Automatic merge sql/mysql_priv.h: Simple merge sql/slave.h: Automatic merge sql/sql_base.cc: Removed code that was backported to 4.1 sql/sql_class.h: Merge (some code moved to sql_insert.cc) sql/sql_db.cc: simple merge sql/sql_insert.cc: Merge (difficult as logic had changed both in 4.1 and 5.0) Some coded moved here from sql_class.h sql/sql_parse.cc: Merge (difficult) sql/sql_prepare.cc: Simple merge sql/sql_select.cc: Automatic merge sql/sql_table.cc: Simple merge sql/sql_update.cc: Difficult merge because of different logic for multi-updates sql/sql_yacc.yy: Simple merge tests/client_test.c: Simple merge
400 lines
11 KiB
C++
400 lines
11 KiB
C++
/* 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
|
|
|
|
class st_select_lex;
|
|
class st_select_lex_unit;
|
|
class JOIN;
|
|
class select_subselect;
|
|
class subselect_engine;
|
|
class Item_bool_func2;
|
|
class Item_arena;
|
|
|
|
/* base class for subselects */
|
|
|
|
class Item_subselect :public Item_result_field
|
|
{
|
|
my_bool value_assigned; /* value already assigned to subselect */
|
|
protected:
|
|
/* thread handler, will be assigned in fix_fields only */
|
|
THD *thd;
|
|
/* substitution instead of subselect in case of optimization */
|
|
Item *substitution;
|
|
/* unit of subquery */
|
|
st_select_lex_unit *unit;
|
|
/* engine that perform execution of subselect (single select or union) */
|
|
subselect_engine *engine;
|
|
/* old engine if engine was changed */
|
|
subselect_engine *old_engine;
|
|
/* cache of used external tables */
|
|
table_map used_tables_cache;
|
|
/* allowed number of columns (1 for single value subqueries) */
|
|
uint max_columns;
|
|
/* where subquery is placed */
|
|
enum_parsing_place parsing_place;
|
|
/* work with 'substitution' */
|
|
bool have_to_be_excluded;
|
|
/* cache of constant state */
|
|
bool const_item_cache;
|
|
|
|
public:
|
|
/* changed engine indicator */
|
|
bool engine_changed;
|
|
/* subquery is transformed */
|
|
bool changed;
|
|
|
|
enum trans_res {RES_OK, RES_REDUCE, RES_ERROR};
|
|
enum subs_type {UNKNOWN_SUBS, SINGLEROW_SUBS,
|
|
EXISTS_SUBS, IN_SUBS, ALL_SUBS, ANY_SUBS};
|
|
|
|
Item_subselect();
|
|
|
|
virtual subs_type substype() { return UNKNOWN_SUBS; }
|
|
|
|
/*
|
|
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.
|
|
*/
|
|
virtual void init (st_select_lex *select_lex,
|
|
select_subselect *result);
|
|
|
|
~Item_subselect();
|
|
void cleanup();
|
|
virtual void reset()
|
|
{
|
|
null_value= 1;
|
|
}
|
|
virtual trans_res select_transformer(JOIN *join);
|
|
bool assigned() { return value_assigned; }
|
|
void assigned(bool a) { value_assigned= a; }
|
|
enum Type type() const;
|
|
bool is_null()
|
|
{
|
|
val_int();
|
|
return null_value;
|
|
}
|
|
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
|
|
virtual bool exec();
|
|
virtual void fix_length_and_dec();
|
|
table_map used_tables() const;
|
|
bool const_item() const;
|
|
inline table_map get_used_tables_cache() { return used_tables_cache; }
|
|
inline bool get_const_item_cache() { return const_item_cache; }
|
|
Item *get_tmp_table_item(THD *thd);
|
|
void update_used_tables();
|
|
void print(String *str);
|
|
bool change_engine(subselect_engine *eng)
|
|
{
|
|
old_engine= engine;
|
|
engine= eng;
|
|
engine_changed= 1;
|
|
return eng == 0;
|
|
}
|
|
/*
|
|
Used by max/min subquery to initialize value presence registration
|
|
mechanism. Engine call this method before rexecution query.
|
|
*/
|
|
virtual void reset_value_registration() {}
|
|
enum_parsing_place place() { return parsing_place; }
|
|
|
|
friend class select_subselect;
|
|
friend class Item_in_optimizer;
|
|
friend bool Item_field::fix_fields(THD *, TABLE_LIST *, Item **);
|
|
friend bool Item_ref::fix_fields(THD *, TABLE_LIST *, Item **);
|
|
};
|
|
|
|
/* single value subselect */
|
|
|
|
class Item_cache;
|
|
class Item_singlerow_subselect :public Item_subselect
|
|
{
|
|
protected:
|
|
Item_cache *value, **row;
|
|
public:
|
|
Item_singlerow_subselect(st_select_lex *select_lex);
|
|
Item_singlerow_subselect() :Item_subselect(), value(0), row (0) {}
|
|
|
|
void cleanup();
|
|
subs_type substype() { return SINGLEROW_SUBS; }
|
|
|
|
void reset();
|
|
trans_res select_transformer(JOIN *join);
|
|
void store(uint i, Item* item);
|
|
double val_real();
|
|
longlong val_int ();
|
|
String *val_str (String *);
|
|
enum Item_result result_type() const;
|
|
void fix_length_and_dec();
|
|
|
|
uint cols();
|
|
Item* el(uint i) { return my_reinterpret_cast(Item*)(row[i]); }
|
|
Item** addr(uint i) { return (Item**)row + i; }
|
|
bool check_cols(uint c);
|
|
bool null_inside();
|
|
void bring_value();
|
|
|
|
friend class select_singlerow_subselect;
|
|
};
|
|
|
|
/* used in static ALL/ANY optimisation */
|
|
class select_max_min_finder_subselect;
|
|
class Item_maxmin_subselect :public Item_singlerow_subselect
|
|
{
|
|
protected:
|
|
bool max;
|
|
bool was_values; // Set if we have found at least one row
|
|
public:
|
|
Item_maxmin_subselect(THD *thd, Item_subselect *parent,
|
|
st_select_lex *select_lex, bool max);
|
|
void print(String *str);
|
|
void cleanup();
|
|
bool any_value() { return was_values; }
|
|
void register_value() { was_values= TRUE; }
|
|
void reset_value_registration() { was_values= FALSE; }
|
|
};
|
|
|
|
/* exists subselect */
|
|
|
|
class Item_exists_subselect :public Item_subselect
|
|
{
|
|
protected:
|
|
longlong value; /* value of this item (boolean: exists/not-exists) */
|
|
|
|
public:
|
|
Item_exists_subselect(st_select_lex *select_lex);
|
|
Item_exists_subselect(): Item_subselect() {}
|
|
|
|
subs_type substype() { return EXISTS_SUBS; }
|
|
void reset()
|
|
{
|
|
value= 0;
|
|
}
|
|
|
|
enum Item_result result_type() const { return INT_RESULT;}
|
|
longlong val_int();
|
|
double val_real();
|
|
String *val_str(String*);
|
|
void fix_length_and_dec();
|
|
void print(String *str);
|
|
|
|
friend class select_exists_subselect;
|
|
friend class subselect_uniquesubquery_engine;
|
|
friend class subselect_indexsubquery_engine;
|
|
};
|
|
|
|
/* IN subselect */
|
|
|
|
class Item_in_subselect :public Item_exists_subselect
|
|
{
|
|
protected:
|
|
Item *left_expr;
|
|
/*
|
|
expr & optimizer used in subselect rewriting to store Item for
|
|
all JOIN in UNION
|
|
*/
|
|
Item *expr;
|
|
Item_in_optimizer *optimizer;
|
|
bool was_null;
|
|
bool abort_on_null;
|
|
bool transformed;
|
|
public:
|
|
Item_func_not_all *upper_item; // point on NOT/NOP before ALL/SOME subquery
|
|
|
|
Item_in_subselect(Item * left_expr, st_select_lex *select_lex);
|
|
Item_in_subselect()
|
|
:Item_exists_subselect(), abort_on_null(0), transformed(0), upper_item(0)
|
|
{}
|
|
|
|
subs_type substype() { return IN_SUBS; }
|
|
void reset()
|
|
{
|
|
value= 0;
|
|
null_value= 0;
|
|
was_null= 0;
|
|
}
|
|
trans_res select_transformer(JOIN *join);
|
|
trans_res single_value_transformer(JOIN *join,
|
|
Comp_creator *func);
|
|
trans_res row_value_transformer(JOIN * join);
|
|
longlong val_int();
|
|
double val_real();
|
|
String *val_str(String*);
|
|
void top_level_item() { abort_on_null=1; }
|
|
bool test_limit(st_select_lex_unit *unit);
|
|
void print(String *str);
|
|
|
|
friend class Item_ref_null_helper;
|
|
friend class Item_is_not_null_test;
|
|
friend class subselect_indexsubquery_engine;
|
|
};
|
|
|
|
|
|
/* ALL/ANY/SOME subselect */
|
|
class Item_allany_subselect :public Item_in_subselect
|
|
{
|
|
protected:
|
|
Comp_creator *func;
|
|
|
|
public:
|
|
bool all;
|
|
|
|
Item_allany_subselect(Item * left_expr, Comp_creator *f,
|
|
st_select_lex *select_lex, bool all);
|
|
|
|
// only ALL subquery has upper not
|
|
subs_type substype() { return all?ALL_SUBS:ANY_SUBS; }
|
|
trans_res select_transformer(JOIN *join);
|
|
void print(String *str);
|
|
};
|
|
|
|
|
|
class subselect_engine: public Sql_alloc
|
|
{
|
|
protected:
|
|
select_subselect *result; /* results storage class */
|
|
THD *thd; /* pointer to current THD */
|
|
Item_subselect *item; /* item, that use this engine */
|
|
enum Item_result res_type; /* type of results */
|
|
bool maybe_null; /* may be null (first item in select) */
|
|
public:
|
|
|
|
subselect_engine(Item_subselect *si, select_subselect *res)
|
|
:thd(0)
|
|
{
|
|
result= res;
|
|
item= si;
|
|
res_type= STRING_RESULT;
|
|
maybe_null= 0;
|
|
}
|
|
virtual ~subselect_engine() {}; // to satisfy compiler
|
|
virtual void cleanup()= 0;
|
|
|
|
// set_thd should be called before prepare()
|
|
void set_thd(THD *thd_arg) { thd= thd_arg; }
|
|
THD * get_thd() { return thd; }
|
|
virtual int prepare()= 0;
|
|
virtual void fix_length_and_dec(Item_cache** row)= 0;
|
|
virtual int exec()= 0;
|
|
virtual uint cols()= 0; /* return number of columnss in select */
|
|
virtual uint8 uncacheable()= 0; /* query is uncacheable */
|
|
enum Item_result type() { return res_type; }
|
|
virtual void exclude()= 0;
|
|
bool may_be_null() { return maybe_null; };
|
|
virtual table_map upper_select_const_tables()= 0;
|
|
static table_map calc_const_tables(TABLE_LIST *);
|
|
virtual void print(String *str)= 0;
|
|
virtual bool change_result(Item_subselect *si, select_subselect *result)= 0;
|
|
virtual bool no_tables()= 0;
|
|
};
|
|
|
|
|
|
class subselect_single_select_engine: public subselect_engine
|
|
{
|
|
my_bool prepared; /* simple subselect is prepared */
|
|
my_bool optimized; /* simple subselect is optimized */
|
|
my_bool executed; /* simple subselect is executed */
|
|
st_select_lex *select_lex; /* corresponding select_lex */
|
|
JOIN * join; /* corresponding JOIN structure */
|
|
public:
|
|
subselect_single_select_engine(st_select_lex *select,
|
|
select_subselect *result,
|
|
Item_subselect *item);
|
|
void cleanup();
|
|
int prepare();
|
|
void fix_length_and_dec(Item_cache** row);
|
|
int exec();
|
|
uint cols();
|
|
uint8 uncacheable();
|
|
void exclude();
|
|
table_map upper_select_const_tables();
|
|
void print (String *str);
|
|
bool change_result(Item_subselect *si, select_subselect *result);
|
|
bool no_tables();
|
|
};
|
|
|
|
|
|
class subselect_union_engine: public subselect_engine
|
|
{
|
|
st_select_lex_unit *unit; /* corresponding unit structure */
|
|
public:
|
|
subselect_union_engine(st_select_lex_unit *u,
|
|
select_subselect *result,
|
|
Item_subselect *item);
|
|
void cleanup();
|
|
int prepare();
|
|
void fix_length_and_dec(Item_cache** row);
|
|
int exec();
|
|
uint cols();
|
|
uint8 uncacheable();
|
|
void exclude();
|
|
table_map upper_select_const_tables();
|
|
void print (String *str);
|
|
bool change_result(Item_subselect *si, select_subselect *result);
|
|
bool no_tables();
|
|
};
|
|
|
|
|
|
struct st_join_table;
|
|
class subselect_uniquesubquery_engine: public subselect_engine
|
|
{
|
|
protected:
|
|
st_join_table *tab;
|
|
Item *cond;
|
|
public:
|
|
|
|
// constructor can assign THD because it will be called after JOIN::prepare
|
|
subselect_uniquesubquery_engine(THD *thd_arg, st_join_table *tab_arg,
|
|
Item_subselect *subs, Item *where)
|
|
:subselect_engine(subs, 0), tab(tab_arg), cond(where)
|
|
{
|
|
set_thd(thd_arg);
|
|
}
|
|
~subselect_uniquesubquery_engine();
|
|
void cleanup();
|
|
int prepare();
|
|
void fix_length_and_dec(Item_cache** row);
|
|
int exec();
|
|
uint cols() { return 1; }
|
|
uint8 uncacheable() { return UNCACHEABLE_DEPENDENT; }
|
|
void exclude();
|
|
table_map upper_select_const_tables() { return 0; }
|
|
void print (String *str);
|
|
bool change_result(Item_subselect *si, select_subselect *result);
|
|
bool no_tables();
|
|
};
|
|
|
|
|
|
class subselect_indexsubquery_engine: public subselect_uniquesubquery_engine
|
|
{
|
|
bool check_null;
|
|
public:
|
|
|
|
// constructor can assign THD because it will be called after JOIN::prepare
|
|
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),
|
|
check_null(chk_null)
|
|
{}
|
|
int exec();
|
|
void print (String *str);
|
|
};
|