diff options
Diffstat (limited to 'internal/tree/mutations.go')
-rw-r--r-- | internal/tree/mutations.go | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/internal/tree/mutations.go b/internal/tree/mutations.go new file mode 100644 index 0000000..ec80ebd --- /dev/null +++ b/internal/tree/mutations.go @@ -0,0 +1,60 @@ +package tree + +import ( + "context" + "fmt" + + "go.neonxp.dev/djson/internal/model" +) + +func (t *Engine) Mutation(ctx context.Context, mut *model.Mutation) error { + t.mu.Lock() + defer t.mu.Unlock() + if err := t.execute(mut); err != nil { + return err + } + return t.storage.Commit(ctx, *mut) +} + +func (t *Engine) execute(mut *model.Mutation) error { + switch mut.Type { + case model.Create: + if len(mut.Path) == 0 { + // create root node + t.Root = mut.Body + return nil + } + key := mut.Path[len(mut.Path)-1] + path := mut.Path[:len(mut.Path)-1] + target, err := t.Root.Query(path) + if err != nil { + return err + } + return target.Set(key, mut.Body) + case model.Merge: + if len(mut.Path) == 0 { + // patch root node + return t.Root.Merge(&mut.Body) + } + target, err := t.Root.Query(mut.Path) + if err != nil { + return err + } + return target.Merge(&mut.Body) + case model.Remove: + if len(mut.Path) == 0 { + return fmt.Errorf("can't remove root node. Only replace or create avaliable") + } + key := mut.Path[len(mut.Path)-1] + if len(mut.Path) == 1 { + return t.Root.Remove(key) + } + path := mut.Path[:len(mut.Path)-1] + target, err := t.Root.Query(path) + if err != nil { + return err + } + return target.Remove(key) + } + return fmt.Errorf("invalid command type: %d", mut.Type) +} |