diff --git a/apps/desktop/src/components/editor/QueryEditor.vue b/apps/desktop/src/components/editor/QueryEditor.vue index 9661682ef1..4b3d0b4bfd 100644 --- a/apps/desktop/src/components/editor/QueryEditor.vue +++ b/apps/desktop/src/components/editor/QueryEditor.vue @@ -223,6 +223,20 @@ const zoomCommitScheduler = createEditorZoomCommitScheduler((fontSize) => { settingsStore.updateEditorSettings({ fontSize }); }); +const queryEditorAppearanceSettings = computed(() => { + const settings = settingsStore.editorSettings; + return { + fontFamily: settings.fontFamily, + fontSize: settings.fontSize, + theme: settings.theme, + customThemeColors: settings.customThemeColors, + customThemes: settings.customThemes, + activeCustomThemeId: settings.activeCustomThemeId, + wordWrap: settings.wordWrap, + shortcuts: settings.shortcuts, + }; +}); + function syncEditorFontCssVars(fontSize = liveFontSize.value, fontFamily = settingsStore.editorSettings.fontFamily) { if (!editorRef.value) return; editorRef.value.style.setProperty(EDITOR_FONT_SIZE_CSS_VAR, `${clampEditorFontSize(fontSize)}px`); @@ -2221,7 +2235,7 @@ function getCurrentCustomThemeColors() { // Reactively apply editor settings changes watch( - [() => settingsStore.editorSettings, () => isDark.value], + [queryEditorAppearanceSettings, () => isDark.value], async ([ss]) => { if (!view.value || !codeMirrorTheme || !fontThemeComp || !wordWrapComp || !runKeymapComp || !editorViewModule) { return; diff --git a/apps/desktop/src/components/structure/TableStructureEditor.vue b/apps/desktop/src/components/structure/TableStructureEditor.vue index feb6b91f0a..3c3ea0f9f6 100644 --- a/apps/desktop/src/components/structure/TableStructureEditor.vue +++ b/apps/desktop/src/components/structure/TableStructureEditor.vue @@ -87,6 +87,9 @@ const loading = ref(false); const saving = ref(false); const postSaveRefreshing = ref(false); const sqlPreviewLoading = ref(false); +const indexesLoading = ref(false); +const foreignKeysLoading = ref(false); +const triggersLoading = ref(false); const ddlContent = ref(""); const ddlLoading = ref(false); const ddlFetched = ref(false); @@ -111,6 +114,7 @@ const pendingStatements = ref([]); const warnings = ref([]); const foreignKeys = ref([]); const triggers = ref([]); +const secondaryMetadataLoading = computed(() => indexesLoading.value || foreignKeysLoading.value || triggersLoading.value); interface StructureRefreshScope { columns: boolean; @@ -224,7 +228,7 @@ const structureDensityMetrics: Record< } > = { compact: { - columns: [28, 120, 136, 82, 60, 52, 108, 124, 128, 108], + columns: [28, 120, 136, 82, 60, 52, 108, 124, 144, 108], indexes: [120, 180, 60, 88, 124, 144, 120, 70], minColumnWidth: 24, minIndexColumnWidth: 48, @@ -240,7 +244,7 @@ const structureDensityMetrics: Record< lineHeight: 1.35, }, standard: { - columns: [32, 144, 160, 104, 72, 64, 128, 152, 152, 136], + columns: [32, 144, 160, 104, 72, 64, 128, 152, 160, 136], indexes: [148, 224, 72, 108, 148, 180, 148, 84], minColumnWidth: 28, minIndexColumnWidth: 60, @@ -256,7 +260,7 @@ const structureDensityMetrics: Record< lineHeight: 1.4, }, comfortable: { - columns: [36, 168, 188, 116, 84, 76, 152, 188, 176, 148], + columns: [36, 168, 188, 116, 84, 76, 152, 188, 188, 148], indexes: [176, 260, 84, 124, 176, 216, 176, 104], minColumnWidth: 32, minIndexColumnWidth: 64, @@ -282,7 +286,8 @@ function metricsForDensity(density: StructureEditorDensity) { } const structureDensity = computed(() => settingsStore.editorSettings.structureEditorDensity); -const structureDensityMetric = computed(() => metricsForDensity(structureDensity.value)); +const localStructureDensity = ref(structureDensity.value); +const structureDensityMetric = computed(() => metricsForDensity(localStructureDensity.value)); const structureDensityOptions = computed(() => [ { value: "compact", label: t("structureEditor.densityCompact") }, { value: "standard", label: t("structureEditor.densityStandard") }, @@ -309,9 +314,14 @@ const structureToolbarButtonClass = "h-[var(--structure-control-height)] gap-1 p const structureIconButtonClass = "h-[var(--structure-control-height)] w-[var(--structure-control-height)]"; const structureIconClass = "h-[var(--structure-icon-size)] w-[var(--structure-icon-size)]"; const structureCheckboxClass = "h-[var(--structure-checkbox-size)] w-[var(--structure-checkbox-size)]"; -const structureHeaderCellClass = "relative border-b border-r px-[var(--structure-cell-px)] py-[var(--structure-header-py)] text-left"; -const structureCellClass = "border-b border-r px-[var(--structure-cell-px)] py-[var(--structure-cell-py)]"; -const structureLastCellClass = "border-b px-[var(--structure-cell-px)] py-[var(--structure-cell-py)]"; +const structureHeaderCellClass = "relative min-w-0 overflow-hidden border-b border-r px-[var(--structure-cell-px)] py-[var(--structure-header-py)] text-left"; +const structureCellClass = "min-w-0 overflow-hidden border-b border-r px-[var(--structure-cell-px)] py-[var(--structure-cell-py)]"; +const structureLastCellClass = "min-w-0 overflow-hidden border-b px-[var(--structure-cell-px)] py-[var(--structure-cell-py)]"; +const structurePropertyListClass = "flex min-w-0 items-center gap-0 overflow-hidden"; +const structurePropertyLabelClass = "flex min-w-0 items-center gap-1 whitespace-nowrap"; +const structureActionButtonClass = `${structureIconButtonClass} shrink-0`; +const structureDensityMenuOpen = ref(false); +const structureDensityMenuRef = ref(); function applyStructureDensityWidths(density: StructureEditorDensity) { const metric = metricsForDensity(density); @@ -321,7 +331,64 @@ function applyStructureDensityWidths(density: StructureEditorDensity) { function setStructureDensity(value: unknown) { if (!isStructureEditorDensity(value)) return; - settingsStore.updateEditorSettings({ structureEditorDensity: value }); + if (value === localStructureDensity.value) return; + localStructureDensity.value = value; +} + +function selectStructureDensity(value: unknown) { + setStructureDensity(value); + structureDensityMenuOpen.value = false; +} + +function toggleStructureDensityMenu() { + structureDensityMenuOpen.value = !structureDensityMenuOpen.value; +} + +function focusStructureDensityOption(offset: number) { + const currentIndex = structureDensityValues.indexOf(localStructureDensity.value); + const nextIndex = (currentIndex + offset + structureDensityValues.length) % structureDensityValues.length; + selectStructureDensity(structureDensityValues[nextIndex]); +} + +function onStructureDensityKeydown(event: KeyboardEvent) { + if (event.key === "Escape") { + structureDensityMenuOpen.value = false; + return; + } + if (event.key === "ArrowDown") { + event.preventDefault(); + if (!structureDensityMenuOpen.value) { + structureDensityMenuOpen.value = true; + return; + } + focusStructureDensityOption(1); + return; + } + if (event.key === "ArrowUp") { + event.preventDefault(); + if (!structureDensityMenuOpen.value) { + structureDensityMenuOpen.value = true; + return; + } + focusStructureDensityOption(-1); + return; + } + if (event.key === "Enter" || event.key === " ") { + event.preventDefault(); + structureDensityMenuOpen.value = !structureDensityMenuOpen.value; + } +} + +function onStructureDensityDocumentPointerdown(event: PointerEvent) { + if (!structureDensityMenuOpen.value) return; + const target = event.target; + if (target instanceof Node && structureDensityMenuRef.value?.contains(target)) return; + structureDensityMenuOpen.value = false; +} + +function persistStructureDensity(density = localStructureDensity.value) { + if (settingsStore.editorSettings.structureEditorDensity === density) return; + settingsStore.updateEditorSettings({ structureEditorDensity: density }); } const initialDensityMetric = metricsForDensity(structureDensity.value); @@ -330,7 +397,16 @@ const colResizing = ref<{ col: number; startX: number; startW: number } | null>( const indexColWidths = ref([...initialDensityMetric.indexes]); const resizing = ref<{ col: number; startX: number; startW: number } | null>(null); -watch(structureDensity, (density, previousDensity) => { +watch( + structureDensity, + (density) => { + if (density === localStructureDensity.value) return; + localStructureDensity.value = density; + }, + { flush: "sync" }, +); + +watch(localStructureDensity, (density, previousDensity) => { if (density === previousDensity) return; applyStructureDensityWidths(density); }); @@ -508,11 +584,62 @@ function isManticoreJsonColumn(column: EditableStructureColumn): boolean { } let sqlPreviewRequestId = 0; +let structureLoadRequestId = 0; +let sqlPreviewDebounceTimer: ReturnType | undefined; +let deferredSqlPreviewRefresh = false; let keydownListenerRegistered = false; let skipNextRefreshVersion = false; +function hasPendingStructureChanges(): boolean { + if (isCreateMode.value) { + return !!newTableName.value.trim() || !!tableComment.value.trim() || columns.value.length > 0 || indexes.value.length > 0 || foreignKeys.value.length > 0 || triggers.value.length > 0; + } + const scope = captureStructureRefreshScope(); + return scope.columns || scope.indexes || scope.foreignKeys || scope.triggers || scope.tableComment; +} + +function clearSqlPreviewState() { + if (sqlPreviewDebounceTimer) { + clearTimeout(sqlPreviewDebounceTimer); + sqlPreviewDebounceTimer = undefined; + } + sqlPreviewRequestId++; + deferredSqlPreviewRefresh = false; + sqlPreviewLoading.value = false; + pendingStatements.value = []; + warnings.value = []; +} + +function scheduleSqlPreviewRefresh() { + if (!hasPendingStructureChanges()) { + clearSqlPreviewState(); + return; + } + if (!isCreateMode.value && secondaryMetadataLoading.value) { + if (sqlPreviewDebounceTimer) { + clearTimeout(sqlPreviewDebounceTimer); + sqlPreviewDebounceTimer = undefined; + } + deferredSqlPreviewRefresh = true; + sqlPreviewLoading.value = true; + return; + } + deferredSqlPreviewRefresh = false; + if (sqlPreviewDebounceTimer) clearTimeout(sqlPreviewDebounceTimer); + sqlPreviewDebounceTimer = setTimeout(() => { + sqlPreviewDebounceTimer = undefined; + void refreshSqlPreview(); + }, 80); +} + async function refreshSqlPreview() { const requestId = ++sqlPreviewRequestId; + if (!hasPendingStructureChanges()) { + pendingStatements.value = []; + warnings.value = []; + sqlPreviewLoading.value = false; + return; + } sqlPreviewLoading.value = true; const options = { databaseType: databaseType.value, @@ -539,7 +666,9 @@ async function refreshSqlPreview() { } } -const canApply = computed(() => !loading.value && !saving.value && !postSaveRefreshing.value && !sqlPreviewLoading.value && pendingStatements.value.length > 0 && warnings.value.length === 0 && !!props.connectionId && (isCreateMode.value ? !!newTableName.value.trim() : !!props.tableName)); +const canApply = computed( + () => !loading.value && !saving.value && !postSaveRefreshing.value && !secondaryMetadataLoading.value && !sqlPreviewLoading.value && pendingStatements.value.length > 0 && warnings.value.length === 0 && !!props.connectionId && (isCreateMode.value ? !!newTableName.value.trim() : !!props.tableName), +); function resetState() { activeTab.value = "columns"; @@ -547,6 +676,9 @@ function resetState() { saving.value = false; postSaveRefreshing.value = false; sqlPreviewLoading.value = false; + indexesLoading.value = false; + foreignKeysLoading.value = false; + triggersLoading.value = false; errorMessage.value = ""; columns.value = []; indexes.value = []; @@ -561,17 +693,51 @@ function resetState() { originalTableComment.value = ""; } -async function loadStructure(silent = false, scope: StructureRefreshScope = FULL_STRUCTURE_REFRESH_SCOPE, showErrors = true) { - if (!props.connectionId || !props.database || !props.tableName) return; - if (!silent) loading.value = true; - errorMessage.value = ""; +function setSecondaryMetadataLoading(scope: StructureRefreshScope, value: boolean) { + if (scope.indexes && tableMetadataCapabilities.value.indexes) indexesLoading.value = value; + if (scope.foreignKeys && tableMetadataCapabilities.value.foreignKeys) foreignKeysLoading.value = value; + if (scope.triggers && tableMetadataCapabilities.value.triggers) triggersLoading.value = value; +} + +async function fetchTableCommentValue(connectionId: string, database: string, schema: string, tableName: string): Promise { try { - await store.ensureConnected(props.connectionId); - if (scope.columns) { - let nextColumns = await api.getColumns(props.connectionId, props.database, metadataSchema.value, props.tableName); + return (await api.getTableComment(connectionId, database, schema, tableName)) || ""; + } catch { + try { + const tables = await api.listTables(connectionId, database, schema); + const table = tables.find((t) => t.name.toLowerCase() === tableName.toLowerCase() && t.table_type !== "VIEW"); + return table?.comment || ""; + } catch { + return undefined; + } + } +} + +async function loadStructure(silent = false, scope: StructureRefreshScope = FULL_STRUCTURE_REFRESH_SCOPE, showErrors = true, options: { blockSecondaryMetadata?: boolean } = {}) { + const connectionId = props.connectionId; + const database = props.database; + const schema = metadataSchema.value; + const tableName = props.tableName; + if (!connectionId || !database || !tableName) return; + const requestId = ++structureLoadRequestId; + if (!silent) loading.value = true; + setSecondaryMetadataLoading(scope, true); + errorMessage.value = ""; + let secondaryMetadataScheduled = false; + try { + await store.ensureConnected(connectionId); + + const columnsPromise = scope.columns ? api.getColumns(connectionId, database, schema, tableName) : Promise.resolve(undefined); + const indexesPromise = scope.indexes ? (tableMetadataCapabilities.value.indexes ? api.listIndexes(connectionId, database, schema, tableName).catch(() => []) : Promise.resolve([])) : Promise.resolve(undefined); + const foreignKeysPromise = scope.foreignKeys ? (tableMetadataCapabilities.value.foreignKeys ? api.listForeignKeys(connectionId, database, schema, tableName).catch(() => []) : Promise.resolve([])) : Promise.resolve(undefined); + const triggersPromise = scope.triggers ? (tableMetadataCapabilities.value.triggers ? api.listTriggers(connectionId, database, schema, tableName).catch(() => []) : Promise.resolve([])) : Promise.resolve(undefined); + const tableCommentPromise = scope.tableComment && structureCapabilities.value.comment ? fetchTableCommentValue(connectionId, database, schema, tableName) : Promise.resolve(undefined); + + let nextColumns = await columnsPromise; + if (nextColumns) { if (databaseType.value === "manticoresearch" && tableMetadataCapabilities.value.ddl) { try { - const ddl = await api.getTableDdl(props.connectionId, props.database, metadataSchema.value, props.tableName); + const ddl = await api.getTableDdl(connectionId, database, schema, tableName); ddlContent.value = ddl; ddlFetched.value = true; nextColumns = applyManticoreDdlColumnExtras(nextColumns, ddl); @@ -582,24 +748,29 @@ async function loadStructure(silent = false, scope: StructureRefreshScope = FULL columns.value = createColumnDrafts(nextColumns, databaseType.value); } - const [nextIndexes, nextForeignKeys, nextTriggers] = await Promise.all([ - scope.indexes ? (tableMetadataCapabilities.value.indexes ? api.listIndexes(props.connectionId, props.database, metadataSchema.value, props.tableName).catch(() => []) : Promise.resolve([])) : Promise.resolve(undefined), - scope.foreignKeys ? (tableMetadataCapabilities.value.foreignKeys ? api.listForeignKeys(props.connectionId, props.database, metadataSchema.value, props.tableName).catch(() => []) : Promise.resolve([])) : Promise.resolve(undefined), - scope.triggers ? (tableMetadataCapabilities.value.triggers ? api.listTriggers(props.connectionId, props.database, metadataSchema.value, props.tableName).catch(() => []) : Promise.resolve([])) : Promise.resolve(undefined), - ]); - if (nextIndexes) indexes.value = createIndexDrafts(nextIndexes); - if (nextForeignKeys) foreignKeys.value = createForeignKeyDrafts(nextForeignKeys); - if (nextTriggers) triggers.value = createTriggerDrafts(nextTriggers); + const nextTableComment = await tableCommentPromise; + if (nextTableComment !== undefined) { + originalTableComment.value = nextTableComment; + tableComment.value = nextTableComment; + } + const applySecondaryMetadata = async () => { + const [nextIndexes, nextForeignKeys, nextTriggers] = await Promise.all([indexesPromise, foreignKeysPromise, triggersPromise]); + if (requestId !== structureLoadRequestId) return; + if (nextIndexes) indexes.value = createIndexDrafts(nextIndexes); + if (nextForeignKeys) foreignKeys.value = createForeignKeyDrafts(nextForeignKeys); + if (nextTriggers) triggers.value = createTriggerDrafts(nextTriggers); + }; - if (scope.tableComment) { - try { - const tables = await api.listTables(props.connectionId, props.database, metadataSchema.value); - const table = tables.find((t) => t.name.toLowerCase() === props.tableName!.toLowerCase() && t.table_type !== "VIEW"); - originalTableComment.value = table?.comment || ""; - tableComment.value = table?.comment || ""; - } catch { - /* ignore — table comment is optional */ - } + secondaryMetadataScheduled = true; + const secondaryMetadataPromise = applySecondaryMetadata() + .catch((error) => { + console.warn("[DBX][structure-editor:secondary-metadata-failed]", error); + }) + .finally(() => { + if (requestId === structureLoadRequestId) setSecondaryMetadataLoading(scope, false); + }); + if (options.blockSecondaryMetadata) { + await secondaryMetadataPromise; } } catch (e: any) { if (showErrors) { @@ -608,13 +779,16 @@ async function loadStructure(silent = false, scope: StructureRefreshScope = FULL console.warn("[DBX][structure-editor:refresh-failed]", e); } } finally { + if (!secondaryMetadataScheduled && requestId === structureLoadRequestId) { + setSecondaryMetadataLoading(scope, false); + } if (!silent) loading.value = false; } } async function refreshStructureAfterSave(scope: StructureRefreshScope) { try { - await loadStructure(true, scope, false); + await loadStructure(true, scope, false, { blockSecondaryMetadata: true }); } catch (e) { console.warn("[DBX][structure-editor:post-save-refresh-failed]", e); } finally { @@ -627,7 +801,7 @@ async function addColumn() { if (!canAddColumn.value) return; activeTab.value = "columns"; const dataType = databaseType.value === "manticoresearch" ? combineDataTypeForDatabase(databaseType.value, dataTypeOptions.value[0] ?? "text", getDefaultLengthForType(databaseType.value, dataTypeOptions.value[0] ?? "text")) : "varchar(255)"; - columns.value.push({ + const column: EditableStructureColumn = { id: `new:${uuid()}`, name: "", dataType, @@ -637,7 +811,8 @@ async function addColumn() { isPrimaryKey: false, extra: {}, markedForDrop: false, - }); + }; + columns.value.push(column); await nextTick(); const newRows = rootRef.value?.querySelectorAll('[data-new-column-row="true"]'); const row = newRows?.[newRows.length - 1]; @@ -652,6 +827,8 @@ function removeNewColumn(column: EditableStructureColumn) { } function canMoveColumn(index: number, direction: -1 | 1): boolean { + if (loading.value || saving.value) return false; + if (!Number.isInteger(index) || (direction !== -1 && direction !== 1)) return false; const targetIndex = index + direction; if (targetIndex < 0 || targetIndex >= columns.value.length) return false; if (columns.value[index]?.markedForDrop || columns.value[targetIndex]?.markedForDrop) return false; @@ -666,9 +843,11 @@ const canShowColumnMoveControls = computed(() => isCreateMode.value || structure function moveColumn(index: number, direction: -1 | 1) { if (!canMoveColumn(index, direction)) return; const targetIndex = index + direction; - const [column] = columns.value.splice(index, 1); + const nextColumns = [...columns.value]; + const [column] = nextColumns.splice(index, 1); if (!column) return; - columns.value.splice(targetIndex, 0, column); + nextColumns.splice(targetIndex, 0, column); + columns.value = nextColumns; } function toggleDropColumn(column: EditableStructureColumn) { @@ -719,7 +898,7 @@ function isManticoreColumnPropertyDisabled(column: EditableStructureColumn): boo } function addIndex() { - if (!structureCapabilities.value.createIndex) return; + if (!structureCapabilities.value.createIndex || indexesLoading.value) return; activeTab.value = "indexes"; indexes.value.push({ id: `new:${uuid()}`, @@ -809,6 +988,7 @@ function toggleDropIndex(index: EditableStructureIndex) { } function canEditIndexDraft(index: EditableStructureIndex): boolean { + if (indexesLoading.value) return false; if (index.markedForDrop || index.isPrimary) return false; if (!index.original) return structureCapabilities.value.createIndex; return structureCapabilities.value.rebuildIndex && structureCapabilities.value.createIndex && structureCapabilities.value.dropIndex; @@ -823,6 +1003,7 @@ function canEditIndexComment(index: EditableStructureIndex): boolean { } function canDropIndex(index: EditableStructureIndex): boolean { + if (indexesLoading.value) return false; return !!index.original && !index.isPrimary && structureCapabilities.value.dropIndex; } @@ -846,7 +1027,7 @@ function generatedForeignKeyName(column = ""): string { } function addForeignKey() { - if (!canEditForeignKeys.value) return; + if (!canEditForeignKeys.value || foreignKeysLoading.value) return; activeTab.value = "foreignKeys"; foreignKeys.value.push({ id: `new:${uuid()}`, @@ -866,16 +1047,16 @@ function removeNewForeignKey(foreignKey: EditableStructureForeignKey) { } function toggleDropForeignKey(foreignKey: EditableStructureForeignKey) { - if (!foreignKey.original) return; + if (foreignKeysLoading.value || !foreignKey.original) return; foreignKey.markedForDrop = !foreignKey.markedForDrop; } function canEditForeignKeyDraft(foreignKey: EditableStructureForeignKey): boolean { - return canEditForeignKeys.value && !foreignKey.markedForDrop; + return !foreignKeysLoading.value && canEditForeignKeys.value && !foreignKey.markedForDrop; } function addTrigger() { - if (!canEditMysqlTriggers.value) return; + if (!canEditMysqlTriggers.value || triggersLoading.value) return; activeTab.value = "triggers"; triggers.value.push({ id: `new:${uuid()}`, @@ -892,12 +1073,12 @@ function removeNewTrigger(trigger: EditableStructureTrigger) { } function toggleDropTrigger(trigger: EditableStructureTrigger) { - if (!trigger.original) return; + if (triggersLoading.value || !trigger.original) return; trigger.markedForDrop = !trigger.markedForDrop; } function canEditTriggerDraft(trigger: EditableStructureTrigger): boolean { - return canEditMysqlTriggers.value && !trigger.markedForDrop; + return !triggersLoading.value && canEditMysqlTriggers.value && !trigger.markedForDrop; } function primarySqlOperation(sql: string): string { @@ -1012,12 +1193,14 @@ function registerStructureEditorShortcuts() { if (keydownListenerRegistered) return; keydownListenerRegistered = true; window.addEventListener("keydown", onStructureEditorKeydown); + document.addEventListener("pointerdown", onStructureDensityDocumentPointerdown, true); } function unregisterStructureEditorShortcuts() { if (!keydownListenerRegistered) return; keydownListenerRegistered = false; window.removeEventListener("keydown", onStructureEditorKeydown); + document.removeEventListener("pointerdown", onStructureDensityDocumentPointerdown, true); } onMounted(() => { @@ -1033,6 +1216,8 @@ onActivated(() => { onDeactivated(unregisterStructureEditorShortcuts); onBeforeUnmount(() => { unregisterStructureEditorShortcuts(); + clearSqlPreviewState(); + persistStructureDensity(); }); function firstStructureMetadataTab(capabilities = tableMetadataCapabilities.value) { @@ -1057,11 +1242,16 @@ watch(tableMetadataCapabilities, (capabilities) => { watch( [isCreateMode, databaseType, () => props.schema, () => props.tableName, newTableName, tableComment, columns, indexes, foreignKeys, triggers], () => { - void refreshSqlPreview(); + scheduleSqlPreviewRefresh(); }, { deep: true, immediate: true }, ); +watch(secondaryMetadataLoading, (value) => { + if (value || !deferredSqlPreviewRefresh) return; + scheduleSqlPreviewRefresh(); +}); + watch([() => props.tableName, newTableName], () => { for (const index of indexes.value) { refreshAutoIndexName(index); @@ -1085,7 +1275,7 @@ watch(activeTab, (tab) => {