feat(restheadspec): match NULL when x-fieldfilter compares a numeric column to 0

Adds a SetNullAsZero handler option: on by default in restheadspec (for
x-fieldfilter only), off by default in resolvespec. When enabled, an eq
filter of 0 on a numeric column renders (col = 0 OR col IS NULL).
This commit is contained in:
Hein
2026-10-12 15:49:57 +02:00
parent fbfc1aadb5
commit d3252f3d02
7 changed files with 239 additions and 2 deletions
+17 -2
View File
@@ -33,6 +33,7 @@ type Handler struct {
openAPIGenerator func() (string, error)
defaultSort map[string][]common.SortOption
disallowNulls bool
nullAsZero bool
}
// NewHandler creates a new API handler with database and registry abstractions
@@ -61,6 +62,12 @@ func (h *Handler) SetDisallowNulls(disallow bool) {
h.disallowNulls = disallow
}
// SetNullAsZero controls whether an equality filter against 0 on a numeric
// column also matches NULLs: (col = 0 OR col IS NULL). Disabled by default.
func (h *Handler) SetNullAsZero(enabled bool) {
h.nullAsZero = enabled
}
// SetFallbackHandler sets a fallback handler to be called when no model is found
// If not set, the handler will simply return (pass through to next route)
func (h *Handler) SetFallbackHandler(fallback FallbackHandler) {
@@ -2026,7 +2033,11 @@ func (h *Handler) buildFilterConditionAlias(filter common.FilterOption, model in
switch filter.Operator {
case "eq", "=":
condition = fmt.Sprintf("%s = ?", filter.Column)
if h.nullAsZero && common.IsNumericZeroFilter(model, rawColumn, filter.Value) {
condition = fmt.Sprintf("(%s = ? OR %s IS NULL)", filter.Column, filter.Column)
} else {
condition = fmt.Sprintf("%s = ?", filter.Column)
}
args = []interface{}{filter.Value}
case "neq", "!=", "<>":
condition = fmt.Sprintf("%s != ?", filter.Column)
@@ -2111,7 +2122,11 @@ func (h *Handler) applyFilter(query common.SelectQuery, filter common.FilterOpti
switch filter.Operator {
case "eq", "=":
condition = fmt.Sprintf("%s = ?", filter.Column)
if h.nullAsZero && common.IsNumericZeroFilter(model, rawColumn, filter.Value) {
condition = fmt.Sprintf("(%s = ? OR %s IS NULL)", filter.Column, filter.Column)
} else {
condition = fmt.Sprintf("%s = ?", filter.Column)
}
args = []interface{}{filter.Value}
case "neq", "!=", "<>":
condition = fmt.Sprintf("%s != ?", filter.Column)