Как сериализовать тип для указанных столбцов базы данных

Я использую 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

Поля являются анонимными, и в любом случае нет места для указания конкретных столбцов базы данных.

Другие вопросы по тегам