ydb-embedded-ui 3.5.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.tsx +3 -3
  3. package/dist/containers/Tenant/QueryEditor/QueryDuration/QueryDuration.scss +8 -0
  4. package/dist/containers/Tenant/QueryEditor/QueryDuration/QueryDuration.tsx +21 -0
  5. package/dist/containers/Tenant/QueryEditor/QueryEditor.js +58 -83
  6. package/dist/containers/Tenant/QueryEditor/QueryEditor.scss +0 -33
  7. package/dist/containers/Tenant/QueryEditor/QueryEditorControls/OldQueryEditorControls.tsx +83 -0
  8. package/dist/containers/Tenant/QueryEditor/QueryEditorControls/QueryEditorControls.scss +57 -0
  9. package/dist/containers/Tenant/QueryEditor/QueryEditorControls/QueryEditorControls.tsx +84 -0
  10. package/dist/containers/Tenant/QueryEditor/QueryEditorControls/shared.ts +23 -0
  11. package/dist/containers/Tenant/QueryEditor/QueryExplain/QueryExplain.js +12 -23
  12. package/dist/containers/Tenant/QueryEditor/QueryResult/QueryResult.js +4 -6
  13. package/dist/containers/Tenant/QueryEditor/i18n/en.json +3 -0
  14. package/dist/containers/Tenant/QueryEditor/i18n/index.ts +11 -0
  15. package/dist/containers/Tenant/QueryEditor/i18n/ru.json +3 -0
  16. package/dist/containers/UserSettings/UserSettings.tsx +30 -1
  17. package/dist/services/api.d.ts +4 -3
  18. package/dist/services/api.js +2 -2
  19. package/dist/store/reducers/executeQuery.ts +12 -37
  20. package/dist/store/reducers/{explainQuery.js → explainQuery.ts} +44 -59
  21. package/dist/store/reducers/settings.js +18 -3
  22. package/dist/types/api/error.ts +14 -0
  23. package/dist/types/api/query.ts +226 -117
  24. package/dist/types/store/executeQuery.ts +4 -8
  25. package/dist/types/store/explainQuery.ts +38 -0
  26. package/dist/types/store/query.ts +23 -3
  27. package/dist/utils/constants.ts +2 -1
  28. package/dist/utils/error.ts +25 -0
  29. package/dist/utils/index.js +0 -49
  30. package/dist/utils/prepareQueryExplain.ts +7 -24
  31. package/dist/utils/query.test.ts +153 -231
  32. package/dist/utils/query.ts +44 -78
  33. package/dist/utils/timeParsers/i18n/en.json +9 -9
  34. package/dist/utils/timeParsers/i18n/ru.json +9 -9
  35. package/dist/utils/timeParsers/parsers.ts +9 -0
  36. package/dist/utils/utils.js +1 -2
  37. package/package.json +1 -1
@@ -1,34 +1,165 @@
1
- // common
1
+ // ==== types from backend protos ====
2
+ interface Position {
3
+ row?: number;
4
+ column?: number;
5
+ file?: string;
6
+ }
2
7
 
3
- type Plan = Record<string, any>;
4
- type AST = string;
5
- type Stats = Record<string, any>;
8
+ /** source: https://github.com/ydb-platform/ydb/blob/main/ydb/public/api/protos/ydb_issue_message.proto */
9
+ export interface IssueMessage {
10
+ position?: Position;
11
+ end_position?: Position;
12
+ message?: string;
13
+ issue_code?: number;
14
+ severity?: number;
15
+ issues?: IssueMessage[];
16
+ }
6
17
 
7
- export interface CommonFields {
8
- ast?: AST;
9
- plan?: Plan;
10
- stats?: Stats;
18
+ /** incomplete */
19
+ interface TDqStageStats {}
20
+
21
+ /** incomplete */
22
+ interface TKqpStatsCompile {}
23
+
24
+ interface TDqTableStats {
25
+ TablePath?: string;
26
+ /** uint64 */
27
+ ReadRows?: string;
28
+ /** uint64 */
29
+ ReadBytes?: string;
30
+ /** uint64 */
31
+ WriteRows?: string;
32
+ /** uint64 */
33
+ WriteBytes?: string;
34
+ /** uint64 */
35
+ EraseRows?: string;
36
+ /** uint64 */
37
+ EraseBytes?: string;
38
+ AffectedPartitions?: number;
39
+ Extra?: unknown;
11
40
  }
12
41
 
13
- interface DeprecatedCommonFields {
14
- stats?: Stats;
42
+ /** source: https://github.com/ydb-platform/ydb/blob/main/ydb/library/yql/dq/actors/protos/dq_stats.proto */
43
+ interface TDqExecutionStats {
44
+ /** uint64 */
45
+ CpuTimeUs?: string;
46
+ /** uint64 */
47
+ DurationUs?: string;
48
+ /** uint64 */
49
+ ResultRows?: string;
50
+ /** uint64 */
51
+ ResultBytes?: string;
52
+
53
+ Tables?: TDqTableStats[];
54
+
55
+ /** uint64 */
56
+ ExecuterCpuTimeUs?: string;
57
+ /** uint64 */
58
+ StartTimeMs?: string;
59
+ /** uint64 */
60
+ FinishTimeMs?: string;
61
+ /** uint64 */
62
+ FirstRowTimeMs?: string;
63
+
64
+ Stages?: TDqStageStats[];
65
+ TxPlansWithStats?: string[];
66
+
67
+ Extra: unknown;
15
68
  }
16
69
 
17
- export interface ErrorResponse {
18
- error?: any;
19
- issues?: any;
70
+ /** source: https://github.com/ydb-platform/ydb/blob/main/ydb/core/protos/kqp_stats.proto */
71
+ export interface TKqpStatsQuery {
72
+ /** uint64 */
73
+ DurationUs?: string;
74
+ Compilation?: TKqpStatsCompile;
75
+
76
+ /** uint64 */
77
+ WorkerCpuTimeUs?: string;
78
+ /** uint64 */
79
+ ReadSetsCount?: string;
80
+ /** uint64 */
81
+ MaxShardProgramSize?: string;
82
+ /** uint64 */
83
+ MaxShardReplySize?: string;
84
+
85
+ Executions?: TDqExecutionStats[];
20
86
  }
21
87
 
22
- export type ExecuteActions = 'execute-script' | 'execute' | 'execute-scan' | undefined;
23
- export type ExplainActions = 'explain' | 'explain-ast';
24
- export type Actions = ExecuteActions | ExplainActions;
88
+ // ==== Self-written types ====
89
+ // ==== Meta version 0.2 ====
90
+ // Backend code: https://github.com/ydb-platform/ydb/blob/main/ydb/core/kqp/opt/kqp_query_plan.cpp
25
91
 
26
- // undefined == 'classic'
27
- export type Schemas = 'classic' | 'modern' | 'ydb' | undefined;
92
+ // ==== Plan ====
93
+ export interface PlanMeta {
94
+ version: string;
95
+ type: 'script' | 'query';
96
+ }
28
97
 
29
- // ==== EXECUTE ====
98
+ export interface PlanTable {
99
+ name: string;
100
+ reads?: {
101
+ type: string;
102
+ lookup_by?: string[];
103
+ scan_by?: string[];
104
+ limit?: string;
105
+ reverse?: boolean;
106
+ columns?: string[];
107
+ }[];
108
+ writes?: {
109
+ type: string;
110
+ key?: string[];
111
+ columns?: string[];
112
+ }[];
113
+ }
30
114
 
31
- // common types
115
+ interface PlanNodeStats {
116
+ TotalCpuTimeUs?: number;
117
+ TotalTasks?: number;
118
+ TotalInputBytes?: number;
119
+ TotalInputRows?: number;
120
+ TotalOutputBytes?: number;
121
+ TotalDurationMs?: number;
122
+ TotalOutputRows?: number;
123
+ }
124
+
125
+ interface PlanNodeOperator {
126
+ Name: string;
127
+ Limit?: string;
128
+ ReadLimit?: string;
129
+ ReadColumns?: string[];
130
+ ReadRanges?: string[];
131
+ Table?: string;
132
+ Iterator?: string;
133
+ }
134
+
135
+ export interface PlanNode {
136
+ PlanNodeId?: number;
137
+ 'Node Type'?: string;
138
+ Plans?: PlanNode[];
139
+ Operators?: PlanNodeOperator[];
140
+ Tables?: string[];
141
+ PlanNodeType?: string;
142
+ Stats?: PlanNodeStats;
143
+ 'CTE Name'?: string;
144
+ 'Subplan Name'?: string;
145
+ 'Parent Relationship'?: string;
146
+ }
147
+
148
+ export interface ScriptPlan {
149
+ queries?: {
150
+ Plan?: PlanNode;
151
+ tables?: PlanTable[];
152
+ }[];
153
+ meta: PlanMeta;
154
+ }
155
+
156
+ export interface ScanPlan {
157
+ Plan?: PlanNode;
158
+ tables?: PlanTable[];
159
+ meta: PlanMeta;
160
+ }
161
+
162
+ // ==== Common types ====
32
163
 
33
164
  export type CellValue = string | number | null | undefined;
34
165
 
@@ -43,113 +174,91 @@ export interface ColumnType {
43
174
  type: string;
44
175
  }
45
176
 
46
- // modern response
47
-
48
- export type ExecuteModernResponse = {
49
- result: ArrayRow[];
50
- columns: ColumnType[];
51
- } & CommonFields;
52
-
53
- export type ExecuteClassicResponseDeep = {
54
- result: KeyValueRow[];
55
- } & CommonFields;
56
-
57
- // can be undefined for queries like `insert into`
58
- export type ExecuteClassicResponsePlain = KeyValueRow[] | undefined;
59
-
60
- export type ExecuteClassicResponse = ExecuteClassicResponseDeep | ExecuteClassicResponsePlain;
61
-
62
- export type ExecuteYdbResponse = {
63
- result: KeyValueRow[];
64
- } & CommonFields;
65
-
66
- // prettier-ignore
67
- type ExecuteResponse<Schema extends Schemas> =
68
- | CommonFields // result can be undefined for queries like `insert into`
69
- | (Schema extends 'modern'
70
- ? ExecuteModernResponse
71
- : Schema extends 'ydb'
72
- ? ExecuteYdbResponse
73
- : Schema extends 'classic' | undefined
74
- ? ExecuteClassicResponse
75
- : unknown);
76
-
77
- // deprecated response from older versions, backward compatibility
78
-
79
- type DeprecatedExecuteResponseValue =
80
- | KeyValueRow[]
81
- | string
82
- // can be here because of a bug in the previous backend version
83
- // should be ignored in parsing
84
- | Plan;
85
-
86
- export type DeprecatedExecuteResponseDeep = {
87
- // can be undefined for queries like `insert into`
88
- result?: DeprecatedExecuteResponseValue;
89
- } & DeprecatedCommonFields;
90
-
91
- // can be undefined for queries like `insert into`
92
- export type DeprecatedExecuteResponsePlain = DeprecatedExecuteResponseValue | undefined;
93
-
94
- export type DeprecatedExecuteResponse =
95
- | DeprecatedExecuteResponseDeep
96
- | DeprecatedExecuteResponsePlain;
177
+ /** undefined = 'classic' */
178
+ export type Schemas = 'classic' | 'modern' | 'ydb' | undefined;
97
179
 
98
- // ==== EXPLAIN ====
180
+ /**
181
+ * undefined = 'execute'
182
+ *
183
+ * execute and execute-script have similar responses
184
+ */
185
+ export type ExecuteActions = 'execute' | 'execute-scan' | 'execute-script' | undefined;
99
186
 
100
- // modern response
187
+ /** explain, explain-scan and explain-ast have similar responses */
188
+ export type ExplainActions = 'explain' | 'explain-scan' | 'explain-script' | 'explain-ast';
101
189
 
102
- type ExplainResponse = CommonFields;
190
+ export type Actions = ExecuteActions | ExplainActions;
103
191
 
104
- // deprecated response from older versions, backward compatibility
192
+ // ==== Error response ====
105
193
 
106
- // prettier-ignore
107
- type DeprecatedExplainResponse<Action extends ExplainActions> =
108
- Action extends 'explain-ast'
109
- ? ({result: {ast: AST}} & Required<DeprecatedCommonFields>) | {ast: AST}
110
- : Action extends 'explain'
111
- ? ({result: Plan} & Required<DeprecatedCommonFields>) | Plan
112
- : unknown;
194
+ export interface ErrorResponse {
195
+ error?: IssueMessage;
196
+ issues?: IssueMessage[];
197
+ }
113
198
 
114
- // ==== COMBINED API RESPONSE ====
199
+ // ==== Explain Responses ====
115
200
 
116
- export type QueryAPIExecuteResponse<Schema extends Schemas = undefined> =
117
- | ExecuteResponse<Schema>
118
- | DeprecatedExecuteResponse
119
- | null;
201
+ export interface ExplainScriptResponse {
202
+ plan?: ScriptPlan;
203
+ }
120
204
 
121
- export type QueryAPIExplainResponse<Action extends ExplainActions> =
122
- | ExplainResponse
123
- | DeprecatedExplainResponse<Action>
124
- | null;
205
+ export interface ExplainScanResponse {
206
+ ast?: string;
207
+ plan?: ScanPlan;
208
+ }
125
209
 
126
- // prettier-ignore
127
- export type QueryAPIResponse<Action extends Actions, Schema extends Schemas = undefined> =
128
- Action extends ExecuteActions
129
- ? QueryAPIExecuteResponse<Schema>
130
- : Action extends ExplainActions
131
- ? QueryAPIExplainResponse<Action>
132
- : unknown;
210
+ export type ExplainResponse<Action extends ExplainActions> = Action extends 'explain-script'
211
+ ? ExplainScriptResponse
212
+ : ExplainScanResponse;
213
+
214
+ // ==== Execute Responses ====
215
+
216
+ type ResultFields<Schema extends Schemas> = Schema extends 'modern'
217
+ ? {
218
+ result?: ArrayRow[];
219
+ columns?: ColumnType[];
220
+ }
221
+ : {
222
+ result?: KeyValueRow[];
223
+ };
224
+
225
+ export type ExecuteScanResponse<Schema extends Schemas> = {
226
+ plan?: ScanPlan;
227
+ ast?: string;
228
+ stats?: TKqpStatsQuery;
229
+ } & ResultFields<Schema>;
230
+
231
+ export type ExecuteScriptResponse<Schema extends Schemas> = {
232
+ plan?: ScriptPlan;
233
+ ast?: string;
234
+ stats?: TKqpStatsQuery;
235
+ } & ResultFields<Schema>;
236
+
237
+ export type ExecuteResponse<
238
+ Action extends ExecuteActions,
239
+ Schema extends Schemas,
240
+ > = Action extends 'execute-scan' ? ExecuteScanResponse<Schema> : ExecuteScriptResponse<Schema>;
241
+
242
+ // ==== Combined API response ====
243
+ export type QueryAPIResponse<
244
+ Action extends Actions,
245
+ Schema extends Schemas,
246
+ > = Action extends ExplainActions
247
+ ? ExplainResponse<Action>
248
+ : Action extends ExecuteActions
249
+ ? ExecuteResponse<Action, Schema>
250
+ : unknown;
251
+
252
+ // ==== types to use in query result preparation ====
253
+ export type AnyExplainResponse = ExplainScanResponse | ExplainScriptResponse;
254
+
255
+ export type ExecuteModernResponse = ExecuteScanResponse<'modern'> | ExecuteScriptResponse<'modern'>;
256
+ export type ExecuteClassicResponse =
257
+ | ExecuteScanResponse<'classic'>
258
+ | ExecuteScriptResponse<'classic'>;
259
+ export type ExecuteYdbResponse = ExecuteScanResponse<'ydb'> | ExecuteScriptResponse<'ydb'>;
133
260
 
134
261
  export type AnyExecuteResponse =
135
262
  | ExecuteModernResponse
136
263
  | ExecuteClassicResponse
137
- | ExecuteYdbResponse
138
- | CommonFields
139
- | DeprecatedExecuteResponse
140
- | null;
141
-
142
- export type DeepExecuteResponse =
143
- | ExecuteModernResponse
144
- | ExecuteClassicResponseDeep
145
- | ExecuteYdbResponse
146
- | DeprecatedExecuteResponseDeep;
147
-
148
- export type AnyExplainResponse =
149
- | ExplainResponse
150
- | CommonFields
151
- | DeprecatedExplainResponse<'explain'>
152
- | DeprecatedExplainResponse<'explain-ast'>
153
- | null;
154
-
155
- export type AnyResponse = AnyExecuteResponse | AnyExplainResponse;
264
+ | ExecuteYdbResponse;
@@ -2,19 +2,17 @@ import {
2
2
  SEND_QUERY,
3
3
  changeUserInput,
4
4
  saveQueryToHistory,
5
- selectRunAction,
6
5
  goToPreviousQuery,
7
6
  setMonacoHotKey,
8
7
  goToNextQuery,
9
8
  MONACO_HOT_KEY_ACTIONS,
10
- RUN_ACTIONS_VALUES,
11
9
  } from '../../store/reducers/executeQuery';
12
10
  import type {ApiRequestAction} from '../../store/utils';
11
+ import type {ErrorResponse} from '../api/query';
13
12
  import type {ValueOf} from '../common';
14
- import type {IQueryResult} from './query';
13
+ import type {IQueryResult, QueryError} from './query';
15
14
 
16
15
  export type MonacoHotKeyAction = ValueOf<typeof MONACO_HOT_KEY_ACTIONS>;
17
- export type RunAction = ValueOf<typeof RUN_ACTIONS_VALUES>;
18
16
 
19
17
  export interface ExecuteQueryState {
20
18
  loading: boolean;
@@ -23,14 +21,13 @@ export interface ExecuteQueryState {
23
21
  queries: string[];
24
22
  currentIndex: number;
25
23
  };
26
- runAction: RunAction;
27
24
  monacoHotKey: null | MonacoHotKeyAction;
28
25
  data?: IQueryResult;
29
26
  stats?: IQueryResult['stats'];
30
- error?: unknown;
27
+ error?: string | ErrorResponse;
31
28
  }
32
29
 
33
- type SendQueryAction = ApiRequestAction<typeof SEND_QUERY, IQueryResult, unknown>;
30
+ type SendQueryAction = ApiRequestAction<typeof SEND_QUERY, IQueryResult, QueryError>;
34
31
 
35
32
  export type ExecuteQueryAction =
36
33
  | SendQueryAction
@@ -38,5 +35,4 @@ export type ExecuteQueryAction =
38
35
  | ReturnType<typeof goToPreviousQuery>
39
36
  | ReturnType<typeof changeUserInput>
40
37
  | ReturnType<typeof saveQueryToHistory>
41
- | ReturnType<typeof selectRunAction>
42
38
  | ReturnType<typeof setMonacoHotKey>;
@@ -0,0 +1,38 @@
1
+ import type {ExplainPlanNodeData, GraphNode, Link} from '@gravity-ui/paranoid';
2
+
3
+ import {GET_EXPLAIN_QUERY, GET_EXPLAIN_QUERY_AST} from '../../store/reducers/explainQuery';
4
+ import type {ApiRequestAction} from '../../store/utils';
5
+ import type {PlanTable, ErrorResponse, ScanPlan, ScriptPlan} from '../api/query';
6
+ import type {IQueryResult, QueryError} from './query';
7
+
8
+ export interface PreparedExplainResponse {
9
+ plan?: {
10
+ links?: Link[];
11
+ nodes?: GraphNode<ExplainPlanNodeData>[];
12
+ tables?: PlanTable[];
13
+ version?: string;
14
+ pristine?: ScanPlan | ScriptPlan;
15
+ };
16
+ ast?: string;
17
+ }
18
+
19
+ export interface ExplainQueryState {
20
+ loading: boolean;
21
+ data?: PreparedExplainResponse['plan'];
22
+ dataAst?: PreparedExplainResponse['ast'];
23
+ error?: string | ErrorResponse;
24
+ errorAst?: string | ErrorResponse;
25
+ }
26
+
27
+ type GetExplainQueryAstAction = ApiRequestAction<
28
+ typeof GET_EXPLAIN_QUERY_AST,
29
+ IQueryResult,
30
+ QueryError
31
+ >;
32
+ type GetExplainQueryAction = ApiRequestAction<
33
+ typeof GET_EXPLAIN_QUERY,
34
+ PreparedExplainResponse,
35
+ QueryError
36
+ >;
37
+
38
+ export type ExplainQueryAction = GetExplainQueryAstAction | GetExplainQueryAction;
@@ -1,9 +1,29 @@
1
- import type {KeyValueRow, ColumnType} from '../api/query';
1
+ import type {NetworkError} from '../api/error';
2
+ import type {
3
+ KeyValueRow,
4
+ ColumnType,
5
+ ErrorResponse,
6
+ ScriptPlan,
7
+ ScanPlan,
8
+ TKqpStatsQuery,
9
+ } from '../api/query';
2
10
 
3
11
  export interface IQueryResult {
4
12
  result?: KeyValueRow[];
5
13
  columns?: ColumnType[];
6
- stats?: any;
7
- plan?: any;
14
+ stats?: TKqpStatsQuery;
15
+ plan?: ScriptPlan | ScanPlan;
8
16
  ast?: string;
9
17
  }
18
+
19
+ export interface QueryRequestParams {
20
+ database: string;
21
+ query: string;
22
+ }
23
+
24
+ export type QueryError = NetworkError | ErrorResponse;
25
+
26
+ export enum QueryModes {
27
+ scan = 'scan',
28
+ script = 'script',
29
+ }
@@ -94,6 +94,7 @@ export type IProblemFilterValues = typeof ALL | typeof PROBLEMS;
94
94
  export const THEME_KEY = 'theme';
95
95
  export const INVERTED_DISKS_KEY = 'invertedDisks';
96
96
  export const USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY = 'useNodesEndpointInDiagnostics';
97
+ export const ENABLE_QUERY_MODES_FOR_EXPLAIN = 'enableQueryModesForExplain';
97
98
  export const SAVED_QUERIES_KEY = 'saved_queries';
98
99
  export const ASIDE_HEADER_COMPACT_KEY = 'asideHeaderCompact';
99
100
  export const QUERIES_HISTORY_KEY = 'queries_history';
@@ -118,6 +119,6 @@ export const DEFAULT_TABLE_SETTINGS = {
118
119
  } as const;
119
120
 
120
121
  export const TENANT_INITIAL_TAB_KEY = 'saved_tenant_initial_tab';
121
- export const QUERY_INITIAL_RUN_ACTION_KEY = 'query_initial_run_action';
122
+ export const QUERY_INITIAL_MODE_KEY = 'query_initial_mode';
122
123
 
123
124
  export const PARTITIONS_SELECTED_COLUMNS_KEY = 'partitionsSelectedColumns';
@@ -0,0 +1,25 @@
1
+ import type {AxiosError} from 'axios';
2
+
3
+ import type {IResponseError, NetworkError} from '../types/api/error';
4
+ import type {ErrorResponse as QueryErrorResponse} from '../types/api/query';
5
+ import type {QueryError} from '../types/store/query';
6
+
7
+ type RequestError = NetworkError | IResponseError | AxiosError | QueryErrorResponse | unknown;
8
+
9
+ const isNetworkError = (error: RequestError): error is NetworkError => {
10
+ return Boolean(
11
+ error &&
12
+ typeof error === 'object' &&
13
+ 'message' in error &&
14
+ (error as {message: unknown}).message === 'Network Error',
15
+ );
16
+ };
17
+
18
+ export const parseQueryError = (error: QueryError): QueryErrorResponse | string | undefined => {
19
+ if (isNetworkError(error)) {
20
+ return error.message;
21
+ }
22
+
23
+ // 401 Unauthorized error is handled by GenericAPI
24
+ return error ?? 'Unauthorized';
25
+ };
@@ -113,52 +113,3 @@ export const renderExplainNode = (node) => {
113
113
  const parts = node.name.split('|');
114
114
  return parts.length > 1 ? parts[1] : node.name;
115
115
  };
116
-
117
- export const getExplainNodeId = (...values) => {
118
- return values.join('|');
119
- };
120
-
121
- const getStringFromProps = (props) => {
122
- return props
123
- .map(([name, value]) => {
124
- return value && `${name}: ${Array.isArray(value) ? value.join(', ') : value}`;
125
- })
126
- .filter(Boolean)
127
- .join('\n');
128
- };
129
-
130
- export const getMetaForExplainNode = (node) => {
131
- switch (node.type) {
132
- case 'MultiLookup':
133
- case 'Lookup': {
134
- return getStringFromProps([
135
- ['lookup by', node.lookup_by],
136
- ['columns', node.columns],
137
- ]);
138
- }
139
- case 'FullScan':
140
- case 'Scan': {
141
- return getStringFromProps([
142
- ['scan by', node.scan_by],
143
- ['limit', node.limit],
144
- ['columns', node.columns],
145
- ]);
146
- }
147
- case 'Upsert':
148
- case 'MultiUpsert': {
149
- return getStringFromProps([
150
- ['key', node.key],
151
- ['columns', node.columns],
152
- ]);
153
- }
154
- case 'Erase':
155
- case 'MultiErase': {
156
- return getStringFromProps([
157
- ['key', node.key],
158
- ['columns', node.columns],
159
- ]);
160
- }
161
- default:
162
- return '';
163
- }
164
- };
@@ -1,4 +1,4 @@
1
- import {
1
+ import type {
2
2
  Link,
3
3
  GraphNode,
4
4
  TopologyNodeDataStats,
@@ -7,28 +7,11 @@ import {
7
7
  TopologyNodeDataStatsItem,
8
8
  } from '@gravity-ui/paranoid';
9
9
 
10
- interface PlanOperator {
11
- Name: string;
12
- [key: string]: any;
13
- }
14
-
15
- export interface Plan {
16
- PlanNodeId: number;
17
- 'Node Type': string;
18
- Plans?: Plan[];
19
- Operators?: PlanOperator[];
20
- Tables?: string[];
21
- PlanNodeType?: string;
22
- [key: string]: any;
23
- }
24
-
25
- export interface RootPlan {
26
- Plan: Plan;
27
- }
10
+ import type {PlanNode} from '../types/api/query';
28
11
 
29
12
  const CONNECTION_NODE_META_FIELDS = new Set(['PlanNodeId', 'PlanNodeType', 'Node Type', 'Plans']);
30
13
 
31
- function prepareStats(plan: Plan) {
14
+ function prepareStats(plan: PlanNode) {
32
15
  const stats: TopologyNodeDataStats[] = [];
33
16
 
34
17
  if (plan.Operators) {
@@ -77,7 +60,7 @@ function prepareStats(plan: Plan) {
77
60
  return stats;
78
61
  }
79
62
 
80
- function getNodeType(plan: Plan) {
63
+ function getNodeType(plan: PlanNode) {
81
64
  switch (plan.PlanNodeType) {
82
65
  case 'Connection':
83
66
  return 'connection';
@@ -90,11 +73,11 @@ function getNodeType(plan: Plan) {
90
73
  }
91
74
  }
92
75
 
93
- export function preparePlan(plan: Plan) {
94
- const nodes: GraphNode[] = [];
76
+ export function preparePlan(plan: PlanNode) {
77
+ const nodes: GraphNode<ExplainPlanNodeData>[] = [];
95
78
  const links: Link[] = [];
96
79
 
97
- function parsePlans(plans: Plan[] = [], from: string) {
80
+ function parsePlans(plans: PlanNode[] = [], from: string) {
98
81
  plans.forEach((p) => {
99
82
  const node: GraphNode<ExplainPlanNodeData> = {
100
83
  name: String(p.PlanNodeId),