Как сериализовать тип для указанных столбцов базы данных
Я использую postgresql-simple в приложении на haskell, и я хочу иметь возможность сериализовать тип данных в строку в моей базе данных, в которой нет сопоставления 1: 1 полей записи, используемых в типе данных, потому что я используя их в других типах данных. (Я довольно новичок в Haskell, но думаю, что это связано с использованием конструктора данных Identifier).
Пример У меня есть таблица базы данных Users со следующими столбцами: user_id, email, имя, пароль, адрес, номер телефона
Теперь у меня есть тип со следующим форматом:
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 }
но я не нашел это.
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
Поля являются анонимными, и в любом случае нет места для указания конкретных столбцов базы данных.