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:
+23
-17
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user