mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
Implemented the implementation of percentile functions using Item_cache instead of Cache_Item
This commit is contained in:
@@ -5322,10 +5322,7 @@ public:
|
|||||||
cmp();
|
cmp();
|
||||||
item= save;
|
item= save;
|
||||||
}
|
}
|
||||||
Item* get_item()
|
|
||||||
{
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
null_value= false;
|
null_value= false;
|
||||||
|
@@ -111,7 +111,7 @@ Item_window_func::fix_fields(THD *thd, Item **ref)
|
|||||||
|
|
||||||
if (only_single_element_order_list())
|
if (only_single_element_order_list())
|
||||||
{
|
{
|
||||||
// need to change the error, the error should say that we have more than one element in the order list
|
//TODO (varun): need to change the error, the error should say that we have more than one element in the order list
|
||||||
if (window_spec->order_list->elements != 1)
|
if (window_spec->order_list->elements != 1)
|
||||||
{
|
{
|
||||||
my_error(ER_NO_ORDER_LIST_IN_WINDOW_SPEC, MYF(0), window_func()->func_name());
|
my_error(ER_NO_ORDER_LIST_IN_WINDOW_SPEC, MYF(0), window_func()->func_name());
|
||||||
@@ -207,12 +207,12 @@ void Item_sum_dense_rank::setup_window_func(THD *thd, Window_spec *window_spec)
|
|||||||
|
|
||||||
void Item_sum_percentile_disc::setup_window_func(THD *thd, Window_spec *window_spec)
|
void Item_sum_percentile_disc::setup_window_func(THD *thd, Window_spec *window_spec)
|
||||||
{
|
{
|
||||||
setup_percentile_func(thd, window_spec->order_list);
|
order_item= window_spec->order_list->first->item[0];
|
||||||
}
|
set_handler_by_cmp_type(order_item->result_type());
|
||||||
|
if (!(value= order_item->get_cache(thd)))
|
||||||
void Item_sum_percentile_disc::set_type_handler(Window_spec *window_spec)
|
return;
|
||||||
{
|
value->setup(thd, order_item);
|
||||||
type_handler()->get_handler_by_cmp_type(window_spec->order_list->first->item[0]->result_type());
|
value->store(order_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Item_sum_dense_rank::add()
|
bool Item_sum_dense_rank::add()
|
||||||
|
@@ -42,6 +42,12 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Group_bound_tracker(THD *thd, Item *item)
|
||||||
|
{
|
||||||
|
Cached_item *tmp= new_Cached_item(thd, item, FALSE);
|
||||||
|
group_fields.push_back(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
first_check= true;
|
first_check= true;
|
||||||
@@ -117,7 +123,6 @@ private:
|
|||||||
bool first_check;
|
bool first_check;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ROW_NUMBER() OVER (...)
|
ROW_NUMBER() OVER (...)
|
||||||
|
|
||||||
@@ -725,7 +730,7 @@ class Item_sum_percentile_disc : public Item_sum_cume_dist,
|
|||||||
public:
|
public:
|
||||||
Item_sum_percentile_disc(THD *thd, Item* arg) : Item_sum_cume_dist(thd, arg),
|
Item_sum_percentile_disc(THD *thd, Item* arg) : Item_sum_cume_dist(thd, arg),
|
||||||
Type_handler_hybrid_field_type(&type_handler_longlong),
|
Type_handler_hybrid_field_type(&type_handler_longlong),
|
||||||
value(NULL), result_value(NULL), val_calculated(FALSE) {}
|
value(NULL), val_calculated(FALSE), first_call(TRUE),prev_value(0), order_item(NULL){}
|
||||||
|
|
||||||
double val_real()
|
double val_real()
|
||||||
{
|
{
|
||||||
@@ -735,7 +740,7 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
null_value= false;
|
null_value= false;
|
||||||
return ((Cached_item_real*) result_value)->get_value();
|
return value->val_real();
|
||||||
}
|
}
|
||||||
|
|
||||||
longlong val_int()
|
longlong val_int()
|
||||||
@@ -746,7 +751,7 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
null_value= false;
|
null_value= false;
|
||||||
return ((Cached_item_int*) result_value)->get_value();
|
return value->val_int();
|
||||||
}
|
}
|
||||||
|
|
||||||
my_decimal* val_decimal(my_decimal* dec)
|
my_decimal* val_decimal(my_decimal* dec)
|
||||||
@@ -757,7 +762,7 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
null_value= false;
|
null_value= false;
|
||||||
return ((Cached_item_decimal*) result_value)->get_value();
|
return value->val_decimal(dec);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool add()
|
bool add()
|
||||||
@@ -765,31 +770,32 @@ public:
|
|||||||
Item *arg = get_arg(0);
|
Item *arg = get_arg(0);
|
||||||
if (arg->is_null())
|
if (arg->is_null())
|
||||||
return true;
|
return true;
|
||||||
/*
|
|
||||||
need to ensure that the Item arg is constant across the entire partition
|
|
||||||
and its value ranges between [0,1]
|
|
||||||
*/
|
|
||||||
value->cmp();
|
|
||||||
|
|
||||||
/* for the null values of the row, we dont count take those rows in account for calculating
|
if (first_call)
|
||||||
the CUME_DIST */
|
{
|
||||||
|
prev_value= arg->val_real();
|
||||||
|
first_call= false;
|
||||||
|
}
|
||||||
|
|
||||||
if(value->null_value)
|
if(prev_value != arg->val_real() || prev_value >1 || prev_value < 0)
|
||||||
|
{
|
||||||
|
// TODO(varun) need to add an error here , check the MDEV-12985 for the information
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val_calculated)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
value->store(order_item);
|
||||||
|
value->cache_value();
|
||||||
|
if (value->null_value)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Item_sum_cume_dist::add();
|
Item_sum_cume_dist::add();
|
||||||
double val1= Item_sum_cume_dist::val_real();
|
double val= Item_sum_cume_dist::val_real();
|
||||||
/* need to check type and return value accordingly*/
|
|
||||||
double val2 =arg->val_real_from_decimal();
|
|
||||||
|
|
||||||
/* use Cached_item to do the comparision using cmp_read_only() */
|
if(val >= prev_value && !val_calculated)
|
||||||
|
|
||||||
if( val1 >= val2 && !val_calculated)
|
|
||||||
{
|
|
||||||
val_calculated= true;
|
val_calculated= true;
|
||||||
result_value->cmp();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -801,8 +807,8 @@ public:
|
|||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
val_calculated= false;
|
val_calculated= false;
|
||||||
|
first_call= true;
|
||||||
value->clear();
|
value->clear();
|
||||||
result_value->clear();
|
|
||||||
Item_sum_cume_dist::clear();
|
Item_sum_cume_dist::clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -825,33 +831,19 @@ public:
|
|||||||
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
||||||
{ return get_item_copy<Item_sum_percentile_disc>(thd, mem_root, this); }
|
{ return get_item_copy<Item_sum_percentile_disc>(thd, mem_root, this); }
|
||||||
void setup_window_func(THD *thd, Window_spec *window_spec);
|
void setup_window_func(THD *thd, Window_spec *window_spec);
|
||||||
void setup_percentile_func(THD *thd, SQL_I_List<ORDER> *list)
|
void setup_hybrid(THD *thd, Item *item);
|
||||||
{
|
|
||||||
value= new_Cached_item(thd, list->first->item[0], FALSE);
|
|
||||||
result_value= new_Cached_item(thd, list->first->item[0], FALSE);
|
|
||||||
}
|
|
||||||
void cleanup()
|
|
||||||
{
|
|
||||||
if (value)
|
|
||||||
{
|
|
||||||
delete value;
|
|
||||||
value= NULL;
|
|
||||||
}
|
|
||||||
if(result_value)
|
|
||||||
{
|
|
||||||
delete result_value;
|
|
||||||
result_value= NULL;
|
|
||||||
}
|
|
||||||
Item_sum_num::cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Cached_item *value;
|
Item_cache *value;
|
||||||
Cached_item *result_value;
|
|
||||||
bool val_calculated;
|
bool val_calculated;
|
||||||
|
bool first_call;
|
||||||
|
double prev_value;
|
||||||
|
Item *order_item;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Item_window_func : public Item_func_or_sum
|
class Item_window_func : public Item_func_or_sum
|
||||||
{
|
{
|
||||||
/* Window function parameters as we've got them from the parser */
|
/* Window function parameters as we've got them from the parser */
|
||||||
|
@@ -319,10 +319,6 @@ setup_windows(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
|
|||||||
while ((win_func_item= li++))
|
while ((win_func_item= li++))
|
||||||
{
|
{
|
||||||
win_func_item->update_used_tables();
|
win_func_item->update_used_tables();
|
||||||
if (win_func_item->only_single_element_order_list())
|
|
||||||
{
|
|
||||||
((Item_sum_percentile_disc*)win_func_item)->set_type_handler(win_func_item->window_spec);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
@@ -908,14 +904,13 @@ private:
|
|||||||
class Partition_read_cursor : public Table_read_cursor
|
class Partition_read_cursor : public Table_read_cursor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Partition_read_cursor(THD *thd, SQL_I_List<ORDER> *partition_list, SQL_I_List<ORDER> *order_list) :
|
Partition_read_cursor(THD *thd, SQL_I_List<ORDER> *partition_list) :
|
||||||
bound_tracker(thd, partition_list), order_tracker(thd, order_list) {}
|
bound_tracker(thd, partition_list){}
|
||||||
|
|
||||||
void init(READ_RECORD *info)
|
void init(READ_RECORD *info)
|
||||||
{
|
{
|
||||||
Table_read_cursor::init(info);
|
Table_read_cursor::init(info);
|
||||||
bound_tracker.init();
|
bound_tracker.init();
|
||||||
order_tracker.init();
|
|
||||||
end_of_partition= false;
|
end_of_partition= false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -967,42 +962,18 @@ public:
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
bool next_func(ha_rows *counter)
|
bool check_for_end_of_partition()
|
||||||
{
|
{
|
||||||
if (next())
|
return end_of_partition;
|
||||||
return true;
|
|
||||||
if (!check_for_null_row())
|
|
||||||
{
|
|
||||||
(*counter)++;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool fetch_func(ha_rows *counter)
|
|
||||||
{
|
|
||||||
if (fetch())
|
|
||||||
return true;
|
|
||||||
if (!check_for_null_row())
|
|
||||||
{
|
|
||||||
(*counter)++;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool check_for_null_row()
|
|
||||||
{
|
|
||||||
if (!end_of_partition)
|
|
||||||
{
|
|
||||||
if (order_tracker.compare_with_cache_for_null_values())
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Group_bound_tracker bound_tracker;
|
Group_bound_tracker bound_tracker;
|
||||||
Group_bound_tracker order_tracker;
|
|
||||||
bool end_of_partition;
|
bool end_of_partition;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1231,7 +1202,7 @@ public:
|
|||||||
SQL_I_List<ORDER> *partition_list,
|
SQL_I_List<ORDER> *partition_list,
|
||||||
SQL_I_List<ORDER> *order_list,
|
SQL_I_List<ORDER> *order_list,
|
||||||
bool is_preceding_arg, Item *n_val_arg) :
|
bool is_preceding_arg, Item *n_val_arg) :
|
||||||
cursor(thd, partition_list, NULL), n_val(n_val_arg), item_add(NULL),
|
cursor(thd, partition_list), n_val(n_val_arg), item_add(NULL),
|
||||||
is_preceding(is_preceding_arg)
|
is_preceding(is_preceding_arg)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(order_list->elements == 1);
|
DBUG_ASSERT(order_list->elements == 1);
|
||||||
@@ -1370,7 +1341,7 @@ public:
|
|||||||
SQL_I_List<ORDER> *partition_list,
|
SQL_I_List<ORDER> *partition_list,
|
||||||
SQL_I_List<ORDER> *order_list,
|
SQL_I_List<ORDER> *order_list,
|
||||||
bool is_preceding_arg, Item *n_val_arg) :
|
bool is_preceding_arg, Item *n_val_arg) :
|
||||||
cursor(thd, partition_list, NULL), n_val(n_val_arg), item_add(NULL),
|
cursor(thd, partition_list), n_val(n_val_arg), item_add(NULL),
|
||||||
is_preceding(is_preceding_arg), added_values(false)
|
is_preceding(is_preceding_arg), added_values(false)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(order_list->elements == 1);
|
DBUG_ASSERT(order_list->elements == 1);
|
||||||
@@ -1500,7 +1471,7 @@ public:
|
|||||||
Frame_range_current_row_bottom(THD *thd,
|
Frame_range_current_row_bottom(THD *thd,
|
||||||
SQL_I_List<ORDER> *partition_list,
|
SQL_I_List<ORDER> *partition_list,
|
||||||
SQL_I_List<ORDER> *order_list) :
|
SQL_I_List<ORDER> *order_list) :
|
||||||
cursor(thd, partition_list, NULL), peer_tracker(thd, order_list)
|
cursor(thd, partition_list), peer_tracker(thd, order_list)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1715,7 +1686,7 @@ public:
|
|||||||
Frame_unbounded_following(THD *thd,
|
Frame_unbounded_following(THD *thd,
|
||||||
SQL_I_List<ORDER> *partition_list,
|
SQL_I_List<ORDER> *partition_list,
|
||||||
SQL_I_List<ORDER> *order_list) :
|
SQL_I_List<ORDER> *order_list) :
|
||||||
cursor(thd, partition_list, order_list){}
|
cursor(thd, partition_list){}
|
||||||
|
|
||||||
void init(READ_RECORD *info)
|
void init(READ_RECORD *info)
|
||||||
{
|
{
|
||||||
@@ -1758,7 +1729,7 @@ public:
|
|||||||
Frame_unbounded_following_set_count(
|
Frame_unbounded_following_set_count(
|
||||||
THD *thd,
|
THD *thd,
|
||||||
SQL_I_List<ORDER> *partition_list, SQL_I_List<ORDER> *order_list) :
|
SQL_I_List<ORDER> *partition_list, SQL_I_List<ORDER> *order_list) :
|
||||||
Frame_unbounded_following(thd, partition_list, order_list) {}
|
Frame_unbounded_following(thd, partition_list, order_list){}
|
||||||
|
|
||||||
void next_partition(ha_rows rownum)
|
void next_partition(ha_rows rownum)
|
||||||
{
|
{
|
||||||
@@ -1769,7 +1740,9 @@ public:
|
|||||||
|
|
||||||
/* Walk to the end of the partition, find how many rows there are. */
|
/* Walk to the end of the partition, find how many rows there are. */
|
||||||
while (!cursor.next())
|
while (!cursor.next())
|
||||||
|
{
|
||||||
num_rows_in_partition++;
|
num_rows_in_partition++;
|
||||||
|
}
|
||||||
|
|
||||||
List_iterator_fast<Item_sum> it(sum_functions);
|
List_iterator_fast<Item_sum> it(sum_functions);
|
||||||
Item_sum* item;
|
Item_sum* item;
|
||||||
@@ -1787,23 +1760,29 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Frame_unbounded_following_set_count_special : public Frame_unbounded_following_set_count
|
class Frame_unbounded_following_set_count_special: public Frame_unbounded_following_set_count
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
Frame_unbounded_following_set_count_special(
|
|
||||||
THD *thd,
|
|
||||||
SQL_I_List<ORDER> *partition_list, SQL_I_List<ORDER> *order_list) :
|
|
||||||
Frame_unbounded_following_set_count(thd, partition_list, order_list)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
Frame_unbounded_following_set_count_special(THD *thd,
|
||||||
|
SQL_I_List<ORDER> *partition_list,
|
||||||
|
SQL_I_List<ORDER> *order_list, Item* arg) :
|
||||||
|
Frame_unbounded_following_set_count(thd,partition_list, order_list)
|
||||||
|
{
|
||||||
|
order_item= order_list->first->item[0];
|
||||||
|
}
|
||||||
void next_partition(ha_rows rownum)
|
void next_partition(ha_rows rownum)
|
||||||
{
|
{
|
||||||
ha_rows num_rows_in_partition= 0;
|
ha_rows num_rows_in_partition= 0;
|
||||||
if (cursor.fetch_func(&num_rows_in_partition))
|
if (cursor.fetch())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Walk to the end of the partition, find how many rows there are. */
|
/* Walk to the end of the partition, find how many rows there are. */
|
||||||
while (!cursor.next_func(&num_rows_in_partition));
|
do
|
||||||
|
{
|
||||||
|
if (!order_item->is_null())
|
||||||
|
num_rows_in_partition++;
|
||||||
|
}while (!cursor.next());
|
||||||
|
|
||||||
List_iterator_fast<Item_sum> it(sum_functions);
|
List_iterator_fast<Item_sum> it(sum_functions);
|
||||||
Item_sum* item;
|
Item_sum* item;
|
||||||
@@ -1814,6 +1793,13 @@ public:
|
|||||||
item_with_row_count->set_row_count(num_rows_in_partition);
|
item_with_row_count->set_row_count(num_rows_in_partition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ha_rows get_curr_rownum() const
|
||||||
|
{
|
||||||
|
return cursor.get_rownum();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Item* order_item;
|
||||||
};
|
};
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -2013,7 +1999,7 @@ public:
|
|||||||
SQL_I_List<ORDER> *order_list,
|
SQL_I_List<ORDER> *order_list,
|
||||||
bool is_top_bound_arg, ha_rows n_rows_arg) :
|
bool is_top_bound_arg, ha_rows n_rows_arg) :
|
||||||
is_top_bound(is_top_bound_arg), n_rows(n_rows_arg),
|
is_top_bound(is_top_bound_arg), n_rows(n_rows_arg),
|
||||||
cursor(thd, partition_list, NULL)
|
cursor(thd, partition_list)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2628,7 +2614,7 @@ void get_window_functions_required_cursors(
|
|||||||
{
|
{
|
||||||
fc= new Frame_unbounded_following_set_count_special(thd,
|
fc= new Frame_unbounded_following_set_count_special(thd,
|
||||||
item_win_func->window_spec->partition_list,
|
item_win_func->window_spec->partition_list,
|
||||||
item_win_func->window_spec->order_list);
|
item_win_func->window_spec->order_list, item_win_func->window_func()->get_arg(0));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user