Search code examples
databasesqlitehaskellexecutemany

How to write a executemany with two inputs in haskell?


saveX :: [String] -> Int->IO ()
saveX [] y= return ()
sav xs y=
     do conn <- connectSqlite3 "cw.db"
        stmt <- prepare conn "INSERT INTO pic (src,urlId) VALUES (?,?)"
        executeMany stmt <what to add here>
        commit conn

I have a table with two columns src and urlId and [String] contains list of src and Int is the urlID. I want to insert all the srcs to table with the urlId. I have tried few ways with converting tuples but toSql does not work for it. Please help me with this


Solution

  • There's an almost identical example in Real World Haskell:

    ghci> conn <- connectSqlite3 "test1.db"
    ghci> stmt <- prepare conn "INSERT INTO test VALUES (?, ?)"
    ghci> executeMany stmt [[toSql 5, toSql "five's nice"], [toSql 6, SqlNull]]
    ghci> commit conn
    ghci> disconnect conn
    

    Edit

    For your specific case, this isn't a question about how to use HDBC, but about how to combine one piece of ordinary Haskell data, y, with a list of data, xs. The map function takes a single function and applies it to every element in a list, returning a list of the results. If we put the single y in a function, we can map it onto the list, and get a result for every item in the list. For example:

    map (\x -> (x, "One Thing")) [1, 2, 3]
    

    Will result in:

    [(1, "One Thing"), (2, "One Thing"), (3, "One Thing")]
    

    To combine your one y that is a urlId with your xs that contain sources, you could write

    map (\x -> [toSql x, toSql y]) xs
    

    This would give you the following entire piece of code:

    saveX :: [String] -> Int->IO ()
    saveX [] y= return ()
    sav xs y=
         do conn <- connectSqlite3 "cw.db"
            stmt <- prepare conn "INSERT INTO pic (src,urlId) VALUES (?,?)"
            executeMany stmt (map (\x -> [toSql x, toSql y]) xs)
            commit conn