Skip to content

Instantly share code, notes, and snippets.

@dminuoso

dminuoso/ex.hs Secret

Last active December 8, 2022 15:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dminuoso/2f30d91630cb5dbf168765ce3bac8a74 to your computer and use it in GitHub Desktop.
Save dminuoso/2f30d91630cb5dbf168765ce3bac8a74 to your computer and use it in GitHub Desktop.
f con = query con qry (getActions clause)
where
qry = [sql| SELECT ...
...
...
|] <> getWhere clause
clause = And [ "state" `isIn` [Locked, Unlocked]
, Or [ "age" `eq` someAge
, isNull "foo"
]
, "name" `like` "Joe%"
]
data Cond = And (NonEmpty Cond)
| Or (NonEmpty Cond)
| CondEq Query Action
| CondNeq Query Action
| CondArg Query Action
| CondLike Query Action
| CondIsIn Query [Action]
| CondIsNull Query
type Traversal' s a = forall f. (Applicative f) => (a -> f a) -> s -> f s
actionVL :: Traversal' Cond Action
actionVL f (CondEq qry act) = CondEq qry <$> f act
actionVL f (CondNeq qry act) = CondNeq qry <$> f act
actionVL f (CondLike qry act) = CondLike qry <$> f act
actionVL f (CondArg qry act) = CondArg qry <$> f act
actionVL f (CondIsIn qry acts) = CondIsIn qry <$> traverse f acts
actionVL _ (CondIsNull qry) = pure (CondIsNull qry)
actionVL f (And conds) = And <$> traverse (actionVL f) conds
actionVL f (Or conds) = Or <$> traverse (actionVL f) conds
queryVL :: Traversal' Cond Query
queryVL f (CondEq qry act) = (`CondEq` act) <$> f qry
queryVL f (CondNeq qry act) = (`CondNeq` act) <$> f qry
queryVL f (CondLike qry act) = (`CondLike` act) <$> f qry
queryVL f (CondArg qry act) = (`CondArg` act) <$> f qry
queryVL f (CondIsIn qry acts) = (`CondIsIn` acts) <$> f qry
queryVL f (CondIsNull qry) = CondIsNull <$> f qry
queryVL f (And conds) = And <$> traverse (queryVL f) conds
queryVL f (Or conds) = Or <$> traverse (queryVL f) conds
toListOf :: Traversal' s a -> s -> [a]
toListOf t s = getConst (t (Const . singleton) s)
singleton :: a -> [a]
singleton = pure
getActions :: Cond -> [Action]
getActions = toListOf actionVL
intercalateM :: Monoid m => m -> NonEmpty m -> m
intercalateM e = fold . NE.intersperse e
getWhere :: Cond -> Query
getWhere c | length (toListOf queryVL c) == 0
= mempty
| otherwise = " WHERE " <> go c
where
go :: Cond -> Query
go (And conds) = parens (intercalateM " AND " (go <$> conds))
go (Or conds) = parens (intercalateM " OR " (go <$> conds))
go (CondEq qry _) = qry <> " = ?"
go (CondNeq qry _) = qry <> " <> ?"
go (CondArg qry _) = qry <> " ?"
go (CondLike qry _) = qry <> " LIKE ?"
go (CondIsNull qry) = qry <> " IS NULL"
isIn :: ToField a => Query -> [a] -> Cond
q `isIn` fs = CondIsIn q (toField <$> fs)
eq :: ToField a => Query -> a -> Cond
q `eq` f = CondEq q (toField f)
neq :: ToField a => Query -> a -> Cond
q `neq` f = CondNeq q (toField f)
like :: ToField a => Query -> a -> Cond
q `like` f = CondLike q (toField f)
arg :: ToField a => Query -> a -> Cond
q `arg` f = CondArg q (toField f)
isNull :: Query -> Cond
isNull = CondIsNull
pair :: ToField a => Query -> a -> (Query, Action)
pair q s = (q, toField s)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment