mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-08-15 19:24:23 +08:00
128 lines
5.3 KiB
Go
128 lines
5.3 KiB
Go
package sync
|
|
|
|
import "GoNavi-Wails/internal/connection"
|
|
|
|
// MigrationCapability describes the executable migration contract for a source
|
|
// and target connection pair. It is intentionally derived from the same type
|
|
// resolver and planner registry used by the migration runtime.
|
|
type MigrationCapability struct {
|
|
SourceType string `json:"sourceType"`
|
|
TargetType string `json:"targetType"`
|
|
SourceModel MigrationDataModel `json:"sourceModel"`
|
|
TargetModel MigrationDataModel `json:"targetModel"`
|
|
Planner string `json:"planner"`
|
|
SupportLevel MigrationSupportLevel `json:"supportLevel"`
|
|
CanExecute bool `json:"canExecute"`
|
|
SupportsAutoCreate bool `json:"supportsAutoCreate"`
|
|
SupportsAutoAddColumns bool `json:"supportsAutoAddColumns"`
|
|
RequiresExistingTarget bool `json:"requiresExistingTarget"`
|
|
SupportsMutations bool `json:"supportsMutations"`
|
|
}
|
|
|
|
// ResolveMigrationCapability returns the migration runtime's effective support
|
|
// for a connection pair without opening either connection.
|
|
func ResolveMigrationCapability(sourceConfig connection.ConnectionConfig, targetConfig connection.ConnectionConfig) MigrationCapability {
|
|
sourceType := resolveMigrationDBType(sourceConfig)
|
|
targetType := resolveMigrationDBType(targetConfig)
|
|
capability := MigrationCapability{
|
|
SourceType: sourceType,
|
|
TargetType: targetType,
|
|
SourceModel: classifyMigrationDataModel(sourceType),
|
|
TargetModel: classifyMigrationDataModel(targetType),
|
|
// Most writable targets support the job engine's update/delete semantics.
|
|
// Time-series targets are deliberately narrowed below.
|
|
SupportsMutations: true,
|
|
}
|
|
if targetType == "tdengine" || targetType == "iotdb" {
|
|
capability.SupportsMutations = false
|
|
}
|
|
syncConfig := SyncConfig{
|
|
SourceConfig: sourceConfig,
|
|
TargetConfig: targetConfig,
|
|
}
|
|
if isRedisToMongoKeyspacePair(syncConfig) {
|
|
capability.Planner = "redis-mongo-keyspace-planner"
|
|
capability.SupportLevel = MigrationSupportLevelFull
|
|
capability.CanExecute = true
|
|
capability.SupportsAutoCreate = true
|
|
return capability
|
|
}
|
|
if isMongoToRedisKeyspacePair(syncConfig) {
|
|
capability.Planner = "mongo-redis-keyspace-planner"
|
|
capability.SupportLevel = MigrationSupportLevelFull
|
|
capability.CanExecute = true
|
|
capability.SupportsAutoCreate = true
|
|
return capability
|
|
}
|
|
if !supportsMigrationSourceEndpoint(sourceConfig, sourceType) || !supportsMigrationTargetEndpoint(targetConfig, targetType) {
|
|
capability.SupportLevel = MigrationSupportLevelUnsupported
|
|
capability.RequiresExistingTarget = true
|
|
return capability
|
|
}
|
|
if isOceanBaseOracleSyncConnection(sourceConfig) || isOceanBaseOracleSyncConnection(targetConfig) {
|
|
capability.Planner = "oceanbase-oracle-existing-target"
|
|
capability.SupportLevel = MigrationSupportLevelPartial
|
|
capability.CanExecute = true
|
|
capability.RequiresExistingTarget = true
|
|
return capability
|
|
}
|
|
|
|
ctx := MigrationBuildContext{Config: syncConfig}
|
|
planner := resolveMigrationPlanner(ctx)
|
|
if planner == nil {
|
|
capability.SupportLevel = MigrationSupportLevelUnsupported
|
|
capability.RequiresExistingTarget = true
|
|
return capability
|
|
}
|
|
|
|
capability.Planner = planner.Name()
|
|
capability.SupportLevel = planner.SupportLevel(ctx)
|
|
capability.CanExecute = capability.SupportLevel == MigrationSupportLevelFull || capability.SupportLevel == MigrationSupportLevelPartial
|
|
capability.SupportsAutoCreate = capability.SupportLevel == MigrationSupportLevelFull
|
|
capability.SupportsAutoAddColumns = capability.CanExecute && (supportsAutoAddColumnsForPair(sourceType, targetType) ||
|
|
capability.Planner == "pglike-mysql-planner")
|
|
capability.RequiresExistingTarget = !capability.SupportsAutoCreate
|
|
return capability
|
|
}
|
|
|
|
// ValidateMigrationCapability rejects normal table migrations that have no
|
|
// executable runtime path. Source-query sync has its own target-table contract
|
|
// and is deliberately validated by that path instead.
|
|
func ValidateMigrationCapability(config SyncConfig) error {
|
|
if hasSourceQuery(config) {
|
|
return nil
|
|
}
|
|
capability := ResolveMigrationCapability(config.SourceConfig, config.TargetConfig)
|
|
if capability.CanExecute {
|
|
return nil
|
|
}
|
|
return syncTextError("data_sync.capability."+string(capability.SupportLevel), map[string]any{
|
|
"sourceType": capability.SourceType,
|
|
"targetType": capability.TargetType,
|
|
})
|
|
}
|
|
|
|
func supportsMigrationSourceEndpoint(config connection.ConnectionConfig, dbType string) bool {
|
|
switch normalizeMigrationDBType(dbType) {
|
|
case "mysql", "mariadb", "oceanbase", "diros", "starrocks", "sphinx",
|
|
"postgres", "kingbase", "highgo", "vastbase", "opengauss", "gaussdb",
|
|
"oracle", "sqlserver", "dameng", "sqlite", "duckdb", "iris",
|
|
"clickhouse", "tdengine", "iotdb", "trino", "mongodb":
|
|
return true
|
|
default:
|
|
return normalizeMigrationDBType(config.Type) == "custom"
|
|
}
|
|
}
|
|
|
|
func supportsMigrationTargetEndpoint(config connection.ConnectionConfig, dbType string) bool {
|
|
switch normalizeMigrationDBType(dbType) {
|
|
case "mysql", "mariadb", "oceanbase", "diros", "starrocks",
|
|
"postgres", "kingbase", "highgo", "vastbase", "opengauss", "gaussdb",
|
|
"oracle", "sqlserver", "dameng", "sqlite", "duckdb", "iris",
|
|
"clickhouse", "tdengine", "iotdb", "mongodb":
|
|
return true
|
|
default:
|
|
return normalizeMigrationDBType(config.Type) == "custom"
|
|
}
|
|
}
|