Skip to content

Commit a1eda5a

Browse files
Improve numeric scalar support (#36)
Make sure to include `::numeric` when comparing a jsonb field to a numeric scalar. This prevents us from getting: ``` ERROR: operator does not exist: text = numeric ```
1 parent 288373a commit a1eda5a

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

filter/converter.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,15 @@ func (c *Converter) convertFilter(filter map[string]any, paramIndex int) (string
294294
return "", nil, fmt.Errorf("invalid comparison value (must be a primitive): %v", value)
295295
}
296296

297+
// If we aren't comparing columns, and the field is a numeric scalar, we also see = ($eq) and != ($ne) as numeric operators.
298+
// This way we can use ::numeric on jsonb values to prevent getting postgres errors like:
299+
// ERROR: operator does not exist: text = numeric
300+
if isNumeric(value) && !isNumericOperator {
301+
if op == "=" || op == "!=" {
302+
isNumericOperator = true
303+
}
304+
}
305+
297306
if isNumericOperator && isNumeric(value) && c.isNestedColumn(key) {
298307
inner = append(inner, fmt.Sprintf("((%s)::numeric %s $%d)", c.columnName(key), op, paramIndex))
299308
} else {
@@ -330,7 +339,12 @@ func (c *Converter) convertFilter(filter map[string]any, paramIndex int) (string
330339
if !isScalar(value) {
331340
return "", nil, fmt.Errorf("invalid comparison value (must be a primitive): %v", value)
332341
}
333-
conditions = append(conditions, fmt.Sprintf("(%s = $%d)", c.columnName(key), paramIndex))
342+
if isNumeric(value) && c.isNestedColumn(key) {
343+
// If the value is numeric and the column is a nested JSONB column, we need to cast the column to numeric.
344+
conditions = append(conditions, fmt.Sprintf("((%s)::numeric = $%d)", c.columnName(key), paramIndex))
345+
} else {
346+
conditions = append(conditions, fmt.Sprintf("(%s = $%d)", c.columnName(key), paramIndex))
347+
}
334348
paramIndex++
335349
values = append(values, value)
336350
}

filter/converter_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,22 @@ func TestConverter_Convert(t *testing.T) {
425425
nil,
426426
fmt.Errorf("invalid value for $eq operator (must be object with $field key only): map[foo:bar]"),
427427
},
428+
{
429+
"numeric comparison with nested jsonb",
430+
[]filter.Option{filter.WithNestedJSONB("meta")},
431+
`{"foo": 12}`,
432+
`(("meta"->>'foo')::numeric = $1)`,
433+
[]any{float64(12)},
434+
nil,
435+
},
436+
{
437+
"numeric comparison with nested jsonb with $eq",
438+
[]filter.Option{filter.WithNestedJSONB("meta")},
439+
`{"foo": { "$eq": 12 }}`,
440+
`(("meta"->>'foo')::numeric = $1)`,
441+
[]any{float64(12)},
442+
nil,
443+
},
428444
}
429445

430446
for _, tt := range tests {

0 commit comments

Comments
 (0)