mariadb/sql/item_windowfunc.cc
Igor Babaev 0c6d753708 Fixed a problems in the parser.
Resolved window names.
Checked some constraints for window frames.
Added test cases for window name resolution.
2016-02-19 23:20:09 -08:00

146 lines
3.4 KiB
C++

#include "item_windowfunc.h"
#include "my_dbug.h"
#include "my_global.h"
#include "sql_select.h" // test if group changed
bool
Item_window_func::resolve_window_name(THD *thd)
{
DBUG_ASSERT(window_name != NULL && window_spec == NULL);
char *ref_name= window_name->str;
/* !TODO: Add the code to resolve ref_name in outer queries */
/*
First look for the deinition of the window with 'window_name'
in the current select
*/
List<Window_spec> curr_window_specs=thd->lex->current_select->window_specs;
List_iterator_fast<Window_spec> it(curr_window_specs);
Window_spec *win_spec;
while((win_spec= it++))
{
char *win_spec_name= win_spec->name();
if (win_spec_name &&
my_strcasecmp(system_charset_info, ref_name, win_spec_name) == 0)
{
window_spec= win_spec;
break;
}
}
if (!window_spec)
{
my_error(ER_WRONG_WINDOW_SPEC_NAME, MYF(0), ref_name);
return true;
}
return false;
}
bool
Item_window_func::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
if (window_name && resolve_window_name(thd))
return true;
/*
TODO: why the last parameter is 'ref' in this call? What if window_func
decides to substitute itself for something else and does *ref=.... ?
This will substitute *this (an Item_window_func object) with Item_sum
object. Is this the intent?
*/
if (window_func->fix_fields(thd, ref))
return true;
max_length= window_func->max_length;
fixed= 1;
force_return_blank= true;
read_value_from_result_field= false;
return false;
}
/*
This must be called before advance_window() can be called.
@detail
If we attempt to do it in fix_fields(), partition_fields will refer
to the original window function arguments.
We need it to refer to temp.table columns.
*/
void Item_window_func::setup_partition_border_check(THD *thd)
{
for (ORDER *curr= window_spec->partition_list.first; curr; curr=curr->next)
{
//curr->item_ptr->fix_fields(thd, curr->item);
Cached_item *tmp= new_Cached_item(thd, curr->item[0], TRUE);
partition_fields.push_back(tmp);
}
window_func->setup_window_func(thd, window_spec);
}
void Item_sum_rank::setup_window_func(THD *thd, Window_spec *window_spec)
{
/* TODO: move this into Item_window_func? */
for (ORDER *curr= window_spec->order_list.first; curr; curr=curr->next)
{
Cached_item *tmp= new_Cached_item(thd, curr->item[0], TRUE);
orderby_fields.push_back(tmp);
}
clear();
}
void Item_sum_dense_rank::setup_window_func(THD *thd, Window_spec *window_spec)
{
/* TODO: consider moving this && Item_sum_rank's implementation */
for (ORDER *curr= window_spec->order_list.first; curr; curr=curr->next)
{
Cached_item *tmp= new_Cached_item(thd, curr->item[0], TRUE);
orderby_fields.push_back(tmp);
}
clear();
}
bool Item_sum_dense_rank::add()
{
if (test_if_group_changed(orderby_fields) > -1)
dense_rank++;
return false;
}
bool Item_sum_rank::add()
{
row_number++;
if (test_if_group_changed(orderby_fields) > -1)
{
/* Row value changed */
cur_rank= row_number;
}
return false;
}
int Item_window_func::check_partition_bound()
{
return test_if_group_changed(partition_fields);
}
void Item_window_func::advance_window()
{
int changed= check_partition_bound();
if (changed > -1)
{
/* Next partition */
window_func->clear();
}
window_func->add();
}