mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2026-09-15 21:02:35 +00:00
fix(restheadspec,resolvespec): stop casting SqlNull-wrapped and citext columns to TEXT in filters
reflect.Type.Kind() on spectypes.SqlNull[T] wrappers (SqlInt16/32/64, SqlFloat64, SqlBool, SqlString, and embedders like SqlTimeStamp) always reports reflect.Struct, never the wrapped T. ValidateAndAdjustFilterForColumnType treated those as "complex" columns and forced CAST(col AS TEXT) on eq/gt/lt filters, e.g. CAST(atdetail.rid_parent AS TEXT) = '90446096', which can't use the index on rid_parent. Add spectypes.UnwrapKind to see through SqlNull wrappers to the underlying Kind, and use it in GetColumnTypeFromModel so numeric/string SqlNull columns are recognized correctly and compared natively. Also stop unconditionally casting to TEXT for LIKE/ILIKE and add reflection.IsCitextColumn: citext columns are already case-insensitive, so casting them to TEXT flips to case-sensitive matching and defeats a citext index.
This commit is contained in:
@@ -97,3 +97,27 @@ func IsJSONType(t reflect.Type) bool {
|
||||
n, ok := SQLTypeName(t)
|
||||
return ok && (n == "jsonb" || n == "json")
|
||||
}
|
||||
|
||||
// UnwrapKind returns the reflect.Kind to use when reasoning about a column's
|
||||
// comparability (numeric vs. string vs. other) for filter building. Plain Go
|
||||
// types return their own Kind unchanged. spectypes.SqlNull[T] wrappers (and
|
||||
// types that embed one, such as SqlTimeStamp/SqlDate/SqlTime) always report
|
||||
// reflect.Struct for their own Kind even when T is an int64 or string, which
|
||||
// would otherwise make numeric/text columns look "complex" and force an
|
||||
// unnecessary CAST(... AS TEXT) that defeats native column indexes. For those
|
||||
// wrappers, UnwrapKind returns the Kind of the wrapped value T instead.
|
||||
func UnwrapKind(t reflect.Type) reflect.Kind {
|
||||
for t != nil && t.Kind() == reflect.Pointer {
|
||||
t = t.Elem()
|
||||
}
|
||||
if t == nil {
|
||||
return reflect.Invalid
|
||||
}
|
||||
if t.Kind() != reflect.Struct || t.PkgPath() != pkgPath {
|
||||
return t.Kind()
|
||||
}
|
||||
if f, ok := t.FieldByName("Val"); ok {
|
||||
return f.Type.Kind()
|
||||
}
|
||||
return t.Kind()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user