Correctly compare numeric field values

This commit is contained in:
Eike Kettner
2021-03-03 01:58:24 +01:00
parent d4006461f6
commit 1c834cbb77
7 changed files with 60 additions and 9 deletions

View File

@ -29,6 +29,8 @@ object DBFunction {
case class Cast(expr: SelectExpr, newType: String) extends DBFunction
case class CastNumeric(expr: SelectExpr) extends DBFunction
case class Avg(expr: SelectExpr) extends DBFunction
case class Sum(expr: SelectExpr) extends DBFunction

View File

@ -89,6 +89,9 @@ trait DSL extends DoobieMeta {
def cast(expr: SelectExpr, targetType: String): DBFunction =
DBFunction.Cast(expr, targetType)
def castNumeric(expr: SelectExpr): DBFunction =
DBFunction.CastNumeric(expr)
def coalesce(expr: SelectExpr, more: SelectExpr*): DBFunction.Coalesce =
DBFunction.Coalesce(expr, more.toVector)

View File

@ -242,16 +242,33 @@ object ItemQueryGenerator {
)(coll: Ident, op: QOp, value: String): Select = {
val cf = RCustomField.as("cf")
val cfv = RCustomFieldValue.as("cfv")
val v = if (op == QOp.LowerLike) QueryWildcard.lower(value) else value
Select(
select(cfv.itemId),
from(cfv).innerJoin(cf, cf.id === cfv.field),
cf.cid === coll && sel(cf) && Condition.CompareVal(
cfv.value,
op,
v
val baseSelect =
Select(
select(cfv.itemId),
from(cfv).innerJoin(cf, sel(cf) && cf.cid === coll && cf.id === cfv.field)
)
)
if (op == QOp.LowerLike) {
val v = QueryWildcard.lower(value)
baseSelect.where(Condition.CompareVal(cfv.value, op, v))
} else {
val stringCmp =
Condition.CompareVal(cfv.value, op, value)
value.toDoubleOption
.map { n =>
val numericCmp = Condition.CompareFVal(castNumeric(cfv.value.s), op, n)
val fieldIsNumeric =
cf.ftype === CustomFieldType.Numeric || cf.ftype === CustomFieldType.Money
val fieldNotNumeric =
cf.ftype <> CustomFieldType.Numeric && cf.ftype <> CustomFieldType.Money
baseSelect.where(
(fieldIsNumeric && numericCmp) || (fieldNotNumeric && stringCmp)
)
}
.getOrElse(baseSelect.where(stringCmp))
}
}
}

View File

@ -46,6 +46,9 @@ object DBFunctionBuilder extends CommonBuilder {
fr" AS" ++ Fragment.const(newType) ++
sql")"
case DBFunction.CastNumeric(f) =>
sql"CAST_TO_NUMERIC(" ++ SelectExprBuilder.build(f) ++ sql")"
case DBFunction.Avg(expr) =>
sql"AVG(" ++ SelectExprBuilder.build(expr) ++ fr")"