Better documentation of Sql's internals.

This commit is contained in:
Felipe Lessa 2012-09-06 10:00:23 -03:00
parent 17a2cb65a9
commit 3b995ba46f

View File

@ -21,6 +21,8 @@ module Database.Esqueleto.Internal.Sql
, update , update
, toRawSql , toRawSql
, Mode(..) , Mode(..)
, Escape
, SqlSelect
) where ) where
import Control.Applicative (Applicative(..), (<$>)) import Control.Applicative (Applicative(..), (<$>))
@ -199,6 +201,7 @@ parensM Parens = parens
data OrderByType = ASC | DESC data OrderByType = ASC | DESC
-- | (Internal) Backend-specific function that escapes a 'DBName'.
type Escape = DBName -> TLB.Builder type Escape = DBName -> TLB.Builder
@ -451,7 +454,12 @@ update = rawExecute UPDATE . from
---------------------------------------------------------------------- ----------------------------------------------------------------------
-- | Pretty prints a 'SqlQuery' into a SQL query. -- | (Internal) Pretty prints a 'SqlQuery' into a SQL query.
--
-- Note: if you're curious about the SQL query being generated by
-- @esqueleto@, instead of manually using this function (which is
-- possible but tedious), you may just turn on query logging of
-- @persistent@.
toRawSql :: SqlSelect a r => Mode -> Escape -> SqlQuery a -> (TLB.Builder, [PersistValue]) toRawSql :: SqlSelect a r => Mode -> Escape -> SqlQuery a -> (TLB.Builder, [PersistValue])
toRawSql mode esc query = toRawSql mode esc query =
let (ret, SideData fromClauses setClauses whereClauses orderByClauses) = let (ret, SideData fromClauses setClauses whereClauses orderByClauses) =
@ -466,6 +474,7 @@ toRawSql mode esc query =
, makeOrderBy esc orderByClauses , makeOrderBy esc orderByClauses
] ]
-- | (Internal) Mode of query being converted by 'toRawSql'.
data Mode = SELECT | SELECT_DISTINCT | DELETE | UPDATE data Mode = SELECT | SELECT_DISTINCT | DELETE | UPDATE
@ -552,8 +561,11 @@ parens :: TLB.Builder -> TLB.Builder
parens b = "(" <> (b <> ")") parens b = "(" <> (b <> ")")
-- | Class for mapping results coming from 'SqlQuery' into actual ----------------------------------------------------------------------
-- results.
-- | (Internal) Class for mapping results coming from 'SqlQuery'
-- into actual results.
-- --
-- This looks very similar to @RawSql@, and it is! However, -- This looks very similar to @RawSql@, and it is! However,
-- there are some crucial differences and ultimately they're -- there are some crucial differences and ultimately they're
@ -571,11 +583,15 @@ class SqlSelect a r | a -> r, r -> a where
-- | Transform a row of the result into the data type. -- | Transform a row of the result into the data type.
sqlSelectProcessRow :: [PersistValue] -> Either T.Text r sqlSelectProcessRow :: [PersistValue] -> Either T.Text r
-- | Not useful for 'select', but used for 'update' and 'delete'.
instance SqlSelect () () where instance SqlSelect () () where
sqlSelectCols _ _ = mempty sqlSelectCols _ _ = mempty
sqlSelectColCount _ = 0 sqlSelectColCount _ = 0
sqlSelectProcessRow _ = Right () sqlSelectProcessRow _ = Right ()
-- | You may return an 'Entity' from a 'select' query.
instance PersistEntity a => SqlSelect (SqlExpr (Entity a)) (Entity a) where instance PersistEntity a => SqlSelect (SqlExpr (Entity a)) (Entity a) where
sqlSelectCols escape expr@(EEntity ident) = ret sqlSelectCols escape expr@(EEntity ident) = ret
where where
@ -602,6 +618,8 @@ instance PersistEntity a => SqlSelect (SqlExpr (Entity a)) (Entity a) where
getEntityVal :: SqlExpr (Entity a) -> a getEntityVal :: SqlExpr (Entity a) -> a
getEntityVal = error "Esqueleto/Sql/getEntityVal" getEntityVal = error "Esqueleto/Sql/getEntityVal"
-- | You may return a possibly-@NULL@ 'Entity' from a 'select' query.
instance PersistEntity a => SqlSelect (SqlExpr (Maybe (Entity a))) (Maybe (Entity a)) where instance PersistEntity a => SqlSelect (SqlExpr (Maybe (Entity a))) (Maybe (Entity a)) where
sqlSelectCols escape (EMaybe ent) = sqlSelectCols escape ent sqlSelectCols escape (EMaybe ent) = sqlSelectCols escape ent
sqlSelectColCount = sqlSelectColCount . fromEMaybe sqlSelectColCount = sqlSelectColCount . fromEMaybe
@ -612,6 +630,9 @@ instance PersistEntity a => SqlSelect (SqlExpr (Maybe (Entity a))) (Maybe (Entit
| all (== PersistNull) cols = return Nothing | all (== PersistNull) cols = return Nothing
| otherwise = Just <$> sqlSelectProcessRow cols | otherwise = Just <$> sqlSelectProcessRow cols
-- | You may return any single value (i.e. a single column) from
-- a 'select' query.
instance PersistField a => SqlSelect (SqlExpr (Value a)) (Value a) where instance PersistField a => SqlSelect (SqlExpr (Value a)) (Value a) where
sqlSelectCols esc (ERaw p f) = let (b, vals) = f esc sqlSelectCols esc (ERaw p f) = let (b, vals) = f esc
in (parensM p b, vals) in (parensM p b, vals)
@ -619,6 +640,9 @@ instance PersistField a => SqlSelect (SqlExpr (Value a)) (Value a) where
sqlSelectProcessRow [pv] = Value <$> fromPersistValue pv sqlSelectProcessRow [pv] = Value <$> fromPersistValue pv
sqlSelectProcessRow _ = Left "SqlSelect (Value a): wrong number of columns." sqlSelectProcessRow _ = Left "SqlSelect (Value a): wrong number of columns."
-- | You may return tuples (up to 8-tuples) and tuples of tuples
-- from a 'select' query.
instance ( SqlSelect a ra instance ( SqlSelect a ra
, SqlSelect b rb , SqlSelect b rb
) => SqlSelect (a, b) (ra, rb) where ) => SqlSelect (a, b) (ra, rb) where
@ -643,6 +667,7 @@ instance ( SqlSelect a ra
in colCountFst `seq` processRow in colCountFst `seq` processRow
-- Avoids recalculating 'colCountFst'. -- Avoids recalculating 'colCountFst'.
instance ( SqlSelect a ra instance ( SqlSelect a ra
, SqlSelect b rb , SqlSelect b rb
, SqlSelect c rc , SqlSelect c rc