feat(mysql): 支持查看和修改表存储引擎
This commit is contained in:
21 files changed
+485
-5
No files matched your search
@@ -33,6 +33,7 @@ import { invalidateObjectMetadataCache, loadObjectMetadataFacet, type ObjectMeta
|
||||
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 { MYSQL_STORAGE_ENGINES_SQL, mysqlTableEngineSql, mysqlTableEngineSqlOption, parseMysqlTableEngineMetadata, refreshMysqlTableEngineDraft, supportsMysqlTableEngine } from "@/lib/table/mysqlTableEngine";
|
||||
import { PRESET_FIELDS_TEMPLATE_ID, createTableColumnTemplateDrafts } from "@/lib/table/tableColumnTemplates";
|
||||
import { getMysqlDataTypeHelp } from "@/lib/table/mysqlDataTypeHelp";
|
||||
import { getPostgresDataTypeHelp, gaussdbMTypeDisplayName } from "@/lib/table/postgresDataTypeHelp";
|
||||
@@ -917,6 +918,11 @@ const mysqlAutoIncrementValue = ref<string>();
|
||||
const originalMysqlAutoIncrementValue = ref<string>();
|
||||
const mysqlAutoIncrementLoading = ref(false);
|
||||
const mysqlAutoIncrementLoadError = ref("");
|
||||
const mysqlTableEngine = ref("");
|
||||
const originalMysqlTableEngine = ref("");
|
||||
const mysqlTableEngineOptions = ref<string[]>([]);
|
||||
const mysqlTableEngineLoading = ref(false);
|
||||
const mysqlTableEngineLoadError = ref("");
|
||||
const tableOwner = ref("");
|
||||
const originalTableOwner = ref("");
|
||||
const tableOwnerLoading = ref(false);
|
||||
@@ -927,6 +933,7 @@ 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 supportsMysqlEngine = computed(() => supportsMysqlTableEngine(connection.value));
|
||||
const tableOwnerOptions = computed(() => {
|
||||
const owner = tableOwner.value;
|
||||
if (!owner || tableOwnerRoles.value.includes(owner)) return tableOwnerRoles.value;
|
||||
@@ -950,6 +957,7 @@ let structureLoadRequestId = 0;
|
||||
let tableOwnerLoadRequestId = 0;
|
||||
let tableOwnerRolesLoadRequestId = 0;
|
||||
let mysqlAutoIncrementLoadRequestId = 0;
|
||||
let mysqlTableEngineLoadRequestId = 0;
|
||||
let dataTypeOptionsRequestId = 0;
|
||||
let sqlPreviewDebounceTimer: ReturnType<typeof setTimeout> | undefined;
|
||||
let deferredSqlPreviewRefresh = false;
|
||||
@@ -1137,6 +1145,8 @@ function createCurrentDraft(initialized = true): TableStructureEditorDraft {
|
||||
originalTableComment: originalTableComment.value,
|
||||
mysqlAutoIncrementValue: mysqlAutoIncrementValue.value,
|
||||
originalMysqlAutoIncrementValue: originalMysqlAutoIncrementValue.value,
|
||||
mysqlTableEngine: mysqlTableEngine.value,
|
||||
originalMysqlTableEngine: originalMysqlTableEngine.value,
|
||||
tableOwner: tableOwner.value,
|
||||
originalTableOwner: originalTableOwner.value,
|
||||
columns: cloneDraftValue(columns.value),
|
||||
@@ -1169,6 +1179,8 @@ function restoreDraft(draft: TableStructureEditorDraft) {
|
||||
originalTableComment.value = draft.originalTableComment || "";
|
||||
mysqlAutoIncrementValue.value = draft.mysqlAutoIncrementValue;
|
||||
originalMysqlAutoIncrementValue.value = draft.originalMysqlAutoIncrementValue;
|
||||
mysqlTableEngine.value = draft.mysqlTableEngine || "";
|
||||
originalMysqlTableEngine.value = draft.originalMysqlTableEngine || "";
|
||||
tableOwner.value = draft.tableOwner || "";
|
||||
originalTableOwner.value = draft.originalTableOwner || "";
|
||||
columns.value = cloneDraftValue(draft.columns || []);
|
||||
@@ -1252,7 +1264,7 @@ function markDraftHydratedAndSync() {
|
||||
|
||||
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;
|
||||
return !!newTableName.value.trim() || !!tableComment.value.trim() || mysqlTableEngine.value !== originalMysqlTableEngine.value || columns.value.length > 0 || indexes.value.length > 0 || foreignKeys.value.length > 0 || triggers.value.length > 0;
|
||||
}
|
||||
const scope = captureStructureRefreshScope();
|
||||
return (
|
||||
@@ -1261,6 +1273,7 @@ function hasPendingStructureChanges(): boolean {
|
||||
scope.foreignKeys ||
|
||||
scope.triggers ||
|
||||
scope.tableComment ||
|
||||
mysqlTableEngine.value.toLowerCase() !== originalMysqlTableEngine.value.toLowerCase() ||
|
||||
(canBuildMysqlAutoIncrement.value && mysqlAutoIncrementValue.value !== originalMysqlAutoIncrementValue.value) ||
|
||||
(supportsTableOwner.value && tableOwner.value.trim() !== originalTableOwner.value.trim())
|
||||
);
|
||||
@@ -1405,6 +1418,7 @@ function structureChangeOptions(): BuildTableStructureChangeSqlOptions {
|
||||
triggers: triggers.value,
|
||||
tableComment: tableComment.value,
|
||||
originalTableComment: isCreateMode.value ? undefined : originalTableComment.value,
|
||||
mysqlEngine: mysqlTableEngineSqlOption({ value: mysqlTableEngine.value, originalValue: originalMysqlTableEngine.value }, isCreateMode.value, supportsMysqlEngine.value && !mysqlTableEngineLoading.value && !mysqlTableEngineLoadError.value),
|
||||
partitioned: isPartitionedParent.value,
|
||||
isGaussdbMMode: connection.value?.driver_profile?.toLowerCase() === "gaussdb-m",
|
||||
};
|
||||
@@ -1491,6 +1505,7 @@ const canApply = computed(
|
||||
!saving.value &&
|
||||
!postSaveRefreshing.value &&
|
||||
!secondaryMetadataLoading.value &&
|
||||
!mysqlTableEngineLoading.value &&
|
||||
!sqlPreviewLoading.value &&
|
||||
!sqlPreviewPending.value &&
|
||||
pendingStatements.value.length > 0 &&
|
||||
@@ -1542,6 +1557,12 @@ function resetState() {
|
||||
mysqlAutoIncrementLoadRequestId += 1;
|
||||
mysqlAutoIncrementLoading.value = false;
|
||||
mysqlAutoIncrementLoadError.value = "";
|
||||
mysqlTableEngine.value = "";
|
||||
originalMysqlTableEngine.value = "";
|
||||
mysqlTableEngineOptions.value = [];
|
||||
mysqlTableEngineLoadRequestId += 1;
|
||||
mysqlTableEngineLoading.value = false;
|
||||
mysqlTableEngineLoadError.value = "";
|
||||
tableOwner.value = "";
|
||||
originalTableOwner.value = "";
|
||||
tableOwnerLoadRequestId += 1;
|
||||
@@ -1578,9 +1599,9 @@ async function reloadStructureFromDatabase() {
|
||||
loadedMetadataFacets.clear();
|
||||
if (refreshDdl) {
|
||||
ddlFetched.value = false;
|
||||
await Promise.all([fetchDdl(true), loadTableOwner(true), loadTableOwnerRoles()]);
|
||||
await Promise.all([fetchDdl(true), loadTableOwner(true), loadTableOwnerRoles(), loadMysqlTableEngine(true)]);
|
||||
} else {
|
||||
await Promise.all([loadStructure(false, visibleTableStructureRefreshScope(activeTab.value), true, { blockSecondaryMetadata: true, forceDdl: true, forceMetadata: true }), loadTableOwner(true), loadTableOwnerRoles()]);
|
||||
await Promise.all([loadStructure(false, visibleTableStructureRefreshScope(activeTab.value), true, { blockSecondaryMetadata: true, forceDdl: true, forceMetadata: true }), loadTableOwner(true), loadTableOwnerRoles(), loadMysqlTableEngine(true)]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1641,6 +1662,43 @@ async function loadMysqlAutoIncrementCounter(preserveDraft = false) {
|
||||
}
|
||||
}
|
||||
|
||||
async function loadMysqlTableEngine(preserveDraft = false) {
|
||||
const requestId = ++mysqlTableEngineLoadRequestId;
|
||||
const connectionId = props.connectionId;
|
||||
const database = props.database;
|
||||
if (!supportsMysqlEngine.value || !connectionId || !database) {
|
||||
mysqlTableEngine.value = "";
|
||||
originalMysqlTableEngine.value = "";
|
||||
mysqlTableEngineOptions.value = [];
|
||||
mysqlTableEngineLoading.value = false;
|
||||
mysqlTableEngineLoadError.value = "";
|
||||
return;
|
||||
}
|
||||
|
||||
mysqlTableEngineLoading.value = true;
|
||||
mysqlTableEngineLoadError.value = "";
|
||||
try {
|
||||
await store.ensureConnected(connectionId);
|
||||
const [enginesResult, tableResult] = await Promise.all([
|
||||
api.executeQuery(connectionId, database, MYSQL_STORAGE_ENGINES_SQL, undefined, undefined, { maxRows: 100 }),
|
||||
isCreateMode.value || !props.tableName ? Promise.resolve(undefined) : api.executeQuery(connectionId, database, mysqlTableEngineSql(database, props.tableName), undefined, undefined, { maxRows: 1 }),
|
||||
]);
|
||||
if (requestId !== mysqlTableEngineLoadRequestId) return;
|
||||
const metadata = parseMysqlTableEngineMetadata(enginesResult, tableResult);
|
||||
const draft = refreshMysqlTableEngineDraft(metadata, { value: mysqlTableEngine.value, originalValue: originalMysqlTableEngine.value }, isCreateMode.value, preserveDraft);
|
||||
const options = [...metadata.engines];
|
||||
if (draft.value && !options.some((option) => option.toLowerCase() === draft.value.toLowerCase())) options.unshift(draft.value);
|
||||
mysqlTableEngineOptions.value = options;
|
||||
mysqlTableEngine.value = draft.value;
|
||||
originalMysqlTableEngine.value = draft.originalValue;
|
||||
} catch (error: any) {
|
||||
if (requestId !== mysqlTableEngineLoadRequestId) return;
|
||||
mysqlTableEngineLoadError.value = error?.message || String(error);
|
||||
} finally {
|
||||
if (requestId === mysqlTableEngineLoadRequestId) mysqlTableEngineLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadTableOwner(force = false, preserveDraft = false) {
|
||||
const connectionId = props.connectionId;
|
||||
const database = props.database;
|
||||
@@ -1852,7 +1910,7 @@ async function loadStructure(
|
||||
|
||||
async function refreshStructureAfterSave(scope: TableStructureRefreshScope, characterLengthUnitsAfterSave: ReadonlyMap<string, string>) {
|
||||
try {
|
||||
await Promise.all([loadStructure(true, scope, false, { blockSecondaryMetadata: true, characterLengthUnitsAfterSave }), loadTableOwner(true)]);
|
||||
await Promise.all([loadStructure(true, scope, false, { blockSecondaryMetadata: true, characterLengthUnitsAfterSave }), loadTableOwner(true), loadMysqlTableEngine(false)]);
|
||||
} catch (e) {
|
||||
console.warn("[DBX][structure-editor:post-save-refresh-failed]", e);
|
||||
} finally {
|
||||
@@ -3354,6 +3412,7 @@ onMounted(() => {
|
||||
observeStructureHorizontalScroller();
|
||||
void loadTableOwner(false, props.draft?.tableOwner !== undefined);
|
||||
void loadTableOwnerRoles();
|
||||
void loadMysqlTableEngine(props.draft?.mysqlTableEngine !== undefined);
|
||||
if (props.draft?.initialized) {
|
||||
void hydrateRestoredDraftFromDatabase().then(() => {
|
||||
applyInitialStructureTarget();
|
||||
@@ -3375,6 +3434,9 @@ onActivated(() => {
|
||||
void loadDynamicDataTypeOptions();
|
||||
if (supportsTableOwner.value && !loadedMetadataFacets.has("owner")) void loadTableOwner(false, props.draft?.tableOwner !== undefined);
|
||||
if (supportsTableOwner.value && !tableOwnerRolesLoading.value && tableOwnerRoles.value.length === 0 && !tableOwnerRolesLoadError.value) void loadTableOwnerRoles();
|
||||
if (supportsMysqlEngine.value && !mysqlTableEngineLoading.value && mysqlTableEngineOptions.value.length === 0 && !mysqlTableEngineLoadError.value) {
|
||||
void loadMysqlTableEngine(props.draft?.mysqlTableEngine !== undefined);
|
||||
}
|
||||
if (props.draft?.initialized && !draftHydrated) {
|
||||
restoreDraft(props.draft);
|
||||
applyInitialStructureTarget();
|
||||
@@ -3503,6 +3565,10 @@ watch(
|
||||
originalMysqlAutoIncrementValue,
|
||||
mysqlAutoIncrementLoading,
|
||||
mysqlAutoIncrementLoadError,
|
||||
mysqlTableEngine,
|
||||
originalMysqlTableEngine,
|
||||
mysqlTableEngineLoading,
|
||||
mysqlTableEngineLoadError,
|
||||
tableOwner,
|
||||
columns,
|
||||
indexes,
|
||||
@@ -3625,6 +3691,29 @@ watch([activeTab, ddlLoading], ([tab, loading]) => {
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<div v-if="supportsMysqlEngine" class="flex shrink-0 items-center gap-2">
|
||||
<label class="shrink-0 font-medium text-muted-foreground">{{ t("structureEditor.mysqlTableEngine") }}</label>
|
||||
<SearchableSelect
|
||||
v-model="mysqlTableEngine"
|
||||
:options="mysqlTableEngineOptions"
|
||||
:placeholder="t('structureEditor.mysqlTableEnginePlaceholder')"
|
||||
:search-placeholder="t('structureEditor.mysqlTableEngineSearchPlaceholder')"
|
||||
:empty-text="t('structureEditor.mysqlTableEngineEmpty')"
|
||||
:loading-text="t('common.loading')"
|
||||
:loading="mysqlTableEngineLoading"
|
||||
:disabled="mysqlTableEngineLoading || !!mysqlTableEngineLoadError || saving"
|
||||
:trigger-class="[structureMonoControlClass, 'w-[220px] max-w-[220px]']"
|
||||
data-mysql-table-engine-select
|
||||
/>
|
||||
<Loader2 v-if="mysqlTableEngineLoading" :class="[structureIconClass, 'animate-spin text-muted-foreground']" />
|
||||
<Tooltip v-else-if="mysqlTableEngineLoadError">
|
||||
<TooltipTrigger as-child>
|
||||
<AlertTriangle :class="[structureIconClass, 'shrink-0 text-destructive']" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{{ t("structureEditor.mysqlTableEngineLoadFailed", { message: mysqlTableEngineLoadError }) }}</TooltipContent>
|
||||
</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
|
||||
|
||||
Reference in new issue
Block a user