diff options
Diffstat (limited to 'sql/sql_window.cc')
-rw-r--r-- | sql/sql_window.cc | 90 |
1 files changed, 84 insertions, 6 deletions
diff --git a/sql/sql_window.cc b/sql/sql_window.cc index 7ae967d7077..3869628dfea 100644 --- a/sql/sql_window.cc +++ b/sql/sql_window.cc @@ -1,3 +1,4 @@ +#include "sql_parse.h" #include "sql_select.h" #include "sql_list.h" #include "item_windowfunc.h" @@ -12,13 +13,13 @@ Window_spec::check_window_names(List_iterator_fast<Window_spec> &it) { if (window_names_are_checked) return false; - char *name= this->name(); - char *ref_name= window_reference(); + const char *name= this->name(); + const char *ref_name= window_reference(); it.rewind(); Window_spec *win_spec; while((win_spec= it++) && win_spec != this) { - char *win_spec_name= win_spec->name(); + const char *win_spec_name= win_spec->name(); if (!win_spec_name) break; if (name && my_strcasecmp(system_charset_info, name, win_spec_name) == 0) @@ -307,6 +308,82 @@ setup_windows(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, DBUG_RETURN(0); } + +/** + @brief + Find fields common for all partition lists used in window functions + + @param thd The thread handle + + @details + This function looks for the field references in the partition lists + of all window functions used in this select that are common for + all the partition lists. The function returns an ORDER list contained + all such references.The list either is specially built by the function + or is taken directly from the first window specification. + + @retval + pointer to the first element of the ORDER list contained field + references common for all partition lists + 0 if no such reference is found. +*/ + +ORDER *st_select_lex::find_common_window_func_partition_fields(THD *thd) +{ + ORDER *ord; + Item *item; + DBUG_ASSERT(window_funcs.elements); + List_iterator_fast<Item_window_func> it(window_funcs); + Item_window_func *first_wf= it++; + if (!first_wf->window_spec->partition_list) + return 0; + List<Item> common_fields; + uint first_partition_elements= 0; + for (ord= first_wf->window_spec->partition_list->first; ord; ord= ord->next) + { + if ((*ord->item)->real_item()->type() == Item::FIELD_ITEM) + common_fields.push_back(*ord->item, thd->mem_root); + first_partition_elements++; + } + if (window_specs.elements == 1 && + common_fields.elements == first_partition_elements) + return first_wf->window_spec->partition_list->first; + List_iterator<Item> li(common_fields); + Item_window_func *wf; + while (common_fields.elements && (wf= it++)) + { + if (!wf->window_spec->partition_list) + return 0; + while ((item= li++)) + { + for (ord= wf->window_spec->partition_list->first; ord; ord= ord->next) + { + if (item->eq(*ord->item, false)) + break; + } + if (!ord) + li.remove(); + } + li.rewind(); + } + if (!common_fields.elements) + return 0; + if (common_fields.elements == first_partition_elements) + return first_wf->window_spec->partition_list->first; + SQL_I_List<ORDER> res_list; + for (ord= first_wf->window_spec->partition_list->first, item= li++; + ord; ord= ord->next) + { + if (item != *ord->item) + continue; + if (add_to_list(thd, res_list, item, ord->direction)) + return 0; + item= li++; + } + return res_list.first; +} + + ///////////////////////////////////////////////////////////////////////////// // Sorting window functions to minimize the number of table scans // performed during the computation of these functions @@ -327,7 +404,8 @@ int compare_order_elements(ORDER *ord1, ORDER *ord2) Item *item2= (*ord2->item)->real_item(); DBUG_ASSERT(item1->type() == Item::FIELD_ITEM && item2->type() == Item::FIELD_ITEM); - ptrdiff_t cmp= ((Item_field *) item1)->field - ((Item_field *) item2)->field; + int cmp= ((Item_field *) item1)->field->field_index - + ((Item_field *) item2)->field->field_index; if (cmp == 0) { if (ord1->direction == ord2->direction) @@ -384,8 +462,8 @@ int compare_window_frame_bounds(Window_frame_bound *win_frame_bound1, return CMP_EQ; else { - res= strcmp(win_frame_bound1->offset->name, - win_frame_bound2->offset->name); + res= strcmp(win_frame_bound1->offset->name.str, + win_frame_bound2->offset->name.str); res= res > 0 ? CMP_GT : CMP_LT; if (is_bottom_bound) res= -res; |