diff --git a/sql/item.cc b/sql/item.cc
index f8404f40421c3bc64bfc700e23dc38d2f2587829..215c7d2424829bc394bf2e56824810547af676d3 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -441,12 +441,11 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
 	cause error ER_NON_UNIQ_ERROR in find_field_in_tables.
       */
       SELECT_LEX *last= 0;
-      for (SELECT_LEX *sl= thd->lex.select->outer_select();
+      for (SELECT_LEX *sl= thd->lex.current_select->outer_select();
 	   sl;
 	   sl= sl->outer_select())
 	if ((tmp= find_field_in_tables(thd, this,
-				       (TABLE_LIST*)
-				       (last= sl)->table_list.first,
+				       (last= sl)->get_table_list(),
 				       0)) != not_found_field)
 	  break;
       if (!tmp)
@@ -464,20 +463,27 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
 	  Mark all selects from resolved to 1 before select where was 
 	  found table as depended (of select where was found table)
 	*/
-	for (SELECT_LEX *s= thd->lex.select;
-	     s &&s != last;
+	for (SELECT_LEX_NODE *s= thd->lex.current_select;
+	     s && s != last;
 	     s= s->outer_select())
-	  if( !s->depended )
+	{
+	  if( !s->dependent)
 	  {
 	    // Select is depended of outer select
-	    s->depended= s->master_unit()->depended= 1;
-	    //Tables will be reopened many times
-	    for (TABLE_LIST *tbl= 
-		   (TABLE_LIST*)s->table_list.first;
-		 tbl;
-		 tbl= tbl->next)
-	      tbl->shared= 1;
+	    s->dependent= 1;
+	    if (s->linkage != GLOBAL_OPTIONS_TYPE)
+	    { 
+              //s is st_select_lex*
+	      
+	      s->master_unit()->dependent= 1;
+	      //Tables will be reopened many times
+	      for (TABLE_LIST *tbl= s->get_table_list();
+		   tbl;
+		   tbl= tbl->next)
+		tbl->shared= 1;
+	    }
 	  }
+	}
       }
     } 
     else if (!tmp)
@@ -822,9 +828,11 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
 {
   if (!ref)
   {
-    SELECT_LEX *sl=thd->lex.select->outer_select();
-    if ((ref= find_item_in_list(this, thd->lex.select->item_list,
-		(sl ? REPORT_EXCEPT_NOT_FOUND : REPORT_ALL_ERRORS))) ==
+    SELECT_LEX *sl= thd->lex.current_select->outer_select();
+    if ((ref= find_item_in_list(this, 
+				*(thd->lex.current_select->get_item_list()),
+				(sl ? REPORT_EXCEPT_NOT_FOUND :
+				 REPORT_ALL_ERRORS))) ==
 	(Item **)not_found_item)
     {
       /*
@@ -850,8 +858,10 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
       else if (ref == (Item **)not_found_item)
       {
 	// Call to report error
-	find_item_in_list(this, thd->lex.select->item_list, REPORT_ALL_ERRORS);
-        ref=0;
+	find_item_in_list(this,
+			  *(thd->lex.current_select->get_item_list()),
+			  REPORT_ALL_ERRORS);
+        ref= 0;
 	return 1;
       }
       else
@@ -861,19 +871,25 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
 	  Mark all selects from resolved to 1 before select where was
 	  found table as depended (of select where was found table)
 	*/
-	for (SELECT_LEX *s= thd->lex.select;
+	for (SELECT_LEX_NODE *s= thd->lex.current_select;
 	     s &&s != last;
 	     s= s->outer_select())
-	  if( !s->depended )
+	  if( !s->dependent )
 	  {
 	    // Select is depended of outer select
-	    s->depended= s->master_unit()->depended= 1;
-	    //Tables will be reopened many times
-	    for (TABLE_LIST *tbl=
-		   (TABLE_LIST*)s->table_list.first;
-		 tbl;
-		 tbl= tbl->next)
-	      tbl->shared= 1;
+	    s->dependent= 1;
+	    if (s->linkage != GLOBAL_OPTIONS_TYPE)
+	    { 
+              //s is st_select_lex*
+
+	      s->master_unit()->dependent= 1;
+	      //Tables will be reopened many times
+	      for (TABLE_LIST *tbl=
+		     s->get_table_list();
+		   tbl;
+		   tbl= tbl->next)
+		tbl->shared= 1;
+	    }
 	  }
       }
     }
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 456ce5f22ba0034108b30f1e30577ef05ab154fd..d0a10e25fa5c689a8b73555200977395b3bf770c 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -252,8 +252,8 @@ int subselect_single_select_engine::prepare()
   if (prepared)
     return 0;
   prepared= 1;
-  SELECT_LEX *save_select= thd->lex.select;
-  thd->lex.select= select_lex;
+  SELECT_LEX_NODE *save_select= thd->lex.current_select;
+  thd->lex.current_select= select_lex;
   if(join->prepare((TABLE_LIST*) select_lex->table_list.first,
 		   select_lex->where,
 		   (ORDER*) select_lex->order_list.first,
@@ -262,7 +262,7 @@ int subselect_single_select_engine::prepare()
 		   (ORDER*) 0, select_lex, 
 		   select_lex->master_unit(), 0))
     return 1;
-  thd->lex.select= save_select;
+  thd->lex.current_select= save_select;
   return 0;
 }
 
@@ -310,7 +310,7 @@ int subselect_single_select_engine::exec()
       DBUG_RETURN(join->error?join->error:1);
     }
   }
-  if (select_lex->depended && executed)
+  if (select_lex->dependent && executed)
   {
     if (join->reinit())
       DBUG_RETURN(1);
@@ -319,10 +319,10 @@ int subselect_single_select_engine::exec()
   }
   if (!executed)
   {
-    SELECT_LEX *save_select= join->thd->lex.select;
-    join->thd->lex.select= select_lex;
+    SELECT_LEX_NODE *save_select= join->thd->lex.current_select;
+    join->thd->lex.current_select= select_lex;
     join->exec();
-    join->thd->lex.select= save_select;
+    join->thd->lex.current_select= save_select;
     executed= 1;
     DBUG_RETURN(join->error||thd->fatal_error);
   }
@@ -346,10 +346,10 @@ uint subselect_union_engine::cols()
 
 bool subselect_single_select_engine::depended()
 {
-  return select_lex->depended;
+  return select_lex->dependent;
 }
 
 bool subselect_union_engine::depended()
 {
-  return unit->depended;
+  return unit->dependent;
 }
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 46e6b14638056630584cbe08c862270343c44503..66d88df4239e00e5b185b9f2dc90dd44002705ca 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -943,7 +943,10 @@ bool Item_sum_count_distinct::fix_fields(THD *thd, TABLE_LIST *tables,
 bool Item_sum_count_distinct::setup(THD *thd)
 {
   List<Item> list;
-  SELECT_LEX *select_lex= current_lex->select;
+  SELECT_LEX *select_lex= (SELECT_LEX *)current_lex->current_select;
+  if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
+    return 1;
+    
   /* Create a table with an unique key over all parameters */
   for (uint i=0; i < arg_count ; i++)
   {
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index f261c9f4632fb1530e8eee0220807f7d2a148056..26ee2db3cc1a6a74dc7724849ae15d930a581d7f 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -537,11 +537,6 @@ bool add_field_to_list(char *field_name, enum enum_field_types type,
 		       char *change, TYPELIB *interval,CHARSET_INFO *cs);
 void store_position_for_column(const char *name);
 bool add_to_list(SQL_LIST &list,Item *group,bool asc=0);
-TABLE_LIST *add_table_to_list(Table_ident *table,LEX_STRING *alias,
-			      bool updating,
-			      thr_lock_type flags=TL_UNLOCK,
-			      List<String> *use_index=0,
-			      List<String> *ignore_index=0);
 void add_join_on(TABLE_LIST *b,Item *expr);
 void add_join_natural(TABLE_LIST *a,TABLE_LIST *b);
 bool add_proc_to_list(Item *item);
@@ -562,8 +557,8 @@ int setup_fields(THD *thd,TABLE_LIST *tables,List<Item> &item,
 		 bool set_query_id,List<Item> *sum_func_list,
 		 bool allow_sum_func);
 int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
-int setup_ftfuncs(THD *thd);
-int init_ftfuncs(THD *thd, bool no_order);
+int setup_ftfuncs(SELECT_LEX* select);
+int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
 void wait_for_refresh(THD *thd);
 int open_tables(THD *thd,TABLE_LIST *tables);
 int open_and_lock_tables(THD *thd,TABLE_LIST *tables);
@@ -850,19 +845,19 @@ Item *get_system_var(enum_var_type var_type, const char *var_name, uint length,
 
 inline bool add_item_to_list(Item *item)
 {
-  return current_lex->select->item_list.push_back(item);
+  return current_lex->current_select->add_item_to_list(item);
 }
 inline bool add_value_to_list(Item *value)
 {
   return current_lex->value_list.push_back(value);
 }
-inline bool add_order_to_list(Item *item,bool asc)
+inline bool add_order_to_list(Item *item, bool asc)
 {
-  return add_to_list(current_lex->select->order_list,item,asc);
+  return current_lex->current_select->add_order_to_list(item, asc);
 }
-inline bool add_group_to_list(Item *item,bool asc)
+inline bool add_group_to_list(Item *item, bool asc)
 {
-  return add_to_list(current_lex->select->group_list,item,asc);
+  return current_lex->current_select->add_group_to_list(item, asc);
 }
 inline void mark_as_null_row(TABLE *table)
 {
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index d9818053e89f6157936b0643c820452b39935c89..3d7768ae333ffe54ce8133bea344243489d871e7 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2451,10 +2451,10 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
   DBUG_RETURN(result);
 }
 
-int setup_ftfuncs(THD *thd)
+int setup_ftfuncs(SELECT_LEX *select_lex)
 {
-  List_iterator<Item_func_match> li(*(thd->lex.select->ftfunc_list)),
-                                 lj(*(thd->lex.select->ftfunc_list));
+  List_iterator<Item_func_match> li(*(select_lex->ftfunc_list)),
+                                 lj(*(select_lex->ftfunc_list));
   Item_func_match *ftf, *ftf2;
 
   while ((ftf=li++))
@@ -2473,11 +2473,11 @@ int setup_ftfuncs(THD *thd)
 }
 
 
-int init_ftfuncs(THD *thd, bool no_order)
+int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order)
 {
-  if (thd->lex.select->ftfunc_list->elements)
+  if (select_lex->ftfunc_list->elements)
   {
-    List_iterator<Item_func_match> li(*(thd->lex.select->ftfunc_list));
+    List_iterator<Item_func_match> li(*(select_lex->ftfunc_list));
     Item_func_match *ifm;
     DBUG_PRINT("info",("Performing FULLTEXT search"));
     thd->proc_info="FULLTEXT initialization";
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 5bdefbaaa30a351b4dda478bfd86331d8e7d7ff9..2f236da2aa3044bd16f854df0f68a4fc524afe6a 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -2444,14 +2444,14 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
 
   if (lex->sql_command == SQLCOM_SELECT &&
       (thd->variables.query_cache_type == 1 ||
-       (thd->variables.query_cache_type == 2 && (lex->select->options &
+       (thd->variables.query_cache_type == 2 && (lex->select_lex.options &
 						 OPTION_TO_QUERY_CACHE))) &&
       thd->safe_to_cache_query)
   {
     my_bool has_transactions = 0;
     DBUG_PRINT("qcache", ("options %lx %lx, type %u",
 			OPTION_TO_QUERY_CACHE,
-			lex->select->options,
+			lex->select_lex.options,
 			(int) thd->variables.query_cache_type));
 
     for (; tables_used; tables_used= tables_used->next)
@@ -2498,7 +2498,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
 	     ("not interesting query: %d or not cacheable, options %lx %lx, type %u",
 	      (int) lex->sql_command,
 	      OPTION_TO_QUERY_CACHE,
-	      lex->select->options,
+	      lex->select_lex.options,
 	      (int) thd->variables.query_cache_type));
   DBUG_RETURN(0);
 }
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index cb1a9db70cd6551fc4985ed275b3e45b2e171a9e..0175fe4448447fd5d1a66c0d2dd41e1f4cb4311e 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -52,7 +52,8 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
   table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
   thd->proc_info="init";
   table->map=1;
-  if (setup_conds(thd,table_list,&conds) || setup_ftfuncs(thd))
+  if (setup_conds(thd,table_list,&conds) || 
+      setup_ftfuncs(&thd->lex.select_lex))
     DBUG_RETURN(-1);
 
   /* Test if the user wants to delete all rows */
@@ -129,7 +130,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
 
   init_read_record(&info,thd,table,select,1,1);
   deleted=0L;
-  init_ftfuncs(thd,1);
+  init_ftfuncs(thd, &thd->lex.select_lex, 1);
   thd->proc_info="updating";
   while (!(error=info.read_record(&info)) && !thd->killed)
   {
@@ -284,7 +285,11 @@ multi_delete::initialize_tables(JOIN *join)
 				     table->file->ref_length,
 				     MEM_STRIP_BUF_SIZE);
   }
-  init_ftfuncs(thd,1);
+  /*
+    There are (SELECT_LEX*) pointer conversion here global union parameters
+    can't be used in multidelete
+  */
+  init_ftfuncs(thd, (SELECT_LEX*)thd->lex.current_select, 1);
 }
 
 
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 52f1be6bddffa324045e20213fba7689bce74fa8..97cf936240f5662b2ceef77c512499c647cfa40c 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -147,7 +147,7 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
   lex->select_lex.in_sum_expr=0;
   lex->select_lex.expr_list.empty();
   lex->select_lex.ftfunc_list_alloc.empty();
-  lex->select_lex.ftfunc_list= &lex->select->ftfunc_list_alloc;
+  lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc;
   lex->convert_set= (lex->thd= thd)->variables.convert_set;
   lex->yacc_yyss=lex->yacc_yyvs=0;
   lex->ignore_space=test(thd->sql_mode & MODE_IGNORE_SPACE);
@@ -934,7 +934,8 @@ void st_select_lex_node::init_select()
   order_list.first= 0;
   order_list.next= (byte**) &order_list.first;
   select_limit= HA_POS_ERROR;
-  offset_limit= 0; 
+  offset_limit= 0;
+  create_refs= dependent= 0;
 }
 
 void st_select_lex_unit::init_query()
@@ -974,7 +975,7 @@ void st_select_lex::init_select()
   ftfunc_list_alloc.empty();
   ftfunc_list= &ftfunc_list_alloc;
   linkage= UNSPECIFIED_TYPE;
-  depended= having_fix_field= 0;
+  having_fix_field= 0;
 }
 
 /*
@@ -1042,6 +1043,44 @@ void st_select_lex_node::exclude()
   */
 }
 
+bool st_select_lex_node::add_item_to_list(Item *item)
+{
+  return 1;
+}
+
+bool  st_select_lex_node::add_group_to_list(Item *item, bool asc)
+{
+  return 1; 
+}
+
+//why compiler/linker do not allow make it inline?
+bool st_select_lex_node::add_order_to_list(Item *item, bool asc)
+{ 
+  return add_to_list(order_list,item,asc);
+}
+
+bool st_select_lex_node::add_ftfunc_to_list(Item_func_match *func)
+{
+  return 1;
+}
+
+bool st_select_lex_node::set_braces(bool value)      { return 1; }
+bool st_select_lex_node::inc_in_sum_expr()           { return 1; }
+uint st_select_lex_node::get_in_sum_expr()           { return 0; }
+TABLE_LIST* st_select_lex_node::get_table_list()     { return 0; }
+List<Item>* st_select_lex_node::get_item_list()      { return 0; }
+List<String>* st_select_lex_node::get_use_index()    { return 0; }
+List<String>* st_select_lex_node::get_ignore_index() { return 0; }
+TABLE_LIST *st_select_lex_node::add_table_to_list(Table_ident *table,
+						  LEX_STRING *alias,
+						  bool updating,
+						  thr_lock_type flags,
+						  List<String> *use_index,
+						  List<String> *ignore_index)
+{
+  return 0;
+}
+
 /*
   This is used for UNION & subselect to create a new table list of all used 
   tables.
@@ -1118,3 +1157,78 @@ bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex,
   *result= new_table_list;
   return 0;
 }
+
+st_select_lex_unit* st_select_lex_unit::master_unit()
+{
+    return this;
+}
+
+st_select_lex* st_select_lex_unit::outer_select()
+{
+  return (st_select_lex*) master;
+}
+
+
+bool st_select_lex::add_item_to_list(Item *item)
+{
+  return item_list.push_back(item);
+}
+
+bool st_select_lex::add_group_to_list(Item *item, bool asc)
+{
+  return add_to_list(group_list, item, asc);
+}
+
+bool st_select_lex::add_ftfunc_to_list(Item_func_match *func)
+{
+  return !func || ftfunc_list->push_back(func); // end of memory?
+}
+
+st_select_lex_unit* st_select_lex::master_unit()
+{
+  return (st_select_lex_unit*) master;
+}
+
+st_select_lex* st_select_lex::outer_select()
+{
+  return (st_select_lex*) master->get_master();
+}
+
+bool st_select_lex::set_braces(bool value)
+{
+  braces= value;
+  return 0; 
+}
+
+bool st_select_lex::inc_in_sum_expr()
+{
+  in_sum_expr++;
+  return 0;
+}
+
+uint st_select_lex::get_in_sum_expr()
+{
+  return in_sum_expr;
+}
+
+TABLE_LIST* st_select_lex::get_table_list()
+{
+  return (TABLE_LIST*) table_list.first;
+}
+
+List<Item>* st_select_lex::get_item_list()
+{
+  return &item_list;
+}
+
+List<String>* st_select_lex::get_use_index()
+{
+  return use_index_ptr;
+}
+
+List<String>* st_select_lex::get_ignore_index()
+{
+  return ignore_index_ptr;
+}
+
+// There are st_select_lex::add_table_to_list in sql_parse.cc
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index dca3fe7e7dfa5d79da8f8e2107cdbc26c3b19d42..7b31e9a81ca63e30d44de16f1e83fc25fac6ea07 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -186,6 +186,8 @@ enum olap_type
     Base class for st_select_lex (SELECT_LEX) & 
     st_select_lex_unit (SELECT_LEX_UNIT)
 */
+class st_select_lex;
+class st_select_lex_unit;
 class st_select_lex_node {
 protected:
   st_select_lex_node *next, **prev,   /* neighbor list */
@@ -195,23 +197,58 @@ class st_select_lex_node {
   ulong options;
   enum sub_select_type linkage;
   SQL_LIST order_list;                /* ORDER clause */
+  List<List_item>     expr_list;
+  List<List_item>     when_list;      /* WHEN clause (expression) */
   ha_rows select_limit, offset_limit; /* LIMIT clause parameters */
-  void init_query();
-  void init_select();
+  bool	create_refs;
+  bool dependent;	/* dependent from outer select subselect */
+
+  static void *operator new(size_t size)
+  {
+    return (void*) sql_calloc((uint) size);
+  }
+  static void operator delete(void *ptr,size_t size) {}
+  virtual ~st_select_lex_node() {}
+  inline st_select_lex_node* get_master() { return master; }
+  virtual void init_query();
+  virtual void init_select();
   void include_down(st_select_lex_node *upper);
   void include_neighbour(st_select_lex_node *before);
   void include_global(st_select_lex_node **plink);
   void exclude();
+
+  virtual bool add_item_to_list(Item *item);
+  bool add_order_to_list(Item *item, bool asc);
+  virtual bool add_group_to_list(Item *item, bool asc);
+  virtual bool add_ftfunc_to_list(Item_func_match *func);
+
+  virtual st_select_lex_unit* master_unit()= 0;
+  virtual st_select_lex* outer_select()= 0;
+
+  virtual bool set_braces(bool value);
+  virtual bool inc_in_sum_expr();
+  virtual uint get_in_sum_expr();
+  virtual TABLE_LIST* get_table_list();
+  virtual List<Item>* get_item_list();
+  virtual List<String>* get_use_index();
+  virtual List<String>* get_ignore_index();
+  virtual TABLE_LIST *add_table_to_list(Table_ident *table,
+					LEX_STRING *alias,
+					bool updating,
+					thr_lock_type flags= TL_UNLOCK,
+					List<String> *use_index= 0,
+					List<String> *ignore_index= 0);
+  
 private:
   void fast_exclude();
 };
+typedef class st_select_lex_node SELECT_LEX_NODE;
 
 /* 
    SELECT_LEX_UNIT - unit of selects (UNION, INTERSECT, ...) group 
    SELECT_LEXs
 */
 struct st_lex;
-class st_select_lex;
 class THD;
 class select_result;
 class JOIN;
@@ -238,14 +275,14 @@ class st_select_lex_unit: public st_select_lex_node {
   st_select_lex_node *global_parameters;
   /* LIMIT clause runtime counters */
   ha_rows select_limit_cnt, offset_limit_cnt;
-  bool depended; /* depended from outer select subselect */
   /* not NULL if union used in subselect, point to subselect item */
   Item_subselect *item;
   uint union_option;
 
   void init_query();
   bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result);
-  st_select_lex* outer_select() { return (st_select_lex*) master; }
+  st_select_lex_unit* master_unit();
+  st_select_lex* outer_select();
   st_select_lex* first_select() { return (st_select_lex*) slave; }
   st_select_lex_unit* next_unit() { return (st_select_lex_unit*) next; }
 
@@ -270,8 +307,6 @@ class st_select_lex: public st_select_lex_node
   char *db, *db1, *table1, *db2, *table2;      	/* For outer join using .. */
   Item *where, *having;                         /* WHERE & HAVING clauses */
   enum olap_type olap;
-  List<List_item>     expr_list;
-  List<List_item>     when_list;                /* WHEN clause */
   SQL_LIST	      table_list, group_list;   /* FROM & GROUP BY clauses */
   List<Item>          item_list; /* list of fields & expressions */
   List<String>        interval_list, use_index, *use_index_ptr,
@@ -286,23 +321,18 @@ class st_select_lex: public st_select_lex_node
   const char *type; /* type of select for EXPLAIN */
   uint in_sum_expr;
   uint select_number; /* number of select (used for EXPLAIN) */
-  bool	create_refs;
   bool  braces;   	/* SELECT ... UNION (SELECT ... ) <- this braces */
-  bool depended;	/* depended from outer select subselect */
   /* TRUE when having fix field called in processing of this SELECT */
   bool having_fix_field;
 
   void init_query();
   void init_select();
-  st_select_lex_unit* master_unit() { return (st_select_lex_unit*) master; }
+  st_select_lex_unit* master_unit();
   st_select_lex_unit* first_inner_unit() 
   { 
     return (st_select_lex_unit*) slave; 
   }
-  st_select_lex* outer_select() 
-  { 
-    return (st_select_lex*) master_unit()->outer_select(); 
-  }
+  st_select_lex* outer_select();
   st_select_lex* next_select() { return (st_select_lex*) next; }
   st_select_lex*  next_select_in_list() 
   {
@@ -313,6 +343,25 @@ class st_select_lex: public st_select_lex_node
     return &link_next;
   }
 
+  bool set_braces(bool value);
+  bool inc_in_sum_expr();
+  uint get_in_sum_expr();
+  bool add_item_to_list(Item *item);
+  bool add_group_to_list(Item *item, bool asc);
+  bool add_ftfunc_to_list(Item_func_match *func);
+
+  TABLE_LIST* get_table_list();
+  List<Item>* get_item_list();
+  List<String>* get_use_index();
+  List<String>* get_ignore_index();
+  TABLE_LIST* add_table_to_list(Table_ident *table,
+				LEX_STRING *alias,
+				bool updating,
+				thr_lock_type flags= TL_UNLOCK,
+				List<String> *use_index= 0,
+				List<String> *ignore_index= 0);
+
+  
   friend void mysql_init_query(THD *thd);
 };
 typedef class st_select_lex SELECT_LEX;
@@ -325,9 +374,9 @@ typedef struct st_lex
   uint	 yylineno,yytoklen;			/* Simulate lex */
   LEX_YYSTYPE yylval;
   SELECT_LEX_UNIT unit;                         /* most upper unit */
-  SELECT_LEX select_lex,                        /* first SELECT_LEX */
-    /* current SELECT_LEX in parsing */
-    *select;
+  SELECT_LEX select_lex;                        /* first SELECT_LEX */
+  /* current SELECT_LEX in parsing */
+  SELECT_LEX_NODE *current_select;
   uchar *ptr,*tok_start,*tok_end,*end_of_query;
   char *length,*dec,*change,*name;
   char *backup_dir;				/* For RESTORE/BACKUP */
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 69f1eae9ac871012cfb33ac0f8a2298e0450044d..fcdcbd72181e6282acbdb3f8bd7eadf63d6b06f4 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2908,9 +2908,9 @@ mysql_init_query(THD *thd)
   thd->select_number= thd->lex.select_lex.select_number= 1;
   thd->lex.value_list.empty();
   thd->free_list= 0;
-  thd->lex.select= &thd->lex.select_lex;
+  thd->lex.current_select= &thd->lex.select_lex;
   thd->lex.olap=thd->lex.describe=0;
-  thd->lex.select->olap= UNSPECIFIED_OLAP_TYPE;
+  thd->lex.select_lex.olap= UNSPECIFIED_OLAP_TYPE;
   thd->fatal_error= 0;				// Safety
   thd->total_warn_count=0;			// Warnings for this query
   thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
@@ -2924,7 +2924,8 @@ mysql_init_query(THD *thd)
 void
 mysql_init_select(LEX *lex)
 {
-  SELECT_LEX *select_lex= lex->select;
+  SELECT_LEX *select_lex= (SELECT_LEX *)lex->current_select;
+  DBUG_ASSERT(select_lex->linkage != GLOBAL_OPTIONS_TYPE);
   select_lex->init_select();
   select_lex->master_unit()->select_limit= select_lex->select_limit= 
     lex->thd->variables.select_limit;
@@ -2938,7 +2939,7 @@ mysql_init_select(LEX *lex)
 bool
 mysql_new_select(LEX *lex, bool move_down)
 {
-  SELECT_LEX *select_lex = (SELECT_LEX *) lex->thd->calloc(sizeof(SELECT_LEX));
+  SELECT_LEX *select_lex = new SELECT_LEX();
   select_lex->select_number= ++lex->thd->select_number;
   if (!select_lex)
     return 1;
@@ -2947,21 +2948,22 @@ mysql_new_select(LEX *lex, bool move_down)
   if (move_down)
   {
     /* first select_lex of subselect or derived table */
-    SELECT_LEX_UNIT *unit= 
-      (SELECT_LEX_UNIT *) lex->thd->calloc(sizeof(SELECT_LEX_UNIT));
+    SELECT_LEX_UNIT *unit= new SELECT_LEX_UNIT();
     if (!unit)
       return 1;
     unit->init_query();
     unit->init_select();
-    unit->include_down(lex->select);
+    unit->include_down(lex->current_select);
     select_lex->include_down(unit);
   }
   else
-    select_lex->include_neighbour(lex->select);
+    select_lex->include_neighbour(lex->current_select);
     
   select_lex->master_unit()->global_parameters= select_lex;
-  select_lex->include_global(lex->select->next_select_in_list_addr());
-  lex->select= select_lex;
+  DBUG_ASSERT(lex->current_select->linkage != GLOBAL_OPTIONS_TYPE);
+  select_lex->include_global(((SELECT_LEX*)lex->current_select)->
+			     next_select_in_list_addr());
+  lex->current_select= select_lex;
   return 0;
 }
 
@@ -2997,10 +2999,10 @@ void mysql_init_multi_delete(LEX *lex)
 {
   lex->sql_command=  SQLCOM_DELETE_MULTI;
   mysql_init_select(lex);
-  lex->select->select_limit= lex->select->master_unit()->select_limit_cnt=
+  lex->select_lex.select_limit= lex->unit.select_limit_cnt=
     HA_POS_ERROR;
   lex->auxilliary_table_list= lex->select_lex.table_list;
-  lex->select->init_query();
+  lex->select_lex.init_query();
 }
 
 
@@ -3410,12 +3412,12 @@ bool add_to_list(SQL_LIST &list,Item *item,bool asc)
 }
 
 
-TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
-			      bool updating,
-			      thr_lock_type flags,
-			      List<String> *use_index,
-			      List<String> *ignore_index
-			      )
+TABLE_LIST *st_select_lex::add_table_to_list(Table_ident *table,
+					     LEX_STRING *alias,
+					     bool updating,
+					     thr_lock_type flags,
+					     List<String> *use_index,
+					     List<String> *ignore_index)
 {
   register TABLE_LIST *ptr;
   THD	*thd=current_thd;
@@ -3477,7 +3479,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
   /* check that used name is unique */
   if (flags != TL_IGNORE)
   {
-    for (TABLE_LIST *tables=(TABLE_LIST*) thd->lex.select->table_list.first ;
+    for (TABLE_LIST *tables=(TABLE_LIST*) table_list.first ;
 	 tables ;
 	 tables=tables->next)
     {
@@ -3488,7 +3490,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
       }
     }
   }
-  link_in_list(&thd->lex.select->table_list,(byte*) ptr,(byte**) &ptr->next);
+  link_in_list(&table_list, (byte*) ptr, (byte**) &ptr->next);
   DBUG_RETURN(ptr);
 }
 
@@ -3691,7 +3693,7 @@ static bool append_file_to_dir(THD *thd, char **filename_ptr, char *table_name)
 bool check_simple_select()
 {
   THD *thd= current_thd;
-  if (thd->lex.select != &thd->lex.select_lex)
+  if (thd->lex.current_select != &thd->lex.select_lex)
   {
     char command[80];
     strmake(command, thd->lex.yylval->symbol.str,
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index bd115f0fc1e90670022697dc6677f50dbfdca63a..2cf51f5d72e6dd2cf84a0e2d3691a08489a6b7ae 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -497,7 +497,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
     if (having->with_sum_func)
       having->split_sum_func(all_fields);
   }
-  if (setup_ftfuncs(thd)) 
+  if (setup_ftfuncs(&thd->lex.select_lex)) 
     DBUG_RETURN(1);
 
   /* 
@@ -543,7 +543,7 @@ static bool send_prepare_results(PREP_STMT *stmt)
   stmt->free_list= thd->free_list;		// Save items used in stmt
   thd->free_list= 0;
 
-  SELECT_LEX *select_lex = lex->select;
+  SELECT_LEX *select_lex = &lex->select_lex;
   TABLE_LIST *tables=(TABLE_LIST*) select_lex->table_list.first;
   
   switch (sql_command) {
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 32b7c3be025f2bb02ddd4c143722d57cedec9faa..93545d1026896b92f0f7e6360881d42e8f2863d9 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -949,8 +949,8 @@ int show_binlog_events(THD* thd)
     LOG_INFO linfo;
     Log_event* ev;
   
-    limit_start = thd->lex.select->offset_limit;
-    limit_end = thd->lex.select->select_limit + limit_start;
+    limit_start = thd->lex.current_select->offset_limit;
+    limit_end = thd->lex.current_select->select_limit + limit_start;
 
     name= search_file_name;
     if (log_file_name)
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index b981ae329cda34df804a61a0d6f493a988608308..c286c57376fa1eeaafdeebd68a6d6d2b0d50fb52 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -38,7 +38,8 @@ static bool make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
 				 DYNAMIC_ARRAY *keyuse);
 static bool update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,
 				JOIN_TAB *join_tab,
-                                uint tables,COND *conds,table_map table_map);
+                                uint tables, COND *conds,
+				table_map table_map, SELECT_LEX *select_lex);
 static int sort_keyuse(KEYUSE *a,KEYUSE *b);
 static void set_position(JOIN *join,uint index,JOIN_TAB *table,KEYUSE *key);
 static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
@@ -250,7 +251,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
     if (having->with_sum_func)
       having->split_sum_func(all_fields);
   }
-  if (setup_ftfuncs(thd)) /* should be after having->fix_fields */
+  if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */
     DBUG_RETURN(-1);
   /*
     Check if one one uses a not constant column with group functions
@@ -420,7 +421,7 @@ JOIN::optimize()
       thd->fatal_error)
     DBUG_RETURN(-1);
 
-  if (select_lex->depended)
+  if (select_lex->dependent)
   {
     /*
       Just remove all const-table optimization in case of depended query
@@ -559,7 +560,7 @@ JOIN::optimize()
   make_join_readinfo(this,
 		     (select_options & (SELECT_DESCRIBE |
 					SELECT_NO_JOIN_CACHE)) |
-		     (thd->lex.select->ftfunc_list->elements ? 
+		     (select_lex->ftfunc_list->elements ? 
 		      SELECT_NO_JOIN_CACHE : 0));
 
   /*
@@ -720,7 +721,7 @@ JOIN::exec()
   }
 
   /* Perform FULLTEXT search before all regular searches */
-  init_ftfuncs(thd,test(order));
+  init_ftfuncs(thd, select_lex, test(order));
 
   /* Create a tmp table if distinct or if the sort is too complicated */
   if (need_tmp)
@@ -1239,8 +1240,8 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
   }
 
   if (conds || outer_join)
-    if (update_ref_and_keys(join->thd,keyuse_array,stat,join->tables,
-                            conds,~outer_join))
+    if (update_ref_and_keys(join->thd, keyuse_array, stat, join->tables,
+                            conds, ~outer_join, join->select_lex))
       DBUG_RETURN(1);
 
   /* Read tables with 0 or 1 rows (system tables) */
@@ -1800,7 +1801,8 @@ sort_keyuse(KEYUSE *a,KEYUSE *b)
 
 static bool
 update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
-		    uint tables, COND *cond, table_map normal_tables)
+		    uint tables, COND *cond, table_map normal_tables,
+		    SELECT_LEX *select_lex)
 {
   uint	and_level,i,found_eq_constant;
 
@@ -1828,7 +1830,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
       add_key_part(keyuse,field);
   }
 
-  if (thd->lex.select->ftfunc_list->elements)
+  if (select_lex->ftfunc_list->elements)
   {
     add_ft_keys(keyuse,join_tab,cond,normal_tables);
   }
@@ -2930,7 +2932,7 @@ join_free(JOIN *join)
       end_read_record(&tab->read_record);
     }
     //TODO: is enough join_free at the end of mysql_select?
-    if (!join->select_lex->depended)
+    if (!join->select_lex->dependent)
       join->table=0;
   }
   /*
@@ -7460,9 +7462,9 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
 			       ((sl->next_select_in_list())?"PRIMARY":
 				"SIMPLE"):
 			       ((sl == first)?
-				((sl->depended)?"DEPENDENT SUBSELECT":
+				((sl->dependent)?"DEPENDENT SUBSELECT":
 				 "SUBSELECT"):
-				((sl->depended)?"DEPENDENT UNION":
+				((sl->dependent)?"DEPENDENT UNION":
 				 "UNION"))),
 			      result);
     if (res)
@@ -7480,7 +7482,7 @@ int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type,
   DBUG_ENTER("mysql_explain_select");
   DBUG_PRINT("info", ("Select 0x%lx, type %s", (ulong)select_lex, type))
   select_lex->type= type;
-  thd->lex.select= select_lex;
+  thd->lex.current_select= select_lex;
   SELECT_LEX_UNIT *unit=  select_lex->master_unit();
   int res= mysql_select(thd,(TABLE_LIST*) select_lex->table_list.first,
 			select_lex->item_list,
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 899dceab9bc384b823af2c69afcf7619588f9505..53f89747ce7980b8b1bbebcb4c641bd99121c2b0 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -115,7 +115,8 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
   TMP_TABLE_PARAM tmp_table_param;
   this->thd= thd;
   this->result= result;
-  SELECT_LEX *lex_select_save= thd->lex.select, *sl;
+  SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
+  SELECT_LEX *sl;
 
   /* Global option */
   if (((void*)(global_parameters)) == ((void*)this))
@@ -169,7 +170,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
 			 sl->options | thd->options | SELECT_NO_UNLOCK,
 			 union_result);
     joins.push_back(new JOIN_P(join));
-    thd->lex.select=sl;
+    thd->lex.current_select= sl;
     offset_limit_cnt= sl->offset_limit;
     select_limit_cnt= sl->select_limit+sl->offset_limit;
     if (select_limit_cnt < sl->select_limit)
@@ -188,29 +189,29 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
     if (res | thd->fatal_error)
       goto err;
   }
-  thd->lex.select= lex_select_save;
+  thd->lex.current_select= lex_select_save;
   DBUG_RETURN(res | thd->fatal_error);
 err:
-  thd->lex.select= lex_select_save;
+  thd->lex.current_select= lex_select_save;
   DBUG_RETURN(-1);
 }
 
 int st_select_lex_unit::exec()
 {
   DBUG_ENTER("st_select_lex_unit::exec");
-  SELECT_LEX *lex_select_save= thd->lex.select;
+  SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
   
-  if (executed && !depended)
+  if (executed && !dependent)
     DBUG_RETURN(0);
   executed= 1;
   
-  if (depended || !item || !item->assigned())
+  if (dependent || !item || !item->assigned())
   {
     if (optimized && item && item->assigned())
       item->assigned(0); // We will reinit & rexecute unit
     for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
     {
-      thd->lex.select=sl;
+      thd->lex.current_select= sl;
       offset_limit_cnt= sl->offset_limit;
       select_limit_cnt= sl->select_limit+sl->offset_limit;
       if (select_limit_cnt < sl->select_limit)
@@ -230,7 +231,7 @@ int st_select_lex_unit::exec()
       }
       if (res)
       {
-	thd->lex.select= lex_select_save;
+	thd->lex.current_select= lex_select_save;
 	DBUG_RETURN(res);
       }
     }
@@ -239,12 +240,14 @@ int st_select_lex_unit::exec()
 
   if (union_result->flush())
   {
-    thd->lex.select= lex_select_save;
+    thd->lex.current_select= lex_select_save;
     DBUG_RETURN(1);
   }
 
   /* Send result to 'result' */
-  thd->lex.select = first_select();
+
+  // to correct ORDER BY reference resolving
+  thd->lex.current_select = first_select();
   res =-1;
   {
     /* Create a list of fields in the temporary table */
@@ -283,7 +286,7 @@ int st_select_lex_unit::exec()
     }
   }
   thd->lex.select_lex.ftfunc_list= &thd->lex.select_lex.ftfunc_list_alloc;
-  thd->lex.select= lex_select_save;
+  thd->lex.current_select= lex_select_save;
   DBUG_RETURN(res);
 }
 
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index e8d4af94640d8f9cf2b563f534e38900989de89c..b00a8ba851cfe9fd6bcdc86ac190674f0a1dde40 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -78,7 +78,7 @@ int mysql_update(THD *thd,
   want_privilege=table->grant.want_privilege;
   table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
   if (setup_tables(table_list) || setup_conds(thd,table_list,&conds)
-                               || setup_ftfuncs(thd))
+                               || setup_ftfuncs(&thd->lex.select_lex))
     DBUG_RETURN(-1);				/* purecov: inspected */
   old_used_keys=table->used_keys;		// Keys used in WHERE
 
@@ -142,7 +142,7 @@ int mysql_update(THD *thd,
       DBUG_RETURN(1);
     }
   }
-  init_ftfuncs(thd,1);
+  init_ftfuncs(thd, &thd->lex.select_lex, 1);
   /* Check if we are modifying a key that we are used to search with */
   if (select && select->quick)
     used_key_is_modified= (!select->quick->unique_key_range() &&
@@ -508,7 +508,14 @@ multi_update::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
       counter++;
     }
   }
-  init_ftfuncs(thd,1);
+  /*
+    
+    There are (SELECT_LEX*) pointer conversion here global union parameters
+    can't be used in multiupdate
+
+    TODO: check is thd->lex.current_select == &thd->lex.select_lex?
+  */
+  init_ftfuncs(thd, (SELECT_LEX*)thd->lex.current_select, 1);
   error = 0; // Timestamps do not need to be restored, so far ...
   DBUG_RETURN(0);
 }
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index a3fe6dd7b79daedccce62578dca4192849258b23..394f11d9bbdeb04cb26818f3426fedf1622853dd 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -21,7 +21,7 @@
 #define YYINITDEPTH 100
 #define YYMAXDEPTH 3200				/* Because of 64K stack */
 #define Lex current_lex
-#define Select Lex->select
+#define Select Lex->current_select
 #include "mysql_priv.h"
 #include "slave.h"
 #include "sql_acl.h"
@@ -581,7 +581,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
 	key_part
 
 %type <table_list>
-	join_table_list join_table
+	join_table_list  join_table
 
 %type <udf>
 	UDF_CHAR_FUNC UDF_FLOAT_FUNC UDF_INT_FUNC
@@ -784,9 +784,11 @@ create:
 	  THD *thd=current_thd;
 	  LEX *lex=Lex;
 	  lex->sql_command= SQLCOM_CREATE_TABLE;
-	  if (!add_table_to_list($5,
-				 ($2 & HA_LEX_CREATE_TMP_TABLE ?
-				   &tmp_table_alias : (LEX_STRING*) 0),1))
+	  if (!lex->select_lex.add_table_to_list($5,
+			 			 ($2 &
+						  HA_LEX_CREATE_TMP_TABLE ?
+						  &tmp_table_alias :
+						  (LEX_STRING*) 0),1))
 	    YYABORT;
 	  lex->create_list.empty();
 	  lex->key_list.empty();
@@ -803,7 +805,7 @@ create:
 	  {
 	    LEX *lex=Lex;
 	    lex->sql_command= SQLCOM_CREATE_INDEX;
-	    if (!add_table_to_list($7,NULL,1))
+	    if (!lex->current_select->add_table_to_list($7,NULL,1))
 	      YYABORT;
 	    lex->create_list.empty();
 	    lex->key_list.empty();
@@ -913,12 +915,12 @@ create_table_option:
 	  {
 	    /* Move the union list to the merge_list */
 	    LEX *lex=Lex;
-	    TABLE_LIST *table_list= (TABLE_LIST*) lex->select->table_list.first;
-	    lex->create_info.merge_list= lex->select->table_list;
+	    TABLE_LIST *table_list= lex->select_lex.get_table_list();
+	    lex->create_info.merge_list= lex->select_lex.table_list;
 	    lex->create_info.merge_list.elements--;
 	    lex->create_info.merge_list.first= (byte*) (table_list->next);
-	    lex->select->table_list.elements=1;
-	    lex->select->table_list.next= (byte**) &(table_list->next);
+	    lex->select_lex.table_list.elements=1;
+	    lex->select_lex.table_list.next= (byte**) &(table_list->next);
 	    table_list->next=0;
 	    lex->create_info.used_fields|= HA_CREATE_USED_UNION;
 	  }
@@ -1302,10 +1304,10 @@ alter:
 	ALTER opt_ignore TABLE_SYM table_ident
 	{
 	  THD *thd=current_thd;
-	  LEX *lex=Lex;
+	  LEX *lex=&thd->lex;
 	  lex->sql_command = SQLCOM_ALTER_TABLE;
 	  lex->name=0;
-	  if (!add_table_to_list($4, NULL,1))
+	  if (!lex->select_lex.add_table_to_list($4, NULL,1))
 	    YYABORT;
 	  lex->drop_primary=0;
 	  lex->create_list.empty();
@@ -1313,10 +1315,11 @@ alter:
 	  lex->col_list.empty();
 	  lex->drop_list.empty();
 	  lex->alter_list.empty();
-          lex->select->order_list.elements=0;
-          lex->select->order_list.first=0;
-          lex->select->order_list.next= (byte**) &lex->select->order_list.first;
-	  lex->select->db=lex->name=0;
+          lex->select_lex.order_list.elements=0;
+          lex->select_lex.order_list.first=0;
+          lex->select_lex.order_list.next= 
+            (byte**) &lex->select_lex.order_list.first;
+	  lex->select_lex.db=lex->name=0;
     	  bzero((char*) &lex->create_info,sizeof(lex->create_info));
 	  lex->create_info.db_type= DB_TYPE_DEFAULT;
 	  lex->create_info.table_charset=thd->db_charset?thd->db_charset:default_charset_info;
@@ -1405,7 +1408,7 @@ alter_list_item:
 	| RENAME opt_to table_ident
 	  { 
 	    LEX *lex=Lex;
-	    lex->select->db=$3->db.str;
+	    lex->select_lex.db=$3->db.str;
 	    lex->name= $3->table.str;
 	  }
         | create_table_options_space_separated { Lex->simple_alter=0; }
@@ -1571,9 +1574,11 @@ table_to_table_list:
 
 table_to_table:
 	table_ident TO_SYM table_ident
-	{ if (!add_table_to_list($1,NULL,1,TL_IGNORE) ||
-	      !add_table_to_list($3,NULL,1,TL_IGNORE))
-	     YYABORT;
+	{ 
+	  SELECT_LEX_NODE *sl= Lex->current_select;
+	  if (!sl->add_table_to_list($1,NULL,1,TL_IGNORE) ||
+	      !sl->add_table_to_list($3,NULL,1,TL_IGNORE))
+	    YYABORT;
  	};
 
 /*
@@ -1585,12 +1590,26 @@ select:
 	select_init { Lex->sql_command=SQLCOM_SELECT; };
 
 select_init:
-	SELECT_SYM select_part2 { Select->braces=false;	} union
+	SELECT_SYM select_part2 
+        { 
+	  LEX *lex= Lex;
+          if (lex->current_select->set_braces(false))
+	  {
+	    send_error(lex->thd, ER_SYNTAX_ERROR);
+	    YYABORT;
+	  }
+	}
+	union
 	|
 	'(' SELECT_SYM 	select_part2 ')' 
 	  { 
-            SELECT_LEX * sel=Select;
-	    sel->braces=true;
+	    LEX *lex= Lex;
+            SELECT_LEX_NODE * sel= lex->current_select;
+	    if (sel->set_braces(true))
+	    {
+	      send_error(lex->thd, ER_SYNTAX_ERROR);
+	      YYABORT;
+	    }
             /* select in braces, can't contain global parameters */
             sel->master_unit()->global_parameters=
               	sel->master_unit();
@@ -1871,10 +1890,10 @@ simple_expr:
 	| singleval_subselect   { $$= $1; }
 	| '{' ident expr '}'	{ $$= $3; }
         | MATCH ident_list_arg AGAINST '(' expr ')'
-          { Select->ftfunc_list->push_back((Item_func_match *)
+          { Select->add_ftfunc_to_list((Item_func_match *)
                    ($$=new Item_func_match_nl(*$2,$5))); }
         | MATCH ident_list_arg AGAINST '(' expr IN_SYM BOOLEAN_SYM MODE_SYM ')'
-          { Select->ftfunc_list->push_back((Item_func_match *)
+          { Select->add_ftfunc_to_list((Item_func_match *)
                    ($$=new Item_func_match_bool(*$2,$5))); }
 	| BINARY expr %prec NEG { $$= new Item_func_set_collation($2,my_charset_bin); }
 	| CAST_SYM '(' expr AS cast_type ')'  { $$= create_func_cast($3, $5); }
@@ -2200,10 +2219,21 @@ sum_expr:
 	  { $$=new Item_sum_sum($3); };
 
 in_sum_expr:
-	{ Select->in_sum_expr++; }
+	{
+	  LEX *lex= Lex;
+	  if (lex->current_select->inc_in_sum_expr())
+	  {
+	    send_error(lex->thd, ER_SYNTAX_ERROR);
+	    YYABORT;	    
+	  }
+	}
 	expr
 	{
-	  Select->in_sum_expr--;
+  	/* 
+	  There are (SELECT_LEX *) pointer conversionis here, because 
+	  global union parameters checked in 'increment' above
+	*/
+	  ((SELECT_LEX *)Select)->in_sum_expr--;
 	  $$=$2;
 	};
 
@@ -2255,13 +2285,13 @@ when_list:
 when_list2:
 	expr THEN_SYM expr
 	  {
-	    SELECT_LEX *sel=Select;	    
+	    SELECT_LEX_NODE *sel=Select;	    
 	    sel->when_list.head()->push_back($1);
 	    sel->when_list.head()->push_back($3);
 	}
 	| when_list2 WHEN_SYM expr THEN_SYM expr
 	  {
-	    SELECT_LEX *sel=Select;
+	    SELECT_LEX_NODE *sel=Select;
 	    sel->when_list.head()->push_back($3);
 	    sel->when_list.head()->push_back($5);
 	  };
@@ -2280,7 +2310,12 @@ join_table_list:
 	  { add_join_on($4,$6); $$=$4; }
 	| join_table_list INNER_SYM JOIN_SYM join_table_list
 	  {
-	    SELECT_LEX *sel=Select;
+  	    /* 
+	      There are (SELECT_LEX *) pointer conversionis here and 
+	      following joins, because it is impossible FROM clause in
+	      global union parameters 
+	    */
+	    SELECT_LEX *sel= (SELECT_LEX *)Select;
 	    sel->db1=$1->db; sel->table1=$1->alias;
 	    sel->db2=$4->db; sel->table2=$4->alias;
 	  }
@@ -2290,7 +2325,7 @@ join_table_list:
 	  { add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
 	| join_table_list LEFT opt_outer JOIN_SYM join_table_list
 	  {
-	    SELECT_LEX *sel=Select;
+	    SELECT_LEX *sel= (SELECT_LEX *)Select;
 	    sel->db1=$1->db; sel->table1=$1->alias;
 	    sel->db2=$5->db; sel->table2=$5->alias;
 	  }
@@ -2302,7 +2337,7 @@ join_table_list:
 	  { add_join_on($1,$7); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; }
 	| join_table_list RIGHT opt_outer JOIN_SYM join_table_list
 	  {
-	    SELECT_LEX *sel=Select;
+	    SELECT_LEX *sel= (SELECT_LEX *)Select;
 	    sel->db1=$1->db; sel->table1=$1->alias;
 	    sel->db2=$5->db; sel->table2=$5->alias;
 	  }
@@ -2320,14 +2355,15 @@ normal_join:
 
 join_table:
 	{
-	  SELECT_LEX *sel=Select;
+	  SELECT_LEX *sel= (SELECT_LEX *)Select;
 	  sel->use_index_ptr=sel->ignore_index_ptr=0;
 	}
         table_ident opt_table_alias opt_key_definition
 	{
-	  SELECT_LEX *sel=Select;
-	  if (!($$=add_table_to_list($2,$3,0,TL_UNLOCK, sel->use_index_ptr,
-	                             sel->ignore_index_ptr)))
+	  SELECT_LEX_NODE *sel=Select;
+	  if (!($$= sel->add_table_to_list($2, $3, 0, TL_UNLOCK,
+					   sel->get_use_index(),
+					   sel->get_ignore_index())))
 	    YYABORT;
 	}
 	| '{' ident join_table LEFT OUTER JOIN_SYM join_table ON expr '}'
@@ -2335,10 +2371,10 @@ join_table:
         | '(' SELECT_SYM select_part3 ')' opt_table_alias 
 	{
 	  LEX *lex=Lex;
-	  SELECT_LEX_UNIT *unit= lex->select->master_unit();
-	  lex->select= unit->outer_select();
-	  if (!($$= add_table_to_list(new Table_ident(unit),
-	                              $5,0,TL_UNLOCK)))
+	  SELECT_LEX_UNIT *unit= lex->current_select->master_unit();
+	  lex->current_select= unit->outer_select();
+	  if (!($$= lex->current_select->
+                add_table_to_list(new Table_ident(unit), $5, 0, TL_UNLOCK)))
 	    YYABORT;
 	};
 
@@ -2346,11 +2382,11 @@ select_part3:
         {
 	  LEX *lex= Lex;
 	  lex->derived_tables= true;
-	  if (lex->select->linkage == GLOBAL_OPTIONS_TYPE || 
+	  if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE || 
               mysql_new_select(lex, 1))
 	    YYABORT;
 	  mysql_init_select(lex);
-	  lex->select->linkage= DERIVED_TABLE_TYPE;
+	  lex->current_select->linkage= DERIVED_TABLE_TYPE;
 	}
         select_options select_item_list select_intoto;
 
@@ -2366,39 +2402,54 @@ opt_key_definition:
 	/* empty */	{}
 	| USE_SYM    key_usage_list
           {
-	    SELECT_LEX *sel=Select;
+  	    /* 
+	      There are (SELECT_LEX *) pointer conversionis here and 
+	      following key definitions, because 
+	      key definitions is impossible in union global parameters
+	    */
+	    SELECT_LEX *sel= (SELECT_LEX*)Select;
 	    sel->use_index= *$2;
 	    sel->use_index_ptr= &sel->use_index;
 	  }
 	| IGNORE_SYM key_usage_list
 	  {
-	    SELECT_LEX *sel=Select;
+	    SELECT_LEX *sel= (SELECT_LEX*)Select;
 	    sel->ignore_index= *$2;
 	    sel->ignore_index_ptr= &sel->ignore_index;
 	  };
 
 key_usage_list:
-	key_or_index { Select->interval_list.empty(); } '(' key_usage_list2 ')'
-        { $$= &Select->interval_list; };
+	key_or_index { ((SELECT_LEX *)Select)->interval_list.empty(); }
+        '(' key_usage_list2 ')'
+        { $$= &((SELECT_LEX *)Select)->interval_list; };
 
 key_usage_list2:
 	key_usage_list2 ',' ident
-        { Select->interval_list.push_back(new String((const char*) $3.str,$3.length,default_charset_info)); }
+        { ((SELECT_LEX *)Select)->
+	    interval_list.push_back(new String((const char*) $3.str, $3.length,
+				    default_charset_info)); }
 	| ident
-        { Select->interval_list.push_back(new String((const char*) $1.str,$1.length,default_charset_info)); }
+        { ((SELECT_LEX *)Select)->
+	    interval_list.push_back(new String((const char*) $1.str, $1.length,
+				    default_charset_info)); }
 	| PRIMARY_SYM
-        { Select->interval_list.push_back(new String("PRIMARY",7,default_charset_info)); };
+        { ((SELECT_LEX *)Select)->
+	    interval_list.push_back(new String("PRIMARY", 7,
+				    default_charset_info)); };
 
 using_list:
 	ident
 	  {
-	    SELECT_LEX *sel=Select;
-	    if (!($$= new Item_func_eq(new Item_field(sel->db1,sel->table1, $1.str), new Item_field(sel->db2,sel->table2,$1.str))))
+	    SELECT_LEX *sel= (SELECT_LEX *)Select;
+	    if (!($$= new Item_func_eq(new Item_field(sel->db1, sel->table1,
+						      $1.str),
+				       new Item_field(sel->db2, sel->table2,
+						      $1.str))))
 	      YYABORT;
 	  }
 	| using_list ',' ident
 	  {
-	    SELECT_LEX *sel=Select;
+	    SELECT_LEX *sel= (SELECT_LEX *)Select;
 	    if (!($$= new Item_cond_and(new Item_func_eq(new Item_field(sel->db1,sel->table1,$3.str), new Item_field(sel->db2,sel->table2,$3.str)), $1)))
 	      YYABORT;
 	  };
@@ -2430,14 +2481,22 @@ opt_table_alias:
 
 
 where_clause:
-	/* empty */  { Select->where= 0; }
-	| WHERE expr { Select->where= $2; };
+	/* 
+	  There are (SELECT_LEX *) pointer conversionis here, because 
+	  it is impossible where_clause in global union parameters
+	*/
+	/* empty */  { ((SELECT_LEX *)Select)->where= 0; }  
+	| WHERE expr { ((SELECT_LEX *)Select)->where= $2; };
 
 having_clause:
+	/* 
+	  There are (SELECT_LEX *) pointer conversionis here, because 
+	  it is impossible having_clause in global union parameters
+	*/
 	/* empty */
-	| HAVING { Select->create_refs=1; } expr
+	| HAVING { ((SELECT_LEX *)Select)->create_refs= 1; } expr
 	{
-	  SELECT_LEX *sel=Select;
+	  SELECT_LEX *sel= (SELECT_LEX*)Select;
 	  sel->having= $3; sel->create_refs=0;
 	};
 
@@ -2466,15 +2525,27 @@ olap_opt:
           {
 	    LEX *lex=Lex;
 	    lex->olap = true;
-	    lex->select->olap= CUBE_TYPE;
+	    if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
+	    {
+	      net_printf(lex->thd, ER_WRONG_USAGE, "WITH CUBE",
+		       "global union parameters");
+	      YYABORT;
+	    }
+	    ((SELECT_LEX *)lex->current_select)->olap= CUBE_TYPE;
 	    net_printf(lex->thd, ER_NOT_SUPPORTED_YET, "CUBE");
 	    YYABORT;	/* To be deleted in 4.1 */
 	  }
 	| WITH ROLLUP_SYM
           {
-	    LEX *lex=Lex;
-	    lex->olap = true;
-	    lex->select->olap= ROLLUP_TYPE;
+	    LEX *lex= Lex;
+	    lex->olap= true;
+	    if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
+	    {
+	      net_printf(lex->thd, ER_WRONG_USAGE, "WITH ROLLUP",
+		       "global union parameters");
+	      YYABORT;
+	    }
+	    ((SELECT_LEX *)lex->current_select)->olap= ROLLUP_TYPE;
 	    net_printf(lex->thd, ER_NOT_SUPPORTED_YET, "ROLLUP");
 	    YYABORT;	/* To be deleted in 4.1 */
 	  }
@@ -2497,8 +2568,9 @@ order_clause:
 	    net_printf(lex->thd, ER_WRONG_USAGE, "UPDATE", "ORDER BY");
 	    YYABORT;
 	  }	
-	  if (lex->select->linkage != GLOBAL_OPTIONS_TYPE &&
-	      lex->select->olap != UNSPECIFIED_OLAP_TYPE)
+	  if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
+	      ((SELECT_LEX*)lex->current_select)->olap !=
+	      UNSPECIFIED_OLAP_TYPE)
 	  {
 	    net_printf(lex->thd, ER_WRONG_USAGE,
 		       "CUBE/ROLLUP",
@@ -2523,29 +2595,31 @@ limit_clause:
 	/* empty */ {}
 	| LIMIT ULONG_NUM
 	  {
-	    LEX *lex=Lex;
-	    if (lex->select->linkage != GLOBAL_OPTIONS_TYPE &&
-	        lex->select->olap != UNSPECIFIED_OLAP_TYPE)
+	    LEX *lex= Lex;
+	    if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
+	        ((SELECT_LEX*)lex->current_select)->olap !=
+		UNSPECIFIED_OLAP_TYPE)
 	    {
 	      net_printf(lex->thd, ER_WRONG_USAGE, "CUBE/ROLLUP",
 		        "LIMIT");
 	      YYABORT;
 	    }
-	    SELECT_LEX *sel=Select;
+	    SELECT_LEX_NODE *sel= Select;
 	    sel->select_limit= $2;
 	    sel->offset_limit= 0L;
 	  }
 	| LIMIT ULONG_NUM ',' ULONG_NUM
 	  {
 	    LEX *lex=Lex;
-	    if (lex->select->linkage != GLOBAL_OPTIONS_TYPE &&
-                lex->select->olap != UNSPECIFIED_OLAP_TYPE)
+	    if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
+                ((SELECT_LEX*)lex->current_select)->olap !=
+		UNSPECIFIED_OLAP_TYPE)
 	    {
 	      net_printf(lex->thd, ER_WRONG_USAGE, "CUBE/ROLLUP",
 		        "LIMIT");
 	      YYABORT;
 	    }	      
-	    SELECT_LEX *sel=lex->select;
+	    SELECT_LEX_NODE *sel= lex->current_select;
 	    sel->select_limit= $4;
 	    sel->offset_limit= $2;
 	  };
@@ -2559,7 +2633,7 @@ delete_limit_clause:
 	    net_printf(lex->thd, ER_WRONG_USAGE, "DELETE", "LIMIT");
 	    YYABORT;
 	  }
-	  lex->select->select_limit= HA_POS_ERROR;
+	  lex->current_select->select_limit= HA_POS_ERROR;
 	}
 	| LIMIT ulonglong_num
 	{ Select->select_limit= (ha_rows) $2; };
@@ -2693,7 +2767,7 @@ drop:
 	     lex->drop_list.empty();
 	     lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY,
 						     $3.str));
-	     if (!add_table_to_list($5,NULL, 1))
+	     if (!lex->current_select->add_table_to_list($5,NULL, 1))
 	      YYABORT;
 	  }
 	| DROP DATABASE if_exists ident
@@ -2717,7 +2791,7 @@ table_list:
 
 table_name:
 	table_ident
-	{ if (!add_table_to_list($1,NULL,1)) YYABORT; };
+	{ if (!Select->add_table_to_list($1, NULL, 1)) YYABORT; };
 
 if_exists:
 	/* empty */ { $$=0; }
@@ -2862,11 +2936,12 @@ expr_or_default:
 update:
         UPDATE_SYM 
 	{ 
-	  LEX *lex=Lex;
-          lex->sql_command = SQLCOM_UPDATE;
-          lex->select->order_list.elements=0;
-          lex->select->order_list.first=0;
-          lex->select->order_list.next= (byte**) &lex->select->order_list.first;
+	  LEX *lex= Lex;
+          lex->sql_command= SQLCOM_UPDATE;
+          lex->select_lex.order_list.elements= 0;
+          lex->select_lex.order_list.first= 0;
+          lex->select_lex.order_list.next= (byte**)
+	    &lex->select_lex.order_list.first;
         }
         opt_low_priority opt_ignore join_table_list SET update_list where_clause opt_order_clause delete_limit_clause;
 
@@ -2891,12 +2966,14 @@ opt_low_priority:
 delete:
 	DELETE_SYM
 	{ 
-	  LEX *lex=Lex;
-	  lex->sql_command= SQLCOM_DELETE; lex->select->options=0;
+	  LEX *lex= Lex;
+	  lex->sql_command= SQLCOM_DELETE;
+	  lex->select_lex.options= 0;
 	  lex->lock_option= lex->thd->update_lock_default;
-	  lex->select->order_list.elements=0;
-	  lex->select->order_list.first=0;
-	  lex->select->order_list.next= (byte**) &lex->select->order_list.first;
+	  lex->select_lex.order_list.elements= 0;
+	  lex->select_lex.order_list.first= 0;
+	  lex->select_lex.order_list.next= (byte**)
+	    &lex->select_lex.order_list.first;
 	}
 	opt_delete_options single_multi	{};
 
@@ -2916,12 +2993,14 @@ table_wild_list:
 table_wild_one:
 	 ident opt_wild
 	 {
-	    if (!add_table_to_list(new Table_ident($1),NULL,1,TL_WRITE))
+	    if (!Select->add_table_to_list(new Table_ident($1), NULL, 1,
+					   TL_WRITE))
 	      YYABORT;
          }
 	 | ident '.' ident opt_wild
 	   {
-	     if (!add_table_to_list(new Table_ident($1,$3,0),NULL,1,TL_WRITE))
+	     if (!Select->add_table_to_list(new Table_ident($1, $3, 0), NULL,
+					    1, TL_WRITE))
 	      YYABORT;
 	   };
 
@@ -2941,12 +3020,13 @@ opt_delete_option:
 truncate:
 	TRUNCATE_SYM opt_table_sym table_name
 	{
-	  LEX* lex = Lex;
+	  LEX* lex= Lex;
 	  lex->sql_command= SQLCOM_TRUNCATE;
-	  lex->select->options=0;
-	  lex->select->order_list.elements=0;
-          lex->select->order_list.first=0;
-          lex->select->order_list.next= (byte**) &lex->select->order_list.first;
+	  lex->select_lex.options= 0;
+	  lex->select_lex.order_list.elements= 0;
+          lex->select_lex.order_list.first= 0;
+          lex->select_lex.order_list.next= (byte**)
+	    &lex->select_lex.order_list.first;
 	  lex->lock_option= current_thd->update_lock_default; };
 
 opt_table_sym:
@@ -2962,30 +3042,31 @@ show_param:
 	  { Lex->sql_command= SQLCOM_SHOW_DATABASES; }
 	| TABLES opt_db wild
 	  {
-	    LEX *lex=Lex;
+	    LEX *lex= Lex;
 	    lex->sql_command= SQLCOM_SHOW_TABLES;
-	    lex->select->db= $2; lex->select->options=0;
+	    lex->select_lex.db= $2;
+	    lex->select_lex.options= 0;
 	   }
 	| TABLE_SYM STATUS_SYM opt_db wild
 	  {
-	    LEX *lex=Lex;
+	    LEX *lex= Lex;
 	    lex->sql_command= SQLCOM_SHOW_TABLES;
-	    lex->select->options|= SELECT_DESCRIBE;
-	    lex->select->db= $3;
+	    lex->select_lex.options|= SELECT_DESCRIBE;
+	    lex->select_lex.db= $3;
 	  }
 	| OPEN_SYM TABLES opt_db wild
 	  {
-	    LEX *lex=Lex;
+	    LEX *lex= Lex;
 	    lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
-	    lex->select->db= $3;
-	    lex->select->options=0;
+	    lex->select_lex.db= $3;
+	    lex->select_lex.options= 0;
 	  }
 	| opt_full COLUMNS from_or_in table_ident opt_db wild
 	  {
 	    Lex->sql_command= SQLCOM_SHOW_FIELDS;
 	    if ($5)
 	      $4->change_db($5);
-	    if (!add_table_to_list($4,NULL,0))
+	    if (!Select->add_table_to_list($4, NULL, 0))
 	      YYABORT;
 	  }
         | NEW_SYM MASTER_SYM FOR_SYM SLAVE WITH MASTER_LOG_FILE_SYM EQ 
@@ -3008,17 +3089,17 @@ show_param:
           }
         | BINLOG_SYM EVENTS_SYM binlog_in binlog_from
           {
-	    LEX *lex=Lex;
-	    lex->sql_command = SQLCOM_SHOW_BINLOG_EVENTS;
-	    lex->select->select_limit= lex->thd->variables.select_limit;
-	    lex->select->offset_limit= 0L;
+	    LEX *lex= Lex;
+	    lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS;
+	    lex->select_lex.select_limit= lex->thd->variables.select_limit;
+	    lex->select_lex.offset_limit= 0L;
           } limit_clause
 	| keys_or_index FROM table_ident opt_db
 	  {
 	    Lex->sql_command= SQLCOM_SHOW_KEYS;
 	    if ($4)
 	      $3->change_db($4);
-	    if (!add_table_to_list($3,NULL,0))
+	    if (!Select->add_table_to_list($3, NULL, 0))
 	      YYABORT;
 	  }
 	| COLUMN_SYM TYPES_SYM
@@ -3075,7 +3156,7 @@ show_param:
         | CREATE TABLE_SYM table_ident
           {
 	    Lex->sql_command = SQLCOM_SHOW_CREATE;
-	    if(!add_table_to_list($3, NULL,0))
+	    if(!Select->add_table_to_list($3, NULL,0))
 	      YYABORT;
 	  }
         | MASTER_SYM STATUS_SYM
@@ -3120,7 +3201,7 @@ describe:
 	  lex->wild=0;
 	  lex->verbose=0;
 	  lex->sql_command=SQLCOM_SHOW_FIELDS;
-	  if (!add_table_to_list($2, NULL,0))
+	  if (!Select->add_table_to_list($2, NULL,0))
 	    YYABORT;
 	}
 	opt_describe_column
@@ -3221,7 +3302,8 @@ kill:
 use:	USE_SYM ident
 	{
 	  LEX *lex=Lex;
-	  lex->sql_command=SQLCOM_CHANGE_DB; lex->select->db= $2.str;
+	  lex->sql_command=SQLCOM_CHANGE_DB;
+	  lex->select_lex.db= $2.str;
 	};
 
 /* import, export of files */
@@ -3238,14 +3320,14 @@ load:	LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING
 	opt_duplicate INTO TABLE_SYM table_ident opt_field_term opt_line_term
 	opt_ignore_lines opt_field_spec
 	{
-	  if (!add_table_to_list($11,NULL,1))
+	  if (!Select->add_table_to_list($11, NULL, 1))
 	    YYABORT;
 	}
         |
 	LOAD TABLE_SYM table_ident FROM MASTER_SYM
         {
 	  Lex->sql_command = SQLCOM_LOAD_MASTER_TABLE;
-	  if (!add_table_to_list($3,NULL,1))
+	  if (!Select->add_table_to_list($3, NULL, 1))
 	    YYABORT;
 
         }
@@ -3370,23 +3452,23 @@ order_ident:
 simple_ident:
 	ident
 	{
-	  SELECT_LEX *sel=Select;
-	  $$ = !sel->create_refs || sel->in_sum_expr > 0 ? (Item*) new Item_field(NullS,NullS,$1.str) : (Item*) new Item_ref(NullS,NullS,$1.str);
+	  SELECT_LEX_NODE *sel=Select;
+	  $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field(NullS,NullS,$1.str) : (Item*) new Item_ref(NullS,NullS,$1.str);
 	}
 	| ident '.' ident
 	{
-	  SELECT_LEX *sel=Select;
-	  $$ = !sel->create_refs || sel->in_sum_expr > 0 ? (Item*) new Item_field(NullS,$1.str,$3.str) : (Item*) new Item_ref(NullS,$1.str,$3.str);
+	  SELECT_LEX_NODE *sel=Select;
+	  $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field(NullS,$1.str,$3.str) : (Item*) new Item_ref(NullS,$1.str,$3.str);
 	}
 	| '.' ident '.' ident
 	{
-	  SELECT_LEX *sel=Select;
-	  $$ = !sel->create_refs || sel->in_sum_expr > 0 ? (Item*) new Item_field(NullS,$2.str,$4.str) : (Item*) new Item_ref(NullS,$2.str,$4.str);
+	  SELECT_LEX_NODE *sel=Select;
+	  $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field(NullS,$2.str,$4.str) : (Item*) new Item_ref(NullS,$2.str,$4.str);
 	}
 	| ident '.' ident '.' ident
 	{
-	  SELECT_LEX *sel=Select;
-	  $$ = !sel->create_refs || sel->in_sum_expr > 0 ? (Item*) new Item_field((current_thd->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str) : (Item*) new Item_ref((current_thd->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str);
+	  SELECT_LEX_NODE *sel=Select;
+	  $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field((current_thd->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str) : (Item*) new Item_ref((current_thd->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str);
 	};
 
 
@@ -3738,7 +3820,10 @@ table_lock_list:
 
 table_lock:
 	table_ident opt_table_alias lock_option
-	{ if (!add_table_to_list($1,$2,0,(thr_lock_type) $3)) YYABORT; }
+	{
+	  if (!Select->add_table_to_list($1, $2, 0, (thr_lock_type) $3))
+	   YYABORT;
+	}
         ;
 
 lock_option:
@@ -3760,14 +3845,16 @@ unlock:
 handler:
 	HANDLER_SYM table_ident OPEN_SYM opt_table_alias
 	{
-	  Lex->sql_command = SQLCOM_HA_OPEN;
-	  if (!add_table_to_list($2,$4,0))
+	  LEX *lex= Lex;
+	  lex->sql_command = SQLCOM_HA_OPEN;
+	  if (!lex->current_select->add_table_to_list($2, $4, 0))
 	    YYABORT;
 	}
 	| HANDLER_SYM table_ident CLOSE_SYM
 	{
-	  Lex->sql_command = SQLCOM_HA_CLOSE;
-	  if (!add_table_to_list($2,0,0))
+	  LEX *lex= Lex;
+	  lex->sql_command = SQLCOM_HA_CLOSE;
+	  if (!lex->current_select->add_table_to_list($2, 0, 0))
 	    YYABORT;
 	}
 	| HANDLER_SYM table_ident READ_SYM
@@ -3775,9 +3862,9 @@ handler:
 	  LEX *lex=Lex;
 	  lex->sql_command = SQLCOM_HA_READ;
 	  lex->ha_rkey_mode= HA_READ_KEY_EXACT;	/* Avoid purify warnings */
-	  lex->select->select_limit= 1;
-	  lex->select->offset_limit= 0L;
-	  if (!add_table_to_list($2,0,0))
+	  lex->current_select->select_limit= 1;
+	  lex->current_select->offset_limit= 0L;
+	  if (!lex->current_select->add_table_to_list($2, 0, 0))
 	    YYABORT;
         }
         handler_read_or_scan where_clause limit_clause { }
@@ -3826,7 +3913,7 @@ revoke:
 	  lex->users_list.empty();
 	  lex->columns.empty();
 	  lex->grant= lex->grant_tot_col=0;
-	  lex->select->db=0;
+	  lex->select_lex.db=0;
 	  lex->ssl_type= SSL_TYPE_NOT_SPECIFIED;
 	  lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0;
 	  bzero((char*) &lex->mqh, sizeof(lex->mqh));
@@ -3841,7 +3928,7 @@ grant:
 	  lex->columns.empty();
 	  lex->sql_command = SQLCOM_GRANT;
 	  lex->grant= lex->grant_tot_col= 0;
-	  lex->select->db= 0;
+	  lex->select_lex.db= 0;
 	  lex->ssl_type= SSL_TYPE_NOT_SPECIFIED;
 	  lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0;
 	  bzero(&(lex->mqh),sizeof(lex->mqh));
@@ -3931,8 +4018,13 @@ require_list_element:
 opt_table:
 	'*'
 	  {
-	    LEX *lex=Lex;
-	    lex->select->db=lex->thd->db;
+	    LEX *lex= Lex;
+	    /* 
+	      There are (SELECT_LEX *) pointer conversionis here and following
+	      opt_table, because it is impossible GRANT clause in global 
+	      union parameters
+	    */
+	    ((SELECT_LEX *)lex->current_select)->db= lex->thd->db;
 	    if (lex->grant == GLOBAL_ACLS)
 	      lex->grant = DB_ACLS & ~GRANT_ACL;
 	    else if (lex->columns.elements)
@@ -3943,8 +4035,8 @@ opt_table:
 	  }
 	| ident '.' '*'
 	  {
-	    LEX *lex=Lex;
-	    lex->select->db = $1.str;
+	    LEX *lex= Lex;
+	    ((SELECT_LEX *)lex->current_select)->db = $1.str;
 	    if (lex->grant == GLOBAL_ACLS)
 	      lex->grant = DB_ACLS & ~GRANT_ACL;
 	    else if (lex->columns.elements)
@@ -3955,8 +4047,8 @@ opt_table:
 	  }
 	| '*' '.' '*'
 	  {
-	    LEX *lex=Lex;
-	    lex->select->db = NULL;
+	    LEX *lex= Lex;
+	    ((SELECT_LEX *)lex->current_select)->db = NULL;
 	    if (lex->grant == GLOBAL_ACLS)
 	      lex->grant= GLOBAL_ACLS & ~GRANT_ACL;
 	    else if (lex->columns.elements)
@@ -3968,7 +4060,7 @@ opt_table:
 	| table_ident
 	  {
 	    LEX *lex=Lex;
-	    if (!add_table_to_list($1,NULL,0))
+	    if (!lex->current_select->add_table_to_list($1,NULL,0))
 	      YYABORT;
 	    if (lex->grant == GLOBAL_ACLS)
 	      lex->grant =  TABLE_ACLS & ~GRANT_ACL;
@@ -4123,14 +4215,14 @@ union_list:
 	    net_printf(lex->thd, ER_WRONG_USAGE, "UNION", "INTO");
 	    YYABORT;
 	  } 
-	  if (lex->select->linkage == GLOBAL_OPTIONS_TYPE)
+	  if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
 	  {
 	    send_error(lex->thd, ER_SYNTAX_ERROR);
 	    YYABORT;
 	  }
 	  if (mysql_new_select(lex, 0))
 	    YYABORT;
-	  lex->select->linkage=UNION_TYPE;
+	  lex->current_select->linkage=UNION_TYPE;
 	}
 	select_init
 	;
@@ -4144,19 +4236,17 @@ optional_order_or_limit:
 	|
 	  {
 	    LEX *lex=Lex;
-	    if (!lex->select->braces)
+	    if (!lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
 	    {
 	      send_error(lex->thd, ER_SYNTAX_ERROR);
 	      YYABORT;
 	    }
-	    lex->select->master_unit()->global_parameters= 
-	      lex->select->master_unit();
-	    /*
-	      Following type conversion looks like hack, but all that need
-	      SELECT_LEX fields always check linkage type.
-	    */
-	    lex->select= (SELECT_LEX*)lex->select->master_unit();
-	    lex->select->select_limit=lex->thd->variables.select_limit;
+	    SELECT_LEX *sel= (SELECT_LEX *)lex->current_select;
+	    sel->master_unit()->global_parameters= 
+	      sel->master_unit();
+	    lex->current_select= sel->master_unit();
+	    lex->current_select->select_limit=
+	      lex->thd->variables.select_limit;
 	  }
 	opt_order_clause limit_clause
 	;
@@ -4176,7 +4266,8 @@ singleval_subselect_init:
 	select_init
 	{
 	  $$= new Item_singleval_subselect(current_thd,
-					   Lex->select->master_unit()->first_select());
+					   Lex->current_select->master_unit()->
+                                             first_select());
 	};
 
 exists_subselect:
@@ -4190,7 +4281,8 @@ exists_subselect_init:
 	select_init
 	{
 	  $$= new Item_exists_subselect(current_thd,
-					Lex->select->master_unit()->first_select());
+					Lex->current_select->master_unit()->
+					  first_select());
 	};
 
 subselect_start:
@@ -4204,5 +4296,5 @@ subselect_end:
 	')'
 	{
 	  LEX *lex=Lex;
-	  lex->select = lex->select->outer_select();
+	  lex->current_select = lex->current_select->outer_select();
 	};