mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-21 08:13:34 +00:00
fix(grid): honor extractor database-name option when copying SQL
This commit is contained in:
@@ -211,9 +211,7 @@ function save() {
|
||||
<label v-if="draftExtractor === 'sql-inserts'" class="flex items-center gap-2 text-sm"
|
||||
><input type="checkbox" :checked="draftOptions.sql.excludePrimaryKeysFromInsert" @change="updateSql('excludePrimaryKeysFromInsert', ($event.target as HTMLInputElement).checked)" />{{ t("grid.copyExtractorExcludePrimaryKeys") }}</label
|
||||
>
|
||||
<label v-if="draftExtractor === 'sql-inserts'" class="flex items-center gap-2 text-sm"
|
||||
><input type="checkbox" :checked="draftOptions.sql.includeDatabaseName" @change="updateSql('includeDatabaseName', ($event.target as HTMLInputElement).checked)" />{{ t("grid.copyExtractorIncludeDatabaseName") }}</label
|
||||
>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" :checked="draftOptions.sql.includeDatabaseName" @change="updateSql('includeDatabaseName', ($event.target as HTMLInputElement).checked)" />{{ t("grid.copyExtractorIncludeDatabaseName") }}</label>
|
||||
<div v-if="draftExtractor === 'sql-inserts'" class="space-y-1.5">
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" :checked="draftOptions.sql.quoteIdentifiers" @change="updateSql('quoteIdentifiers', ($event.target as HTMLInputElement).checked)" />{{ t("grid.copyExtractorQuoteIdentifiers") }}</label>
|
||||
<Label>{{ t("grid.copyExtractorTemporalFormat") }}</Label>
|
||||
|
||||
@@ -103,6 +103,20 @@ describe("extractor draft preview", () => {
|
||||
expect(host.querySelector("pre")?.textContent).toBe("initial");
|
||||
});
|
||||
|
||||
it("offers the database-name option for SQL updates as well (#11195)", async () => {
|
||||
const { props, host, save } = mountDialog();
|
||||
props.preference = "sql-updates";
|
||||
props.items = [{ value: "sql-updates", label: "UPDATE" }];
|
||||
props.open = true;
|
||||
await advancePreview();
|
||||
|
||||
// 勾选后保存应带上 includeDatabaseName(复制为 UPDATE 也支持带库名/模式名)
|
||||
await toggle(host, "copyExtractorIncludeDatabaseName");
|
||||
const button = Array.from(host.querySelectorAll("button")).find((item) => item.textContent?.includes("common.save"))!;
|
||||
button.click();
|
||||
expect(save).toHaveBeenCalledWith(expect.objectContaining({ options: expect.objectContaining({ sql: expect.objectContaining({ includeDatabaseName: true }) }) }));
|
||||
});
|
||||
|
||||
it("previews unsaved quote and temporal options without mutating saved settings", async () => {
|
||||
const { props, host, preview, save } = mountDialog();
|
||||
props.open = true;
|
||||
|
||||
@@ -1289,6 +1289,22 @@ describe("useDataGridExport prepared row statements", () => {
|
||||
expect(vi.mocked(extractDataGridSelection).mock.lastCall?.[0].options.sql).toEqual(saved.sql);
|
||||
});
|
||||
|
||||
it("follows the extractor option for the copied SQL table qualifier (#11195)", async () => {
|
||||
const tableMeta: DataGridTableMeta = { ...editableTable, schema: "SYSDBA" };
|
||||
const matrix: CellSelectionMatrix = { rowIndexes: [0], columnIndexes: [0, 1], columns: ["id", "name"], rows: [[1, "Ada"]] };
|
||||
vi.mocked(extractDataGridSelection).mockResolvedValue({ text: "copied", mimeType: "text/plain", fileExtension: "sql", rowCount: 1, columnCount: 2 });
|
||||
const withDatabaseName = { ...DEFAULT_DATA_GRID_EXTRACTOR_OPTIONS, sql: { ...DEFAULT_DATA_GRID_EXTRACTOR_OPTIONS.sql, includeDatabaseName: true } };
|
||||
|
||||
const enabled = createExportState(tableMeta, ["id", "name"], matrix, [1, "Ada"], undefined, matrix.rows, [], withDatabaseName, false, undefined, false, undefined, undefined, "dameng");
|
||||
await enabled.copyWithExtractor("sql-inserts");
|
||||
expect(vi.mocked(extractDataGridSelection).mock.lastCall?.[0].tableMeta).toMatchObject({ schema: "SYSDBA", tableName: "users" });
|
||||
|
||||
// 未勾选(默认)时保持既有行为:把可选的库名/模式名前缀交给后端省略
|
||||
const disabled = createExportState(tableMeta, ["id", "name"], matrix, [1, "Ada"], undefined, matrix.rows, [], DEFAULT_DATA_GRID_EXTRACTOR_OPTIONS, false, undefined, false, undefined, undefined, "dameng");
|
||||
await disabled.copyWithExtractor("sql-inserts");
|
||||
expect(vi.mocked(extractDataGridSelection).mock.lastCall?.[0].tableMeta?.schema).toBeUndefined();
|
||||
});
|
||||
|
||||
it("does not report success when an extractor export save is cancelled", async () => {
|
||||
const matrix: CellSelectionMatrix = { rowIndexes: [0], columnIndexes: [1], columns: ["name"], rows: [["Ada"]] };
|
||||
vi.mocked(extractDataGridSelection).mockResolvedValueOnce({ text: '[{"name":"Ada"}]', mimeType: "application/json", fileExtension: "json", rowCount: 1, columnCount: 1 });
|
||||
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
import { computed, ref } from "vue";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { useDataGridExtractor } from "@/composables/useDataGridExtractor";
|
||||
import { DEFAULT_DATA_GRID_EXTRACTOR_OPTIONS, type DataGridExtractorOptions } from "@/lib/dataGrid/dataGridCopyExtractor";
|
||||
import type { DataGridTableMeta } from "@/lib/dataGrid/dataGridSql";
|
||||
import type { DatabaseType } from "@/types/database";
|
||||
|
||||
const mocks = vi.hoisted(() => ({ extract: vi.fn() }));
|
||||
vi.mock("@/lib/backend/api", () => ({ extractDataGridSelection: mocks.extract }));
|
||||
vi.mock("@/composables/useToast", () => ({ useToast: () => ({ toast: vi.fn() }) }));
|
||||
vi.mock("vue-i18n", () => ({ useI18n: () => ({ t: (key: string) => key }) }));
|
||||
|
||||
function createState(databaseType: DatabaseType, tableMeta: DataGridTableMeta, extractorOptions?: DataGridExtractorOptions, includeDatabaseName = false) {
|
||||
const items = [{ id: 1, data: [1, "Ada"], isDraft: false }];
|
||||
return useDataGridExtractor({
|
||||
columns: computed(() => ["id", "name"]),
|
||||
allColumns: computed(() => ["id", "name"]),
|
||||
displayItems: computed(() => items),
|
||||
allDisplayItems: computed(() => items),
|
||||
allSourceColumns: computed(() => undefined),
|
||||
visibleColumnIndexes: computed(() => [0, 1]),
|
||||
columnTypes: computed(() => undefined),
|
||||
extractorOptions: computed(() => extractorOptions ?? DEFAULT_DATA_GRID_EXTRACTOR_OPTIONS),
|
||||
databaseType: computed(() => databaseType),
|
||||
identifierQuote: computed(() => undefined),
|
||||
tableMeta: computed(() => tableMeta),
|
||||
includeDatabaseName: computed(() => includeDatabaseName),
|
||||
hasCellSelection: computed(() => false),
|
||||
selectedCells: computed(() => ({ columns: [], rows: [] })),
|
||||
selectedCellMatrix: computed(() => null),
|
||||
hasRowSelection: computed(() => true),
|
||||
hasColumnSelection: computed(() => false),
|
||||
selectedRowIds: ref(new Set<number>([1])),
|
||||
contextCell: ref(null),
|
||||
contextSelectionIsSynthetic: ref(false),
|
||||
copyText: vi.fn(async () => true),
|
||||
canCopySqlInsert: () => true,
|
||||
buildMongoInsert: vi.fn(async () => undefined),
|
||||
});
|
||||
}
|
||||
|
||||
function qualifiedMeta(schema?: string, database?: string): DataGridTableMeta {
|
||||
return {
|
||||
tableName: "users",
|
||||
schema,
|
||||
database,
|
||||
primaryKeys: ["id"],
|
||||
columns: [
|
||||
{ name: "id", data_type: "int" },
|
||||
{ name: "name", data_type: "varchar" },
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
async function capturedRequest(databaseType: DatabaseType, tableMeta: DataGridTableMeta, extractorOptions?: DataGridExtractorOptions, includeDatabaseName = false) {
|
||||
const state = createState(databaseType, tableMeta, extractorOptions, includeDatabaseName);
|
||||
const extraction = await state.extractWithExtractor("sql-inserts");
|
||||
expect(extraction).not.toBeNull();
|
||||
return mocks.extract.mock.calls[mocks.extract.mock.calls.length - 1]![0]!;
|
||||
}
|
||||
|
||||
describe("useDataGridExtractor includeDatabaseName payload", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
mocks.extract.mockResolvedValue({ text: "INSERT INTO users VALUES (1, 'Ada');", rowCount: 1 });
|
||||
});
|
||||
|
||||
it.each([
|
||||
["sqlserver", "dbo", "app"],
|
||||
["snowflake", "PUBLIC", undefined],
|
||||
] as const)("keeps the namespace flag true for %s even when the option is off", async (databaseType, schema, database) => {
|
||||
const request = await capturedRequest(databaseType, qualifiedMeta(schema, database));
|
||||
expect(request.tableMeta.schema).toBe(schema);
|
||||
expect(request.options.sql.includeDatabaseName).toBe(true);
|
||||
});
|
||||
|
||||
it("strips optional qualifiers and keeps the flag off for non schema-qualified dialects", async () => {
|
||||
const request = await capturedRequest("mysql", qualifiedMeta(undefined, "mydb"));
|
||||
expect(request.tableMeta.database).toBeUndefined();
|
||||
expect(request.tableMeta.schema).toBeUndefined();
|
||||
expect(request.options.sql.includeDatabaseName).toBe(false);
|
||||
});
|
||||
|
||||
it("preserves an explicit opt-in for non schema-qualified dialects", async () => {
|
||||
const request = await capturedRequest("mysql", qualifiedMeta(undefined, "mydb"), { ...DEFAULT_DATA_GRID_EXTRACTOR_OPTIONS, sql: { ...DEFAULT_DATA_GRID_EXTRACTOR_OPTIONS.sql, includeDatabaseName: true } });
|
||||
expect(request.tableMeta.database).toBe("mydb");
|
||||
expect(request.options.sql.includeDatabaseName).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -230,6 +230,10 @@ export function useDataGridExtractor(options: UseDataGridExtractorOptions) {
|
||||
const presentBinaryText = descriptor.category !== "sql";
|
||||
const rawRows = sourceRows.map((row) => requiredSourceIndexes.map((sourceIndex) => row[sourceIndex]));
|
||||
const rows = rawRows.map((row) => row.map((value, index) => extractorCellValue(value, columnTypes[index], normalizeValues, keepUnsafeJsonText, presentBinaryText, index)));
|
||||
// 「包含数据库名称」:复制/导出 SQL 时,提取器自身的勾选框与编辑器全局设置
|
||||
// (`generateSqlIncludeDatabaseName`)任一开启都保留库名/模式名;后者还会影响
|
||||
// 保存 SQL、侧栏导出等其它路径,因此这里取“或”,不覆盖全局偏好。
|
||||
const extractorOptionValues = normalizeDataGridExtractorOptions(extractorOptions);
|
||||
const tableMeta =
|
||||
descriptor.category === "sql"
|
||||
? tableMetaWithoutOptionalDatabaseQualifier(
|
||||
@@ -238,7 +242,7 @@ export function useDataGridExtractor(options: UseDataGridExtractorOptions) {
|
||||
columns.map((column) => column.sourceName ?? column.displayName),
|
||||
),
|
||||
options.databaseType.value,
|
||||
options.includeDatabaseName?.value,
|
||||
options.includeDatabaseName?.value === true || extractorOptionValues.sql.includeDatabaseName === true,
|
||||
)
|
||||
: undefined;
|
||||
const request: DataGridExtractRequest = {
|
||||
@@ -251,7 +255,12 @@ export function useDataGridExtractor(options: UseDataGridExtractorOptions) {
|
||||
selectedColumnIndexes,
|
||||
rows,
|
||||
selectionKind,
|
||||
options: normalizeDataGridExtractorOptions(extractorOptions),
|
||||
// For dialects whose tableMeta keeps the schema qualifier regardless of
|
||||
// the flag (DATABASE_SCHEMA_QUALIFIED_TYPES), the backend strips every
|
||||
// namespace prefix when include_database_name=false, which would regress
|
||||
// the default output to a bare table name; keep the flag aligned with
|
||||
// the qualified tableMeta we intentionally preserved.
|
||||
options: tableMeta && (tableMeta.schema !== undefined || tableMeta.database !== undefined) ? { ...extractorOptionValues, sql: { ...extractorOptionValues.sql, includeDatabaseName: true } } : extractorOptionValues,
|
||||
};
|
||||
requestSources.set(request, {
|
||||
rowIds: sourceRowIds,
|
||||
|
||||
@@ -12,11 +12,13 @@ describe("data-grid extractor options", () => {
|
||||
expect(normalizeDataGridExtractorOptions({ sql: { quoteIdentifiers: "false", temporalFormat: "custom" } }).sql).toMatchObject({ quoteIdentifiers: true, temporalFormat: "native" });
|
||||
});
|
||||
|
||||
it("keeps database qualification for legacy options and persists explicit opt-out", () => {
|
||||
expect(normalizeDataGridExtractorOptions({ sql: {} }).sql.includeDatabaseName).toBe(true);
|
||||
const configured = normalizeDataGridExtractorOptions({ sql: { includeDatabaseName: false } });
|
||||
expect(normalizeDataGridExtractorOptions(JSON.parse(JSON.stringify(configured))).sql.includeDatabaseName).toBe(false);
|
||||
expect(normalizeDataGridExtractorOptions({ sql: { includeDatabaseName: "false" } }).sql.includeDatabaseName).toBe(true);
|
||||
it("defaults to dropping database qualification and keeps an explicit opt-in", () => {
|
||||
expect(DEFAULT_DATA_GRID_EXTRACTOR_OPTIONS.sql.includeDatabaseName).toBe(false);
|
||||
expect(normalizeDataGridExtractorOptions({ sql: {} }).sql.includeDatabaseName).toBe(false);
|
||||
const configured = normalizeDataGridExtractorOptions({ sql: { includeDatabaseName: true } });
|
||||
expect(configured.sql.includeDatabaseName).toBe(true);
|
||||
expect(normalizeDataGridExtractorOptions(JSON.parse(JSON.stringify(configured))).sql.includeDatabaseName).toBe(true);
|
||||
expect(normalizeDataGridExtractorOptions({ sql: { includeDatabaseName: "true" } }).sql.includeDatabaseName).toBe(false);
|
||||
});
|
||||
|
||||
it("defaults DSV NULL output to an empty spreadsheet field", () => {
|
||||
|
||||
@@ -239,6 +239,20 @@ describe("tableMetaWithoutOptionalDatabaseQualifier — copy extractors (#9326)"
|
||||
expect(tableMetaWithoutOptionalDatabaseQualifier({ schema: "public", tableName: "users" }, "postgres", false)).toEqual({ schema: undefined, tableName: "users" });
|
||||
});
|
||||
|
||||
it("covers the copy-SQL dialects reported in #11195", () => {
|
||||
// Dameng exposes schemas as databases; a copied INSERT/UPDATE must still be
|
||||
// able to opt into the schema prefix, so the qualifier only drops when the
|
||||
// extractor option is off.
|
||||
const damengMeta = { schema: "SYSDBA", tableName: "PEOPLE" };
|
||||
expect(tableMetaWithoutOptionalDatabaseQualifier(damengMeta, "dameng", false)).toEqual({ schema: undefined, tableName: "PEOPLE" });
|
||||
expect(tableMetaWithoutOptionalDatabaseQualifier(damengMeta, "dameng", true)).toBe(damengMeta);
|
||||
// MySQL family and ClickHouse address tables as database.table.
|
||||
const clickhouseMeta = { database: "analytics", tableName: "events" };
|
||||
expect(tableMetaWithoutOptionalDatabaseQualifier(clickhouseMeta, "clickhouse", false)).toEqual({ database: undefined, tableName: "events" });
|
||||
expect(tableMetaWithoutOptionalDatabaseQualifier(clickhouseMeta, "clickhouse", true)).toBe(clickhouseMeta);
|
||||
expect(tableMetaWithoutOptionalDatabaseQualifier({ database: "appdb", tableName: "people" }, "goldendb", false)).toEqual({ database: undefined, tableName: "people" });
|
||||
});
|
||||
|
||||
it("returns undefined tableMeta unchanged", () => {
|
||||
expect(tableMetaWithoutOptionalDatabaseQualifier(undefined, "mysql", false)).toBeUndefined();
|
||||
});
|
||||
|
||||
@@ -29,7 +29,9 @@ export const DATA_GRID_DEFAULT_COPY_PREFERENCES: readonly DataGridCopyPreference
|
||||
];
|
||||
|
||||
export const DATA_GRID_EXTRACTOR_CONTRACT_VERSION = 1 as const;
|
||||
export const DATA_GRID_EXTRACTOR_OPTIONS_MIGRATION_VERSION = 1 as const;
|
||||
// v2:复制/导出 SQL 的「包含数据库名称」改为由提取器自身的勾选框决定,默认关闭(不带库名/模式名),
|
||||
// 历史持久化的 `true` 由 settingsStore 的迁移归位到新默认。
|
||||
export const DATA_GRID_EXTRACTOR_OPTIONS_MIGRATION_VERSION = 2 as const;
|
||||
|
||||
export const DATA_GRID_COPY_EXTRACTOR_DESCRIPTORS: Record<DataGridCopyExtractorId, { category: DataGridExtractorCategory; separatorBefore?: boolean }> = {
|
||||
raw: { category: "raw" },
|
||||
@@ -151,7 +153,7 @@ export const DEFAULT_DATA_GRID_EXTRACTOR_OPTIONS: DataGridExtractorOptions = {
|
||||
skipGeneratedColumns: true,
|
||||
insertMode: "merged",
|
||||
excludePrimaryKeysFromInsert: false,
|
||||
includeDatabaseName: true,
|
||||
includeDatabaseName: false,
|
||||
quoteIdentifiers: true,
|
||||
temporalFormat: "native",
|
||||
},
|
||||
@@ -184,7 +186,7 @@ export function normalizeDataGridExtractorOptions(value: unknown): DataGridExtra
|
||||
skipGeneratedColumns: sql.skipGeneratedColumns !== false,
|
||||
insertMode: sql.insertMode === "row-by-row" ? "row-by-row" : "merged",
|
||||
excludePrimaryKeysFromInsert: sql.excludePrimaryKeysFromInsert === true,
|
||||
includeDatabaseName: sql.includeDatabaseName !== false,
|
||||
includeDatabaseName: sql.includeDatabaseName === true,
|
||||
quoteIdentifiers: sql.quoteIdentifiers !== false,
|
||||
temporalFormat: sql.temporalFormat === "string" ? "string" : "native",
|
||||
},
|
||||
|
||||
@@ -611,6 +611,23 @@ describe("normalizeEditorSettings", () => {
|
||||
expect(configured.dataGridExtractorOptions.dsv.nullText).toBe("NULL");
|
||||
});
|
||||
|
||||
it("resets the copy extractor database-name opt-in once when migrating to v2", () => {
|
||||
const legacy = normalizeEditorSettings({
|
||||
dataGridExtractorOptionsMigrationVersion: 1,
|
||||
dataGridExtractorOptions: { sql: { includeDatabaseName: true } },
|
||||
});
|
||||
// 历史持久化的「包含数据库名称」归位到新默认:复制/导出 SQL 默认不带库名/模式名
|
||||
expect(legacy.dataGridExtractorOptions.sql.includeDatabaseName).toBe(false);
|
||||
expect(legacy.dataGridExtractorOptionsMigrationVersion).toBe(DATA_GRID_EXTRACTOR_OPTIONS_MIGRATION_VERSION);
|
||||
|
||||
const current = normalizeEditorSettings({
|
||||
dataGridExtractorOptionsMigrationVersion: DATA_GRID_EXTRACTOR_OPTIONS_MIGRATION_VERSION,
|
||||
dataGridExtractorOptions: { sql: { includeDatabaseName: true } },
|
||||
});
|
||||
// 迁移之后用户的显式勾选必须被保留
|
||||
expect(current.dataGridExtractorOptions.sql.includeDatabaseName).toBe(true);
|
||||
});
|
||||
|
||||
it("defaults retained result runs to tiled tabs and preserves list mode", () => {
|
||||
expect(normalizeEditorSettings({}).resultRunDisplayMode).toBe("tabs");
|
||||
expect(normalizeEditorSettings({ resultRunDisplayMode: "list" }).resultRunDisplayMode).toBe("list");
|
||||
|
||||
@@ -1783,7 +1783,14 @@ export function normalizeEditorSettings(settings: Partial<EditorSettings>, exist
|
||||
const savedExtractorMigrationVersion = settings.dataGridExtractorOptionsMigrationVersion;
|
||||
const normalizedExtractorOptions = normalizeDataGridExtractorOptions(settings.dataGridExtractorOptions);
|
||||
const isLegacyExtractorOptions = typeof savedExtractorMigrationVersion !== "number" || savedExtractorMigrationVersion < DATA_GRID_EXTRACTOR_OPTIONS_MIGRATION_VERSION;
|
||||
const dataGridExtractorOptions = isLegacyExtractorOptions && normalizedExtractorOptions.dsv.nullText === "NULL" ? { ...normalizedExtractorOptions, dsv: { ...normalizedExtractorOptions.dsv, nullText: "" } } : normalizedExtractorOptions;
|
||||
const dataGridExtractorOptions = (() => {
|
||||
if (!isLegacyExtractorOptions) return normalizedExtractorOptions;
|
||||
// v1:旧的 "NULL" 文本迁移为空串
|
||||
const nullTextMigrated = normalizedExtractorOptions.dsv.nullText === "NULL" ? { ...normalizedExtractorOptions, dsv: { ...normalizedExtractorOptions.dsv, nullText: "" } } : normalizedExtractorOptions;
|
||||
// v2:复制/导出 SQL 的「包含数据库名称」改为由提取器勾选框决定且默认关闭,
|
||||
// 历史持久化的 true 一并归位到新默认(想带库名/模式名的用户重新勾选即可)
|
||||
return nullTextMigrated.sql.includeDatabaseName ? { ...nullTextMigrated, sql: { ...nullTextMigrated.sql, includeDatabaseName: false } } : nullTextMigrated;
|
||||
})();
|
||||
// Preserve the explicit intent behind the legacy update controls. Disabling
|
||||
// update reminders was a full opt-out; disabling automatic downloads only
|
||||
// opted out of downloading the DBX package itself.
|
||||
@@ -2302,7 +2309,12 @@ export const useSettingsStore = defineStore("settings", () => {
|
||||
const needsWelcomePageDefaultMigration = typeof savedSettings.welcomePageModeDefaultVersion !== "number" || savedSettings.welcomePageModeDefaultVersion < WELCOME_PAGE_DEFAULT_VERSION;
|
||||
const needsTabNavigationShortcutMigration = needsTabNavigationHistoryShortcutMigration(savedSettings.shortcuts);
|
||||
const savedNullText = (savedSettings.dataGridExtractorOptions as Partial<DataGridExtractorOptions> | undefined)?.dsv?.nullText;
|
||||
const needsDataGridExtractorOptionsMigration = (typeof savedSettings.dataGridExtractorOptionsMigrationVersion !== "number" || savedSettings.dataGridExtractorOptionsMigrationVersion < DATA_GRID_EXTRACTOR_OPTIONS_MIGRATION_VERSION) && savedNullText === "NULL";
|
||||
// v2 also resets a historically persisted includeDatabaseName=true, so
|
||||
// trigger the eager persist for that stale disk value even when the
|
||||
// v1 "NULL" marker is already migrated away.
|
||||
const savedSqlIncludeDatabaseName = (savedSettings.dataGridExtractorOptions as Partial<DataGridExtractorOptions> | undefined)?.sql?.includeDatabaseName;
|
||||
const needsDataGridExtractorOptionsMigration =
|
||||
(typeof savedSettings.dataGridExtractorOptionsMigrationVersion !== "number" || savedSettings.dataGridExtractorOptionsMigrationVersion < DATA_GRID_EXTRACTOR_OPTIONS_MIGRATION_VERSION) && (savedNullText === "NULL" || savedSqlIncludeDatabaseName === true);
|
||||
const savedUpdateDownloadSource = (saved as { updateDownloadSource?: unknown }).updateDownloadSource;
|
||||
if (savedUpdateDownloadSource === "atomgit" || needsExecuteModeDefaultMigration || needsWelcomePageDefaultMigration || needsTabNavigationShortcutMigration || needsSidebarBrowseObjectsMigration || needsDataGridExtractorOptionsMigration) {
|
||||
// Persist one-time migrations so removed or unsafe defaults cannot reappear.
|
||||
|
||||
Reference in New Issue
Block a user