Soy un programador de Java que aprende Haskell.
Trabajo en una pequeña aplicación web que utiliza Happstack y habla con una base de datos a través de HDBC.Grupo de conexiones de bases de datos concurrentes en Haskell
He escrito seleccione y ejecutivo funciones y los utilizo como esto:
module Main where
import Control.Exception (throw)
import Database.HDBC
import Database.HDBC.Sqlite3 -- just for this example, I use MySQL in production
main = do
exec "CREATE TABLE IF NOT EXISTS users (name VARCHAR(80) NOT NULL)" []
exec "INSERT INTO users VALUES ('John')" []
exec "INSERT INTO users VALUES ('Rick')" []
rows <- select "SELECT name FROM users" []
let toS x = (fromSql x)::String
let names = map (toS . head) rows
print names
muy simple como se ve. Hay consulta, params y resultado.
La creación de la conexión y las tareas de compromiso/restitución están ocultas dentro de select y exec.
Esto es bueno, no me importa en mi código "lógico".
exec :: String -> [SqlValue] -> IO Integer
exec query params = withDb $ \c -> run c query params
select :: String -> [SqlValue] -> IO [[SqlValue]]
select query params = withDb $ \c -> quickQuery' c query params
withDb :: (Connection -> IO a) -> IO a
withDb f = do
conn <- handleSqlError $ connectSqlite3 "users.db"
catchSql
(do r <- f conn
commit conn
disconnect conn
return r)
(\[email protected](SqlError _ _ m) -> do
rollback conn
disconnect conn
throw e)
puntos negativos:
- una nueva conexión siempre se crea para cada llamada - Esto mata el rendimiento en carga pesada
- DB url "users.db" está codificado - No puedo reutilizar estas funciones a través de otros proyectos w/o editar
PREGUNTA 1: cómo introducir un grupo de conexiones wi ¿Alguna cantidad definida (mínima, máxima) de conexiones concurrentes, por lo que las conexiones se reutilizarán entre las llamadas select/exec?
PREGUNTA 2: ¿Cómo hacer que la cadena "users.db" se pueda configurar? (¿Cómo moverlo al código de cliente?)
Debe ser una función transparente: el código de usuario no debe requerir el manejo/liberación explícita de la conexión.
No tengo una respuesta completa para usted, pero su problema es que ha abstraído la conexión incorrectamente. Probablemente desee colocarlo en una estructura similar a Reader, para que se pueda pasar a cada consulta. – jrockway
Hmm, las operaciones de SQL están todas atrapadas en la mónada de 'IO', así que tal vez' ReaderT IO'? Suena razonable. – ephemient