Skip to content

Commit adc597a

Browse files
committed
feat: use mutation
1 parent afab4eb commit adc597a

File tree

9 files changed

+168
-135
lines changed

9 files changed

+168
-135
lines changed

src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {NavigationTree} from 'ydb-ui-components';
77

88
import {useCreateDirectoryFeatureAvailable} from '../../../../store/reducers/capabilities/hooks';
99
import {schemaApi} from '../../../../store/reducers/schema/schema';
10+
import type {GetTableSchemaDataParams} from '../../../../store/reducers/tableSchemaData';
11+
import {useGetTableSchemaDataMutation} from '../../../../store/reducers/tableSchemaData';
1012
import type {EPathType, TEvDescribeSchemeResult} from '../../../../types/api/schema';
1113
import {useQueryExecutionSettings, useTypedDispatch} from '../../../../utils/hooks';
1214
import {getSchemaControls} from '../../utils/controls';
@@ -26,6 +28,19 @@ export function SchemaTree(props: SchemaTreeProps) {
2628
const createDirectoryFeatureAvailable = useCreateDirectoryFeatureAvailable();
2729
const {rootPath, rootName, rootType, currentPath, onActivePathUpdate} = props;
2830
const dispatch = useTypedDispatch();
31+
const [getTableSchemaDataMutation] = useGetTableSchemaDataMutation();
32+
33+
const getTableSchemaDataPromise = React.useCallback(
34+
async (args: GetTableSchemaDataParams) => {
35+
try {
36+
const result = await getTableSchemaDataMutation(args).unwrap();
37+
return result;
38+
} catch (e) {
39+
return undefined;
40+
}
41+
},
42+
[getTableSchemaDataMutation],
43+
);
2944

3045
const [querySettings, setQueryExecutionSettings] = useQueryExecutionSettings();
3146
const [createDirectoryOpen, setCreateDirectoryOpen] = React.useState(false);
@@ -119,6 +134,7 @@ export function SchemaTree(props: SchemaTreeProps) {
119134
showCreateDirectoryDialog: createDirectoryFeatureAvailable
120135
? handleOpenCreateDirectoryDialog
121136
: undefined,
137+
getTableSchemaDataPromise,
122138
},
123139
rootPath,
124140
)}

src/containers/Tenant/Schema/SchemaViewer/SchemaViewer.tsx

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
import React from 'react';
22

3+
import {skipToken} from '@reduxjs/toolkit/query';
4+
35
import {ResizeableDataTable} from '../../../../components/ResizeableDataTable/ResizeableDataTable';
46
import {TableSkeleton} from '../../../../components/TableSkeleton/TableSkeleton';
7+
import {overviewApi} from '../../../../store/reducers/overview/overview';
8+
import {viewSchemaApi} from '../../../../store/reducers/viewSchema/viewSchema';
59
import type {EPathType} from '../../../../types/api/schema';
610
import {DEFAULT_TABLE_SETTINGS} from '../../../../utils/constants';
7-
import {useTableData} from '../../../../utils/hooks';
11+
import {useAutoRefreshInterval} from '../../../../utils/hooks';
812
import {
913
isColumnEntityType,
1014
isExternalTableType,
@@ -20,6 +24,7 @@ import {
2024
getRowTableColumns,
2125
getViewColumns,
2226
} from './columns';
27+
import {prepareSchemaData, prepareViewSchema} from './prepareData';
2328
import {b} from './shared';
2429

2530
import './SchemaViewer.scss';
@@ -32,11 +37,31 @@ interface SchemaViewerProps {
3237
}
3338

3439
export const SchemaViewer = ({type, path, tenantName, extended = false}: SchemaViewerProps) => {
35-
const {tableData, isOverviewLoading, isViewSchemaLoading} = useTableData({
36-
type,
37-
path,
38-
tenantName,
39-
});
40+
const [autoRefreshInterval] = useAutoRefreshInterval();
41+
const {currentData, isLoading: loading} = overviewApi.useGetOverviewQuery(
42+
{
43+
paths: [path],
44+
database: tenantName,
45+
},
46+
{
47+
pollingInterval: autoRefreshInterval,
48+
},
49+
);
50+
51+
const {data: schemaData} = currentData ?? {};
52+
53+
const viewSchemaRequestParams = isViewType(type) ? {path, database: tenantName} : skipToken;
54+
55+
const {data: viewColumnsData, isLoading: isViewSchemaLoading} =
56+
viewSchemaApi.useGetViewSchemaQuery(viewSchemaRequestParams);
57+
58+
const tableData = React.useMemo(() => {
59+
if (isViewType(type)) {
60+
return prepareViewSchema(viewColumnsData);
61+
}
62+
63+
return prepareSchemaData(type, schemaData);
64+
}, [schemaData, type, viewColumnsData]);
4065

4166
const hasAutoIncrement = React.useMemo(() => {
4267
return tableData.some((i) => i.autoIncrement);
@@ -63,7 +88,7 @@ export const SchemaViewer = ({type, path, tenantName, extended = false}: SchemaV
6388
return [];
6489
}, [type, extended, hasAutoIncrement, hasDefaultValue]);
6590

66-
if (isOverviewLoading || isViewSchemaLoading) {
91+
if (loading || isViewSchemaLoading) {
6792
return <TableSkeleton />;
6893
}
6994

src/utils/prepareTableData.ts renamed to src/containers/Tenant/Schema/SchemaViewer/prepareData.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
1-
import type {SchemaData} from '../containers/Tenant/Schema/SchemaViewer/types';
2-
import {
3-
isColumnEntityType,
4-
isExternalTableType,
5-
isRowTableType,
6-
} from '../containers/Tenant/utils/schema';
7-
import type {ColumnType} from '../types/api/query';
1+
import type {ColumnType} from '../../../../types/api/query';
82
import type {
93
EPathType,
104
TColumnTableDescription,
115
TEvDescribeSchemeResult,
126
TExternalTableDescription,
137
TFamilyDescription,
148
TTableDescription,
15-
} from '../types/api/schema';
16-
import {EColumnCodec} from '../types/api/schema';
9+
} from '../../../../types/api/schema';
10+
import {EColumnCodec} from '../../../../types/api/schema';
11+
import type {Nullable} from '../../../../utils/typecheckers';
12+
import {isColumnEntityType, isExternalTableType, isRowTableType} from '../../utils/schema';
1713

18-
import type {Nullable} from './typecheckers';
14+
import type {SchemaData} from './types';
1915

2016
function formatColumnCodec(codec?: EColumnCodec) {
2117
if (!codec) {

src/containers/Tenant/utils/schemaActions.ts

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ import type {NavigationTreeNodeType, NavigationTreeProps} from 'ydb-ui-component
33

44
import type {AppDispatch} from '../../../store';
55
import {changeUserInput} from '../../../store/reducers/executeQuery';
6+
import type {GetTableSchemaDataParams} from '../../../store/reducers/tableSchemaData';
67
import {TENANT_PAGES_IDS, TENANT_QUERY_TABS_ID} from '../../../store/reducers/tenant/constants';
78
import {setQueryTab, setTenantPage} from '../../../store/reducers/tenant/tenant';
89
import type {QueryMode, QuerySettings} from '../../../types/store/query';
910
import createToast from '../../../utils/createToast';
10-
import {getTableDataPromise} from '../../../utils/hooks';
1111
import {transformPath} from '../ObjectSummary/transformPath';
12+
import type {SchemaData} from '../Schema/SchemaViewer/types';
1213
import i18n from '../i18n';
1314

1415
import {nodeTableTypeToPathType} from './schema';
@@ -37,11 +38,9 @@ interface ActionsAdditionalEffects {
3738
updateQueryExecutionSettings: (settings?: Partial<QuerySettings>) => void;
3839
setActivePath: (path: string) => void;
3940
showCreateDirectoryDialog?: (path: string) => void;
40-
}
41-
42-
interface AdditionalInputQueryOptions {
43-
mode?: QueryMode;
44-
withTableData?: boolean;
41+
getTableSchemaDataPromise?: (
42+
params: GetTableSchemaDataParams,
43+
) => Promise<SchemaData[] | undefined>;
4544
}
4645

4746
interface BindActionParams {
@@ -56,19 +55,28 @@ const bindActions = (
5655
dispatch: AppDispatch,
5756
additionalEffects: ActionsAdditionalEffects,
5857
) => {
59-
const {setActivePath, updateQueryExecutionSettings, showCreateDirectoryDialog} =
60-
additionalEffects;
61-
62-
const inputQuery = (tmpl: TemplateFn, options?: AdditionalInputQueryOptions) => () => {
63-
if (options?.mode) {
64-
updateQueryExecutionSettings({queryMode: options.mode});
58+
const {
59+
setActivePath,
60+
updateQueryExecutionSettings,
61+
showCreateDirectoryDialog,
62+
getTableSchemaDataPromise,
63+
} = additionalEffects;
64+
65+
const inputQuery = (tmpl: TemplateFn, mode?: QueryMode) => () => {
66+
if (mode) {
67+
updateQueryExecutionSettings({queryMode: mode});
6568
}
6669

6770
const pathType = nodeTableTypeToPathType[params.type];
71+
const withTableData = [selectQueryTemplate, upsertQueryTemplate].includes(tmpl);
6872

6973
const userInputDataPromise =
70-
options?.withTableData && pathType
71-
? getTableDataPromise(params.path, params.tenantName, pathType, dispatch)
74+
withTableData && pathType && getTableSchemaDataPromise
75+
? getTableSchemaDataPromise({
76+
path: params.path,
77+
tenantName: params.tenantName,
78+
type: pathType,
79+
})
7280
: Promise.resolve(undefined);
7381

7482
userInputDataPromise.then((tableData) => {
@@ -86,24 +94,24 @@ const bindActions = (
8694
showCreateDirectoryDialog(params.path);
8795
}
8896
: undefined,
89-
createTable: inputQuery(createTableTemplate, {mode: 'script'}),
90-
createColumnTable: inputQuery(createColumnTableTemplate, {mode: 'script'}),
91-
createAsyncReplication: inputQuery(createAsyncReplicationTemplate, {mode: 'script'}),
92-
alterAsyncReplication: inputQuery(alterAsyncReplicationTemplate, {mode: 'script'}),
93-
dropAsyncReplication: inputQuery(dropAsyncReplicationTemplate, {mode: 'script'}),
94-
alterTable: inputQuery(alterTableTemplate, {mode: 'script'}),
95-
selectQuery: inputQuery(selectQueryTemplate, {withTableData: true}),
96-
upsertQuery: inputQuery(upsertQueryTemplate, {withTableData: true}),
97-
createExternalTable: inputQuery(createExternalTableTemplate, {mode: 'script'}),
98-
dropExternalTable: inputQuery(dropExternalTableTemplate, {mode: 'script'}),
99-
selectQueryFromExternalTable: inputQuery(selectQueryTemplate, {mode: 'query'}),
100-
createTopic: inputQuery(createTopicTemplate, {mode: 'script'}),
101-
alterTopic: inputQuery(alterTopicTemplate, {mode: 'script'}),
102-
dropTopic: inputQuery(dropTopicTemplate, {mode: 'script'}),
103-
createView: inputQuery(createViewTemplate, {mode: 'script'}),
104-
dropView: inputQuery(dropViewTemplate, {mode: 'script'}),
105-
dropIndex: inputQuery(dropTableIndex, {mode: 'script'}),
106-
addTableIndex: inputQuery(addTableIndex, {mode: 'script'}),
97+
createTable: inputQuery(createTableTemplate, 'script'),
98+
createColumnTable: inputQuery(createColumnTableTemplate, 'script'),
99+
createAsyncReplication: inputQuery(createAsyncReplicationTemplate, 'script'),
100+
alterAsyncReplication: inputQuery(alterAsyncReplicationTemplate, 'script'),
101+
dropAsyncReplication: inputQuery(dropAsyncReplicationTemplate, 'script'),
102+
alterTable: inputQuery(alterTableTemplate, 'script'),
103+
selectQuery: inputQuery(selectQueryTemplate),
104+
upsertQuery: inputQuery(upsertQueryTemplate),
105+
createExternalTable: inputQuery(createExternalTableTemplate, 'script'),
106+
dropExternalTable: inputQuery(dropExternalTableTemplate, 'script'),
107+
selectQueryFromExternalTable: inputQuery(selectQueryTemplate, 'query'),
108+
createTopic: inputQuery(createTopicTemplate, 'script'),
109+
alterTopic: inputQuery(alterTopicTemplate, 'script'),
110+
dropTopic: inputQuery(dropTopicTemplate, 'script'),
111+
createView: inputQuery(createViewTemplate, 'script'),
112+
dropView: inputQuery(dropViewTemplate, 'script'),
113+
dropIndex: inputQuery(dropTableIndex, 'script'),
114+
addTableIndex: inputQuery(addTableIndex, 'script'),
107115
copyPath: () => {
108116
try {
109117
copy(params.relativePath);

src/services/api.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
374374
);
375375
}
376376
getDescribe(
377-
{path, database}: {path: string; database: string},
377+
{path, database, timeout}: {path: string; database: string; timeout?: Timeout},
378378
{concurrentId, signal}: AxiosOptions = {},
379379
) {
380380
return this.get<Nullable<TEvDescribeSchemeResult>>(
@@ -386,7 +386,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
386386
partition_stats: true,
387387
subs: 0,
388388
},
389-
{concurrentId: concurrentId || `getDescribe|${path}`, requestConfig: {signal}},
389+
{concurrentId: concurrentId || `getDescribe|${path}`, requestConfig: {signal}, timeout},
390390
);
391391
}
392392
getSchemaAcl(
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import {
2+
prepareSchemaData,
3+
prepareViewSchema,
4+
} from '../../containers/Tenant/Schema/SchemaViewer/prepareData';
5+
import type {SchemaData} from '../../containers/Tenant/Schema/SchemaViewer/types';
6+
import {isViewType} from '../../containers/Tenant/utils/schema';
7+
import type {EPathType} from '../../types/api/schema';
8+
import {isQueryErrorResponse} from '../../utils/query';
9+
10+
import {api} from './api';
11+
import {createViewSchemaQuery} from './viewSchema/viewSchema';
12+
13+
export interface GetTableSchemaDataParams {
14+
path: string;
15+
tenantName: string;
16+
type: EPathType;
17+
}
18+
19+
const tableSchemaDataConcurrentId = 'getTableSchemaData';
20+
21+
const TABLE_SCHEMA_TIMEOUT = 1000;
22+
23+
export const tableSchemeDataApi = api.injectEndpoints({
24+
endpoints: (build) => ({
25+
getTableSchemaData: build.mutation<SchemaData[], GetTableSchemaDataParams>({
26+
queryFn: async ({path, tenantName, type}, {signal}) => {
27+
try {
28+
const schemaData = await window.api.getDescribe(
29+
{
30+
path,
31+
database: tenantName,
32+
timeout: TABLE_SCHEMA_TIMEOUT,
33+
},
34+
{signal, concurrentId: tableSchemaDataConcurrentId + 'describe'},
35+
);
36+
37+
if (isViewType(type)) {
38+
const response = await window.api.sendQuery(
39+
{
40+
query: createViewSchemaQuery(path),
41+
database: tenantName,
42+
action: 'execute-scan',
43+
timeout: TABLE_SCHEMA_TIMEOUT,
44+
},
45+
{
46+
withRetries: true,
47+
concurrentId: tableSchemaDataConcurrentId + 'query',
48+
},
49+
);
50+
51+
if (isQueryErrorResponse(response)) {
52+
return {error: response};
53+
}
54+
55+
const viewColumnsData = {data: response?.result?.[0]?.columns || []};
56+
const result = prepareViewSchema(viewColumnsData.data);
57+
return {data: result};
58+
}
59+
60+
const result = prepareSchemaData(type, schemaData);
61+
62+
return {data: result};
63+
} catch (error) {
64+
return {error};
65+
}
66+
},
67+
}),
68+
}),
69+
});
70+
71+
export const {useGetTableSchemaDataMutation} = tableSchemeDataApi;

src/store/reducers/viewSchema/viewSchema.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {isQueryErrorResponse} from '../../../utils/query';
22
import {api} from '../api';
33

4-
function createViewSchemaQuery(path: string) {
4+
export function createViewSchemaQuery(path: string) {
55
return `SELECT * FROM \`${path}\` LIMIT 0`;
66
}
77

src/utils/hooks/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,3 @@ export * from './useTableSort';
66
export * from './useSearchQuery';
77
export * from './useAutoRefreshInterval';
88
export * from './useEventHandler';
9-
export * from './useTableData';

0 commit comments

Comments
 (0)