/* Copyright (c) 2023, MariaDB plc
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 St, Fifth Floor, Boston, MA 02110-1335 USA */
#include "mariadb.h"
#include "sql_priv.h"
#include <m_ctype.h>
#include "sql_partition.h"
#include "sql_select.h"
#include "opt_trace.h"
/*
@ brief
Check if passed item is " UCASE ( table . colX ) " where colX is either covered
by some index or is a part of partition expression .
@ return
Argument of the UCASE if passed item matches
NULL otherwise .
*/
static Item* is_upper_key_col(Item *item)
{
Item_func_ucase *item_func;
if ((item_func= dynamic_cast <Item_func_ucase*>(item)))
{
Item *arg= item_func->arguments()[0 ];
Item *arg_real= arg->real_item();
if (arg_real->type() == Item::FIELD_ITEM)
{
if (dynamic_cast <const Type_handler_longstr*>(arg_real->type_handler()))
{
Field *field= ((Item_field*)arg_real)->field;
bool appl= (field->flags & PART_KEY_FLAG);
#ifdef WITH_PARTITION_STORAGE_ENGINE
partition_info *part_info;
if (!appl && ((part_info= field->table->part_info)))
{
appl= bitmap_is_set(&part_info->full_part_field_set,
field->field_index);
}
#endif
if (appl)
{
/*
Make sure COERCIBILITY ( UPPER ( col ) ) = COERCIBILITY ( col )
*/
DBUG_ASSERT(arg->collation.derivation ==
item_func->collation.derivation);
/* Return arg, not arg_real. Do not walk into Item_ref objects */
return arg;
}
}
}
}
return nullptr;
}
static void trace_upper_removal_rewrite(THD *thd, Item *old_item, Item *new_item)
{
Json_writer_object trace_wrapper(thd);
Json_writer_object obj(thd, "sargable_casefold_removal" );
obj.add("before" , old_item)
.add("after" , new_item);
}
/*
@ brief
Rewrite UPPER ( key_varchar_col ) = expr into key_varchar_col = expr
@ detail
UPPER ( ) may occur on both sides of the equality .
UCASE ( ) is a synonym of UPPER ( ) so we handle it , too .
*/
Item* Item_func_eq::varchar_upper_cmp_transformer(THD *thd, uchar *arg)
{
if (cmp.compare_type() == STRING_RESULT &&
cmp.compare_collation()->state & MY_CS_UPPER_EQUAL_AS_EQUAL)
{
Item *arg0= arguments()[0 ];
Item *arg1= arguments()[1 ];
bool do_rewrite= false ;
Item *tmp;
// Try rewriting the left argument
if ((tmp= is_upper_key_col(arguments()[0 ])))
{
arg0= tmp;
do_rewrite= true ;
}
// Try rewriting the right argument
if ((tmp= is_upper_key_col(arguments()[1 ])))
{
arg1=tmp;
do_rewrite= true ;
}
if (do_rewrite)
{
Item *res= new (thd->mem_root) Item_func_eq(thd, arg0, arg1);
if (res && !res->fix_fields(thd, &res))
{
trace_upper_removal_rewrite(thd, this , res);
return res;
}
}
}
return this ;
}
/*
@ brief
Rewrite " UPPER ( key_col ) IN ( const - list ) " into " key_col IN ( const - list ) "
*/
Item* Item_func_in::varchar_upper_cmp_transformer(THD *thd, uchar *arg)
{
if (arg_types_compatible &&
m_comparator.cmp_type() == STRING_RESULT &&
cmp_collation.collation->state & MY_CS_UPPER_EQUAL_AS_EQUAL &&
all_items_are_consts(args + 1 , arg_count - 1 ))
{
Item *arg0= arguments()[0 ];
Item *tmp;
if ((tmp= is_upper_key_col(arg0)))
{
Item_func_in *cl= (Item_func_in*)deep_copy_with_checks(thd);
if (!cl)
return this ;
Item *res;
cl->arguments()[0 ]= tmp;
cl->walk(&Item::cleanup_excluding_const_fields_processor, 0 , 0 );
res= cl;
if (res->fix_fields(thd, &res))
return this ;
trace_upper_removal_rewrite(thd, this , res);
return res;
}
}
return this ;
}
Messung V0.5 in Prozent C=96 H=100 G=97
¤ Dauer der Verarbeitung: 0.0 Sekunden
(vorverarbeitet am 2026-10-08)
¤
*© Formatika GbR, Deutschland