Haskell Esqueleto project subset of columns to list of custom records

后端 未结 1 1761
星月不相逢
星月不相逢 2021-01-06 05:46

In all the examples I have seen the results from esqueleto are projected into a list of tuples or to entities records.

For example:

previousLogItems          


        
相关标签:
1条回答
  • 2021-01-06 06:42

    What esqueleto is actually doing here is a little complicated. Here is the type for select:

    select :: (SqlSelect a r, MonadIO m) => SqlQuery a -> SqlReadT m [r]
    

    This takes an SqlQuery a (a monad wrapping the value you return), and returns an SqlReadT m [r] (a monad wrapping a list of results). When you return your Custom type, the following happens:

    1. esqueleto converts your a type to persistent's internal SQL representation
    2. persistent executes the query and gets back a results list
    3. esqueleto converts the results list from persistent's internal SQL representation to [r]

    To make this work for custom types, you'll need to instantiate SqlSelect, and define conversion functions to and from the persistent types:

    data Custom' = Custom' (Value Text) (Value Int)
    
    data Custom = Custom
      { title :: Text
      , id    :: Int
      }
    
    instance SqlSelect Custom' Custom where
      sqlSelectCols esc (Custom' a b) = (mconcat [ta, ", ", tb], va ++ vb)
        where
          (ta, va) = sqlSelectCols esc a
          (tb, vb) = sqlSelectCols esc b
      sqlSelectColCount _ = 2
      sqlSelectProcessRow [PersistText a, PersistInt64 b] = Right $ Custom a b
      sqlSelectProcessRow _ = Left "Error: Incorrect rows to translate to Custom"
    

    (note that I wasn't actually able to test any of the above, so it might have bugs)

    One thing to note is that in the above example, the a and r types are not the same (Custom' vs Custom). This is because inside of a select, all of the values you're working with are of type Value, not their actual types.

    0 讨论(0)
提交回复
热议问题