diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 2 | ||||
-rw-r--r-- | sql/item.h | 1 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 37 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 21 | ||||
-rw-r--r-- | sql/item_subselect.cc | 28 | ||||
-rw-r--r-- | sql/item_subselect.h | 1 | ||||
-rw-r--r-- | sql/mysqld.cc | 12 | ||||
-rw-r--r-- | sql/protocol.cc | 2 | ||||
-rw-r--r-- | sql/set_var.cc | 88 | ||||
-rw-r--r-- | sql/set_var.h | 28 | ||||
-rw-r--r-- | sql/sql_class.cc | 1 | ||||
-rw-r--r-- | sql/sql_class.h | 8 | ||||
-rw-r--r-- | sql/sql_lex.cc | 55 | ||||
-rw-r--r-- | sql/sql_lex.h | 8 | ||||
-rw-r--r-- | sql/sql_parse.cc | 11 | ||||
-rw-r--r-- | sql/sql_select.cc | 5 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 29 |
17 files changed, 229 insertions, 108 deletions
diff --git a/sql/item.cc b/sql/item.cc index 2e9866fcd58..2bb9fa62ff4 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -172,7 +172,7 @@ bool Item::get_time(TIME *ltime) CHARSET_INFO * Item::default_charset() const { - return current_thd->variables.connection_collation; + return current_thd->variables.collation_connection; } bool Item::set_charset(CHARSET_INFO *cs1, enum coercion co1, diff --git a/sql/item.h b/sql/item.h index 6a7ebd506ac..4862ad21fbe 100644 --- a/sql/item.h +++ b/sql/item.h @@ -603,6 +603,7 @@ public: item(it) {} bool fix_fields(THD *, struct st_table_list *, Item ** ref); + Item **storage() {return &item;} }; /* diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index ac2d0b4f847..0f21cf5a774 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1781,6 +1781,43 @@ longlong Item_func_isnull::val_int() return args[0]->is_null() ? 1: 0; } +longlong Item_is_not_null_test::val_int() +{ + DBUG_ENTER("Item_is_not_null_test::val_int"); + if (!used_tables_cache) + { + owner->was_null|= (!cached_value); + DBUG_PRINT("info", ("cached :%d", cached_value)); + DBUG_RETURN(cached_value); + } + if (args[0]->is_null()) + { + DBUG_PRINT("info", ("null")) + owner->was_null|= 1; + DBUG_RETURN(0); + } + else + DBUG_RETURN(1); +} + +/* Optimize case of not_null_column IS NULL */ +void Item_is_not_null_test::update_used_tables() +{ + if (!args[0]->maybe_null) + { + used_tables_cache= 0; /* is always true */ + cached_value= (longlong) 1; + } + else + { + args[0]->update_used_tables(); + if (!(used_tables_cache=args[0]->used_tables())) + { + /* Remember if the value is always NULL or never NULL */ + cached_value= (longlong) !args[0]->is_null(); + } + } +} longlong Item_func_isnotnull::val_int() { diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index e7670755396..5e246e3e285 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -648,6 +648,7 @@ class Item_func_in :public Item_int_func class Item_func_isnull :public Item_bool_func { +protected: longlong cached_value; public: Item_func_isnull(Item *a) :Item_bool_func(a) {} @@ -656,11 +657,11 @@ public: void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=0; - Item_func_isnull::update_used_tables(); + update_used_tables(); } const char *func_name() const { return "isnull"; } /* Optimize case of not_null_column IS NULL */ - void update_used_tables() + virtual void update_used_tables() { if (!args[0]->maybe_null) { @@ -680,6 +681,22 @@ public: optimize_type select_optimize() const { return OPTIMIZE_NULL; } }; +/* Functions used by HAVING for rewriting IN subquery */ + +class Item_in_subselect; +class Item_is_not_null_test :public Item_func_isnull +{ + Item_in_subselect* owner; +public: + Item_is_not_null_test(Item_in_subselect* ow, Item *a) + :Item_func_isnull(a), owner(ow) + {} + longlong val_int(); + const char *func_name() const { return "is_not_null_test"; } + void update_used_tables(); +}; + + class Item_func_isnotnull :public Item_bool_func { public: diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 76451680b59..6c0b799b4de 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -508,9 +508,31 @@ void Item_in_subselect::single_value_transformer(THD *thd, sl->item_list.push_back(new Item_int("Not_used", (longlong) 1, 21)); if (sl->table_list.elements) { - item= (*func)(expr, new Item_asterisk_remover(this, item, - (char *)"<no matter>", - (char*)"<result>")); + Item *having= item, *isnull= item; + if (item->type() == Item::FIELD_ITEM && + ((Item_field*) item)->field_name[0] == '*') + { + Item_asterisk_remover *remover; + item= remover= new Item_asterisk_remover(this, item, + (char*)"<no matter>", + (char*)"<result>"); + having= + new Item_is_not_null_test(this, + new Item_ref(remover->storage(), + (char*)"<no matter>", + (char*)"<null test>")); + isnull= + new Item_is_not_null_test(this, + new Item_ref(remover->storage(), + (char*)"<no matter>", + (char*)"<null test>")); + } + having= new Item_is_not_null_test(this, having); + sl->having= (sl->having ? + new Item_cond_and(having, sl->having) : + having); + item= new Item_cond_or((*func)(expr, item), + new Item_func_isnull(isnull)); sl->where= and_items(sl->where, item); } else diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 351c4af7f33..fc4dad5a6b3 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -183,6 +183,7 @@ public: friend class Item_asterisk_remover; friend class Item_ref_null_helper; + friend class Item_is_not_null_test; }; /* ALL/ANY/SOME subselect */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f04ca371c60..ea0311bafc6 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2092,9 +2092,9 @@ static int init_common_variables(const char *conf_file_name, int argc, #endif if (!(default_charset_info= get_charset_by_name(sys_charset.value, MYF(MY_WME)))) return 1; - global_system_variables.result_collation= default_charset_info; - global_system_variables.client_collation= default_charset_info; - global_system_variables.connection_collation= default_charset_info; + global_system_variables.collation_results= default_charset_info; + global_system_variables.collation_client= default_charset_info; + global_system_variables.collation_connection= default_charset_info; charsets_list= list_charsets(MYF(MY_CS_COMPILED | MY_CS_CONFIG)); @@ -4575,9 +4575,9 @@ static void set_options(void) sizeof(mysql_real_data_home)-1); /* Set default values for some variables */ - global_system_variables.result_collation= default_charset_info; - global_system_variables.client_collation= default_charset_info; - global_system_variables.connection_collation= default_charset_info; + global_system_variables.collation_results= default_charset_info; + global_system_variables.collation_client= default_charset_info; + global_system_variables.collation_connection= default_charset_info; global_system_variables.table_type= DB_TYPE_MYISAM; global_system_variables.tx_isolation= ISO_REPEATABLE_READ; global_system_variables.select_limit= (ulonglong) HA_POS_ERROR; diff --git a/sql/protocol.cc b/sql/protocol.cc index 99b815a7840..d00ecb5dbc4 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -724,7 +724,7 @@ bool Protocol_simple::store(const char *from, uint length, bool Protocol_simple::store(const char *from, uint length, CHARSET_INFO *fromcs) { - CHARSET_INFO *tocs= this->thd->variables.result_collation; + CHARSET_INFO *tocs= this->thd->variables.collation_results; #ifndef DEBUG_OFF DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_DECIMAL || diff --git a/sql/set_var.cc b/sql/set_var.cc index 46fc35e11cf..d39a506c82d 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -105,12 +105,13 @@ sys_var_str sys_charset("character_set", sys_check_charset, sys_update_charset, sys_set_default_charset); -sys_var_client_collation sys_client_collation("client_collation"); +sys_var_collation_client sys_collation_client("collation_client"); +sys_var_collation_connection sys_collation_connection("collation_connection"); +sys_var_collation_results sys_collation_results("collation_results"); sys_var_bool_ptr sys_concurrent_insert("concurrent_insert", &myisam_concurrent_insert); sys_var_long_ptr sys_connect_timeout("connect_timeout", &connect_timeout); -sys_var_connection_collation sys_connection_collation("connection_collation"); sys_var_enum sys_delay_key_write("delay_key_write", &delay_key_write_options, &delay_key_write_typelib, @@ -200,7 +201,6 @@ sys_var_thd_ulong sys_read_buff_size("read_buffer_size", &SV::read_buff_size); sys_var_thd_ulong sys_read_rnd_buff_size("read_rnd_buffer_size", &SV::read_rnd_buff_size); -sys_var_result_collation sys_result_collation("result_collation"); sys_var_long_ptr sys_rpl_recovery_rank("rpl_recovery_rank", &rpl_recovery_rank); sys_var_long_ptr sys_query_cache_size("query_cache_size", @@ -343,10 +343,11 @@ sys_var *sys_variables[]= &sys_binlog_cache_size, &sys_buffer_results, &sys_bulk_insert_buff_size, - &sys_client_collation, + &sys_collation_client, + &sys_collation_connection, + &sys_collation_results, &sys_concurrent_insert, &sys_connect_timeout, - &sys_connection_collation, &sys_default_week_format, &sys_delay_key_write, &sys_delayed_insert_limit, @@ -406,7 +407,6 @@ sys_var *sys_variables[]= &sys_rand_seed2, &sys_read_buff_size, &sys_read_rnd_buff_size, - &sys_result_collation, &sys_rpl_recovery_rank, &sys_safe_updates, &sys_select_limit, @@ -455,10 +455,11 @@ struct show_var_st init_vars[]= { {sys_bulk_insert_buff_size.name,(char*) &sys_bulk_insert_buff_size,SHOW_SYS}, {sys_charset.name, (char*) &sys_charset, SHOW_SYS}, {"character_sets", (char*) &charsets_list, SHOW_CHAR_PTR}, - {sys_client_collation.name, (char*) &sys_client_collation, SHOW_SYS}, + {sys_collation_client.name, (char*) &sys_collation_client, SHOW_SYS}, + {sys_collation_connection.name,(char*) &sys_collation_connection, SHOW_SYS}, + {sys_collation_results.name, (char*) &sys_collation_results, SHOW_SYS}, {sys_concurrent_insert.name,(char*) &sys_concurrent_insert, SHOW_SYS}, {sys_connect_timeout.name, (char*) &sys_connect_timeout, SHOW_SYS}, - {sys_connection_collation.name,(char*) &sys_connection_collation, SHOW_SYS}, {"datadir", mysql_real_data_home, SHOW_CHAR}, {"default_week_format", (char*) &sys_default_week_format, SHOW_SYS}, {sys_delay_key_write.name, (char*) &sys_delay_key_write, SHOW_SYS}, @@ -562,7 +563,6 @@ struct show_var_st init_vars[]= { {sys_pseudo_thread_id.name, (char*) &sys_pseudo_thread_id, SHOW_SYS}, {sys_read_buff_size.name, (char*) &sys_read_buff_size, SHOW_SYS}, {sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS}, - {sys_result_collation.name, (char*) &sys_result_collation, SHOW_SYS}, {sys_rpl_recovery_rank.name,(char*) &sys_rpl_recovery_rank, SHOW_SYS}, #ifdef HAVE_QUERY_CACHE {sys_query_cache_limit.name,(char*) &sys_query_cache_limit, SHOW_SYS}, @@ -1210,86 +1210,80 @@ bool sys_var_collation::check(THD *thd, set_var *var) return 0; } -bool sys_var_client_collation::update(THD *thd, set_var *var) +bool sys_var_collation_client::update(THD *thd, set_var *var) { if (var->type == OPT_GLOBAL) - global_system_variables.client_collation= var->save_result.charset; + global_system_variables.collation_client= var->save_result.charset; else - { - thd->variables.client_collation= var->save_result.charset; - thd->protocol_simple.init(thd); - thd->protocol_prep.init(thd); - } + thd->variables.collation_client= var->save_result.charset; return 0; } -byte *sys_var_client_collation::value_ptr(THD *thd, enum_var_type type) +byte *sys_var_collation_client::value_ptr(THD *thd, enum_var_type type) { CHARSET_INFO *cs= ((type == OPT_GLOBAL) ? - global_system_variables.client_collation : - thd->variables.client_collation); + global_system_variables.collation_client : + thd->variables.collation_client); return cs ? (byte*) cs->name : (byte*) ""; } -void sys_var_client_collation::set_default(THD *thd, enum_var_type type) +void sys_var_collation_client::set_default(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) - global_system_variables.client_collation= default_charset_info; + global_system_variables.collation_client= default_charset_info; else - { - thd->variables.client_collation= global_system_variables.client_collation; - } + thd->variables.collation_client= global_system_variables.collation_client; } -bool sys_var_connection_collation::update(THD *thd, set_var *var) +bool sys_var_collation_connection::update(THD *thd, set_var *var) { if (var->type == OPT_GLOBAL) - global_system_variables.connection_collation= var->save_result.charset; + global_system_variables.collation_connection= var->save_result.charset; else - thd->variables.connection_collation= var->save_result.charset; + thd->variables.collation_connection= var->save_result.charset; return 0; } -byte *sys_var_connection_collation::value_ptr(THD *thd, enum_var_type type) +byte *sys_var_collation_connection::value_ptr(THD *thd, enum_var_type type) { CHARSET_INFO *cs= ((type == OPT_GLOBAL) ? - global_system_variables.connection_collation : - thd->variables.connection_collation); + global_system_variables.collation_connection : + thd->variables.collation_connection); return cs ? (byte*) cs->name : (byte*) ""; } -void sys_var_connection_collation::set_default(THD *thd, enum_var_type type) +void sys_var_collation_connection::set_default(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) - global_system_variables.connection_collation= default_charset_info; + global_system_variables.collation_connection= default_charset_info; else - thd->variables.connection_collation= global_system_variables.connection_collation; + thd->variables.collation_connection= global_system_variables.collation_connection; } -bool sys_var_result_collation::update(THD *thd, set_var *var) +bool sys_var_collation_results::update(THD *thd, set_var *var) { if (var->type == OPT_GLOBAL) - global_system_variables.result_collation= var->save_result.charset; + global_system_variables.collation_results= var->save_result.charset; else - thd->variables.result_collation= var->save_result.charset; + thd->variables.collation_results= var->save_result.charset; return 0; } -byte *sys_var_result_collation::value_ptr(THD *thd, enum_var_type type) +byte *sys_var_collation_results::value_ptr(THD *thd, enum_var_type type) { CHARSET_INFO *cs= ((type == OPT_GLOBAL) ? - global_system_variables.result_collation : - thd->variables.result_collation); + global_system_variables.collation_results : + thd->variables.collation_results); return cs ? (byte*) cs->name : (byte*) ""; } -void sys_var_result_collation::set_default(THD *thd, enum_var_type type) +void sys_var_collation_results::set_default(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) - global_system_variables.result_collation= default_charset_info; + global_system_variables.collation_results= default_charset_info; else - thd->variables.result_collation= global_system_variables.result_collation; + thd->variables.collation_results= global_system_variables.collation_results; } @@ -1297,16 +1291,16 @@ void sys_var_result_collation::set_default(THD *thd, enum_var_type type) Functions to handle SET NAMES and SET CHARACTER SET *****************************************************************************/ -int set_var_client_collation::check(THD *thd) +int set_var_collation_client::check(THD *thd) { return 0; } -int set_var_client_collation::update(THD *thd) +int set_var_collation_client::update(THD *thd) { - thd->variables.client_collation= client_collation; - thd->variables.connection_collation= connection_collation; - thd->variables.result_collation= result_collation; + thd->variables.collation_client= collation_client; + thd->variables.collation_connection= collation_connection; + thd->variables.collation_results= collation_results; thd->protocol_simple.init(thd); thd->protocol_prep.init(thd); return 0; diff --git a/sql/set_var.h b/sql/set_var.h index f236f8f850c..fbd20228d24 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -420,28 +420,28 @@ SHOW_TYPE type() { return SHOW_CHAR; } virtual void set_default(THD *thd, enum_var_type type)= 0; }; -class sys_var_client_collation :public sys_var_collation +class sys_var_collation_client :public sys_var_collation { public: - sys_var_client_collation(const char *name_arg) :sys_var_collation(name_arg) {} + sys_var_collation_client(const char *name_arg) :sys_var_collation(name_arg) {} bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); byte *value_ptr(THD *thd, enum_var_type type); }; -class sys_var_connection_collation :public sys_var_collation +class sys_var_collation_connection :public sys_var_collation { public: - sys_var_connection_collation(const char *name_arg) :sys_var_collation(name_arg) {} + sys_var_collation_connection(const char *name_arg) :sys_var_collation(name_arg) {} bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); byte *value_ptr(THD *thd, enum_var_type type); }; -class sys_var_result_collation :public sys_var_collation +class sys_var_collation_results :public sys_var_collation { public: - sys_var_result_collation(const char *name_arg) :sys_var_collation(name_arg) {} + sys_var_collation_results(const char *name_arg) :sys_var_collation(name_arg) {} bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); byte *value_ptr(THD *thd, enum_var_type type); @@ -553,18 +553,18 @@ public: /* For SET NAMES and SET CHARACTER SET */ -class set_var_client_collation: public set_var_base +class set_var_collation_client: public set_var_base { - CHARSET_INFO *client_collation; - CHARSET_INFO *connection_collation; - CHARSET_INFO *result_collation; + CHARSET_INFO *collation_client; + CHARSET_INFO *collation_connection; + CHARSET_INFO *collation_results; public: - set_var_client_collation(CHARSET_INFO *client_coll_arg, + set_var_collation_client(CHARSET_INFO *client_coll_arg, CHARSET_INFO *connection_coll_arg, CHARSET_INFO *result_coll_arg) - :client_collation(client_coll_arg), - connection_collation(connection_coll_arg), - result_collation(result_coll_arg) + :collation_client(client_coll_arg), + collation_connection(connection_coll_arg), + collation_results(result_coll_arg) {} int check(THD *thd); int update(THD *thd); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 31159dc259f..f579b02ee50 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -207,7 +207,6 @@ void THD::init(void) { pthread_mutex_lock(&LOCK_global_system_variables); variables= global_system_variables; - variables.client_collation= default_charset_info; pthread_mutex_unlock(&LOCK_global_system_variables); server_status= SERVER_STATUS_AUTOCOMMIT; options= thd_startup_options; diff --git a/sql/sql_class.h b/sql/sql_class.h index 58f27bf2bcb..d3cb843ad85 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -382,9 +382,9 @@ struct system_variables my_bool low_priority_updates; my_bool new_mode; - CHARSET_INFO *client_collation; - CHARSET_INFO *connection_collation; - CHARSET_INFO *result_collation; + CHARSET_INFO *collation_client; + CHARSET_INFO *collation_connection; + CHARSET_INFO *collation_results; }; void free_tmp_table(THD *thd, TABLE *entry); @@ -665,7 +665,7 @@ public: net.report_error= 1; DBUG_PRINT("error",("Fatal error set")); } - inline CHARSET_INFO *charset() { return variables.client_collation; } + inline CHARSET_INFO *charset() { return variables.collation_client; } }; /* diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index d5d438fc3a1..d88908d9e0f 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1203,23 +1203,60 @@ TABLE_LIST *st_select_lex_node::add_table_to_list(THD *thd, Table_ident *table, } ulong st_select_lex_node::get_table_join_options() { return 0; } -/* - This is used for UNION & subselect to create a new table list of all used - tables. - The table_list->table entry in all used tables are set to point - to the entries in this list. -*/ -// interface +/* + Interface method of table list creation for query + + SYNOPSIS + st_select_lex_unit::create_total_list() + thd THD pointer + result pointer on result list of tables pointer + check_derived force derived table chacking (used for creating + table list for derived query) + DESCRIPTION + This is used for UNION & subselect to create a new table list of all used + tables. + The table_list->table entry in all used tables are set to point + to the entries in this list. + + RETURN + 0 - OK + !0 - error +*/ bool st_select_lex_unit::create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result, bool check_derived) { *result= 0; - return create_total_list_n_last_return(thd, lex, &result, check_derived); + for (SELECT_LEX_UNIT *unit= this; unit; unit= unit->next_unit()) + { + if ((res= unit->create_total_list_n_last_return(thd, lex, &result, + check_derived))) + return res; + } + return 0; } -// list creator +/* + Table list creation for query + + SYNOPSIS + st_select_lex_unit::create_total_list() + thd THD pointer + lex pointer on LEX stricture + result pointer on pointer on result list of tables pointer + check_derived force derived table chacking (used for creating + table list for derived query) + DESCRIPTION + This is used for UNION & subselect to create a new table list of all used + tables. + The table_list->table entry in all used tables are set to point + to the entries in this list. + + RETURN + 0 - OK + !0 - error +*/ bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex, TABLE_LIST ***result, bool check_derived) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 9fb0f8cfdf5..75ec2f2d3fb 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -230,6 +230,7 @@ public: virtual st_select_lex_unit* master_unit()= 0; virtual st_select_lex* outer_select()= 0; + virtual st_select_lex_node* return_after_parsing()= 0; virtual bool set_braces(bool value); virtual bool inc_in_sum_expr(); @@ -284,6 +285,8 @@ public: global parameters for union */ st_select_lex_node *global_parameters; + //node on wich we should return current_select pointer after parsing subquery + st_select_lex_node *return_to; /* LIMIT clause runtime counters */ ha_rows select_limit_cnt, offset_limit_cnt; /* not NULL if union used in subselect, point to subselect item */ @@ -304,6 +307,7 @@ public: (st_select_lex*) slave->next : (st_select_lex*) slave; } st_select_lex_unit* next_unit() { return (st_select_lex_unit*) next; } + st_select_lex_node* return_after_parsing() { return return_to; } void exclude_level(); /* UNION methods */ @@ -366,6 +370,10 @@ public: { return &link_next; } + st_select_lex_node* return_after_parsing() + { + return master_unit()->return_after_parsing(); + } bool set_braces(bool value); bool inc_in_sum_expr(); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2f4915c74f1..d0a970c98b7 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3235,7 +3235,8 @@ mysql_init_query(THD *thd) lex->select_lex.init_query(); lex->value_list.empty(); lex->param_list.empty(); - lex->unit.next= lex->unit.master= lex->unit.link_next= 0; + lex->unit.next= lex->unit.master= lex->unit.return_to= + lex->unit.link_next= 0; lex->unit.prev= lex->unit.link_prev= 0; lex->unit.global_parameters= lex->unit.slave= lex->current_select= lex->all_selects_list= &lex->select_lex; @@ -3283,9 +3284,9 @@ bool mysql_new_select(LEX *lex, bool move_down) { SELECT_LEX *select_lex = new SELECT_LEX(); - select_lex->select_number= ++lex->thd->select_number; if (!select_lex) return 1; + select_lex->select_number= ++lex->thd->select_number; select_lex->init_query(); select_lex->init_select(); if (move_down) @@ -3297,9 +3298,13 @@ mysql_new_select(LEX *lex, bool move_down) unit->init_query(); unit->init_select(); unit->thd= lex->thd; - unit->include_down(lex->current_select); + if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE) + unit->include_neighbour(lex->current_select); + else + unit->include_down(lex->current_select); unit->link_next= 0; unit->link_prev= 0; + unit->return_to= lex->current_select; select_lex->include_down(unit); } else diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3fdff4e96a4..f2dc2b2afd6 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -299,7 +299,7 @@ JOIN::prepare(Item ***rref_pointer_array, DBUG_RETURN(-1); /* purecov: inspected */ ref_pointer_array= *rref_pointer_array; - + if (having) { thd->where="having clause"; @@ -313,6 +313,7 @@ JOIN::prepare(Item ***rref_pointer_array, if (having->with_sum_func) having->split_sum_func(ref_pointer_array, all_fields); } + if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */ DBUG_RETURN(-1); /* @@ -426,7 +427,7 @@ JOIN::optimize() #ifdef HAVE_REF_TO_FIELDS // Not done yet /* Add HAVING to WHERE if possible */ - if (having && !group_list && ! sum_func_count) + if (having && !group_list && !sum_func_count) { if (!conds) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d312bc5571f..71035a75084 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3924,7 +3924,7 @@ text_literal: TEXT_STRING_literal { THD *thd= YYTHD; - $$ = new Item_string($1.str,$1.length,thd->variables.connection_collation); + $$ = new Item_string($1.str,$1.length,thd->variables.collation_connection); } | NCHAR_STRING { $$= new Item_string($1.str,$1.length,national_charset_info); } @@ -3936,7 +3936,7 @@ text_literal: text_string: TEXT_STRING_literal - { $$= new String($1.str,$1.length,YYTHD->variables.connection_collation); } + { $$= new String($1.str,$1.length,YYTHD->variables.collation_connection); } | HEX_NUM { Item *tmp = new Item_varbinary($1.str,$1.length); @@ -4106,14 +4106,14 @@ TEXT_STRING_literal: TEXT_STRING { THD *thd= YYTHD; - if (my_charset_same(thd->charset(),thd->variables.connection_collation)) + if (my_charset_same(thd->charset(),thd->variables.collation_connection)) { $$=$1; } else { String ident; - ident.copy($1.str,$1.length,thd->charset(),thd->variables.connection_collation); + ident.copy($1.str,$1.length,thd->charset(),thd->variables.collation_connection); $$.str= thd->strmake(ident.ptr(),ident.length()); $$.length= ident.length(); } @@ -4405,28 +4405,27 @@ option_value: { THD *thd= YYTHD; LEX *lex= Lex; - $2= $2 ? $2: global_system_variables.client_collation; + $2= $2 ? $2: global_system_variables.collation_client; $3= $3 ? $3 : $2; if (!my_charset_same($2,$3)) { - net_printf(YYTHD,ER_COLLATION_CHARSET_MISMATCH, - $3->name,$2->csname); - YYABORT; + net_printf(thd,ER_COLLATION_CHARSET_MISMATCH,$3->name,$2->csname); + YYABORT; } - lex->var_list.push_back(new set_var_client_collation($3,thd->db_charset,$3)); + lex->var_list.push_back(new set_var_collation_client($3,thd->db_charset,$3)); } | NAMES_SYM charset_name_or_default opt_collate { + THD *thd= YYTHD; LEX *lex= Lex; - $2= $2 ? $2 : global_system_variables.client_collation; + $2= $2 ? $2 : global_system_variables.collation_client; $3= $3 ? $3 : $2; if (!my_charset_same($2,$3)) { - net_printf(YYTHD,ER_COLLATION_CHARSET_MISMATCH, - $3->name,$2->csname); - YYABORT; + net_printf(thd,ER_COLLATION_CHARSET_MISMATCH,$3->name,$2->csname); + YYABORT; } - lex->var_list.push_back(new set_var_client_collation($3,$3,$3)); + lex->var_list.push_back(new set_var_collation_client($3,$3,$3)); } | PASSWORD equal text_or_password { @@ -5014,5 +5013,5 @@ subselect_end: ')' { LEX *lex=Lex; - lex->current_select = lex->current_select->outer_select(); + lex->current_select = lex->current_select->return_after_parsing(); }; |