Fix Toolkit Overriding Semantics

- key: null and key: "****" now mean “remove this row's identity”
  - only "null": true blanks the whole row
  - explicit id remains authoritative on id + key overrides
  - when a row claims a key from another row, the key and lock entry can move with it if the old row
    loses that key
This commit is contained in:
2026-05-14 00:15:58 +02:00
parent 985bffa8fb
commit c66b7dcb2b
2 changed files with 190 additions and 17 deletions
+23 -17
View File
@@ -809,13 +809,7 @@ func collectBaseDataset(dataset nativeDataset) (nativeCollectedDataset, error) {
lockModified = true
return override, nil
}
cloned := make(map[string]any, len(override)-1)
for field, value := range override {
if field != "id" {
cloned[field] = value
}
}
return cloned, nil
return override, nil
}
validExplicitIDForNewKey := func(key string, rowID int) bool {
if key == "" {
@@ -4063,18 +4057,23 @@ func resolveOverrideTarget(datasetName string, override map[string]any, rowByID
}
func overrideRequestsNullRow(override map[string]any) bool {
rawKey, ok := override["key"]
value, ok := override["null"]
if !ok {
return false
}
if rawKey == nil {
return true
}
typed, ok := rawKey.(string)
if !ok {
switch typed := value.(type) {
case bool:
return typed
case string:
trimmed := strings.TrimSpace(strings.ToLower(typed))
return trimmed == "true" || trimmed == "1" || trimmed == "yes"
case int:
return typed != 0
case float64:
return typed != 0
default:
return false
}
return strings.TrimSpace(typed) == nullValue
}
func nullifyOverrideRow(row map[string]any, columns []string, rowByKey map[string]map[string]any) {
@@ -4119,12 +4118,14 @@ func updateOverrideRowKey(datasetName string, row map[string]any, expanded map[s
return changed, nil
}
newKey, ok := newKeyValue.(string)
if !ok || newKey == "" {
if !ok || newKey == "" || strings.TrimSpace(newKey) == nullValue {
delete(row, "key")
return changed, nil
}
conflictingID := -1
if conflicting, ok := rowByKey[newKey]; ok && conflicting != nil {
conflictingID, conflictingHasID := conflicting["id"].(int)
var conflictingHasID bool
conflictingID, conflictingHasID = conflicting["id"].(int)
rowHasID := rowID != 0 || row["id"] != nil
if !conflictingHasID || !rowHasID || conflictingID != rowID {
delete(conflicting, "key")
@@ -4135,7 +4136,12 @@ func updateOverrideRowKey(datasetName string, row map[string]any, expanded map[s
rowByKey[newKey] = row
if existingID, ok := lockData[newKey]; ok {
if existingID != rowID {
return false, fmt.Errorf("dataset %s: key %q is locked to id %d and cannot be rewritten to id %d", datasetName, newKey, existingID, rowID)
if conflictingID >= 0 && existingID == conflictingID {
lockData[newKey] = rowID
changed = true
} else {
return false, fmt.Errorf("dataset %s: key %q is locked to id %d and cannot be rewritten to id %d", datasetName, newKey, existingID, rowID)
}
}
} else {
lockData[newKey] = rowID