diff --git a/sql/item_windowfunc.cc b/sql/item_windowfunc.cc index 8a35cd34e82..051dc203ab9 100644 --- a/sql/item_windowfunc.cc +++ b/sql/item_windowfunc.cc @@ -117,6 +117,12 @@ Item_window_func::fix_fields(THD *thd, Item **ref) my_error(ER_NO_ORDER_LIST_IN_WINDOW_SPEC, MYF(0), window_func()->func_name()); return true; } + /*switch(window_spec->order_list->firt->item[0]->type()) + { + case INT_TYPE: + default: + break; + }*/ } /* @@ -215,6 +221,21 @@ void Item_sum_percentile_disc::setup_window_func(THD *thd, Window_spec *window_s value->store(order_item); } +void Item_sum_percentile_cont::setup_window_func(THD *thd, Window_spec *window_spec) +{ + order_item= window_spec->order_list->first->item[0]; + //set_handler_by_cmp_type(order_item->result_type()); + if (!(ceil_value= order_item->get_cache(thd))) + return; + ceil_value->setup(thd, order_item); + ceil_value->store(order_item); + + if (!(floor_value= order_item->get_cache(thd))) + return; + floor_value->setup(thd, order_item); + floor_value->store(order_item); +} + bool Item_sum_dense_rank::add() { if (peer_tracker->check_if_next_group() || first_add) diff --git a/sql/item_windowfunc.h b/sql/item_windowfunc.h index 7c6c3c87025..9dfff36f952 100644 --- a/sql/item_windowfunc.h +++ b/sql/item_windowfunc.h @@ -646,7 +646,7 @@ class Item_sum_cume_dist: public Item_sum_window_with_row_count ulonglong get_row_number() { - return current_row_count_; + return current_row_count_ ; } private: @@ -774,10 +774,14 @@ public: if (first_call) { prev_value= arg->val_real(); + if (prev_value >1 || prev_value < 0) + { + return true; + } first_call= false; } - if(prev_value != arg->val_real() || prev_value >1 || prev_value < 0) + if(prev_value != arg->val_real()) { // TODO(varun) need to add an error here , check the MDEV-12985 for the information return true; @@ -841,6 +845,159 @@ private: Item *order_item; }; +class Item_sum_percentile_cont : public Item_sum_cume_dist, + public Type_handler_hybrid_field_type +{ +public: + Item_sum_percentile_cont(THD *thd, Item* arg) : Item_sum_cume_dist(thd, arg), + Type_handler_hybrid_field_type(&type_handler_double), + floor_value(NULL), ceil_value(NULL), first_call(TRUE),prev_value(0), + ceil_val_calculated(FALSE), floor_val_calculated(FALSE), order_item(NULL){} + + double val_real() + { + if (get_row_count() == 0 || get_arg(0)->is_null()) + { + null_value= true; + return 0; + } + null_value= false; + double val= 1 + prev_value * (get_row_count()-1); + + /* + Applying the formula to get the value + If (CRN = FRN = RN) then the result is (value of expression from row at RN) + Otherwise the result is + (CRN - RN) * (value of expression for row at FRN) + + (RN - FRN) * (value of expression for row at CRN) + */ + + if(ceil(val) == floor(val)) + return floor_value->val_real(); + + double ret_val= ((val - floor(val)) * ceil_value->val_real()) + + ((ceil(val) - val) * floor_value->val_real()); + + return ret_val; + + } + longlong val_int() + { + if (get_row_count() == 0 || get_arg(0)->is_null()) + { + null_value= true; + return 0; + } + null_value= false; + return 0; + } + + my_decimal* val_decimal(my_decimal* dec) + { + if (get_row_count() == 0 || get_arg(0)->is_null()) + { + null_value= true; + return 0; + return 0; + } + null_value= false; + return ceil_value->val_decimal(dec); + } + + bool add() + { + Item *arg = get_arg(0); + if (arg->is_null()) + return true; + + if (first_call) + { + first_call= false; + prev_value= arg->val_real(); + if (prev_value >1 || prev_value < 0) + { + // TODO(varun) need to add an error here , check the MDEV-12985 for the information + return true; + } + } + + if (prev_value != arg->val_real()) + { + // TODO(varun) need to add an error here , check the MDEV-12985 for the information + return true; + } + + if (!floor_val_calculated) + { + floor_value->store(order_item); + floor_value->cache_value(); + if (floor_value->null_value) + return false; + } + if (floor_val_calculated && !ceil_val_calculated) + { + ceil_value->store(order_item); + ceil_value->cache_value(); + if (ceil_value->null_value) + return false; + } + + Item_sum_cume_dist::add(); + double val= 1 + prev_value * (get_row_count()-1); + + if (!floor_val_calculated && get_row_number() == floor(val)) + floor_val_calculated= true; + + if (!ceil_val_calculated && get_row_number() == ceil(val)) + ceil_val_calculated= true; + return false; + } + + enum Sumfunctype sum_func() const + { + return PERCENTILE_DISC_FUNC; + } + + void clear() + { + first_call= true; + floor_value->clear(); + ceil_value->clear(); + floor_val_calculated= false; + ceil_val_calculated= false; + Item_sum_cume_dist::clear(); + } + + const char*func_name() const + { + return "percentile_cont"; + } + void update_field() {} + void set_type_handler(Window_spec *window_spec); + const Type_handler *type_handler() const + {return Type_handler_hybrid_field_type::type_handler();} + + void fix_length_and_dec() + { + decimals = 10; // TODO-cvicentiu find out how many decimals the standard + // requires. + } + + Item *get_copy(THD *thd, MEM_ROOT *mem_root) + { return get_item_copy(thd, mem_root, this); } + void setup_window_func(THD *thd, Window_spec *window_spec); + void setup_hybrid(THD *thd, Item *item); + +private: + Item_cache *floor_value; + Item_cache *ceil_value; + bool first_call; + double prev_value; + bool ceil_val_calculated; + bool floor_val_calculated; + Item *order_item; +}; + diff --git a/sql/sql_window.cc b/sql/sql_window.cc index bb7742b029a..d1628c46e2a 100644 --- a/sql/sql_window.cc +++ b/sql/sql_window.cc @@ -2540,6 +2540,7 @@ void add_special_frame_cursors(THD *thd, Cursor_manager *cursor_manager, cursor_manager->add_cursor(fc); break; } + case Item_sum::PERCENTILE_CONT_FUNC: case Item_sum::PERCENTILE_DISC_FUNC: { fc= new Frame_unbounded_preceding(thd, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 62dbc3860ec..b5bc70639b0 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -10723,7 +10723,9 @@ inverse_distribution_function: inverse_distribution_function_def: PERCENTILE_CONT_SYM '(' expr ')' { - //Not yet started implementing + $$= new (thd->mem_root) Item_sum_percentile_cont(thd, $3); + if ($$ == NULL) + MYSQL_YYABORT; } | PERCENTILE_DISC_SYM '(' expr ')' {