Commit d8a20d4d authored by Sergei Petrunia's avatar Sergei Petrunia

Post-merge fixes. win.test passes but further cleanup is needed.

parent a9ed132a
...@@ -29,8 +29,8 @@ insert into t1 values (3, 10, 'xxx'); ...@@ -29,8 +29,8 @@ insert into t1 values (3, 10, 'xxx');
insert into t1 values (3, 20, 'vvv'); insert into t1 values (3, 20, 'vvv');
select a, row_number() over (partition by a order by b) from t1; select a, row_number() over (partition by a order by b) from t1;
a row_number() over (partition by a order by b) a row_number() over (partition by a order by b)
2 1
2 2 2 2
2 1
2 3 2 3
3 1 3 1
3 2 3 2
......
...@@ -19,6 +19,7 @@ Item_window_func::fix_fields(THD *thd, Item **ref) ...@@ -19,6 +19,7 @@ Item_window_func::fix_fields(THD *thd, Item **ref)
return TRUE; return TRUE;
fixed= 1; fixed= 1;
force_return_blank= true;
read_value_from_result_field= false; read_value_from_result_field= false;
return FALSE; return FALSE;
} }
......
...@@ -19,11 +19,18 @@ class Item_sum_row_number: public Item_sum_int ...@@ -19,11 +19,18 @@ class Item_sum_row_number: public Item_sum_int
{ {
longlong count; longlong count;
void clear() {} public:
bool add() { return false; } void clear()
{
count= 0;
}
bool add()
{
count++;
return false;
}
void update_field() {} void update_field() {}
public:
Item_sum_row_number(THD *thd) Item_sum_row_number(THD *thd)
: Item_sum_int(thd), count(0) {} : Item_sum_int(thd), count(0) {}
...@@ -32,6 +39,10 @@ class Item_sum_row_number: public Item_sum_int ...@@ -32,6 +39,10 @@ class Item_sum_row_number: public Item_sum_int
return ROW_NUMBER_FUNC; return ROW_NUMBER_FUNC;
} }
longlong val_int()
{
return count;
}
const char*func_name() const const char*func_name() const
{ {
return "row_number"; return "row_number";
...@@ -251,19 +262,29 @@ class Item_sum_cume_dist: public Item_sum_num ...@@ -251,19 +262,29 @@ class Item_sum_cume_dist: public Item_sum_num
class Item_window_func : public Item_result_field class Item_window_func : public Item_result_field
{ {
/* Window function parameters as we've got them from the parser */
Item_sum *window_func; Item_sum *window_func;
LEX_STRING *window_name; LEX_STRING *window_name;
public:
Window_spec *window_spec; Window_spec *window_spec;
/*
This stores the data bout the partition we're currently in.
advance_window() uses this to tell when we've left one partition and
entered another.
*/
List<Cached_item> partition_fields;
public: public:
Item_window_func(THD *thd, Item_sum *win_func, LEX_STRING *win_name) Item_window_func(THD *thd, Item_sum *win_func, LEX_STRING *win_name)
: Item_result_field(thd), window_func(win_func), : Item_result_field(thd), window_func(win_func),
window_name(win_name), window_spec(NULL), window_name(win_name), window_spec(NULL),
force_return_blank(true),
read_value_from_result_field(false) {} read_value_from_result_field(false) {}
Item_window_func(THD *thd, Item_sum *win_func, Window_spec *win_spec) Item_window_func(THD *thd, Item_sum *win_func, Window_spec *win_spec)
: Item_result_field(thd), window_func(win_func), : Item_result_field(thd), window_func(win_func),
window_name(NULL), window_spec(win_spec), window_name(NULL), window_spec(win_spec),
force_return_blank(true),
read_value_from_result_field(false) {} read_value_from_result_field(false) {}
/* /*
...@@ -271,6 +292,8 @@ class Item_window_func : public Item_result_field ...@@ -271,6 +292,8 @@ class Item_window_func : public Item_result_field
*/ */
void setup_partition_border_check(THD *thd); void setup_partition_border_check(THD *thd);
void advance_window();
enum_field_types field_type() const { return window_func->field_type(); } enum_field_types field_type() const { return window_func->field_type(); }
enum Item::Type type() const { return Item::WINDOW_FUNC_ITEM; } enum Item::Type type() const { return Item::WINDOW_FUNC_ITEM; }
...@@ -292,7 +315,11 @@ class Item_window_func : public Item_result_field ...@@ -292,7 +315,11 @@ class Item_window_func : public Item_result_field
item_windowfunc->val_int() will be called. item_windowfunc->val_int() will be called.
During Phase#3, read_value_from_result_field= true. During Phase#3, read_value_from_result_field= true.
*/ */
public:
// TODO: how to reset this for subquery re-execution??
bool force_return_blank;
private: private:
bool read_value_from_result_field; bool read_value_from_result_field;
public: public:
...@@ -303,24 +330,32 @@ class Item_window_func : public Item_result_field ...@@ -303,24 +330,32 @@ class Item_window_func : public Item_result_field
double val_real() double val_real()
{ {
if (force_return_blank)
return 0.0;
return read_value_from_result_field? result_field->val_real() : return read_value_from_result_field? result_field->val_real() :
window_func->val_real(); window_func->val_real();
} }
longlong val_int() longlong val_int()
{ {
if (force_return_blank)
return 0;
return read_value_from_result_field? result_field->val_int() : return read_value_from_result_field? result_field->val_int() :
window_func->val_int(); window_func->val_int();
} }
String* val_str(String* str) String* val_str(String* str)
{ {
if (force_return_blank)
return str;
return read_value_from_result_field? result_field->val_str(str) : return read_value_from_result_field? result_field->val_str(str) :
window_func->val_str(str); window_func->val_str(str);
} }
my_decimal* val_decimal(my_decimal* dec) my_decimal* val_decimal(my_decimal* dec)
{ {
if (force_return_blank)
return dec;
return read_value_from_result_field? result_field->val_decimal(dec) : return read_value_from_result_field? result_field->val_decimal(dec) :
window_func->val_decimal(dec); window_func->val_decimal(dec);
} }
......
...@@ -181,7 +181,6 @@ end_update(JOIN *join, JOIN_TAB *join_tab, bool end_of_records); ...@@ -181,7 +181,6 @@ end_update(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
static enum_nested_loop_state static enum_nested_loop_state
end_unique_update(JOIN *join, JOIN_TAB *join_tab, bool end_of_records); end_unique_update(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
static int test_if_group_changed(List<Cached_item> &list);
static int join_read_const_table(THD *thd, JOIN_TAB *tab, POSITION *pos); static int join_read_const_table(THD *thd, JOIN_TAB *tab, POSITION *pos);
static int join_read_system(JOIN_TAB *tab); static int join_read_system(JOIN_TAB *tab);
static int join_read_const(JOIN_TAB *tab); static int join_read_const(JOIN_TAB *tab);
...@@ -234,7 +233,7 @@ static bool list_contains_unique_index(TABLE *table, ...@@ -234,7 +233,7 @@ static bool list_contains_unique_index(TABLE *table,
bool (*find_func) (Field *, void *), void *data); bool (*find_func) (Field *, void *), void *data);
static bool find_field_in_item_list (Field *field, void *data); static bool find_field_in_item_list (Field *field, void *data);
static bool find_field_in_order_list (Field *field, void *data); static bool find_field_in_order_list (Field *field, void *data);
static int create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab); int create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab);
static int remove_dup_with_compare(THD *thd, TABLE *entry, Field **field, static int remove_dup_with_compare(THD *thd, TABLE *entry, Field **field,
Item *having); Item *having);
static int remove_dup_with_hash_index(THD *thd,TABLE *table, static int remove_dup_with_hash_index(THD *thd,TABLE *table,
...@@ -3235,7 +3234,6 @@ void JOIN::exec_inner() ...@@ -3235,7 +3234,6 @@ void JOIN::exec_inner()
error= thd->is_error(); error= thd->is_error();
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
process_window_functions(curr_fields_list);
THD_STAGE_INFO(thd, stage_sending_data); THD_STAGE_INFO(thd, stage_sending_data);
DBUG_PRINT("info", ("%s", thd->proc_info)); DBUG_PRINT("info", ("%s", thd->proc_info));
...@@ -8500,6 +8498,11 @@ bool JOIN::get_best_combination() ...@@ -8500,6 +8498,11 @@ bool JOIN::get_best_combination()
(tmp_table_param. using_outer_summary_function ? 2 : 1) : 0) + (tmp_table_param. using_outer_summary_function ? 2 : 1) : 0) +
(order ? 1 : 0) + (order ? 1 : 0) +
(select_options & (SELECT_BIG_RESULT | OPTION_BUFFER_RESULT) ? 1 : 0) ; (select_options & (SELECT_BIG_RESULT | OPTION_BUFFER_RESULT) ? 1 : 0) ;
// psergey-temp:
if (select_lex->window_specs.elements)
aggr_tables++;
if (aggr_tables > 2) if (aggr_tables > 2)
aggr_tables= 2; aggr_tables= 2;
if (!(join_tab= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)* if (!(join_tab= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)*
...@@ -19062,7 +19065,7 @@ int join_init_read_record(JOIN_TAB *tab) ...@@ -19062,7 +19065,7 @@ int join_init_read_record(JOIN_TAB *tab)
if (tab->distinct && tab->remove_duplicates()) // Remove duplicates. if (tab->distinct && tab->remove_duplicates()) // Remove duplicates.
return 1; return 1;
if (tab->filesort && tab->sort_table()) // Sort table. if (tab->filesort && !tab->used_for_window_func && tab->sort_table()) // Sort table.
return 1; return 1;
if (tab->select && tab->select->quick && (error= tab->select->quick->reset())) if (tab->select && tab->select->quick && (error= tab->select->quick->reset()))
...@@ -21102,7 +21105,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, ...@@ -21102,7 +21105,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
1 No records 1 No records
*/ */
static int int
create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab) create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab)
{ {
ha_rows examined_rows; ha_rows examined_rows;
...@@ -22347,7 +22350,7 @@ int test_if_item_cache_changed(List<Cached_item> &list) ...@@ -22347,7 +22350,7 @@ int test_if_item_cache_changed(List<Cached_item> &list)
value>=0 - Number of the component where the group changed value>=0 - Number of the component where the group changed
*/ */
static int int
test_if_group_changed(List<Cached_item> &list) test_if_group_changed(List<Cached_item> &list)
{ {
DBUG_ENTER("test_if_group_changed"); DBUG_ENTER("test_if_group_changed");
...@@ -25810,8 +25813,10 @@ AGGR_OP::end_send() ...@@ -25810,8 +25813,10 @@ AGGR_OP::end_send()
table->file->print_error(new_errno,MYF(0)); table->file->print_error(new_errno,MYF(0));
return NESTED_LOOP_ERROR; return NESTED_LOOP_ERROR;
} }
// Update ref array // Update ref array
join_tab->join->set_items_ref_array(*join_tab->ref_array); join_tab->join->set_items_ref_array(*join_tab->ref_array);
join->process_window_functions(&join->fields_list); // location #2
table->reginfo.lock_type= TL_UNLOCK; table->reginfo.lock_type= TL_UNLOCK;
bool in_first_read= true; bool in_first_read= true;
......
...@@ -424,6 +424,8 @@ typedef struct st_join_table { ...@@ -424,6 +424,8 @@ typedef struct st_join_table {
/* Sorting related info */ /* Sorting related info */
Filesort *filesort; Filesort *filesort;
bool used_for_window_func;
/** /**
List of topmost expressions in the select list. The *next* JOIN TAB List of topmost expressions in the select list. The *next* JOIN TAB
in the plan should use it to obtain correct values. Same applicable to in the plan should use it to obtain correct values. Same applicable to
...@@ -2295,4 +2297,6 @@ class Pushdown_query: public Sql_alloc ...@@ -2295,4 +2297,6 @@ class Pushdown_query: public Sql_alloc
}; };
bool test_if_order_compatible(SQL_I_List<ORDER> &a, SQL_I_List<ORDER> &b); bool test_if_order_compatible(SQL_I_List<ORDER> &a, SQL_I_List<ORDER> &b);
int test_if_group_changed(List<Cached_item> &list);
int create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab);
#endif /* SQL_SELECT_INCLUDED */ #endif /* SQL_SELECT_INCLUDED */
...@@ -233,9 +233,24 @@ bool JOIN::process_window_functions(List<Item> *curr_fields_list) ...@@ -233,9 +233,24 @@ bool JOIN::process_window_functions(List<Item> *curr_fields_list)
if (item->type() == Item::WINDOW_FUNC_ITEM) if (item->type() == Item::WINDOW_FUNC_ITEM)
{ {
Item_window_func *item_win = (Item_window_func *) item; Item_window_func *item_win = (Item_window_func *) item;
item_win->force_return_blank= false;
Window_spec *spec = item_win->window_spec; Window_spec *spec = item_win->window_spec;
DBUG_ASSERT(spec->partition_list.next[0] == NULL);
*(spec->partition_list.next)= spec->order_list.first;
// spec->partition_list // spec->partition_list
// spec->order_list // spec->order_list
add_sorting_to_table(&join_tab[top_join_tab_count],
spec->partition_list.first);
join_tab[top_join_tab_count].used_for_window_func= true;
create_sort_index(this->thd, this, &join_tab[top_join_tab_count]);
*(spec->partition_list.next)= NULL;
//join_tab[top_join_tab_count] has the temp. table that we need.
//bool JOIN::add_sorting_to_table(JOIN_TAB *tab, ORDER *order)
// spec->partition_list.first
#if 0
ha_rows examined_rows = 0; ha_rows examined_rows = 0;
ha_rows found_rows = 0; ha_rows found_rows = 0;
ha_rows filesort_retval; ha_rows filesort_retval;
...@@ -277,18 +292,19 @@ bool JOIN::process_window_functions(List<Item> *curr_fields_list) ...@@ -277,18 +292,19 @@ bool JOIN::process_window_functions(List<Item> *curr_fields_list)
join_tab->records= found_rows; join_tab->records= found_rows;
my_free(s_order); my_free(s_order);
#endif
/* /*
Go through the sorted array and compute the window function Go through the sorted array and compute the window function
*/ */
READ_RECORD info; READ_RECORD info;
if (init_read_record(&info, thd, table[0], select, 0, 1, FALSE)) //TABLE *tbl= *table;
TABLE *tbl= join_tab[top_join_tab_count].table;
if (init_read_record(&info, thd, tbl, select, 0, 1, FALSE))
return true; return true;
item_win->setup_partition_border_check(thd); item_win->setup_partition_border_check(thd);
int err; int err;
TABLE *tbl= *table;
while (!(err=info.read_record(&info))) while (!(err=info.read_record(&info)))
{ {
store_record(tbl,record[1]); store_record(tbl,record[1]);
...@@ -311,8 +327,10 @@ bool JOIN::process_window_functions(List<Item> *curr_fields_list) ...@@ -311,8 +327,10 @@ bool JOIN::process_window_functions(List<Item> *curr_fields_list)
} }
item_win->set_read_value_from_result_field(); item_win->set_read_value_from_result_field();
end_read_record(&info); end_read_record(&info);
#if 0
filesort_free_buffers(table[0], true); filesort_free_buffers(table[0], true);
free_io_cache(table[0]); free_io_cache(table[0]);
#endif
} }
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment