ydb-embedded-ui 3.4.5 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/dist/components/InfoViewer/formatters/table.ts +6 -0
- package/dist/components/TruncatedQuery/TruncatedQuery.js +1 -1
- package/dist/components/TruncatedQuery/TruncatedQuery.scss +7 -3
- package/dist/containers/Node/{NodePages.js → NodePages.ts} +1 -1
- package/dist/containers/Tablet/TabletControls/TabletControls.tsx +2 -2
- package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +11 -43
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx +19 -17
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.ts +192 -37
- package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.scss +20 -14
- package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +49 -12
- package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.tsx +37 -18
- package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.tsx +3 -3
- package/dist/containers/Tenant/QueryEditor/QueryDuration/QueryDuration.scss +8 -0
- package/dist/containers/Tenant/QueryEditor/QueryDuration/QueryDuration.tsx +21 -0
- package/dist/containers/Tenant/QueryEditor/QueryEditor.js +58 -82
- package/dist/containers/Tenant/QueryEditor/QueryEditor.scss +0 -33
- package/dist/containers/Tenant/QueryEditor/QueryEditorControls/OldQueryEditorControls.tsx +83 -0
- package/dist/containers/Tenant/QueryEditor/QueryEditorControls/QueryEditorControls.scss +57 -0
- package/dist/containers/Tenant/QueryEditor/QueryEditorControls/QueryEditorControls.tsx +84 -0
- package/dist/containers/Tenant/QueryEditor/QueryEditorControls/shared.ts +23 -0
- package/dist/containers/Tenant/QueryEditor/QueryExplain/QueryExplain.js +12 -23
- package/dist/containers/Tenant/QueryEditor/QueryResult/QueryResult.js +4 -6
- package/dist/containers/Tenant/QueryEditor/i18n/en.json +3 -0
- package/dist/containers/Tenant/QueryEditor/i18n/index.ts +11 -0
- package/dist/containers/Tenant/QueryEditor/i18n/ru.json +3 -0
- package/dist/containers/UserSettings/UserSettings.tsx +30 -1
- package/dist/routes.ts +1 -1
- package/dist/services/api.d.ts +4 -3
- package/dist/services/api.js +5 -5
- package/dist/store/reducers/{executeQuery.js → executeQuery.ts} +48 -43
- package/dist/store/reducers/executeTopQueries.ts +5 -1
- package/dist/store/reducers/{explainQuery.js → explainQuery.ts} +44 -59
- package/dist/store/reducers/{olapStats.js → olapStats.ts} +8 -18
- package/dist/store/reducers/settings.js +19 -4
- package/dist/store/reducers/storage.js +5 -7
- package/dist/types/api/error.ts +14 -0
- package/dist/types/api/query.ts +227 -115
- package/dist/types/api/schema.ts +523 -3
- package/dist/types/common.ts +1 -0
- package/dist/types/store/executeQuery.ts +38 -0
- package/dist/types/store/explainQuery.ts +38 -0
- package/dist/types/store/olapStats.ts +14 -0
- package/dist/types/store/query.ts +23 -3
- package/dist/utils/constants.ts +2 -1
- package/dist/utils/error.ts +25 -0
- package/dist/utils/index.js +0 -49
- package/dist/utils/prepareQueryExplain.ts +7 -24
- package/dist/utils/query.test.ts +148 -213
- package/dist/utils/query.ts +68 -90
- package/dist/utils/timeParsers/formatDuration.ts +30 -12
- package/dist/utils/timeParsers/i18n/en.json +9 -5
- package/dist/utils/timeParsers/i18n/ru.json +9 -5
- package/dist/utils/timeParsers/parsers.ts +9 -0
- package/dist/utils/utils.js +1 -2
- package/package.json +1 -1
@@ -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
|
+
};
|
package/dist/utils/index.js
CHANGED
@@ -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
|
-
|
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:
|
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:
|
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:
|
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:
|
80
|
+
function parsePlans(plans: PlanNode[] = [], from: string) {
|
98
81
|
plans.forEach((p) => {
|
99
82
|
const node: GraphNode<ExplainPlanNodeData> = {
|
100
83
|
name: String(p.PlanNodeId),
|
package/dist/utils/query.test.ts
CHANGED
@@ -1,247 +1,182 @@
|
|
1
|
+
import type {PlanMeta, PlanNode, PlanTable, TKqpStatsQuery} from '../types/api/query';
|
1
2
|
import {
|
2
3
|
parseQueryAPIExecuteResponse,
|
3
4
|
parseQueryAPIExplainResponse,
|
5
|
+
parseQueryExplainPlan,
|
4
6
|
} from './query';
|
5
7
|
|
6
8
|
describe('API utils', () => {
|
7
9
|
describe('json/viewer/query', () => {
|
8
10
|
describe('parseQueryAPIExecuteResponse', () => {
|
9
|
-
describe('
|
10
|
-
|
11
|
-
|
12
|
-
expect(parseQueryAPIExecuteResponse(null).result).toBeUndefined();
|
13
|
-
});
|
14
|
-
|
15
|
-
it('should parse json string', () => {
|
16
|
-
const json = {foo: 'bar'};
|
17
|
-
const response = JSON.stringify(json);
|
18
|
-
expect(parseQueryAPIExecuteResponse(response).result).toEqual(json);
|
19
|
-
});
|
20
|
-
|
21
|
-
// it should not be in the response, but is there because of a bug
|
22
|
-
it('should ignore request plan as the response', () => {
|
23
|
-
const response = {queries: 'some queries'};
|
24
|
-
expect(parseQueryAPIExecuteResponse(response).result).toBeUndefined();
|
25
|
-
});
|
26
|
-
|
27
|
-
it('should accept key-value rows', () => {
|
28
|
-
const response = [{foo: 'bar'}];
|
29
|
-
expect(parseQueryAPIExecuteResponse(response).result).toEqual(response);
|
30
|
-
});
|
11
|
+
describe('should handle responses with incorrect format', () => {
|
12
|
+
it('should handle null response', () => {
|
13
|
+
expect(parseQueryAPIExecuteResponse(null)).toEqual({});
|
31
14
|
});
|
32
|
-
|
33
|
-
|
34
|
-
it('should parse json string in the result field', () => {
|
35
|
-
const json = {foo: 'bar'};
|
36
|
-
const response = {result: JSON.stringify(json)};
|
37
|
-
expect(parseQueryAPIExecuteResponse(response).result).toEqual(json);
|
38
|
-
});
|
39
|
-
|
40
|
-
// it should not be in the response, but is there because of a bug
|
41
|
-
it('should ignore request plan in the result field', () => {
|
42
|
-
const response = {result: {queries: 'some queries'}};
|
43
|
-
expect(parseQueryAPIExecuteResponse(response).result).toBeUndefined();
|
44
|
-
});
|
45
|
-
|
46
|
-
it('should accept key-value rows in the result field', () => {
|
47
|
-
const response = {result: [{foo: 'bar'}]};
|
48
|
-
expect(parseQueryAPIExecuteResponse(response).result).toEqual(response.result);
|
49
|
-
});
|
15
|
+
it('should handle undefined response', () => {
|
16
|
+
expect(parseQueryAPIExecuteResponse(undefined)).toEqual({});
|
50
17
|
});
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
it('should ignore request plan in the result field', () => {
|
66
|
-
const response = {
|
67
|
-
result: {queries: 'some queries'},
|
68
|
-
stats: {metric: 'good'},
|
69
|
-
};
|
70
|
-
const actual = parseQueryAPIExecuteResponse(response);
|
71
|
-
expect(actual.result).toBeUndefined();
|
72
|
-
expect(actual.stats).toEqual(response.stats);
|
73
|
-
});
|
74
|
-
|
75
|
-
it('should accept key-value rows in the result field', () => {
|
76
|
-
const response = {
|
77
|
-
result: [{foo: 'bar'}],
|
78
|
-
stats: {metric: 'good'},
|
79
|
-
};
|
80
|
-
const actual = parseQueryAPIExecuteResponse(response);
|
81
|
-
expect(actual.result).toEqual(response.result);
|
82
|
-
expect(actual.stats).toEqual(response.stats);
|
83
|
-
});
|
84
|
-
|
85
|
-
it('should accept stats without a result', () => {
|
86
|
-
const response = {
|
87
|
-
stats: {metric: 'good'},
|
88
|
-
};
|
89
|
-
const actual = parseQueryAPIExecuteResponse(response);
|
90
|
-
expect(actual.result).toBeUndefined();
|
91
|
-
expect(actual.stats).toEqual(response.stats);
|
92
|
-
});
|
18
|
+
it('should handle string response', () => {
|
19
|
+
expect(parseQueryAPIExecuteResponse('foo')).toEqual({});
|
20
|
+
});
|
21
|
+
it('should handle array response', () => {
|
22
|
+
expect(parseQueryAPIExecuteResponse([{foo: 'bar'}])).toEqual({});
|
23
|
+
});
|
24
|
+
it('should handle json string in the result field', () => {
|
25
|
+
const json = {foo: 'bar'};
|
26
|
+
const response = {result: JSON.stringify(json)};
|
27
|
+
expect(parseQueryAPIExecuteResponse(response)).toEqual({});
|
28
|
+
});
|
29
|
+
it('should handle object with request plan in the result field', () => {
|
30
|
+
const response = {result: {queries: 'some queries'}};
|
31
|
+
expect(parseQueryAPIExecuteResponse(response)).toEqual({});
|
93
32
|
});
|
94
33
|
});
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
columns: [{
|
34
|
+
describe('should correctly parse data', () => {
|
35
|
+
it('should parse modern schema result to KeyValueRow', () => {
|
36
|
+
const response = {
|
37
|
+
result: [['42', 'hello world']],
|
38
|
+
columns: [
|
39
|
+
{
|
102
40
|
name: 'id',
|
103
|
-
type: 'Uint64?'
|
104
|
-
},
|
41
|
+
type: 'Uint64?',
|
42
|
+
},
|
43
|
+
{
|
105
44
|
name: 'value',
|
106
|
-
type: 'Utf8?'
|
107
|
-
}
|
108
|
-
|
109
|
-
|
110
|
-
|
45
|
+
type: 'Utf8?',
|
46
|
+
},
|
47
|
+
],
|
48
|
+
};
|
49
|
+
const parsedResponse = parseQueryAPIExecuteResponse(response);
|
50
|
+
|
51
|
+
expect(parsedResponse.result).toEqual([
|
52
|
+
{
|
111
53
|
id: '42',
|
112
|
-
value: 'hello world'
|
113
|
-
}
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
it('should handle empty response for classic schema', () => {
|
118
|
-
expect(parseQueryAPIExecuteResponse(null).result).toBeUndefined();
|
119
|
-
});
|
120
|
-
|
121
|
-
it('should parse plain classic schema', () => {
|
122
|
-
const response = [{foo: 'bar'}];
|
123
|
-
expect(parseQueryAPIExecuteResponse(response).result).toEqual(response);
|
124
|
-
});
|
125
|
-
|
126
|
-
it('should parse deep classic schema', () => {
|
127
|
-
const response = {result: [{foo: 'bar'}]};
|
128
|
-
expect(parseQueryAPIExecuteResponse(response).result).toEqual(response.result);
|
129
|
-
});
|
130
|
-
|
131
|
-
it('should parse ydb schema', () => {
|
132
|
-
const response = {result: [{foo: 'bar'}]};
|
133
|
-
expect(parseQueryAPIExecuteResponse(response).result).toEqual(response.result);
|
134
|
-
});
|
54
|
+
value: 'hello world',
|
55
|
+
},
|
56
|
+
]);
|
57
|
+
expect(parsedResponse.columns).toEqual(response.columns);
|
135
58
|
});
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
59
|
+
it('should return KeyValueRow result for ydb and classic schemas unchanged', () => {
|
60
|
+
const response = {result: [{foo: 'bar'}]};
|
61
|
+
expect(parseQueryAPIExecuteResponse(response).result).toEqual(response.result);
|
62
|
+
});
|
63
|
+
it('shoudl return stats for modern schema', () => {
|
64
|
+
const result = [['42', 'hello world']];
|
65
|
+
const columns = [
|
66
|
+
{
|
67
|
+
name: 'id',
|
68
|
+
type: 'Uint64?',
|
69
|
+
},
|
70
|
+
{
|
71
|
+
name: 'value',
|
72
|
+
type: 'Utf8?',
|
73
|
+
},
|
74
|
+
];
|
75
|
+
|
76
|
+
const stats = {metric: 'good'} as TKqpStatsQuery;
|
77
|
+
|
78
|
+
const response = {result, columns, stats};
|
79
|
+
const parsedResponse = parseQueryAPIExecuteResponse(response);
|
80
|
+
|
81
|
+
expect(parsedResponse.result).toEqual([
|
82
|
+
{
|
152
83
|
id: '42',
|
153
|
-
value: 'hello world'
|
154
|
-
}
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
stats: {metric: 'good'},
|
163
|
-
};
|
164
|
-
const actual = parseQueryAPIExecuteResponse(response);
|
165
|
-
expect(actual.result).toEqual(response.result);
|
166
|
-
expect(actual.stats).toEqual(response.stats);
|
167
|
-
});
|
84
|
+
value: 'hello world',
|
85
|
+
},
|
86
|
+
]);
|
87
|
+
expect(parsedResponse.columns).toEqual(response.columns);
|
88
|
+
expect(parsedResponse.stats).toEqual(response.stats);
|
89
|
+
});
|
90
|
+
it('shoudl return stats for ydb and classic schemas', () => {
|
91
|
+
const result = [{foo: 'bar'}];
|
92
|
+
const stats = {metric: 'good'} as TKqpStatsQuery;
|
168
93
|
|
169
|
-
|
170
|
-
|
171
|
-
result: [{foo: 'bar'}],
|
172
|
-
stats: {metric: 'good'},
|
173
|
-
};
|
174
|
-
const actual = parseQueryAPIExecuteResponse(response);
|
175
|
-
expect(actual.result).toEqual(response.result);
|
176
|
-
expect(actual.stats).toEqual(response.stats);
|
177
|
-
});
|
94
|
+
const response = {result, stats};
|
95
|
+
const parsedResponse = parseQueryAPIExecuteResponse(response);
|
178
96
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
97
|
+
expect(parsedResponse.result).toEqual(response.result);
|
98
|
+
expect(parsedResponse.stats).toEqual(response.stats);
|
99
|
+
});
|
100
|
+
it('should accept stats without a result', () => {
|
101
|
+
const stats = {metric: 'good'} as TKqpStatsQuery;
|
102
|
+
const response = {stats};
|
103
|
+
const actual = parseQueryAPIExecuteResponse(response);
|
104
|
+
expect(actual.result).toBeUndefined();
|
105
|
+
expect(actual.columns).toBeUndefined();
|
106
|
+
expect(actual.stats).toEqual(response.stats);
|
188
107
|
});
|
189
108
|
});
|
190
109
|
});
|
191
110
|
|
192
111
|
describe('parseQueryAPIExplainResponse', () => {
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
it('should accept stats without a plan', () => {
|
198
|
-
const stats = {metric: 'good'};
|
199
|
-
expect(parseQueryAPIExplainResponse({stats}).stats).toEqual(stats);
|
200
|
-
});
|
201
|
-
|
202
|
-
describe('old format', () => {
|
203
|
-
describe('explain', () => {
|
204
|
-
it('should parse plan data in the root', () => {
|
205
|
-
const plan = {foo: 'bar'};
|
206
|
-
expect(parseQueryAPIExplainResponse(plan).plan).toEqual(plan);
|
207
|
-
});
|
208
|
-
|
209
|
-
it('should parse plan in the result field with stats', () => {
|
210
|
-
const plan = {foo: 'bar'};
|
211
|
-
const stats = {metric: 'good'};
|
212
|
-
const actual = parseQueryAPIExplainResponse({result: plan, stats});
|
213
|
-
expect(actual.plan).toEqual(plan);
|
214
|
-
expect(actual.stats).toEqual(stats);
|
215
|
-
});
|
112
|
+
describe('should handle responses with incorrect format', () => {
|
113
|
+
it('should handle null response', () => {
|
114
|
+
expect(parseQueryAPIExecuteResponse(null)).toEqual({});
|
216
115
|
});
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
});
|
223
|
-
|
224
|
-
it('should parse ast in the result field with stats', () => {
|
225
|
-
const ast = 'ast';
|
226
|
-
const stats = {metric: 'good'};
|
227
|
-
const actual = parseQueryAPIExplainResponse({result: {ast}, stats});
|
228
|
-
expect(actual.ast).toBe(ast);
|
229
|
-
expect(actual.stats).toEqual(stats);
|
230
|
-
});
|
116
|
+
it('should handle undefined response', () => {
|
117
|
+
expect(parseQueryAPIExecuteResponse(undefined)).toEqual({});
|
118
|
+
});
|
119
|
+
it('should handle object with plan in the result field', () => {
|
120
|
+
const response = {result: {foo: 'bar'}};
|
121
|
+
expect(parseQueryAPIExecuteResponse(response)).toEqual({});
|
231
122
|
});
|
232
123
|
});
|
233
124
|
|
234
|
-
describe('
|
235
|
-
it('should parse explain
|
236
|
-
const plan = {
|
125
|
+
describe('should correctly parse data', () => {
|
126
|
+
it('should parse explain-scan', () => {
|
127
|
+
const plan: PlanNode = {};
|
128
|
+
const tables: PlanTable[] = [];
|
129
|
+
const meta: PlanMeta = {version: '0.2', type: 'script'};
|
237
130
|
const ast = 'ast';
|
238
|
-
const
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
131
|
+
const response = {plan: {Plan: plan, tables, meta}, ast};
|
132
|
+
expect(parseQueryAPIExplainResponse(response)).toBe(response);
|
133
|
+
});
|
134
|
+
it('should parse explain-script', () => {
|
135
|
+
const plan: PlanNode = {};
|
136
|
+
const tables: PlanTable[] = [];
|
137
|
+
const meta: PlanMeta = {version: '0.2', type: 'script'};
|
138
|
+
|
139
|
+
const response = {
|
140
|
+
plan: {queries: [{Plan: plan, tables}], meta},
|
141
|
+
};
|
142
|
+
expect(parseQueryAPIExplainResponse(response)).toBe(response);
|
243
143
|
});
|
244
144
|
});
|
245
145
|
});
|
146
|
+
|
147
|
+
describe('parseQueryExplainPlan', () => {
|
148
|
+
it('should parse explain script plan to explain scan', () => {
|
149
|
+
const plan: PlanNode = {};
|
150
|
+
const tables: PlanTable[] = [];
|
151
|
+
const meta: PlanMeta = {version: '0.2', type: 'script'};
|
152
|
+
|
153
|
+
const rawPlan = {
|
154
|
+
queries: [
|
155
|
+
{
|
156
|
+
Plan: plan,
|
157
|
+
tables,
|
158
|
+
},
|
159
|
+
],
|
160
|
+
meta,
|
161
|
+
};
|
162
|
+
const parsedPlan = parseQueryExplainPlan(rawPlan);
|
163
|
+
expect(parsedPlan.Plan).toEqual(plan);
|
164
|
+
expect(parsedPlan.tables).toBe(tables);
|
165
|
+
expect(parsedPlan.meta).toEqual(meta);
|
166
|
+
});
|
167
|
+
it('should left scan plan unchanged', () => {
|
168
|
+
const plan: PlanNode = {};
|
169
|
+
const tables: PlanTable[] = [];
|
170
|
+
const meta: PlanMeta = {version: '0.2', type: 'script'};
|
171
|
+
|
172
|
+
const rawPlan = {
|
173
|
+
Plan: plan,
|
174
|
+
tables: tables,
|
175
|
+
meta: meta,
|
176
|
+
};
|
177
|
+
const parsedPlan = parseQueryExplainPlan(rawPlan);
|
178
|
+
expect(parsedPlan).toEqual(rawPlan);
|
179
|
+
});
|
180
|
+
});
|
246
181
|
});
|
247
182
|
});
|