Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
914e2c9b
Commit
914e2c9b
authored
Nov 01, 2017
by
Igor Babaev
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '10.3' of github.com:MariaDB/server into 10.3
parents
6f1b6061
a607e4e7
Changes
11
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
1077 additions
and
8 deletions
+1077
-8
include/source_revision.h.in
include/source_revision.h.in
+1
-1
mysql-test/r/win_percentile.result
mysql-test/r/win_percentile.result
+326
-0
mysql-test/t/win_percentile.test
mysql-test/t/win_percentile.test
+104
-0
sql/item_sum.h
sql/item_sum.h
+2
-1
sql/item_windowfunc.cc
sql/item_windowfunc.cc
+82
-1
sql/item_windowfunc.h
sql/item_windowfunc.h
+315
-3
sql/lex.h
sql/lex.h
+4
-0
sql/share/errmsg-utf8.txt
sql/share/errmsg-utf8.txt
+10
-0
sql/sql_window.cc
sql/sql_window.cc
+84
-1
sql/sql_yacc.yy
sql/sql_yacc.yy
+79
-1
sql/sql_yacc_ora.yy
sql/sql_yacc_ora.yy
+70
-0
No files found.
include/source_revision.h.in
View file @
914e2c9b
#
cmake
define SOURCE_REVISION "@SOURCE_REVISION@"
#define SOURCE_REVISION "@SOURCE_REVISION@"
mysql-test/r/win_percentile.result
0 → 100644
View file @
914e2c9b
This diff is collapsed.
Click to expand it.
mysql-test/t/win_percentile.test
0 → 100644
View file @
914e2c9b
CREATE
TABLE
t1
(
name
CHAR
(
10
),
test
double
,
score
DECIMAL
(
19
,
4
));
INSERT
INTO
t1
VALUES
(
'Chun'
,
0
,
3
),
(
'Chun'
,
0
,
7
),
(
'Kaolin'
,
0.5
,
3
),
(
'Kaolin'
,
0.6
,
7
),
(
'Kaolin'
,
0.5
,
4
),
(
'Tatiana'
,
0.8
,
4
),
(
'Tata'
,
0.8
,
4
);
--
echo
#
--
echo
# Test invalid syntax
--
echo
#
--
echo
# Order by clause has more than one element
--
error
ER_PARSE_ERROR
select
percentile_disc
(
0.5
)
within
group
(
order
by
score
,
test
)
over
(
partition
by
name
)
from
t1
;
--
error
ER_PARSE_ERROR
select
percentile_cont
(
0.5
)
within
group
(
order
by
score
,
test
)
over
(
partition
by
name
)
from
t1
;
--
echo
# Order by clause has no element
--
error
ER_PARSE_ERROR
select
percentile_disc
(
0.5
)
within
group
()
over
(
partition
by
name
)
from
t1
;
--
error
ER_PARSE_ERROR
select
percentile_cont
(
0.5
)
within
group
()
over
(
partition
by
name
)
from
t1
;
--
echo
# No parameters to the percentile functions
--
error
ER_PARSE_ERROR
select
percentile_disc
()
within
group
()
over
(
partition
by
name
)
from
t1
;
--
error
ER_PARSE_ERROR
select
percentile_cont
()
within
group
()
over
(
partition
by
name
)
from
t1
;
--
echo
#
--
echo
# Test simple syntax
--
echo
#
select
name
,
percentile_cont
(
0.5
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
name
,
percentile_disc
(
0.5
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
--
echo
# no partition clause
select
name
,
percentile_disc
(
0.5
)
within
group
(
order
by
score
)
over
()
from
t1
;
select
name
,
percentile_cont
(
0.5
)
within
group
(
order
by
score
)
over
()
from
t1
;
--
echo
# argument set to null
--
error
ER_WRONG_TYPE_OF_ARGUMENT
select
name
,
percentile_cont
(
null
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
from
t1
;
--
error
ER_WRONG_TYPE_OF_ARGUMENT
select
name
,
percentile_disc
(
null
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
from
t1
;
--
echo
#subqueries having percentile functions
select
*
from
(
select
name
,
percentile_cont
(
0.5
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
from
t1
)
as
t
;
select
*
from
(
select
name
,
percentile_disc
(
0.5
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
from
t1
)
as
t
;
select
name
from
t1
a
where
(
select
percentile_disc
(
0.5
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
from
t1
b
limit
1
)
>=
0.5
;
--
echo
#disallowed fields in order by
--
error
ER_WRONG_TYPE_FOR_PERCENTILE_FUNC
select
score
,
percentile_cont
(
0.5
)
within
group
(
order
by
name
)
over
(
partition
by
score
)
from
t1
;
--
error
ER_WRONG_TYPE_FOR_PERCENTILE_FUNC
select
score
,
percentile_disc
(
0.5
)
within
group
(
order
by
name
)
over
(
partition
by
score
)
from
t1
;
--
echo
#parameter value should be in the range of [0,1]
--
error
ER_ARGUMENT_OUT_OF_RANGE
select
percentile_disc
(
1.5
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
from
t1
;
--
error
ER_ARGUMENT_OUT_OF_RANGE
select
percentile_cont
(
1.5
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
from
t1
;
--
echo
#Argument should remain constant for the entire partition
--
error
ER_ARGUMENT_NOT_CONSTANT
select
name
,
percentile_cont
(
test
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
from
t1
;
--
error
ER_ARGUMENT_NOT_CONSTANT
select
name
,
percentile_disc
(
test
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
from
t1
;
--
echo
#only numerical types are allowed as argument to percentile functions
--
error
ER_WRONG_TYPE_OF_ARGUMENT
select
name
,
percentile_cont
(
name
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
from
t1
;
--
error
ER_WRONG_TYPE_OF_ARGUMENT
select
name
,
percentile_disc
(
name
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
from
t1
;
--
echo
#complete query with partition column
select
name
,
cume_dist
()
over
(
partition
by
name
order
by
score
),
percentile_disc
(
0.5
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
name
,
percentile_cont
(
0.5
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
name
,
cume_dist
()
over
(
partition
by
name
order
by
score
)
as
b
,
percentile_disc
(
0.1
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
name
,
cume_dist
()
over
(
partition
by
name
order
by
score
)
as
b
,
percentile_disc
(
0.2
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
name
,
cume_dist
()
over
(
partition
by
name
order
by
score
)
as
b
,
percentile_disc
(
0.3
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
name
,
cume_dist
()
over
(
partition
by
name
order
by
score
)
as
b
,
percentile_disc
(
0.4
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
name
,
cume_dist
()
over
(
partition
by
name
order
by
score
)
as
b
,
percentile_disc
(
0.5
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
name
,
cume_dist
()
over
(
partition
by
name
order
by
score
)
as
b
,
percentile_disc
(
0.6
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
name
,
cume_dist
()
over
(
partition
by
name
order
by
score
)
as
b
,
percentile_disc
(
0.7
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
name
,
cume_dist
()
over
(
partition
by
name
order
by
score
)
as
b
,
percentile_disc
(
0.8
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
name
,
cume_dist
()
over
(
partition
by
name
order
by
score
)
as
b
,
percentile_disc
(
0.9
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
name
,
cume_dist
()
over
(
partition
by
name
order
by
score
)
as
b
,
percentile_disc
(
1
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
median
(
score
)
over
(
partition
by
name
),
percentile_cont
(
0
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
median
(
score
)
over
(
partition
by
name
),
percentile_cont
(
0.1
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
median
(
score
)
over
(
partition
by
name
),
percentile_cont
(
0.2
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
median
(
score
)
over
(
partition
by
name
),
percentile_cont
(
0.3
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
median
(
score
)
over
(
partition
by
name
),
percentile_cont
(
0.4
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
median
(
score
)
over
(
partition
by
name
),
percentile_cont
(
0.5
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
median
(
score
)
over
(
partition
by
name
),
percentile_cont
(
0.6
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
median
(
score
)
over
(
partition
by
name
),
percentile_cont
(
0.7
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
median
(
score
)
over
(
partition
by
name
),
percentile_cont
(
0.8
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
median
(
score
)
over
(
partition
by
name
),
percentile_cont
(
0.9
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
select
median
(
score
)
over
(
partition
by
name
),
percentile_cont
(
1
)
within
group
(
order
by
score
)
over
(
partition
by
name
)
as
c
from
t1
;
drop
table
t1
;
sql/item_sum.h
View file @
914e2c9b
...
...
@@ -354,7 +354,8 @@ class Item_sum :public Item_func_or_sum
VARIANCE_FUNC
,
SUM_BIT_FUNC
,
UDF_SUM_FUNC
,
GROUP_CONCAT_FUNC
,
ROW_NUMBER_FUNC
,
RANK_FUNC
,
DENSE_RANK_FUNC
,
PERCENT_RANK_FUNC
,
CUME_DIST_FUNC
,
NTILE_FUNC
,
FIRST_VALUE_FUNC
,
LAST_VALUE_FUNC
,
NTH_VALUE_FUNC
,
LEAD_FUNC
,
LAG_FUNC
NTH_VALUE_FUNC
,
LEAD_FUNC
,
LAG_FUNC
,
PERCENTILE_CONT_FUNC
,
PERCENTILE_DISC_FUNC
};
Item
**
ref_by
;
/* pointer to a ref to the object used to register it */
...
...
sql/item_windowfunc.cc
View file @
914e2c9b
...
...
@@ -108,6 +108,7 @@ 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
;
}
/*
TODO: why the last parameter is 'ref' in this call? What if window_func
decides to substitute itself for something else and does *ref=.... ?
...
...
@@ -168,10 +169,25 @@ void Item_window_func::split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
window_func
()
->
setup_caches
(
thd
);
}
bool
Item_window_func
::
check_result_type_of_order_item
()
{
if
(
only_single_element_order_list
())
{
Item_result
rtype
=
window_spec
->
order_list
->
first
->
item
[
0
]
->
cmp_type
();
// TODO (varun) : support date type in percentile_cont function
if
(
rtype
!=
REAL_RESULT
&&
rtype
!=
INT_RESULT
&&
rtype
!=
DECIMAL_RESULT
&&
rtype
!=
TIME_RESULT
)
{
my_error
(
ER_WRONG_TYPE_FOR_PERCENTILE_FUNC
,
MYF
(
0
),
window_func
()
->
func_name
());
return
TRUE
;
}
setting_handler_for_percentile_functions
(
rtype
);
}
return
FALSE
;
}
/*
This must be called before attempting to compute the window function values.
@detail
If we attempt to do it in fix_fields(), partition_fields will refer
to the original window function arguments.
...
...
@@ -194,6 +210,71 @@ void Item_sum_dense_rank::setup_window_func(THD *thd, Window_spec *window_spec)
clear
();
}
void
Item_sum_percentile_disc
::
setup_window_func
(
THD
*
thd
,
Window_spec
*
window_spec
)
{
order_item
=
window_spec
->
order_list
->
first
->
item
[
0
];
if
(
!
(
value
=
order_item
->
get_cache
(
thd
)))
return
;
value
->
setup
(
thd
,
order_item
);
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
];
/* TODO(varun): need to discuss and finalise what type should we
return for percentile cont functions
*/
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_percentile_cont
::
fix_fields
(
THD
*
thd
,
Item
**
ref
)
{
bool
res
;
res
=
Item_sum_num
::
fix_fields
(
thd
,
ref
);
if
(
res
)
return
res
;
switch
(
args
[
0
]
->
cmp_type
())
{
case
DECIMAL_RESULT
:
case
REAL_RESULT
:
case
INT_RESULT
:
break
;
default:
my_error
(
ER_WRONG_TYPE_OF_ARGUMENT
,
MYF
(
0
),
func_name
());
return
TRUE
;
}
return
res
;
}
bool
Item_sum_percentile_disc
::
fix_fields
(
THD
*
thd
,
Item
**
ref
)
{
bool
res
;
res
=
Item_sum_num
::
fix_fields
(
thd
,
ref
);
if
(
res
)
return
res
;
switch
(
args
[
0
]
->
cmp_type
())
{
case
DECIMAL_RESULT
:
case
REAL_RESULT
:
case
INT_RESULT
:
break
;
default:
my_error
(
ER_WRONG_TYPE_OF_ARGUMENT
,
MYF
(
0
),
func_name
());
return
TRUE
;
}
return
res
;
}
bool
Item_sum_dense_rank
::
add
()
{
if
(
peer_tracker
->
check_if_next_group
()
||
first_add
)
...
...
sql/item_windowfunc.h
View file @
914e2c9b
...
...
@@ -24,6 +24,7 @@ class Window_spec;
int
test_if_group_changed
(
List
<
Cached_item
>
&
list
);
/* A wrapper around test_if_group_changed */
class
Group_bound_tracker
{
...
...
@@ -31,10 +32,10 @@ class Group_bound_tracker
Group_bound_tracker
(
THD
*
thd
,
SQL_I_List
<
ORDER
>
*
list
)
{
for
(
ORDER
*
curr
=
list
->
first
;
curr
;
curr
=
curr
->
next
)
for
(
ORDER
*
curr
=
list
->
first
;
curr
;
curr
=
curr
->
next
)
{
Cached_item
*
tmp
=
new_Cached_item
(
thd
,
curr
->
item
[
0
],
TRUE
);
group_fields
.
push_back
(
tmp
);
Cached_item
*
tmp
=
new_Cached_item
(
thd
,
curr
->
item
[
0
],
TRUE
);
group_fields
.
push_back
(
tmp
);
}
}
...
...
@@ -572,6 +573,9 @@ class Item_sum_cume_dist: public Item_sum_window_with_row_count
Item_sum_cume_dist
(
THD
*
thd
)
:
Item_sum_window_with_row_count
(
thd
),
current_row_count_
(
0
)
{}
Item_sum_cume_dist
(
THD
*
thd
,
Item
*
arg
)
:
Item_sum_window_with_row_count
(
thd
,
arg
),
current_row_count_
(
0
)
{}
double
val_real
()
{
if
(
get_row_count
()
==
0
)
...
...
@@ -618,6 +622,11 @@ class Item_sum_cume_dist: public Item_sum_window_with_row_count
Item
*
get_copy
(
THD
*
thd
,
MEM_ROOT
*
mem_root
)
{
return
get_item_copy
<
Item_sum_cume_dist
>
(
thd
,
mem_root
,
this
);
}
ulonglong
get_row_number
()
{
return
current_row_count_
;
}
private:
ulonglong
current_row_count_
;
};
...
...
@@ -693,6 +702,277 @@ class Item_sum_ntile : public Item_sum_window_with_row_count
ulong
current_row_count_
;
};
class
Item_sum_percentile_disc
:
public
Item_sum_cume_dist
,
public
Type_handler_hybrid_field_type
{
public:
Item_sum_percentile_disc
(
THD
*
thd
,
Item
*
arg
)
:
Item_sum_cume_dist
(
thd
,
arg
),
Type_handler_hybrid_field_type
(
&
type_handler_longlong
),
value
(
NULL
),
val_calculated
(
FALSE
),
first_call
(
TRUE
),
prev_value
(
0
),
order_item
(
NULL
){}
double
val_real
()
{
if
(
get_row_count
()
==
0
||
get_arg
(
0
)
->
is_null
())
{
null_value
=
true
;
return
0
;
}
null_value
=
false
;
return
value
->
val_real
();
}
longlong
val_int
()
{
if
(
get_row_count
()
==
0
||
get_arg
(
0
)
->
is_null
())
{
null_value
=
true
;
return
0
;
}
null_value
=
false
;
return
value
->
val_int
();
}
my_decimal
*
val_decimal
(
my_decimal
*
dec
)
{
if
(
get_row_count
()
==
0
||
get_arg
(
0
)
->
is_null
())
{
null_value
=
true
;
return
0
;
}
null_value
=
false
;
return
value
->
val_decimal
(
dec
);
}
String
*
val_str
(
String
*
str
)
{
if
(
get_row_count
()
==
0
||
get_arg
(
0
)
->
is_null
())
{
null_value
=
true
;
return
0
;
}
null_value
=
false
;
return
value
->
val_str
(
str
);
}
bool
add
()
{
Item
*
arg
=
get_arg
(
0
);
if
(
arg
->
is_null
())
return
false
;
if
(
first_call
)
{
prev_value
=
arg
->
val_real
();
if
(
prev_value
>
1
||
prev_value
<
0
)
{
my_error
(
ER_ARGUMENT_OUT_OF_RANGE
,
MYF
(
0
),
func_name
());
return
true
;
}
first_call
=
false
;
}
double
arg_val
=
arg
->
val_real
();
if
(
prev_value
!=
arg_val
)
{
my_error
(
ER_ARGUMENT_NOT_CONSTANT
,
MYF
(
0
),
func_name
());
return
true
;
}
if
(
val_calculated
)
return
false
;
value
->
store
(
order_item
);
value
->
cache_value
();
if
(
value
->
null_value
)
return
false
;
Item_sum_cume_dist
::
add
();
double
val
=
Item_sum_cume_dist
::
val_real
();
if
(
val
>=
prev_value
&&
!
val_calculated
)
val_calculated
=
true
;
return
false
;
}
enum
Sumfunctype
sum_func
()
const
{
return
PERCENTILE_DISC_FUNC
;
}
void
clear
()
{
val_calculated
=
false
;
first_call
=
true
;
value
->
clear
();
Item_sum_cume_dist
::
clear
();
}
const
char
*
func_name
()
const
{
return
"percentile_disc"
;
}
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
<
Item_sum_percentile_disc
>
(
thd
,
mem_root
,
this
);
}
void
setup_window_func
(
THD
*
thd
,
Window_spec
*
window_spec
);
void
setup_hybrid
(
THD
*
thd
,
Item
*
item
);
bool
fix_fields
(
THD
*
thd
,
Item
**
ref
);
private:
Item_cache
*
value
;
bool
val_calculated
;
bool
first_call
;
double
prev_value
;
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
;
}
bool
add
()
{
Item
*
arg
=
get_arg
(
0
);
if
(
arg
->
is_null
())
return
false
;
if
(
first_call
)
{
first_call
=
false
;
prev_value
=
arg
->
val_real
();
if
(
prev_value
>
1
||
prev_value
<
0
)
{
my_error
(
ER_ARGUMENT_OUT_OF_RANGE
,
MYF
(
0
),
func_name
());
return
true
;
}
}
double
arg_val
=
arg
->
val_real
();
if
(
prev_value
!=
arg_val
)
{
my_error
(
ER_ARGUMENT_NOT_CONSTANT
,
MYF
(
0
),
func_name
());
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_CONT_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
<
Item_sum_percentile_cont
>
(
thd
,
mem_root
,
this
);
}
void
setup_window_func
(
THD
*
thd
,
Window_spec
*
window_spec
);
void
setup_hybrid
(
THD
*
thd
,
Item
*
item
);
bool
fix_fields
(
THD
*
thd
,
Item
**
ref
);
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
;
};
class
Item_window_func
:
public
Item_func_or_sum
{
...
...
@@ -747,6 +1027,8 @@ class Item_window_func : public Item_func_or_sum
case
Item_sum
:
:
PERCENT_RANK_FUNC
:
case
Item_sum
:
:
CUME_DIST_FUNC
:
case
Item_sum
:
:
NTILE_FUNC
:
case
Item_sum
:
:
PERCENTILE_CONT_FUNC
:
case
Item_sum
:
:
PERCENTILE_DISC_FUNC
:
return
true
;
default:
return
false
;
...
...
@@ -773,6 +1055,8 @@ class Item_window_func : public Item_func_or_sum
case
Item_sum
:
:
PERCENT_RANK_FUNC
:
case
Item_sum
:
:
CUME_DIST_FUNC
:
case
Item_sum
:
:
NTILE_FUNC
:
case
Item_sum
:
:
PERCENTILE_CONT_FUNC
:
case
Item_sum
:
:
PERCENTILE_DISC_FUNC
:
return
true
;
default:
return
false
;
...
...
@@ -796,12 +1080,40 @@ class Item_window_func : public Item_func_or_sum
case
Item_sum
:
:
DENSE_RANK_FUNC
:
case
Item_sum
:
:
PERCENT_RANK_FUNC
:
case
Item_sum
:
:
CUME_DIST_FUNC
:
case
Item_sum
:
:
PERCENTILE_CONT_FUNC
:
case
Item_sum
:
:
PERCENTILE_DISC_FUNC
:
return
true
;
default:
return
false
;
}
}
bool
only_single_element_order_list
()
const
{
switch
(
window_func
()
->
sum_func
()){
case
Item_sum
:
:
PERCENTILE_CONT_FUNC
:
case
Item_sum
:
:
PERCENTILE_DISC_FUNC
:
return
true
;
default:
return
false
;
}
}
void
setting_handler_for_percentile_functions
(
Item_result
rtype
)
const
{
switch
(
window_func
()
->
sum_func
()){
case
Item_sum
:
:
PERCENTILE_DISC_FUNC
:
((
Item_sum_percentile_disc
*
)
window_func
())
->
set_handler_by_cmp_type
(
rtype
);
break
;
default:
return
;
}
}
bool
check_result_type_of_order_item
();
/*
Computation functions.
TODO: consoder merging these with class Group_bound_tracker.
...
...
sql/lex.h
View file @
914e2c9b
...
...
@@ -701,6 +701,7 @@ static SYMBOL symbols[] = {
{
"WHILE"
,
SYM
(
WHILE_SYM
)},
{
"WINDOW"
,
SYM
(
WINDOW_SYM
)},
{
"WITH"
,
SYM
(
WITH
)},
{
"WITHIN"
,
SYM
(
WITHIN
)},
{
"WORK"
,
SYM
(
WORK_SYM
)},
{
"WRAPPER"
,
SYM
(
WRAPPER_SYM
)},
{
"WRITE"
,
SYM
(
WRITE_SYM
)},
...
...
@@ -736,6 +737,7 @@ static SYMBOL sql_functions[] = {
{
"LAG"
,
SYM
(
LAG_SYM
)},
{
"LEAD"
,
SYM
(
LEAD_SYM
)},
{
"MAX"
,
SYM
(
MAX_SYM
)},
{
"MEDIAN"
,
SYM
(
MEDIAN_SYM
)},
{
"MID"
,
SYM
(
SUBSTRING
)},
/* unireg function */
{
"MIN"
,
SYM
(
MIN_SYM
)},
{
"NOW"
,
SYM
(
NOW_SYM
)},
...
...
@@ -743,6 +745,8 @@ static SYMBOL sql_functions[] = {
{
"NTILE"
,
SYM
(
NTILE_SYM
)},
{
"POSITION"
,
SYM
(
POSITION_SYM
)},
{
"PERCENT_RANK"
,
SYM
(
PERCENT_RANK_SYM
)},
{
"PERCENTILE_CONT"
,
SYM
(
PERCENTILE_CONT_SYM
)},
{
"PERCENTILE_DISC"
,
SYM
(
PERCENTILE_DISC_SYM
)},
{
"RANK"
,
SYM
(
RANK_SYM
)},
{
"ROW_NUMBER"
,
SYM
(
ROW_NUMBER_SYM
)},
{
"SESSION_USER"
,
SYM
(
USER_SYM
)},
...
...
sql/share/errmsg-utf8.txt
View file @
914e2c9b
...
...
@@ -7790,3 +7790,13 @@ ER_WRONG_NUMBER_OF_VALUES_IN_TVC
eng "The used table value constructor has a different number of values"
ER_FIELD_REFERENCE_IN_TVC
eng "Field reference '%-.192s' can't be used in table value constructor"
ER_NOT_SINGLE_ELEMENT_ORDER_LIST
eng "Incorrect number of elements in the order list for '%s'"
ER_WRONG_TYPE_FOR_PERCENTILE_FUNC
eng "Numeric datatype is required for %s function"
ER_ARGUMENT_NOT_CONSTANT
eng "Argument to the %s function is not a constant for a partition"
ER_ARGUMENT_OUT_OF_RANGE
eng "Argument to the %s function does not belong to the range [0,1]"
ER_WRONG_TYPE_OF_ARGUMENT
eng "%s function only accepts arguments that can be converted to numerical types"
sql/sql_window.cc
View file @
914e2c9b
...
...
@@ -321,6 +321,12 @@ setup_windows(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
win_func_item
->
update_used_tables
();
}
li
.
rewind
();
while
((
win_func_item
=
li
++
))
{
if
(
win_func_item
->
check_result_type_of_order_item
())
DBUG_RETURN
(
1
);
}
DBUG_RETURN
(
0
);
}
...
...
@@ -968,6 +974,8 @@ class Partition_read_cursor : public Table_read_cursor
bool
end_of_partition
;
};
/////////////////////////////////////////////////////////////////////////////
/*
...
...
@@ -1735,7 +1743,17 @@ class Frame_unbounded_following_set_count : public Frame_unbounded_following
/* Walk to the end of the partition, find how many rows there are. */
while
(
!
cursor
.
next
())
num_rows_in_partition
++
;
set_win_funcs_row_count
(
num_rows_in_partition
);
}
ha_rows
get_curr_rownum
()
const
{
return
cursor
.
get_rownum
();
}
protected:
void
set_win_funcs_row_count
(
ha_rows
num_rows_in_partition
)
{
List_iterator_fast
<
Item_sum
>
it
(
sum_functions
);
Item_sum
*
item
;
while
((
item
=
it
++
))
...
...
@@ -1745,11 +1763,43 @@ class Frame_unbounded_following_set_count : public Frame_unbounded_following
item_with_row_count
->
set_row_count
(
num_rows_in_partition
);
}
}
};
class
Frame_unbounded_following_set_count_no_nulls
:
public
Frame_unbounded_following_set_count
{
public:
Frame_unbounded_following_set_count_no_nulls
(
THD
*
thd
,
SQL_I_List
<
ORDER
>
*
partition_list
,
SQL_I_List
<
ORDER
>
*
order_list
)
:
Frame_unbounded_following_set_count
(
thd
,
partition_list
,
order_list
)
{
order_item
=
order_list
->
first
->
item
[
0
];
}
void
next_partition
(
ha_rows
rownum
)
{
ha_rows
num_rows_in_partition
=
0
;
if
(
cursor
.
fetch
())
return
;
/* Walk to the end of the partition, find how many rows there are. */
do
{
if
(
!
order_item
->
is_null
())
num_rows_in_partition
++
;
}
while
(
!
cursor
.
next
());
set_win_funcs_row_count
(
num_rows_in_partition
);
}
ha_rows
get_curr_rownum
()
const
{
return
cursor
.
get_rownum
();
}
private:
Item
*
order_item
;
};
/////////////////////////////////////////////////////////////////////////////
...
...
@@ -2490,6 +2540,21 @@ 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
,
spec
->
partition_list
,
spec
->
order_list
);
fc
->
add_sum_func
(
item_sum
);
cursor_manager
->
add_cursor
(
fc
);
fc
=
new
Frame_unbounded_following
(
thd
,
spec
->
partition_list
,
spec
->
order_list
);
fc
->
add_sum_func
(
item_sum
);
cursor_manager
->
add_cursor
(
fc
);
break
;
}
default:
fc
=
new
Frame_unbounded_preceding
(
thd
,
spec
->
partition_list
,
spec
->
order_list
);
...
...
@@ -2514,6 +2579,8 @@ static bool is_computed_with_remove(Item_sum::Sumfunctype sum_func)
case
Item_sum
:
:
NTILE_FUNC
:
case
Item_sum
:
:
FIRST_VALUE_FUNC
:
case
Item_sum
:
:
LAST_VALUE_FUNC
:
case
Item_sum
:
:
PERCENTILE_CONT_FUNC
:
case
Item_sum
:
:
PERCENTILE_DISC_FUNC
:
return
false
;
default:
return
true
;
...
...
@@ -2544,9 +2611,18 @@ void get_window_functions_required_cursors(
*/
if
(
item_win_func
->
requires_partition_size
())
{
fc
=
new
Frame_unbounded_following_set_count
(
thd
,
if
(
item_win_func
->
only_single_element_order_list
())
{
fc
=
new
Frame_unbounded_following_set_count_no_nulls
(
thd
,
item_win_func
->
window_spec
->
partition_list
,
item_win_func
->
window_spec
->
order_list
);
}
else
{
fc
=
new
Frame_unbounded_following_set_count
(
thd
,
item_win_func
->
window_spec
->
partition_list
,
item_win_func
->
window_spec
->
order_list
);
}
fc
->
add_sum_func
(
sum_func
);
cursor_manager
->
add_cursor
(
fc
);
}
...
...
@@ -2727,6 +2803,13 @@ bool compute_window_func(THD *thd,
{
cursor_manager
->
notify_cursors_next_row
();
}
/* Check if we found any error in the window function while adding values
through cursors. */
if
(
thd
->
is_error
()
||
thd
->
is_killed
())
break
;
/* Return to current row after notifying cursors for each window
function. */
tbl
->
file
->
ha_rnd_pos
(
tbl
->
record
[
0
],
rowid_buf
);
...
...
sql/sql_yacc.yy
View file @
914e2c9b
...
...
@@ -1237,6 +1237,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token MAX_STATEMENT_TIME_SYM
%token MAX_USER_CONNECTIONS_SYM
%token MAXVALUE_SYM /* SQL-2003-N */
%token MEDIAN_SYM
%token MEDIUMBLOB
%token MEDIUMINT
%token MEDIUMTEXT
...
...
@@ -1329,6 +1330,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token PARTITIONING_SYM
%token PASSWORD_SYM
%token PERCENT_RANK_SYM
%token PERCENTILE_CONT_SYM
%token PERCENTILE_DISC_SYM
%token PERSISTENT_SYM
%token PHASE_SYM
%token PLUGINS_SYM
...
...
@@ -1577,6 +1580,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token WINDOW_SYM
%token WHILE_SYM
%token WITH /* SQL-2003-R */
%token WITHIN
%token WITH_CUBE_SYM /* INTERNAL */
%token WITH_ROLLUP_SYM /* INTERNAL */
%token WORK_SYM /* SQL-2003-N */
...
...
@@ -1736,6 +1740,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
window_func_expr
window_func
simple_window_func
inverse_distribution_function
percentile_function
inverse_distribution_function_def
function_call_keyword
function_call_nonkeyword
function_call_generic
...
...
@@ -1958,7 +1965,6 @@ END_OF_INPUT
%type <spvar_definition> row_field_name row_field_definition
%type <spvar_definition_list> row_field_definition_list row_type_body
%type <NONE> opt_window_clause window_def_list window_def window_spec
%type <lex_str_ptr> window_name
%type <NONE> opt_window_ref opt_window_frame_clause
...
...
@@ -9411,6 +9417,7 @@ column_default_non_parenthesized_expr:
| variable
| sum_expr
| window_func_expr
| inverse_distribution_function
| ROW_SYM '(' expr ',' expr_list ')'
{
$5->push_front($3, thd->mem_root);
...
...
@@ -10269,6 +10276,11 @@ geometry_function:
Geometry::wkb_polygon,
Geometry::wkb_linestring));
}
| WITHIN '(' expr ',' expr ')'
{
$$= GEOM_NEW(thd, Item_func_spatial_precise_rel(thd, $3, $5,
Item_func::SP_WITHIN_FUNC));
}
;
/*
...
...
@@ -10730,6 +10742,71 @@ simple_window_func:
}
;
inverse_distribution_function:
percentile_function OVER_SYM
'(' opt_window_partition_clause ')'
{
LEX *lex= Lex;
if (Select->add_window_spec(thd, lex->win_ref,
Select->group_list,
Select->order_list,
NULL))
MYSQL_YYABORT;
$$= new (thd->mem_root) Item_window_func(thd, (Item_sum *) $1,
thd->lex->win_spec);
if ($$ == NULL)
MYSQL_YYABORT;
if (Select->add_window_func((Item_window_func *) $$))
MYSQL_YYABORT;
}
;
percentile_function:
inverse_distribution_function_def WITHIN GROUP_SYM '('
{ Select->prepare_add_window_spec(thd); }
order_by_single_element_list ')'
{
$$= $1;
}
| MEDIAN_SYM '(' expr ')'
{
Item *args= new (thd->mem_root) Item_decimal(thd, "0.5", 3,
thd->charset());
if (($$ == NULL) || (thd->is_error()))
{
MYSQL_YYABORT;
}
if (add_order_to_list(thd, $3,FALSE)) MYSQL_YYABORT;
$$= new (thd->mem_root) Item_sum_percentile_cont(thd, args);
if ($$ == NULL)
MYSQL_YYABORT;
}
;
inverse_distribution_function_def:
PERCENTILE_CONT_SYM '(' expr ')'
{
$$= new (thd->mem_root) Item_sum_percentile_cont(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| PERCENTILE_DISC_SYM '(' expr ')'
{
$$= new (thd->mem_root) Item_sum_percentile_disc(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
;
order_by_single_element_list:
ORDER_SYM BY order_ident order_dir
{ if (add_order_to_list(thd, $3,(bool) $4)) MYSQL_YYABORT; }
;
window_name:
ident
{
...
...
@@ -14665,6 +14742,7 @@ keyword:
| UNICODE_SYM {}
| UNINSTALL_SYM {}
| UNBOUNDED_SYM {}
| WITHIN {}
| WRAPPER_SYM {}
| XA_SYM {}
| UPGRADE_SYM {}
...
...
sql/sql_yacc_ora.yy
View file @
914e2c9b
...
...
@@ -645,6 +645,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token MAX_STATEMENT_TIME_SYM
%token MAX_USER_CONNECTIONS_SYM
%token MAXVALUE_SYM /* SQL-2003-N */
%token MEDIAN_SYM
%token MEDIUMBLOB
%token MEDIUMINT
%token MEDIUMTEXT
...
...
@@ -737,6 +738,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token PARTITIONING_SYM
%token PASSWORD_SYM
%token PERCENT_RANK_SYM
%token PERCENTILE_CONT_SYM
%token PERCENTILE_DISC_SYM
%token PERSISTENT_SYM
%token PHASE_SYM
%token PLUGINS_SYM
...
...
@@ -983,6 +986,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token WINDOW_SYM
%token WHILE_SYM
%token WITH /* SQL-2003-R */
%token WITHIN
%token WITH_CUBE_SYM /* INTERNAL */
%token WITH_ROLLUP_SYM /* INTERNAL */
%token WORK_SYM /* SQL-2003-N */
...
...
@@ -1147,6 +1151,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
window_func_expr
window_func
simple_window_func
inverse_distribution_function
percentile_function
inverse_distribution_function_def
explicit_cursor_attr
function_call_keyword
function_call_nonkeyword
...
...
@@ -9389,6 +9396,7 @@ column_default_non_parenthesized_expr:
| variable
| sum_expr
| window_func_expr
| inverse_distribution_function
| ROW_SYM '(' expr ',' expr_list ')'
{
$5->push_front($3, thd->mem_root);
...
...
@@ -10717,6 +10725,67 @@ simple_window_func:
MYSQL_YYABORT;
}
;
inverse_distribution_function:
percentile_function OVER_SYM
'(' opt_window_partition_clause ')'
{
LEX *lex= Lex;
if (Select->add_window_spec(thd, lex->win_ref,
Select->group_list,
Select->order_list,
NULL))
MYSQL_YYABORT;
$$= new (thd->mem_root) Item_window_func(thd, (Item_sum *) $1,
thd->lex->win_spec);
if ($$ == NULL)
MYSQL_YYABORT;
if (Select->add_window_func((Item_window_func *) $$))
MYSQL_YYABORT;
}
;
percentile_function:
inverse_distribution_function_def WITHIN GROUP_SYM '('
{ Select->prepare_add_window_spec(thd); }
order_by_single_element_list ')'
{
$$= $1;
}
| MEDIAN_SYM '(' expr ')'
{
Item *args= new (thd->mem_root) Item_decimal(thd, "0.5", 3,
thd->charset());
if (($$ == NULL) || (thd->is_error()))
{
MYSQL_YYABORT;
}
if (add_order_to_list(thd, $3,FALSE)) MYSQL_YYABORT;
$$= new (thd->mem_root) Item_sum_percentile_cont(thd, args);
if ($$ == NULL)
MYSQL_YYABORT;
}
;
inverse_distribution_function_def:
PERCENTILE_CONT_SYM '(' expr ')'
{
$$= new (thd->mem_root) Item_sum_percentile_cont(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| PERCENTILE_DISC_SYM '(' expr ')'
{
$$= new (thd->mem_root) Item_sum_percentile_disc(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
;
order_by_single_element_list:
ORDER_SYM BY order_ident order_dir
{ if (add_order_to_list(thd, $3,(bool) $4)) MYSQL_YYABORT; }
;
window_name:
ident
...
...
@@ -14703,6 +14772,7 @@ keyword_directly_assignable:
| UNICODE_SYM {}
| UNINSTALL_SYM {}
| UNBOUNDED_SYM {}
| WITHIN {}
| WRAPPER_SYM {}
| XA_SYM {}
| UPGRADE_SYM {}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment