Jestem programistą Java, który uczy się Haskell.
Pracuję w małej aplikacji internetowej, która używa Happstack i rozmawia z bazą danych za pośrednictwem HDBC.Pula połączeń współbieżnych DB w Haskell
Pisałem wybrać i Exec funkcje i wykorzystać je tak:
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
Bardzo proste, jak widać. Istnieje zapytanie, params i wynik.
Tworzenie połączeń i zatwierdzanie/wycofywanie elementów są ukryte w select i exec.
To dobrze, nie chcę się tym przejmować w moim "logicznym" kodzie.
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)
Minusy:
- nowe połączenie jest zawsze tworzone dla każdej rozmowy - to zabija wydajność na dużym obciążeniem
- DB url "users.db" jest ustalony - Nie mogę ponownego użycia tych funkcji na innych projektów w/o edycję
pytanie 1: jak wprowadzić pulę połączeń Wi jakąś określoną (min., maks.) liczbę współbieżnych połączeń, aby połączenia były ponownie wykorzystywane między wywołaniami select/exec?
PYTANIE 2: Jak skonfigurować ciąg "users.db"? (Jak przenieść go do kodu klienta?)
Powinna to być funkcja przezroczysta: kod użytkownika nie powinien wymagać jawnej obsługi/zwalniania połączenia.
Nie mam dla ciebie pełnej odpowiedzi, ale Twoim problemem jest nieprawidłowe usunięcie połączenia. Prawdopodobnie chcesz umieścić go w strukturze podobnej do Czytnika, aby można było go przekazać do każdego zapytania. – jrockway
Hmm, operacje SQL utknęły w monadzie 'IO', więc może' ReaderT IO'? Brzmi rozsądnie. – ephemient