Skip to content

Commit

Permalink
Code compiling
Browse files Browse the repository at this point in the history
  • Loading branch information
eatonphil committed Mar 1, 2020
1 parent 0e77cd6 commit e4ec0ef
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 73 deletions.
12 changes: 8 additions & 4 deletions ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,13 @@ const (
insertKind
)

type ast struct {
slct *SelectStatement
crtTbl *CreateTableStatement
inst *InsertStatement
type Statement struct {
SelectStatement *SelectStatement
CreateTableStatement *CreateTableStatement
InsertStatement *InsertStatement
kind astKind
}

type Ast struct {
Statements []*Statement
}
21 changes: 14 additions & 7 deletions cmd/main.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
package main

import "github.com/eatonphil/gosql"
import (
"bytes"
"fmt"

"github.com/eatonphil/gosql"
)

func main() {
mb := gosql.NewMemoryBackend()

ast, err := gosql.Parse("CREATE TABLE users (id INT, name TEXT); INSERT INTO users VALUES (1, 'Admin'); SELECT id, name FROM users")
source := bytes.NewBufferString("CREATE TABLE users (id INT, name TEXT); INSERT INTO users VALUES (1, 'Admin'); SELECT id, name FROM users")

ast, err := gosql.Parse(source)
if err != nil {
panic(err)
}
Expand All @@ -20,12 +27,12 @@ func main() {
panic(err)
}

results, err = mb.Select(ast.Statements[2].SelectStatement)
results, err := mb.Select(ast.Statements[2].SelectStatement)
if err != nil {
panic(err)
}

for _, col := range results.columns {
for _, col := range results.Columns {
fmt.Printf("| %s ", col.Name)
}
fmt.Println()
Expand All @@ -37,9 +44,9 @@ func main() {
typ := results.Columns[i].Type
s := ""
switch typ {
case gosql.Int:
s = fmt.Printf("%d", cell.AsInt())
case gosql.Text:
case gosql.IntType:
s = fmt.Sprintf("%d", cell.AsInt())
case gosql.TextType:
s = cell.AsText()
}

Expand Down
10 changes: 9 additions & 1 deletion interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,16 @@ type Cell interface {
AsInt() int
}

type Results struct {
Columns []struct{
Type ColumnType
Name string
}
Rows [][]Cell
}

type Backend interface {
CreateTable(*CreateTableStatement) error
Insert(*InsertStatement) error
Select(*SelectStatement) ([][]Cell, error)
Select(*SelectStatement) (*Results, error)
}
48 changes: 37 additions & 11 deletions memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (mb *MemoryBackend) tokenToCell(t *token) MemoryCell {
return nil
}

func (mb *MemoryBackend) Select(slct *SelectStatement) ([][]MemoryCell, error) {
func (mb *MemoryBackend) Select(slct *SelectStatement) (*Results, error) {
table := table{}

if slct.from != nil && slct.from.table != nil {
Expand All @@ -63,17 +63,20 @@ func (mb *MemoryBackend) Select(slct *SelectStatement) ([][]MemoryCell, error) {
}
}

results := [][]MemoryCell{}

if slct.item == nil || len(*slct.item) == 0 {
return results, nil
return &Results{}, nil
}

results := [][]Cell{}
columns := []struct{
Type ColumnType
Name string
}{}
if len(table.rows) > 0 {
for _, row := range table.rows {
result := []MemoryCell{}
result := []Cell{}

resultRow := []MemoryCell{}
resultRow := []Cell{}
for _, col := range *slct.item {
if col.asterisk {
// TODO: handle asterisk
Expand All @@ -93,6 +96,14 @@ func (mb *MemoryBackend) Select(slct *SelectStatement) ([][]MemoryCell, error) {
found := false
for i, tableCol := range table.columns {
if tableCol == lit.value {
columns = append(columns, struct{
Type ColumnType
Name string
}{
Type: table.columnTypes[i],
Name: lit.value,
})

resultRow = append(resultRow, row[i])
found = true
break
Expand All @@ -107,6 +118,18 @@ func (mb *MemoryBackend) Select(slct *SelectStatement) ([][]MemoryCell, error) {
}

if lit.kind == numericKind || lit.kind == stringKind {
columnType := IntType
if lit.kind == stringKind {
columnType = TextType
}

columns = append(columns, struct{
Type ColumnType
Name string
}{
Type: columnType,
Name: col.exp.literal.value,
})
resultRow = append(resultRow, mb.tokenToCell(lit))
continue
}
Expand All @@ -128,15 +151,18 @@ func (mb *MemoryBackend) Select(slct *SelectStatement) ([][]MemoryCell, error) {
}
}

return results, nil
return &Results{
Columns: columns,
Rows: results,
}, nil
}

func (mb *MemoryBackend) Insert(inst *InsertStatement) {

func (mb *MemoryBackend) Insert(inst *InsertStatement) (error) {
return nil
}

func (mb *MemoryBackend) CreateTable(crt *CreateTableStatement) {

func (mb *MemoryBackend) CreateTable(crt *CreateTableStatement) (error) {
return nil
}

func NewMemoryBackend() *MemoryBackend {
Expand Down
11 changes: 7 additions & 4 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,26 +193,29 @@ func parseSelectStatement(tokens []*token, initialCursor uint, delimiter token)
return &slct, cursor, true
}

func parse(source io.Reader) (*ast, error) {
func Parse(source io.Reader) (*Ast, error) {
tokens, err := lex(source)
if err != nil {
return nil, err
}

a := ast{}
a := Ast{}
cursor := uint(0)
for cursor < uint(len(tokens)) {
stmt := &Statement{}
slct, newCursor, ok := parseSelectStatement(tokens, cursor, semicolonToken)
if ok {
a.kind = selectKind
a.slct = slct
stmt.kind = selectKind
stmt.SelectStatement = slct
cursor = newCursor
}

if !ok {
return nil, errors.New("Failed to parse")
}

a.Statements = append(a.Statements, stmt)

if !expectToken(tokens, cursor, semicolonToken) {
helpMessage(tokens, cursor, "Expected semi-colon delimiter between statements")
return nil, errors.New("Missing semi-colon between statements")
Expand Down
100 changes: 54 additions & 46 deletions parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,28 @@ import (
func TestParse(t *testing.T) {
tests := []struct {
source string
ast *ast
ast *Ast
}{
{
source: "SELECT *, exclusive",
ast: &ast{
kind: selectKind,
slct: &SelectStatement{
item: &[]*selectItem{
{
asterisk: true,
},
{
exp: &expression{
kind: literalKind,
literal: &token{
loc: location{col: 9, line: 0},
kind: identifierKind,
value: "exclusive",
ast: &Ast{
Statements: []*Statement{
{
kind: selectKind,
SelectStatement: &SelectStatement{
item: &[]*selectItem{
{
asterisk: true,
},
{
exp: &expression{
kind: literalKind,
literal: &token{
loc: location{col: 9, line: 0},
kind: identifierKind,
value: "exclusive",
},
},
},
},
},
Expand All @@ -37,41 +41,45 @@ func TestParse(t *testing.T) {
},
{
source: "SELECT id, name AS fullname FROM users",
ast: &ast{
kind: selectKind,
slct: &SelectStatement{
item: &[]*selectItem{
{
exp: &expression{
kind: literalKind,
literal: &token{
loc: location{col: 6, line: 0},
kind: identifierKind,
value: "id",
ast: &Ast{
Statements: []*Statement{
{
kind: selectKind,
SelectStatement: &SelectStatement{
item: &[]*selectItem{
{
exp: &expression{
kind: literalKind,
literal: &token{
loc: location{col: 6, line: 0},
kind: identifierKind,
value: "id",
},
},
},
{
exp: &expression{
kind: literalKind,
literal: &token{
loc: location{col: 10, line: 0},
kind: identifierKind,
value: "name",
},
},
as: &token{
loc: location{col: 18, line: 0},
kind: identifierKind,
value: "fullname",
},
},
},
},
{
exp: &expression{
kind: literalKind,
literal: &token{
loc: location{col: 10, line: 0},
from: &fromItem{
table: &token{
loc: location{col: 32, line: 0},
kind: identifierKind,
value: "name",
value: "users",
},
},
as: &token{
loc: location{col: 18, line: 0},
kind: identifierKind,
value: "fullname",
},
},
},
from: &fromItem{
table: &token{
loc: location{col: 32, line: 0},
kind: identifierKind,
value: "users",
},
},
},
Expand All @@ -80,7 +88,7 @@ func TestParse(t *testing.T) {
}

for _, test := range tests {
ast, err := parse(bytes.NewBufferString(test.source))
ast, err := Parse(bytes.NewBufferString(test.source))
assert.Nil(t, err, test.source)
assert.Equal(t, test.ast, ast, test.source)
}
Expand Down

0 comments on commit e4ec0ef

Please sign in to comment.