Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Insert/Update a whole row using ToRow instance #96

Open
danwdart opened this issue Jun 29, 2021 · 3 comments
Open

Insert/Update a whole row using ToRow instance #96

danwdart opened this issue Jun 29, 2021 · 3 comments

Comments

@danwdart
Copy link

Is there a way to say INSERT INTO table_name (something) values (something) or UPDATE table_name SET a = "b", c = "d", etc., using the ToRow instance to automatically fill in these fields for me?

Otherwise I would have to have a super long convoluted API call with all the fields being specific. Maybe I'm missing something in the instances, but this isn't in any examples, so I'm not sure if it exists.

@danwdart
Copy link
Author

At the moment, for INSERT, I have this very dodgy code which will break as soon as the column ordering isn't the same as in the ToRow instance:

{-# LANGUAGE ScopedTypeVariables #-}

import Control.Monad (void)
import Control.Monad.IO.Class (MonadIO (liftIO))
import Data.Maybe
import Data.Text as T (Text, intercalate)
import Database.SQLite.Simple
import Database.SQLite.Simple.FromField
import Database.SQLite.Simple.ToField

type TableName = Text

insertOne :: forall row m. (FromRow row, ToRow row, MonadIO m) => Connection -> TableName -> row -> m ()
insertOne conn' table row = do
    statement <- liftIO $
        openStatement conn' (
            Query $
                "INSERT INTO " <>
                table <>
                " values (" <>
                (
                    T.intercalate "," (
                        -- Currently, the table columns have to be in the same order as the rows in the datatype.
                        replicate (length . toRow $ row) "?"
                    ) <>
                    ")"
                )
            )
    liftIO $ bind statement row
    void (liftIO $ nextRow statement :: m (Maybe row))

Ugh. There ought to be a way to grab the correct field names and do a proper SQL SET instead of using VALUES.

@danwdart
Copy link
Author

This might be fixable with the help of #95 as I'm now investigating getting field names which needs Generic.

@danwdart
Copy link
Author

This should be easier to work with now that Generic instances exist on 0.4.18.1. I'll take the code from GitHub instead of Hackage for now until #95 is released.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant