+1
-1
@@ -1,5 +1,5 @@
|
||||
name: dbapi
|
||||
version: 0.2.0.0
|
||||
version: 0.2.1.0
|
||||
synopsis: The database is your api
|
||||
license: MIT
|
||||
license-file: LICENSE
|
||||
|
||||
+38
-2
@@ -19,8 +19,9 @@ module PgQuery (
|
||||
import Data.Text (Text)
|
||||
import Data.String.Conversions (cs)
|
||||
import Data.Functor ( (<$>) )
|
||||
import Data.Maybe (fromMaybe)
|
||||
import Data.Maybe (fromMaybe, mapMaybe)
|
||||
import Data.List (intersperse, intercalate)
|
||||
import Data.List.Split (splitOn)
|
||||
import Data.Monoid ((<>), mconcat)
|
||||
import qualified Data.Map as M
|
||||
|
||||
@@ -65,6 +66,7 @@ getRows schema table qq range conn = do
|
||||
jsonArrayRows
|
||||
(selectStarClause schema table
|
||||
<> whereClause qq
|
||||
<> orderClause qq
|
||||
<> limitClause range)
|
||||
r <- quickQuery conn query []
|
||||
|
||||
@@ -78,12 +80,46 @@ getRows schema table qq range conn = do
|
||||
where
|
||||
offset = fromMaybe 0 $ R.offset <$> range
|
||||
|
||||
|
||||
whereClause :: Net.Query -> QuotedSql
|
||||
whereClause qs =
|
||||
if null qs then ("", []) else (" where ", []) <> conjunction
|
||||
|
||||
where
|
||||
conjunction = mconcat $ intersperse (" and ", []) (map wherePred qs)
|
||||
cols = [ col | col <- qs, fst col `notElem` ["order"] ]
|
||||
conjunction = mconcat $ intersperse (" and ", []) (map wherePred cols)
|
||||
|
||||
|
||||
orderClause :: Net.Query -> QuotedSql
|
||||
orderClause qs = do
|
||||
let order = fromMaybe "" $ join $ lookup "order" qs
|
||||
terms = mapMaybe parseOrderTerm $ splitOn "," $ cs order
|
||||
termPred = mconcat $ intersperse (", ", []) (map orderTermSql terms)
|
||||
|
||||
if null terms
|
||||
then ("", [])
|
||||
else (" order by ", []) <> termPred
|
||||
|
||||
where
|
||||
parseOrderTerm :: String -> Maybe OrderTerm
|
||||
parseOrderTerm s =
|
||||
case splitOn "." s of
|
||||
[d,c] ->
|
||||
if d `elem` ["asc", "desc"]
|
||||
then Just $ OrderTerm d c
|
||||
else Nothing
|
||||
_ -> Nothing
|
||||
|
||||
orderTermSql :: OrderTerm -> QuotedSql
|
||||
orderTermSql t =
|
||||
("%I " <> otDirection t, [toSql $ otColumn t])
|
||||
|
||||
|
||||
data OrderTerm = OrderTerm {
|
||||
otDirection :: String
|
||||
, otColumn :: String
|
||||
}
|
||||
|
||||
|
||||
wherePred :: Net.QueryItem -> QuotedSql
|
||||
wherePred (column, predicate) =
|
||||
|
||||
@@ -20,6 +20,22 @@ spec = around appWithFixture $ do
|
||||
, matchHeaders = ["Content-Range" <:> "0-0/1"]
|
||||
}
|
||||
|
||||
describe "ordering response" $ do
|
||||
it "by a column asc" $
|
||||
get "/items?id=lte.2&order=asc.id"
|
||||
`shouldRespondWith` ResponseMatcher {
|
||||
matchBody = Just "[{\"id\":1},{\"id\":2}]"
|
||||
, matchStatus = 200
|
||||
, matchHeaders = ["Content-Range" <:> "0-1/2"]
|
||||
}
|
||||
it "by a column desc" $
|
||||
get "/items?id=lte.2&order=desc.id"
|
||||
`shouldRespondWith` ResponseMatcher {
|
||||
matchBody = Just "[{\"id\":2},{\"id\":1}]"
|
||||
, matchStatus = 200
|
||||
, matchHeaders = ["Content-Range" <:> "0-1/2"]
|
||||
}
|
||||
|
||||
describe "Canonical location" $
|
||||
it "Sets Content-Location with alphabetized params" $
|
||||
get "/no_pk?b=eq.1&a=eq.1"
|
||||
|
||||
Reference in New Issue
Block a user