[wip] add missing filters

Signed-off-by: Anton Nesterov <anton@demiurg.io>
This commit is contained in:
Anton Nesterov 2024-08-08 11:09:17 +02:00
parent d28d976b8e
commit 8e45c45624
No known key found for this signature in database
GPG key ID: 59121E8AE2851FB5
9 changed files with 209 additions and 5 deletions

1
pkg/dal/convert_test.go Normal file
View file

@ -0,0 +1 @@
package dal

7
pkg/dal/go.mod Normal file
View file

@ -0,0 +1,7 @@
module l12.xyz/dal
go 1.22.6
replace l12.xyz/dal/utils v0.0.0 => ../utils
replace l12.xyz/dal/filters v0.0.0 => ../filters

View file

@ -2,17 +2,20 @@ package filters
import ( import (
"fmt" "fmt"
"strings"
) )
type And struct { type And struct {
And []interface{} `json:"$and"` And []string `json:"$and"`
} }
func (a And) ToSQLPart(ctx Context) string { func (f And) ToSQLPart(ctx Context) string {
if f.And == nil {
fmt.Println(ctx, a)
return "" return ""
} }
value := strings.Join(f.And, " AND ")
return fmt.Sprintf("(%s)", value)
}
func (a And) FromJSON(data interface{}) Filter { func (a And) FromJSON(data interface{}) Filter {
return FromJson[And](data) return FromJson[And](data)

20
pkg/filters/Like.go Normal file
View file

@ -0,0 +1,20 @@
package filters
import "fmt"
type Like struct {
Like interface{} `json:"$like"`
}
func (f Like) FromJSON(data interface{}) Filter {
return FromJson[Like](data)
}
func (f Like) ToSQLPart(ctx Context) string {
if f.Like == nil {
return ""
}
name := ctx.GetFieldName()
value := ctx.NormalizeValue(f.Like)
return fmt.Sprintf("%s LIKE %v ESCAPE '\\'", name, value)
}

31
pkg/filters/NotIn.go Normal file
View file

@ -0,0 +1,31 @@
package filters
import (
"fmt"
"strings"
"l12.xyz/dal/utils"
)
type NotIn struct {
NotIn []interface{} `json:"$nin"`
}
func (f NotIn) FromJSON(data interface{}) Filter {
return FromJson[NotIn](data)
}
func (f NotIn) ToSQLPart(ctx Context) string {
if f.NotIn == nil {
return ""
}
name := ctx.GetFieldName()
values := utils.Map(f.NotIn, ctx.NormalizeValue)
data := make([]string, len(values))
for i, v := range values {
data[i] = fmt.Sprintf("%v", v)
}
value := strings.Join(data, ", ")
return fmt.Sprintf("%s NOT IN (%v)", name, value)
}

20
pkg/filters/NotLike.go Normal file
View file

@ -0,0 +1,20 @@
package filters
import "fmt"
type NotLike struct {
NotLike interface{} `json:"$nlike"`
}
func (f NotLike) FromJSON(data interface{}) Filter {
return FromJson[NotLike](data)
}
func (f NotLike) ToSQLPart(ctx Context) string {
if f.NotLike == nil {
return ""
}
name := ctx.GetFieldName()
value := ctx.NormalizeValue(f.NotLike)
return fmt.Sprintf("%s NOT LIKE %v ESCAPE '\\'", name, value)
}

22
pkg/filters/Or.go Normal file
View file

@ -0,0 +1,22 @@
package filters
import (
"fmt"
"strings"
)
type Or struct {
Or []string `json:"$or"`
}
func (f Or) ToSQLPart(ctx Context) string {
if f.Or == nil {
return ""
}
value := strings.Join(f.Or, " OR ")
return fmt.Sprintf("(%s)", value)
}
func (a Or) FromJSON(data interface{}) Filter {
return FromJson[Or](data)
}

View file

@ -1,6 +1,8 @@
package filters package filters
var FilterRegistry = map[string]Filter{ var FilterRegistry = map[string]Filter{
"And": &And{},
"Or": &Or{},
"Eq": &Eq{}, "Eq": &Eq{},
"Ne": &Ne{}, "Ne": &Ne{},
"Gt": &Gt{}, "Gt": &Gt{},
@ -8,9 +10,12 @@ var FilterRegistry = map[string]Filter{
"Lt": &Lt{}, "Lt": &Lt{},
"Lte": &Lte{}, "Lte": &Lte{},
"In": &In{}, "In": &In{},
"Nin": &NotIn{},
"Between": &Between{}, "Between": &Between{},
"NotBetween": &NotBetween{}, "NotBetween": &NotBetween{},
"Glob": &Glob{}, "Glob": &Glob{},
"Like": &Like{},
"NotLike": &NotLike{},
} }
func Convert(ctx Context, json interface{}) string { func Convert(ctx Context, json interface{}) string {

View file

@ -20,6 +20,22 @@ func TestEq(t *testing.T) {
} }
} }
func TestGte(t *testing.T) {
ctx := SQLiteContext{
TableAlias: "t",
FieldName: "test",
}
result := Convert(ctx, `{"$gte": 1}`)
resultMap := Convert(ctx, map[string]any{"$gte": 1})
if result != `t.test >= 1` {
t.Errorf("Expected t.test >= 1, got %s", result)
}
if resultMap != result {
t.Log(resultMap)
t.Errorf("Expected resultMap to be equal to result")
}
}
func TestNe(t *testing.T) { func TestNe(t *testing.T) {
ctx := SQLiteContext{ ctx := SQLiteContext{
FieldName: "test", FieldName: "test",
@ -50,6 +66,21 @@ func TestBetween(t *testing.T) {
} }
} }
func TestNotBetween(t *testing.T) {
ctx := SQLiteContext{
FieldName: "test",
}
result := Convert(ctx, `{"$nbetween": ["1", "5"]}`)
resultMap := Convert(ctx, map[string]any{"$nbetween": []string{"1", "5"}})
if result != `test NOT BETWEEN '1' AND '5'` {
t.Errorf("Expected test BETWEEN '1' AND '5', got %s", result)
}
if resultMap != result {
t.Log(resultMap)
t.Errorf("Expected resultMap to be equal to result")
}
}
func TestGlob(t *testing.T) { func TestGlob(t *testing.T) {
ctx := SQLiteContext{ ctx := SQLiteContext{
TableAlias: "t", TableAlias: "t",
@ -81,3 +112,67 @@ func TestIn(t *testing.T) {
t.Errorf("Expected resultMap to be equal to result") t.Errorf("Expected resultMap to be equal to result")
} }
} }
func TestNotIn(t *testing.T) {
ctx := SQLiteContext{
TableAlias: "t",
FieldName: "test",
}
result := Convert(ctx, `{"$nin": [1, 2, 3]}`)
resultMap := Convert(ctx, map[string]any{"$nin": []int{1, 2, 3}})
if result != `t.test NOT IN (1, 2, 3)` {
t.Errorf("Expected t.test NOT IN (1, 2, 3), got %s", result)
}
if resultMap != result {
t.Log(resultMap)
t.Errorf("Expected resultMap to be equal to result")
}
}
func TestLike(t *testing.T) {
ctx := SQLiteContext{
TableAlias: "t",
FieldName: "test",
}
result := Convert(ctx, `{"$like": "199_"}`)
resultMap := Convert(ctx, map[string]any{"$like": "199_"})
if result != `t.test LIKE '199_' ESCAPE '\'` {
t.Errorf("Expected t.test LIKE '199_' ESCAPE '\\', got %s", result)
}
if resultMap != result {
t.Log(resultMap)
t.Errorf("Expected resultMap to be equal to result")
}
}
func TestAnd(t *testing.T) {
ctx := SQLiteContext{
TableAlias: "t",
FieldName: "test",
}
result := Convert(ctx, `{"$and": ["a > 0", "b < 10"]}`)
resultMap := Convert(ctx, map[string]any{"$and": []string{"a > 0", "b < 10"}})
if result != `(a > 0 AND b < 10)` {
t.Errorf("Expected (a > 0 AND b < 10), got %s", result)
}
if resultMap != result {
t.Log(resultMap)
t.Errorf("Expected resultMap to be equal to result")
}
}
func TestOr(t *testing.T) {
ctx := SQLiteContext{
TableAlias: "t",
FieldName: "test",
}
result := Convert(ctx, `{"$or": ["a = 0", "b < 10"]}`)
resultMap := Convert(ctx, map[string]any{"$or": []string{"a = 0", "b < 10"}})
if result != `(a = 0 OR b < 10)` {
t.Errorf("Expected (a > 0 OR b < 10), got %s", result)
}
if resultMap != result {
t.Log(resultMap)
t.Errorf("Expected resultMap to be equal to result")
}
}