1

我在 haskell 应用程序中使用 postgresql-simple,并且我希望能够将数据类型序列化为我的数据库中没有数据类型中使用的记录字段的 1 对 1 映射的行,因为我是在其他数据类型中使用它们。(我对 Haskell 很陌生,但我认为这涉及使用 Identifier 数据构造函数)。

示例我有一个数据库表用户,其中包含以下列:user_id、email、name、password、address、phone_number

现在我有一个具有以下格式的类型:

data UserDetails = UserDetails {
  user_id :: Int,
  email :: Text,
  phone_number :: Maybe (Text),
  password :: Text,
  name :: Maybe (Text),
  address :: Maybe (Text),
} deriving (Show, Generic, FromRow)

而且我可以为这种类型实现一个通用的 ToRow 没有问题,因为记录字段与列名相同,但是我有另一种类型,我想为其生成一个 ToRow 实例:

data UserEditDetails = UserEditDetails {
  ued_email :: Maybe (Email),
  ued_phone_number :: Maybe (Text),
  ued_address :: Maybe (Text),
  ued_name :: Maybe (Text),
} deriving (Show, Generic)

我将如何实现这种类型的 ToRow 实例或更一般地我如何编写一个 ToRow 实例,如下面的伪代码

instance ToRow UserEditDetails where
  toRow a = (columnname, ued_email a)... etc

希望它具有类似于 Aeson 的功能,您可以在其中轻松编写如下内容:

instance ToJSON Login where
  toJSON = genericToJSON defaultOptions { fieldLabelModifier = drop 4 }

但我还没有找到这个。

4

1 回答 1

1

postgresql-simple不注意数据库列名。它只期望ToRow/FromRow实例序列化或反序列化的列的计数和顺序与 SQL 查询中列的计数和顺序匹配。ToRow UserEditDetails只要您提供的查询以正确的顺序匹配四列,您就可以使用通用实例。例如,如果您有以下定义和通用ToRow实例:

data UserEditDetails = UserEditDetails
  { ued_email :: Maybe Text
  , ued_phone_number :: Maybe Text
  , ued_address :: Maybe Text
  , ued_name :: Maybe Text
  } deriving (Show, Generic, ToRow)

那么我相信以下查询会正常工作:

do let q = "update user_table set email=?, phone_number=?, address=?, name=? "
           ++ "where user_id=?"
   execute conn q $ (UserEditDetails
                      (Just "me@example.invalid")
                      (Just "555-1212")
                      (Just "123 Fake Street")
                      (Just "Bob Jones"))
                    :. Only (15 :: Int)  -- user_id 15

请注意,来自FromRow和的通用实例ToRow等价于:

instance ToRow UserEditDetails where
  toRow (UserEditDetails a b c d) = [toField a, toField b, toField c, toField d]
instance FromRow UserEditDetails where
  fromRow = UserEditDetails <$> field <*> field <*> field <*> field

这些字段是匿名的,无论如何都没有地方提供特定的数据库列。

于 2019-04-17T05:50:12.023 回答