Hawk-0.0.2: src/Hawk/Model/Criteria/Criteria.hs
-- --------------------------------------------------------------------------
{- |
Module : $Header$
Copyright : Copyright (C) 2009 Björn Peemöller, Stefan Roggensack
License : BSD3
Maintainer : {inf6254, inf6509}fh-wedel.de
Stability : experimental
Portability : portable
Version : $Id: Criteria.hs 291 2009-05-01 13:01:55Z inf6509 $
Function for working with the whole Criteria data
-}
-- ----------------------------------------------------------------------------
module Hawk.Model.Criteria.Criteria
(
-- * Criteria
Criteria (..)
, setRestriction
, newCriteria
, restrictionCriteria
, addExtra
, addLimit
, setOrder
-- * Query
, Query (..)
, newSelect
, setOption
, setCriteria
, setProjection
, setTables
, setGrouping
, setHaving
, modifyCriteria
-- * Manipulation
, Manipulation (..)
, newDelete
, newUpdate
, newInsert
, setManipulationCriteria
, modifyManipulationCriteria
, setTable
, setSet
, setValues
) where
import Hawk.Model.Criteria.Types
import Hawk.Model.Criteria.Projection
import Hawk.Model.Criteria.Restriction
import Hawk.Model.Criteria.Order
import Data.List (intercalate)
data Criteria = Criteria
{ restriction :: Maybe Restriction -- ^ WHERE
, ordering :: [Order] -- ^ ORDER BY
, extra :: [String] -- ^ LIMIT, OFFSET, ...
}
data Query = Select
{ option :: Maybe String -- ^ ALL, DISTINCT, ...
, projection :: [Projection] -- ^ SELECT
, tables :: [TableName] -- ^ FROM
, grouping :: [ColumnName] -- ^ GROUP BY
, having :: Maybe Restriction -- ^ HAVING
, criteria :: Criteria -- ^ WHERE, ORDER BY and LIMIT, OFFSET, ...
}
data Manipulation =
Delete
{ table :: TableName
, manipulationCriteria :: Criteria
}
| Update
{ table :: TableName
, set :: [(ColumnName, SqlValue)]
, manipulationCriteria :: Criteria
}
| Insert
{ table :: TableName
, values :: [(ColumnName, SqlValue)]
}
instance ShowSql Criteria where
showSql c = whereClause (restriction c)
++ orderClause (ordering c)
++ extraClause (extra c)
where
whereClause r = case r of
Nothing -> []
Just rs -> " WHERE " ++ showSql rs
orderClause o = case o of
[] -> ""
os -> " ORDER BY " ++ intercalate ", " (map showSql os)
extraClause e = ' ' : intercalate ", " e
instance ShowSql Query where
showSql c = optionsClause (option c)
++ selectClause (projection c)
++ fromClause (tables c)
++ whereClause (restriction $ criteria c)
++ groupClause (grouping c)
++ orderClause (ordering $ criteria c)
++ havingClause (having c)
++ extraClause (extra $ criteria c)
where
optionsClause opt = case opt of
Nothing -> "SELECT"
Just o -> "SELECT " ++ o
selectClause proj = case proj of
[] -> " *"
p -> ' ' : intercalate ", " (map showSql p)
fromClause tbls = " FROM " ++ intercalate ", " tbls
whereClause r = case r of
Nothing -> []
Just rs -> " WHERE " ++ showSql rs
groupClause g = case g of
[] -> ""
gs -> " GROUP BY " ++ intercalate ", " gs
orderClause o = case o of
[] -> ""
os -> " ORDER BY " ++ intercalate ", " (map showSql os)
havingClause h = case h of
Nothing -> []
Just hs -> " HAVING " ++ showSql hs
extraClause e = ' ' : intercalate ", " e
instance ShowSql Manipulation where
showSql (Delete t c) = showDelete t c
showSql (Update t s c) = showUpdate t s c
showSql (Insert t s ) = showInsert t s
showDelete :: TableName -> Criteria -> String
showDelete tbl cri =
deleteClause ++ showSql cri
where
deleteClause = "DELETE FROM " ++ tbl
showUpdate :: TableName -> [(ColumnName, SqlValue)] -> Criteria -> String
showUpdate tbl s cri =
updateClause ++ columnExpr ++ showSql cri
where
updateClause = "UPDATE " ++ tbl
columnExpr = " SET " ++ intercalate ", " (map (\(cn,_) -> cn ++ " = ? ") s)
showInsert :: TableName -> [(ColumnName, SqlValue)] -> String
showInsert tbl s =
insertClause ++ columns ++ value
where
insertClause = "INSERT INTO " ++ tbl
columns = " (" ++ intercalate ", " (map fst s) ++ ")"
value = " VALUES (" ++ intercalate ", " (map (const "?") s) ++ ")"
instance GetValues Criteria where
getValues = maybe [] getValues . restriction
instance GetValues Query where
getValues (Select _ _ _ _ h c) = getValues c ++ maybe [] getValues h
instance GetValues Manipulation where
getValues (Delete _ c) = getValues c
getValues (Update _ s c) = map snd s ++ getValues c
getValues (Insert _ s) = map snd s
-- * Criteria functions
-- | Create a empty Criteria
newCriteria :: Criteria
newCriteria = Criteria Nothing [] []
restrictionCriteria :: Restriction -> Criteria
restrictionCriteria r = setRestriction r newCriteria
-- | Set the Restriction of a Criteria (sql where clause)
setRestriction :: Restriction -> Criteria -> Criteria
setRestriction r c = c {restriction = Just r}
-- | Set the Order of a Criteria (sql order by clause)
setOrder :: [Order] -> Criteria -> Criteria
setOrder o c = c {ordering = o}
-- | Set the Extra of a Criteria (sql limit, offset, etc.)
addExtra :: String -> Criteria -> Criteria
addExtra e c = c { extra = e : extra c }
-- | Set the Projection of a Selct (sql select clause)
setProjection :: [Projection] -> Query -> Query
setProjection p c = c {projection = p}
-- * Query functions
-- | Create a empty Select
newSelect :: Query
newSelect = Select Nothing [] [] [] Nothing newCriteria
-- | Set the select Option (ALL, DISTINCT)
setOption :: String -> Query -> Query
setOption o q = q {option = Just o}
-- | Set the criteria
setCriteria :: Criteria -> Query -> Query
setCriteria c q = q {criteria = c}
-- | apply a funktion to the containing Criteria
modifyCriteria :: (Criteria -> Criteria) -> Query -> Query
modifyCriteria f q = q {criteria = f $ criteria q}
-- | Set a limit for the query
addLimit :: Int -> Int -> Criteria -> Criteria
addLimit start cnt = addExtra $ "LIMIT " ++ show start ++ ", " ++ show cnt
-- | Set the Tables of a Criteria (sql where clause)
setTables :: [TableName] -> Query -> Query
setTables t c = c {tables = t}
-- | Set the Grouoing of a Criteria (sql group by clause)
setGrouping :: [ColumnName] -> Query -> Query
setGrouping g c = c {grouping = g}
-- | Set the Restriction of a Criteria (sql having clause)
setHaving :: Restriction -> Query -> Query
setHaving h c = c {having = Just h}
-- * Manipulation functions
-- | Create a new DELETE sql
newDelete :: TableName -> Manipulation
newDelete t = Delete t newCriteria
-- | Create a new UPDATE sql
newUpdate :: TableName -> Manipulation
newUpdate t = Update t [] newCriteria
-- | Create a new INSERT sql
newInsert :: TableName -> Manipulation
newInsert t = Insert t []
-- | Set the criteria
setManipulationCriteria :: Criteria -> Manipulation -> Manipulation
setManipulationCriteria c m = m {manipulationCriteria = c}
-- | apply a funktion to the containing Criteria
modifyManipulationCriteria :: (Criteria -> Criteria) -> Manipulation -> Manipulation
modifyManipulationCriteria _ m@(Insert _ _) = m
modifyManipulationCriteria f q = q {manipulationCriteria = f $ manipulationCriteria q}
-- | set the Table name to a different value
setTable :: TableName -> Manipulation -> Manipulation
setTable t c = c {table = t}
-- | set the Column value combination for a UPDATE sql
setSet :: [(ColumnName, SqlValue)] -> Manipulation -> Manipulation
setSet s u@(Update _ _ _) = u {set = s}
setSet _ m = m
-- | set the Column value combination for a INSERT sql
setValues :: [(ColumnName, SqlValue)] -> Manipulation -> Manipulation
setValues v u@(Insert _ _) = u {values = v}
setValues _ m = m