1
- {-# LANGUAGE FlexibleContexts, OverloadedStrings, RecordWildCards
2
- , ScopedTypeVariables, TypeFamilies #-}
3
- {-# OPTIONS_GHC -Wall #-}
1
+ module Catalog (catalog ) where
4
2
5
3
import Control.Arrow (second )
6
4
import Control.Monad
7
5
import Control.Monad.Base
8
6
import Control.Monad.Catch
9
7
import Data.Function
10
8
import Data.Int
11
- import Data.Monoid
12
9
import Data.Monoid.Utils
10
+ import Data.Pool
11
+ import Data.Text qualified as T
13
12
import Database.PostgreSQL.PQTypes
14
13
import Database.PostgreSQL.PQTypes.Internal.Utils (mread )
15
14
import System.Console.Readline
16
15
import System.Environment
17
- import qualified Data.ByteString.Char8 as BS
18
16
19
17
-- | Generic 'putStrLn'.
20
18
printLn :: MonadBase IO m => String -> m ()
@@ -25,7 +23,7 @@ getConnSettings :: IO ConnectionSettings
25
23
getConnSettings = do
26
24
args <- getArgs
27
25
case args of
28
- [conninfo] -> return def { csConnInfo = BS . pack conninfo }
26
+ [conninfo] -> return defaultConnectionSettings { csConnInfo = T . pack conninfo}
29
27
_ -> do
30
28
prog <- getProgName
31
29
error $ " Usage:" <+> prog <+> " <connection info>"
@@ -34,10 +32,11 @@ getConnSettings = do
34
32
35
33
-- | Representation of a book.
36
34
data Book = Book
37
- { bookID :: Int64
38
- , bookName :: String
39
- , bookYear :: Int32
40
- } deriving (Read , Show )
35
+ { bookID :: Int64
36
+ , bookName :: String
37
+ , bookYear :: Int32
38
+ }
39
+ deriving (Read , Show )
41
40
42
41
-- | Intermediate representation of 'Book'.
43
42
type instance CompositeRow Book = (Int64 , String , Int32 )
@@ -46,78 +45,87 @@ instance PQFormat Book where
46
45
pqFormat = " %book_"
47
46
48
47
instance CompositeFromSQL Book where
49
- toComposite (bid, name, year) = Book {
50
- bookID = bid
51
- , bookName = name
52
- , bookYear = year
53
- }
48
+ toComposite (bid, name, year) =
49
+ Book
50
+ { bookID = bid
51
+ , bookName = name
52
+ , bookYear = year
53
+ }
54
54
55
55
withCatalog :: ConnectionSettings -> IO () -> IO ()
56
- withCatalog cs = bracket_ createStructure dropStructure
56
+ withCatalog settings = bracket_ createStructure dropStructure
57
57
where
58
- -- | Create needed tables and types.
59
- createStructure = runDBT (simpleSource cs) def $ do
58
+ ConnectionSource cs = simpleSource settings
59
+
60
+ -- Create needed tables and types.
61
+ createStructure = runDBT cs defaultTransactionSettings $ do
60
62
printLn " Creating tables..."
61
- runSQL_ $ mconcat [
62
- " CREATE TABLE authors_ ("
63
- , " id BIGSERIAL NOT NULL"
64
- , " , name TEXT NOT NULL"
65
- , " , PRIMARY KEY (id)"
66
- , " )"
67
- ]
68
- runSQL_ $ mconcat [
69
- " CREATE TABLE books_ ("
70
- , " id BIGSERIAL NOT NULL"
71
- , " , name TEXT NOT NULL"
72
- , " , year INTEGER NOT NULL"
73
- , " , author_id BIGINT NOT NULL"
74
- , " , PRIMARY KEY (id)"
75
- , " , FOREIGN KEY (author_id) REFERENCES authors_ (id)"
76
- , " )"
77
- ]
78
- runSQL_ $ mconcat [
79
- " CREATE TYPE book_ AS ("
80
- , " id BIGINT"
81
- , " , name TEXT"
82
- , " , year INTEGER"
83
- , " )"
84
- ]
85
- -- | Drop previously created database structures.
86
- dropStructure = runDBT (simpleSource cs) def $ do
63
+ runSQL_ $
64
+ mconcat
65
+ [ " CREATE TABLE authors_ ("
66
+ , " id BIGSERIAL NOT NULL"
67
+ , " , name TEXT NOT NULL"
68
+ , " , PRIMARY KEY (id)"
69
+ , " )"
70
+ ]
71
+ runSQL_ $
72
+ mconcat
73
+ [ " CREATE TABLE books_ ("
74
+ , " id BIGSERIAL NOT NULL"
75
+ , " , name TEXT NOT NULL"
76
+ , " , year INTEGER NOT NULL"
77
+ , " , author_id BIGINT NOT NULL"
78
+ , " , PRIMARY KEY (id)"
79
+ , " , FOREIGN KEY (author_id) REFERENCES authors_ (id)"
80
+ , " )"
81
+ ]
82
+ runSQL_ $
83
+ mconcat
84
+ [ " CREATE TYPE book_ AS ("
85
+ , " id BIGINT"
86
+ , " , name TEXT"
87
+ , " , year INTEGER"
88
+ , " )"
89
+ ]
90
+ -- Drop previously created database structures.
91
+ dropStructure = runDBT cs defaultTransactionSettings $ do
87
92
printLn " Dropping tables..."
88
93
runSQL_ " DROP TYPE book_"
89
94
runSQL_ " DROP TABLE books_"
90
95
runSQL_ " DROP TABLE authors_"
91
96
92
97
----------------------------------------
93
98
94
- processCommand :: ConnectionSource -> String -> IO ()
99
+ processCommand :: ConnectionSourceM IO -> String -> IO ()
95
100
processCommand cs cmd = case parse cmd of
96
- -- | Display authors.
97
- (" authors" , " " ) -> runDBT cs def $ do
101
+ -- Display authors.
102
+ (" authors" , " " ) -> runDBT cs defaultTransactionSettings $ do
98
103
runSQL_ " SELECT * FROM authors_ ORDER BY name"
99
- mapDB_ $ \ (aid:: Int64 , name ) -> printLn $ show aid <> " :" <+> name
100
- -- | Display books.
101
- (" books" , " " ) -> runDBT cs def $ do
104
+ mapDB_ $ \ (aid :: Int64 , name ) -> printLn $ show aid <> " :" <+> name
105
+ -- Display books.
106
+ (" books" , " " ) -> runDBT cs defaultTransactionSettings $ do
102
107
runSQL_ " SELECT a.name, ARRAY(SELECT (b.id, b.name, b.year)::book_ FROM books_ b WHERE b.author_id = a.id) FROM authors_ a ORDER BY a.name"
103
- mapDB_ $ \ (author, CompositeArray1 (books:: [Book ])) -> do
108
+ mapDB_ $ \ (author, CompositeArray1 (books :: [Book ])) -> do
104
109
printLn $ author <> " :"
105
110
forM_ books $ \ book -> printLn $ " *" <+> show book
106
- -- | Insert an author.
111
+ -- Insert an author.
107
112
(" insert_author" , mname) -> case mread mname of
108
- Just (name:: String ) -> runDBT cs def . runQuery_ $
109
- " INSERT INTO authors_ (name) VALUES (" <?> name <+> " )"
113
+ Just (name :: String ) ->
114
+ runDBT cs defaultTransactionSettings . runQuery_ $
115
+ " INSERT INTO authors_ (name) VALUES (" <?> name <+> " )"
110
116
Nothing -> printLn $ " Invalid name"
111
- -- | Insert a book.
117
+ -- Insert a book.
112
118
(" insert_book" , mbook) -> case mread mbook of
113
- Just record -> runDBT cs def . runQuery_ $ rawSQL
114
- " INSERT INTO books_ (name, year, author_id) VALUES ($1, $2, $3)"
115
- (record:: (String , Int32 , Int64 ))
119
+ Just record ->
120
+ runDBT cs defaultTransactionSettings . runQuery_ $
121
+ rawSQL
122
+ " INSERT INTO books_ (name, year, author_id) VALUES ($1, $2, $3)"
123
+ (record :: (String , Int32 , Int64 ))
116
124
Nothing -> printLn $ " Invalid book record"
117
- -- | Handle unknown commands.
125
+ -- Handle unknown commands.
118
126
_ -> printLn $ " Unknown command:" <+> cmd
119
127
where
120
- parse = second (drop 1 ) . break (== ' ' )
128
+ parse = second (drop 1 ) . break (== ' ' )
121
129
122
130
-- | Example chain of commands:
123
131
--
@@ -131,14 +139,18 @@ processCommand cs cmd = case parse cmd of
131
139
--
132
140
-- If you want to check out exceptions in action,
133
141
-- try inserting a book with invalid author id.
134
- main :: IO ()
135
- main = do
142
+ catalog :: IO ()
143
+ catalog = do
136
144
cs <- getConnSettings
137
145
withCatalog cs $ do
138
- pool <- poolSource (cs { csComposites = [" book_" ] }) 1 10 4
139
- fix $ \ next -> readline " > " >>= maybe (printLn " " ) (\ cmd -> do
140
- when (cmd /= " quit" ) $ do
141
- processCommand pool cmd
142
- addHistory cmd
143
- next
144
- )
146
+ ConnectionSource pool <- poolSource (cs {csComposites = [" book_" ]}) (\ connect disconnect -> defaultPoolConfig connect disconnect 1 10 )
147
+ fix $ \ next ->
148
+ readline " > "
149
+ >>= maybe
150
+ (printLn " " )
151
+ ( \ cmd -> do
152
+ when (cmd /= " quit" ) $ do
153
+ processCommand pool cmd
154
+ addHistory cmd
155
+ next
156
+ )
0 commit comments