mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2026-09-15 21:02:35 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e3124e4e0 |
@@ -137,3 +137,39 @@ func TestApplyFilter_Citext_NeverCastForEqOrIlike(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestValidateAndAdjustFilterForColumnType_NumericColumn_Ilike reproduces a
|
||||||
|
// global "search all columns" request (x-searchor-contains-<col> per column,
|
||||||
|
// e.g. the X-Filter-All style OR group) landing an ILIKE filter with a
|
||||||
|
// '%...%'-wrapped numeric-looking value on a numeric column such as
|
||||||
|
// rid_parent. Before the fix, ValidateAndAdjustFilterForColumnType trimmed
|
||||||
|
// the '%' wildcards, saw a numeric string, and rewrote filter.Value to an
|
||||||
|
// int64 -- so applyFilter's CAST(col AS TEXT) ILIKE ? bound an integer
|
||||||
|
// argument instead of the wildcard string, and Postgres rejected it with
|
||||||
|
// "operator does not exist: text ~~* integer".
|
||||||
|
func TestValidateAndAdjustFilterForColumnType_NumericColumn_Ilike(t *testing.T) {
|
||||||
|
h := &Handler{}
|
||||||
|
model := atdetailModel{}
|
||||||
|
|
||||||
|
filter := &common.FilterOption{Column: "rid_parent", Operator: "ilike", Value: "%345346346%"}
|
||||||
|
info := h.ValidateAndAdjustFilterForColumnType(filter, model)
|
||||||
|
|
||||||
|
if !info.NeedsCast {
|
||||||
|
t.Fatalf("expected NeedsCast=true so the numeric column is cast to TEXT for ILIKE")
|
||||||
|
}
|
||||||
|
if filter.Value != "%345346346%" {
|
||||||
|
t.Fatalf("ILIKE must keep the wildcard-wrapped string value untouched, got %#v", filter.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
q := &jsonCapQuery{}
|
||||||
|
h.applyFilter(q, *filter, "public.atdetail", info.NeedsCast, "OR", model)
|
||||||
|
|
||||||
|
c := q.only(t)
|
||||||
|
const want = "CAST(atdetail.rid_parent AS TEXT) ILIKE ?"
|
||||||
|
if c.query != want {
|
||||||
|
t.Fatalf("query = %q, want %q", c.query, want)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(c.args, []interface{}{"%345346346%"}) {
|
||||||
|
t.Fatalf("args = %#v, want [\"%%345346346%%\"]", c.args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1479,6 +1479,18 @@ func (h *Handler) ValidateAndAdjustFilterForColumnType(filter *common.FilterOpti
|
|||||||
return ColumnCastInfo{NeedsCast: false, IsNumericType: false}
|
return ColumnCastInfo{NeedsCast: false, IsNumericType: false}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LIKE/ILIKE always compare against text, wildcards and all. Never coerce
|
||||||
|
// the value to the column's native numeric/bool/time type here: doing so
|
||||||
|
// strips the '%' wildcards and hands the driver a non-string argument,
|
||||||
|
// which fails with "operator does not exist: text ~~* integer" once the
|
||||||
|
// column is cast to TEXT below.
|
||||||
|
if op := strings.ToLower(filter.Operator); op == "like" || op == "ilike" {
|
||||||
|
if reflection.IsStringType(colType) {
|
||||||
|
return ColumnCastInfo{NeedsCast: false, IsNumericType: false}
|
||||||
|
}
|
||||||
|
return ColumnCastInfo{NeedsCast: true, IsNumericType: reflection.IsNumericType(colType)}
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the input value is numeric
|
// Check if the input value is numeric
|
||||||
valueIsNumeric := false
|
valueIsNumeric := false
|
||||||
if strVal, ok := filter.Value.(string); ok {
|
if strVal, ok := filter.Value.(string); ok {
|
||||||
|
|||||||
Reference in New Issue
Block a user