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
c17f1df8
Commit
c17f1df8
authored
Feb 04, 2016
by
Sergei Petrunia
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Moved window function computation code from JOIN::exec_inner() into
a separate function, JOIN::process_window_functions().
parent
373cd9f5
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
151 additions
and
0 deletions
+151
-0
sql/sql_select.cc
sql/sql_select.cc
+1
-0
sql/sql_select.h
sql/sql_select.h
+4
-0
sql/sql_window.cc
sql/sql_window.cc
+139
-0
sql/sql_window.h
sql/sql_window.h
+7
-0
No files found.
sql/sql_select.cc
View file @
c17f1df8
...
...
@@ -3235,6 +3235,7 @@ void JOIN::exec_inner()
error
=
thd
->
is_error
();
DBUG_VOID_RETURN
;
}
process_window_functions
(
curr_fields_list
);
THD_STAGE_INFO
(
thd
,
stage_sending_data
);
DBUG_PRINT
(
"info"
,
(
"%s"
,
thd
->
proc_info
));
...
...
sql/sql_select.h
View file @
c17f1df8
...
...
@@ -1518,6 +1518,9 @@ class JOIN :public Sql_alloc
int
reinit
();
int
init_execution
();
void
exec
();
void
process_window_functions
(
List
<
Item
>
*
curr_fields_list
);
void
exec_inner
();
bool
prepare_result
(
List
<
Item
>
**
columns_list
);
int
destroy
();
...
...
@@ -2291,4 +2294,5 @@ class Pushdown_query: public Sql_alloc
int
execute
(
JOIN
*
join
);
};
bool
test_if_order_compatible
(
SQL_I_List
<
ORDER
>
&
a
,
SQL_I_List
<
ORDER
>
&
b
);
#endif
/* SQL_SELECT_INCLUDED */
sql/sql_window.cc
View file @
c17f1df8
#include "sql_select.h"
#include "item_windowfunc.h"
#include "filesort.h"
#include "sql_window.h"
...
...
@@ -77,3 +79,140 @@ setup_windows(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
}
DBUG_RETURN
(
0
);
}
/*
@brief
This function is called by JOIN::exec to compute window function values
@detail
JOIN::exec calls this after it has filled the temporary table with query
output. The temporary table has fields to store window function values.
*/
void
JOIN
::
process_window_functions
(
List
<
Item
>
*
curr_fields_list
)
{
/*
TODO Get this code to set can_compute_window_function during preparation,
not during execution.
The reason for this is the following:
Our single scan optimization for window functions without tmp table,
is valid, if and only if, we only need to perform one sorting operation,
via filesort. The cases where we need to perform one sorting operation only:
* A select with only one window function.
* A select with multiple window functions, but they must have their
partition and order by clauses compatible. This means that one ordering
is acceptable for both window functions.
For example:
partition by a, b, c; order by d, e results in sorting by a b c d e.
partition by a; order by d results in sorting by a d.
This kind of sorting is compatible. The less specific partition does
not care for the order of b and c columns so it is valid if we sort
by those in case of equality over a.
partition by a, b; order by d, e results in sorting by a b d e
partition by a; order by e results in sorting by a e
This sorting is incompatible due to the order by clause. The partition by
clause is compatible, (partition by a) is a prefix for (partition by a, b)
However, order by e is not a prefix for order by d, e, thus it is not
compatible.
The rule for having compatible sorting is thus:
Each partition order must contain the other window functions partitions
prefixes, or be a prefix itself. This must hold true for all partitions.
Analog for the order by clause.
*/
List
<
Item_window_func
>
window_functions
;
SQL_I_List
<
ORDER
>
largest_partition
;
SQL_I_List
<
ORDER
>
largest_order_by
;
List_iterator_fast
<
Item
>
it
(
*
curr_fields_list
);
bool
can_compute_window_live
=
!
need_tmp
;
Item
*
item
;
// Construct the window_functions item list and check if they can be
// computed using only one sorting.
//
// TODO: Perhaps group functions into compatible sorting bins
// to minimize the number of sorting passes required to compute all of them.
while
((
item
=
it
++
))
{
if
(
item
->
type
()
==
Item
::
WINDOW_FUNC_ITEM
)
{
Item_window_func
*
item_win
=
(
Item_window_func
*
)
item
;
window_functions
.
push_back
(
item_win
);
if
(
!
can_compute_window_live
)
continue
;
// No point checking since we have to perform multiple sorts.
Window_spec
*
spec
=
item_win
->
window_spec
;
// Having an empty partition list on one window function and a
// not empty list on a separate window function causes the sorting
// to be incompatible.
//
// Example:
// over (partition by a, order by x) && over (order by x).
//
// The first function requires an ordering by a first and then by x,
// while the seond function requires an ordering by x first.
// The same restriction is not required for the order by clause.
if
(
largest_partition
.
elements
&&
!
spec
->
partition_list
.
elements
)
{
can_compute_window_live
=
FALSE
;
continue
;
}
can_compute_window_live
=
test_if_order_compatible
(
largest_partition
,
spec
->
partition_list
);
if
(
!
can_compute_window_live
)
continue
;
can_compute_window_live
=
test_if_order_compatible
(
largest_order_by
,
spec
->
order_list
);
if
(
!
can_compute_window_live
)
continue
;
if
(
largest_partition
.
elements
<
spec
->
partition_list
.
elements
)
largest_partition
=
spec
->
partition_list
;
if
(
largest_order_by
.
elements
<
spec
->
order_list
.
elements
)
largest_order_by
=
spec
->
order_list
;
}
}
if
(
can_compute_window_live
&&
window_functions
.
elements
&&
table_count
==
1
)
{
ha_rows
examined_rows
=
0
;
ha_rows
found_rows
=
0
;
ha_rows
filesort_retval
;
SORT_FIELD
*
s_order
=
(
SORT_FIELD
*
)
my_malloc
(
sizeof
(
SORT_FIELD
)
*
(
largest_partition
.
elements
+
largest_order_by
.
elements
)
+
1
,
MYF
(
MY_WME
|
MY_ZEROFILL
|
MY_THREAD_SPECIFIC
));
size_t
pos
=
0
;
for
(
ORDER
*
curr
=
largest_partition
.
first
;
curr
;
curr
=
curr
->
next
,
pos
++
)
s_order
[
pos
].
item
=
*
curr
->
item
;
for
(
ORDER
*
curr
=
largest_order_by
.
first
;
curr
;
curr
=
curr
->
next
,
pos
++
)
s_order
[
pos
].
item
=
*
curr
->
item
;
table
[
0
]
->
sort
.
io_cache
=
(
IO_CACHE
*
)
my_malloc
(
sizeof
(
IO_CACHE
),
MYF
(
MY_WME
|
MY_ZEROFILL
|
MY_THREAD_SPECIFIC
));
filesort_retval
=
filesort
(
thd
,
table
[
0
],
s_order
,
(
largest_partition
.
elements
+
largest_order_by
.
elements
),
this
->
select
,
HA_POS_ERROR
,
FALSE
,
&
examined_rows
,
&
found_rows
,
this
->
explain
->
ops_tracker
.
report_sorting
(
thd
));
table
[
0
]
->
sort
.
found_records
=
filesort_retval
;
join_tab
->
read_first_record
=
join_init_read_record
;
join_tab
->
records
=
found_rows
;
my_free
(
s_order
);
}
}
sql/sql_window.h
View file @
c17f1df8
...
...
@@ -5,6 +5,13 @@
#include "my_global.h"
#include "item.h"
/*
Window functions module.
Each instance of window function has its own element in SELECT_LEX::window_specs.
*/
class
Window_frame_bound
:
public
Sql_alloc
{
...
...
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