Skip to content

Commit

Permalink
Rudimentary REPL implementation to allow you to run BQL statements.
Browse files Browse the repository at this point in the history
  • Loading branch information
xllora committed Mar 3, 2016
1 parent b53cf82 commit 58d877c
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 16 deletions.
2 changes: 1 addition & 1 deletion storage/memory/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func NewStore() storage.Store {

// Name returns the ID of the backend being used.
func (s *memoryStore) Name(ctx context.Context) string {
return "MEMORY_STORE"
return "VOLATILE"
}

// Version returns the version of the driver implementation.
Expand Down
2 changes: 2 additions & 0 deletions tools/vcli/bw/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/google/badwolf/storage"
"github.com/google/badwolf/tools/vcli/bw/assert"
"github.com/google/badwolf/tools/vcli/bw/command"
"github.com/google/badwolf/tools/vcli/bw/repl"
"github.com/google/badwolf/tools/vcli/bw/run"
"github.com/google/badwolf/tools/vcli/bw/version"
"github.com/google/badwolf/triple/literal"
Expand Down Expand Up @@ -98,6 +99,7 @@ func InitializeCommands(driver storage.Store, chanSize int) []*command.Command {
return []*command.Command{
assert.New(driver, literal.DefaultBuilder(), chanSize),
run.New(driver, chanSize),
repl.New(driver, chanSize),
version.New(),
}
}
Expand Down
9 changes: 9 additions & 0 deletions tools/vcli/bw/io/io.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ import (
"strings"
)

// GetStatementsFromFile returns the statements found in the provided file.
func GetStatementsFromFile(path string) ([]string, error) {
stms, err := ReadLines(path)
if err != nil {
return nil, err
}
return stms, nil
}

// ReadLines from a file into a string array.
func ReadLines(path string) ([]string, error) {
f, err := os.Open(path)
Expand Down
161 changes: 161 additions & 0 deletions tools/vcli/bw/repl/repl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
// Copyright 2016 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package repl contains the implementation of the command that prints the
// BQL version.
package repl

import (
"bufio"
"fmt"
"os"
"strings"
"time"

"golang.org/x/net/context"

"github.com/google/badwolf/bql/grammar"
"github.com/google/badwolf/bql/planner"
"github.com/google/badwolf/bql/semantic"
"github.com/google/badwolf/bql/table"
"github.com/google/badwolf/bql/version"
"github.com/google/badwolf/storage"
"github.com/google/badwolf/tools/vcli/bw/command"
"github.com/google/badwolf/tools/vcli/bw/io"
)

const prompt = "bql> "

// New create the version command.
func New(driver storage.Store, chanSize int) *command.Command {
return &command.Command{
Run: func(ctx context.Context, args []string) int {
REPL(driver, os.Stdin, simpleReadLine, chanSize)
return 0
},
UsageLine: "bql",
Short: "starts a REPL to run BQL statements.",
Long: "Starts a REPL from the command line to accept BQL statements. Type quit; to leave the REPL.",
}
}

type readLiner func(*os.File) <-chan string

// simpleReadline reads a line from the provided file. This does not support
// any advanced terminal functionalities.
//
// TODO(xllora): Replace simple reader for function that supports advanced
// teminal input.
func simpleReadLine(f *os.File) <-chan string {
c := make(chan string)
go func() {
defer close(c)
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
c <- strings.TrimSpace(scanner.Text())
}
}()
return c
}

// REPL starts a read-evaluation-print-loop to run BQL commands.
func REPL(driver storage.Store, input *os.File, rl readLiner, chanSize int) int {
ctx := context.Background()
fmt.Printf("Welcome to BadWolf vCli (%d.%d.%d-%s)\n", version.Major, version.Minor, version.Patch, version.Release)
fmt.Printf("Using driver %q. Type quit; to exit\n", driver.Name(ctx))
fmt.Printf("Session started at %v\n\n", time.Now())
defer func() {
fmt.Printf("\nThanks for all those BQL queries!\n\n")
}()
fmt.Print(prompt)
for l := range rl(input) {
if strings.HasPrefix(l, "quit") {
break
}
if strings.HasPrefix(l, "help") {
printHelp()
fmt.Print(prompt)
continue
}
if strings.HasPrefix(l, "run") {
path, cmds, err := loadData(ctx, driver, chanSize, l)
if err != nil {
fmt.Printf("[ERROR] %s\n\n", err)
} else {
fmt.Printf("Loaded %q and run %d BQL commands successfully\n\n", path, cmds)
}
fmt.Print(prompt)
continue
}
table, err := runBQL(ctx, l, driver, chanSize)
if err != nil {
fmt.Printf("[ERROR] %s\n\n", err)
} else {
fmt.Println(table.String())
}
fmt.Print(prompt)
}
return 0
}

// printHelp prints help for the console commands.
func printHelp() {
fmt.Println("help - prints help for the bw console.")
fmt.Println("run <file_with_bql_statements> - quits the console.")
fmt.Println("quit - quits the console.")
fmt.Println()
}

// loadData loads all the triples in the file into the current driver.
func loadData(ctx context.Context, driver storage.Store, chanSize int, line string) (string, int, error) {
ss := strings.Split(strings.TrimSpace(line), " ")
if len(ss) != 2 {
return "", 0, fmt.Errorf("wrong syntax: run <file_with_bql_statements>")
}
path := ss[1]
lines, err := io.GetStatementsFromFile(path)
if err != nil {
return "", 0, fmt.Errorf("failed to read file %q with error %v on\n", path, err)
}
for idx, stm := range lines {
fmt.Printf("Processing statement (%d/%d)\n", idx+1, len(lines))
_, err := runBQL(ctx, stm, driver, chanSize)
if err != nil {
return "", 0, fmt.Errorf("%v on\n%s\n", err, stm)
}
}
fmt.Println()
return path, len(lines), nil
}

// runBQL attemps to excecute the provided query against the given store.
func runBQL(ctx context.Context, bql string, s storage.Store, chanSize int) (*table.Table, error) {
p, err := grammar.NewParser(grammar.SemanticBQL())
if err != nil {
return nil, fmt.Errorf("failed to initilize a valid BQL parser")
}
stm := &semantic.Statement{}
if err := p.Parse(grammar.NewLLk(bql, 1), stm); err != nil {
return nil, fmt.Errorf("failed to parse BQL statement with error %v", err)
}
pln, err := planner.New(ctx, s, stm, chanSize)
if err != nil {
return nil, fmt.Errorf("should have not failed to create a plan using memory.DefaultStorage for statement %v with error %v", stm, err)
}
res, err := pln.Excecute(ctx)
if err != nil {
return nil, fmt.Errorf("planner.Execute: failed to execute insert plan with error %v", err)
}
return res, nil
}
11 changes: 1 addition & 10 deletions tools/vcli/bw/run/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func runCommand(ctx context.Context, cmd *command.Command, args []string, store
return 2
}
file := strings.TrimSpace(args[len(args)-1])
lines, err := getStatementsFromFile(file)
lines, err := io.GetStatementsFromFile(file)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to read file %s\n\n\t%v\n\n", file, err)
return 2
Expand Down Expand Up @@ -98,12 +98,3 @@ func runBQL(ctx context.Context, bql string, s storage.Store, chanSize int) (*ta
}
return res, nil
}

// getStatementsFromFile returns the statements found in the provided file.
func getStatementsFromFile(path string) ([]string, error) {
stms, err := io.ReadLines(path)
if err != nil {
return nil, err
}
return stms, nil
}
5 changes: 0 additions & 5 deletions tools/vcli/bw/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,6 @@ import (
"github.com/google/badwolf/tools/vcli/bw/command"
)

var stage = "alpha"
var major = 0
var minor = 1
var patch = "dev"

// New create the version command.
func New() *command.Command {
return &command.Command{
Expand Down

0 comments on commit 58d877c

Please sign in to comment.