Copied from here:
- I see this as an opportunity to simplify how queries are executed (or any SQL statements) - making the whole process more abstract is one thing and simplifying some type classes is the other.
- type classes like GenericQuery are there for two reasons:
- to hide complicated constraints from the user, e.q. so that the type of the query consists of one constraint without any intermediate type parameters
- overloading convenience
- but the user should not be forced to use them
- we should provide common query variations that could be used by current type classes and users directly. I've included examples that should illustrate my point
primGenericQuery ∷
∀ s a i.
GetCols i ⇒
String → -- query parameter placeholder, e.g. '$' for pg, and '?' for sqlite
Int → -- first query parameter index, usually `1`
-- both of these parameters determine how we generate query
-- parameter names, e.g. '$1', '$2', ... for pg
(String → Array Foreign → a) →
FullQuery s { | i } →
a
primGenericQuery ph i exec q = do
-- transform Query AST `q` into a query string and query parameters
let { strQuery, params } = showM ph i $ showQuery q
-- execute the query with the parameters
exec strQuery params
pgPrimGenericQuery ∷
∀ s a i m.
GetCols i ⇒ -- needed by query string generation
MonadSeldaPG m ⇒ -- PG specific monad constraints
(Array Foreign → m a) → -- generic decoder, errors are handled by monad `m`
FullQuery s { | i } → -- query AST
m (Array a) -- result rows of output records, record type `{ | o }` is determined by `i` via the type-function
pgPrimGenericQuery decodeRow = primGenericQuery "$" 1 exec
where
exec strQuery params = do
conn ← ask
errOrResult ← liftAff $ PostgreSQL.unsafeQuery conn strQuery params
result ← either throwError pure errOrResult
traverse decodeRow result.rows
pgGenericQuery ∷
∀ s o i m.
GetCols i ⇒
MapR UnCol_ i o ⇒ -- type-level function that maps over `{ | i }`
-- and removes `Col s` from each record member
-- thus `o` is now determined by the input `i`
MonadSeldaPG m ⇒
(Array Foreign → m { | o }) →
FullQuery s { | i } →
m (Array { | o }) -- the additional constraint forces the
-- appropriate result type
pgGenericQuery = pgPrimGenericQuery
Copied from here: