Skip to content

Commit

Permalink
Fix empty objects (#5)
Browse files Browse the repository at this point in the history
A top level empty object returns a TRUE condition as you're not
filtering on anything. Nested empty objects will return an error as they
most likely indicate an error.

---------

Co-authored-by: Koen Bollen <[email protected]>
  • Loading branch information
erikdubbelboer and koenbollen authored May 3, 2024
1 parent ec4961e commit 0b1842c
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 1 deletion.
14 changes: 14 additions & 0 deletions examples/basic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,20 @@ func ExampleNewConverter() {
// []interface {}{"2020-01-01T00:00:00Z", "John"}
}

func ExampleNewConverter_emptyfilter() {
converter := filter.NewConverter(filter.WithEmptyCondition("TRUE")) // The default is FALSE if you don't change it.

mongoFilterQuery := `{}`
conditions, _, err := converter.Convert([]byte(mongoFilterQuery), 1)
if err != nil {
// handle error
}

fmt.Println(conditions)
// Output:
// TRUE
}

func ExampleNewConverter_nonIsolatedConditions() {
converter := filter.NewConverter()

Expand Down
13 changes: 12 additions & 1 deletion filter/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,16 @@ type Converter struct {
driver.Valuer
sql.Scanner
}
emptyCondition string
}

// NewConverter creates a new Converter with optional nested JSONB field mapping.
//
// Note: When using github.com/lib/pq, the filter.WithArrayDriver should be set to pq.Array.
func NewConverter(options ...Option) *Converter {
converter := &Converter{}
converter := &Converter{
emptyCondition: "FALSE",
}
for _, option := range options {
if option != nil {
option(converter)
Expand All @@ -56,6 +59,10 @@ func (c *Converter) Convert(query []byte, startAtParameterIndex int) (conditions
return "", nil, err
}

if len(mongoFilter) == 0 {
return c.emptyCondition, []any{}, nil
}

conditions, values, err = c.convertFilter(mongoFilter, startAtParameterIndex)
if err != nil {
return "", nil, err
Expand All @@ -68,6 +75,10 @@ func (c *Converter) convertFilter(filter map[string]any, paramIndex int) (string
var conditions []string
var values []any

if len(filter) == 0 {
return "", nil, fmt.Errorf("empty objects not allowed")
}

keys := []string{}
for key := range filter {
keys = append(keys, key)
Expand Down
29 changes: 29 additions & 0 deletions filter/converter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,21 @@ func TestConverter_Convert(t *testing.T) {
[]any{[]any{}},
nil,
},
{
"empty filter",
nil,
`{}`,
`FALSE`,
[]any{},
nil,
}, {
"empty or conditions",
nil,
`{"$or": [{}, {}]}`,
``,
nil,
fmt.Errorf("empty objects not allowed"),
},
}

for _, tt := range tests {
Expand Down Expand Up @@ -245,3 +260,17 @@ func TestConverter_Convert_startAtParameterIndex(t *testing.T) {
t.Errorf("Converter.Convert(..., 1234551231231231231) error = %v, want nil", err)
}
}

func TestConverter_WithEmptyCondition(t *testing.T) {
c := filter.NewConverter(filter.WithEmptyCondition("TRUE"))
conditions, values, err := c.Convert([]byte(`{}`), 1)
if err != nil {
t.Fatal(err)
}
if want := "TRUE"; conditions != want {
t.Errorf("Converter.Convert() conditions = %v, want %v", conditions, want)
}
if len(values) != 0 {
t.Errorf("Converter.Convert() values = %v, want nil", values)
}
}
10 changes: 10 additions & 0 deletions filter/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,13 @@ func WithArrayDriver(f func(a any) interface {
c.arrayDriver = f
}
}

// WithEmptyCondition is an option to specify the condition to be used when the
// input query filter is empty. (e.g. you have a query with no conditions)
//
// The default value is `FALSE`, because it's the safer choice in most cases.
func WithEmptyCondition(condition string) Option {
return func(c *Converter) {
c.emptyCondition = condition
}
}
2 changes: 2 additions & 0 deletions fuzz/testdata/fuzz/FuzzConverter/439ca8de24f74c60
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
go test fuzz v1
string("{\"$or\":[{},{}]}")
6 changes: 6 additions & 0 deletions integration/postgres_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,12 @@ func TestIntegration_BasicOperators(t *testing.T) {
nil,
errors.New("pq: invalid input syntax for type integer: \"town1\""),
},
{
`empty object`,
`{}`, // Should return FALSE as the condition.
[]int{},
nil,
},
}

for _, tt := range tests {
Expand Down

0 comments on commit 0b1842c

Please sign in to comment.