Make query/... interfaces more idiomatic

Also revert the data type returned by queries to interface{} (the change
made sense at the time).
This commit is contained in:
kortschak 2015-02-10 10:06:57 +10:30
parent ad7649806b
commit 21c2d75d07
11 changed files with 304 additions and 299 deletions

File diff suppressed because it is too large Load diff

View file

@ -19,6 +19,7 @@ import (
"io"
"os"
"os/signal"
"strconv"
"strings"
"time"
@ -53,9 +54,9 @@ func Run(query string, ses query.Session) {
}()
fmt.Printf("\n")
c := make(chan interface{}, 5)
go ses.ExecInput(query, c, 100)
go ses.Execute(query, c, 100)
for res := range c {
fmt.Print(ses.ToText(res))
fmt.Print(ses.Format(res))
nResults++
}
if nResults > 0 {
@ -122,8 +123,22 @@ func Repl(h *graph.Handle, queryLanguage string, cfg *config.Config) error {
switch cmd {
case ":debug":
ses.ToggleDebug()
fmt.Println("Debug Toggled")
args = strings.TrimSpace(args)
var debug bool
switch args {
case "t":
debug = true
case "f":
// Do nothing.
default:
debug, err = strconv.ParseBool(args)
if err != nil {
fmt.Printf("Error: cannot parse %q as a valid boolean - acceptable values: 't'|'true' or 'f'|'false'\n", args)
continue
}
}
ses.Debug(debug)
fmt.Printf("Debug set to %t\n", debug)
continue
case ":a":
@ -155,7 +170,7 @@ func Repl(h *graph.Handle, queryLanguage string, cfg *config.Config) error {
code += line
result, err := ses.InputParses(code)
result, err := ses.Parse(code)
switch result {
case query.Parsed:
Run(code, ses)

View file

@ -30,9 +30,9 @@ var testSplitLines = []struct {
expectedArguments: " arg1 arg2 arg3 .",
},
{
line: ":debug",
expectedCommand: ":debug",
// expectedArguments is nil
line: ":debug t",
expectedCommand: ":debug",
expectedArguments: " t",
},
{
line: "",

View file

@ -49,21 +49,19 @@ func WrapResult(result interface{}) ([]byte, error) {
func Run(q string, ses query.HTTP) (interface{}, error) {
c := make(chan interface{}, 5)
go ses.ExecInput(q, c, 100)
go ses.Execute(q, c, 100)
for res := range c {
ses.BuildJSON(res)
ses.Collate(res)
}
return ses.GetJSON()
return ses.Results()
}
func GetQueryShape(q string, ses query.HTTP) ([]byte, error) {
c := make(chan map[string]interface{}, 5)
go ses.GetQuery(q, c)
var data map[string]interface{}
for res := range c {
data = res
s, err := ses.ShapeOf(q)
if err != nil {
return nil, err
}
return json.Marshal(data)
return json.Marshal(s)
}
// TODO(barakmich): Turn this into proper middleware.
@ -82,7 +80,7 @@ func (api *API) ServeV1Query(w http.ResponseWriter, r *http.Request, params http
return jsonResponse(w, 400, err)
}
code := string(bodyBytes)
result, err := ses.InputParses(code)
result, err := ses.Parse(code)
switch result {
case query.Parsed:
var output interface{}
@ -127,7 +125,7 @@ func (api *API) ServeV1Shape(w http.ResponseWriter, r *http.Request, params http
return jsonResponse(w, 400, err)
}
code := string(bodyBytes)
result, err := ses.InputParses(code)
result, err := ses.Parse(code)
switch result {
case query.Parsed:
var output []byte

View file

@ -265,7 +265,7 @@ var testQueries = []struct {
func runQueryGetTag(g []quad.Quad, query string, tag string) []string {
js := makeTestSession(g)
c := make(chan interface{}, 5)
js.ExecInput(query, c, -1)
js.Execute(query, c, -1)
var results []string
for res := range c {
@ -318,7 +318,7 @@ func TestIssue160(t *testing.T) {
ses := makeTestSession(issue160TestGraph)
c := make(chan interface{}, 5)
go ses.ExecInput(query, c, 100)
go ses.Execute(query, c, 100)
var got []string
for res := range c {
func() {
@ -327,7 +327,7 @@ func TestIssue160(t *testing.T) {
t.Errorf("Unexpected panic: %v", r)
}
}()
got = append(got, ses.ToText(res))
got = append(got, ses.Format(res))
}()
}
sort.Strings(got)

View file

@ -65,19 +65,21 @@ type Result struct {
actualResults map[string]graph.Value
}
func (s *Session) ToggleDebug() {
s.debug = !s.debug
func (s *Session) Debug(ok bool) {
s.debug = ok
}
func (s *Session) GetQuery(input string, out chan map[string]interface{}) {
defer close(out)
func (s *Session) ShapeOf(query string) (interface{}, error) {
// TODO(kortschak) It would be nice to be able
// to return an error for bad queries here.
s.wk.shape = make(map[string]interface{})
s.wk.env.Run(input)
out <- s.wk.shape
s.wk.env.Run(query)
out := s.wk.shape
s.wk.shape = nil
return out, nil
}
func (s *Session) InputParses(input string) (query.ParseResult, error) {
func (s *Session) Parse(input string) (query.ParseResult, error) {
script, err := s.wk.env.Compile("", input)
if err != nil {
return query.ParseFail, err
@ -130,7 +132,7 @@ func (s *Session) runUnsafe(input interface{}) (otto.Value, error) {
return env.Run(input)
}
func (s *Session) ExecInput(input string, out chan interface{}, _ int) {
func (s *Session) Execute(input string, out chan interface{}, _ int) {
defer close(out)
s.err = nil
s.wk.results = out
@ -153,7 +155,7 @@ func (s *Session) ExecInput(input string, out chan interface{}, _ int) {
s.wk.Unlock()
}
func (s *Session) ToText(result interface{}) string {
func (s *Session) Format(result interface{}) string {
data := result.(*Result)
if data.metaresult {
if data.err != nil {
@ -212,7 +214,7 @@ func (s *Session) ToText(result interface{}) string {
}
// Web stuff
func (s *Session) BuildJSON(result interface{}) {
func (s *Session) Collate(result interface{}) {
data := result.(*Result)
if !data.metaresult {
if data.val == nil {
@ -246,8 +248,8 @@ func (s *Session) BuildJSON(result interface{}) {
}
}
func (s *Session) GetJSON() ([]interface{}, error) {
defer s.ClearJSON()
func (s *Session) Results() (interface{}, error) {
defer s.Clear()
if s.err != nil {
return nil, s.err
}
@ -259,6 +261,6 @@ func (s *Session) GetJSON() ([]interface{}, error) {
}
}
func (s *Session) ClearJSON() {
func (s *Session) Clear() {
s.dataOutput = nil
}

View file

@ -170,11 +170,11 @@ var testQueries = []struct {
func runQuery(g []quad.Quad, query string) interface{} {
s := makeTestSession(g)
c := make(chan interface{}, 5)
go s.ExecInput(query, c, -1)
go s.Execute(query, c, -1)
for result := range c {
s.BuildJSON(result)
s.Collate(result)
}
result, _ := s.GetJSON()
result, _ := s.Results()
return result
}

View file

@ -108,8 +108,6 @@ func (p Path) ToResultPathFromMap(resultMap map[Path]string) ResultPath {
func NewQuery(ses *Session) *Query {
var q Query
q.ses = ses
q.results = make([]interface{}, 0)
q.resultOrder = make([]string, 0)
q.err = nil
return &q
}

View file

@ -38,16 +38,15 @@ func NewSession(qs graph.QuadStore) *Session {
return &m
}
func (s *Session) ToggleDebug() {
s.debug = !s.debug
func (s *Session) Debug(ok bool) {
s.debug = ok
}
func (s *Session) GetQuery(input string, out chan map[string]interface{}) {
defer close(out)
func (s *Session) ShapeOf(query string) (interface{}, error) {
var mqlQuery interface{}
err := json.Unmarshal([]byte(input), &mqlQuery)
err := json.Unmarshal([]byte(query), &mqlQuery)
if err != nil {
return
return nil, err
}
s.currentQuery = NewQuery(s)
s.currentQuery.BuildIteratorTree(mqlQuery)
@ -59,10 +58,10 @@ func (s *Session) GetQuery(input string, out chan map[string]interface{}) {
nodes = append(nodes, n)
}
output["nodes"] = nodes
out <- output
return output, nil
}
func (s *Session) InputParses(input string) (query.ParseResult, error) {
func (s *Session) Parse(input string) (query.ParseResult, error) {
var x interface{}
err := json.Unmarshal([]byte(input), &x)
if err != nil {
@ -71,7 +70,7 @@ func (s *Session) InputParses(input string) (query.ParseResult, error) {
return query.Parsed, nil
}
func (s *Session) ExecInput(input string, c chan interface{}, _ int) {
func (s *Session) Execute(input string, c chan interface{}, _ int) {
defer close(c)
var mqlQuery interface{}
err := json.Unmarshal([]byte(input), &mqlQuery)
@ -104,7 +103,7 @@ func (s *Session) ExecInput(input string, c chan interface{}, _ int) {
}
}
func (s *Session) ToText(result interface{}) string {
func (s *Session) Format(result interface{}) string {
tags := result.(map[string]graph.Value)
out := fmt.Sprintln("****")
tagKeys := make([]string, len(tags))
@ -127,11 +126,11 @@ func (s *Session) ToText(result interface{}) string {
return out
}
func (s *Session) BuildJSON(result interface{}) {
func (s *Session) Collate(result interface{}) {
s.currentQuery.treeifyResult(result.(map[string]graph.Value))
}
func (s *Session) GetJSON() ([]interface{}, error) {
func (s *Session) Results() (interface{}, error) {
s.currentQuery.buildResults()
if s.currentQuery.isError() {
return nil, s.currentQuery.err
@ -139,7 +138,7 @@ func (s *Session) GetJSON() ([]interface{}, error) {
return s.currentQuery.results, nil
}
func (s *Session) ClearJSON() {
func (s *Session) Clear() {
// Since we create a new Query underneath every query, clearing isn't necessary.
return
}

View file

@ -26,20 +26,19 @@ const (
type Session interface {
// Return whether the string is a valid expression.
InputParses(string) (ParseResult, error)
ExecInput(string, chan interface{}, int)
ToText(interface{}) string
ToggleDebug()
Parse(string) (ParseResult, error)
Execute(string, chan interface{}, int)
Format(interface{}) string
Debug(bool)
}
type HTTP interface {
// Return whether the string is a valid expression.
InputParses(string) (ParseResult, error)
Parse(string) (ParseResult, error)
// Runs the query and returns individual results on the channel.
ExecInput(string, chan interface{}, int)
GetQuery(string, chan map[string]interface{})
BuildJSON(interface{})
GetJSON() ([]interface{}, error)
ClearJSON()
ToggleDebug()
Execute(string, chan interface{}, int)
ShapeOf(string) (interface{}, error)
Collate(interface{})
Results() (interface{}, error)
Clear()
}

View file

@ -37,11 +37,11 @@ func NewSession(qs graph.QuadStore) *Session {
return &s
}
func (s *Session) ToggleDebug() {
s.debug = !s.debug
func (s *Session) Debug(ok bool) {
s.debug = ok
}
func (s *Session) InputParses(input string) (query.ParseResult, error) {
func (s *Session) Parse(input string) (query.ParseResult, error) {
var parenDepth int
for i, x := range input {
if x == '(' {
@ -67,7 +67,7 @@ func (s *Session) InputParses(input string) (query.ParseResult, error) {
return query.ParseFail, errors.New("invalid syntax")
}
func (s *Session) ExecInput(input string, out chan interface{}, limit int) {
func (s *Session) Execute(input string, out chan interface{}, limit int) {
it := BuildIteratorTreeForQuery(s.qs, input)
newIt, changed := it.Optimize()
if changed {
@ -104,7 +104,7 @@ func (s *Session) ExecInput(input string, out chan interface{}, limit int) {
close(out)
}
func (s *Session) ToText(result interface{}) string {
func (s *Session) Format(result interface{}) string {
out := fmt.Sprintln("****")
tags := result.(map[string]graph.Value)
tagKeys := make([]string, len(tags))