Compare commits

..
34 Commits
Author SHA1 Message Date
Joe Nelson 02228b76cc Bump version 2015-04-17 16:26:27 -07:00
Joe Nelson 4d7cc3d67e Merge branch 'bulk-insert' 2015-04-17 15:55:42 -07:00
Joe Nelson ad8700e996 bulk insert in changelog 2015-04-17 15:52:57 -07:00
Joe Nelson fbc90bdb84 Tests for csv bulk import
Fixes #17
2015-04-17 15:42:58 -07:00
Joe Nelson f4c49f03f4 Allow NULL in csv field and unquote the multipart headers 2015-04-16 12:43:22 -07:00
Joe Nelson a87f13f9bb Fix original tests 2015-04-16 10:45:24 -07:00
Joe Nelson 7d03a71fed All tests but one are passing 2015-04-12 19:56:33 -07:00
Joe Nelson 70d33445db WIP: nice but doomed approach to making multipart response 2015-04-12 13:03:16 -07:00
Joe Nelson 4dbcf45555 WIP: typechecking but not yet sending back links
Rather amazing how well this actually works given
it only type checked
2015-04-11 21:41:32 -07:00
Joe Nelson 87acee924e WIP: parsing csv 2015-04-05 17:13:16 -07:00
Joe Nelson a22cf82688 Build sql for inserting multiple rows 2015-04-04 20:20:13 -07:00
Joe Nelson 532cfdff95 Merge pull request #183 from begriffs/jsonb
Filter results using properties in a jsonb column
2015-04-04 18:35:40 -07:00
Joe Nelson 5807b41997 Add jsonb to changelog 2015-04-04 18:33:08 -07:00
Joe Nelson c78d323989 Specify hasql versions exactly to help ci 2015-04-04 17:43:14 -07:00
Joe Nelson 9792b9b46a Allow filtering by values inside json columns 2015-04-04 17:38:54 -07:00
Joe Nelson ca1c524ede WIP: working on querying and ordering with jsonb paths
Affects #118
2015-03-30 00:51:52 -07:00
Joe Nelson a1822a8e08 Update whitespace 2015-03-29 12:32:14 -07:00
Joe Nelson 066cdbc697 Merge pull request #176 from brikou/patch-2
Add link to GUI demo
2015-03-23 18:35:02 -07:00
Brikou CARRE b9c3902bd8 Add link to GUI demo
You can read more about using ng-admin with postgREST here http://marmelab.com/blog/2015/03/23/using-ng-admin-with-postgrest.html
2015-03-23 15:54:34 +01:00
Joe Nelson 03613e2f8e Add link to tutorial
Thanks @prio
2015-03-22 20:27:54 -07:00
Joe Nelson de7eecb166 Document fix from pull request 2015-03-16 21:11:57 -07:00
Joe Nelson 417d98d7fa Merge pull request #172 from GaloisInc/master
Show long help output with defaults on usage errors
2015-03-16 21:09:57 -07:00
Jonathan Daugherty 6dfbe854a0 Make postgrest show long help output with defaults on usage errors
This makes optparse-applicative show the long version of help output.
Its default behavior is not to do this since the showHelpOnError
setting defaults to False.  This turns it on.
2015-03-16 13:27:22 -07:00
Joe Nelson a9bc119b82 Merge branch 'insert-nulls'
Fixes #166
2015-03-15 18:30:47 -07:00
Joe Nelson 42d3d0de6c Fix location header for inserted objects with nulls 2015-03-15 18:26:32 -07:00
Joe Nelson ddb5ba8b64 Can now post nulls, but header link is wrong
affects #166
2015-03-15 16:30:42 -07:00
Joe Nelson 185d5b1c62 Merge branch 'jcristovao-isnull' 2015-03-15 15:22:28 -07:00
Joe Nelson f7ff08edf7 Test is.null matcher 2015-03-15 15:20:31 -07:00
João CristóvãoandJoe Nelson f4e0c12cba IS/IS NOT null, true, false 2015-03-15 13:37:45 -07:00
Joe Nelson 8ed599a769 Merge branch 'jcristovao-nullsFirst' 2015-03-15 12:30:34 -07:00
Joe Nelson aeb62e75bd Add nullsfirst to changelog 2015-03-15 12:30:17 -07:00
Joe Nelson 5c7ee1effc Fix problems caused by my rebase 2015-03-15 12:24:30 -07:00
João CristóvãoandJoe Nelson 01c67ab793 Added tests for nullsfirst / nullslast 2015-03-15 11:37:06 -07:00
João CristóvãoandJoe Nelson 97c9bfe93f Added support for nulls first / nulls last 2015-03-15 10:28:21 -07:00
12 changed files with 356 additions and 446 deletions
+11
View File
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [0.2.8.0] - 2015-04-17
### Added
- Option to specify nulls first or last, eg `/people?order=age.desc.nullsfirst`
- Filter nulls, `?col=is.null` and `?col=isnot.null`
- Filter within jsonb, `?col->a->>b=eq.c`
- Accept CSV in post body for bulk inserts
### Fixed
- Allow NULL values in posts
- Show full command line usage on param errors
## [0.2.7.0] - 2015-03-03
### Added
- Server response logging
+4 -2
View File
@@ -9,7 +9,7 @@ PostgREST serves a fully RESTful API from any existing PostgreSQL
database. It provides a cleaner, more standards-compliant, faster
API than you are likely to write from scratch.
### Demo [postgrest.herokuapp.com](https://postgrest.herokuapp.com) | Watch [Video](http://begriffs.com/posts/2014-12-30-intro-to-postgrest.html)
### Demo [postgrest.herokuapp.com](https://postgrest.herokuapp.com) | Watch [Video](http://begriffs.com/posts/2014-12-30-intro-to-postgrest.html) | [GUI Demo](http://marmelab.com/ng-admin-postgrest)
Try making requests to the live demo server with an HTTP client
such as [postman](http://www.getpostman.com/). The structure of the
@@ -20,7 +20,7 @@ your own projects.
### Usage
Download the binary ([OS X](http://bin.begriffs.com/dbapi/osx/postgrest-0.2.7.0.tar.xz) / [Linux](http://bin.begriffs.com/dbapi/heroku/postgrest-0.2.7.0.tar.xz)) and invoke like so:
Download the binary ([OS X](http://bin.begriffs.com/dbapi/osx/postgrest-0.2.8.0.tar.xz) / [Linux](http://bin.begriffs.com/dbapi/heroku/postgrest-0.2.8.0.tar.xz)) and invoke like so:
```bash
postgrest --db-host localhost --db-port 5432 \
@@ -153,6 +153,7 @@ and the [guide to routing](https://github.com/begriffs/postgrest/wiki/Routing).
* [Versioning](https://github.com/begriffs/postgrest/wiki/API-Versioning)
* [Performance](https://github.com/begriffs/postgrest/wiki/Performance-and-Scaling)
* [Security](https://github.com/begriffs/postgrest/wiki/Security-and-Permissions)
* [Tutorial](http://blog.jonharrington.org/postgrest-introduction/) (external)
### Thanks
@@ -162,3 +163,4 @@ and the [guide to routing](https://github.com/begriffs/postgrest/wiki/Routing).
wonderful [Hasql](https://github.com/nikita-volkov/hasql) library
and helping me use it
* [Mikey Casalaina](https://github.com/casalaina) for the cool logo
* [Jonathan Harrington](https://github.com/prio) for writing a nice tutorial
+1 -1
View File
@@ -10,7 +10,7 @@
},
"POSTGREST_VER": {
"description": "Version of PostgREST to deploy",
"value": "0.2.7.0"
"value": "0.2.8.0"
},
"DB_NAME": {
"description": "Database name",
+8 -5
View File
@@ -2,7 +2,7 @@ name: postgrest
description: Reads the schema of a PostgreSQL database and creates RESTful routes
for the tables and views, supporting all HTTP verbs that security
permits.
version: 0.2.7.0
version: 0.2.8.0
synopsis: REST API for any Postgres database
license: MIT
license-file: LICENSE
@@ -19,8 +19,8 @@ executable postgrest
default-language: Haskell2010
default-extensions: OverloadedStrings, ScopedTypeVariables, QuasiQuotes
build-depends: base >=4.6 && <5
, hasql == 0.7.*, hasql-backend
, hasql-postgres == 0.10.*
, hasql == 0.7.3, hasql-backend == 0.4.1
, hasql-postgres == 0.10.3
, warp >= 3.0.2, wai >= 3.0.1
, wai-extra, wai-cors
, wai-middleware-static >= 0.6.0
@@ -42,6 +42,7 @@ executable postgrest
, blaze-builder
, vector
, mtl
, cassava
Other-Modules: App
, Auth
, Config
@@ -73,8 +74,8 @@ Test-Suite spec
, SpecHelper
Build-Depends: base, hspec >= 2.1.2, QuickCheck
, hspec-wai >= 0.5.0, hspec-wai-json
, hasql, hasql-backend
, hasql-postgres
, hasql == 0.7.3, hasql-backend == 0.4.1
, hasql-postgres == 0.10.3
, warp, wai
, packdeps, hlint
, HTTP, convertible
@@ -98,4 +99,6 @@ Test-Suite spec
, blaze-builder
, vector
, mtl
, cassava
, process
, heredoc
+64 -26
View File
@@ -2,26 +2,30 @@
module App (app, sqlError, isSqlError) where
import Control.Monad (join)
import Control.Arrow ((***))
import Control.Arrow ((***), second)
import Control.Applicative
import Data.Text hiding (map)
import Data.Maybe (fromMaybe)
import Data.Maybe (fromMaybe, mapMaybe)
import Text.Regex.TDFA ((=~))
import Data.Ord (comparing)
import Data.Ranged.Ranges (emptyRange)
import Data.HashMap.Strict (keys, elems, filterWithKey, toList)
import qualified Data.HashMap.Strict as M
import Data.String.Conversions (cs)
import Data.CaseInsensitive (original)
import Data.List (sortBy)
import Data.Functor.Identity
import qualified Data.Set as S
import qualified Data.ByteString.Lazy as BL
import qualified Blaze.ByteString.Builder as BB
import qualified Data.Csv as CSV
import Network.HTTP.Types.Status
import Network.HTTP.Types.Header
import Network.HTTP.Types.URI (parseSimpleQuery)
import Network.HTTP.Base (urlEncodeVars)
import Network.Wai
import Network.Wai.Internal (Response(..))
import Data.Aeson
import Data.Monoid
@@ -98,26 +102,40 @@ app v1schema reqBody req =
, (hLocation, "/postgrest/users?id=eq." <> cs (userId u))
] ""
([table], "POST") ->
handleJsonObj reqBody $ \obj -> do
let qt = QualifiedTable schema (cs table)
query = insertInto qt (map cs $ keys obj) (elems obj)
echoRequested = lookup "Prefer" hdrs == Just "return=representation"
row <- H.maybeEx query
let (Identity insertedJson) = fromMaybe (Identity "{}" :: Identity Text) row
Just inserted = decode (cs insertedJson) :: Maybe Object
primaryKeys <- map cs <$> primaryKeyColumns qt
let primaries = if Prelude.null primaryKeys
then inserted
else filterWithKey (const . (`elem` primaryKeys)) inserted
let params = urlEncodeVars
$ map (\t -> (cs $ fst t, "eq." <> cs (unquoted $ snd t)))
$ sortBy (comparing fst) $ toList primaries
return $ responseLBS status201
[ jsonH
, (hLocation, "/" <> cs table <> "?" <> cs params)
] $ if echoRequested then cs insertedJson else ""
([table], "POST") -> do
let qt = QualifiedTable schema (cs table)
echoRequested = lookup "Prefer" hdrs == Just "return=representation"
parsed :: Either String (V.Vector Text, V.Vector (V.Vector Value))
parsed = if lookup "Content-Type" hdrs == Just "text/csv"
then do
rows <- CSV.decode CSV.NoHeader reqBody
if V.null rows then Left "CSV requires header"
else Right (V.head rows, (V.map $ V.map $ parseCsvCell . cs) (V.tail rows))
else eitherDecode reqBody >>= \val ->
case val of
Object obj -> Right . second V.singleton . V.unzip . V.fromList $
M.toList obj
_ -> Left "Expecting single JSON object or CSV rows"
case parsed of
Left err -> return $ responseLBS status400 [] $
encode . object $ [("message", String $ "Failed to parse JSON payload. " <> cs err)]
Right toBeInserted -> do
rows :: [Identity Text] <- H.listEx $ uncurry (insertInto qt) toBeInserted
let inserted :: [Object] = mapMaybe (decode . cs . runIdentity) rows
primaryKeys <- primaryKeyColumns qt
let responses = flip map inserted $ \obj -> do
let primaries =
if Prelude.null primaryKeys
then obj
else M.filterWithKey (const . (`elem` primaryKeys)) obj
let params = urlEncodeVars
$ map (\t -> (cs $ fst t, cs (paramFilter $ snd t)))
$ sortBy (comparing fst) $ M.toList primaries
responseLBS status201
[ jsonH
, (hLocation, "/" <> cs table <> "?" <> cs params)
] $ if echoRequested then encode obj else ""
return $ multipart status201 responses
([table], "PUT") ->
handleJsonObj reqBody $ \obj -> do
@@ -129,10 +147,10 @@ app v1schema reqBody req =
"You must speficy all and only primary keys as params"
else do
tableCols <- map (cs . colName) <$> columns qt
let cols = map cs $ keys obj
let cols = map cs $ M.keys obj
if S.fromList tableCols == S.fromList cols
then do
let vals = elems obj
let vals = M.elems obj
H.unitEx $ iffNotT
(whereT qq $ update qt cols vals)
(insertSelect qt cols vals)
@@ -148,7 +166,7 @@ app v1schema reqBody req =
let qt = QualifiedTable schema (cs table)
H.unitEx
$ whereT qq
$ update qt (map cs $ keys obj) (elems obj)
$ update qt (map cs $ M.keys obj) (M.elems obj)
return $ responseLBS status204 [ jsonH ] ""
([table], "DELETE") -> do
@@ -227,6 +245,26 @@ handleJsonObj reqBody handler = do
jErr = encode . object $
[("message", String "Expecting a JSON object")]
parseCsvCell :: BL.ByteString -> Value
parseCsvCell s = if s == "NULL" then Null else String $ cs s
multipart :: Status -> [Response] -> Response
multipart _ [] = responseLBS status204 [] ""
multipart _ [r] = r
multipart s rs =
responseLBS s [(hContentType, "multipart/mixed; boundary=\"postgrest_boundary\"")] $
BL.intercalate "\n--postgrest_boundary\n" (map renderResponseBody rs)
where
renderHeader :: Header -> BL.ByteString
renderHeader (k, v) = cs (original k) <> ": " <> cs v
renderResponseBody :: Response -> BL.ByteString
renderResponseBody (ResponseBuilder _ headers b) =
BL.intercalate "\n" (map renderHeader headers)
<> "\n\n" <> BB.toLazyByteString b
renderResponseBody _ = error
"Unable to create multipart response from non-ResponseBuilder"
data TableOptions = TableOptions {
tblOptcolumns :: [Column]
+2 -1
View File
@@ -32,7 +32,8 @@ main = do
<> prettyVersion
<> " / create a REST API to an existing Postgres database"
)
conf <- execParser opts
parserPrefs = prefs showHelpOnError
conf <- customExecParser parserPrefs opts
let port = configPort conf
unless (configSecure conf) $
+83 -21
View File
@@ -1,4 +1,4 @@
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, MultiWayIf #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module PgQuery where
@@ -22,6 +22,7 @@ import Control.Monad (join)
import Data.String.Conversions (cs)
import qualified Data.Aeson as JSON
import qualified Data.List as L
import qualified Data.Vector as V
import Data.Scientific (isInteger, formatScientific, FPFormat(..))
type PStmt = H.Stmt P.Postgres
@@ -39,6 +40,7 @@ data QualifiedTable = QualifiedTable {
data OrderTerm = OrderTerm {
otTerm :: T.Text
, otDirection :: BS.ByteString
, otNullOrder :: Maybe BS.ByteString
}
limitT :: Maybe NonnegRange -> StatementT
@@ -67,7 +69,8 @@ orderT ts q =
queryTerm :: OrderTerm -> PStmt
queryTerm t = B.Stmt
(" " <> cs (pgFmtIdent $ otTerm t) <> " "
<> cs (otDirection t) <> " ")
<> cs (otDirection t) <> " "
<> maybe "" cs (otNullOrder t) <> " ")
empty True
parentheticT :: StatementT
@@ -106,16 +109,24 @@ returningStarT s = s { B.stmtTemplate = B.stmtTemplate s <> " RETURNING *" }
deleteFrom :: QualifiedTable -> PStmt
deleteFrom t = B.Stmt ("delete from " <> fromQt t) empty True
insertInto :: QualifiedTable -> [T.Text] -> [JSON.Value] -> PStmt
insertInto t [] _ = B.Stmt
("insert into " <> fromQt t <> " default values returning *") empty True
insertInto t cols vals = B.Stmt
("insert into " <> fromQt t <> " (" <>
T.intercalate ", " (map pgFmtIdent cols) <>
") values ("
<> T.intercalate ", " (map ((<> "::unknown") . pgFmtLit . unquoted) vals)
<> ") returning row_to_json(" <> fromQt t <> ".*)")
empty True
insertInto :: QualifiedTable
-> V.Vector T.Text
-> V.Vector (V.Vector JSON.Value)
-> PStmt
insertInto t cols vals
| V.null cols = B.Stmt ("insert into " <> fromQt t <> " default values returning *") empty True
| otherwise = B.Stmt
("insert into " <> fromQt t <> " (" <>
T.intercalate ", " (V.toList $ V.map pgFmtIdent cols) <>
") values "
<> T.intercalate ", "
(V.toList $ V.map (\v -> "("
<> T.intercalate ", " (V.toList $ V.map insertableValue v)
<> ")"
) vals
)
<> " returning row_to_json(" <> fromQt t <> ".*)")
empty True
insertSelect :: QualifiedTable -> [T.Text] -> [JSON.Value] -> PStmt
insertSelect t [] _ = B.Stmt
@@ -124,7 +135,7 @@ insertSelect t cols vals = B.Stmt
("insert into " <> fromQt t <> " ("
<> T.intercalate ", " (map pgFmtIdent cols)
<> ") select "
<> T.intercalate ", " (map ((<> "::unknown") . pgFmtLit . unquoted) vals))
<> T.intercalate ", " (map insertableValue vals))
empty True
update :: QualifiedTable -> [T.Text] -> [JSON.Value] -> PStmt
@@ -132,19 +143,23 @@ update t cols vals = B.Stmt
("update " <> fromQt t <> " set ("
<> T.intercalate ", " (map pgFmtIdent cols)
<> ") = ("
<> T.intercalate ", " (map ((<> "::unknown") . pgFmtLit . unquoted) vals)
<> T.intercalate ", " (map insertableValue vals)
<> ")")
empty True
wherePred :: Net.QueryItem -> PStmt
wherePred (col, predicate) = B.Stmt
(" " <> cs (pgFmtIdent $ cs col) <> " " <> op <> " " <> cs sqlValue)
empty True
wherePred (col, predicate) =
B.Stmt (" " <> pgFmtJsonbPath (cs col) <> " " <> op <> " " <>
if opCode `elem` ["is","isnot"] then whiteList value
else cs sqlValue)
empty True
where
opCode:rest = T.split (=='.') $ cs $ fromMaybe "." predicate
value = T.intercalate "." rest
whiteList val = fromMaybe (cs (pgFmtLit val) <> "::unknown ")
(L.find ((==) . T.toLower $ val)
["null","true","false"])
star c = if c == '*' then '%' else c
unknownLiteral = (<> "::unknown ") . pgFmtLit
@@ -164,6 +179,8 @@ wherePred (col, predicate) = B.Stmt
"like"-> "like"
"ilike"-> "ilike"
"in" -> "in"
"is" -> "is"
"isnot" -> "is not"
_ -> "="
orderParse :: Net.Query -> [OrderTerm]
@@ -175,10 +192,16 @@ orderParse q =
orderParseTerm :: T.Text -> Maybe OrderTerm
orderParseTerm s =
case T.split (=='.') s of
[c,d] ->
(c:d:nls) ->
if d `elem` ["asc", "desc"]
then Just $ OrderTerm c $
if d == "asc" then "asc" else "desc"
then Just $ OrderTerm c
( if d == "asc" then "asc" else "desc" )
( case nls of
[n] -> if | n == "nullsfirst" -> Just "nulls first"
| n == "nullslast" -> Just "nulls last"
| otherwise -> Nothing
_ -> Nothing
)
else Nothing
_ -> Nothing
@@ -188,6 +211,34 @@ commaq = B.Stmt ", " empty True
andq :: PStmt
andq = B.Stmt " and " empty True
data JsonbPath =
ColIdentifier T.Text
| KeyIdentifier T.Text
| SingleArrow JsonbPath JsonbPath
| DoubleArrow JsonbPath JsonbPath
deriving (Show)
parseJsonbPath :: T.Text -> Maybe JsonbPath
parseJsonbPath p =
case T.splitOn "->>" p of
[a,b] ->
let i:is = T.splitOn "->" a in
Just $ DoubleArrow
(foldl SingleArrow (ColIdentifier i) (map KeyIdentifier is))
(KeyIdentifier b)
_ -> Nothing
pgFmtJsonbPath :: T.Text -> T.Text
pgFmtJsonbPath p =
pgFmtJsonbPath' $ fromMaybe (ColIdentifier p) (parseJsonbPath p)
where
pgFmtJsonbPath' (ColIdentifier i) = pgFmtIdent i
pgFmtJsonbPath' (KeyIdentifier i) = pgFmtLit i
pgFmtJsonbPath' (SingleArrow a b) =
pgFmtJsonbPath' a <> "->" <> pgFmtJsonbPath' b
pgFmtJsonbPath' (DoubleArrow a b) =
pgFmtJsonbPath' a <> "->>" <> pgFmtJsonbPath' b
pgFmtIdent :: T.Text -> T.Text
pgFmtIdent x =
let escaped = T.replace "\"" "\"\"" (trimNullChars $ cs x) in
@@ -218,3 +269,14 @@ unquoted (JSON.Number n) =
cs $ formatScientific Fixed (if isInteger n then Just 0 else Nothing) n
unquoted (JSON.Bool b) = cs . show $ b
unquoted _ = ""
insertableText :: T.Text -> T.Text
insertableText = (<> "::unknown") . pgFmtLit
insertableValue :: JSON.Value -> T.Text
insertableValue JSON.Null = "null"
insertableValue v = insertableText $ unquoted v
paramFilter :: JSON.Value -> T.Text
paramFilter JSON.Null = "is.null"
paramFilter v = "eq." <> unquoted v
+54
View File
@@ -9,6 +9,7 @@ import SpecHelper
import qualified Data.Aeson as JSON
import Data.Maybe (fromJust)
import Text.Heredoc
import Network.HTTP.Types.Header
import Network.HTTP.Types
import Control.Monad (replicateM_)
@@ -66,6 +67,15 @@ spec = afterAll_ resetDb $ around withApp $ do
simpleHeaders p `shouldSatisfy` matchHeader hLocation "/no_pk\\?a=eq.bar&b=eq.baz"
simpleStatus p `shouldBe` created201
it "can post nulls" $ do
p <- request methodPost "/no_pk"
[("Prefer", "return=representation")]
[json| { "a":null, "b":"foo" } |]
liftIO $ do
simpleBody p `shouldBe` [json| { "a":null, "b":"foo" } |]
simpleHeaders p `shouldSatisfy` matchHeader hLocation "/no_pk\\?a=is.null&b=eq.foo"
simpleStatus p `shouldBe` created201
context "with compound pk supplied" . after_ (clearTable "compound_pk") $
it "builds response location header appropriately" $
post "/compound_pk" [json| { "k1":12, "k2":42 } |]
@@ -84,6 +94,50 @@ spec = afterAll_ resetDb $ around withApp $ do
, matchHeaders = []
}
describe "CSV insert" $ do
after_ (clearTable "menagerie") . context "disparate csv types" $
it "succeeds with multipart response" $ do
p <- request methodPost "/menagerie" [("Content-Type", "text/csv")]
[str|integer,double,varchar,boolean,date,money,enum
|13,3.14159,testing!,false,1900-01-01,$3.99,foo
|12,0.1,a string,true,1929-10-01,12,bar
|]
liftIO $ do
simpleBody p `shouldBe` "Content-Type: application/json\nLocation: /menagerie?integer=eq.13\n\n\n--postgrest_boundary\nContent-Type: application/json\nLocation: /menagerie?integer=eq.12\n\n"
simpleStatus p `shouldBe` created201
after_ (clearTable "no_pk") . context "requesting full representation" $ do
it "returns full details of inserted record" $
request methodPost "/no_pk"
[("Content-Type", "text/csv"), ("Prefer", "return=representation")]
"a,b\nbar,baz"
`shouldRespondWith` ResponseMatcher {
matchBody = Just [json| { "a":"bar", "b":"baz" } |]
, matchStatus = 201
, matchHeaders = ["Content-Type" <:> "application/json",
"Location" <:> "/no_pk?a=eq.bar&b=eq.baz"]
}
it "can post nulls" $
request methodPost "/no_pk"
[("Content-Type", "text/csv"), ("Prefer", "return=representation")]
"a,b\nNULL,foo"
`shouldRespondWith` ResponseMatcher {
matchBody = Just [json| { "a":null, "b":"foo" } |]
, matchStatus = 201
, matchHeaders = ["Content-Type" <:> "application/json",
"Location" <:> "/no_pk?a=is.null&b=eq.foo"]
}
after_ (clearTable "no_pk") . context "with wrong number of columns" $ do
it "fails for too few" $ do
p <- request methodPost "/no_pk" [("Content-Type", "text/csv")] "a,b\nfoo,bar\nbaz"
liftIO $ simpleStatus p `shouldBe` badRequest400
it "fails for too many" $ do
p <- request methodPost "/no_pk" [("Content-Type", "text/csv")] "a,b\nfoo,bar\nbaz,bat,bad"
liftIO $ simpleStatus p `shouldBe` badRequest400
describe "Putting record" $ do
context "to unkonwn uri" $
+67 -35
View File
@@ -3,28 +3,20 @@ module Feature.QuerySpec where
import Test.Hspec
import Test.Hspec.Wai
import Test.Hspec.Wai.JSON
import Hasql as H
import Hasql.Postgres as H
import Control.Monad (void)
import Data.Text(Text)
import Network.Wai.Test (SResponse(simpleHeaders))
import SpecHelper
testSet :: IO ()
testSet = do
clearTable "items" >> clearTable "no_pk"
createItems 15
pool <- H.acquirePool pgSettings testPoolOpts
void . liftIO $ H.session pool $ H.tx Nothing $ do
H.unitEx $ insertNoPk "xyyx" "u"
H.unitEx $ insertNoPk "xYYx" "v"
where
insertNoPk :: Text -> Text -> H.Stmt H.Postgres
insertNoPk = [H.stmt|insert into "1".no_pk (a, b) values (?,?)|]
spec :: Spec
spec = beforeAll testSet . afterAll_ (clearTable "items") . around withApp $ do
spec =
beforeAll (clearTable "items" >> createItems 15)
. beforeAll (
clearTable "no_pk" >>
createNulls 2 >>
createLikableStrings >>
createJsonData)
. afterAll_ (clearTable "items" >> clearTable "no_pk" >> clearTable "simple_pk")
. around withApp $ do
describe "Querying a nonexistent table" $
it "causes a 404" $
get "/faketable" `shouldRespondWith` 404
@@ -46,19 +38,23 @@ spec = beforeAll testSet . afterAll_ (clearTable "items") . around withApp $ do
, matchHeaders = ["Content-Range" <:> "0-2/3"]
}
it "matches nulls" $
get "/no_pk?a=is.null" `shouldRespondWith`
[json| [{"a": null, "b": null}] |]
it "matches with like" $ do
get "/no_pk?a=like.*yx" `shouldRespondWith` [json|
[{"a":"xyyx","b":"u"}]|]
get "/no_pk?a=like.xy*" `shouldRespondWith` [json|
[{"a":"xyyx","b":"u"}]|]
get "/no_pk?a=like.*YY*" `shouldRespondWith` [json|
[{"a":"xYYx","b":"v"}]|]
get "/simple_pk?k=like.*yx" `shouldRespondWith`
"[{\"k\":\"xyyx\",\"extra\":\"u\"}]"
get "/simple_pk?k=like.xy*" `shouldRespondWith`
"[{\"k\":\"xyyx\",\"extra\":\"u\"}]"
get "/simple_pk?k=like.*YY*" `shouldRespondWith`
"[{\"k\":\"xYYx\",\"extra\":\"v\"}]"
it "matches with ilike" $ do
get "/no_pk?a=ilike.xy*&order=b.asc" `shouldRespondWith` [json|
[{"a":"xyyx","b":"u"},{"a":"xYYx","b":"v"}]|]
get "/no_pk?a=ilike.*YY*&order=b.asc" `shouldRespondWith` [json|
[{"a":"xyyx","b":"u"},{"a":"xYYx","b":"v"}]|]
get "/simple_pk?k=ilike.xy*&order=extra.asc" `shouldRespondWith`
"[{\"k\":\"xyyx\",\"extra\":\"u\"},{\"k\":\"xYYx\",\"extra\":\"v\"}]"
get "/simple_pk?k=ilike.*YY*&order=extra.asc" `shouldRespondWith`
"[{\"k\":\"xyyx\",\"extra\":\"u\"},{\"k\":\"xYYx\",\"extra\":\"v\"}]"
describe "ordering response" $ do
it "by a column asc" $
@@ -76,6 +72,36 @@ spec = beforeAll testSet . afterAll_ (clearTable "items") . around withApp $ do
, matchHeaders = ["Content-Range" <:> "0-1/2"]
}
it "by a column asc with nulls last" $
get "/no_pk?order=a.asc.nullslast"
`shouldRespondWith` ResponseMatcher {
matchBody = Just [json| [{"a":"1","b":"0"},
{"a":"2","b":"0"},
{"a":null,"b":null}] |]
, matchStatus = 200
, matchHeaders = ["Content-Range" <:> "0-2/3"]
}
it "by a column desc with nulls first" $
get "/no_pk?order=a.desc.nullsfirst"
`shouldRespondWith` ResponseMatcher {
matchBody = Just [json| [{"a":null,"b":null},
{"a":"2","b":"0"},
{"a":"1","b":"0"}] |]
, matchStatus = 200
, matchHeaders = ["Content-Range" <:> "0-2/3"]
}
it "by a column desc with nulls last" $
get "/no_pk?order=a.desc.nullslast"
`shouldRespondWith` ResponseMatcher {
matchBody = Just [json| [{"a":"2","b":"0"},
{"a":"1","b":"0"},
{"a":null,"b":null}] |]
, matchStatus = 200
, matchHeaders = ["Content-Range" <:> "0-2/3"]
}
it "without other constraints" $
get "/items?order=asc.id" `shouldRespondWith` 200
@@ -88,10 +114,16 @@ spec = beforeAll testSet . afterAll_ (clearTable "items") . around withApp $ do
, matchHeaders = ["Content-Location" <:> "/no_pk?a=eq.1&b=eq.1"]
}
it "Omits question mark when there are no params" $
get "/simple_pk"
`shouldRespondWith` ResponseMatcher {
matchBody = Just "[]"
, matchStatus = 200
, matchHeaders = ["Content-Location" <:> "/simple_pk"]
}
it "Omits question mark when there are no params" $ do
r <- get "/simple_pk"
liftIO $ do
let respHeaders = simpleHeaders r
respHeaders `shouldSatisfy` matchHeader
"Content-Location" "/simple_pk"
describe "jsonb" $
it "can filter by properties inside json column" $ do
get "/json?data->foo->>bar=eq.baz" `shouldRespondWith`
[json| [{"data": {"foo": {"bar": "baz"}}}] |]
get "/json?data->foo->>bar=eq.fake" `shouldRespondWith`
[json| [] |]
+1
View File
@@ -18,6 +18,7 @@ spec = around withApp $ do
, {"schema":"1","name":"compound_pk","insertable":true}
, {"schema":"1","name":"has_fk","insertable":true}
, {"schema":"1","name":"items","insertable":true}
, {"schema":"1","name":"json","insertable":true}
, {"schema":"1","name":"menagerie","insertable":true}
, {"schema":"1","name":"no_pk","insertable":true}
, {"schema":"1","name":"simple_pk","insertable":true}
+42 -19
View File
@@ -5,8 +5,8 @@ import Test.Hspec
import Test.Hspec.Wai
import Hasql as H
import Hasql.Backend as H
import Hasql.Postgres as H
import Hasql.Backend as B
import Hasql.Postgres as P
import Data.String.Conversions (cs)
import Data.Monoid
@@ -24,11 +24,12 @@ import qualified Data.ByteString.Char8 as BS
import Network.Wai.Middleware.Cors (cors)
import System.Process (readProcess)
import qualified Data.Aeson.Types as J
import App (app)
import Config (AppConfig(..), corsPolicy)
import Middleware
import Error(errResponse)
-- import Auth (addUser)
isLeft :: Either a b -> Bool
isLeft (Left _ ) = True
@@ -40,8 +41,8 @@ cfg = AppConfig "postgrest_test" 5432 "postgrest_test" "" "localhost" 3000 "post
testPoolOpts :: PoolSettings
testPoolOpts = fromMaybe (error "bad settings") $ H.poolSettings 1 30
pgSettings :: H.Settings
pgSettings = H.ParamSettings (cs $ configDbHost cfg)
pgSettings :: P.Settings
pgSettings = P.ParamSettings (cs $ configDbHost cfg)
(fromIntegral $ configDbPort cfg)
(cs $ configDbUser cfg)
(cs $ configDbPass cfg)
@@ -51,7 +52,7 @@ withApp :: ActionWith Application -> IO ()
withApp perform = do
let anonRole = cs $ configAnonRole cfg
currRole = cs $ configDbUser cfg
pool :: H.Pool H.Postgres
pool :: H.Pool P.Postgres
<- H.acquirePool pgSettings testPoolOpts
perform $ middle $ \req resp -> do
@@ -65,7 +66,7 @@ withApp perform = do
resetDb :: IO ()
resetDb = do
pool :: H.Pool H.Postgres
pool :: H.Pool P.Postgres
<- H.acquirePool pgSettings testPoolOpts
void . liftIO $ H.session pool $
H.tx Nothing $ do
@@ -96,26 +97,48 @@ authHeader :: String -> String -> Header
authHeader u p =
(hAuthorization, cs $ "Basic " ++ encode (u ++ ":" ++ p))
testPool :: IO(H.Pool P.Postgres)
testPool = H.acquirePool pgSettings testPoolOpts
clearTable :: Text -> IO ()
clearTable table = do
pool :: H.Pool H.Postgres
<- H.acquirePool pgSettings testPoolOpts
pool <- testPool
void . liftIO $ H.session pool $ H.tx Nothing $
H.unitEx $ H.Stmt ("delete from \"1\"."<>table) V.empty True
H.unitEx $ B.Stmt ("delete from \"1\"."<>table) V.empty True
createItems :: Int -> IO ()
createItems n = do
pool :: H.Pool H.Postgres
<- H.acquirePool pgSettings testPoolOpts
pool <- testPool
void . liftIO $ H.session pool $ H.tx Nothing txn
where
txn = sequence_ $ map H.unitEx stmts
txn = mapM_ H.unitEx stmts
stmts = map [H.stmt|insert into "1".items (id) values (?)|] [1..n]
-- for hspec-wai
pending_ :: WaiSession ()
pending_ = liftIO Test.Hspec.pending
createNulls :: Int -> IO ()
createNulls n = do
pool <- testPool
void . liftIO $ H.session pool $ H.tx Nothing txn
where
txn = mapM_ H.unitEx (stmt':stmts)
stmt' = [H.stmt|insert into "1".no_pk (a,b) values (null,null)|]
stmts = map [H.stmt|insert into "1".no_pk (a,b) values (?,0)|] [1..n]
-- for hspec-wai
pendingWith_ :: String -> WaiSession ()
pendingWith_ = liftIO . Test.Hspec.pendingWith
createLikableStrings :: IO ()
createLikableStrings = do
pool <- testPool
void . liftIO $ H.session pool $ H.tx Nothing $ do
H.unitEx $ insertSimplePk "xyyx" "u"
H.unitEx $ insertSimplePk "xYYx" "v"
where
insertSimplePk :: Text -> Text -> H.Stmt P.Postgres
insertSimplePk = [H.stmt|insert into "1".simple_pk (k, extra) values (?,?)|]
createJsonData :: IO ()
createJsonData = do
pool <- testPool
void . liftIO $ H.session pool $ H.tx Nothing $
H.unitEx $
[H.stmt|
insert into "1".json (data) values (?)
|]
(J.object [("foo", J.object [("bar", J.String "baz")])])
+19 -336
View File
@@ -1,70 +1,37 @@
--
-- PostgreSQL database dump
--
-- Dumped from database version 9.3.5
-- Dumped by pg_dump version 9.3.5
-- Started on 2014-10-21 15:12:44 PDT
SET statement_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SET check_function_bodies = false;
SET client_min_messages = warning;
--
-- TOC entry 20 (class 2615 OID 337536)
-- Name: 1; Type: SCHEMA; Schema: -; Owner: postgrest_test
--
CREATE SCHEMA "1";
ALTER SCHEMA "1" OWNER TO postgrest_test;
--
-- TOC entry 19 (class 2615 OID 337537)
-- Name: postgrest; Type: SCHEMA; Schema: -; Owner: postgrest_test
--
CREATE SCHEMA postgrest;
ALTER SCHEMA postgrest OWNER TO postgrest_test;
--
-- TOC entry 16 (class 2615 OID 337538)
-- Name: private; Type: SCHEMA; Schema: -; Owner: postgrest_test
--
CREATE SCHEMA private;
ALTER SCHEMA private OWNER TO postgrest_test;
--
-- TOC entry 205 (class 3079 OID 12018)
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner:
--
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
--
-- TOC entry 2321 (class 0 OID 0)
-- Dependencies: 205
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner:
--
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
SET search_path = "1", pg_catalog;
--
-- TOC entry 553 (class 1247 OID 337540)
-- Name: enum_menagerie_type; Type: TYPE; Schema: 1; Owner: postgrest_test
--
CREATE TYPE enum_menagerie_type AS ENUM (
'foo',
@@ -76,10 +43,6 @@ ALTER TYPE "1".enum_menagerie_type OWNER TO postgrest_test;
SET search_path = postgrest, pg_catalog;
--
-- TOC entry 218 (class 1255 OID 337545)
-- Name: check_role_exists(); Type: FUNCTION; Schema: postgrest; Owner: postgrest_test
--
CREATE FUNCTION check_role_exists() RETURNS trigger
LANGUAGE plpgsql
@@ -96,10 +59,6 @@ $$;
ALTER FUNCTION postgrest.check_role_exists() OWNER TO postgrest_test;
--
-- TOC entry 219 (class 1255 OID 337546)
-- Name: update_owner(); Type: FUNCTION; Schema: postgrest; Owner: postgrest_test
--
CREATE FUNCTION update_owner() RETURNS trigger
LANGUAGE plpgsql
@@ -119,10 +78,6 @@ SET default_tablespace = '';
SET default_with_oids = false;
--
-- TOC entry 191 (class 1259 OID 337547)
-- Name: authors_only; Type: TABLE; Schema: 1; Owner: postgrest_test_author; Tablespace:
--
CREATE TABLE authors_only (
secret character varying NOT NULL
@@ -131,10 +86,6 @@ CREATE TABLE authors_only (
ALTER TABLE "1".authors_only OWNER TO postgrest_test_author;
--
-- TOC entry 192 (class 1259 OID 337553)
-- Name: auto_incrementing_pk; Type: TABLE; Schema: 1; Owner: postgrest_test; Tablespace:
--
CREATE TABLE auto_incrementing_pk (
id integer NOT NULL,
@@ -146,10 +97,6 @@ CREATE TABLE auto_incrementing_pk (
ALTER TABLE "1".auto_incrementing_pk OWNER TO postgrest_test;
--
-- TOC entry 193 (class 1259 OID 337560)
-- Name: auto_incrementing_pk_id_seq; Type: SEQUENCE; Schema: 1; Owner: postgrest_test
--
CREATE SEQUENCE auto_incrementing_pk_id_seq
START WITH 1
@@ -161,19 +108,10 @@ CREATE SEQUENCE auto_incrementing_pk_id_seq
ALTER TABLE "1".auto_incrementing_pk_id_seq OWNER TO postgrest_test;
--
-- TOC entry 2324 (class 0 OID 0)
-- Dependencies: 193
-- Name: auto_incrementing_pk_id_seq; Type: SEQUENCE OWNED BY; Schema: 1; Owner: postgrest_test
--
ALTER SEQUENCE auto_incrementing_pk_id_seq OWNED BY auto_incrementing_pk.id;
--
-- TOC entry 194 (class 1259 OID 337562)
-- Name: compound_pk; Type: TABLE; Schema: 1; Owner: postgrest_test; Tablespace:
--
CREATE TABLE compound_pk (
k1 integer NOT NULL,
@@ -184,10 +122,6 @@ CREATE TABLE compound_pk (
ALTER TABLE "1".compound_pk OWNER TO postgrest_test;
--
-- TOC entry 195 (class 1259 OID 337565)
-- Name: has_fk; Type: TABLE; Schema: 1; Owner: postgrest_test; Tablespace:
--
CREATE TABLE has_fk (
id bigint NOT NULL,
@@ -198,10 +132,6 @@ CREATE TABLE has_fk (
ALTER TABLE "1".has_fk OWNER TO postgrest_test;
--
-- TOC entry 196 (class 1259 OID 337568)
-- Name: has_fk_id_seq; Type: SEQUENCE; Schema: 1; Owner: postgrest_test
--
CREATE SEQUENCE has_fk_id_seq
START WITH 1
@@ -213,19 +143,10 @@ CREATE SEQUENCE has_fk_id_seq
ALTER TABLE "1".has_fk_id_seq OWNER TO postgrest_test;
--
-- TOC entry 2327 (class 0 OID 0)
-- Dependencies: 196
-- Name: has_fk_id_seq; Type: SEQUENCE OWNED BY; Schema: 1; Owner: postgrest_test
--
ALTER SEQUENCE has_fk_id_seq OWNED BY has_fk.id;
--
-- TOC entry 197 (class 1259 OID 337570)
-- Name: items; Type: TABLE; Schema: 1; Owner: postgrest_test; Tablespace:
--
CREATE TABLE items (
id bigint NOT NULL
@@ -234,10 +155,6 @@ CREATE TABLE items (
ALTER TABLE "1".items OWNER TO postgrest_test;
--
-- TOC entry 198 (class 1259 OID 337573)
-- Name: items_id_seq; Type: SEQUENCE; Schema: 1; Owner: postgrest_test
--
CREATE SEQUENCE items_id_seq
START WITH 1
@@ -249,19 +166,10 @@ CREATE SEQUENCE items_id_seq
ALTER TABLE "1".items_id_seq OWNER TO postgrest_test;
--
-- TOC entry 2329 (class 0 OID 0)
-- Dependencies: 198
-- Name: items_id_seq; Type: SEQUENCE OWNED BY; Schema: 1; Owner: postgrest_test
--
ALTER SEQUENCE items_id_seq OWNED BY items.id;
--
-- TOC entry 199 (class 1259 OID 337575)
-- Name: menagerie; Type: TABLE; Schema: 1; Owner: postgrest_test; Tablespace:
--
CREATE TABLE menagerie (
"integer" integer NOT NULL,
@@ -276,10 +184,6 @@ CREATE TABLE menagerie (
ALTER TABLE "1".menagerie OWNER TO postgrest_test;
--
-- TOC entry 200 (class 1259 OID 337581)
-- Name: no_pk; Type: TABLE; Schema: 1; Owner: postgrest_test; Tablespace:
--
CREATE TABLE no_pk (
a character varying,
@@ -289,10 +193,6 @@ CREATE TABLE no_pk (
ALTER TABLE "1".no_pk OWNER TO postgrest_test;
--
-- TOC entry 201 (class 1259 OID 337587)
-- Name: simple_pk; Type: TABLE; Schema: 1; Owner: postgrest_test; Tablespace:
--
CREATE TABLE simple_pk (
k character varying NOT NULL,
@@ -302,12 +202,18 @@ CREATE TABLE simple_pk (
ALTER TABLE "1".simple_pk OWNER TO postgrest_test;
CREATE TABLE json
(
data json
);
ALTER TABLE "1".json OWNER TO postgrest_test;
SET search_path = postgrest, pg_catalog;
--
-- TOC entry 202 (class 1259 OID 337593)
-- Name: auth; Type: TABLE; Schema: postgrest; Owner: postgrest_test; Tablespace:
--
CREATE TABLE auth (
id character varying NOT NULL,
@@ -320,10 +226,6 @@ ALTER TABLE postgrest.auth OWNER TO postgrest_test;
SET search_path = private, pg_catalog;
--
-- TOC entry 203 (class 1259 OID 337599)
-- Name: articles; Type: TABLE; Schema: private; Owner: postgrest_test; Tablespace:
--
CREATE TABLE articles (
body text,
@@ -334,10 +236,6 @@ CREATE TABLE articles (
ALTER TABLE private.articles OWNER TO postgrest_test;
--
-- TOC entry 204 (class 1259 OID 337605)
-- Name: articles_id_seq; Type: SEQUENCE; Schema: private; Owner: postgrest_test
--
CREATE SEQUENCE articles_id_seq
START WITH 1
@@ -349,232 +247,113 @@ CREATE SEQUENCE articles_id_seq
ALTER TABLE private.articles_id_seq OWNER TO postgrest_test;
--
-- TOC entry 2336 (class 0 OID 0)
-- Dependencies: 204
-- Name: articles_id_seq; Type: SEQUENCE OWNED BY; Schema: private; Owner: postgrest_test
--
ALTER SEQUENCE articles_id_seq OWNED BY articles.id;
SET search_path = "1", pg_catalog;
--
-- TOC entry 2165 (class 2604 OID 337607)
-- Name: id; Type: DEFAULT; Schema: 1; Owner: postgrest_test
--
ALTER TABLE ONLY auto_incrementing_pk ALTER COLUMN id SET DEFAULT nextval('auto_incrementing_pk_id_seq'::regclass);
--
-- TOC entry 2166 (class 2604 OID 337608)
-- Name: id; Type: DEFAULT; Schema: 1; Owner: postgrest_test
--
ALTER TABLE ONLY has_fk ALTER COLUMN id SET DEFAULT nextval('has_fk_id_seq'::regclass);
--
-- TOC entry 2167 (class 2604 OID 337609)
-- Name: id; Type: DEFAULT; Schema: 1; Owner: postgrest_test
--
ALTER TABLE ONLY items ALTER COLUMN id SET DEFAULT nextval('items_id_seq'::regclass);
SET search_path = private, pg_catalog;
--
-- TOC entry 2168 (class 2604 OID 337610)
-- Name: id; Type: DEFAULT; Schema: private; Owner: postgrest_test
--
ALTER TABLE ONLY articles ALTER COLUMN id SET DEFAULT nextval('articles_id_seq'::regclass);
SET search_path = "1", pg_catalog;
--
-- TOC entry 2298 (class 0 OID 337547)
-- Dependencies: 191
-- Data for Name: authors_only; Type: TABLE DATA; Schema: 1; Owner: postgrest_test_author
--
--
-- TOC entry 2299 (class 0 OID 337553)
-- Dependencies: 192
-- Data for Name: auto_incrementing_pk; Type: TABLE DATA; Schema: 1; Owner: postgrest_test
--
--
-- TOC entry 2337 (class 0 OID 0)
-- Dependencies: 193
-- Name: auto_incrementing_pk_id_seq; Type: SEQUENCE SET; Schema: 1; Owner: postgrest_test
--
SELECT pg_catalog.setval('auto_incrementing_pk_id_seq', 54, true);
SELECT pg_catalog.setval('auto_incrementing_pk_id_seq', 1, true);
--
-- TOC entry 2301 (class 0 OID 337562)
-- Dependencies: 194
-- Data for Name: compound_pk; Type: TABLE DATA; Schema: 1; Owner: postgrest_test
--
--
-- TOC entry 2302 (class 0 OID 337565)
-- Dependencies: 195
-- Data for Name: has_fk; Type: TABLE DATA; Schema: 1; Owner: postgrest_test
--
--
-- TOC entry 2338 (class 0 OID 0)
-- Dependencies: 196
-- Name: has_fk_id_seq; Type: SEQUENCE SET; Schema: 1; Owner: postgrest_test
--
SELECT pg_catalog.setval('has_fk_id_seq', 1, false);
--
-- TOC entry 2304 (class 0 OID 337570)
-- Dependencies: 197
-- Data for Name: items; Type: TABLE DATA; Schema: 1; Owner: postgrest_test
--
INSERT INTO items (id) VALUES (1);
--
-- TOC entry 2339 (class 0 OID 0)
-- Dependencies: 198
-- Name: items_id_seq; Type: SEQUENCE SET; Schema: 1; Owner: postgrest_test
--
SELECT pg_catalog.setval('items_id_seq', 19, true);
SELECT pg_catalog.setval('items_id_seq', 1, true);
--
-- TOC entry 2306 (class 0 OID 337575)
-- Dependencies: 199
-- Data for Name: menagerie; Type: TABLE DATA; Schema: 1; Owner: postgrest_test
--
--
-- TOC entry 2307 (class 0 OID 337581)
-- Dependencies: 200
-- Data for Name: no_pk; Type: TABLE DATA; Schema: 1; Owner: postgrest_test
--
--
-- TOC entry 2308 (class 0 OID 337587)
-- Dependencies: 201
-- Data for Name: simple_pk; Type: TABLE DATA; Schema: 1; Owner: postgrest_test
--
SET search_path = postgrest, pg_catalog;
--
-- TOC entry 2309 (class 0 OID 337593)
-- Dependencies: 202
-- Data for Name: auth; Type: TABLE DATA; Schema: postgrest; Owner: postgrest_test
--
SET search_path = private, pg_catalog;
--
-- TOC entry 2310 (class 0 OID 337599)
-- Dependencies: 203
-- Data for Name: articles; Type: TABLE DATA; Schema: private; Owner: postgrest_test
--
--
-- TOC entry 2340 (class 0 OID 0)
-- Dependencies: 204
-- Name: articles_id_seq; Type: SEQUENCE SET; Schema: private; Owner: postgrest_test
--
SELECT pg_catalog.setval('articles_id_seq', 1, false);
SET search_path = "1", pg_catalog;
--
-- TOC entry 2170 (class 2606 OID 337612)
-- Name: authors_only_pkey; Type: CONSTRAINT; Schema: 1; Owner: postgrest_test_author; Tablespace:
--
ALTER TABLE ONLY authors_only
ADD CONSTRAINT authors_only_pkey PRIMARY KEY (secret);
--
-- TOC entry 2172 (class 2606 OID 337614)
-- Name: auto_incrementing_pk_pkey; Type: CONSTRAINT; Schema: 1; Owner: postgrest_test; Tablespace:
--
ALTER TABLE ONLY auto_incrementing_pk
ADD CONSTRAINT auto_incrementing_pk_pkey PRIMARY KEY (id);
--
-- TOC entry 2174 (class 2606 OID 337616)
-- Name: compound_pk_pkey; Type: CONSTRAINT; Schema: 1; Owner: postgrest_test; Tablespace:
--
ALTER TABLE ONLY compound_pk
ADD CONSTRAINT compound_pk_pkey PRIMARY KEY (k1, k2);
--
-- TOC entry 2182 (class 2606 OID 337618)
-- Name: contacts_pkey; Type: CONSTRAINT; Schema: 1; Owner: postgrest_test; Tablespace:
--
ALTER TABLE ONLY simple_pk
ADD CONSTRAINT contacts_pkey PRIMARY KEY (k);
--
-- TOC entry 2176 (class 2606 OID 337620)
-- Name: has_fk_pkey; Type: CONSTRAINT; Schema: 1; Owner: postgrest_test; Tablespace:
--
ALTER TABLE ONLY has_fk
ADD CONSTRAINT has_fk_pkey PRIMARY KEY (id);
--
-- TOC entry 2178 (class 2606 OID 337622)
-- Name: items_pkey; Type: CONSTRAINT; Schema: 1; Owner: postgrest_test; Tablespace:
--
ALTER TABLE ONLY items
ADD CONSTRAINT items_pkey PRIMARY KEY (id);
--
-- TOC entry 2180 (class 2606 OID 337624)
-- Name: menagerie_pkey; Type: CONSTRAINT; Schema: 1; Owner: postgrest_test; Tablespace:
--
ALTER TABLE ONLY menagerie
ADD CONSTRAINT menagerie_pkey PRIMARY KEY ("integer");
@@ -582,10 +361,6 @@ ALTER TABLE ONLY menagerie
SET search_path = postgrest, pg_catalog;
--
-- TOC entry 2184 (class 2606 OID 337626)
-- Name: auth_pkey; Type: CONSTRAINT; Schema: postgrest; Owner: postgrest_test; Tablespace:
--
ALTER TABLE ONLY auth
ADD CONSTRAINT auth_pkey PRIMARY KEY (id);
@@ -593,10 +368,6 @@ ALTER TABLE ONLY auth
SET search_path = private, pg_catalog;
--
-- TOC entry 2186 (class 2606 OID 337628)
-- Name: articles_pkey; Type: CONSTRAINT; Schema: private; Owner: postgrest_test; Tablespace:
--
ALTER TABLE ONLY articles
ADD CONSTRAINT articles_pkey PRIMARY KEY (id);
@@ -604,49 +375,28 @@ ALTER TABLE ONLY articles
SET search_path = postgrest, pg_catalog;
--
-- TOC entry 2189 (class 2620 OID 337630)
-- Name: ensure_auth_role_exists; Type: TRIGGER; Schema: postgrest; Owner: postgrest_test
--
CREATE CONSTRAINT TRIGGER ensure_auth_role_exists AFTER INSERT OR UPDATE ON auth NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE PROCEDURE check_role_exists();
SET search_path = private, pg_catalog;
--
-- TOC entry 2190 (class 2620 OID 337631)
-- Name: articles_owner_track; Type: TRIGGER; Schema: private; Owner: postgrest_test
--
CREATE TRIGGER articles_owner_track BEFORE INSERT OR UPDATE ON articles FOR EACH ROW EXECUTE PROCEDURE postgrest.update_owner();
SET search_path = "1", pg_catalog;
--
-- TOC entry 2187 (class 2606 OID 337632)
-- Name: has_fk_fk_fkey; Type: FK CONSTRAINT; Schema: 1; Owner: postgrest_test
--
ALTER TABLE ONLY has_fk
ADD CONSTRAINT has_fk_fk_fkey FOREIGN KEY (auto_inc_fk) REFERENCES auto_incrementing_pk(id);
--
-- TOC entry 2188 (class 2606 OID 337637)
-- Name: has_fk_simple_fk_fkey; Type: FK CONSTRAINT; Schema: 1; Owner: postgrest_test
--
ALTER TABLE ONLY has_fk
ADD CONSTRAINT has_fk_simple_fk_fkey FOREIGN KEY (simple_fk) REFERENCES simple_pk(k);
--
-- TOC entry 2317 (class 0 OID 0)
-- Dependencies: 20
-- Name: 1; Type: ACL; Schema: -; Owner: postgrest_test
--
REVOKE ALL ON SCHEMA "1" FROM PUBLIC;
REVOKE ALL ON SCHEMA "1" FROM postgrest_test;
@@ -655,11 +405,6 @@ GRANT USAGE ON SCHEMA "1" TO postgrest_anonymous;
GRANT USAGE ON SCHEMA "1" TO postgrest_test_author;
--
-- TOC entry 2318 (class 0 OID 0)
-- Dependencies: 19
-- Name: postgrest; Type: ACL; Schema: -; Owner: postgrest_test
--
REVOKE ALL ON SCHEMA postgrest FROM PUBLIC;
REVOKE ALL ON SCHEMA postgrest FROM postgrest_test;
@@ -667,33 +412,17 @@ GRANT ALL ON SCHEMA postgrest TO postgrest_test;
GRANT USAGE ON SCHEMA postgrest TO postgrest_anonymous;
--
-- TOC entry 2320 (class 0 OID 0)
-- Dependencies: 21
-- Name: public; Type: ACL; Schema: -; Owner: postgres
--
REVOKE ALL ON SCHEMA public FROM PUBLIC;
GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO PUBLIC;
--
-- TOC entry 2322 (class 0 OID 0)
-- Dependencies: 191
-- Name: authors_only; Type: ACL; Schema: 1; Owner: postgrest_test_author
--
REVOKE ALL ON TABLE authors_only FROM PUBLIC;
REVOKE ALL ON TABLE authors_only FROM postgrest_test_author;
GRANT ALL ON TABLE authors_only TO postgrest_test_author;
--
-- TOC entry 2323 (class 0 OID 0)
-- Dependencies: 192
-- Name: auto_incrementing_pk; Type: ACL; Schema: 1; Owner: postgrest_test
--
REVOKE ALL ON TABLE auto_incrementing_pk FROM PUBLIC;
REVOKE ALL ON TABLE auto_incrementing_pk FROM postgrest_test;
@@ -701,11 +430,6 @@ GRANT ALL ON TABLE auto_incrementing_pk TO postgrest_test;
GRANT ALL ON TABLE auto_incrementing_pk TO postgrest_anonymous;
--
-- TOC entry 2325 (class 0 OID 0)
-- Dependencies: 193
-- Name: auto_incrementing_pk_id_seq; Type: ACL; Schema: 1; Owner: postgrest_test
--
REVOKE ALL ON SEQUENCE auto_incrementing_pk_id_seq FROM PUBLIC;
REVOKE ALL ON SEQUENCE auto_incrementing_pk_id_seq FROM postgrest_test;
@@ -713,11 +437,6 @@ GRANT ALL ON SEQUENCE auto_incrementing_pk_id_seq TO postgrest_test;
GRANT USAGE ON SEQUENCE auto_incrementing_pk_id_seq TO postgrest_anonymous;
--
-- TOC entry 2326 (class 0 OID 0)
-- Dependencies: 194
-- Name: compound_pk; Type: ACL; Schema: 1; Owner: postgrest_test
--
REVOKE ALL ON TABLE compound_pk FROM PUBLIC;
REVOKE ALL ON TABLE compound_pk FROM postgrest_test;
@@ -730,11 +449,6 @@ REVOKE ALL ON TABLE has_fk FROM postgrest_test;
GRANT ALL ON TABLE has_fk TO postgrest_test;
GRANT ALL ON TABLE has_fk TO postgrest_anonymous;
--
-- TOC entry 2328 (class 0 OID 0)
-- Dependencies: 197
-- Name: items; Type: ACL; Schema: 1; Owner: postgrest_test
--
REVOKE ALL ON TABLE items FROM PUBLIC;
REVOKE ALL ON TABLE items FROM postgrest_test;
@@ -742,11 +456,6 @@ GRANT ALL ON TABLE items TO postgrest_test;
GRANT ALL ON TABLE items TO postgrest_anonymous;
--
-- TOC entry 2330 (class 0 OID 0)
-- Dependencies: 198
-- Name: items_id_seq; Type: ACL; Schema: 1; Owner: postgrest_test
--
REVOKE ALL ON SEQUENCE items_id_seq FROM PUBLIC;
REVOKE ALL ON SEQUENCE items_id_seq FROM postgrest_test;
@@ -754,11 +463,6 @@ GRANT ALL ON SEQUENCE items_id_seq TO postgrest_test;
GRANT USAGE ON SEQUENCE items_id_seq TO postgrest_anonymous;
--
-- TOC entry 2331 (class 0 OID 0)
-- Dependencies: 199
-- Name: menagerie; Type: ACL; Schema: 1; Owner: postgrest_test
--
REVOKE ALL ON TABLE menagerie FROM PUBLIC;
REVOKE ALL ON TABLE menagerie FROM postgrest_test;
@@ -766,11 +470,6 @@ GRANT ALL ON TABLE menagerie TO postgrest_test;
GRANT ALL ON TABLE menagerie TO postgrest_anonymous;
--
-- TOC entry 2332 (class 0 OID 0)
-- Dependencies: 200
-- Name: no_pk; Type: ACL; Schema: 1; Owner: postgrest_test
--
REVOKE ALL ON TABLE no_pk FROM PUBLIC;
REVOKE ALL ON TABLE no_pk FROM postgrest_test;
@@ -778,11 +477,6 @@ GRANT ALL ON TABLE no_pk TO postgrest_test;
GRANT ALL ON TABLE no_pk TO postgrest_anonymous;
--
-- TOC entry 2333 (class 0 OID 0)
-- Dependencies: 201
-- Name: simple_pk; Type: ACL; Schema: 1; Owner: postgrest_test
--
REVOKE ALL ON TABLE simple_pk FROM PUBLIC;
REVOKE ALL ON TABLE simple_pk FROM postgrest_test;
@@ -790,13 +484,15 @@ GRANT ALL ON TABLE simple_pk TO postgrest_test;
GRANT ALL ON TABLE simple_pk TO postgrest_anonymous;
REVOKE ALL ON TABLE json FROM PUBLIC;
REVOKE ALL ON TABLE json FROM postgrest_test;
GRANT ALL ON TABLE json TO postgrest_test;
GRANT ALL ON TABLE json TO postgrest_anonymous;
SET search_path = postgrest, pg_catalog;
--
-- TOC entry 2334 (class 0 OID 0)
-- Dependencies: 202
-- Name: auth; Type: ACL; Schema: postgrest; Owner: postgrest_test
--
REVOKE ALL ON TABLE auth FROM PUBLIC;
REVOKE ALL ON TABLE auth FROM postgrest_test;
@@ -806,20 +502,7 @@ GRANT INSERT ON TABLE auth TO postgrest_anonymous;
SET search_path = private, pg_catalog;
--
-- TOC entry 2335 (class 0 OID 0)
-- Dependencies: 203
-- Name: articles; Type: ACL; Schema: private; Owner: postgrest_test
--
REVOKE ALL ON TABLE articles FROM PUBLIC;
REVOKE ALL ON TABLE articles FROM postgrest_test;
GRANT ALL ON TABLE articles TO postgrest_test;
-- Completed on 2014-10-21 15:12:44 PDT
--
-- PostgreSQL database dump complete
--