relational-query-0.8.6.0: src/Database/Relational/Query/SQL.hs
{-# LANGUAGE OverloadedStrings #-}
-- |
-- Module : Database.Relational.Query.SQL
-- Copyright : 2013-2017 Kei Hibino
-- License : BSD3
--
-- Maintainer : ex8k.hibino@gmail.com
-- Stability : experimental
-- Portability : unknown
--
-- This module defines functions to generate simple SQL strings.
module Database.Relational.Query.SQL (
-- * Query suffix
QuerySuffix, showsQuerySuffix,
-- * Update SQL
updatePrefixSQL,
updateSQL',
updateOtherThanKeySQL', updateOtherThanKeySQL,
-- * Insert SQL
insertPrefixSQL, insertSQL,
-- * Delete SQL
deletePrefixSQL', deletePrefixSQL
) where
import Data.Array (listArray, (!))
import Data.Monoid (mconcat, (<>))
import Language.SQL.Keyword (Keyword(..), (.=.), (|*|))
import qualified Language.SQL.Keyword as SQL
import Database.Record (PersistableWidth)
import Database.Record.ToSql (untypedUpdateValuesIndex)
import Database.Relational.Query.Internal.SQL
(StringSQL, stringSQL, showStringSQL, rowConsStringSQL, )
import Database.Relational.Query.Pi (Pi)
import qualified Database.Relational.Query.Pi.Unsafe as UnsafePi
import Database.Relational.Query.Table (Table, name, columns, recordWidth)
import qualified Database.Relational.Query.Projection as Projection
-- | Type for query suffix words
type QuerySuffix = [Keyword]
-- | Expand query suffix words
showsQuerySuffix :: QuerySuffix -> StringSQL
showsQuerySuffix = mconcat
-- | Generate prefix string of update SQL.
updatePrefixSQL :: Table r -> StringSQL
updatePrefixSQL table = UPDATE <> stringSQL (name table)
-- | Generate update SQL by specified key and table.
-- Columns name list of table are also required.
updateSQL' :: String -- ^ Table name
-> [StringSQL] -- ^ Column name list to update
-> [StringSQL] -- ^ Key column name list
-> String -- ^ Result SQL
updateSQL' table cols key =
showStringSQL $ mconcat
[UPDATE, stringSQL table, SET, SQL.fold (|*|) updAssigns,
WHERE, SQL.fold SQL.and keyAssigns]
where
assigns cs = [ c .=. "?" | c <- cs ]
updAssigns = assigns cols
keyAssigns = assigns key
-- | Generate update SQL by specified key and table.
-- Columns name list of table are also required.
updateOtherThanKeySQL' :: String -- ^ Table name
-> [StringSQL] -- ^ Column name list
-> [Int] -- ^ Key column indexes
-> String -- ^ Result SQL
updateOtherThanKeySQL' table cols ixs =
updateSQL' table updColumns keyColumns
where
width' = length cols
cols' = listArray (0, width' -1) cols
otherThanKey = untypedUpdateValuesIndex ixs width'
columns' is = [ cols' ! i | i <- is ]
updColumns = columns' otherThanKey
keyColumns = columns' ixs
-- | Generate update SQL specified by single key.
updateOtherThanKeySQL :: Table r -- ^ Table metadata
-> Pi r p -- ^ Key columns
-> String -- ^ Result SQL
updateOtherThanKeySQL tbl key =
updateOtherThanKeySQL' (name tbl) (columns tbl) (UnsafePi.unsafeExpandIndexes' (recordWidth tbl) key)
-- | Generate prefix string of insert SQL.
insertPrefixSQL :: Pi r r' -> Table r -> StringSQL
insertPrefixSQL pi' table =
INSERT <> INTO <> stringSQL (name table) <> rowConsStringSQL cols where
cols = Projection.columns . Projection.wpi (recordWidth table) (Projection.unsafeFromTable table) $ pi'
{-# DEPRECATED insertSQL "Deprecated." #-}
-- | Generate insert SQL.
insertSQL :: PersistableWidth r
=> Pi r r' -- ^ Columns selector to insert
-> Table r -- ^ Table metadata
-> String -- ^ Result SQL
insertSQL pi' tbl = showStringSQL $ insertPrefixSQL pi' tbl <> VALUES <> vs where
w = UnsafePi.width pi'
vs = rowConsStringSQL (replicate w "?")
-- | Generate all column delete SQL by specified table. Untyped table version.
deletePrefixSQL' :: String -> StringSQL
deletePrefixSQL' table = DELETE <> FROM <> stringSQL table
-- | Generate all column delete SQL by specified table.
deletePrefixSQL :: Table r -- ^ Table metadata
-> StringSQL -- ^ Result SQL
deletePrefixSQL = deletePrefixSQL' . name