Skip to content
This repository has been archived by the owner on May 17, 2020. It is now read-only.

Handle schema change in node #20

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions action.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,42 @@ type Action func(*Checkpoint)

// ActionDefault ...
func ActionDefault(cp *Checkpoint) {}

// ActionPostSet ...
func ActionPostSet(cp *Checkpoint) {
cp.SetID("$0", cp.Get("0_sets", "$0", "name").(string))
}

// ActionPostAttr ...
func ActionPostAttr(cp *Checkpoint) {
set := cp.Get("0_sets", "$0", "set").(string)
name := cp.Get("0_sets", "$0", "name").(string)

cp.SetID("$0", set+"_"+name)
}

// ActionPostRel ...
func ActionPostRel(cp *Checkpoint) {
set := cp.Get("0_sets", "$0", "set").(string)
name := cp.Get("0_sets", "$0", "from-name").(string)

cp.SetID("$0", set+"_"+name)
}

// ActionPatchSet ...
func ActionPatchSet(cp *Checkpoint) {}

// ActionPatchAttr ...
func ActionPatchAttr(cp *Checkpoint) {}

// ActionPatchRel ...
func ActionPatchRel(cp *Checkpoint) {}

// ActionDeleteSet ...
func ActionDeleteSet(cp *Checkpoint) {}

// ActionDeleteAttr ...
func ActionDeleteAttr(cp *Checkpoint) {}

// ActionDeleteRel ...
func ActionDeleteRel(cp *Checkpoint) {}
77 changes: 72 additions & 5 deletions checkpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package karigo

import (
"errors"
"fmt"
"strconv"

"github.com/mfcochauxlaberge/karigo/query"

Expand All @@ -10,13 +12,12 @@ import (

// Checkpoint ...
type Checkpoint struct {
Res jsonapi.Resource
Inc map[string]jsonapi.Resource

tx query.Tx
node *Node
tx query.Tx
schema *jsonapi.Schema
node *Node

ops []query.Op
ids map[string]string

err error
}
Expand Down Expand Up @@ -78,6 +79,72 @@ func (c *Checkpoint) Fail(err error) {
c.err = err
}

// Val finds and returns the value the given field is set to in the current ops.
//
// The second return argument reports whether a set operation was found. Other
// operations (add, subtract, insert, etc) are ignored since a fix value cannot
// be calculated.
func (c *Checkpoint) Val(set, id, field string) (interface{}, bool) {
for _, op := range c.ops {
if op.Key.Set == set && op.Key.ID == id && op.Key.Field == field {
return op.Value, true
}
}

return nil, false
}

// NumChange finds and returns the change applied to the given field in the
// current ops.
//
// A change is represented by OpAdd or OpSubtract. It is assumed that the field
// is of numerical type (int, int8, uint, etc).
func (c *Checkpoint) NumChange(set, id, field string) int {
for _, op := range c.ops {
if op.Key.Set == set && op.Key.ID == id && op.Key.Field == field {
i, _ := strconv.ParseInt(fmt.Sprintf("%d", op.Value), 10, 64)
return int(i)
}
}

return 0
}

// RelsChange finds and returns the inserted and removed IDs for the given
// relationship.
//
// The first return argument is the added IDs, and the second one is the removed
// IDs.
//
// A change is represented by OpInset or OpRemove. It is assumed that the field
// is of type []byte or []string for to-many relationships.
func (c *Checkpoint) RelsChange(set, id, field string) ([]string, []string) {
var insertions, removals []string

for _, op := range c.ops {
if op.Key.Set == set && op.Key.ID == id && op.Key.Field == field {
if op.Op == query.OpInsert {
insertions = op.Value.([]string)
} else {
removals = op.Value.([]string)
}
}
}

return insertions, removals
}

// SetID ...
func (c *Checkpoint) SetID(placeholder, id string) interface{} {
if c.ids == nil {
c.ids = map[string]string{}
}

c.ids[placeholder] = id

return nil
}

// commit ...
func (c *Checkpoint) commit() error {
return c.tx.Commit()
Expand Down
53 changes: 20 additions & 33 deletions node.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,17 @@ func (n *Node) Handle(r *Request) *jsonapi.Document {
}

if n.funcs == nil {
n.funcs = map[string]Action{}
n.funcs = map[string]Action{
"POST 0_sets": ActionPostSet,
"POST 0_attrs": ActionPostSet,
"POST 0_rels": ActionPostSet,
"PATCH 0_sets": ActionPatchSet,
"PATCH 0_attrs": ActionPatchSet,
"PATCH 0_rels": ActionPatchSet,
"DELETE 0_sets": ActionDeleteSet,
"DELETE 0_attrs": ActionDeleteSet,
"DELETE 0_rels": ActionDeleteSet,
}
}

var (
Expand Down Expand Up @@ -211,33 +221,8 @@ func (n *Node) Handle(r *Request) *jsonapi.Document {
if res.GetID() == "" {
res.SetID(uuid.New().String()[:8])
}
// TODO Do not hardcode the following conditions. It can
// be handled in a much better way.
switch res.GetType().Name {
case "0_sets":
res.SetID(res.Get("name").(string))
ops = query.NewOpCreateSet(res.GetID())
case "0_attrs":
ops = query.NewOpCreateAttr(
res.GetToOne("set"),
res.Get("name").(string),
res.Get("type").(string),
res.Get("null").(bool),
)
res.SetID(ops[0].Value.(string))
case "0_rels":
ops = query.NewOpCreateRel(
res.GetToOne("from-set"),
res.Get("from-name").(string),
res.GetToOne("to-set"),
res.Get("to-name").(string),
res.Get("to-one").(bool),
res.Get("from-one").(bool),
)
res.SetID(ops[0].Value.(string))
default:
ops = query.NewOpCreateRes(res)
}

ops = query.NewOpCreateRes(res)

found, _ := cp.tx.Resource(query.Res{
Set: res.GetType().Name,
Expand Down Expand Up @@ -283,12 +268,14 @@ func (n *Node) Handle(r *Request) *jsonapi.Document {

cp.Apply(ops)

// Execute
execute(cp)

if r.isSchemaChange() {
// Handle schema change
handleSchemaChange(n.schema, r, cp)
} else {
// Execute
execute(cp)
err = updateSchema(n.schema, cp.tx)
if err != nil {
panic(fmt.Errorf("could not update schema: %s", err))
}
}

for _, op := range cp.ops {
Expand Down
Loading