mirror of https://github.com/apache/druid.git
allow segment table to sort on start and end when grouped (#15720)
This commit is contained in:
parent
4e50a14d50
commit
45ad47cc66
|
@ -26,6 +26,10 @@
|
||||||
.rt-td.padded,
|
.rt-td.padded,
|
||||||
.rt-expandable {
|
.rt-expandable {
|
||||||
padding: $table-cell-v-padding $table-cell-h-padding;
|
padding: $table-cell-v-padding $table-cell-h-padding;
|
||||||
|
|
||||||
|
.default-aggregated {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -218,6 +218,7 @@ exports[`SegmentsView matches snapshot 1`] = `
|
||||||
"width": 100,
|
"width": 100,
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
|
"Aggregated": [Function],
|
||||||
"Cell": [Function],
|
"Cell": [Function],
|
||||||
"Header": "Shard spec",
|
"Header": "Shard spec",
|
||||||
"accessor": "shard_spec",
|
"accessor": "shard_spec",
|
||||||
|
|
|
@ -56,6 +56,7 @@ import { Api } from '../../singletons';
|
||||||
import type { NumberLike } from '../../utils';
|
import type { NumberLike } from '../../utils';
|
||||||
import {
|
import {
|
||||||
compact,
|
compact,
|
||||||
|
countBy,
|
||||||
deepGet,
|
deepGet,
|
||||||
filterMap,
|
filterMap,
|
||||||
formatBytes,
|
formatBytes,
|
||||||
|
@ -64,6 +65,7 @@ import {
|
||||||
isNumberLikeNaN,
|
isNumberLikeNaN,
|
||||||
LocalStorageBackedVisibility,
|
LocalStorageBackedVisibility,
|
||||||
LocalStorageKeys,
|
LocalStorageKeys,
|
||||||
|
oneOf,
|
||||||
queryDruidSql,
|
queryDruidSql,
|
||||||
QueryManager,
|
QueryManager,
|
||||||
QueryState,
|
QueryState,
|
||||||
|
@ -137,6 +139,11 @@ interface Sorted {
|
||||||
desc: boolean;
|
desc: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sortedToOrderByClause(sorted: Sorted[]): string | undefined {
|
||||||
|
if (!sorted.length) return;
|
||||||
|
return 'ORDER BY ' + sorted.map(sort => `${C(sort.id)} ${sort.desc ? 'DESC' : 'ASC'}`).join(', ');
|
||||||
|
}
|
||||||
|
|
||||||
interface TableState {
|
interface TableState {
|
||||||
page: number;
|
page: number;
|
||||||
pageSize: number;
|
pageSize: number;
|
||||||
|
@ -315,9 +322,9 @@ END AS "time_span"`,
|
||||||
|
|
||||||
let queryParts: string[];
|
let queryParts: string[];
|
||||||
|
|
||||||
let whereClause = '';
|
let filterClause = '';
|
||||||
if (whereParts.length) {
|
if (whereParts.length) {
|
||||||
whereClause = SqlExpression.and(...whereParts).toString();
|
filterClause = SqlExpression.and(...whereParts).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
let effectiveSorted = sorted;
|
let effectiveSorted = sorted;
|
||||||
|
@ -331,61 +338,45 @@ END AS "time_span"`,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const base = SegmentsView.baseQuery(visibleColumns);
|
||||||
|
const orderByClause = sortedToOrderByClause(effectiveSorted);
|
||||||
|
|
||||||
if (groupByInterval) {
|
if (groupByInterval) {
|
||||||
const innerQuery = compact([
|
const innerQuery = compact([
|
||||||
`SELECT "start" || '/' || "end" AS "interval"`,
|
`SELECT "start", "end"`,
|
||||||
`FROM sys.segments`,
|
`FROM sys.segments`,
|
||||||
whereClause ? `WHERE ${whereClause}` : undefined,
|
filterClause ? `WHERE ${filterClause}` : undefined,
|
||||||
`GROUP BY 1`,
|
`GROUP BY 1, 2`,
|
||||||
|
sortedToOrderByClause(sorted.filter(sort => oneOf(sort.id, 'start', 'end'))) ||
|
||||||
`ORDER BY 1 DESC`,
|
`ORDER BY 1 DESC`,
|
||||||
`LIMIT ${pageSize}`,
|
`LIMIT ${pageSize}`,
|
||||||
page ? `OFFSET ${page * pageSize}` : undefined,
|
page ? `OFFSET ${page * pageSize}` : undefined,
|
||||||
]).join('\n');
|
]).join('\n');
|
||||||
|
|
||||||
const intervals: string = (await queryDruidSql({ query: innerQuery }))
|
const intervals: string = (await queryDruidSql({ query: innerQuery }))
|
||||||
.map(row => `'${row.interval}'`)
|
.map(({ start, end }) => `'${start}/${end}'`)
|
||||||
.join(', ');
|
.join(', ');
|
||||||
|
|
||||||
queryParts = compact([
|
queryParts = compact([
|
||||||
SegmentsView.baseQuery(visibleColumns),
|
base,
|
||||||
`SELECT "start" || '/' || "end" AS "interval", *`,
|
`SELECT "start" || '/' || "end" AS "interval", *`,
|
||||||
`FROM s`,
|
`FROM s`,
|
||||||
`WHERE`,
|
`WHERE`,
|
||||||
intervals ? ` ("start" || '/' || "end") IN (${intervals})` : 'FALSE',
|
intervals ? ` ("start" || '/' || "end") IN (${intervals})` : 'FALSE',
|
||||||
whereClause ? ` AND ${whereClause}` : '',
|
filterClause ? ` AND ${filterClause}` : '',
|
||||||
|
orderByClause,
|
||||||
|
`LIMIT ${pageSize * 1000}`,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (effectiveSorted.length) {
|
|
||||||
queryParts.push(
|
|
||||||
'ORDER BY ' +
|
|
||||||
effectiveSorted
|
|
||||||
.map(sort => `${C(sort.id)} ${sort.desc ? 'DESC' : 'ASC'}`)
|
|
||||||
.join(', '),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
queryParts.push(`LIMIT ${pageSize * 1000}`);
|
|
||||||
} else {
|
} else {
|
||||||
queryParts = [SegmentsView.baseQuery(visibleColumns), `SELECT *`, `FROM s`];
|
queryParts = compact([
|
||||||
|
base,
|
||||||
if (whereClause) {
|
`SELECT *`,
|
||||||
queryParts.push(`WHERE ${whereClause}`);
|
`FROM s`,
|
||||||
}
|
filterClause ? `WHERE ${filterClause}` : undefined,
|
||||||
|
orderByClause,
|
||||||
if (effectiveSorted.length) {
|
`LIMIT ${pageSize}`,
|
||||||
queryParts.push(
|
page ? `OFFSET ${page * pageSize}` : undefined,
|
||||||
'ORDER BY ' +
|
]);
|
||||||
effectiveSorted
|
|
||||||
.map(sort => `${C(sort.id)} ${sort.desc ? 'DESC' : 'ASC'}`)
|
|
||||||
.join(', '),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
queryParts.push(`LIMIT ${pageSize}`);
|
|
||||||
|
|
||||||
if (page) {
|
|
||||||
queryParts.push(`OFFSET ${page * pageSize}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const sqlQuery = queryParts.join('\n');
|
const sqlQuery = queryParts.join('\n');
|
||||||
setIntermediateQuery(sqlQuery);
|
setIntermediateQuery(sqlQuery);
|
||||||
|
@ -762,6 +753,19 @@ END AS "time_span"`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Aggregated: opt => {
|
||||||
|
const { subRows } = opt;
|
||||||
|
const previewValues = filterMap(subRows, row => row['shard_spec'].type);
|
||||||
|
const previewCount = countBy(previewValues);
|
||||||
|
return (
|
||||||
|
<div className="default-aggregated">
|
||||||
|
{Object.keys(previewCount)
|
||||||
|
.sort()
|
||||||
|
.map(v => `${v} (${previewCount[v]})`)
|
||||||
|
.join(', ')}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: 'Partition',
|
Header: 'Partition',
|
||||||
|
|
Loading…
Reference in New Issue