From b9dccb34ddcf8c528c48103d01885de8e8fd9d84 Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Fri, 17 Oct 2003 00:36:01 +0300 Subject: [PATCH 1/4] fixed support of used_tables() and const_item() in subqueries (BUG#1444) --- mysql-test/r/subselect.result | 18 +++++++++++++ mysql-test/t/subselect.test | 16 ++++++++++++ sql/item.cc | 44 +++++++++++++++++++++++++++++--- sql/item_subselect.cc | 48 ++++++++++++++++++++++++++++++++--- sql/item_subselect.h | 15 ++++++++++- 5 files changed, 133 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 6e35b6e78c1..e91dc6e2149 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1439,3 +1439,21 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t3 ALL NULL NULL NULL NULL 3 Using where 2 SUBQUERY t2 ALL NULL NULL NULL NULL 4 Using temporary; Using filesort drop table if exists t2, t3; +CREATE TABLE `t1` ( `id` mediumint(9) NOT NULL auto_increment, `taskid` bigint(20) NOT NULL default '0', `dbid` int(11) NOT NULL default '0', `create_date` datetime NOT NULL default '0000-00-00 00:00:00', `last_update` datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (`id`)) TYPE=MyISAM CHARSET=latin1 AUTO_INCREMENT=3 ; +INSERT INTO `t1` (`id`, `taskid`, `dbid`, `create_date`,`last_update`) VALUES (1, 1, 15, '2003-09-29 10:31:36', '2003-09-29 10:31:36'), (2, 1, 21, now(), now()); +CREATE TABLE `t2` (`db_id` int(11) NOT NULL auto_increment,`name` varchar(200) NOT NULL default '',`primary_uid` smallint(6) NOT NULL default '0',`secondary_uid` smallint(6) NOT NULL default '0',PRIMARY KEY (`db_id`),UNIQUE KEY `name_2` (`name`),FULLTEXT KEY `name` (`name`)) TYPE=MyISAM CHARSET=latin1 AUTO_INCREMENT=2147483647; +INSERT INTO `t2` (`db_id`, `name`, `primary_uid`, `secondary_uid`) VALUES (18, 'Not Set 1', 0, 0),(19, 'Valid', 1, 2),(20, 'Valid 2', 1, 2),(21, 'Should Not Return', 1, 2),(26, 'Not Set 2', 0, 0),(-1, 'ALL DB\'S', 0, 0); +CREATE TABLE `t3` (`taskgenid` mediumint(9) NOT NULL auto_increment,`dbid` int(11) NOT NULL default '0',`taskid` int(11) NOT NULL default '0',`mon` tinyint(4) NOT NULL default '1',`tues` tinyint(4) NOT NULL default '1',`wed` tinyint(4) NOT NULL default '1',`thur` tinyint(4) NOT NULL default '1',`fri` tinyint(4) NOT NULL default '1',`sat` tinyint(4) NOT NULL default '0',`sun` tinyint(4) NOT NULL default '0',`how_often` smallint(6) NOT NULL default '1',`userid` smallint(6) NOT NULL default '0',`active` tinyint(4) NOT NULL default '1',PRIMARY KEY (`taskgenid`)) TYPE=MyISAM CHARSET=latin1 AUTO_INCREMENT=2 ; +INSERT INTO `t3` (`taskgenid`, `dbid`, `taskid`, `mon`, `tues`,`wed`, `thur`, `fri`, `sat`, `sun`, `how_often`, `userid`, `active`) VALUES (1,-1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1); +CREATE TABLE `t4` (`task_id` smallint(6) NOT NULL default '0',`description` varchar(200) NOT NULL default '') TYPE=MyISAM CHARSET=latin1; +INSERT INTO `t4` (`task_id`, `description`) VALUES (1, 'Daily Check List'),(2, 'Weekly Status'); +select dbid, name, (date_format(now() , '%Y-%m-%d') - INTERVAL how_often DAY) >= ifnull((SELECT date_format(max(create_date),'%Y-%m-%d') FROM t1 WHERE dbid = b.db_id AND taskid = a.taskgenid), '1950-01-01') from t3 a, t2 b, t4 WHERE dbid = - 1 AND primary_uid = '1' AND t4.task_id = taskid; +dbid name (date_format(now() , '%Y-%m-%d') - INTERVAL how_often DAY) >= ifnull((SELECT date_format(max(create_date),'%Y-%m-%d') FROM t1 WHERE dbid = b.db_id AND taskid = a.taskgenid), '1950-01-01') +-1 Valid 1 +-1 Valid 2 1 +-1 Should Not Return 0 +SELECT dbid, name FROM t3 a, t2 b, t4 WHERE dbid = - 1 AND primary_uid = '1' AND ((date_format(now() , '%Y-%m-%d') - INTERVAL how_often DAY) >= ifnull((SELECT date_format(max(create_date),'%Y-%m-%d') FROM t1 WHERE dbid = b.db_id AND taskid = a.taskgenid), '1950-01-01')) AND t4.task_id = taskid; +dbid name +-1 Valid +-1 Valid 2 +drop table t1,t2,t3,t4; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 9ba91c7e0a6..861b37ec53e 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -965,3 +965,19 @@ insert into t2 values (2,2), (2,1), (3,3), (3,1); select * from t3 where a > all (select max(b) from t2 group by a); explain select * from t3 where a > all (select max(b) from t2 group by a); drop table if exists t2, t3; + +# +# correct used_tables() +# + +CREATE TABLE `t1` ( `id` mediumint(9) NOT NULL auto_increment, `taskid` bigint(20) NOT NULL default '0', `dbid` int(11) NOT NULL default '0', `create_date` datetime NOT NULL default '0000-00-00 00:00:00', `last_update` datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (`id`)) TYPE=MyISAM CHARSET=latin1 AUTO_INCREMENT=3 ; +INSERT INTO `t1` (`id`, `taskid`, `dbid`, `create_date`,`last_update`) VALUES (1, 1, 15, '2003-09-29 10:31:36', '2003-09-29 10:31:36'), (2, 1, 21, now(), now()); +CREATE TABLE `t2` (`db_id` int(11) NOT NULL auto_increment,`name` varchar(200) NOT NULL default '',`primary_uid` smallint(6) NOT NULL default '0',`secondary_uid` smallint(6) NOT NULL default '0',PRIMARY KEY (`db_id`),UNIQUE KEY `name_2` (`name`),FULLTEXT KEY `name` (`name`)) TYPE=MyISAM CHARSET=latin1 AUTO_INCREMENT=2147483647; +INSERT INTO `t2` (`db_id`, `name`, `primary_uid`, `secondary_uid`) VALUES (18, 'Not Set 1', 0, 0),(19, 'Valid', 1, 2),(20, 'Valid 2', 1, 2),(21, 'Should Not Return', 1, 2),(26, 'Not Set 2', 0, 0),(-1, 'ALL DB\'S', 0, 0); +CREATE TABLE `t3` (`taskgenid` mediumint(9) NOT NULL auto_increment,`dbid` int(11) NOT NULL default '0',`taskid` int(11) NOT NULL default '0',`mon` tinyint(4) NOT NULL default '1',`tues` tinyint(4) NOT NULL default '1',`wed` tinyint(4) NOT NULL default '1',`thur` tinyint(4) NOT NULL default '1',`fri` tinyint(4) NOT NULL default '1',`sat` tinyint(4) NOT NULL default '0',`sun` tinyint(4) NOT NULL default '0',`how_often` smallint(6) NOT NULL default '1',`userid` smallint(6) NOT NULL default '0',`active` tinyint(4) NOT NULL default '1',PRIMARY KEY (`taskgenid`)) TYPE=MyISAM CHARSET=latin1 AUTO_INCREMENT=2 ; +INSERT INTO `t3` (`taskgenid`, `dbid`, `taskid`, `mon`, `tues`,`wed`, `thur`, `fri`, `sat`, `sun`, `how_often`, `userid`, `active`) VALUES (1,-1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1); +CREATE TABLE `t4` (`task_id` smallint(6) NOT NULL default '0',`description` varchar(200) NOT NULL default '') TYPE=MyISAM CHARSET=latin1; +INSERT INTO `t4` (`task_id`, `description`) VALUES (1, 'Daily Check List'),(2, 'Weekly Status'); +select dbid, name, (date_format(now() , '%Y-%m-%d') - INTERVAL how_often DAY) >= ifnull((SELECT date_format(max(create_date),'%Y-%m-%d') FROM t1 WHERE dbid = b.db_id AND taskid = a.taskgenid), '1950-01-01') from t3 a, t2 b, t4 WHERE dbid = - 1 AND primary_uid = '1' AND t4.task_id = taskid; +SELECT dbid, name FROM t3 a, t2 b, t4 WHERE dbid = - 1 AND primary_uid = '1' AND ((date_format(now() , '%Y-%m-%d') - INTERVAL how_often DAY) >= ifnull((SELECT date_format(max(create_date),'%Y-%m-%d') FROM t1 WHERE dbid = b.db_id AND taskid = a.taskgenid), '1950-01-01')) AND t4.task_id = taskid; +drop table t1,t2,t3,t4; diff --git a/sql/item.cc b/sql/item.cc index 4de4951cb51..970a92992ed 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -817,9 +817,11 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) // Prevent using outer fields in subselects, that is not supported now SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select; if (cursel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE) - for (SELECT_LEX *sl= cursel->outer_select(); + { + SELECT_LEX_UNIT *prev_unit= cursel->master_unit(); + for (SELECT_LEX *sl= prev_unit->outer_select(); sl; - sl= sl->outer_select()) + sl= (prev_unit= sl->master_unit())->outer_select()) { table_list= (last= sl)->get_table_list(); if (sl->resolve_mode == SELECT_LEX::INSERT_MODE && table_list) @@ -830,16 +832,33 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) if ((tmp= find_field_in_tables(thd, this, table_list, &where, 0)) != not_found_field) + { + prev_unit->item->used_tables_cache|= tmp->table->map; + prev_unit->item->const_item_cache= 0; break; + } if (sl->resolve_mode == SELECT_LEX::SELECT_MODE && (refer= find_item_in_list(this, sl->item_list, &counter, REPORT_EXCEPT_NOT_FOUND)) != (Item **) not_found_item) + { + if (*refer && (*refer)->fixed) // Avoid crash in case of error + { + prev_unit->item->used_tables_cache|= (*refer)->used_tables(); + prev_unit->item->const_item_cache&= (*refer)->const_item(); + } break; + } + + // Reference is not found => depend from outer (or just error) + prev_unit->item->used_tables_cache|= OUTER_REF_TABLE_BIT; + prev_unit->item->const_item_cache= 0; + if (sl->master_unit()->first_select()->linkage == DERIVED_TABLE_TYPE) break; // do not look over derived table } + } if (!tmp) return -1; else if (!refer) @@ -1350,7 +1369,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) if (!ref) { TABLE_LIST *where= 0, *table_list; - SELECT_LEX *sl= thd->lex.current_select->outer_select(); + SELECT_LEX_UNIT *prev_unit= thd->lex.current_select->master_unit(); + SELECT_LEX *sl= prev_unit->outer_select(); /* Finding only in current select will be performed for selects that have not outer one and for derived tables (which not support using outer @@ -1378,7 +1398,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) cause error ER_NON_UNIQ_ERROR in find_item_in_list. */ SELECT_LEX *last=0; - for ( ; sl ; sl= sl->outer_select()) + for ( ; sl ; sl= (prev_unit= sl->master_unit())->outer_select()) { last= sl; if (sl->resolve_mode == SELECT_LEX::SELECT_MODE && @@ -1386,7 +1406,14 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) &counter, REPORT_EXCEPT_NOT_FOUND)) != (Item **)not_found_item) + { + if (*ref && (*ref)->fixed) // Avoid crash in case of error + { + prev_unit->item->used_tables_cache|= (*ref)->used_tables(); + prev_unit->item->const_item_cache&= (*ref)->const_item(); + } break; + } table_list= sl->get_table_list(); if (sl->resolve_mode == SELECT_LEX::INSERT_MODE && table_list) { @@ -1396,7 +1423,16 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) if ((tmp= find_field_in_tables(thd, this, table_list, &where, 0)) != not_found_field) + { + prev_unit->item->used_tables_cache|= tmp->table->map; + prev_unit->item->const_item_cache= 0; break; + } + + // Reference is not found => depend from outer (or just error) + prev_unit->item->used_tables_cache|= OUTER_REF_TABLE_BIT; + prev_unit->item->const_item_cache= 0; + if (sl->master_unit()->first_select()->linkage == DERIVED_TABLE_TYPE) break; // do not look over derived table diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 5e0221ad6c7..4ad49ebec74 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -36,7 +36,8 @@ inline Item * and_items(Item* cond, Item *item) Item_subselect::Item_subselect(): Item_result_field(), engine_owner(1), value_assigned(0), substitution(0), - engine(0), have_to_be_excluded(0), engine_changed(0) + engine(0), used_tables_cache(0), have_to_be_excluded(0), + const_item_cache(1), engine_changed(0) { reset(); /* @@ -146,12 +147,27 @@ void Item_subselect::fix_length_and_dec() engine->fix_length_and_dec(0); } -inline table_map Item_subselect::used_tables() const +table_map Item_subselect::used_tables() const { - return (table_map) (engine->dependent() ? 1L : + return (table_map) (engine->dependent() ? used_tables_cache : (engine->uncacheable() ? RAND_TABLE_BIT : 0L)); } +bool Item_subselect::const_item() const +{ + return engine->uncacheable()? 0 : const_item_cache; +} + +void Item_subselect::update_used_tables() +{ + if (!engine->uncacheable()) + { + // did all used tables become ststic? + if ((used_tables_cache & ~engine->upper_select_const_tables()) == 0) + const_item_cache= 1; + } +} + Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex) :Item_subselect(), value(0) { @@ -1138,3 +1154,29 @@ void subselect_uniquesubquery_engine::exclude() //this never should be called DBUG_ASSERT(0); } + + +table_map subselect_engine::calc_const_tables(TABLE_LIST *table) +{ + table_map map= 0; + for(; table; table= table->next) + { + TABLE *tbl= table->table; + if (tbl && tbl->const_table) + map|= tbl->map; + } + return map; +} + + +table_map subselect_single_select_engine::upper_select_const_tables() +{ + return calc_const_tables((TABLE_LIST *) select_lex->outer_select()-> + table_list.first); +} + +table_map subselect_union_engine::upper_select_const_tables() +{ + return calc_const_tables((TABLE_LIST *) unit->outer_select()-> + table_list.first); +} diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 312b453a5a2..3a543ff288c 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -41,11 +41,15 @@ protected: /* substitution instead of subselect in case of optimization */ Item *substitution; /* engine that perform execution of subselect (single select or union) */ - subselect_engine *engine; + subselect_engine *engine; + /* cache of used external tables */ + table_map used_tables_cache; /* allowed number of columns (1 for single value subqueries) */ uint max_columns; /* work with 'substitution' */ bool have_to_be_excluded; + /* cache of constante state */ + bool const_item_cache; public: /* changed engine indicator */ @@ -85,6 +89,8 @@ public: bool exec(); virtual void fix_length_and_dec(); table_map used_tables() const; + bool const_item() const; + void update_used_tables(); void print(String *str) { if (name) @@ -101,6 +107,8 @@ public: 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 */ @@ -264,6 +272,8 @@ public: 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 *); }; @@ -285,6 +295,7 @@ public: bool dependent(); bool uncacheable(); void exclude(); + table_map upper_select_const_tables(); }; @@ -302,6 +313,7 @@ public: bool dependent(); bool uncacheable(); void exclude(); + table_map upper_select_const_tables(); }; @@ -328,6 +340,7 @@ public: bool dependent() { return 1; } bool uncacheable() { return 1; } void exclude(); + table_map upper_select_const_tables() { return 0; } }; From b04af449235b495dbfc775f542f320b4fd7fe3c4 Mon Sep 17 00:00:00 2001 From: "hf@deer.(none)" <> Date: Tue, 21 Oct 2003 16:05:17 +0500 Subject: [PATCH 2/4] Fix for Windows bug reported throuhg Miguel --- libmysqld/lib_sql.cc | 5 ----- sql/derror.cc | 13 +++++++------ sql/init.cc | 2 ++ sql/mysql_priv.h | 6 +++++- sql/mysqld.cc | 15 ++++++++++----- 5 files changed, 24 insertions(+), 17 deletions(-) diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index c9f98a701ef..d4cb916a89c 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -435,11 +435,6 @@ void STDCALL mysql_server_end() my_free((char*) copy_arguments_ptr, MYF(MY_ALLOW_ZERO_PTR)); copy_arguments_ptr=0; clean_up(0); -#ifdef THREAD - /* Don't call my_thread_end() if the application is using MY_INIT() */ - if (!org_my_init_done) - my_thread_end(); -#endif /* If library called my_init(), free memory allocated by it */ if (!org_my_init_done) my_end(0); diff --git a/sql/derror.cc b/sql/derror.cc index 78efdcc33f3..7f4068c487e 100644 --- a/sql/derror.cc +++ b/sql/derror.cc @@ -20,27 +20,28 @@ #include "mysql_priv.h" #include "mysys_err.h" -static void read_texts(const char *file_name,const char ***point, +static bool read_texts(const char *file_name,const char ***point, uint error_messages); static void init_myfunc_errs(void); /* Read messages from errorfile */ -void init_errmessage(void) +bool init_errmessage(void) { DBUG_ENTER("init_errmessage"); - read_texts(ERRMSG_FILE,&my_errmsg[ERRMAPP],ER_ERROR_MESSAGES); + if (read_texts(ERRMSG_FILE,&my_errmsg[ERRMAPP],ER_ERROR_MESSAGES)) + DBUG_RETURN(TRUE); errmesg=my_errmsg[ERRMAPP]; /* Init global variabel */ init_myfunc_errs(); /* Init myfunc messages */ - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } /* Read text from packed textfile in language-directory */ /* If we can't read messagefile then it's panic- we can't continue */ -static void read_texts(const char *file_name,const char ***point, +static bool read_texts(const char *file_name,const char ***point, uint error_messages) { register uint i; @@ -116,7 +117,7 @@ Check that the above file is the right version for this program!", point[i]= *point +uint2korr(head+10+i+i); } VOID(my_close(file,MYF(0))); - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); err: switch (funktpos) { diff --git a/sql/init.cc b/sql/init.cc index 50d504068a0..8b15fef4ee3 100644 --- a/sql/init.cc +++ b/sql/init.cc @@ -37,7 +37,9 @@ void unireg_init(ulong options) #ifdef USE_MY_ATOF init_my_atof(); /* use our atof */ #endif +#ifndef EMBEDDED_LIBRARY my_abort_hook=unireg_abort; /* Abort with close of databases */ +#endif VOID(strmov(reg_ext,".frm")); for (i=0 ; i < 6 ; i++) // YYMMDDHHMMSS diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 6c1f7bfa472..f30702afcc2 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -725,7 +725,7 @@ void key_restore(TABLE *form,byte *key,uint index,uint key_length); int key_cmp(TABLE *form,const byte *key,uint index,uint key_length); void key_unpack(String *to,TABLE *form,uint index); bool check_if_key_used(TABLE *table, uint idx, List &fields); -void init_errmessage(void); +bool init_errmessage(void); void sql_perror(const char *message); void sql_print_error(const char *format,...) @@ -919,7 +919,11 @@ void calc_time_from_sec(TIME *to, long seconds, long microseconds); int test_if_number(char *str,int *res,bool allow_wildcards); void change_byte(byte *,uint,char,char); +#ifndef EMBEDDED_LIBRARY extern "C" void unireg_abort(int exit_code); +#else +#define unireg_abort(exit_code) DBUG_RETURN(exit_code) +#endif void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form, SQL_SELECT *select, int use_record_cache, bool print_errors); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 812a5b28ff7..d2c04f634f9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -845,6 +845,7 @@ extern "C" sig_handler print_signal_warning(int sig) (Mac OS X) we have to call exit() instead if pthread_exit(). */ +#ifndef EMBEDDED_LIBRARY void unireg_end(void) { clean_up(1); @@ -856,7 +857,6 @@ void unireg_end(void) #endif } - extern "C" void unireg_abort(int exit_code) { DBUG_ENTER("unireg_abort"); @@ -868,7 +868,7 @@ extern "C" void unireg_abort(int exit_code) my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); exit(exit_code); /* purecov: inspected */ } - +#endif void clean_up(bool print_message) { @@ -1015,6 +1015,7 @@ static void set_ports() } } +#ifndef EMBEDDED_LIBRARY /* Change to run as another user if started with --user */ static void set_user(const char *user) @@ -1097,7 +1098,6 @@ static void set_root(const char *path) #endif } - static void server_init(void) { struct sockaddr_in IPaddr; @@ -1248,6 +1248,7 @@ static void server_init(void) DBUG_VOID_RETURN; } +#endif /*!EMBEDDED_LIBRARY*/ void yyerror(const char *s) { @@ -2081,7 +2082,8 @@ static int init_common_variables(const char *conf_file_name, int argc, open_files_limit= 0; /* Can't set or detect limit */ #endif unireg_init(opt_specialflag); /* Set up extern variabels */ - init_errmessage(); /* Read error messages from file */ + if (init_errmessage()) /* Read error messages from file */ + return 1; init_client_errs(); lex_init(); item_init(); @@ -2188,6 +2190,7 @@ static void init_ssl() static int init_server_components() { + DBUG_ENTER("init_server_components"); table_cache_init(); hostname_cache_init(); query_cache_result_size_limit(query_cache_limit); @@ -2279,7 +2282,7 @@ Now disabling --log-slave-updates."); init_max_user_conn(); init_update_queries(); - return 0; + DBUG_RETURN(0); } @@ -5537,8 +5540,10 @@ static void get_options(int argc,char **argv) /* Set global MyISAM variables from delay_key_write_options */ fix_delay_key_write((THD*) 0, OPT_GLOBAL); +#ifndef EMBEDDED_LIBRARY if (mysqld_chroot) set_root(mysqld_chroot); +#endif fix_paths(); /* From b0bd7f80be30f049facfc9b8d465c5717a554179 Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Thu, 23 Oct 2003 20:50:53 +0300 Subject: [PATCH 3/4] ufter review fix (BUG#1444) --- sql/item.cc | 27 +++++++++++++++------------ sql/item_subselect.cc | 12 ++++++++---- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index 970a92992ed..42753750c17 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -829,12 +829,14 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) // it is primary INSERT st_select_lex => skip first table resolving table_list= table_list->next; } + + Item_subselect *prev_subselect_item= prev_unit->item; if ((tmp= find_field_in_tables(thd, this, table_list, &where, 0)) != not_found_field) { - prev_unit->item->used_tables_cache|= tmp->table->map; - prev_unit->item->const_item_cache= 0; + prev_subselect_item->used_tables_cache|= tmp->table->map; + prev_subselect_item->const_item_cache= 0; break; } if (sl->resolve_mode == SELECT_LEX::SELECT_MODE && @@ -844,15 +846,15 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { if (*refer && (*refer)->fixed) // Avoid crash in case of error { - prev_unit->item->used_tables_cache|= (*refer)->used_tables(); - prev_unit->item->const_item_cache&= (*refer)->const_item(); + prev_subselect_item->used_tables_cache|= (*refer)->used_tables(); + prev_subselect_item->const_item_cache&= (*refer)->const_item(); } break; } // Reference is not found => depend from outer (or just error) - prev_unit->item->used_tables_cache|= OUTER_REF_TABLE_BIT; - prev_unit->item->const_item_cache= 0; + prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT; + prev_subselect_item->const_item_cache= 0; if (sl->master_unit()->first_select()->linkage == DERIVED_TABLE_TYPE) @@ -1401,6 +1403,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) for ( ; sl ; sl= (prev_unit= sl->master_unit())->outer_select()) { last= sl; + Item_subselect *prev_subselect_item= prev_unit->item; if (sl->resolve_mode == SELECT_LEX::SELECT_MODE && (ref= find_item_in_list(this, sl->item_list, &counter, @@ -1409,8 +1412,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) { if (*ref && (*ref)->fixed) // Avoid crash in case of error { - prev_unit->item->used_tables_cache|= (*ref)->used_tables(); - prev_unit->item->const_item_cache&= (*ref)->const_item(); + prev_subselect_item->used_tables_cache|= (*ref)->used_tables(); + prev_subselect_item->const_item_cache&= (*ref)->const_item(); } break; } @@ -1424,14 +1427,14 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) table_list, &where, 0)) != not_found_field) { - prev_unit->item->used_tables_cache|= tmp->table->map; - prev_unit->item->const_item_cache= 0; + prev_subselect_item->used_tables_cache|= tmp->table->map; + prev_subselect_item->const_item_cache= 0; break; } // Reference is not found => depend from outer (or just error) - prev_unit->item->used_tables_cache|= OUTER_REF_TABLE_BIT; - prev_unit->item->const_item_cache= 0; + prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT; + prev_subselect_item->const_item_cache= 0; if (sl->master_unit()->first_select()->linkage == DERIVED_TABLE_TYPE) diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 4ad49ebec74..704681dd511 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -112,6 +112,11 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref) } fix_length_and_dec(); } + if (engine->uncacheable()) + { + const_item_cache= 0; + used_tables_cache|= RAND_TABLE_BIT; + } fixed= 1; thd->where= save_where; return res; @@ -149,13 +154,12 @@ void Item_subselect::fix_length_and_dec() table_map Item_subselect::used_tables() const { - return (table_map) (engine->dependent() ? used_tables_cache : - (engine->uncacheable() ? RAND_TABLE_BIT : 0L)); + return (table_map) (engine->dependent() ? used_tables_cache : 0L); } bool Item_subselect::const_item() const { - return engine->uncacheable()? 0 : const_item_cache; + return const_item_cache; } void Item_subselect::update_used_tables() @@ -163,7 +167,7 @@ void Item_subselect::update_used_tables() if (!engine->uncacheable()) { // did all used tables become ststic? - if ((used_tables_cache & ~engine->upper_select_const_tables()) == 0) + if ((used_tables_cache & ~engine->upper_select_const_tables())) const_item_cache= 1; } } From 6457b89948c034aa7a65407555d2db73e9ab56fb Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Thu, 23 Oct 2003 23:54:21 +0300 Subject: [PATCH 4/4] added check of cardinality to IN/ALL/ANY subquery transformer (BUG#1638) --- mysql-test/r/subselect.result | 7 +++++++ mysql-test/t/subselect.test | 11 +++++++++++ sql/item_subselect.cc | 17 ++++++++++++----- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index aa3c1a8f5cd..110db3cfa13 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1457,3 +1457,10 @@ dbid name -1 Valid -1 Valid 2 drop table t1,t2,t3,t4; +CREATE TABLE t1 (id int(11) default NULL) TYPE=MyISAM CHARSET=latin1; +INSERT INTO t1 VALUES (1),(5); +CREATE TABLE t2 (id int(11) default NULL) TYPE=MyISAM CHARSET=latin1; +INSERT INTO t2 VALUES (2),(6); +select * from t1 where (1,2,6) in (select * from t2); +ERROR 21000: Operand should contain 3 column(s) +DROP TABLE t1,t2; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 79ac7d82c61..48c87f6cbd3 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -981,3 +981,14 @@ INSERT INTO `t4` (`task_id`, `description`) VALUES (1, 'Daily Check List'),(2, ' select dbid, name, (date_format(now() , '%Y-%m-%d') - INTERVAL how_often DAY) >= ifnull((SELECT date_format(max(create_date),'%Y-%m-%d') FROM t1 WHERE dbid = b.db_id AND taskid = a.taskgenid), '1950-01-01') from t3 a, t2 b, t4 WHERE dbid = - 1 AND primary_uid = '1' AND t4.task_id = taskid; SELECT dbid, name FROM t3 a, t2 b, t4 WHERE dbid = - 1 AND primary_uid = '1' AND ((date_format(now() , '%Y-%m-%d') - INTERVAL how_often DAY) >= ifnull((SELECT date_format(max(create_date),'%Y-%m-%d') FROM t1 WHERE dbid = b.db_id AND taskid = a.taskgenid), '1950-01-01')) AND t4.task_id = taskid; drop table t1,t2,t3,t4; + +# +# cardinality check +# +CREATE TABLE t1 (id int(11) default NULL) TYPE=MyISAM CHARSET=latin1; +INSERT INTO t1 VALUES (1),(5); +CREATE TABLE t2 (id int(11) default NULL) TYPE=MyISAM CHARSET=latin1; +INSERT INTO t2 VALUES (2),(6); +-- error 1240 +select * from t1 where (1,2,6) in (select * from t2); +DROP TABLE t1,t2; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 704681dd511..6ac191af267 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -514,6 +514,12 @@ Item_in_subselect::single_value_transformer(JOIN *join, THD *thd= join->thd; thd->where= "scalar IN/ALL/ANY subquery"; + if (select_lex->item_list.elements > 1) + { + my_error(ER_OPERAND_COLUMNS, MYF(0), 1); + DBUG_RETURN(RES_ERROR); + } + if ((abort_on_null || (upper_not && upper_not->top_level())) && !select_lex->master_unit()->dependent && (func == &Item_bool_func2::gt_creator || @@ -606,11 +612,6 @@ Item_in_subselect::single_value_transformer(JOIN *join, select_lex->dependent= 1; Item *item; - if (select_lex->item_list.elements > 1) - { - my_error(ER_OPERAND_COLUMNS, MYF(0), 1); - DBUG_RETURN(RES_ERROR); - } item= (Item*) select_lex->item_list.head(); @@ -710,6 +711,12 @@ Item_in_subselect::row_value_transformer(JOIN *join, SELECT_LEX *select_lex= join->select_lex; + if (select_lex->item_list.elements != left_expr->cols()) + { + my_error(ER_OPERAND_COLUMNS, MYF(0), left_expr->cols()); + DBUG_RETURN(RES_ERROR); + } + if (!substitution) { //first call for this unit