relational-query-0.8.5.0: src/Database/Relational/Query/Internal/BaseSQL.hs
-- |
-- Module : Database.Relational.Query.Internal.BaseSQL
-- Copyright : 2013-2017 Kei Hibino
-- License : BSD3
--
-- Maintainer : ex8k.hibino@gmail.com
-- Stability : experimental
-- Portability : unknown
--
-- This module provides base structure of SQL syntax tree.
module Database.Relational.Query.Internal.BaseSQL (
Duplication (..), showsDuplication,
Order (..), OrderColumn, OrderingTerm, composeOrderBy,
AssignColumn, AssignTerm, Assignment, composeSets,
composeChunkValues, composeChunkValuesWithColumns,
) where
import Data.Monoid (Monoid (..), (<>))
import Language.SQL.Keyword (Keyword(..), (|*|), (.=.))
import qualified Language.SQL.Keyword as SQL
import Database.Relational.Query.Internal.SQL
(StringSQL, rowConsStringSQL)
-- | Result record duplication attribute
data Duplication = All | Distinct deriving Show
-- | Compose duplication attribute string.
showsDuplication :: Duplication -> StringSQL
showsDuplication = dup where
dup All = ALL
dup Distinct = DISTINCT
-- | Order direction. Ascendant or Descendant.
data Order = Asc | Desc deriving Show
-- | Type for order-by column
type OrderColumn = StringSQL
-- | Type for order-by term
type OrderingTerm = (Order, OrderColumn)
-- | Compose ORDER BY clause from OrderingTerms
composeOrderBy :: [OrderingTerm] -> StringSQL
composeOrderBy = d where
d [] = mempty
d ts@(_:_) = ORDER <> BY <> SQL.fold (|*|) (map showsOt ts)
showsOt (o, e) = e <> order o
order Asc = ASC
order Desc = DESC
-- | Column SQL String of assignment
type AssignColumn = StringSQL
-- | Value SQL String of assignment
type AssignTerm = StringSQL
-- | Assignment pair
type Assignment = (AssignColumn, AssignTerm)
-- | Compose SET clause from ['Assignment'].
composeSets :: [Assignment] -> StringSQL
composeSets as = assigns where
assignList = foldr (\ (col, term) r ->
(col .=. term) : r)
[] as
assigns | null assignList = error "Update assignment list is null!"
| otherwise = SET <> SQL.fold (|*|) assignList
-- | Compose VALUES clause from value expression list.
composeChunkValues :: Int -- ^ record count per chunk
-> [StringSQL] -- ^ value expression list
-> Keyword
composeChunkValues n0 vs =
VALUES <> cvs
where
n | n0 >= 1 = n0
| otherwise = error $ "Invalid record count value: " ++ show n0
cvs = SQL.fold (|*|) . replicate n $ rowConsStringSQL vs
-- | Compose VALUES clause from value expression list.
composeChunkValuesWithColumns :: Int -- ^ record count per chunk
-> [Assignment] -- ^
-> StringSQL
composeChunkValuesWithColumns sz as =
rowConsStringSQL cs <> composeChunkValues sz vs
where
(cs, vs) = unzip as