mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-10 09:32:06 +00:00
Fixed absolutely incorrect code; added test [#CLICKHOUSE-2755].
This commit is contained in:
parent
74cef1d69e
commit
0673f75265
@ -195,67 +195,45 @@ int ColumnNullable::compareAt(size_t n, size_t m, const IColumn & rhs_, int null
|
||||
|
||||
void ColumnNullable::getPermutation(bool reverse, size_t limit, Permutation & res) const
|
||||
{
|
||||
nested_column->getPermutation(reverse, limit, res);
|
||||
size_t s = res.size();
|
||||
/// Cannot pass limit because of unknown amount of NULLs.
|
||||
nested_column->getPermutation(reverse, 0, res);
|
||||
|
||||
/// Since we have created a permutation "res" that sorts a subset of the column values
|
||||
/// and some of these values may actually be nulls, there is no guarantee that
|
||||
/// these null values are well positioned. So we create a permutation "p" which
|
||||
/// operates on the result of "res" by moving all the null values to the required
|
||||
/// direction and leaving the order of the remaining elements unchanged.
|
||||
/// Shift all NULL values to the end.
|
||||
|
||||
/// Create the permutation p.
|
||||
Permutation p;
|
||||
p.resize(s);
|
||||
size_t read_idx = 0;
|
||||
size_t write_idx = 0;
|
||||
size_t end_idx = res.size();
|
||||
|
||||
size_t pos_left = 0;
|
||||
size_t pos_right = s - 1;
|
||||
if (!limit)
|
||||
limit = end_idx;
|
||||
|
||||
if (reverse)
|
||||
while (read_idx < limit && !isNullAt(res[read_idx]))
|
||||
{
|
||||
/// Move the null elements to the right.
|
||||
for (size_t i = 0; i < s; ++i)
|
||||
{
|
||||
if (isNullAt(res[i]))
|
||||
{
|
||||
p[i] = pos_right;
|
||||
--pos_right;
|
||||
}
|
||||
else
|
||||
{
|
||||
p[i] = pos_left;
|
||||
++pos_left;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Move the null elements to the left.
|
||||
for (size_t i = 0; i < s; ++i)
|
||||
{
|
||||
size_t j = s - i - 1;
|
||||
|
||||
if (isNullAt(res[j]))
|
||||
{
|
||||
p[j] = pos_left;
|
||||
++pos_left;
|
||||
}
|
||||
else
|
||||
{
|
||||
p[j] = pos_right;
|
||||
--pos_right;
|
||||
}
|
||||
}
|
||||
++read_idx;
|
||||
++write_idx;
|
||||
}
|
||||
|
||||
/// Combine the permutations res and p.
|
||||
Permutation res2;
|
||||
res2.resize(s);
|
||||
++read_idx;
|
||||
|
||||
for (size_t i = 0; i < s; ++i)
|
||||
res2[i] = res[p[i]];
|
||||
/// Invariants:
|
||||
/// write_idx < read_idx
|
||||
/// write_idx points to NULL
|
||||
/// read_idx will be incremented to position of next not-NULL
|
||||
/// there are range of NULLs between write_idx and read_idx - 1,
|
||||
/// We are moving elements from end to begin of this range,
|
||||
/// so range will "bubble" towards the end.
|
||||
/// Relative order of NULL elements could be changed,
|
||||
/// but relative order of non-NULLs is preserved.
|
||||
|
||||
res = std::move(res2);
|
||||
while (read_idx < end_idx && write_idx < limit)
|
||||
{
|
||||
if (!isNullAt(res[read_idx]))
|
||||
{
|
||||
std::swap(res[read_idx], res[write_idx]);
|
||||
++write_idx;
|
||||
}
|
||||
++read_idx;
|
||||
}
|
||||
}
|
||||
|
||||
void ColumnNullable::reserve(size_t n)
|
||||
|
@ -98,7 +98,7 @@ void sortBlock(Block & block, const SortDescription & description, size_t limit)
|
||||
if (!block)
|
||||
return;
|
||||
|
||||
/// Если столбец сортировки один
|
||||
/// If only one column to sort by
|
||||
if (description.size() == 1)
|
||||
{
|
||||
bool reverse = description[0].direction == -1;
|
||||
|
116
dbms/tests/queries/0_stateless/00426_nulls_sorting.reference
Normal file
116
dbms/tests/queries/0_stateless/00426_nulls_sorting.reference
Normal file
@ -0,0 +1,116 @@
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
1
|
||||
2
|
||||
2
|
||||
3
|
||||
4
|
||||
12
|
||||
\N
|
||||
12
|
||||
4
|
||||
3
|
||||
2
|
||||
2
|
||||
1
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
\N
|
||||
1
|
||||
2
|
||||
4
|
||||
5
|
||||
7
|
||||
8
|
||||
\N
|
||||
\N
|
||||
\N
|
||||
\N
|
||||
8
|
||||
7
|
||||
5
|
||||
4
|
||||
2
|
||||
1
|
||||
\N
|
||||
\N
|
||||
\N
|
||||
\N
|
||||
1
|
||||
2
|
||||
4
|
||||
5
|
||||
7
|
||||
8
|
||||
\N
|
||||
\N
|
||||
\N
|
||||
\N
|
||||
8
|
||||
7
|
||||
5
|
||||
4
|
||||
2
|
||||
1
|
||||
\N
|
||||
\N
|
||||
\N
|
||||
\N
|
||||
1 1
|
||||
2 2
|
||||
4 4
|
||||
5 5
|
||||
7 7
|
||||
8 8
|
||||
\N 0
|
||||
\N 3
|
||||
\N 6
|
||||
\N 9
|
||||
8 8
|
||||
7 7
|
||||
5 5
|
||||
4 4
|
||||
2 2
|
||||
1 1
|
||||
\N 0
|
||||
\N 3
|
||||
\N 6
|
||||
\N 9
|
||||
1 1
|
||||
2 2
|
||||
4 4
|
||||
5 5
|
||||
7 7
|
||||
8 8
|
||||
\N 0
|
||||
\N 3
|
||||
\N 6
|
||||
\N 9
|
||||
8 8
|
||||
7 7
|
||||
5 5
|
||||
4 4
|
||||
2 2
|
||||
1 1
|
||||
\N 0
|
||||
\N 3
|
||||
\N 6
|
||||
\N 9
|
22
dbms/tests/queries/0_stateless/00426_nulls_sorting.sql
Normal file
22
dbms/tests/queries/0_stateless/00426_nulls_sorting.sql
Normal file
@ -0,0 +1,22 @@
|
||||
SELECT arrayJoin([0,0,0,0,0,0,0,0,0,0,0,1,2,2,3,4,12,NULL]) AS x ORDER BY x;
|
||||
SELECT arrayJoin([0,0,0,0,0,0,0,0,0,0,0,1,2,2,3,4,12,NULL]) AS x ORDER BY x DESC;
|
||||
|
||||
SET max_block_size = 1000;
|
||||
|
||||
SELECT nullIf(number, number % 3 = 0 ? number : 0) AS x FROM (SELECT * FROM system.numbers LIMIT 10) ORDER BY x;
|
||||
SELECT nullIf(number, number % 3 = 0 ? number : 0) AS x FROM (SELECT * FROM system.numbers LIMIT 10) ORDER BY x DESC;
|
||||
|
||||
SET max_block_size = 5;
|
||||
|
||||
SELECT nullIf(number, number % 3 = 0 ? number : 0) AS x FROM (SELECT * FROM system.numbers LIMIT 10) ORDER BY x;
|
||||
SELECT nullIf(number, number % 3 = 0 ? number : 0) AS x FROM (SELECT * FROM system.numbers LIMIT 10) ORDER BY x DESC;
|
||||
|
||||
SET max_block_size = 1000;
|
||||
|
||||
SELECT nullIf(number, number % 3 = 0 ? number : 0) AS x, number AS y FROM (SELECT * FROM system.numbers LIMIT 10) ORDER BY x, y;
|
||||
SELECT nullIf(number, number % 3 = 0 ? number : 0) AS x, number AS y FROM (SELECT * FROM system.numbers LIMIT 10) ORDER BY x DESC, y;
|
||||
|
||||
SET max_block_size = 5;
|
||||
|
||||
SELECT nullIf(number, number % 3 = 0 ? number : 0) AS x, number AS y FROM (SELECT * FROM system.numbers LIMIT 10) ORDER BY x, y;
|
||||
SELECT nullIf(number, number % 3 = 0 ? number : 0) AS x, number AS y FROM (SELECT * FROM system.numbers LIMIT 10) ORDER BY x DESC, y;
|
Loading…
Reference in New Issue
Block a user