Harden chunk plan cache storage and reuse
This commit is contained in:
@@ -207,7 +207,34 @@ func cloneJSONMap(values map[string]any) map[string]any {
|
||||
}
|
||||
cloned := make(map[string]any, len(values))
|
||||
for key, value := range values {
|
||||
cloned[key] = value
|
||||
cloned[key] = cloneJSONValue(value)
|
||||
}
|
||||
return cloned
|
||||
}
|
||||
|
||||
func cloneJSONValue(value any) any {
|
||||
switch typed := value.(type) {
|
||||
case map[string]any:
|
||||
return cloneJSONMap(typed)
|
||||
case []any:
|
||||
cloned := make([]any, len(typed))
|
||||
for i := range typed {
|
||||
cloned[i] = cloneJSONValue(typed[i])
|
||||
}
|
||||
return cloned
|
||||
case json.RawMessage:
|
||||
return append(json.RawMessage(nil), typed...)
|
||||
case []byte:
|
||||
return append([]byte(nil), typed...)
|
||||
case []string:
|
||||
return append([]string(nil), typed...)
|
||||
case map[string]string:
|
||||
cloned := make(map[string]string, len(typed))
|
||||
for key, item := range typed {
|
||||
cloned[key] = item
|
||||
}
|
||||
return cloned
|
||||
default:
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,6 +202,22 @@ func TestMaterializeChunkPlanExactOutputAndMutationSafety(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMaterializeChunkPlanDeepClonesUnitMetadata(t *testing.T) {
|
||||
doc := planDocument()
|
||||
doc.Units[0].Metadata = map[string]any{"nested": map[string]any{"values": []any{json.RawMessage(`{"ok":true}`)}}}
|
||||
chunks, err := MaterializeChunkPlan(doc, validChunkPlan(doc))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
nested := chunks[0].Units[0].Metadata["nested"].(map[string]any)
|
||||
nested["values"].([]any)[0].(json.RawMessage)[0] = '['
|
||||
nested["changed"] = true
|
||||
original := doc.Units[0].Metadata["nested"].(map[string]any)
|
||||
if _, exists := original["changed"]; exists || string(original["values"].([]any)[0].(json.RawMessage)) != `{"ok":true}` {
|
||||
t.Fatalf("source metadata changed through materialized chunk: %#v", doc.Units[0].Metadata)
|
||||
}
|
||||
}
|
||||
|
||||
func planDocument() *SourceDocument {
|
||||
doc := &SourceDocument{ID: "source-plan", Kind: "test", Format: "application/test", Digest: "sha256:source-plan"}
|
||||
for _, id := range []int{10, 20, 30, 40, 50} {
|
||||
|
||||
Reference in New Issue
Block a user