Skip to content

Commit

Permalink
Export more
Browse files Browse the repository at this point in the history
  • Loading branch information
eatonphil committed Jan 23, 2021
1 parent 323efd4 commit ca1f00e
Show file tree
Hide file tree
Showing 9 changed files with 806 additions and 777 deletions.
126 changes: 63 additions & 63 deletions ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,146 +5,146 @@ import (
"strings"
)

type expressionKind uint
type ExpressionKind uint

const (
literalKind expressionKind = iota
binaryKind
LiteralKind ExpressionKind = iota
BinaryKind
)

type binaryExpression struct {
a expression
b expression
op token
type BinaryExpression struct {
A Expression
B Expression
Op Token
}

func (be binaryExpression) generateCode() string {
return fmt.Sprintf("(%s %s %s)", be.a.generateCode(), be.op.value, be.b.generateCode())
func (be BinaryExpression) GenerateCode() string {
return fmt.Sprintf("(%s %s %s)", be.A.GenerateCode(), be.Op.Value, be.B.GenerateCode())
}

type expression struct {
literal *token
binary *binaryExpression
kind expressionKind
type Expression struct {
Literal *Token
Binary *BinaryExpression
Kind ExpressionKind
}

func (e expression) generateCode() string {
switch e.kind {
case literalKind:
switch e.literal.kind {
case identifierKind:
return fmt.Sprintf("\"%s\"", e.literal.value)
case stringKind:
return fmt.Sprintf("'%s'", e.literal.value)
func (e Expression) GenerateCode() string {
switch e.Kind {
case LiteralKind:
switch e.Literal.Kind {
case IdentifierKind:
return fmt.Sprintf("\"%s\"", e.Literal.Value)
case StringKind:
return fmt.Sprintf("'%s'", e.Literal.Value)
default:
return fmt.Sprintf(e.literal.value)
return fmt.Sprintf(e.Literal.Value)
}

case binaryKind:
return e.binary.generateCode()
case BinaryKind:
return e.Binary.GenerateCode()
}

return ""
}

type selectItem struct {
exp *expression
asterisk bool // for *
as *token
Exp *Expression
Asterisk bool // for *
As *Token
}

type SelectStatement struct {
item *[]*selectItem
from *token
where *expression
Item *[]*selectItem
From *Token
Where *Expression
}

func (ss SelectStatement) GenerateCode() string {
item := []string{}
for _, i := range *ss.item {
for _, i := range *ss.Item {
s := "\t*"
if !i.asterisk {
s = "\t" + i.exp.generateCode()
if !i.Asterisk {
s = "\t" + i.Exp.GenerateCode()

if i.as != nil {
s = fmt.Sprintf("\t%s AS \"%s\"", s, i.as.value)
if i.As != nil {
s = fmt.Sprintf("\t%s AS \"%s\"", s, i.As.Value)
}
}
item = append(item, s)
}

from := ""
if ss.from != nil {
from = fmt.Sprintf("\nFROM\n\t\"%s\"", ss.from.value)
if ss.From != nil {
from = fmt.Sprintf("\nFROM\n\t\"%s\"", ss.From.Value)
}

where := ""
if ss.where != nil {
where = fmt.Sprintf("\nWHERE\n\t%s", ss.where.generateCode())
if ss.Where != nil {
where = fmt.Sprintf("\nWHERE\n\t%s", ss.Where.GenerateCode())
}

return fmt.Sprintf("SELECT\n%s%s%s;", strings.Join(item, ",\n"), from, where)
}

type columnDefinition struct {
name token
datatype token
primaryKey bool
type ColumnDefinition struct {
Name Token
Datatype Token
PrimaryKey bool
}

type CreateTableStatement struct {
name token
cols *[]*columnDefinition
Name Token
Cols *[]*ColumnDefinition
}

func (cts CreateTableStatement) GenerateCode() string {
cols := []string{}
for _, col := range *cts.cols {
for _, col := range *cts.Cols {
modifiers := ""
if col.primaryKey {
if col.PrimaryKey {
modifiers += " " + "PRIMARY KEY"
}
spec := fmt.Sprintf("\t\"%s\" %s%s", col.name.value, strings.ToUpper(col.datatype.value), modifiers)
spec := fmt.Sprintf("\t\"%s\" %s%s", col.Name.Value, strings.ToUpper(col.Datatype.Value), modifiers)
cols = append(cols, spec)
}
return fmt.Sprintf("CREATE TABLE \"%s\" (\n%s\n);", cts.name.value, strings.Join(cols, ",\n"))
return fmt.Sprintf("CREATE TABLE \"%s\" (\n%s\n);", cts.Name.Value, strings.Join(cols, ",\n"))
}

type CreateIndexStatement struct {
name token
unique bool
primaryKey bool
table token
exp expression
Name Token
Unique bool
PrimaryKey bool
Table Token
Exp Expression
}

func (cis CreateIndexStatement) GenerateCode() string {
unique := ""
if cis.unique {
if cis.Unique {
unique = " UNIQUE"
}
return fmt.Sprintf("CREATE%s INDEX \"%s\" ON \"%s\" (%s);", unique, cis.name.value, cis.table.value, cis.exp.generateCode())
return fmt.Sprintf("CREATE%s INDEX \"%s\" ON \"%s\" (%s);", unique, cis.Name.Value, cis.Table.Value, cis.Exp.GenerateCode())
}

type DropTableStatement struct {
name token
Name Token
}

func (dts DropTableStatement) GenerateCode() string {
return fmt.Sprintf("DROP TABLE \"%s\";", dts.name.value)
return fmt.Sprintf("DROP TABLE \"%s\";", dts.Name.Value)
}

type InsertStatement struct {
table token
values *[]*expression
Table Token
Values *[]*Expression
}

func (is InsertStatement) GenerateCode() string {
values := []string{}
for _, exp := range *is.values {
values = append(values, exp.generateCode())
for _, exp := range *is.Values {
values = append(values, exp.GenerateCode())
}
return fmt.Sprintf("INSERT INTO \"%s\" VALUES (%s);", is.table.value, strings.Join(values, ", "))
return fmt.Sprintf("INSERT INTO \"%s\" VALUES (%s);", is.Table.Value, strings.Join(values, ", "))
}

type AstKind uint
Expand Down
54 changes: 27 additions & 27 deletions ast_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func TestStatement_GenerateCode(t *testing.T) {
`DROP TABLE "foo";`,
Statement{
DropTableStatement: &DropTableStatement{
name: token{value: "foo"},
Name: Token{Value: "foo"},
},
Kind: DropTableKind,
},
Expand All @@ -27,16 +27,16 @@ func TestStatement_GenerateCode(t *testing.T) {
);`,
Statement{
CreateTableStatement: &CreateTableStatement{
name: token{value: "users"},
cols: &[]*columnDefinition{
Name: Token{Value: "users"},
Cols: &[]*ColumnDefinition{
{
name: token{value: "id"},
datatype: token{value: "int"},
primaryKey: true,
Name: Token{Value: "id"},
Datatype: Token{Value: "int"},
PrimaryKey: true,
},
{
name: token{value: "name"},
datatype: token{value: "text"},
Name: Token{Value: "name"},
Datatype: Token{Value: "text"},
},
},
},
Expand All @@ -47,10 +47,10 @@ func TestStatement_GenerateCode(t *testing.T) {
`CREATE UNIQUE INDEX "age_idx" ON "users" ("age");`,
Statement{
CreateIndexStatement: &CreateIndexStatement{
name: token{value: "age_idx"},
unique: true,
table: token{value: "users"},
exp: expression{literal: &token{value: "age", kind: identifierKind}, kind: literalKind},
Name: Token{Value: "age_idx"},
Unique: true,
Table: Token{Value: "users"},
Exp: Expression{Literal: &Token{Value: "age", Kind: IdentifierKind}, Kind: LiteralKind},
},
Kind: CreateIndexKind,
},
Expand All @@ -59,11 +59,11 @@ func TestStatement_GenerateCode(t *testing.T) {
`INSERT INTO "foo" VALUES (1, 'flubberty', true);`,
Statement{
InsertStatement: &InsertStatement{
table: token{value: "foo"},
values: &[]*expression{
{literal: &token{value: "1", kind: numericKind}, kind: literalKind},
{literal: &token{value: "flubberty", kind: stringKind}, kind: literalKind},
{literal: &token{value: "true", kind: boolKind}, kind: literalKind},
Table: Token{Value: "foo"},
Values: &[]*Expression{
{Literal: &Token{Value: "1", Kind: NumericKind}, Kind: LiteralKind},
{Literal: &Token{Value: "flubberty", Kind: StringKind}, Kind: LiteralKind},
{Literal: &Token{Value: "true", Kind: BoolKind}, Kind: LiteralKind},
},
},
Kind: InsertKind,
Expand All @@ -79,18 +79,18 @@ WHERE
("id" = 2);`,
Statement{
SelectStatement: &SelectStatement{
item: &[]*selectItem{
{exp: &expression{literal: &token{value: "id", kind: identifierKind}, kind: literalKind}},
{exp: &expression{literal: &token{value: "name", kind: identifierKind}, kind: literalKind}},
Item: &[]*selectItem{
{Exp: &Expression{Literal: &Token{Value: "id", Kind: IdentifierKind}, Kind: LiteralKind}},
{Exp: &Expression{Literal: &Token{Value: "name", Kind: IdentifierKind}, Kind: LiteralKind}},
},
from: &token{value: "users"},
where: &expression{
binary: &binaryExpression{
a: expression{literal: &token{value: "id", kind: identifierKind}, kind: literalKind},
b: expression{literal: &token{value: "2", kind: numericKind}, kind: literalKind},
op: token{value: "=", kind: symbolKind},
From: &Token{Value: "users"},
Where: &Expression{
Binary: &BinaryExpression{
A: Expression{Literal: &Token{Value: "id", Kind: IdentifierKind}, Kind: LiteralKind},
B: Expression{Literal: &Token{Value: "2", Kind: NumericKind}, Kind: LiteralKind},
Op: Token{Value: "=", Kind: SymbolKind},
},
kind: binaryKind,
Kind: BinaryKind,
},
},
Kind: SelectKind,
Expand Down
29 changes: 29 additions & 0 deletions backend.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package gosql

import "errors"

type ColumnType uint

const (
Expand Down Expand Up @@ -60,3 +62,30 @@ type Backend interface {
Select(*SelectStatement) (*Results, error)
GetTables() []TableMetadata
}

// Useful to embed when prototyping new backends
type EmptyBackend struct{}

func (eb EmptyBackend) CreateTable(_ *CreateTableStatement) error {
return errors.New("Create not supported")
}

func (eb EmptyBackend) DropTable(_ *DropTableStatement) error {
return errors.New("Drop not supported")
}

func (eb EmptyBackend) CreateIndex(_ *CreateIndexStatement) error {
return errors.New("Create index not supported")
}

func (eb EmptyBackend) Insert(_ *InsertStatement) error {
return errors.New("Insert not supported")
}

func (eb EmptyBackend) Select(_ *SelectStatement) (*Results, error) {
return nil, errors.New("Select not supported")
}

func (eb EmptyBackend) GetTables() []TableMetadata {
return nil
}
Loading

0 comments on commit ca1f00e

Please sign in to comment.