{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module Database.Esqueleto.Internal.ExprParser where
import Prelude hiding (takeWhile)
import Control.Applicative ((<|>))
import Control.Monad (void)
import Data.Attoparsec.Text
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Text (Text)
import qualified Data.Text as Text
import Database.Persist.Sql
import Database.Persist.SqlBackend
data TableAccess = TableAccess
{ TableAccess -> Text
tableAccessTable :: Text
, TableAccess -> Text
tableAccessColumn :: Text
}
deriving (TableAccess -> TableAccess -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TableAccess -> TableAccess -> Bool
$c/= :: TableAccess -> TableAccess -> Bool
== :: TableAccess -> TableAccess -> Bool
$c== :: TableAccess -> TableAccess -> Bool
Eq, Eq TableAccess
TableAccess -> TableAccess -> Bool
TableAccess -> TableAccess -> Ordering
TableAccess -> TableAccess -> TableAccess
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: TableAccess -> TableAccess -> TableAccess
$cmin :: TableAccess -> TableAccess -> TableAccess
max :: TableAccess -> TableAccess -> TableAccess
$cmax :: TableAccess -> TableAccess -> TableAccess
>= :: TableAccess -> TableAccess -> Bool
$c>= :: TableAccess -> TableAccess -> Bool
> :: TableAccess -> TableAccess -> Bool
$c> :: TableAccess -> TableAccess -> Bool
<= :: TableAccess -> TableAccess -> Bool
$c<= :: TableAccess -> TableAccess -> Bool
< :: TableAccess -> TableAccess -> Bool
$c< :: TableAccess -> TableAccess -> Bool
compare :: TableAccess -> TableAccess -> Ordering
$ccompare :: TableAccess -> TableAccess -> Ordering
Ord, Int -> TableAccess -> ShowS
[TableAccess] -> ShowS
TableAccess -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TableAccess] -> ShowS
$cshowList :: [TableAccess] -> ShowS
show :: TableAccess -> String
$cshow :: TableAccess -> String
showsPrec :: Int -> TableAccess -> ShowS
$cshowsPrec :: Int -> TableAccess -> ShowS
Show)
parseOnExpr :: SqlBackend -> Text -> Either String (Set TableAccess)
parseOnExpr :: SqlBackend -> Text -> Either String (Set TableAccess)
parseOnExpr SqlBackend
sqlBackend Text
text = do
Char
c <- SqlBackend -> Either String Char
mkEscapeChar SqlBackend
sqlBackend
forall a. Parser a -> Text -> Either String a
parseOnly (ExprParser (Set TableAccess)
onExpr Char
c) Text
text
mkEscapeChar :: SqlBackend -> Either String Char
mkEscapeChar :: SqlBackend -> Either String Char
mkEscapeChar SqlBackend
sqlBackend =
case Text -> Maybe (Char, Text)
Text.uncons (forall backend (m :: * -> *).
(BackendCompatible SqlBackend backend, MonadReader backend m) =>
Text -> m Text
getEscapedRawName Text
"" SqlBackend
sqlBackend) of
Maybe (Char, Text)
Nothing ->
forall a b. a -> Either a b
Left String
"Failed to get an escape character from the SQL backend."
Just (Char
c, Text
_) ->
forall a b. b -> Either a b
Right Char
c
type ExprParser a = Char -> Parser a
onExpr :: ExprParser (Set TableAccess)
onExpr :: ExprParser (Set TableAccess)
onExpr Char
e = forall a. Ord a => [a] -> Set a
Set.fromList forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' Parser Text TableAccess
tableAccesses
where
tableAccesses :: Parser Text TableAccess
tableAccesses = do
ExprParser ()
skipToEscape Char
e forall i a. Parser i a -> String -> Parser i a
<?> String
"Skipping to an escape char"
ExprParser TableAccess
parseTableAccess Char
e forall i a. Parser i a -> String -> Parser i a
<?> String
"Parsing a table access"
skipToEscape :: ExprParser ()
skipToEscape :: ExprParser ()
skipToEscape Char
escapeChar = forall (f :: * -> *) a. Functor f => f a -> f ()
void ((Char -> Bool) -> Parser Text
takeWhile (forall a. Eq a => a -> a -> Bool
/= Char
escapeChar))
parseEscapedIdentifier :: ExprParser [Char]
parseEscapedIdentifier :: ExprParser String
parseEscapedIdentifier Char
escapeChar = do
Char
_ <- Char -> Parser Char
char Char
escapeChar
String
str <- ExprParser String
parseEscapedChars Char
escapeChar
Char
_ <- Char -> Parser Char
char Char
escapeChar
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
str
parseTableAccess :: ExprParser TableAccess
parseTableAccess :: ExprParser TableAccess
parseTableAccess Char
ec = do
Text
tableAccessTable <- String -> Text
Text.pack forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ExprParser String
parseEscapedIdentifier Char
ec
Char
_ <- Char -> Parser Char
char Char
'.'
Text
tableAccessColumn <- String -> Text
Text.pack forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ExprParser String
parseEscapedIdentifier Char
ec
forall (f :: * -> *) a. Applicative f => a -> f a
pure TableAccess {Text
tableAccessColumn :: Text
tableAccessTable :: Text
tableAccessColumn :: Text
tableAccessTable :: Text
..}
parseEscapedChars :: ExprParser [Char]
parseEscapedChars :: ExprParser String
parseEscapedChars Char
escapeChar = Parser String
go
where
twoEscapes :: Parser Char
twoEscapes = Char -> Parser Char
char Char
escapeChar forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Char -> Parser Char
char Char
escapeChar
go :: Parser String
go = forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' (Char -> Parser Char
notChar Char
escapeChar forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Char
twoEscapes)