diff --git a/command/encoding/json.go b/command/encoding/json.go index f59548c7..beeccf42 100644 --- a/command/encoding/json.go +++ b/command/encoding/json.go @@ -35,7 +35,7 @@ type Rows struct { // AssociativeRows represents the outcome of an operation that returns query data. type AssociativeRows struct { Types map[string]string `json:"types,omitempty"` - Rows []map[string]interface{} `json:"rows,omitempty"` + Rows []map[string]interface{} `json:"rows"` Error string `json:"error,omitempty"` Time float64 `json:"time,omitempty"` } diff --git a/command/encoding/json_test.go b/command/encoding/json_test.go index 1eda3bb2..7ac082a8 100644 --- a/command/encoding/json_test.go +++ b/command/encoding/json_test.go @@ -438,8 +438,17 @@ func Test_MarshalExecuteQueryResponse(t *testing.T) { }, }, }, + { + Result: &command.ExecuteQueryResponse_Q{ + Q: &command.QueryRows{ + Columns: []string{"column1", "column2"}, + Types: []string{"int", "text"}, + Values: []*command.Values{}, + }, + }, + }, }, - expected: `[{"last_insert_id":123,"rows_affected":456},{"error":"unique constraint failed"},{"columns":["column1","column2"],"types":["int","text"],"values":[[456,"declan"]]}]`, + expected: `[{"last_insert_id":123,"rows_affected":456},{"error":"unique constraint failed"},{"columns":["column1","column2"],"types":["int","text"],"values":[[456,"declan"]]},{"columns":["column1","column2"],"types":["int","text"]}]`, }, } @@ -551,8 +560,26 @@ func Test_MarshalExecuteQueryAssociativeResponse(t *testing.T) { }, }, }, + { + Result: &command.ExecuteQueryResponse_Q{ + Q: &command.QueryRows{ + Columns: []string{"aaa", "bbb"}, + Types: []string{"int", "text"}, + Values: []*command.Values{}, + }, + }, + }, + { + Result: &command.ExecuteQueryResponse_Q{ + Q: &command.QueryRows{ + Columns: []string{"ccc", "ddd"}, + Types: []string{"int", "text"}, + Values: nil, + }, + }, + }, }, - expected: `[{"last_insert_id":123,"rows_affected":456,"rows":null},{"error":"unique constraint failed"},{"types":{"column1":"int","column2":"text"},"rows":[{"column1":456,"column2":"declan"}]}]`, + expected: `[{"last_insert_id":123,"rows_affected":456,"rows":null},{"error":"unique constraint failed"},{"types":{"column1":"int","column2":"text"},"rows":[{"column1":456,"column2":"declan"}]},{"types":{"aaa":"int","bbb":"text"},"rows":[]},{"types":{"ccc":"int","ddd":"text"},"rows":[]}]`, }, } diff --git a/store/store_test.go b/store/store_test.go index 667461f1..ac8d5854 100644 --- a/store/store_test.go +++ b/store/store_test.go @@ -2305,6 +2305,26 @@ func Test_MultiNodeExecuteQueryFreshness(t *testing.T) { if exp, got := `[[1,"fiona"]]`, asJSON(r[0].Values); exp != got { t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got) } + + // Check Stale-read detection works with Requests too. + eqr := executeQueryRequestFromString("SELECT * FROM foo", command.ExecuteQueryRequest_QUERY_REQUEST_LEVEL_NONE, + false, false) + eqr.Freshness = mustParseDuration("1ns").Nanoseconds() + _, err = s1.Request(eqr) + if err == nil { + t.Fatalf("freshness violating request didn't return an error") + } + if err != ErrStaleRead { + t.Fatalf("freshness violating request returned wrong error: %s", err.Error()) + } + eqr.Freshness = 0 + eqresp, err := s1.Request(eqr) + if err != nil { + t.Fatalf("inactive freshness violating request returned an error") + } + if exp, got := `[{"columns":["id","name"],"types":["integer","text"],"values":[[1,"fiona"]]}]`, asJSON(eqresp); exp != got { + t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got) + } } func Test_StoreLogTruncationMultinode(t *testing.T) { @@ -2933,6 +2953,10 @@ func queryRequestFromStrings(s []string, timings, tx bool) *command.QueryRequest } } +func executeQueryRequestFromString(s string, lvl command.ExecuteQueryRequest_Level, timings, tx bool) *command.ExecuteQueryRequest { + return executeQueryRequestFromStrings([]string{s}, lvl, timings, tx) +} + func executeQueryRequestFromStrings(s []string, lvl command.ExecuteQueryRequest_Level, timings, tx bool) *command.ExecuteQueryRequest { stmts := make([]*command.Statement, len(s)) for i := range s {