haskellsqlitetransactionshdbc

Submitting multiple SQL statements strictly to SQLite in a single transaction from Haskell HDBC


My Haskell skills are very much in it's infancy, and monads puzzle me.

However, I need to construct a function that will install all the fixtures in a sqlite3 database.

module UmeQuery where

import Database.HDBC 
import Database.HDBC.Sqlite3

testdb = "testdata/ume.umedb"

runSetup dbFile = do
    conn <- connectSqlite3 dbFile
    res <- withTransaction conn ( setup conn )
    disconnect conn
    return $ res

setup conn = do 
    n1 <- setupUtterances conn
    n2 <- setupLevels conn
    return $ [n1, n2] 


setupUtterances conn = do 
    q1 <- quickQuery' conn "DROP TABLE IF EXISTS utterances;" []
    q2 <- quickQuery' conn "CREATE TABLE utterances (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, filelength REAL, updated_at TEXT, checksum_algorithm TEXT, checksum TEXT, UNIQUE(name) ON CONFLICT FAIL );" []
    return $ [q1,q2] 

setupLevels conn = do 
    q1 <- quickQuery' conn "DROP TABLE IF EXISTS levels;"
    q2 <- quickQuery' conn "CREATE TABLE levels (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE ON CONFLICT FAIL );"
    return $ [q1,q2]

When I try to run this, i get the following output:

UmeQuery.hs:16:15:
Couldn't match expected type `IO [[[SqlValue]]]'
            with actual type `[SqlValue] -> [IO [[SqlValue]]]'
In the return type of a call of `setupLevels'
Probable cause: `setupLevels' is applied to too few arguments
In a stmt of a 'do' block: n2 <- setupLevels conn
In the expression:
  do { n1 <- setupUtterances conn;
       n2 <- setupLevels conn;
       return $ [n1, n2] }

What I would like to get is just something that indicates that everything is fine. Please note that I seem to be needing strictness, otherwise the "DROP TABLE " statements are not always exceeded before the new table is created.

Also, if I may ask two questions at once: setup is will eventually set up 12 tables in a similar fashion. Is there any way I can construct setup as an fmap of a ($ conn) over a list containing the involved functions in this case? It would make the code much nicer, of course.


Solution

  • Sorry, yes the problem was ideed that i was currying without realizing it. Too late for coding, I guess.

    import Database.HDBC 
    import Database.HDBC.Sqlite3
    
    testdb = "testdata/ume.umedb"
    
    runSetup dbFile = do
        conn <- connectSqlite3 dbFile
        res <- withTransaction conn ( setup )
        disconnect conn
        return $ res
    
    setup conn = do 
        n1 <- setupUtterances conn
        n2 <- setupLevels conn
        return $ n1 
    
    setupUtterances conn = do 
        quickQuery' conn "DROP TABLE IF EXISTS utterances;" []
        quickQuery' conn "CREATE TABLE utterances (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, filelength REAL, updated_at TEXT, checksum_algorithm TEXT, checksum TEXT, UNIQUE(name) ON CONFLICT FAIL );" []
        return ()
    
    setupLevels conn = do 
        quickQuery' conn "DROP TABLE IF EXISTS levels;" []
        quickQuery' conn "CREATE TABLE levels (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE ON CONFLICT FAIL );" []
        return ()
    
    main = runSetup testdb
    

    This works.