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:
parent
ad7649806b
commit
21c2d75d07
11 changed files with 304 additions and 299 deletions
454
cayley_test.go
454
cayley_test.go
File diff suppressed because it is too large
Load diff
25
db/repl.go
25
db/repl.go
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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: "",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue