[wip] joins
Signed-off-by: Anton Nesterov <anton@demiurg.io>
This commit is contained in:
parent
9fae95b906
commit
758eab6520
|
@ -1,19 +0,0 @@
|
||||||
package dal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
filters "l12.xyz/dal/filters"
|
|
||||||
)
|
|
||||||
|
|
||||||
func CovertFind(find Find, ctx Context) string {
|
|
||||||
expressions := []string{}
|
|
||||||
for key, value := range find {
|
|
||||||
context := ctx.New(CtxOpts{
|
|
||||||
"FieldName": key,
|
|
||||||
})
|
|
||||||
values, _ := filters.Convert(context, value)
|
|
||||||
expressions = append(expressions, values)
|
|
||||||
}
|
|
||||||
return strings.Join(expressions, " AND ")
|
|
||||||
}
|
|
37
pkg/dal/convert_find.go
Normal file
37
pkg/dal/convert_find.go
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
package dal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
filters "l12.xyz/dal/filters"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CovertFind(find Find, ctx Context) string {
|
||||||
|
return covert_find(find, ctx, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func covert_find(find Find, ctx Context, join string) string {
|
||||||
|
if join == "" {
|
||||||
|
join = " AND "
|
||||||
|
}
|
||||||
|
expressions := []string{}
|
||||||
|
for key, value := range find {
|
||||||
|
if strings.Contains(key, "$and") {
|
||||||
|
v := covert_find(value.(Find), ctx, "")
|
||||||
|
expressions = append(expressions, fmt.Sprintf("(%s)", v))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.Contains(key, "$or") {
|
||||||
|
v := covert_find(value.(Find), ctx, " OR ")
|
||||||
|
expressions = append(expressions, fmt.Sprintf("(%s)", v))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
context := ctx.New(CtxOpts{
|
||||||
|
"FieldName": key,
|
||||||
|
})
|
||||||
|
values, _ := filters.Convert(context, value)
|
||||||
|
expressions = append(expressions, values)
|
||||||
|
}
|
||||||
|
return strings.Join(expressions, join)
|
||||||
|
}
|
75
pkg/dal/convert_find_test.go
Normal file
75
pkg/dal/convert_find_test.go
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
package dal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
f "l12.xyz/dal/filters"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConvertFind(t *testing.T) {
|
||||||
|
find := Find{
|
||||||
|
"impl": "1",
|
||||||
|
"exp": Is{
|
||||||
|
"$gt": 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ctx := f.SQLiteContext{
|
||||||
|
TableAlias: "t",
|
||||||
|
}
|
||||||
|
result := CovertFind(find, ctx)
|
||||||
|
if result == `t.exp > 1 AND t.impl = '1'` {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if result == `t.impl = '1' AND t.exp > 1` {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Errorf(`Expected "t.impl = '1' AND t.exp = 1", got %s`, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConvertFindAnd(t *testing.T) {
|
||||||
|
find := Find{
|
||||||
|
"$and": Find{
|
||||||
|
"a": Is{
|
||||||
|
"$gt": 1,
|
||||||
|
},
|
||||||
|
"b": Is{
|
||||||
|
"$lt": 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ctx := f.SQLiteContext{
|
||||||
|
TableAlias: "t",
|
||||||
|
}
|
||||||
|
result := CovertFind(find, ctx)
|
||||||
|
if result == `(t.a > 1 AND t.b < 10)` {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if result == `(t.b < 10 AND t.a > 1)` {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Errorf(`Expected "(t.b < 10 AND t.a > 1)", got %s`, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConvertFindOr(t *testing.T) {
|
||||||
|
find := Query{
|
||||||
|
"$or": Query{
|
||||||
|
"a": Is{
|
||||||
|
"$gt": 1,
|
||||||
|
},
|
||||||
|
"b": Is{
|
||||||
|
"$lt": 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ctx := f.SQLiteContext{
|
||||||
|
TableAlias: "t",
|
||||||
|
}
|
||||||
|
result := CovertFind(find, ctx)
|
||||||
|
if result == `(t.a > 1 OR t.b < 10)` {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if result == `(t.b < 10 OR t.a > 1)` {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Errorf(`Expected "(t.b < 10 OR t.a > 1)", got %s`, result)
|
||||||
|
}
|
17
pkg/dal/convert_join.go
Normal file
17
pkg/dal/convert_join.go
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package dal
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type Join struct {
|
||||||
|
For string `json:"$for"`
|
||||||
|
Do Find `json:"$do"`
|
||||||
|
As string `json:"$as"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j Join) Convert(ctx Context) string {
|
||||||
|
if j.For == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
filter := CovertFind(j.Do, ctx)
|
||||||
|
return fmt.Sprintf("%s JOIN %s ON %s", j.As, j.For, filter)
|
||||||
|
}
|
25
pkg/dal/convert_join_test.go
Normal file
25
pkg/dal/convert_join_test.go
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package dal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
f "l12.xyz/dal/filters"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestJoin(t *testing.T) {
|
||||||
|
j := Join{
|
||||||
|
For: "artist a",
|
||||||
|
Do: Find{
|
||||||
|
"a.impl": "t.impl",
|
||||||
|
},
|
||||||
|
As: "LEFT",
|
||||||
|
}
|
||||||
|
ctx := f.SQLiteContext{
|
||||||
|
TableAlias: "t",
|
||||||
|
}
|
||||||
|
result := j.Convert(ctx)
|
||||||
|
if result == `LEFT JOIN artist a ON a.impl = t.impl` {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Errorf(`Expected "LEFT JOIN artist a ON a.impl = t.impl", got %s`, result)
|
||||||
|
}
|
|
@ -1,24 +0,0 @@
|
||||||
package dal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
f "l12.xyz/dal/filters"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestConvertFind(t *testing.T) {
|
|
||||||
find := Find{
|
|
||||||
"test": "1",
|
|
||||||
"test2": "2",
|
|
||||||
"test3": Filter{
|
|
||||||
"$ne": 1,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
ctx := f.SQLiteContext{
|
|
||||||
TableAlias: "t",
|
|
||||||
}
|
|
||||||
result := CovertFind(find, ctx)
|
|
||||||
if result != `t.test = '1'` {
|
|
||||||
t.Errorf("Expected t.test = '1', got %s", result)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,6 +5,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Find = filters.Find
|
type Find = filters.Find
|
||||||
|
type Query = filters.Find
|
||||||
type Filter = filters.Filter
|
type Filter = filters.Filter
|
||||||
|
type Is = filters.Filter
|
||||||
type Context = filters.Context
|
type Context = filters.Context
|
||||||
type CtxOpts = filters.CtxOpts
|
type CtxOpts = filters.CtxOpts
|
||||||
|
|
|
@ -23,9 +23,9 @@ var FilterRegistry = map[string]IFilter{
|
||||||
}
|
}
|
||||||
|
|
||||||
func Convert(ctx Context, data interface{}) (string, error) {
|
func Convert(ctx Context, data interface{}) (string, error) {
|
||||||
for _, t := range FilterRegistry {
|
for _, impl := range FilterRegistry {
|
||||||
filter := t.FromJSON(data)
|
filter := impl.FromJSON(data)
|
||||||
if reflect.DeepEqual(t, filter) {
|
if reflect.DeepEqual(impl, filter) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
value := filter.ToSQLPart(ctx)
|
value := filter.ToSQLPart(ctx)
|
||||||
|
|
Loading…
Reference in a new issue