bitemyapp / esqueleto

New home of Esqueleto, please file issues so we can get things caught up!
BSD 3-Clause "New" or "Revised" License
370 stars 107 forks source link

Convert `Database.Persist.Query.Filter` into `SqlExpr` ? #247

Closed ranjitjhala closed 3 years ago

ranjitjhala commented 3 years ago

Hi,

(My apologies in advance if this is not the right place to ask!)

Is there an existing way to convert Persistents "where" clauses represented as

https://hackage.haskell.org/package/persistent-1.1.3/docs/Database-Persist-Query.html#t:Filter

into Esqueletos SqlExpr (Value Bool) ?

Thanks in advance!

parsonsmatt commented 3 years ago

It should be possible, yes. I haven't tested or compiled this code, but i Think it'd work with a bit of completing

filterToWhere :: PersistEntity rec => Filter rec -> SqlExpr (Value Bool)
filterToWhere = \case
    Filter { filterField, filterValue, filterFilter } ->
       case (filterFilter, filterValue) of
            (Eq, FilterValue v) -> filterField ==. val v
            (Eq, FilterValues vs) -> error "nope"
            (Eq, UnsafeFilter x) -> filterField ==.  veryUnsafeCoerceSqlExprValue (val x)

            -- etc
            (In, FilterValue v) -> error "nope"
            (In, FilterValues vs) -> filterField `in_` valList vs
            (In, UnsafeFilter x) -> filterField `in_` valList (_notSure (veryUnsafeCoerceSqlExprValue x))
    FilterAnd filters -> foldr (&&.) (val True) (map filterToWhere filters)
    FilterOr filters -> foldr (||.) (val False) (map filterToWhere filters)
belevy commented 3 years ago

looks like Matt's incomplete implementation also missed the fact that the fuction will need to take a SqlExpr (Entity rec) to extract the existing field from. That said, I cant imagine the use of this theoretical filterToWhere would be worth the complexity and confusion it would create. Perhaps you could explain what it is that you are trying to achieve with this kind of functionality.

ranjitjhala commented 3 years ago

Hi all,

Our use case was that we had a bunch of infrastructure set up for writing filters and wanted to reuse those in (restricted) joins using esqueleto.

in the end I went with a recursive traversal of the kind @parsonsmatt suggested

https://github.com/storm-framework/storm/blob/main/src/Storm/Actions.hs#L273

Thanks!

Ranjit.