mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-08-22 00:42:47 +08:00
fix(sync): constrain TDengine and IoTDB targets to append writes (#891)
## Summary - expose append-only capability for TDengine and IoTDB targets - constrain the delivery UI to INSERT/append and remove delete propagation - block mutation and delete configurations during backend preflight - add Go and frontend regression coverage ## Verification - Go sync capability and preflight regression tests passed - frontend delivery and Wails DTO regression tests passed - frontend production build passed - Wails desktop build passed Closes #883
This commit is contained in:
@@ -16,6 +16,7 @@ type MigrationCapability struct {
|
||||
SupportsAutoCreate bool `json:"supportsAutoCreate"`
|
||||
SupportsAutoAddColumns bool `json:"supportsAutoAddColumns"`
|
||||
RequiresExistingTarget bool `json:"requiresExistingTarget"`
|
||||
SupportsMutations bool `json:"supportsMutations"`
|
||||
}
|
||||
|
||||
// ResolveMigrationCapability returns the migration runtime's effective support
|
||||
@@ -28,6 +29,12 @@ func ResolveMigrationCapability(sourceConfig connection.ConnectionConfig, target
|
||||
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,
|
||||
|
||||
@@ -21,6 +21,7 @@ func TestResolveMigrationCapability_MySQLToPostgresUsesFullPlanner(t *testing.T)
|
||||
SupportsAutoCreate: true,
|
||||
SupportsAutoAddColumns: true,
|
||||
RequiresExistingTarget: false,
|
||||
SupportsMutations: true,
|
||||
}
|
||||
|
||||
if got != want {
|
||||
@@ -44,6 +45,7 @@ func TestResolveMigrationCapability_PostgresToKingbaseUsesSameFamilyPlanner(t *t
|
||||
SupportsAutoCreate: true,
|
||||
SupportsAutoAddColumns: true,
|
||||
RequiresExistingTarget: false,
|
||||
SupportsMutations: true,
|
||||
}
|
||||
|
||||
if got != want {
|
||||
@@ -67,6 +69,7 @@ func TestResolveMigrationCapability_OracleToSQLServerUsesExistingTargetCompatibi
|
||||
SupportsAutoCreate: false,
|
||||
SupportsAutoAddColumns: false,
|
||||
RequiresExistingTarget: true,
|
||||
SupportsMutations: true,
|
||||
}
|
||||
|
||||
if got != want {
|
||||
@@ -90,6 +93,7 @@ func TestResolveMigrationCapability_MongoToOracleReportsPlannedNonExecutablePath
|
||||
SupportsAutoCreate: false,
|
||||
SupportsAutoAddColumns: false,
|
||||
RequiresExistingTarget: true,
|
||||
SupportsMutations: true,
|
||||
}
|
||||
|
||||
if got != want {
|
||||
@@ -113,6 +117,7 @@ func TestResolveMigrationCapability_RedisToMongoReportsFullKeyspaceBridge(t *tes
|
||||
SupportsAutoCreate: true,
|
||||
SupportsAutoAddColumns: false,
|
||||
RequiresExistingTarget: false,
|
||||
SupportsMutations: true,
|
||||
}
|
||||
|
||||
if got != want {
|
||||
@@ -136,6 +141,7 @@ func TestResolveMigrationCapability_MongoToRedisReportsFullKeyspaceBridge(t *tes
|
||||
SupportsAutoCreate: true,
|
||||
SupportsAutoAddColumns: false,
|
||||
RequiresExistingTarget: false,
|
||||
SupportsMutations: true,
|
||||
}
|
||||
|
||||
if got != want {
|
||||
@@ -159,6 +165,7 @@ func TestResolveMigrationCapability_CustomPostgresUsesResolvedDriverFamily(t *te
|
||||
SupportsAutoCreate: true,
|
||||
SupportsAutoAddColumns: true,
|
||||
RequiresExistingTarget: false,
|
||||
SupportsMutations: true,
|
||||
}
|
||||
|
||||
if got != want {
|
||||
@@ -182,6 +189,7 @@ func TestResolveMigrationCapability_KafkaToQdrantIsUnsupported(t *testing.T) {
|
||||
SupportsAutoCreate: false,
|
||||
SupportsAutoAddColumns: false,
|
||||
RequiresExistingTarget: true,
|
||||
SupportsMutations: true,
|
||||
}
|
||||
|
||||
if got != want {
|
||||
@@ -200,6 +208,20 @@ func TestResolveMigrationCapability_RedisToNonMongoTargetIsUnsupported(t *testin
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveMigrationCapability_TimeSeriesTargetsAreAppendOnly(t *testing.T) {
|
||||
for _, targetType := range []string{"tdengine", "iotdb"} {
|
||||
t.Run(targetType, func(t *testing.T) {
|
||||
capability := ResolveMigrationCapability(
|
||||
connection.ConnectionConfig{Type: "mysql"},
|
||||
connection.ConnectionConfig{Type: targetType},
|
||||
)
|
||||
if !capability.CanExecute || capability.SupportsMutations {
|
||||
t.Fatalf("expected %s target to be executable and append-only, got %+v", targetType, capability)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveMigrationCapability_GoldenDBUsesMySQLPlannerFamily(t *testing.T) {
|
||||
got := ResolveMigrationCapability(
|
||||
connection.ConnectionConfig{Type: "goldendb"},
|
||||
|
||||
Reference in New Issue
Block a user