summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2003-08-12 12:38:03 +0300
committerunknown <bell@sanja.is.com.ua>2003-08-12 12:38:03 +0300
commit4a36d2ada66e1aa4d685b1b69094ff5226b24e5f (patch)
treebf79484f7cc14e515e3fc508ecb3815329621ca3 /sql
parent168b5179794a8ee3fc09dbaba4dcdf0f724f3312 (diff)
downloadmariadb-git-4a36d2ada66e1aa4d685b1b69094ff5226b24e5f.tar.gz
optimisation of independent ALL/ANY with aggregate function (WL#1115) (SCRUM)
mysql-test/r/subselect.result: test of new optimisation mysql-test/t/subselect.test: test of new optimisation sql/item_subselect.cc: special subselect to finding max/min of returned values optimisation of independent ALL/ANY with aggregate function sql/item_subselect.h: special subselect to finding max/min of returned values sql/sql_class.cc: class for collaction result for max/min subquery sql/sql_class.h: class for collaction result for max/min subquery
Diffstat (limited to 'sql')
-rw-r--r--sql/item_subselect.cc84
-rw-r--r--sql/item_subselect.h10
-rw-r--r--sql/sql_class.cc89
-rw-r--r--sql/sql_class.h16
4 files changed, 169 insertions, 30 deletions
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 77300dd2cf3..c6e421d763c 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -152,8 +152,8 @@ inline table_map Item_subselect::used_tables() const
}
Item_singlerow_subselect::Item_singlerow_subselect(THD *thd,
- st_select_lex *select_lex):
- Item_subselect(), value(0)
+ st_select_lex *select_lex)
+ :Item_subselect(), value(0)
{
DBUG_ENTER("Item_singlerow_subselect::Item_singlerow_subselect");
init(thd, select_lex, new select_singlerow_subselect(this));
@@ -163,6 +163,19 @@ Item_singlerow_subselect::Item_singlerow_subselect(THD *thd,
DBUG_VOID_RETURN;
}
+Item_maxmin_subselect::Item_maxmin_subselect(THD *thd,
+ st_select_lex *select_lex,
+ bool max)
+ :Item_singlerow_subselect()
+{
+ DBUG_ENTER("Item_maxmin_subselect::Item_maxmin_subselect");
+ init(thd, select_lex, new select_max_min_finder_subselect(this, max));
+ max_columns= 1;
+ maybe_null= 1;
+ max_columns= 1;
+ DBUG_VOID_RETURN;
+}
+
void Item_singlerow_subselect::reset()
{
null_value= 1;
@@ -499,38 +512,50 @@ Item_in_subselect::single_value_transformer(JOIN *join,
(func == &Item_bool_func2::gt_creator ||
func == &Item_bool_func2::lt_creator ||
func == &Item_bool_func2::ge_creator ||
- func == &Item_bool_func2::le_creator) &&
- !select_lex->group_list.elements &&
- !select_lex->with_sum_func)
+ func == &Item_bool_func2::le_creator))
{
- Item *item;
- subs_type type= substype();
- if (func == &Item_bool_func2::le_creator ||
- func == &Item_bool_func2::lt_creator)
+ Item *subs;
+ if (!select_lex->group_list.elements &&
+ !select_lex->with_sum_func)
{
- /*
- (ALL && (> || =>)) || (ANY && (< || =<))
- for ALL condition is inverted
- */
- item= new Item_sum_max(*select_lex->ref_pointer_array);
+ Item *item;
+ subs_type type= substype();
+ if (func == &Item_bool_func2::le_creator ||
+ func == &Item_bool_func2::lt_creator)
+ {
+ /*
+ (ALL && (> || =>)) || (ANY && (< || =<))
+ for ALL condition is inverted
+ */
+ item= new Item_sum_max(*select_lex->ref_pointer_array);
+ }
+ else
+ {
+ /*
+ (ALL && (< || =<)) || (ANY && (> || =>))
+ for ALL condition is inverted
+ */
+ item= new Item_sum_min(*select_lex->ref_pointer_array);
+ }
+ *select_lex->ref_pointer_array= item;
+ select_lex->item_list.empty();
+ select_lex->item_list.push_back(item);
+
+ if (item->fix_fields(thd, join->tables_list, &item))
+ {
+ DBUG_RETURN(ERROR);
+ }
+ subs= new Item_singlerow_subselect(thd, select_lex);
}
else
{
- /*
- (ALL && (< || =<)) || (ANY && (> || =>))
- for ALL condition is inverted
- */
- item= new Item_sum_min(*select_lex->ref_pointer_array);
- }
- *select_lex->ref_pointer_array= item;
- select_lex->item_list.empty();
- select_lex->item_list.push_back(item);
-
- if (item->fix_fields(thd, join->tables_list, &item))
- {
- DBUG_RETURN(ERROR);
+ // remove LIMIT placed by ALL/ANY subquery
+ select_lex->master_unit()->global_parameters->select_limit=
+ HA_POS_ERROR;
+ subs= new Item_maxmin_subselect(thd, select_lex,
+ (func == &Item_bool_func2::le_creator ||
+ func == &Item_bool_func2::lt_creator));
}
-
// left expression belong to outer select
SELECT_LEX *current= thd->lex.current_select, *up;
thd->lex.current_select= up= current->return_after_parsing();
@@ -540,8 +565,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
DBUG_RETURN(ERROR);
}
thd->lex.current_select= current;
- substitution= (*func)(left_expr,
- new Item_singlerow_subselect(thd, select_lex));
+ substitution= (*func)(left_expr, subs);
DBUG_RETURN(OK);
}
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 9cfa304bb47..d3aa8f59e49 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -130,6 +130,7 @@ public:
max_length= item->max_length;
decimals= item->decimals;
}
+ Item_singlerow_subselect() :Item_subselect(), value(0), row (0) {}
subs_type substype() { return SINGLEROW_SUBS; }
@@ -153,6 +154,15 @@ public:
friend class select_singlerow_subselect;
};
+/* used in static ALL/ANY optimisation */
+class Item_maxmin_subselect: public Item_singlerow_subselect
+{
+public:
+ Item_maxmin_subselect(THD *thd, st_select_lex *select_lex, bool max);
+ Item_maxmin_subselect(Item_maxmin_subselect *item)
+ :Item_singlerow_subselect(item) {}
+};
+
/* exists subselect */
class Item_exists_subselect :public Item_subselect
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index c233ffd422a..6f72d592b6f 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -986,6 +986,95 @@ bool select_singlerow_subselect::send_data(List<Item> &items)
DBUG_RETURN(0);
}
+bool select_max_min_finder_subselect::send_data(List<Item> &items)
+{
+ DBUG_ENTER("select_max_min_finder_subselect::send_data");
+ Item_singlerow_subselect *it= (Item_singlerow_subselect *)item;
+ List_iterator_fast<Item> li(items);
+ Item *val_item= li++;
+ if (it->assigned())
+ {
+ cache->store(val_item);
+ if ((this->*op)())
+ it->store(0, cache);
+ }
+ else
+ {
+ if (!cache)
+ {
+ cache= Item_cache::get_cache(val_item->result_type());
+ switch (val_item->result_type())
+ {
+ case REAL_RESULT:
+ op= &select_max_min_finder_subselect::cmp_real;
+ break;
+ case INT_RESULT:
+ op= &select_max_min_finder_subselect::cmp_int;
+ break;
+ case STRING_RESULT:
+ op= &select_max_min_finder_subselect::cmp_str;
+ break;
+ case ROW_RESULT:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ op= 0;
+ }
+ }
+ cache->store(val_item);
+ it->store(0, cache);
+ }
+ it->assigned(1);
+ DBUG_RETURN(0);
+}
+
+bool select_max_min_finder_subselect::cmp_real()
+{
+ Item *maxmin= ((Item_singlerow_subselect *)item)->el(0);
+ double val1= cache->val(), val2= maxmin->val();
+ if (fmax)
+ return (cache->null_value && !maxmin->null_value) ||
+ (!cache->null_value && !maxmin->null_value &&
+ val1 > val2);
+ else
+ return (maxmin->null_value && !cache->null_value) ||
+ (!cache->null_value && !maxmin->null_value &&
+ val1 < val2);
+}
+
+bool select_max_min_finder_subselect::cmp_int()
+{
+ Item *maxmin= ((Item_singlerow_subselect *)item)->el(0);
+ longlong val1= cache->val_int(), val2= maxmin->val_int();
+ if (fmax)
+ return (cache->null_value && !maxmin->null_value) ||
+ (!cache->null_value && !maxmin->null_value &&
+ val1 > val2);
+ else
+ return (maxmin->null_value && !cache->null_value) ||
+ (!cache->null_value && !maxmin->null_value &&
+ val1 < val2);
+}
+
+bool select_max_min_finder_subselect::cmp_str()
+{
+ String *val1, *val2, buf1, buf2;
+ Item *maxmin= ((Item_singlerow_subselect *)item)->el(0);
+ /*
+ as far as both operand is Item_cache buf1 & buf2 will not be used,
+ but added for safety
+ */
+ val1= cache->val_str(&buf1);
+ val2= maxmin->val_str(&buf1);
+ if (fmax)
+ return (cache->null_value && !maxmin->null_value) ||
+ (!cache->null_value && !maxmin->null_value &&
+ sortcmp(val1, val2, cache->collation.collation) > 0) ;
+ else
+ return (maxmin->null_value && !cache->null_value) ||
+ (!cache->null_value && !maxmin->null_value &&
+ sortcmp(val1, val2, cache->collation.collation) < 0);
+}
+
bool select_exists_subselect::send_data(List<Item> &items)
{
DBUG_ENTER("select_exists_subselect::send_data");
diff --git a/sql/sql_class.h b/sql/sql_class.h
index f6336cb7dd9..0c17c7b2b49 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -920,6 +920,22 @@ public:
bool send_data(List<Item> &items);
};
+/* used in independent ALL/ANY optimisation */
+class select_max_min_finder_subselect :public select_subselect
+{
+ Item_cache *cache;
+ bool (select_max_min_finder_subselect::*op)();
+ bool fmax;
+public:
+ select_max_min_finder_subselect(Item_subselect *item, bool mx)
+ :select_subselect(item), cache(0), fmax(mx)
+ {}
+ bool send_data(List<Item> &items);
+ bool cmp_real();
+ bool cmp_int();
+ bool cmp_str();
+};
+
/* EXISTS subselect interface class */
class select_exists_subselect :public select_subselect
{