summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/item.cc2
-rw-r--r--sql/item.h1
-rw-r--r--sql/item_cmpfunc.cc37
-rw-r--r--sql/item_cmpfunc.h21
-rw-r--r--sql/item_subselect.cc28
-rw-r--r--sql/item_subselect.h1
-rw-r--r--sql/mysqld.cc12
-rw-r--r--sql/protocol.cc2
-rw-r--r--sql/set_var.cc88
-rw-r--r--sql/set_var.h28
-rw-r--r--sql/sql_class.cc1
-rw-r--r--sql/sql_class.h8
-rw-r--r--sql/sql_lex.cc55
-rw-r--r--sql/sql_lex.h8
-rw-r--r--sql/sql_parse.cc11
-rw-r--r--sql/sql_select.cc5
-rw-r--r--sql/sql_yacc.yy29
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();
};