Skip to content
Snippets Groups Projects
Commit 1824910a authored by Manish R Jain's avatar Manish R Jain
Browse files

Parse Mutation along with query.

parent 5a7e209a
Branches
No related tags found
No related merge requests found
...@@ -36,6 +36,11 @@ type GraphQuery struct { ...@@ -36,6 +36,11 @@ type GraphQuery struct {
Children []*GraphQuery Children []*GraphQuery
} }
type Mutation struct {
Set string
Del string
}
func run(l *lex.Lexer) { func run(l *lex.Lexer) {
for state := lexText; state != nil; { for state := lexText; state != nil; {
state = state(l) state = state(l)
...@@ -43,10 +48,11 @@ func run(l *lex.Lexer) { ...@@ -43,10 +48,11 @@ func run(l *lex.Lexer) {
close(l.Items) // No more tokens. close(l.Items) // No more tokens.
} }
func Parse(input string) (gq *GraphQuery, rerr error) { func Parse(input string) (gq *GraphQuery, mu *Mutation, rerr error) {
l := lex.NewLexer(input) l := lex.NewLexer(input)
go run(l) go run(l)
mu = nil
gq = nil gq = nil
for item := range l.Items { for item := range l.Items {
if item.Typ == itemText { if item.Typ == itemText {
...@@ -54,7 +60,13 @@ func Parse(input string) (gq *GraphQuery, rerr error) { ...@@ -54,7 +60,13 @@ func Parse(input string) (gq *GraphQuery, rerr error) {
} }
if item.Typ == itemOpType { if item.Typ == itemOpType {
if item.Val == "mutation" { if item.Val == "mutation" {
return nil, errors.New("Mutations not supported") if mu != nil {
return nil, nil, errors.New("Only one mutation block allowed.")
}
mu, rerr = getMutation(l)
if rerr != nil {
return nil, nil, rerr
}
} }
} }
if item.Typ == itemLeftCurl { if item.Typ == itemLeftCurl {
...@@ -62,16 +74,71 @@ func Parse(input string) (gq *GraphQuery, rerr error) { ...@@ -62,16 +74,71 @@ func Parse(input string) (gq *GraphQuery, rerr error) {
gq, rerr = getRoot(l) gq, rerr = getRoot(l)
if rerr != nil { if rerr != nil {
x.Err(glog, rerr).Error("While retrieving subgraph root") x.Err(glog, rerr).Error("While retrieving subgraph root")
return nil, rerr return nil, nil, rerr
} }
} else { } else {
if err := godeep(l, gq); err != nil { if err := godeep(l, gq); err != nil {
return gq, err return nil, nil, err
} }
} }
} }
} }
return gq, nil return gq, mu, nil
}
func getMutation(l *lex.Lexer) (mu *Mutation, rerr error) {
for item := range l.Items {
if item.Typ == itemText {
continue
}
if item.Typ == itemLeftCurl {
mu = new(Mutation)
}
if item.Typ == itemRightCurl {
return mu, nil
}
if item.Typ == itemMutationOp {
if err := parseMutationOp(l, item.Val, mu); err != nil {
return nil, err
}
}
}
return nil, errors.New("Invalid mutation.")
}
func parseMutationOp(l *lex.Lexer, op string, mu *Mutation) error {
if mu == nil {
return errors.New("Mutation is nil.")
}
parse := false
for item := range l.Items {
if item.Typ == itemText {
continue
}
if item.Typ == itemLeftCurl {
if parse {
return errors.New("Too many left curls in set mutation.")
}
parse = true
}
if item.Typ == itemMutationContent {
if !parse {
return errors.New("Mutation syntax invalid.")
}
if op == "set" {
mu.Set = item.Val
} else if op == "delete" {
mu.Del = item.Val
} else {
return errors.New("Invalid mutation operation.")
}
}
if item.Typ == itemRightCurl {
return nil
}
}
return errors.New("Invalid mutation formatting.")
} }
func getRoot(l *lex.Lexer) (gq *GraphQuery, rerr error) { func getRoot(l *lex.Lexer) (gq *GraphQuery, rerr error) {
......
...@@ -18,6 +18,7 @@ package gql ...@@ -18,6 +18,7 @@ package gql
import ( import (
"fmt" "fmt"
"strings"
"testing" "testing"
) )
...@@ -41,7 +42,7 @@ func TestParse(t *testing.T) { ...@@ -41,7 +42,7 @@ func TestParse(t *testing.T) {
} }
` `
gq, err := Parse(query) gq, _, err := Parse(query)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
...@@ -82,7 +83,7 @@ func TestParseXid(t *testing.T) { ...@@ -82,7 +83,7 @@ func TestParseXid(t *testing.T) {
type.object.name type.object.name
} }
}` }`
gq, err := Parse(query) gq, _, err := Parse(query)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
...@@ -99,22 +100,6 @@ func TestParseXid(t *testing.T) { ...@@ -99,22 +100,6 @@ func TestParseXid(t *testing.T) {
} }
} }
func TestParse_error1(t *testing.T) {
query := `
mutation {
me(_uid_:0x0a) {
name
}
}
`
var err error
_, err = Parse(query)
t.Log(err)
if err == nil {
t.Error("Expected error")
}
}
func TestParse_error2(t *testing.T) { func TestParse_error2(t *testing.T) {
query := ` query := `
query { query {
...@@ -124,7 +109,7 @@ func TestParse_error2(t *testing.T) { ...@@ -124,7 +109,7 @@ func TestParse_error2(t *testing.T) {
} }
` `
var err error var err error
_, err = Parse(query) _, _, err = Parse(query)
t.Log(err) t.Log(err)
if err == nil { if err == nil {
t.Error("Expected error") t.Error("Expected error")
...@@ -141,7 +126,7 @@ func TestParse_pass1(t *testing.T) { ...@@ -141,7 +126,7 @@ func TestParse_pass1(t *testing.T) {
} }
} }
` `
gq, err := Parse(query) gq, _, err := Parse(query)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
...@@ -168,7 +153,7 @@ func TestParse_block(t *testing.T) { ...@@ -168,7 +153,7 @@ func TestParse_block(t *testing.T) {
} }
} }
` `
gq, err := Parse(query) gq, _, err := Parse(query)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
...@@ -179,3 +164,134 @@ func TestParse_block(t *testing.T) { ...@@ -179,3 +164,134 @@ func TestParse_block(t *testing.T) {
t.Error(err) t.Error(err)
} }
} }
func TestParseMutation(t *testing.T) {
query := `
mutation {
set {
<name> <is> <something> .
<hometown> <is> <san francisco> .
}
delete {
<name> <is> <something-else> .
}
}
`
_, mu, err := Parse(query)
if err != nil {
t.Error(err)
return
}
if strings.Index(mu.Set, "<name> <is> <something> .") == -1 {
t.Error("Unable to find mutation content.")
}
if strings.Index(mu.Set, "<hometown> <is> <san francisco> .") == -1 {
t.Error("Unable to find mutation content.")
}
if strings.Index(mu.Del, "<name> <is> <something-else> .") == -1 {
t.Error("Unable to find mutation content.")
}
}
func TestParseMutation_error(t *testing.T) {
query := `
mutation {
set {
<name> <is> <something> .
<hometown> <is> <san francisco> .
}
delete {
<name> <is> <something-else> .
}
`
_, _, err := Parse(query)
if err == nil {
t.Error(err)
return
}
t.Log(err)
}
func TestParseMutation_error2(t *testing.T) {
query := `
mutation {
set {
<name> <is> <something> .
<hometown> <is> <san francisco> .
}
delete {
<name> <is> <something-else> .
}
}
mutation {
set {
another one?
}
}
`
_, _, err := Parse(query)
if err == nil {
t.Error(err)
return
}
t.Log(err)
}
func TestParseMutationAndQuery(t *testing.T) {
query := `
mutation {
set {
<name> <is> <something> .
<hometown> <is> <san francisco> .
}
delete {
<name> <is> <something-else> .
}
}
query {
me(_xid_: tomhanks) {
name
hometown
}
}
`
gq, mu, err := Parse(query)
if err != nil {
t.Error(err)
return
}
if mu == nil {
t.Error("mutation is nil")
return
}
if strings.Index(mu.Set, "<name> <is> <something> .") == -1 {
t.Error("Unable to find mutation content.")
}
if strings.Index(mu.Set, "<hometown> <is> <san francisco> .") == -1 {
t.Error("Unable to find mutation content.")
}
if strings.Index(mu.Del, "<name> <is> <something-else> .") == -1 {
t.Error("Unable to find mutation content.")
}
if gq == nil {
t.Error("subgraph is nil")
return
}
if gq.XID != "tomhanks" {
t.Error("Expected: tomhanks. Got: %v", gq.XID)
return
}
if len(gq.Children) != 2 {
t.Errorf("Expected 2 children. Got: %v", len(gq.Children))
return
}
if err := checkAttr(gq.Children[0], "name"); err != nil {
t.Error(err)
}
if err := checkAttr(gq.Children[1], "hometown"); err != nil {
t.Error(err)
}
}
...@@ -190,7 +190,7 @@ func TestProcessGraph(t *testing.T) { ...@@ -190,7 +190,7 @@ func TestProcessGraph(t *testing.T) {
} }
} }
` `
gq, err := gql.Parse(query) gq, _, err := gql.Parse(query)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
...@@ -282,7 +282,7 @@ func TestToJson(t *testing.T) { ...@@ -282,7 +282,7 @@ func TestToJson(t *testing.T) {
} }
` `
gq, err := gql.Parse(query) gq, _, err := gql.Parse(query)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
......
...@@ -72,7 +72,7 @@ func queryHandler(w http.ResponseWriter, r *http.Request) { ...@@ -72,7 +72,7 @@ func queryHandler(w http.ResponseWriter, r *http.Request) {
} }
glog.WithField("q", string(q)).Debug("Query received.") glog.WithField("q", string(q)).Debug("Query received.")
gq, err := gql.Parse(string(q)) gq, _, err := gql.Parse(string(q))
if err != nil { if err != nil {
x.Err(glog, err).Error("While parsing query") x.Err(glog, err).Error("While parsing query")
x.SetStatus(w, x.E_INVALID_REQUEST, err.Error()) x.SetStatus(w, x.E_INVALID_REQUEST, err.Error())
......
...@@ -88,7 +88,7 @@ func TestQuery(t *testing.T) { ...@@ -88,7 +88,7 @@ func TestQuery(t *testing.T) {
defer closeAll(dir1, dir2, clog) defer closeAll(dir1, dir2, clog)
// Parse GQL into internal query representation. // Parse GQL into internal query representation.
gq, err := gql.Parse(q0) gq, _, err := gql.Parse(q0)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
...@@ -184,7 +184,7 @@ func BenchmarkQuery(b *testing.B) { ...@@ -184,7 +184,7 @@ func BenchmarkQuery(b *testing.B) {
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
gq, err := gql.Parse(q1) gq, _, err := gql.Parse(q1)
if err != nil { if err != nil {
b.Error(err) b.Error(err)
return return
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment