Skip to content
This repository has been archived by the owner on Aug 18, 2020. It is now read-only.

Commit

Permalink
Merge pull request #60 from dadleyy/GH-59/store-interfaces
Browse files Browse the repository at this point in the history
store interfaces + feature code consolidation
  • Loading branch information
dadleyy authored Nov 12, 2017
2 parents f6d46a5 + 6c1b2d1 commit 50beffd
Show file tree
Hide file tree
Showing 28 changed files with 678 additions and 380 deletions.
1 change: 0 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ example: $(LIBRARY_EXAMPLE_SRC) $(LIBRARY_EXAMPLE_MAIN) $(EXE)

test-example: example
mkdir -p $(LIBRARY_COVERAGE_OUTPUT_DIR)
$(EXE) -input=$(LIBRARY_EXAMPLE_MODEL_DIR)
$(GO) test $(LIBRARY_EXAMPLE_TEST_FLAGS) -p=$(MAX_TEST_CONCURRENCY) $(LIBRARY_EXAMPLE_MODEL_DIR)
$(GO) tool cover -html $(LIBRARY_EXAMPLE_COVERAGE_REPORT) -o $(LIBRARY_EXAMPLE_COVERAGE_DISTRIBUTABLE)
$(VET) $(VET_FLAGS) $(LIBRARY_EXAMPLE_MODEL_DIR)
Expand Down
4 changes: 2 additions & 2 deletions examples/library/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ func main() {
NameLike: []string{"danny"},
})

authorStore := models.AuthorStore{DB: db}
authorStore := models.NewAuthorStore(db)

a, e := authorStore.FindAuthors(&models.AuthorBlueprint{
ID: []int{1, 2, 3},
Expand All @@ -133,7 +133,7 @@ func main() {
log.Printf("found author name[%s]", author.Name)
}

bookStore := models.BookStore{DB: db}
bookStore := models.NewBookStore(db)
b, e := bookStore.FindBooks(&models.BookBlueprint{
ID: []int{1, 2},
})
Expand Down
4 changes: 2 additions & 2 deletions examples/library/models/author_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func addAuthorRow(db *sql.DB, values ...[]string) error {
func Test_Author(t *testing.T) {
g := goblin.Goblin(t)
var db *sql.DB
var store *AuthorStore
var store AuthorStore

dbFile := "author-testing.db"
generatedAuthorCount := 150
Expand Down Expand Up @@ -120,7 +120,7 @@ func Test_Author(t *testing.T) {
})

g.BeforeEach(func() {
store = &AuthorStore{DB: db}
store = NewAuthorStore(db)
})

g.After(func() {
Expand Down
4 changes: 2 additions & 2 deletions examples/library/models/book_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func addBookRow(db *sql.DB, values ...[]string) error {

func Test_Book(t *testing.T) {
var db *sql.DB
var store *BookStore
var store BookStore

g := goblin.Goblin(t)
testBookCount := 150
Expand Down Expand Up @@ -67,7 +67,7 @@ func Test_Book(t *testing.T) {
})

g.BeforeEach(func() {
store = &BookStore{DB: db}
store = NewBookStore(db)
})

g.After(func() {
Expand Down
101 changes: 43 additions & 58 deletions marlow/features/blueprint.go → marlow/blueprint.go
Original file line number Diff line number Diff line change
@@ -1,29 +1,18 @@
package features
package marlow

import "io"
import "fmt"
import "sync"
import "strings"
import "net/url"
import "github.com/gedex/inflector"
import "github.com/dadleyy/marlow/marlow/writing"
import "github.com/dadleyy/marlow/marlow/constants"

type blueprint struct {
record url.Values
fields map[string]url.Values
}

func (p blueprint) Name() string {
singular := inflector.Singularize(p.record.Get(constants.RecordNameConfigOption))
return fmt.Sprintf("%sBlueprint", singular)
}

func writeBlueprint(destination io.Writer, bp blueprint, imports chan<- string) error {
func writeBlueprint(destination io.Writer, record marlowRecord) error {
out := writing.NewGoWriter(destination)

e := out.WithStruct(bp.Name(), func(url.Values) error {
for name, config := range bp.fields {
e := out.WithStruct(record.blueprint(), func(url.Values) error {
for name, config := range record.fields {
fieldType := config.Get("type")

if fieldType == "" {
Expand All @@ -32,16 +21,16 @@ func writeBlueprint(destination io.Writer, bp blueprint, imports chan<- string)

// Support IN lookup on string fields.
if fieldType == "int" {
out.Println("%s%s []int", name, bp.record.Get(constants.BlueprintRangeFieldSuffixConfigOption))
out.Println("%s%s []int", name, record.config.Get(constants.BlueprintRangeFieldSuffixConfigOption))
}

// Support LIKE lookup on string fields.
if fieldType == "string" {
out.Println("%s%s []string", name, bp.record.Get(constants.BlueprintLikeFieldSuffixConfigOption))
out.Println("%s%s []string", name, record.config.Get(constants.BlueprintLikeFieldSuffixConfigOption))
}

if fieldImport := config.Get("import"); fieldImport != "" {
imports <- fieldImport
record.registerImports(fieldImport)
}

out.Println("%s []%s", name, fieldType)
Expand All @@ -59,8 +48,7 @@ func writeBlueprint(destination io.Writer, bp blueprint, imports chan<- string)
return e
}

imports <- "fmt"
imports <- "strings"
record.registerImports("fmt", "strings")

var readers []io.Reader
methodReceiver := make(chan string)
Expand All @@ -75,8 +63,8 @@ func writeBlueprint(destination io.Writer, bp blueprint, imports chan<- string)
wg.Done()
}()

for name, config := range bp.fields {
fieldGenerators := fieldMethods(bp, name, config, methodReceiver)
for name, config := range record.fields {
fieldGenerators := fieldMethods(record, name, config, methodReceiver)

if len(fieldGenerators) == 0 {
continue
Expand All @@ -100,7 +88,7 @@ func writeBlueprint(destination io.Writer, bp blueprint, imports chan<- string)
// With all of our fields having generated non-exported clause generation methods on our struct, we can create the
// final 'String' method which iterates over all of these, calling them and adding the non-empty string clauses to
// a list, which eventually is returned as a joined string.
e = out.WithMethod("String", bp.Name(), nil, []string{"string"}, func(scope url.Values) error {
e = out.WithMethod("String", record.blueprint(), nil, []string{"string"}, func(scope url.Values) error {
out.Println("%s := make([]string, 0, %d)", symbols.ClauseSlice, len(clauseMethods))

for _, method := range clauseMethods {
Expand All @@ -123,7 +111,7 @@ func writeBlueprint(destination io.Writer, bp blueprint, imports chan<- string)
return e
}

return out.WithMethod("Values", bp.Name(), nil, []string{"[]interface{}"}, func(scope url.Values) error {
return out.WithMethod("Values", record.blueprint(), nil, []string{"[]interface{}"}, func(scope url.Values) error {
out.Println("%s := make([]interface{}, 0, %d)", symbols.ClauseSlice, len(clauseMethods))

out.WithIf("%s == nil", func(url.Values) error {
Expand All @@ -144,24 +132,24 @@ func writeBlueprint(destination io.Writer, bp blueprint, imports chan<- string)
})
}

func fieldMethods(print blueprint, name string, config url.Values, methods chan<- string) []io.Reader {
func fieldMethods(record marlowRecord, name string, config url.Values, methods chan<- string) []io.Reader {
fieldType := config.Get("type")
results := make([]io.Reader, 0, len(print.fields))
results := make([]io.Reader, 0, len(record.fields))

if fieldType == "string" || fieldType == "int" {
results = append(results, simpleTypeIn(print, name, config, methods))
results = append(results, simpleTypeIn(record, name, config, methods))
}

if fieldType == "string" {
results = append(results, stringMethods(print, name, config, methods))
results = append(results, stringMethods(record, name, config, methods))
}

if fieldType == "int" {
results = append(results, numericalMethods(print, name, config, methods))
results = append(results, numericalMethods(record, name, config, methods))
}

if fieldType == "sql.NullInt64" {
results = append(results, nullableIntMethods(print, name, config, methods))
results = append(results, nullableIntMethods(record, name, config, methods))
}

if len(results) == 0 {
Expand All @@ -173,10 +161,9 @@ func fieldMethods(print blueprint, name string, config url.Values, methods chan<
return results
}

func nullableIntMethods(print blueprint, fieldName string, config url.Values, methods chan<- string) io.Reader {
func nullableIntMethods(record marlowRecord, fieldName string, config url.Values, methods chan<- string) io.Reader {
pr, pw := io.Pipe()
columnName := config.Get(constants.ColumnConfigOption)
tableName := print.record.Get(constants.TableNameConfigOption)
methodName := fmt.Sprintf("%sInString", columnName)

symbols := struct {
Expand All @@ -186,13 +173,15 @@ func nullableIntMethods(print blueprint, fieldName string, config url.Values, me
JoinedValues string
}{"_placeholders", "_values", "_v", "_joined"}

columnReference := fmt.Sprintf("%s.%s", tableName, columnName)
columnReference := fmt.Sprintf("%s.%s", record.table(), columnName)

returns := []string{"string", "[]interface{}"}

write := func() {
writer := writing.NewGoWriter(pw)
writer.Comment("[marlow] nullable clause gen for \"%s\"", columnReference)

e := writer.WithMethod(methodName, print.Name(), nil, []string{"string", "[]interface{}"}, func(scope url.Values) error {
e := writer.WithMethod(methodName, record.blueprint(), nil, returns, func(scope url.Values) error {
fieldReference := fmt.Sprintf("%s.%s", scope.Get("receiver"), fieldName)

// Add conditional check for length presence on lookup slice.
Expand Down Expand Up @@ -224,7 +213,7 @@ func nullableIntMethods(print blueprint, fieldName string, config url.Values, me
writer.Println("%s := strings.Join(%s, \",\")", symbols.JoinedValues, symbols.PlaceholderSlice)
writer.Println(
"return fmt.Sprintf(\"%s.%s IN (%%s)\", %s), %s",
tableName,
record.table(),
columnName,
symbols.JoinedValues,
symbols.ValueSlice,
Expand All @@ -244,12 +233,11 @@ func nullableIntMethods(print blueprint, fieldName string, config url.Values, me
return pr
}

func simpleTypeIn(print blueprint, fieldName string, config url.Values, methods chan<- string) io.Reader {
func simpleTypeIn(record marlowRecord, fieldName string, fieldConfig url.Values, methods chan<- string) io.Reader {
pr, pw := io.Pipe()
columnName := config.Get(constants.ColumnConfigOption)
tableName := print.record.Get(constants.TableNameConfigOption)
columnName := fieldConfig.Get(constants.ColumnConfigOption)
methodName := fmt.Sprintf("%sInString", columnName)
columnReference := fmt.Sprintf("%s.%s", tableName, columnName)
columnReference := fmt.Sprintf("%s.%s", record.table(), columnName)

symbols := struct {
PlaceholderSlice string
Expand All @@ -258,11 +246,13 @@ func simpleTypeIn(print blueprint, fieldName string, config url.Values, methods
JoinedValues string
}{"_placeholder", "_values", "_v", "_joined"}

returns := []string{"string", "[]interface{}"}

write := func() {
writer := writing.NewGoWriter(pw)
writer.Comment("[marlow] type IN clause for \"%s\"", columnReference)

e := writer.WithMethod(methodName, print.Name(), nil, []string{"string", "[]interface{}"}, func(scope url.Values) error {
e := writer.WithMethod(methodName, record.blueprint(), nil, returns, func(scope url.Values) error {
fieldReference := fmt.Sprintf("%s.%s", scope.Get("receiver"), fieldName)

// Add conditional check for length presence on lookup slice.
Expand Down Expand Up @@ -302,11 +292,12 @@ func simpleTypeIn(print blueprint, fieldName string, config url.Values, methods
return pr
}

func stringMethods(print blueprint, name string, config url.Values, methods chan<- string) io.Reader {
columnName := config.Get(constants.ColumnConfigOption)
func stringMethods(record marlowRecord, fieldName string, fieldConfig url.Values, methods chan<- string) io.Reader {
columnName := fieldConfig.Get(constants.ColumnConfigOption)
methodName := fmt.Sprintf("%sLikeString", columnName)
likeFieldName := fmt.Sprintf("%s%s", name, print.record.Get(constants.BlueprintLikeFieldSuffixConfigOption))
columnReference := fmt.Sprintf("%s.%s", print.record.Get(constants.TableNameConfigOption), columnName)
likeSuffix := record.config.Get(constants.BlueprintLikeFieldSuffixConfigOption)
likeFieldName := fmt.Sprintf("%s%s", fieldName, likeSuffix)
columnReference := fmt.Sprintf("%s.%s", record.table(), columnName)

symbols := struct {
PlaceholderSlice string
Expand All @@ -323,7 +314,7 @@ func stringMethods(print blueprint, name string, config url.Values, methods chan
writer := writing.NewGoWriter(pw)
writer.Comment("[marlow] string LIKE clause for \"%s\"", columnReference)

e := writer.WithMethod(methodName, print.Name(), nil, returns, func(scope url.Values) error {
e := writer.WithMethod(methodName, record.blueprint(), nil, returns, func(scope url.Values) error {
likeSlice := fmt.Sprintf("%s.%s", scope.Get("receiver"), likeFieldName)

writer.WithIf("%s == nil || %s == nil || len(%s) == 0", func(url.Values) error {
Expand Down Expand Up @@ -358,12 +349,11 @@ func stringMethods(print blueprint, name string, config url.Values, methods chan
return pr
}

func numericalMethods(print blueprint, name string, config url.Values, methods chan<- string) io.Reader {
tableName := print.record.Get(constants.TableNameConfigOption)
columnName := config.Get(constants.ColumnConfigOption)
func numericalMethods(record marlowRecord, fieldName string, fieldConfig url.Values, methods chan<- string) io.Reader {
columnName := fieldConfig.Get(constants.ColumnConfigOption)
rangeMethodName := fmt.Sprintf("%sRangeString", columnName)
rangeFieldName := fmt.Sprintf("%s%s", name, print.record.Get(constants.BlueprintRangeFieldSuffixConfigOption))
columnReference := fmt.Sprintf("%s.%s", tableName, columnName)
rangeFieldName := fmt.Sprintf("%s%s", fieldName, record.config.Get(constants.BlueprintRangeFieldSuffixConfigOption))
columnReference := fmt.Sprintf("%s.%s", record.table(), columnName)

pr, pw := io.Pipe()

Expand All @@ -377,7 +367,7 @@ func numericalMethods(print blueprint, name string, config url.Values, methods c
writer := writing.NewGoWriter(pw)
writer.Comment("[marlow] range clause methods for %s", columnReference)

e := writer.WithMethod(rangeMethodName, print.Name(), nil, returns, func(scope url.Values) error {
e := writer.WithMethod(rangeMethodName, record.blueprint(), nil, returns, func(scope url.Values) error {
receiver := scope.Get("receiver")
rangeArray := fmt.Sprintf("%s.%s", receiver, rangeFieldName)

Expand Down Expand Up @@ -408,16 +398,11 @@ func numericalMethods(print blueprint, name string, config url.Values, methods c
}

// NewBlueprintGenerator returns a reader that will generate the basic query struct type used for record lookups.
func NewBlueprintGenerator(record url.Values, fields map[string]url.Values, imports chan<- string) io.Reader {
func newBlueprintGenerator(record marlowRecord) io.Reader {
pr, pw := io.Pipe()

go func() {
bp := blueprint{
record: record,
fields: fields,
}

e := writeBlueprint(pw, bp, imports)
e := writeBlueprint(pw, record)
pw.CloseWithError(e)
}()

Expand Down
Loading

0 comments on commit 50beffd

Please sign in to comment.