Я программист Java, который изучает Haskell.
Я работаю над небольшим веб-приложением, которое использует Happstack и разговаривает с базой данных через HDBC.Параллельный пул соединений DB в Haskell
Я написал выбрать и EXEC функции, и я использую их, как это:
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
Очень просто, как вы видите. Существует запрос, params и результат.
Создание соединения и фиксация/откат скрыты внутри select и exec.
Это хорошо, я не хочу заботиться об этом в своем «логическом» коде.
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)
Плохие пункты:
- новое соединение всегда создается для каждого вызова - это убивает производительность на большой нагрузке
- DB URL "users.db" жестко закодировано - я не могу повторное использование этих функций через другие проекты без редактирования
Вопрос 1: как ввести пул соединений остроумия h определенное определенное (мин., макс.) количество одновременных соединений, поэтому соединения будут повторно использоваться между вызовами select/exec?
ВОПРОС 2: Как настроить строку «users.db»? (Как переместить его на клиентский код?)
Должна быть прозрачная функция: код пользователя не должен требовать явной обработки/освобождения подключения.
У меня нет полного ответа для вас, но ваша проблема в том, что вы неправильно отстранили соединение. Вероятно, вы захотите поместить его в структуру, подобную Reader, чтобы он мог быть передан каждому запросу. – jrockway
Хм, операции SQL все застряли в монаде «IO», так что, возможно, «ReaderT IO»? Звучит разумно. – ephemient