summaryrefslogtreecommitdiff
path: root/sql/sql_derived.cc
diff options
context:
space:
mode:
authorSergei Petrunia <psergey@askmonty.org>2021-06-30 15:06:54 +0300
committerSergei Petrunia <psergey@askmonty.org>2021-06-30 15:06:54 +0300
commit586870f9effa48831fda2590f2aee2b95b30be39 (patch)
treebc674573cb34b871045c4db1ebd7d7eea1349314 /sql/sql_derived.cc
parent29098083f7ac3b445ee59c3e765eb634ec70b947 (diff)
parenteb20c91b55e4b51be533314994b36bf9b24016f3 (diff)
downloadmariadb-git-586870f9effa48831fda2590f2aee2b95b30be39.tar.gz
Merge 10.2->10.3
Diffstat (limited to 'sql/sql_derived.cc')
-rw-r--r--sql/sql_derived.cc79
1 files changed, 73 insertions, 6 deletions
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 8f10013bed1..93dc62828ac 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -1264,6 +1264,68 @@ bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived)
}
+/*
+ @brief
+ Given condition cond and transformer+argument, try transforming as many
+ conjuncts as possible.
+
+ @detail
+ The motivation of this function is to convert the condition that's being
+ pushed into a WHERE clause with derived_field_transformer_for_where or
+ with derived_grouping_field_transformer_for_where.
+ The transformer may fail for some sub-condition, in this case we want to
+ convert the most restrictive part of the condition that can be pushed.
+
+ This function only does it for top-level AND: conjuncts that could not be
+ converted are dropped.
+
+ @return
+ Converted condition, or NULL if nothing could be converted
+*/
+
+static
+Item *transform_condition_or_part(THD *thd,
+ Item *cond,
+ Item_transformer transformer,
+ uchar *arg)
+{
+ if (cond->type() != Item::COND_ITEM ||
+ ((Item_cond*) cond)->functype() != Item_func::COND_AND_FUNC)
+ {
+ Item *new_item= cond->transform(thd, transformer, arg);
+ // Indicate that the condition is not pushable
+ if (!new_item)
+ cond->clear_extraction_flag();
+ return new_item;
+ }
+
+ List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
+ Item *item;
+ while ((item=li++))
+ {
+ Item *new_item= item->transform(thd, transformer, arg);
+ if (!new_item)
+ {
+ // Indicate that the condition is not pushable
+ item->clear_extraction_flag();
+ li.remove();
+ }
+ else
+ li.replace(new_item);
+ }
+
+ switch (((Item_cond*) cond)->argument_list()->elements)
+ {
+ case 0:
+ return NULL;
+ case 1:
+ return ((Item_cond*) cond)->argument_list()->head();
+ default:
+ return cond;
+ }
+}
+
+
/**
@brief
Extract the condition depended on derived table/view and pushed it there
@@ -1395,9 +1457,11 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
if (!sl->join->group_list && !sl->with_sum_func)
{
/* extracted_cond_copy is pushed into where of sl */
- extracted_cond_copy= extracted_cond_copy->transform(thd,
- &Item::derived_field_transformer_for_where,
- (uchar*) sl);
+ extracted_cond_copy=
+ transform_condition_or_part(thd,
+ extracted_cond_copy,
+ &Item::derived_field_transformer_for_where,
+ (uchar*)sl);
if (extracted_cond_copy)
{
extracted_cond_copy->walk(
@@ -1424,9 +1488,12 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
pushed into the where clause of sl to make them usable in the new context
*/
if (cond_over_grouping_fields)
- cond_over_grouping_fields= cond_over_grouping_fields->transform(thd,
- &Item::derived_grouping_field_transformer_for_where,
- (uchar*) sl);
+ {
+ cond_over_grouping_fields=
+ transform_condition_or_part(thd, cond_over_grouping_fields,
+ &Item::derived_grouping_field_transformer_for_where,
+ (uchar*) sl);
+ }
if (cond_over_grouping_fields)
{