Commit 1fa12cdf authored by Sergei Petrunia's avatar Sergei Petrunia

MDEV-9676: RANGE-type frames for window functions

Support RANGE ... CURRENT ROW as frame's first and second bound.
parent b579a626
......@@ -460,3 +460,111 @@ part_id pk a CNT
1 8 1 3
1 9 1 2
drop table t0, t2;
#
# RANGE-type bounds
#
create table t3 (
pk int,
val int
);
insert into t3 values
(0, 1),
(1, 1),
(2, 1),
(3, 2),
(4, 2),
(5, 2),
(6, 2);
select
pk,
val,
count(val) over (order by val
range between current row and
current row)
as CNT
from t3;
pk val CNT
0 1 3
1 1 3
2 1 3
3 2 4
4 2 4
5 2 4
6 2 4
insert into t3 values
(7, 3),
(8, 3);
select
pk,
val,
count(val) over (order by val
range between current row and
current row)
as CNT
from t3;
pk val CNT
0 1 3
1 1 3
2 1 3
3 2 4
4 2 4
5 2 4
6 2 4
7 3 2
8 3 2
drop table t3;
# Now, check with PARTITION BY
create table t4 (
part_id int,
pk int,
val int
);
insert into t4 values
(1234, 100, 1),
(1234, 101, 1),
(1234, 102, 1),
(1234, 103, 2),
(1234, 104, 2),
(1234, 105, 2),
(1234, 106, 2),
(1234, 107, 3),
(1234, 108, 3),
(5678, 200, 1),
(5678, 201, 1),
(5678, 202, 1),
(5678, 203, 2),
(5678, 204, 2),
(5678, 205, 2),
(5678, 206, 2),
(5678, 207, 3),
(5678, 208, 3);
select
part_id,
pk,
val,
count(val) over (partition by part_id
order by val
range between current row and
current row)
as CNT
from t4;
part_id pk val CNT
1234 100 1 3
1234 101 1 3
1234 102 1 3
1234 103 2 4
1234 104 2 4
1234 105 2 4
1234 106 2 4
1234 107 3 2
1234 108 3 2
5678 200 1 3
5678 201 1 3
5678 202 1 3
5678 203 2 4
5678 204 2 4
5678 205 2 4
5678 206 2 4
5678 207 3 2
5678 208 3 2
drop table t4;
......@@ -303,3 +303,86 @@ from t2;
drop table t0, t2;
--echo #
--echo # RANGE-type bounds
--echo #
create table t3 (
pk int,
val int
);
insert into t3 values
(0, 1),
(1, 1),
(2, 1),
(3, 2),
(4, 2),
(5, 2),
(6, 2);
select
pk,
val,
count(val) over (order by val
range between current row and
current row)
as CNT
from t3;
insert into t3 values
(7, 3),
(8, 3);
select
pk,
val,
count(val) over (order by val
range between current row and
current row)
as CNT
from t3;
drop table t3;
--echo # Now, check with PARTITION BY
create table t4 (
part_id int,
pk int,
val int
);
insert into t4 values
(1234, 100, 1),
(1234, 101, 1),
(1234, 102, 1),
(1234, 103, 2),
(1234, 104, 2),
(1234, 105, 2),
(1234, 106, 2),
(1234, 107, 3),
(1234, 108, 3),
(5678, 200, 1),
(5678, 201, 1),
(5678, 202, 1),
(5678, 203, 2),
(5678, 204, 2),
(5678, 205, 2),
(5678, 206, 2),
(5678, 207, 3),
(5678, 208, 3);
select
part_id,
pk,
val,
count(val) over (partition by part_id
order by val
range between current row and
current row)
as CNT
from t4;
drop table t4;
......@@ -4778,17 +4778,10 @@ class Item_copy_decimal : public Item_copy
- cmp() method that compares the saved value with the current value of the
source item, and if they were not equal saves item's value into the saved
value.
*/
/*
Cached_item_XXX objects are not exactly caches. They do the following:
Each Cached_item_XXX object has
- its source item
- saved value of the source item
- cmp() method that compares the saved value with the current value of the
source item, and if they were not equal saves item's value into the saved
value.
TODO: add here:
- a way to save the new value w/o comparison
- a way to do less/equal/greater comparison
*/
class Cached_item :public Sql_alloc
......@@ -4796,7 +4789,18 @@ class Cached_item :public Sql_alloc
public:
bool null_value;
Cached_item() :null_value(0) {}
/*
Compare the cached value with the source value. If not equal, copy
the source value to the cache.
@return
true - Not equal
false - Equal
*/
virtual bool cmp(void)=0;
/* Compare the cached value with the source value, without copying */
virtual int cmp_read_only()=0;
virtual ~Cached_item(); /*line -e1509 */
};
......@@ -4808,6 +4812,7 @@ class Cached_item_str :public Cached_item
public:
Cached_item_str(THD *thd, Item *arg);
bool cmp(void);
int cmp_read_only();
~Cached_item_str(); // Deallocate String:s
};
......@@ -4819,6 +4824,7 @@ class Cached_item_real :public Cached_item
public:
Cached_item_real(Item *item_par) :item(item_par),value(0.0) {}
bool cmp(void);
int cmp_read_only();
};
class Cached_item_int :public Cached_item
......@@ -4828,6 +4834,7 @@ class Cached_item_int :public Cached_item
public:
Cached_item_int(Item *item_par) :item(item_par),value(0) {}
bool cmp(void);
int cmp_read_only();
};
......@@ -4838,6 +4845,7 @@ class Cached_item_decimal :public Cached_item
public:
Cached_item_decimal(Item *item_par);
bool cmp(void);
int cmp_read_only();
};
class Cached_item_field :public Cached_item
......@@ -4854,6 +4862,7 @@ class Cached_item_field :public Cached_item
buff= (uchar*) thd_calloc(thd, length= field->pack_length());
}
bool cmp(void);
int cmp_read_only();
};
class Item_default_value : public Item_field
......
......@@ -98,6 +98,25 @@ bool Cached_item_str::cmp(void)
return tmp;
}
int Cached_item_str::cmp_read_only()
{
String *res= item->val_str(&tmp_value);
if (null_value)
{
if (item->null_value)
return 0;
else
return -1;
}
if (item->null_value)
return 1;
return sortcmp(&value, res, item->collation.collation);
}
Cached_item_str::~Cached_item_str()
{
item=0; // Safety
......@@ -115,6 +134,23 @@ bool Cached_item_real::cmp(void)
return FALSE;
}
int Cached_item_real::cmp_read_only()
{
double nr= item->val_real();
if (null_value)
{
if (item->null_value)
return 0;
else
return -1;
}
if (item->null_value)
return 1;
return (nr == value)? 0 : ((nr < value)? 1: -1);
}
bool Cached_item_int::cmp(void)
{
longlong nr=item->val_int();
......@@ -128,6 +164,22 @@ bool Cached_item_int::cmp(void)
}
int Cached_item_int::cmp_read_only()
{
longlong nr= item->val_int();
if (null_value)
{
if (item->null_value)
return 0;
else
return -1;
}
if (item->null_value)
return 1;
return (nr == value)? 0 : ((nr < value)? 1: -1);
}
bool Cached_item_field::cmp(void)
{
bool tmp= FALSE; // Value is identical
......@@ -148,6 +200,22 @@ bool Cached_item_field::cmp(void)
}
int Cached_item_field::cmp_read_only()
{
if (null_value)
{
if (field->is_null())
return 0;
else
return -1;
}
if (field->is_null())
return 1;
return field->cmp(buff);
}
Cached_item_decimal::Cached_item_decimal(Item *it)
:item(it)
{
......@@ -174,3 +242,20 @@ bool Cached_item_decimal::cmp()
return FALSE;
}
int Cached_item_decimal::cmp_read_only()
{
my_decimal tmp;
my_decimal *ptmp= item->val_decimal(&tmp);
if (null_value)
{
if (item->null_value)
return 0;
else
return -1;
}
if (item->null_value)
return 1;
return my_decimal_cmp(&value, ptmp);
}
This diff is collapsed.
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