[wip] add missing filters
Signed-off-by: Anton Nesterov <anton@demiurg.io>
This commit is contained in:
parent
d28d976b8e
commit
8e45c45624
1
pkg/dal/convert_test.go
Normal file
1
pkg/dal/convert_test.go
Normal file
|
@ -0,0 +1 @@
|
|||
package dal
|
7
pkg/dal/go.mod
Normal file
7
pkg/dal/go.mod
Normal 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
|
|
@ -2,17 +2,20 @@ package filters
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type And struct {
|
||||
And []interface{} `json:"$and"`
|
||||
And []string `json:"$and"`
|
||||
}
|
||||
|
||||
func (a And) ToSQLPart(ctx Context) string {
|
||||
|
||||
fmt.Println(ctx, a)
|
||||
func (f And) ToSQLPart(ctx Context) string {
|
||||
if f.And == nil {
|
||||
return ""
|
||||
}
|
||||
value := strings.Join(f.And, " AND ")
|
||||
return fmt.Sprintf("(%s)", value)
|
||||
}
|
||||
|
||||
func (a And) FromJSON(data interface{}) Filter {
|
||||
return FromJson[And](data)
|
||||
|
|
20
pkg/filters/Like.go
Normal file
20
pkg/filters/Like.go
Normal 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
31
pkg/filters/NotIn.go
Normal 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
20
pkg/filters/NotLike.go
Normal 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
22
pkg/filters/Or.go
Normal 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)
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
package filters
|
||||
|
||||
var FilterRegistry = map[string]Filter{
|
||||
"And": &And{},
|
||||
"Or": &Or{},
|
||||
"Eq": &Eq{},
|
||||
"Ne": &Ne{},
|
||||
"Gt": &Gt{},
|
||||
|
@ -8,9 +10,12 @@ var FilterRegistry = map[string]Filter{
|
|||
"Lt": &Lt{},
|
||||
"Lte": &Lte{},
|
||||
"In": &In{},
|
||||
"Nin": &NotIn{},
|
||||
"Between": &Between{},
|
||||
"NotBetween": &NotBetween{},
|
||||
"Glob": &Glob{},
|
||||
"Like": &Like{},
|
||||
"NotLike": &NotLike{},
|
||||
}
|
||||
|
||||
func Convert(ctx Context, json interface{}) string {
|
||||
|
|
|
@ -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) {
|
||||
ctx := SQLiteContext{
|
||||
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) {
|
||||
ctx := SQLiteContext{
|
||||
TableAlias: "t",
|
||||
|
@ -81,3 +112,67 @@ func TestIn(t *testing.T) {
|
|||
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")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue