mirror of
https://github.com/pocketbase/pocketbase.git
synced 2026-09-08 15:41:18 +02:00
backported fixes from v0.40.2
This commit is contained in:
+28
-16
@@ -41,27 +41,39 @@ func (f FilterData) BuildExpr(
|
||||
raw := string(f)
|
||||
|
||||
// replace the placeholder params in the raw string filter
|
||||
for _, p := range placeholderReplacements {
|
||||
for key, value := range p {
|
||||
var replacement string
|
||||
switch v := value.(type) {
|
||||
case nil:
|
||||
replacement = "null"
|
||||
case bool, float64, float32, int, int64, int32, int16, int8, uint, uint64, uint32, uint16, uint8:
|
||||
replacement = cast.ToString(v)
|
||||
default:
|
||||
replacement = cast.ToString(v)
|
||||
if len(placeholderReplacements) > 0 {
|
||||
replacements := make([]string, 0, len(placeholderReplacements[0])*2)
|
||||
|
||||
// try to json serialize as fallback
|
||||
if replacement == "" {
|
||||
raw, _ := json.Marshal(v)
|
||||
replacement = string(raw)
|
||||
for _, p := range placeholderReplacements {
|
||||
for key, value := range p {
|
||||
var replacement string
|
||||
|
||||
switch v := value.(type) {
|
||||
case nil:
|
||||
replacement = "null"
|
||||
case bool, float64, float32, int, int64, int32, int16, int8, uint, uint64, uint32, uint16, uint8:
|
||||
replacement = cast.ToString(v)
|
||||
default:
|
||||
casted, err := cast.ToStringE(v)
|
||||
|
||||
// try to json serialize as fallback
|
||||
if err != nil {
|
||||
raw, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to serialize param %q: %w", key, err)
|
||||
}
|
||||
casted = string(raw)
|
||||
}
|
||||
|
||||
replacement = strconv.Quote(casted)
|
||||
}
|
||||
|
||||
replacement = strconv.Quote(replacement)
|
||||
replacements = append(replacements, "{:"+key+"}", replacement)
|
||||
}
|
||||
raw = strings.ReplaceAll(raw, "{:"+key+"}", replacement)
|
||||
}
|
||||
|
||||
replacer := strings.NewReplacer(replacements...)
|
||||
raw = replacer.Replace(raw)
|
||||
}
|
||||
|
||||
if parsedFilterData.Has(raw) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package search_test
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -233,12 +234,44 @@ func TestFilterDataBuildExprWithParams(t *testing.T) {
|
||||
t.Fatalf("Expected 1 query, got %d", len(calledQueries))
|
||||
}
|
||||
|
||||
expectedQuery := `SELECT * WHERE ([[test1]] = 1 OR [[test2]] = 0 OR [[test3a]] = 123.456 OR [[test3b]] = 123.456 OR ([[test4]] = '' OR [[test4]] IS NULL) OR [[test5]] = '""' OR [[test6]] = 'simple' OR [[test7]] = '''single_quotes''' OR [[test8]] = '"double_quotes"' OR [[test9]] = 'escape\"quote' OR [[test10]] = '2023-01-01 00:00:00 +0000 UTC' OR [[test11]] = '["a","b","\"quote"]' OR [[test12]] = '{"a":123,"b":"quote\""}')`
|
||||
expectedQuery := `SELECT * WHERE ([[test1]] = 1 OR [[test2]] = 0 OR [[test3a]] = 123.456 OR [[test3b]] = 123.456 OR ([[test4]] = '' OR [[test4]] IS NULL) OR ([[test5]] = '' OR [[test5]] IS NULL) OR [[test6]] = 'simple' OR [[test7]] = '''single_quotes''' OR [[test8]] = '"double_quotes"' OR [[test9]] = 'escape\"quote' OR [[test10]] = '2023-01-01 00:00:00 +0000 UTC' OR [[test11]] = '["a","b","\"quote"]' OR [[test12]] = '{"a":123,"b":"quote\""}')`
|
||||
if expectedQuery != calledQueries[0] {
|
||||
t.Fatalf("Expected query \n%s, \ngot \n%s", expectedQuery, calledQueries[0])
|
||||
}
|
||||
}
|
||||
|
||||
type brokenJSON struct{}
|
||||
|
||||
func (j brokenJSON) MarshalJSON() ([]byte, error) {
|
||||
return nil, errors.New("test_error")
|
||||
}
|
||||
|
||||
func TestFilterDataBuildExprWithParamsFallbackError(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
resolver := search.NewSimpleFieldResolver("test")
|
||||
|
||||
filter := search.FilterData(`test = {:test}`)
|
||||
|
||||
t.Run("non-string type but valid marshalized json", func(t *testing.T) {
|
||||
_, err := filter.BuildExpr(resolver, dbx.Params{
|
||||
"test": map[string]any{"a": "123"},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("non-string type but invalid marshalized json", func(t *testing.T) {
|
||||
_, err := filter.BuildExpr(resolver, dbx.Params{
|
||||
"test": brokenJSON{},
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatal("Expected filter build error, got nil")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestLikeParamsWrapping(t *testing.T) {
|
||||
// create a dummy db
|
||||
sqlDB, err := sql.Open("sqlite", "file::memory:?cache=shared")
|
||||
|
||||
Reference in New Issue
Block a user