ydb-embedded-ui 1.8.7 → 1.10.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +56 -0
- package/dist/components/BasicNodeViewer/BasicNodeViewer.scss +43 -0
- package/dist/components/BasicNodeViewer/BasicNodeViewer.tsx +53 -0
- package/dist/components/BasicNodeViewer/index.ts +1 -0
- package/dist/components/EntityStatus/EntityStatus.js +15 -3
- package/dist/components/FullNodeViewer/FullNodeViewer.js +29 -48
- package/dist/components/FullNodeViewer/FullNodeViewer.scss +0 -45
- package/dist/components/IndexInfoViewer/IndexInfoViewer.tsx +52 -0
- package/dist/components/InfoViewer/index.ts +4 -0
- package/dist/components/InfoViewer/utils.ts +32 -0
- package/dist/components/ProgressViewer/ProgressViewer.js +1 -1
- package/dist/components/TabletsOverall/TabletsOverall.tsx +1 -1
- package/dist/containers/Node/Node.scss +5 -1
- package/dist/containers/Node/Node.tsx +7 -1
- package/dist/containers/Node/NodeOverview/NodeOverview.tsx +1 -3
- package/dist/containers/Node/NodeStructure/NodeStructure.scss +30 -1
- package/dist/containers/Node/NodeStructure/PDiskTitleBadge.tsx +25 -0
- package/dist/containers/Node/NodeStructure/Pdisk.tsx +24 -2
- package/dist/containers/Nodes/Nodes.js +1 -0
- package/dist/containers/ReduxTooltip/ReduxTooltip.js +1 -1
- package/dist/containers/Storage/Pdisk/Pdisk.tsx +25 -33
- package/dist/containers/Storage/Vdisk/Vdisk.js +2 -0
- package/dist/containers/Tablet/Tablet.js +2 -2
- package/dist/containers/Tablets/Tablets.js +1 -1
- package/dist/containers/Tablets/Tablets.scss +0 -6
- package/dist/containers/TabletsFilters/TabletsFilters.scss +0 -7
- package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +6 -2
- package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.ts +24 -14
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.js +6 -2
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.scss +6 -2
- package/dist/containers/Tenant/Diagnostics/HotKeys/HotKeys.js +3 -3
- package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +24 -3
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +15 -13
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.scss +22 -6
- package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.js +80 -10
- package/dist/containers/Tenant/Schema/SchemaInfoViewer/SchemaInfoViewer.js +20 -16
- package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +1 -0
- package/dist/containers/Tenant/utils/schema.ts +73 -28
- package/dist/containers/Tenant/utils/schemaActions.ts +42 -32
- package/dist/services/api.js +13 -8
- package/dist/store/reducers/executeQuery.js +1 -1
- package/dist/store/reducers/executeTopQueries.js +1 -1
- package/dist/store/reducers/olapStats.js +5 -1
- package/dist/store/reducers/preview.js +1 -1
- package/dist/store/reducers/shardsWorkload.js +32 -4
- package/dist/types/api/schema.ts +43 -1
- package/dist/types/api/storage.ts +54 -0
- package/dist/utils/getNodesColumns.js +2 -0
- package/dist/utils/pdisk.ts +74 -0
- package/dist/utils/tooltip.js +27 -0
- package/package.json +2 -2
@@ -1,4 +1,4 @@
|
|
1
|
-
import {useContext, useEffect, useMemo} from 'react';
|
1
|
+
import {useState, useContext, useEffect, useMemo} from 'react';
|
2
2
|
import cn from 'bem-cn-lite';
|
3
3
|
import {connect} from 'react-redux';
|
4
4
|
import {Loader} from '@yandex-cloud/uikit';
|
@@ -14,15 +14,25 @@ import HistoryContext from '../../../../contexts/HistoryContext';
|
|
14
14
|
import {DEFAULT_TABLE_SETTINGS} from '../../../../utils/constants';
|
15
15
|
import {isColumnEntityType} from '../../utils/schema';
|
16
16
|
import {prepareQueryError} from '../../../../utils';
|
17
|
+
import {i18n} from '../../../../utils/i18n';
|
17
18
|
|
18
19
|
import './TopShards.scss';
|
19
20
|
|
20
21
|
const b = cn('top-shards');
|
21
22
|
const bLink = cn('yc-link');
|
22
23
|
|
24
|
+
const TABLE_SETTINGS = {
|
25
|
+
...DEFAULT_TABLE_SETTINGS,
|
26
|
+
dynamicRender: false, // no more than 20 rows
|
27
|
+
externalSort: true,
|
28
|
+
disableSortReset: true,
|
29
|
+
defaultOrder: DataTable.DESCENDING,
|
30
|
+
};
|
31
|
+
|
23
32
|
const tableColumnsNames = {
|
24
33
|
TabletId: 'TabletId',
|
25
34
|
CPUCores: 'CPUCores',
|
35
|
+
DataSize: 'DataSize',
|
26
36
|
Path: 'Path',
|
27
37
|
};
|
28
38
|
|
@@ -32,6 +42,28 @@ function prepareCPUWorkloadValue(value) {
|
|
32
42
|
return `${(value * 100).toFixed(2)}%`;
|
33
43
|
}
|
34
44
|
|
45
|
+
function prepareDateSizeValue(value) {
|
46
|
+
return new Intl.NumberFormat(i18n.lang).format(value);
|
47
|
+
}
|
48
|
+
|
49
|
+
function stringToDataTableSortOrder(value) {
|
50
|
+
return value && value.split(',').map((columnId) => ({
|
51
|
+
columnId,
|
52
|
+
order: DataTable.DESCENDING,
|
53
|
+
}));
|
54
|
+
}
|
55
|
+
|
56
|
+
function stringToQuerySortOrder(value) {
|
57
|
+
return value && value.split(',').map((columnId) => ({
|
58
|
+
columnId,
|
59
|
+
order: 'DESC',
|
60
|
+
}));
|
61
|
+
}
|
62
|
+
|
63
|
+
function dataTableToStringSortOrder(value = []) {
|
64
|
+
return value.map(({columnId}) => columnId).join(',');
|
65
|
+
}
|
66
|
+
|
35
67
|
function TopShards({
|
36
68
|
sendShardQuery,
|
37
69
|
currentSchemaPath,
|
@@ -46,25 +78,40 @@ function TopShards({
|
|
46
78
|
setShardQueryOptions,
|
47
79
|
type,
|
48
80
|
}) {
|
81
|
+
const [sortOrder, setSortOrder] = useState(tableColumnsNames.CPUCores);
|
82
|
+
|
49
83
|
useEffect(() => {
|
84
|
+
autofetcher.stop();
|
85
|
+
|
50
86
|
if (autorefresh) {
|
51
87
|
autofetcher.start();
|
52
|
-
autofetcher.fetch(() => sendShardQuery({
|
53
|
-
|
54
|
-
|
88
|
+
autofetcher.fetch(() => sendShardQuery({
|
89
|
+
database: path,
|
90
|
+
path: currentSchemaPath,
|
91
|
+
sortOrder: stringToQuerySortOrder(sortOrder),
|
92
|
+
}));
|
55
93
|
}
|
94
|
+
|
56
95
|
return () => {
|
57
96
|
autofetcher.stop();
|
58
97
|
};
|
59
|
-
}, [autorefresh]);
|
98
|
+
}, [autorefresh, currentSchemaPath, path, sendShardQuery, sortOrder]);
|
60
99
|
|
100
|
+
// don't show loader for requests triggered by table sort, only for path change
|
61
101
|
useEffect(() => {
|
62
|
-
sendShardQuery({database: path, path: currentSchemaPath});
|
63
102
|
setShardQueryOptions({
|
64
103
|
wasLoaded: false,
|
65
104
|
data: undefined,
|
66
105
|
});
|
67
|
-
}, [currentSchemaPath]);
|
106
|
+
}, [currentSchemaPath, path, setShardQueryOptions]);
|
107
|
+
|
108
|
+
useEffect(() => {
|
109
|
+
sendShardQuery({
|
110
|
+
database: path,
|
111
|
+
path: currentSchemaPath,
|
112
|
+
sortOrder: stringToQuerySortOrder(sortOrder),
|
113
|
+
});
|
114
|
+
}, [currentSchemaPath, path, sendShardQuery, sortOrder]);
|
68
115
|
|
69
116
|
const history = useContext(HistoryContext);
|
70
117
|
|
@@ -76,6 +123,13 @@ function TopShards({
|
|
76
123
|
};
|
77
124
|
};
|
78
125
|
|
126
|
+
const onSort = (newSortOrder) => {
|
127
|
+
// omit information about sort order to disable ASC order, only DESC makes sense for top shards
|
128
|
+
// use a string (and not the DataTable default format) to prevent reference change,
|
129
|
+
// which would cause an excess state change, to avoid repeating requests
|
130
|
+
setSortOrder(dataTableToStringSortOrder(newSortOrder));
|
131
|
+
};
|
132
|
+
|
79
133
|
const tableColumns = useMemo(() => {
|
80
134
|
return [
|
81
135
|
{
|
@@ -83,11 +137,16 @@ function TopShards({
|
|
83
137
|
// eslint-disable-next-line
|
84
138
|
render: ({value}) => {
|
85
139
|
return (
|
86
|
-
<span
|
140
|
+
<span
|
141
|
+
// tenant name is substringed out in sql query but is needed here
|
142
|
+
onClick={onSchemaClick(path + value)}
|
143
|
+
className={bLink({view: 'normal'})}
|
144
|
+
>
|
87
145
|
{value}
|
88
146
|
</span>
|
89
147
|
);
|
90
148
|
},
|
149
|
+
sortable: false,
|
91
150
|
},
|
92
151
|
{
|
93
152
|
name: tableColumnsNames.CPUCores,
|
@@ -97,6 +156,14 @@ function TopShards({
|
|
97
156
|
},
|
98
157
|
align: DataTable.RIGHT,
|
99
158
|
},
|
159
|
+
{
|
160
|
+
name: tableColumnsNames.DataSize,
|
161
|
+
header: 'DataSize (B)',
|
162
|
+
render: ({value}) => {
|
163
|
+
return prepareDateSizeValue(value);
|
164
|
+
},
|
165
|
+
align: DataTable.RIGHT,
|
166
|
+
},
|
100
167
|
{
|
101
168
|
name: tableColumnsNames.TabletId,
|
102
169
|
// eslint-disable-next-line
|
@@ -107,6 +174,7 @@ function TopShards({
|
|
107
174
|
</InternalLink>
|
108
175
|
);
|
109
176
|
},
|
177
|
+
sortable: false,
|
110
178
|
},
|
111
179
|
];
|
112
180
|
}, []);
|
@@ -123,7 +191,7 @@ function TopShards({
|
|
123
191
|
if (isColumnEntityType(type)) {
|
124
192
|
return 'No data';
|
125
193
|
}
|
126
|
-
if (error) {
|
194
|
+
if (error && !error.isCancelled) {
|
127
195
|
return prepareQueryError(error);
|
128
196
|
}
|
129
197
|
|
@@ -132,9 +200,11 @@ function TopShards({
|
|
132
200
|
<DataTable
|
133
201
|
columns={tableColumns}
|
134
202
|
data={data}
|
135
|
-
settings={
|
203
|
+
settings={TABLE_SETTINGS}
|
136
204
|
className={b('table')}
|
137
205
|
theme="yandex-cloud"
|
206
|
+
onSort={onSort}
|
207
|
+
sortOrder={stringToDataTableSortOrder(sortOrder)}
|
138
208
|
/>
|
139
209
|
</div>
|
140
210
|
) : (
|
@@ -28,29 +28,33 @@ class SchemaInfoViewer extends React.Component {
|
|
28
28
|
if (data) {
|
29
29
|
const {PathDescription = {}} = data;
|
30
30
|
const {TableStats = {}, TabletMetrics = {}} = PathDescription;
|
31
|
-
const
|
32
|
-
TableStats &&
|
33
|
-
Object.keys(TableStats).map((key) => ({
|
34
|
-
label: key,
|
35
|
-
value: TableStats[key].toString(),
|
36
|
-
}));
|
31
|
+
const {PartCount, ...restTableStats} = TableStats;
|
37
32
|
|
38
|
-
const
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
value: this.formatTabletMetricsValue(key, TabletMetrics[key].toString()),
|
43
|
-
}));
|
33
|
+
const priorityInfo = [{
|
34
|
+
label: 'PartCount',
|
35
|
+
value: PartCount,
|
36
|
+
}].filter(({value}) => value !== undefined);
|
44
37
|
|
45
|
-
|
46
|
-
|
38
|
+
const tableStatsInfo = Object.keys(restTableStats).map((key) => ({
|
39
|
+
label: key,
|
40
|
+
value: TableStats[key].toString(),
|
41
|
+
}));
|
47
42
|
|
48
|
-
const
|
43
|
+
const tabletMetricsInfo = Object.keys(TabletMetrics).map((key) => ({
|
44
|
+
label: key,
|
45
|
+
value: this.formatTabletMetricsValue(key, TabletMetrics[key].toString()),
|
46
|
+
}));
|
49
47
|
|
48
|
+
const generalInfo = [
|
49
|
+
...priorityInfo,
|
50
|
+
...tabletMetricsInfo,
|
51
|
+
...tableStatsInfo,
|
52
|
+
];
|
53
|
+
|
50
54
|
return (
|
51
55
|
<div className={b()}>
|
52
56
|
<div className={b('item')}>
|
53
|
-
{
|
57
|
+
{generalInfo.length ? (
|
54
58
|
<InfoViewer info={generalInfo}></InfoViewer>
|
55
59
|
) : (
|
56
60
|
<div>Empty</div>
|
@@ -1,43 +1,88 @@
|
|
1
1
|
import type {NavigationTreeNodeType} from 'ydb-ui-components';
|
2
2
|
import {EPathSubType, EPathType} from '../../../types/api/schema';
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
4
|
+
// this file contains verbose mappings that are typed in a way that ensures
|
5
|
+
// correctness when a new node type or a new path type is added
|
6
|
+
// TS will error if a new entity is added but not mapped here
|
7
|
+
|
8
|
+
const pathSubTypeToNodeType: Record<EPathSubType, NavigationTreeNodeType | undefined> = {
|
9
|
+
[EPathSubType.EPathSubTypeSyncIndexImplTable]: 'index_table',
|
10
|
+
[EPathSubType.EPathSubTypeAsyncIndexImplTable]: 'index_table',
|
11
|
+
|
12
|
+
[EPathSubType.EPathSubTypeStreamImpl]: undefined,
|
13
|
+
[EPathSubType.EPathSubTypeEmpty]: undefined,
|
14
|
+
};
|
15
|
+
|
16
|
+
const pathTypeToNodeType: Record<EPathType, NavigationTreeNodeType | undefined> = {
|
17
|
+
[EPathType.EPathTypeInvalid]: undefined,
|
18
|
+
|
19
|
+
[EPathType.EPathTypeSubDomain]: 'database',
|
20
|
+
[EPathType.EPathTypeExtSubDomain]: 'database',
|
21
|
+
|
22
|
+
[EPathType.EPathTypeDir]: 'directory',
|
23
|
+
[EPathType.EPathTypeColumnStore]: 'directory',
|
24
|
+
|
25
|
+
[EPathType.EPathTypeTable]: 'table',
|
26
|
+
|
27
|
+
[EPathType.EPathTypeTableIndex]: 'index',
|
28
|
+
|
29
|
+
[EPathType.EPathTypeColumnTable]: 'column_table',
|
30
|
+
|
31
|
+
[EPathType.EPathTypeCdcStream]: 'topic',
|
12
32
|
};
|
13
33
|
|
14
34
|
export const mapPathTypeToNavigationTreeType = (
|
15
35
|
type: EPathType = EPathType.EPathTypeDir,
|
16
36
|
subType?: EPathSubType,
|
17
37
|
defaultType: NavigationTreeNodeType = 'directory'
|
18
|
-
): NavigationTreeNodeType =>
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
38
|
+
): NavigationTreeNodeType =>
|
39
|
+
(subType && pathSubTypeToNodeType[subType]) || pathTypeToNodeType[type] || defaultType;
|
40
|
+
|
41
|
+
// ====================
|
42
|
+
|
43
|
+
const pathTypeToIsTable: Record<EPathType, boolean> = {
|
44
|
+
[EPathType.EPathTypeTable]: true,
|
45
|
+
[EPathType.EPathTypeColumnTable]: true,
|
46
|
+
|
47
|
+
[EPathType.EPathTypeInvalid]: false,
|
48
|
+
[EPathType.EPathTypeDir]: false,
|
49
|
+
[EPathType.EPathTypeSubDomain]: false,
|
50
|
+
[EPathType.EPathTypeTableIndex]: false,
|
51
|
+
[EPathType.EPathTypeExtSubDomain]: false,
|
52
|
+
[EPathType.EPathTypeColumnStore]: false,
|
53
|
+
[EPathType.EPathTypeCdcStream]: false,
|
33
54
|
};
|
34
55
|
|
35
|
-
export const isTableType = (
|
36
|
-
|
56
|
+
export const isTableType = (pathType?: EPathType) =>
|
57
|
+
(pathType && pathTypeToIsTable[pathType]) ?? false;
|
58
|
+
|
59
|
+
// ====================
|
60
|
+
|
61
|
+
const pathSubTypeToIsIndexImpl: Record<EPathSubType, boolean> = {
|
62
|
+
[EPathSubType.EPathSubTypeSyncIndexImplTable]: true,
|
63
|
+
[EPathSubType.EPathSubTypeAsyncIndexImplTable]: true,
|
64
|
+
|
65
|
+
[EPathSubType.EPathSubTypeStreamImpl]: false,
|
66
|
+
[EPathSubType.EPathSubTypeEmpty]: false,
|
67
|
+
};
|
37
68
|
|
38
69
|
export const isIndexTable = (subType?: EPathSubType) =>
|
39
|
-
|
70
|
+
(subType && pathSubTypeToIsIndexImpl[subType]) ?? false;
|
71
|
+
|
72
|
+
// ====================
|
73
|
+
|
74
|
+
const pathTypeToIsColumn: Record<EPathType, boolean> = {
|
75
|
+
[EPathType.EPathTypeColumnStore]: true,
|
76
|
+
[EPathType.EPathTypeColumnTable]: true,
|
77
|
+
|
78
|
+
[EPathType.EPathTypeInvalid]: false,
|
79
|
+
[EPathType.EPathTypeDir]: false,
|
80
|
+
[EPathType.EPathTypeTable]: false,
|
81
|
+
[EPathType.EPathTypeSubDomain]: false,
|
82
|
+
[EPathType.EPathTypeTableIndex]: false,
|
83
|
+
[EPathType.EPathTypeExtSubDomain]: false,
|
84
|
+
[EPathType.EPathTypeCdcStream]: false,
|
85
|
+
};
|
40
86
|
|
41
87
|
export const isColumnEntityType = (type?: EPathType) =>
|
42
|
-
type
|
43
|
-
type === EPathType.EPathTypeColumnTable;
|
88
|
+
(type && pathTypeToIsColumn[type]) ?? false;
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import {Dispatch} from 'react';
|
2
|
-
import type {NavigationTreeNodeType} from 'ydb-ui-components';
|
2
|
+
import type {NavigationTreeNodeType, NavigationTreeProps} from 'ydb-ui-components';
|
3
3
|
|
4
4
|
import {changeUserInput} from '../../../store/reducers/executeQuery';
|
5
5
|
import {setShowPreview} from '../../../store/reducers/schema';
|
@@ -73,6 +73,8 @@ const bindActions = (
|
|
73
73
|
};
|
74
74
|
};
|
75
75
|
|
76
|
+
type ActionsSet = ReturnType<Required<NavigationTreeProps>['getActions']>;
|
77
|
+
|
76
78
|
export const getActions = (
|
77
79
|
dispatch: Dispatch<any>,
|
78
80
|
setActivePath: (path: string) => void,
|
@@ -81,35 +83,43 @@ export const getActions = (
|
|
81
83
|
const actions = bindActions(path, dispatch, setActivePath);
|
82
84
|
const copyItem = {text: 'Copy path', action: actions.copyPath};
|
83
85
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
86
|
+
const DIR_SET: ActionsSet = [
|
87
|
+
[
|
88
|
+
copyItem,
|
89
|
+
],
|
90
|
+
[
|
91
|
+
{text: 'Create table...', action: actions.createTable},
|
92
|
+
],
|
93
|
+
];
|
94
|
+
const TABLE_SET: ActionsSet = [
|
95
|
+
[
|
96
|
+
{text: 'Open preview', action: actions.openPreview},
|
97
|
+
copyItem,
|
98
|
+
],
|
99
|
+
[
|
100
|
+
{text: 'Alter table...', action: actions.alterTable},
|
101
|
+
{text: 'Select query...', action: actions.selectQuery},
|
102
|
+
{text: 'Upsert query...', action: actions.upsertQuery},
|
103
|
+
],
|
104
|
+
];
|
105
|
+
|
106
|
+
const JUST_COPY: ActionsSet = [
|
107
|
+
copyItem,
|
108
|
+
];
|
109
|
+
|
110
|
+
const EMPTY_SET: ActionsSet = [];
|
111
|
+
|
112
|
+
// verbose mapping to guarantee a correct actions set for new node types
|
113
|
+
// TS will error when a new type is added in the lib but is not mapped here
|
114
|
+
const nodeTypeToActions: Record<NavigationTreeNodeType, ActionsSet> = {
|
115
|
+
database: DIR_SET,
|
116
|
+
directory: DIR_SET,
|
117
|
+
table: TABLE_SET,
|
118
|
+
column_table: TABLE_SET,
|
119
|
+
index_table: JUST_COPY,
|
120
|
+
index: EMPTY_SET,
|
121
|
+
topic: DIR_SET,
|
122
|
+
};
|
123
|
+
|
124
|
+
return nodeTypeToActions[type];
|
115
125
|
};
|
package/dist/services/api.js
CHANGED
@@ -147,14 +147,19 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
147
147
|
state: 0,
|
148
148
|
});
|
149
149
|
}
|
150
|
-
sendQuery(query, database, action, stats) {
|
151
|
-
return this.post(
|
152
|
-
query,
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
150
|
+
sendQuery({query, database, action, stats}, {concurrentId} = {}) {
|
151
|
+
return this.post(
|
152
|
+
this.getPath('/viewer/json/query'),
|
153
|
+
{
|
154
|
+
query,
|
155
|
+
database,
|
156
|
+
action,
|
157
|
+
stats,
|
158
|
+
timeout: 600000,
|
159
|
+
},
|
160
|
+
null,
|
161
|
+
{concurrentId},
|
162
|
+
);
|
158
163
|
}
|
159
164
|
getExplainQuery(query, database) {
|
160
165
|
return this.post(this.getPath('/viewer/json/query'), {
|
@@ -141,7 +141,7 @@ const executeQuery = (state = initialState, action) => {
|
|
141
141
|
|
142
142
|
export const sendQuery = ({query, database, action}) => {
|
143
143
|
return createApiRequest({
|
144
|
-
request: window.api.sendQuery(query, database, action, 'profile'),
|
144
|
+
request: window.api.sendQuery({query, database, action, stats: 'profile'}),
|
145
145
|
actions: SEND_QUERY,
|
146
146
|
dataHandler: (result) => {
|
147
147
|
const resultData = result.result ?? result;
|
@@ -47,7 +47,7 @@ const executeTopQueries = (state = initialState, action) => {
|
|
47
47
|
|
48
48
|
export const sendQuery = ({query, database, action}) => {
|
49
49
|
return createApiRequest({
|
50
|
-
request: window.api.sendQuery(query, database, action),
|
50
|
+
request: window.api.sendQuery({query, database, action}),
|
51
51
|
actions: SEND_QUERY,
|
52
52
|
dataHandler: (result) => {
|
53
53
|
if (result && typeof result === 'string') {
|
@@ -52,7 +52,11 @@ const olapStats = (state = initialState, action) => {
|
|
52
52
|
|
53
53
|
export const getOlapStats = ({path = ''}) => {
|
54
54
|
return createApiRequest({
|
55
|
-
request: window.api.sendQuery(
|
55
|
+
request: window.api.sendQuery({
|
56
|
+
query: createOlatStatsQuery(path),
|
57
|
+
database: path,
|
58
|
+
action: queryAction,
|
59
|
+
}),
|
56
60
|
actions: FETCH_OLAP_STATS,
|
57
61
|
dataHandler: (result) => {
|
58
62
|
if (result && typeof result === 'string') {
|
@@ -47,7 +47,7 @@ const preview = (state = initialState, action) => {
|
|
47
47
|
|
48
48
|
export const sendQuery = ({query, database, action}) => {
|
49
49
|
return createApiRequest({
|
50
|
-
request: window.api.sendQuery(query, database, action),
|
50
|
+
request: window.api.sendQuery({query, database, action}),
|
51
51
|
actions: SEND_QUERY,
|
52
52
|
dataHandler: (data) => {
|
53
53
|
if (!Array.isArray(data)) {
|
@@ -9,8 +9,30 @@ const initialState = {
|
|
9
9
|
wasLoaded: false,
|
10
10
|
};
|
11
11
|
|
12
|
-
function
|
13
|
-
return
|
12
|
+
function formatSortOrder({columnId, order}) {
|
13
|
+
return `${columnId} ${order}`;
|
14
|
+
}
|
15
|
+
|
16
|
+
function createShardQuery(path, sortOrder, tenantName) {
|
17
|
+
const orderBy = Array.isArray(sortOrder) ?
|
18
|
+
`ORDER BY ${sortOrder.map(formatSortOrder).join(', ')}` :
|
19
|
+
'';
|
20
|
+
|
21
|
+
const pathSelect = tenantName ?
|
22
|
+
`CAST(SUBSTRING(CAST(Path AS String), ${tenantName.length}) AS Utf8) AS Path` :
|
23
|
+
'Path';
|
24
|
+
|
25
|
+
return `SELECT
|
26
|
+
${pathSelect},
|
27
|
+
TabletId,
|
28
|
+
CPUCores,
|
29
|
+
DataSize
|
30
|
+
FROM \`.sys/partition_stats\`
|
31
|
+
WHERE
|
32
|
+
Path='${path}'
|
33
|
+
OR Path LIKE '${path}/%'
|
34
|
+
${orderBy}
|
35
|
+
LIMIT 20`;
|
14
36
|
}
|
15
37
|
|
16
38
|
const queryAction = 'execute-scan';
|
@@ -51,9 +73,15 @@ const shardsWorkload = (state = initialState, action) => {
|
|
51
73
|
}
|
52
74
|
};
|
53
75
|
|
54
|
-
export const sendShardQuery = ({database, path = ''}) => {
|
76
|
+
export const sendShardQuery = ({database, path = '', sortOrder}) => {
|
55
77
|
return createApiRequest({
|
56
|
-
request: window.api.sendQuery(
|
78
|
+
request: window.api.sendQuery({
|
79
|
+
query: createShardQuery(path, sortOrder, database),
|
80
|
+
database,
|
81
|
+
action: queryAction,
|
82
|
+
}, {
|
83
|
+
concurrentId: 'topShards',
|
84
|
+
}),
|
57
85
|
actions: SEND_SHARD_QUERY,
|
58
86
|
dataHandler: (result) => {
|
59
87
|
if (result && typeof result === 'string') {
|
package/dist/types/api/schema.ts
CHANGED
@@ -54,6 +54,8 @@ interface TPathDescription {
|
|
54
54
|
|
55
55
|
ColumnStoreDescription?: unknown;
|
56
56
|
ColumnTableDescription?: unknown;
|
57
|
+
|
58
|
+
TableIndex?: TIndexDescription;
|
57
59
|
}
|
58
60
|
|
59
61
|
interface TDirEntry {
|
@@ -80,15 +82,42 @@ interface TDirEntry {
|
|
80
82
|
Version?: TPathVersion;
|
81
83
|
}
|
82
84
|
|
85
|
+
export interface TIndexDescription {
|
86
|
+
Name?: string;
|
87
|
+
/** uint64 */
|
88
|
+
LocalPathId?: string;
|
89
|
+
|
90
|
+
Type?: EIndexType;
|
91
|
+
State?: EIndexState;
|
92
|
+
|
93
|
+
KeyColumnNames?: string[];
|
94
|
+
|
95
|
+
/** uint64 */
|
96
|
+
SchemaVersion?: string;
|
97
|
+
|
98
|
+
/** uint64 */
|
99
|
+
PathOwnerId?: string;
|
100
|
+
|
101
|
+
DataColumnNames?: string[];
|
102
|
+
/** uint64 */
|
103
|
+
DataSize?: string;
|
104
|
+
}
|
105
|
+
|
83
106
|
// incomplete
|
84
107
|
export enum EPathType {
|
85
108
|
EPathTypeInvalid = 'EPathTypeInvalid',
|
86
109
|
EPathTypeDir = 'EPathTypeDir',
|
87
110
|
EPathTypeTable = 'EPathTypeTable',
|
111
|
+
|
88
112
|
EPathTypeSubDomain = 'EPathTypeSubDomain',
|
113
|
+
|
114
|
+
EPathTypeTableIndex = 'EPathTypeTableIndex',
|
115
|
+
EPathTypeExtSubDomain = 'EPathTypeExtSubDomain',
|
116
|
+
|
89
117
|
EPathTypeColumnStore = 'EPathTypeColumnStore',
|
90
118
|
EPathTypeColumnTable = 'EPathTypeColumnTable',
|
91
|
-
|
119
|
+
EPathTypeCdcStream = 'EPathTypeCdcStream',
|
120
|
+
|
92
121
|
}
|
93
122
|
|
94
123
|
export enum EPathSubType {
|
@@ -112,6 +141,19 @@ enum EPathState {
|
|
112
141
|
EPathStateMoving = 'EPathStateMoving',
|
113
142
|
}
|
114
143
|
|
144
|
+
enum EIndexType {
|
145
|
+
EIndexTypeInvalid = 'EIndexTypeInvalid',
|
146
|
+
EIndexTypeGlobal = 'EIndexTypeGlobal',
|
147
|
+
EIndexTypeGlobalAsync = 'EIndexTypeGlobalAsync',
|
148
|
+
}
|
149
|
+
|
150
|
+
enum EIndexState {
|
151
|
+
EIndexStateInvalid = 'EIndexStateInvalid',
|
152
|
+
EIndexStateReady = 'EIndexStateReady',
|
153
|
+
EIndexStateNotReady = 'EIndexStateNotReady',
|
154
|
+
EIndexStateWriteOnly = 'EIndexStateWriteOnly',
|
155
|
+
}
|
156
|
+
|
115
157
|
// incomplete
|
116
158
|
interface TPathVersion {
|
117
159
|
/** uint64 */
|