From 2bfed9eb1258c707d3d4964280c5bf02745373b2 Mon Sep 17 00:00:00 2001 From: Elena Makarova Date: Mon, 24 Nov 2025 13:39:56 +0300 Subject: [PATCH 1/2] fix: insert SHOW CREATE TABLE resp to editor --- .../ObjectSummary/SchemaTree/SchemaTree.tsx | 21 ++++++++- src/containers/Tenant/utils/schema.ts | 5 +++ src/containers/Tenant/utils/schemaActions.tsx | 16 +++++-- .../Tenant/utils/schemaQueryTemplates.ts | 4 ++ .../showCreateTable/showCreateTable.ts | 44 +++++++++++++++++++ 5 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 src/store/reducers/showCreateTable/showCreateTable.ts diff --git a/src/containers/Tenant/ObjectSummary/SchemaTree/SchemaTree.tsx b/src/containers/Tenant/ObjectSummary/SchemaTree/SchemaTree.tsx index 7ebc9ce8e0..b9deeaa3d5 100644 --- a/src/containers/Tenant/ObjectSummary/SchemaTree/SchemaTree.tsx +++ b/src/containers/Tenant/ObjectSummary/SchemaTree/SchemaTree.tsx @@ -13,6 +13,7 @@ import { import {useClusterBaseInfo} from '../../../../store/reducers/cluster/cluster'; import {selectIsDirty, selectUserInput} from '../../../../store/reducers/query/query'; import {schemaApi} from '../../../../store/reducers/schema/schema'; +import {showCreateTableApi} from '../../../../store/reducers/showCreateTable/showCreateTable'; import {streamingQueriesApi} from '../../../../store/reducers/streamingQuery/streamingQuery'; import {tableSchemaDataApi} from '../../../../store/reducers/tableSchemaData'; import {useTenantBaseInfo} from '../../../../store/reducers/tenant/tenant'; @@ -28,12 +29,13 @@ import { mapPathTypeToNavigationTreeType, nodeStreamingQueryTypeToPathType, nodeTableTypeToPathType, + tableTypeToPathType, } from '../../utils/schema'; import {getActions} from '../../utils/schemaActions'; import type {DropdownItem, TreeNodeMeta} from '../../utils/types'; import {CreateDirectoryDialog} from '../CreateDirectoryDialog/CreateDirectoryDialog'; import {useDispatchTreeKey, useTreeKey} from '../UpdateTreeContext'; -import {isDomain} from '../transformPath'; +import {isDomain, transformPath} from '../transformPath'; interface SchemaTreeProps { rootName: string; @@ -58,6 +60,10 @@ export function SchemaTree(props: SchemaTreeProps) { getStreamingQueryInfo, {currentData: streamingSysData, isFetching: isStreamingInfoFetching}, ] = streamingQueriesApi.useLazyGetStreamingQueryInfoQuery(); + const [ + getShowCreateTable, + {currentData: showCreateTableData, isFetching: isShowCreateTableFetching}, + ] = showCreateTableApi.useLazyGetShowCreateTableQuery(); const isTopicPreviewAvailable = useTopicDataAvailable(); @@ -162,6 +168,10 @@ export function SchemaTree(props: SchemaTreeProps) { isSchemaDataLoading: isActionsDataFetching, hasMonitoring, streamingQueryData: streamingSysData, + showCreateTableData: showCreateTableData + ? showCreateTableData.toString() + : undefined, + isShowCreateTableLoading: isShowCreateTableFetching, isStreamingQueryTextLoading: isStreamingInfoFetching, }, databaseFullPath, @@ -181,6 +191,9 @@ export function SchemaTree(props: SchemaTreeProps) { databaseFullPath, controlPlane, clusterMonitoring, + showCreateTableData, + isShowCreateTableFetching, + handleTenantPageChange, ]); return ( @@ -208,6 +221,12 @@ export function SchemaTree(props: SchemaTreeProps) { if (isOpen && pathType) { getTableSchemaDataQuery({path, database, type: pathType, databaseFullPath}); } + const tableType = tableTypeToPathType[type]; + + if (isOpen && tableType) { + const relativePath = transformPath(path, databaseFullPath); + getShowCreateTable({path: relativePath, database}); + } const streamingPathType = nodeStreamingQueryTypeToPathType[type]; if (isOpen && streamingPathType) { diff --git a/src/containers/Tenant/utils/schema.ts b/src/containers/Tenant/utils/schema.ts index 54a822fa1b..dd1df9c59b 100644 --- a/src/containers/Tenant/utils/schema.ts +++ b/src/containers/Tenant/utils/schema.ts @@ -57,6 +57,11 @@ export const nodeTableTypeToPathType: Partial> = { + table: EPathType.EPathTypeTable, + column_table: EPathType.EPathTypeColumnTable, +}; + export const nodeStreamingQueryTypeToPathType: Partial> = { streaming_query: EPathType.EPathTypeStreamingQuery, diff --git a/src/containers/Tenant/utils/schemaActions.tsx b/src/containers/Tenant/utils/schemaActions.tsx index 4d790250d4..0be1df5af5 100644 --- a/src/containers/Tenant/utils/schemaActions.tsx +++ b/src/containers/Tenant/utils/schemaActions.tsx @@ -62,7 +62,9 @@ interface ActionsAdditionalParams { isSchemaDataLoading?: boolean; hasMonitoring?: boolean; streamingQueryData?: IQueryResult; + showCreateTableData?: string; isStreamingQueryTextLoading?: boolean; + isShowCreateTableLoading?: boolean; } interface BindActionParams { @@ -86,6 +88,7 @@ const bindActions = ( getConnectToDBDialog, schemaData, streamingQueryData, + showCreateTableData, } = additionalEffects; const inputQuery = (tmpl: TemplateFn) => () => { @@ -94,7 +97,9 @@ const bindActions = ( setTenantPage(TENANT_PAGES_IDS.query); dispatch(setQueryTab(TENANT_QUERY_TABS_ID.newQuery)); setActivePath(params.path); - insertSnippetToEditor(tmpl({...params, schemaData, streamingQueryData})); + insertSnippetToEditor( + tmpl({...params, schemaData, streamingQueryData, showCreateTableData}), + ); }; if (getConfirmation) { const confirmedPromise = getConfirmation(); @@ -174,9 +179,10 @@ interface ActionConfig { text: string; action: () => void; isLoading?: boolean; + iconStart?: React.ReactNode; } -const getActionWithLoader = ({text, action, isLoading}: ActionConfig) => ({ +const getActionWithLoader = ({text, action, isLoading, iconStart}: ActionConfig) => ({ text: ( {text} @@ -185,6 +191,7 @@ const getActionWithLoader = ({text, action, isLoading}: ActionConfig) => ({ ), action, disabled: isLoading, + iconStart, }); export const getActions = @@ -269,11 +276,12 @@ export const getActions = DIR_SET.splice(1, 0, [createDirectoryItem]); } - const showCreateTableItem = { + const showCreateTableItem = getActionWithLoader({ text: i18n('actions.showCreateTable'), action: actions.showCreateTable, + isLoading: additionalEffects.isShowCreateTableLoading, iconStart: , - }; + }); const ROW_TABLE_SET: ActionsSet = [ [copyItem], diff --git a/src/containers/Tenant/utils/schemaQueryTemplates.ts b/src/containers/Tenant/utils/schemaQueryTemplates.ts index 6f80ed51c6..57f6c1d441 100644 --- a/src/containers/Tenant/utils/schemaQueryTemplates.ts +++ b/src/containers/Tenant/utils/schemaQueryTemplates.ts @@ -11,6 +11,7 @@ export interface SchemaQueryParams { relativePath: string; schemaData?: SchemaData[]; streamingQueryData?: IQueryResult; + showCreateTableData?: string; } export type TemplateFn = (params?: SchemaQueryParams) => string; @@ -161,6 +162,9 @@ ${filters}LIMIT \${5:10};`; }; export const showCreateTableTemplate = (params?: SchemaQueryParams) => { + if (params?.showCreateTableData) { + return params?.showCreateTableData; + } const tablePath = params?.relativePath ? `\`${normalizeParameter(params.relativePath)}\`` : '${2:}'; diff --git a/src/store/reducers/showCreateTable/showCreateTable.ts b/src/store/reducers/showCreateTable/showCreateTable.ts new file mode 100644 index 0000000000..48bcffacfb --- /dev/null +++ b/src/store/reducers/showCreateTable/showCreateTable.ts @@ -0,0 +1,44 @@ +import {QUERY_TECHNICAL_MARK} from '../../../utils/constants'; +import {isQueryErrorResponse, parseQueryAPIResponse} from '../../../utils/query'; +import {api} from '../api'; + +function getShowCreateTableSQL(path: string) { + const safePath = path.replace(/'/g, "''"); + return `${QUERY_TECHNICAL_MARK} +SHOW CREATE TABLE \`${safePath}\``; +} + +export const showCreateTableApi = api.injectEndpoints({ + endpoints: (build) => ({ + getShowCreateTable: build.query({ + queryFn: async ({database, path}: {database: string; path: string}, {signal}) => { + try { + const response = await window.api.viewer.sendQuery( + { + query: getShowCreateTableSQL(path), + database, + action: 'execute-query', + }, + {signal, withRetries: true}, + ); + + if (isQueryErrorResponse(response)) { + return {error: response}; + } + + const data = parseQueryAPIResponse(response); + + const result = data?.resultSets?.[0]?.result || []; + + const showCreateTableQuery = result[0]?.CreateQuery; + + return {data: showCreateTableQuery}; + } catch (error) { + return {error}; + } + }, + providesTags: ['All'], + }), + }), + overrideExisting: 'throw', +}); From f389e771a111e4308945e478ea8598cd672f22c1 Mon Sep 17 00:00:00 2001 From: Elena Makarova Date: Wed, 26 Nov 2025 12:37:08 +0300 Subject: [PATCH 2/2] fix: review --- .../Tenant/ObjectSummary/SchemaTree/SchemaTree.tsx | 5 ++--- src/containers/Tenant/utils/schemaQueryTemplates.ts | 2 +- src/store/reducers/showCreateTable/showCreateTable.ts | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/containers/Tenant/ObjectSummary/SchemaTree/SchemaTree.tsx b/src/containers/Tenant/ObjectSummary/SchemaTree/SchemaTree.tsx index b9deeaa3d5..225cfffcb9 100644 --- a/src/containers/Tenant/ObjectSummary/SchemaTree/SchemaTree.tsx +++ b/src/containers/Tenant/ObjectSummary/SchemaTree/SchemaTree.tsx @@ -19,6 +19,7 @@ import {tableSchemaDataApi} from '../../../../store/reducers/tableSchemaData'; import {useTenantBaseInfo} from '../../../../store/reducers/tenant/tenant'; import type {EPathType, TEvDescribeSchemeResult} from '../../../../types/api/schema'; import {valueIsDefined} from '../../../../utils'; +import {getStringifiedData} from '../../../../utils/dataFormatters/dataFormatters'; import {useTypedDispatch, useTypedSelector} from '../../../../utils/hooks'; import {getConfirmation} from '../../../../utils/hooks/withConfirmation/useChangeInputWithConfirmation'; import {canShowTenantMonitoringTab} from '../../../../utils/monitoringVisibility'; @@ -168,9 +169,7 @@ export function SchemaTree(props: SchemaTreeProps) { isSchemaDataLoading: isActionsDataFetching, hasMonitoring, streamingQueryData: streamingSysData, - showCreateTableData: showCreateTableData - ? showCreateTableData.toString() - : undefined, + showCreateTableData: getStringifiedData(showCreateTableData), isShowCreateTableLoading: isShowCreateTableFetching, isStreamingQueryTextLoading: isStreamingInfoFetching, }, diff --git a/src/containers/Tenant/utils/schemaQueryTemplates.ts b/src/containers/Tenant/utils/schemaQueryTemplates.ts index 57f6c1d441..521d28027d 100644 --- a/src/containers/Tenant/utils/schemaQueryTemplates.ts +++ b/src/containers/Tenant/utils/schemaQueryTemplates.ts @@ -163,7 +163,7 @@ ${filters}LIMIT \${5:10};`; export const showCreateTableTemplate = (params?: SchemaQueryParams) => { if (params?.showCreateTableData) { - return params?.showCreateTableData; + return params.showCreateTableData; } const tablePath = params?.relativePath ? `\`${normalizeParameter(params.relativePath)}\`` diff --git a/src/store/reducers/showCreateTable/showCreateTable.ts b/src/store/reducers/showCreateTable/showCreateTable.ts index 48bcffacfb..ae4b1cf3ae 100644 --- a/src/store/reducers/showCreateTable/showCreateTable.ts +++ b/src/store/reducers/showCreateTable/showCreateTable.ts @@ -3,7 +3,7 @@ import {isQueryErrorResponse, parseQueryAPIResponse} from '../../../utils/query' import {api} from '../api'; function getShowCreateTableSQL(path: string) { - const safePath = path.replace(/'/g, "''"); + const safePath = path.replace(/`/g, '``'); return `${QUERY_TECHNICAL_MARK} SHOW CREATE TABLE \`${safePath}\``; }