This repository has been archived by the owner on Feb 11, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor and implement
dumbql:"-"
(omit) struct tag
- Loading branch information
Showing
7 changed files
with
932 additions
and
714 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package match_test | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/defer-panic/dumbql/match" | ||
"github.com/defer-panic/dumbql/query" | ||
) | ||
|
||
type MatchUser struct { | ||
ID int64 `dumbql:"id"` | ||
Name string `dumbql:"name"` | ||
Age int64 `dumbql:"age"` | ||
Score float64 `dumbql:"score"` | ||
Location string `dumbql:"location"` | ||
Role string `dumbql:"role"` | ||
} | ||
|
||
func Example() { | ||
users := []MatchUser{ | ||
{ | ||
ID: 1, | ||
Name: "John Doe", | ||
Age: 30, | ||
Score: 4.5, | ||
Location: "New York", | ||
Role: "admin", | ||
}, | ||
{ | ||
ID: 2, | ||
Name: "Jane Smith", | ||
Age: 25, | ||
Score: 3.8, | ||
Location: "Los Angeles", | ||
Role: "user", | ||
}, | ||
{ | ||
ID: 3, | ||
Name: "Bob Johnson", | ||
Age: 35, | ||
Score: 4.2, | ||
Location: "Chicago", | ||
Role: "user", | ||
}, | ||
// This one will be dropped: | ||
{ | ||
ID: 4, | ||
Name: "Alice Smith", | ||
Age: 25, | ||
Score: 3.8, | ||
Location: "Los Angeles", | ||
Role: "admin", | ||
}, | ||
} | ||
|
||
q := `(age >= 30 and score > 4.0) or (location:"Los Angeles" and role:"user")` | ||
ast, _ := query.Parse("test", []byte(q)) | ||
expr := ast.(query.Expr) | ||
|
||
matcher := &match.StructMatcher{} | ||
|
||
filtered := make([]MatchUser, 0, len(users)) | ||
|
||
for _, user := range users { | ||
if expr.Match(&user, matcher) { | ||
filtered = append(filtered, user) | ||
} | ||
} | ||
|
||
fmt.Println(filtered) | ||
// Output: | ||
// [{1 John Doe 30 4.5 New York admin} {2 Jane Smith 25 3.8 Los Angeles user} {3 Bob Johnson 35 4.2 Chicago user}] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package match | ||
|
||
import ( | ||
"reflect" | ||
|
||
"github.com/defer-panic/dumbql/query" | ||
) | ||
|
||
// StructMatcher is a basic implementation of the Matcher interface for evaluating query expressions against structs. | ||
// It supports struct tags using the `dumbql` tag name, which allows you to specify a custom field name. | ||
type StructMatcher struct{} | ||
|
||
func (m *StructMatcher) MatchAnd(target any, left, right query.Expr) bool { | ||
return left.Match(target, m) && right.Match(target, m) | ||
} | ||
|
||
func (m *StructMatcher) MatchOr(target any, left, right query.Expr) bool { | ||
return left.Match(target, m) || right.Match(target, m) | ||
} | ||
|
||
func (m *StructMatcher) MatchNot(target any, expr query.Expr) bool { | ||
return !expr.Match(target, m) | ||
} | ||
|
||
// MatchField matches a field in the target struct using the provided value and operator. It supports struct tags using | ||
// the `dumbql` tag name, which allows you to specify a custom field name. If struct tag is not provided, it will use | ||
// the field name as is. | ||
func (m *StructMatcher) MatchField(target any, field string, value query.Valuer, op query.FieldOperator) bool { | ||
t := reflect.TypeOf(target) | ||
|
||
if t.Kind() == reflect.Ptr { | ||
t = t.Elem() | ||
} | ||
|
||
if t.Kind() != reflect.Struct { | ||
return false | ||
} | ||
|
||
for i := 0; i < t.NumField(); i++ { | ||
f := t.Field(i) | ||
|
||
tag := f.Tag.Get("dumbql") | ||
if tag == "-" { | ||
return true // Field marked with dumbql:"-" always match (in other words does not affect the result) | ||
} | ||
|
||
fname := f.Name | ||
if tag != "" { | ||
fname = tag | ||
} | ||
|
||
if fname == field { | ||
v := reflect.ValueOf(target) | ||
if v.Kind() == reflect.Ptr { | ||
v = v.Elem() | ||
} | ||
|
||
return m.MatchValue(v.Field(i).Interface(), value, op) | ||
} | ||
} | ||
|
||
return true | ||
} | ||
|
||
func (m *StructMatcher) MatchValue(target any, value query.Valuer, op query.FieldOperator) bool { | ||
return value.Match(target, op) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.