diff --git a/.travis.yml b/.travis.yml index 0b87406..d349588 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,4 +23,4 @@ before_install: - curl http://localhost:$NEO4J_PORT/db/data/ - curl -X DELETE 'http://localhost:7474/cleandb/supersecretdebugkey!' env: - - NEO4J_VERSION="2.0.0-M03" + - NEO4J_VERSION="2.0.0-M05" diff --git a/README.md b/README.md index b35eab1..908ddc8 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ the [Neo4j](http://www.neo4j.org) graph database via its REST API. [Go 1.1](http://golang.org/doc/go1.1) or later is required. -Neo4j Milestone 2.0.0-M03 or greater is required to run the full test suite. +Neo4j Milestone 2.0.0-M05 or greater is required to run the full test suite. # Documentation diff --git a/cypher_test.go b/cypher_test.go index 8b4bf2a..596509b 100644 --- a/cypher_test.go +++ b/cypher_test.go @@ -46,7 +46,7 @@ func TestCypherParameters(t *testing.T) { Statement: ` START n = node:name_index(name={startName}) MATCH path = (n)-[r]->(m) - WHERE m.name? = {name} + WHERE m.name = {name} RETURN id(n), id(r), id(m) `, Parameters: map[string]interface{}{ @@ -159,12 +159,12 @@ func TestCypher(t *testing.T) { // query := "START x = node:name_index(name=I) MATCH path = (x-[r]-friend) WHERE friend.name = you RETURN TYPE(r)" type resultStruct struct { Type string `json:"type(r)"` - Name string `json:"n.name?"` - Age int `json:"n.age?"` + Name string `json:"n.name"` + Age int `json:"n.age"` } result := []resultStruct{} cq := CypherQuery{ - Statement: "start x = node(" + strconv.Itoa(n0.Id()) + ") match x -[r]-> n return type(r), n.name?, n.age?", + Statement: "start x = node(" + strconv.Itoa(n0.Id()) + ") match x -[r]-> n return type(r), n.name, n.age", Result: &result, } err := db.Cypher(&cq) @@ -175,7 +175,7 @@ func TestCypher(t *testing.T) { // // Our test only passes if Neo4j returns columns in the expected order - is // there any guarantee about order? - expCol := []string{"type(r)", "n.name?", "n.age?"} + expCol := []string{"type(r)", "n.name", "n.age"} expDat := []resultStruct{ resultStruct{ Type: "know", diff --git a/transaction.go b/transaction.go index c981263..042cae9 100644 --- a/transaction.go +++ b/transaction.go @@ -5,6 +5,7 @@ package neoism import ( + "encoding/json" "errors" ) @@ -34,8 +35,13 @@ type txRequest struct { } type txResponse struct { - Commit string - Results []cypherResult + Commit string + Results []struct { + Columns []string + Data []struct { + Row []*json.RawMessage + } + } Transaction struct { Expires string } @@ -45,9 +51,24 @@ type txResponse struct { // unmarshal populates a slice of CypherQuery object with result data returned // from the server. func (tr *txResponse) unmarshal(qs []*CypherQuery) error { + if len(tr.Results) != len(qs) { + return errors.New("Result count does not match query count") + } + // NOTE: Beginning in 2.0.0-M05, the data format returned by transaction + // endpoint diverged from the format returned by cypher batch. At least + // until final 2.0.0 release, we will work around this by munging the new + // result format into the existing cypherResult struct. for i, res := range tr.Results { + data := make([][]*json.RawMessage, len(res.Data)) + for n, d := range res.Data { + data[n] = d.Row + } q := qs[i] - q.cr = res + cr := cypherResult{ + Columns: res.Columns, + Data: data, + } + q.cr = cr if q.Result != nil { err := q.Unmarshal(q.Result) if err != nil { @@ -78,13 +99,13 @@ func (db *Database) Begin(qs []*CypherQuery) (*Tx, error) { Errors: result.Errors, Expires: result.Transaction.Expires, } + if len(t.Errors) != 0 { + return &t, TxQueryError + } err = result.unmarshal(qs) if err != nil { return &t, err } - if len(t.Errors) != 0 { - return &t, TxQueryError - } return &t, err } @@ -121,13 +142,13 @@ func (t *Tx) Query(qs []*CypherQuery) error { } t.Expires = result.Transaction.Expires t.Errors = append(t.Errors, result.Errors...) + if len(t.Errors) != 0 { + return TxQueryError + } err = result.unmarshal(qs) if err != nil { return err } - if len(t.Errors) != 0 { - return TxQueryError - } return nil } diff --git a/transaction_test.go b/transaction_test.go index 27272e4..12b8c5e 100644 --- a/transaction_test.go +++ b/transaction_test.go @@ -64,10 +64,10 @@ func TestTxBegin(t *testing.T) { assert.Equal(t, *new([]string), q1.Columns()) stmts := []*CypherQuery{&q0, &q1, &q2} tx, err := db.Begin(stmts) + tx.Rollback() if err != nil { t.Fatal(err) } - tx.Rollback() // Else cleanup will hang til Tx times out assert.Equal(t, 1, len(res0)) assert.Equal(t, "James T Kirk", res0[0].N.Name) assert.Equal(t, 1, len(res1)) @@ -168,9 +168,9 @@ func TestTxBadQuery(t *testing.T) { } tx, err := db.Begin(qs) assert.Equal(t, TxQueryError, err) + tx.Rollback() // Else cleanup will hang til Tx times out numErr := len(tx.Errors) assert.T(t, numErr == 1, "Expected one tx error, got "+strconv.Itoa(numErr)) - tx.Rollback() // Else cleanup will hang til Tx times out } func TestTxQuery(t *testing.T) {