{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
module Database.Persist.Migration.Utils.Sql
( commas
, uncommas
, quote
, interpolate
) where
import Data.Monoid ((<>))
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Data.Text.Encoding as Text
import Database.Persist (PersistValue(..))
commas :: Text -> [Text]
commas t = go (Text.unpack t) "" [] (0 :: Int)
where
go src buffer result level =
let result' = result ++ [Text.pack buffer]
in case src of
"" -> result'
',':xs | level == 0 -> go xs "" result' level
'(':xs -> go xs (buffer ++ "(") result (level + 1)
')':xs -> go xs (buffer ++ ")") result (max 0 $ level - 1)
x:xs -> go xs (buffer ++ [x]) result level
uncommas :: [Text] -> Text
uncommas = Text.intercalate ","
quote :: Text -> Text
quote t = "\"" <> t <> "\""
interpolate :: Text -> [PersistValue] -> Text
interpolate t values = if length splitted == length values + 1
then Text.concat . interleave splitted . map showValue $ values
else error $ "Number of ?'s does not match number of values: " ++ show t
where
splitted = Text.splitOn "?" t
interleave (x:xs) (y:ys) = x : y : interleave xs ys
interleave xs [] = xs
interleave [] ys = ys
showValue = \case
PersistText v -> "'" <> v <> "'"
PersistByteString v -> "'" <> Text.decodeUtf8 v <> "'"
PersistInt64 v -> Text.pack . show $ v
PersistDouble v -> Text.pack . show $ v
PersistRational v -> Text.pack . show $ v
PersistBool v -> Text.pack . show $ v
PersistNull -> "NULL"
v -> error $ "Could not interpolate value: " ++ show v