You've already forked mariadb-columnstore-engine
							
							
				mirror of
				https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
				synced 2025-10-30 07:25:34 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			151 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			151 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* Copyright (C) 2019-20 MariaDB Corporation
 | |
| 
 | |
|    This program is free software; you can redistribute it and/or
 | |
|    modify it under the terms of the GNU General Public License
 | |
|    as published by the Free Software Foundation; version 2 of
 | |
|    the License.
 | |
| 
 | |
|    This program is distributed in the hope that it will be useful,
 | |
|    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|    GNU General Public License for more details.
 | |
| 
 | |
|    You should have received a copy of the GNU General Public License
 | |
|    along with this program; if not, write to the Free Software
 | |
|    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 | |
|    MA 02110-1301, USA. */
 | |
| 
 | |
| #include <typeinfo>
 | |
| 
 | |
| #include "ha_mcs_opt_rewrites.h"
 | |
| 
 | |
| /*@brief  in_subselect_rewrite_walk - Rewrites Item_in_subselect*/
 | |
| /************************************************************
 | |
|  * DESCRIPTION:
 | |
|  * It traverses filter predicates searching for
 | |
|  * Item_in_subselect and rewrites it adding equi-join predicate
 | |
|  * to finalise IN_2_EXISTS rewrite.
 | |
|  * PARAMETERS:
 | |
|  *    item_arg - Item to check.
 | |
|  *    arg - bool to early return if predicate injection fails.
 | |
|  * RETURN:
 | |
|  ***********************************************************/
 | |
| void in_subselect_rewrite_walk(const Item* item_arg, void* arg)
 | |
| {
 | |
|   bool* result = reinterpret_cast<bool*>(arg);
 | |
|   if (*result)
 | |
|     return;
 | |
| 
 | |
|   Item* item = const_cast<Item*>(item_arg);
 | |
| 
 | |
|   JOIN* join = nullptr;
 | |
|   if (typeid(*item) == typeid(Item_in_subselect))
 | |
|   {
 | |
|     Item_in_subselect* sub = reinterpret_cast<Item_in_subselect*>(item);
 | |
|     // MCS 1.4.3 doesn't support IN + subquery with UNION so
 | |
|     // we safe to take this JOIN.
 | |
|     join = sub->unit->first_select()->join;
 | |
|     // Inject equi-JOIN predicates if needed.
 | |
|     *result = sub->create_in_to_exists_cond(join);
 | |
|     *result = (*result) ? *result : sub->inject_in_to_exists_cond(join);
 | |
|     sub->unit->first_select()->prep_where = join->conds ? join->conds->copy_andor_structure(current_thd) : 0;
 | |
|   }
 | |
|   else if (typeid(*item) == typeid(Item_singlerow_subselect))
 | |
|   {
 | |
|     Item_singlerow_subselect* sub = reinterpret_cast<Item_singlerow_subselect*>(item);
 | |
|     // MCS 1.4.3 doesn't support IN + subquery with UNION so
 | |
|     // we safe to take this JOIN.
 | |
|     join = sub->unit->first_select()->join;
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     // Exit for any but dedicated Items.
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // Walk recursively to process nested IN ops.
 | |
|   if (join->conds)
 | |
|   {
 | |
|     join->conds->traverse_cond(in_subselect_rewrite_walk, arg, Item::POSTFIX);
 | |
|   }
 | |
| }
 | |
| 
 | |
| // Sets SELECT_LEX::first_cond_optimization
 | |
| void first_cond_optimization_flag_set(SELECT_LEX* select_lex)
 | |
| {
 | |
|   select_lex->first_cond_optimization = true;
 | |
| }
 | |
| 
 | |
| // Unsets SELECT_LEX::first_cond_optimization
 | |
| void first_cond_optimization_flag_unset(SELECT_LEX* select_lex)
 | |
| {
 | |
|   select_lex->first_cond_optimization = false;
 | |
| }
 | |
| 
 | |
| /* @brief  first_cond_optimization_flag_toggle() - Sets/Unsets first_cond_optimization */
 | |
| /************************************************************
 | |
|  * DESCRIPTION:
 | |
|  * This function traverses SELECT_LEX::table_list recursively
 | |
|  * to set/unset SELECT_LEX::first_cond_optimization: a marker
 | |
|  * to control optimizations executing PS. If set it allows to
 | |
|  * apply optimizations. If unset, it disables optimizations.
 | |
|  * PARAMETERS:
 | |
|  *    select_lex - SELECT_LEX* that describes the query.
 | |
|  *    func - Pointer to a function which either sets/unsets
 | |
|  *           SELECT_LEX::first_cond_optimization
 | |
|  ***********************************************************/
 | |
| void first_cond_optimization_flag_toggle(SELECT_LEX* select_lex, void (*func)(SELECT_LEX*))
 | |
| {
 | |
|   for (TABLE_LIST* tl = select_lex->get_table_list(); tl; tl = tl->next_local)
 | |
|   {
 | |
|     if (tl->is_view_or_derived())
 | |
|     {
 | |
|       SELECT_LEX_UNIT* unit = tl->get_unit();
 | |
| 
 | |
|       if (unit)
 | |
|       {
 | |
|         for (SELECT_LEX* sl = unit->first_select(); sl; sl = sl->next_select())
 | |
|         {
 | |
|           first_cond_optimization_flag_toggle(sl, func);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   (*func)(select_lex);
 | |
| }
 | |
| 
 | |
| /* @brief  in_subselect_rewrite - Rewrites Item_in_subselect */
 | |
| /************************************************************
 | |
|  * DESCRIPTION:
 | |
|  * This function traverses TABLE_LISTs running in_subselect_rewrite_walk
 | |
|  * PARAMETERS:
 | |
|  *    select_lex - SELECT_LEX* that describes the query.
 | |
|  * RETURN:
 | |
|  *    bool to indicate predicate injection failures.
 | |
|  ***********************************************************/
 | |
| bool in_subselect_rewrite(SELECT_LEX* select_lex)
 | |
| {
 | |
|   bool result = false;
 | |
|   TABLE_LIST* tbl;
 | |
|   List_iterator_fast<TABLE_LIST> li(select_lex->leaf_tables);
 | |
| 
 | |
|   while (!result && (tbl = li++))
 | |
|   {
 | |
|     if (tbl->is_view_or_derived())
 | |
|     {
 | |
|       SELECT_LEX_UNIT* unit = tbl->get_unit();
 | |
| 
 | |
|       for (SELECT_LEX* sl = unit->first_select(); sl; sl = sl->next_select())
 | |
|         result = in_subselect_rewrite(sl);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (select_lex->join && select_lex->join->conds)
 | |
|   {
 | |
|     select_lex->join->conds->traverse_cond(in_subselect_rewrite_walk, &result, Item::POSTFIX);
 | |
|   }
 | |
| 
 | |
|   return result;
 | |
| }
 |