Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Jamess-Lucass committed May 22, 2024
1 parent 56a87ac commit 231abb3
Show file tree
Hide file tree
Showing 8 changed files with 349 additions and 46 deletions.
63 changes: 63 additions & 0 deletions module/gorm/apply.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package gorm

import (
"fmt"

"github.com/goatquery/goatquery-go"
"github.com/goatquery/goatquery-go/lexer"
"github.com/goatquery/goatquery-go/parser"
"gorm.io/gorm"
)

type SearchFunc = func(db *gorm.DB, searchTerm string) *gorm.DB

func Apply(db *gorm.DB, query goatquery.Query, model interface{}, searchFunc SearchFunc, options *goatquery.QueryOptions) (*gorm.DB, *int64, error) {
if options != nil && query.Top > options.MaxTop {
return nil, nil, fmt.Errorf("The value supplied for the query parameter 'Top' was greater than the maximum top allowed for this resource")
}

// Order by
if query.OrderBy != "" {
l := lexer.NewLexer(query.OrderBy)
p := parser.NewParser(l)

statements := p.ParseOrderBy()

for _, statement := range statements {
sql := fmt.Sprintf("%s %s", statement.TokenLiteral(), statement.Direction)

db = db.Order(sql)
}
}

// Search
if searchFunc != nil && query.Search != "" {
db = searchFunc(db, query.Search)
}

// Count
var count int64
if query.Count {
db.Model(&model).Count(&count)
}

// Skip
if query.Skip > 0 {
db = db.Offset(query.Skip)
}

// Top
if query.Top > 0 {
db = db.Limit(query.Top)
}

if query.Top <= 0 && options != nil && options.MaxTop > 0 {
db = db.Limit(options.MaxTop)
}

if query.Count {
return db, &count, nil
}

return db, nil, nil
}
275 changes: 275 additions & 0 deletions module/gorm/apply_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
package gorm

import (
"fmt"
"os"
"testing"

"github.com/glebarez/sqlite"
"github.com/goatquery/goatquery-go"
"github.com/stretchr/testify/assert"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)

type User struct {
Age uint
Firstname string
}

var DB *gorm.DB

func TestMain(m *testing.M) {
setup()
code := m.Run()
os.Exit(code)
}

func setup() {
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
})

if err != nil {
panic("failed to connect database")
}
DB = db

db.AutoMigrate(&User{})

if err := db.Model(&User{}).Create([]User{
{2, "John"},
{1, "Jane"},
{2, "Apple"},
{1, "Harry"},
{3, "Doe"},
{3, "Egg"},
}).Error; err != nil {
panic("failed to seed")
}
}

func Test_OrderBy(t *testing.T) {
tests := []struct {
input string
expected []User
}{
{"age desc, firstname asc", []User{
{3, "Doe"},
{3, "Egg"},
{2, "Apple"},
{2, "John"},
{1, "Harry"},
{1, "Jane"},
}},
}

for _, test := range tests {
query := goatquery.Query{
OrderBy: test.input,
}

var output []User
res, _, err := Apply(DB, query, &output, nil, nil)
assert.NoError(t, err)

err = res.Find(&output).Error
assert.NoError(t, err)

assert.Equal(t, test.expected, output)
}
}

func Test_Count(t *testing.T) {
tests := []struct {
input bool
expectedCount *int64
}{
{true, makeIntPointer(6)},
{false, nil},
}

for _, test := range tests {
query := goatquery.Query{
Count: test.input,
}

_, count, err := Apply(DB, query, &User{}, nil, nil)
assert.NoError(t, err)

assert.Equal(t, test.expectedCount, count)
}
}

func Test_Search(t *testing.T) {
tests := []struct {
input string
expectedCount int
}{
{"john", 1},
{"JOHN", 1},
{"j", 2},
{"e", 4},
{"eg", 1},
}

searchFunc := func(db *gorm.DB, searchTerm string) *gorm.DB {
return db.Where("firstname like ?", fmt.Sprintf("%%%s%%", searchTerm)) // Escape % for LIKE
}

for _, test := range tests {
query := goatquery.Query{
Search: test.input,
}

var output []User
res, _, err := Apply(DB, query, &output, searchFunc, nil)
assert.NoError(t, err)

err = res.Find(&output).Error
assert.NoError(t, err)

assert.Len(t, output, test.expectedCount)
}
}

func Test_Skip(t *testing.T) {
tests := []struct {
input int
expected []User
}{
{1, []User{
{1, "Jane"},
{2, "Apple"},
{2, "John"},
{3, "Doe"},
{3, "Egg"},
}},
{2, []User{
{2, "Apple"},
{2, "John"},
{3, "Doe"},
{3, "Egg"},
}},
{3, []User{
{2, "John"},
{3, "Doe"},
{3, "Egg"},
}},
{4, []User{
{3, "Doe"},
{3, "Egg"},
}},
{5, []User{
{3, "Egg"},
}},
{6, []User{}},
{10_000, []User{}},
}

for _, test := range tests {
query := goatquery.Query{
Skip: test.input,
OrderBy: "age asc, firstname asc",
}

var output []User
res, _, err := Apply(DB, query, &output, nil, nil)
assert.NoError(t, err)

err = res.Find(&output).Error
assert.NoError(t, err)

assert.Equal(t, test.expected, output)
}
}

func Test_Top(t *testing.T) {
tests := []struct {
input int
expectedCount int
}{
{-1, 6},
{0, 6},
{1, 1},
{2, 2},
{3, 3},
{4, 4},
{5, 5},
{100, 6},
{100_000, 6},
}

for _, test := range tests {
query := goatquery.Query{
Top: test.input,
}

var output []User
res, _, err := Apply(DB, query, &output, nil, nil)
assert.NoError(t, err)

err = res.Find(&output).Error
assert.NoError(t, err)

assert.Len(t, output, test.expectedCount)
}
}

func Test_TopWithMaxTop(t *testing.T) {
tests := []struct {
input int
expectedCount int
}{
{-1, 4},
{0, 4},
{1, 1},
{2, 2},
{3, 3},
{4, 4},
}

for _, test := range tests {
query := goatquery.Query{
Top: test.input,
}

options := goatquery.QueryOptions{
MaxTop: 4,
}

var output []User
res, _, err := Apply(DB, query, &output, nil, &options)
assert.NoError(t, err)

err = res.Find(&output).Error
assert.NoError(t, err)

assert.Len(t, output, test.expectedCount)
}
}

func Test_TopWithMaxTopReturnsError(t *testing.T) {
tests := []int{
5,
100,
100_000,
}

for _, test := range tests {
query := goatquery.Query{
Top: test,
}

options := goatquery.QueryOptions{
MaxTop: 4,
}

_, _, err := Apply(DB, query, &User{}, nil, &options)
assert.Error(t, err)
}
}

func makeIntPointer(v int64) *int64 {
return &v
}
1 change: 1 addition & 0 deletions module/gorm/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.22.0

require (
github.com/glebarez/sqlite v1.11.0
github.com/goatquery/goatquery-go v0.0.0-00010101000000-000000000000
github.com/stretchr/testify v1.9.0
gorm.io/gorm v1.25.10
)
Expand Down
11 changes: 0 additions & 11 deletions module/gorm/orderby.go

This file was deleted.

2 changes: 0 additions & 2 deletions module/gorm/parser.go

This file was deleted.

33 changes: 0 additions & 33 deletions module/gorm/parser_test.go

This file was deleted.

Loading

0 comments on commit 231abb3

Please sign in to comment.