1 parent
44dc2a88f8
commit
277386ec81
13 files changed
+513
-32
No files matched your search
+115
-6
@@ -8,12 +8,16 @@ const mocks = vi.hoisted(() => ({
|
||||
id: "structure-charset-test",
|
||||
name: "MySQL",
|
||||
db_type: "mysql",
|
||||
driver_profile: "mysql",
|
||||
driver_label: "MySQL",
|
||||
},
|
||||
ensureConnected: vi.fn(),
|
||||
executeQuery: vi.fn(),
|
||||
listDataTypes: vi.fn(),
|
||||
buildTableStructureChangeSql: vi.fn(),
|
||||
buildMysqlAutoIncrementSql: vi.fn(),
|
||||
getMysqlTableAutoIncrement: vi.fn(),
|
||||
executeBatch: vi.fn(),
|
||||
updateEditorSettings: vi.fn(),
|
||||
loadObjectDdl: vi.fn(),
|
||||
invalidateObjectDdl: vi.fn(),
|
||||
@@ -222,19 +226,25 @@ vi.mock("@/lib/backend/api", () => ({
|
||||
executeQuery: mocks.executeQuery,
|
||||
listDataTypes: mocks.listDataTypes,
|
||||
buildTableStructureChangeSql: mocks.buildTableStructureChangeSql,
|
||||
buildMysqlAutoIncrementSql: mocks.buildMysqlAutoIncrementSql,
|
||||
getMysqlTableAutoIncrement: mocks.getMysqlTableAutoIncrement,
|
||||
executeBatch: mocks.executeBatch,
|
||||
}));
|
||||
|
||||
import TableStructureEditor from "@/components/structure/TableStructureEditor.vue";
|
||||
|
||||
const mountedApps: App[] = [];
|
||||
let mountedEditor: { applyChanges: () => Promise<boolean> } | undefined;
|
||||
|
||||
function draft() {
|
||||
function draft(autoIncrement = false, counter?: { value?: string; originalValue?: string }) {
|
||||
return {
|
||||
initialized: true,
|
||||
activeTab: "columns" as const,
|
||||
newTableName: "",
|
||||
tableComment: "",
|
||||
originalTableComment: "",
|
||||
mysqlAutoIncrementValue: counter?.value,
|
||||
originalMysqlAutoIncrementValue: counter?.originalValue,
|
||||
columns: [
|
||||
{
|
||||
id: "existing:id",
|
||||
@@ -246,14 +256,14 @@ function draft() {
|
||||
isPrimaryKey: false,
|
||||
characterSet: "utf8mb3",
|
||||
collation: "utf8mb3_uca1400_ai_ci",
|
||||
extra: "",
|
||||
extra: { autoIncrement },
|
||||
original: {
|
||||
name: "id",
|
||||
data_type: "VARCHAR",
|
||||
is_nullable: true,
|
||||
column_default: null,
|
||||
is_primary_key: false,
|
||||
extra: null,
|
||||
extra: autoIncrement ? "auto_increment" : null,
|
||||
comment: null,
|
||||
},
|
||||
originalPosition: 0,
|
||||
@@ -266,7 +276,7 @@ function draft() {
|
||||
};
|
||||
}
|
||||
|
||||
async function mountEditor() {
|
||||
async function mountEditor(autoIncrement = false, counter?: { value?: string; originalValue?: string }) {
|
||||
mocks.ensureConnected.mockResolvedValue(undefined);
|
||||
mocks.listDataTypes.mockResolvedValue([]);
|
||||
mocks.buildTableStructureChangeSql.mockResolvedValue({ statements: [], warnings: [] });
|
||||
@@ -278,10 +288,10 @@ async function mountEditor() {
|
||||
database: "test",
|
||||
schema: "test",
|
||||
tableName: "users",
|
||||
draft: draft(),
|
||||
draft: draft(autoIncrement, counter),
|
||||
});
|
||||
mountedApps.push(app);
|
||||
app.mount(root);
|
||||
mountedEditor = app.mount(root) as unknown as { applyChanges: () => Promise<boolean> };
|
||||
await nextTick();
|
||||
await Promise.resolve();
|
||||
await nextTick();
|
||||
@@ -303,9 +313,13 @@ beforeEach(() => {
|
||||
mocks.connection.db_type = "mysql";
|
||||
mocks.connection.name = "MySQL";
|
||||
mocks.connection.driver_label = "MySQL";
|
||||
mocks.connection.driver_profile = "mysql";
|
||||
mocks.loadObjectDdl.mockResolvedValue({ ddl: "CREATE TABLE users (id varchar(255))", cacheStatus: "remote" });
|
||||
mocks.invalidateObjectDdl.mockResolvedValue(undefined);
|
||||
mocks.loadObjectMetadataFacet.mockResolvedValue({ value: [], cacheStatus: "remote" });
|
||||
mocks.getMysqlTableAutoIncrement.mockResolvedValue("10");
|
||||
mocks.buildMysqlAutoIncrementSql.mockImplementation(async ({ value }: { value: string }) => `ALTER TABLE \`test\`.\`users\` AUTO_INCREMENT = ${value};`);
|
||||
mocks.executeBatch.mockResolvedValue({ affected_rows: 0 });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -333,3 +347,98 @@ describe("TableStructureEditor charset/collation column width", () => {
|
||||
expect(triggerClass.split(",")).not.toEqual(expect.arrayContaining(["w-28"]));
|
||||
});
|
||||
});
|
||||
|
||||
describe("TableStructureEditor MySQL AUTO_INCREMENT counter", () => {
|
||||
it("loads and renders the server value as a decimal string only for an existing auto-increment column", async () => {
|
||||
const root = await mountEditor(true);
|
||||
await vi.waitFor(() => expect(mocks.getMysqlTableAutoIncrement).toHaveBeenCalledWith("structure-charset-test", "test", "users"));
|
||||
|
||||
const input = root.querySelector<HTMLInputElement>("[data-mysql-auto-increment-counter]");
|
||||
expect(input?.value).toBe("10");
|
||||
expect(input?.disabled).toBe(false);
|
||||
});
|
||||
|
||||
it("refreshes a restored clean counter draft from the server", async () => {
|
||||
mocks.getMysqlTableAutoIncrement.mockResolvedValueOnce("30");
|
||||
const root = await mountEditor(true, { value: "10", originalValue: "10" });
|
||||
|
||||
await vi.waitFor(() => expect(root.querySelector<HTMLInputElement>("[data-mysql-auto-increment-counter]")?.value).toBe("30"));
|
||||
expect(mocks.buildMysqlAutoIncrementSql).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("keeps a restored dirty value while rebasing its server baseline", async () => {
|
||||
mocks.getMysqlTableAutoIncrement.mockResolvedValueOnce("15");
|
||||
const root = await mountEditor(true, { value: "20", originalValue: "10" });
|
||||
const input = root.querySelector<HTMLInputElement>("[data-mysql-auto-increment-counter]")!;
|
||||
|
||||
await vi.waitFor(() => expect(input.value).toBe("20"));
|
||||
await vi.waitFor(() => expect(mocks.buildMysqlAutoIncrementSql).toHaveBeenCalledWith(expect.objectContaining({ value: "20" })));
|
||||
mocks.buildMysqlAutoIncrementSql.mockClear();
|
||||
input.value = "15";
|
||||
input.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
await new Promise((resolve) => setTimeout(resolve, 400));
|
||||
expect(mocks.buildMysqlAutoIncrementSql).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("keeps NULL or failed optional metadata from enabling a counter edit", async () => {
|
||||
mocks.getMysqlTableAutoIncrement.mockResolvedValueOnce(null);
|
||||
const nullRoot = await mountEditor(true);
|
||||
await vi.waitFor(() => expect(mocks.getMysqlTableAutoIncrement).toHaveBeenCalled());
|
||||
expect(nullRoot.querySelector<HTMLInputElement>("[data-mysql-auto-increment-counter]")?.disabled).toBe(true);
|
||||
|
||||
for (const app of mountedApps.splice(0)) app.unmount();
|
||||
document.body.innerHTML = "";
|
||||
mocks.getMysqlTableAutoIncrement.mockRejectedValueOnce(new Error("permission denied"));
|
||||
const errorRoot = await mountEditor(true);
|
||||
await vi.waitFor(() => expect(errorRoot.querySelector<HTMLInputElement>("[data-mysql-auto-increment-counter]")?.title).toBe("permission denied"));
|
||||
expect(mocks.buildMysqlAutoIncrementSql).not.toHaveBeenCalled();
|
||||
|
||||
const structureStatement = "ALTER TABLE `test`.`users` COMMENT = 'ordinary edit';";
|
||||
mocks.buildTableStructureChangeSql.mockResolvedValue({ statements: [structureStatement], warnings: [] });
|
||||
const commentInput = Array.from(errorRoot.querySelectorAll<HTMLInputElement>("input")).find((input) => !input.hasAttribute("data-mysql-auto-increment-counter"))!;
|
||||
commentInput.value = "ordinary edit";
|
||||
commentInput.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
await vi.waitFor(() => expect(mocks.buildTableStructureChangeSql).toHaveBeenCalled());
|
||||
await vi.waitFor(() => expect(Array.from(errorRoot.querySelectorAll("button")).find((button) => button.textContent?.includes("structureEditor.apply"))?.disabled).toBe(false));
|
||||
await expect(mountedEditor?.applyChanges()).resolves.toBe(true);
|
||||
expect(mocks.executeBatch.mock.calls[mocks.executeBatch.mock.calls.length - 1]?.[2]).toEqual([structureStatement]);
|
||||
expect(mocks.buildMysqlAutoIncrementSql).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("appends validated counter DDL and preserves the draft when execution fails", async () => {
|
||||
const root = await mountEditor(true);
|
||||
await vi.waitFor(() => expect(root.querySelector<HTMLInputElement>("[data-mysql-auto-increment-counter]")?.value).toBe("10"));
|
||||
const input = root.querySelector<HTMLInputElement>("[data-mysql-auto-increment-counter]")!;
|
||||
input.value = "9007199254740993";
|
||||
input.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
await vi.waitFor(() => expect(mocks.buildMysqlAutoIncrementSql).toHaveBeenCalledWith(expect.objectContaining({ value: "9007199254740993" })));
|
||||
|
||||
mocks.executeBatch.mockRejectedValueOnce(new Error("ALTER command denied"));
|
||||
await expect(mountedEditor?.applyChanges()).resolves.toBe(false);
|
||||
await vi.waitFor(() => expect(root.textContent).toContain("ALTER command denied"));
|
||||
expect(input.value).toBe("9007199254740993");
|
||||
});
|
||||
|
||||
it("does not treat the requested value as persisted when the post-save metadata refresh fails", async () => {
|
||||
const persistedColumn = draft(true).columns[0]!.original;
|
||||
mocks.loadObjectMetadataFacet.mockImplementation(async (_request, facet: string) => ({
|
||||
value: facet === "columns" ? [persistedColumn] : [],
|
||||
cacheStatus: "remote",
|
||||
}));
|
||||
const root = await mountEditor(true);
|
||||
await vi.waitFor(() => expect(root.querySelector<HTMLInputElement>("[data-mysql-auto-increment-counter]")?.value).toBe("10"));
|
||||
const input = root.querySelector<HTMLInputElement>("[data-mysql-auto-increment-counter]")!;
|
||||
input.value = "20";
|
||||
input.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
await vi.waitFor(() => expect(mocks.buildMysqlAutoIncrementSql).toHaveBeenCalledWith(expect.objectContaining({ value: "20" })));
|
||||
const metadataCallsBeforeSave = mocks.getMysqlTableAutoIncrement.mock.calls.length;
|
||||
mocks.getMysqlTableAutoIncrement.mockRejectedValueOnce(new Error("refresh denied"));
|
||||
mocks.buildMysqlAutoIncrementSql.mockClear();
|
||||
|
||||
await expect(mountedEditor?.applyChanges()).resolves.toBe(true);
|
||||
await vi.waitFor(() => expect(mocks.getMysqlTableAutoIncrement.mock.calls.length).toBeGreaterThan(metadataCallsBeforeSave));
|
||||
await vi.waitFor(() => expect(root.querySelector<HTMLInputElement>("[data-mysql-auto-increment-counter]")?.title).toBe("refresh denied"));
|
||||
expect(root.querySelector<HTMLInputElement>("[data-mysql-auto-increment-counter]")?.value).toBe("20");
|
||||
expect(mocks.buildMysqlAutoIncrementSql).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -32,6 +32,7 @@ import { invalidateObjectDdl, loadObjectDdl } from "@/lib/metadata/objectDdlCach
|
||||
import { invalidateObjectMetadataCache, loadObjectMetadataFacet, type ObjectMetadataFacet } from "@/lib/metadata/objectMetadataCache";
|
||||
import { invalidateTableMetadataCache } from "@/lib/metadata/tableMetadataCache";
|
||||
import { type BuildTableStructureChangeSqlOptions, type EditableStructureColumn, type EditableStructureForeignKey, type EditableStructureIndex, type EditableStructureTrigger } from "@/lib/table/tableStructureEditorSql";
|
||||
import { buildMysqlAutoIncrementCounterStatement, canEditMysqlAutoIncrementCounter, refreshMysqlAutoIncrementCounterDraft } from "@/lib/table/mysqlAutoIncrementCounter";
|
||||
import { PRESET_FIELDS_TEMPLATE_ID, createTableColumnTemplateDrafts } from "@/lib/table/tableColumnTemplates";
|
||||
import { getMysqlDataTypeHelp } from "@/lib/table/mysqlDataTypeHelp";
|
||||
import { getPostgresDataTypeHelp, gaussdbMTypeDisplayName } from "@/lib/table/postgresDataTypeHelp";
|
||||
@@ -912,6 +913,10 @@ const canAddColumn = computed(() => canAddTableStructureColumn(databaseType.valu
|
||||
const newTableName = ref("");
|
||||
const tableComment = ref("");
|
||||
const originalTableComment = ref("");
|
||||
const mysqlAutoIncrementValue = ref<string>();
|
||||
const originalMysqlAutoIncrementValue = ref<string>();
|
||||
const mysqlAutoIncrementLoading = ref(false);
|
||||
const mysqlAutoIncrementLoadError = ref("");
|
||||
const tableOwner = ref("");
|
||||
const originalTableOwner = ref("");
|
||||
const tableOwnerLoading = ref(false);
|
||||
@@ -920,6 +925,8 @@ const tableOwnerRoles = ref<string[]>([]);
|
||||
const tableOwnerRolesLoading = ref(false);
|
||||
const tableOwnerRolesLoadError = ref("");
|
||||
const supportsTableOwner = computed(() => !isCreateMode.value && databaseType.value === "postgres");
|
||||
const canEditMysqlAutoIncrement = computed(() => canEditMysqlAutoIncrementCounter(connection.value, isCreateMode.value, columns.value));
|
||||
const canBuildMysqlAutoIncrement = computed(() => canEditMysqlAutoIncrement.value && !mysqlAutoIncrementLoading.value && !mysqlAutoIncrementLoadError.value && originalMysqlAutoIncrementValue.value !== undefined);
|
||||
const tableOwnerOptions = computed(() => {
|
||||
const owner = tableOwner.value;
|
||||
if (!owner || tableOwnerRoles.value.includes(owner)) return tableOwnerRoles.value;
|
||||
@@ -942,6 +949,7 @@ let sqlPreviewRequestId = 0;
|
||||
let structureLoadRequestId = 0;
|
||||
let tableOwnerLoadRequestId = 0;
|
||||
let tableOwnerRolesLoadRequestId = 0;
|
||||
let mysqlAutoIncrementLoadRequestId = 0;
|
||||
let dataTypeOptionsRequestId = 0;
|
||||
let sqlPreviewDebounceTimer: ReturnType<typeof setTimeout> | undefined;
|
||||
let deferredSqlPreviewRefresh = false;
|
||||
@@ -1127,6 +1135,8 @@ function createCurrentDraft(initialized = true): TableStructureEditorDraft {
|
||||
newTableName: newTableName.value,
|
||||
tableComment: tableComment.value,
|
||||
originalTableComment: originalTableComment.value,
|
||||
mysqlAutoIncrementValue: mysqlAutoIncrementValue.value,
|
||||
originalMysqlAutoIncrementValue: originalMysqlAutoIncrementValue.value,
|
||||
tableOwner: tableOwner.value,
|
||||
originalTableOwner: originalTableOwner.value,
|
||||
columns: cloneDraftValue(columns.value),
|
||||
@@ -1157,6 +1167,8 @@ function restoreDraft(draft: TableStructureEditorDraft) {
|
||||
newTableName.value = draft.newTableName || "";
|
||||
tableComment.value = draft.tableComment || "";
|
||||
originalTableComment.value = draft.originalTableComment || "";
|
||||
mysqlAutoIncrementValue.value = draft.mysqlAutoIncrementValue;
|
||||
originalMysqlAutoIncrementValue.value = draft.originalMysqlAutoIncrementValue;
|
||||
tableOwner.value = draft.tableOwner || "";
|
||||
originalTableOwner.value = draft.originalTableOwner || "";
|
||||
columns.value = cloneDraftValue(draft.columns || []);
|
||||
@@ -1243,7 +1255,15 @@ function hasPendingStructureChanges(): boolean {
|
||||
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 || (supportsTableOwner.value && tableOwner.value.trim() !== originalTableOwner.value.trim());
|
||||
return (
|
||||
scope.columns ||
|
||||
scope.indexes ||
|
||||
scope.foreignKeys ||
|
||||
scope.triggers ||
|
||||
scope.tableComment ||
|
||||
(canBuildMysqlAutoIncrement.value && mysqlAutoIncrementValue.value !== originalMysqlAutoIncrementValue.value) ||
|
||||
(supportsTableOwner.value && tableOwner.value.trim() !== originalTableOwner.value.trim())
|
||||
);
|
||||
}
|
||||
|
||||
function clearSqlPreviewState() {
|
||||
@@ -1426,18 +1446,30 @@ async function refreshSqlPreview() {
|
||||
sqlPreviewLoading.value = true;
|
||||
const options = structureChangeOptions();
|
||||
try {
|
||||
const result = isCreateMode.value ? await api.buildCreateTableSql(options) : hasSqliteTypeChange.value ? await api.previewSqliteTableStructureChange(props.connectionId, props.database, options) : await api.buildTableStructureChangeSql(options);
|
||||
const ownerResult = supportsTableOwner.value
|
||||
? await api.buildTableOwnerChangeSql({
|
||||
databaseType: databaseType.value,
|
||||
schema: metadataSchema.value,
|
||||
tableName: props.tableName || "",
|
||||
owner: tableOwner.value,
|
||||
originalOwner: originalTableOwner.value,
|
||||
})
|
||||
: { statements: [], warnings: [] };
|
||||
const [result, ownerResult, mysqlAutoIncrementStatement] = await Promise.all([
|
||||
isCreateMode.value ? api.buildCreateTableSql(options) : hasSqliteTypeChange.value ? api.previewSqliteTableStructureChange(props.connectionId, props.database, options) : api.buildTableStructureChangeSql(options),
|
||||
supportsTableOwner.value
|
||||
? api.buildTableOwnerChangeSql({
|
||||
databaseType: databaseType.value,
|
||||
schema: metadataSchema.value,
|
||||
tableName: props.tableName || "",
|
||||
owner: tableOwner.value,
|
||||
originalOwner: originalTableOwner.value,
|
||||
})
|
||||
: Promise.resolve({ statements: [], warnings: [] }),
|
||||
buildMysqlAutoIncrementCounterStatement({
|
||||
enabled: canBuildMysqlAutoIncrement.value,
|
||||
originalValue: originalMysqlAutoIncrementValue.value,
|
||||
value: mysqlAutoIncrementValue.value,
|
||||
databaseType: databaseType.value,
|
||||
driverProfile: connection.value?.driver_profile,
|
||||
schema: props.schema || props.database,
|
||||
tableName: props.tableName || "",
|
||||
buildSql: api.buildMysqlAutoIncrementSql,
|
||||
}),
|
||||
]);
|
||||
if (requestId !== sqlPreviewRequestId) return;
|
||||
pendingStatements.value = [...result.statements, ...ownerResult.statements];
|
||||
pendingStatements.value = [...result.statements, ...ownerResult.statements, ...(mysqlAutoIncrementStatement ? [mysqlAutoIncrementStatement] : [])];
|
||||
warnings.value = [...result.warnings, ...ownerResult.warnings];
|
||||
sqliteSchemaRevision.value = "schemaRevision" in result && typeof result.schemaRevision === "string" ? result.schemaRevision : undefined;
|
||||
} catch (e: any) {
|
||||
@@ -1505,6 +1537,11 @@ function resetState() {
|
||||
newTableName.value = "";
|
||||
tableComment.value = "";
|
||||
originalTableComment.value = "";
|
||||
mysqlAutoIncrementValue.value = undefined;
|
||||
originalMysqlAutoIncrementValue.value = undefined;
|
||||
mysqlAutoIncrementLoadRequestId += 1;
|
||||
mysqlAutoIncrementLoading.value = false;
|
||||
mysqlAutoIncrementLoadError.value = "";
|
||||
tableOwner.value = "";
|
||||
originalTableOwner.value = "";
|
||||
tableOwnerLoadRequestId += 1;
|
||||
@@ -1578,6 +1615,32 @@ function loadCachedTableComment(request: ReturnType<typeof ddlRequest>, force =
|
||||
return loadObjectMetadataFacet(request, "comment", () => fetchTableCommentValue(request.connectionId, request.database, request.schema, request.tableName, request.catalog), { force });
|
||||
}
|
||||
|
||||
async function loadMysqlAutoIncrementCounter(preserveDraft = false) {
|
||||
const requestId = ++mysqlAutoIncrementLoadRequestId;
|
||||
if (!canEditMysqlAutoIncrement.value || !props.connectionId || !props.database || !props.tableName) {
|
||||
mysqlAutoIncrementValue.value = undefined;
|
||||
originalMysqlAutoIncrementValue.value = undefined;
|
||||
mysqlAutoIncrementLoading.value = false;
|
||||
mysqlAutoIncrementLoadError.value = "";
|
||||
return;
|
||||
}
|
||||
mysqlAutoIncrementLoading.value = true;
|
||||
mysqlAutoIncrementLoadError.value = "";
|
||||
try {
|
||||
await store.ensureConnected(props.connectionId);
|
||||
const value = await api.getMysqlTableAutoIncrement(props.connectionId, props.database, props.tableName);
|
||||
if (requestId !== mysqlAutoIncrementLoadRequestId) return;
|
||||
const draft = refreshMysqlAutoIncrementCounterDraft(value, { value: mysqlAutoIncrementValue.value, originalValue: originalMysqlAutoIncrementValue.value }, preserveDraft);
|
||||
originalMysqlAutoIncrementValue.value = draft.originalValue;
|
||||
mysqlAutoIncrementValue.value = draft.value;
|
||||
} catch (error: any) {
|
||||
if (requestId !== mysqlAutoIncrementLoadRequestId) return;
|
||||
mysqlAutoIncrementLoadError.value = error?.message || String(error);
|
||||
} finally {
|
||||
if (requestId === mysqlAutoIncrementLoadRequestId) mysqlAutoIncrementLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadTableOwner(force = false, preserveDraft = false) {
|
||||
const connectionId = props.connectionId;
|
||||
const database = props.database;
|
||||
@@ -1712,6 +1775,8 @@ async function loadStructure(
|
||||
if (!options.preserveDraft) clearColumnSelection();
|
||||
}
|
||||
|
||||
await loadMysqlAutoIncrementCounter(options.preserveDraft === true);
|
||||
|
||||
const nextTableComment = await tableCommentPromise;
|
||||
if (nextTableComment !== undefined) {
|
||||
originalTableComment.value = nextTableComment;
|
||||
@@ -1792,6 +1857,7 @@ async function refreshStructureAfterSave(scope: TableStructureRefreshScope, char
|
||||
console.warn("[DBX][structure-editor:post-save-refresh-failed]", e);
|
||||
} finally {
|
||||
postSaveRefreshing.value = false;
|
||||
if (mysqlAutoIncrementValue.value !== originalMysqlAutoIncrementValue.value) scheduleSqlPreviewRefresh();
|
||||
if (activeTab.value === "ddl") void fetchDdl(true);
|
||||
}
|
||||
}
|
||||
@@ -3291,6 +3357,7 @@ onMounted(() => {
|
||||
if (props.draft?.initialized) {
|
||||
void hydrateRestoredDraftFromDatabase().then(() => {
|
||||
applyInitialStructureTarget();
|
||||
void loadMysqlAutoIncrementCounter(true);
|
||||
void loadActiveTableStructureMetadataIfNeeded();
|
||||
});
|
||||
} else if (isCreateMode.value) {
|
||||
@@ -3313,6 +3380,7 @@ onActivated(() => {
|
||||
applyInitialStructureTarget();
|
||||
void hydrateRestoredDraftFromDatabase().then(() => {
|
||||
applyInitialStructureTarget();
|
||||
void loadMysqlAutoIncrementCounter(true);
|
||||
void loadActiveTableStructureMetadataIfNeeded();
|
||||
});
|
||||
}
|
||||
@@ -3422,7 +3490,25 @@ watch([() => props.connectionId, () => props.database, databaseType], () => {
|
||||
});
|
||||
|
||||
watch(
|
||||
[isCreateMode, () => props.connectionId, () => props.database, databaseType, () => props.schema, () => props.tableName, newTableName, tableComment, tableOwner, columns, indexes, foreignKeys, triggers],
|
||||
[
|
||||
isCreateMode,
|
||||
() => props.connectionId,
|
||||
() => props.database,
|
||||
databaseType,
|
||||
() => props.schema,
|
||||
() => props.tableName,
|
||||
newTableName,
|
||||
tableComment,
|
||||
mysqlAutoIncrementValue,
|
||||
originalMysqlAutoIncrementValue,
|
||||
mysqlAutoIncrementLoading,
|
||||
mysqlAutoIncrementLoadError,
|
||||
tableOwner,
|
||||
columns,
|
||||
indexes,
|
||||
foreignKeys,
|
||||
triggers,
|
||||
],
|
||||
() => {
|
||||
scheduleSqlPreviewRefresh();
|
||||
syncDraftToParent();
|
||||
@@ -3539,6 +3625,26 @@ watch([activeTab, ddlLoading], ([tab, loading]) => {
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<div v-if="canEditMysqlAutoIncrement" class="flex shrink-0 items-center gap-2">
|
||||
<label class="shrink-0 font-medium text-muted-foreground">AUTO_INCREMENT</label>
|
||||
<Input
|
||||
v-model="mysqlAutoIncrementValue"
|
||||
inputmode="numeric"
|
||||
autocomplete="off"
|
||||
data-mysql-auto-increment-counter
|
||||
:placeholder="mysqlAutoIncrementLoading ? t('common.loading') : '—'"
|
||||
:title="mysqlAutoIncrementLoadError || undefined"
|
||||
:class="[structureMonoControlClass, 'max-w-[220px]']"
|
||||
:disabled="mysqlAutoIncrementLoading || !!mysqlAutoIncrementLoadError || originalMysqlAutoIncrementValue === undefined || saving"
|
||||
/>
|
||||
<Tooltip v-if="mysqlAutoIncrementLoadError">
|
||||
<TooltipTrigger as-child>
|
||||
<AlertTriangle :class="[structureIconClass, 'shrink-0 text-destructive']" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{{ mysqlAutoIncrementLoadError }}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<div v-if="supportsTableOwner" class="flex shrink-0 items-center gap-2">
|
||||
<label class="flex shrink-0 items-center gap-1 font-medium text-muted-foreground">
|
||||
<UserRound :class="structureIconClass" />
|
||||
|
||||
Reference in new issue
Block a user