Compare commits

...
12 Commits
Author SHA1 Message Date
Steve ChávezandGitHub 713b214c9a Bump to version v6.0.2
* Add missing CHANGELOG entry for #1368
2019-08-22 11:12:01 -05:00
steve-chavez 681388631b Add raw-media-types to Dockerfile 2019-08-21 10:34:28 -05:00
steve-chavez ae9e27a0c7 Fix #1348, go back to converting plus "+" to space
Not doing this conflicts with some http clients and proxies.

Use the alternative url-safe character '!' instead for
disambiguating resource embedding.
2019-08-21 10:34:28 -05:00
Steve ChávezandGitHub e83144ce7f Add documentation links 2019-08-16 12:41:24 -05:00
Joe NelsonandGitHub 1c54c7130a Another funding link 2019-08-14 14:05:12 -05:00
Steve ChávezandGitHub 1a8d5fed8a Update ISSUE_TEMPLATE.md 2019-08-13 08:15:11 -05:00
Nathan BouscalandSteve Chávez 57ebf43e85 Allow select in OpenAPI for POST requests (#1375)
If you use `return=representation`, `select` is useful in `POST` requests.
It already works correctly, but is missing from the OpenAPI spec.
2019-08-09 14:10:20 -05:00
steve-chavez b87734343e Update BACKERS.md 2019-08-08 18:50:34 -05:00
Dan AmorosoandSteve Chávez c80c9ef726 Reword error message for BinaryFieldError (#1372) 2019-08-08 14:20:06 -05:00
Dan AmorosoandSteve Chávez d5758523f3 Change raw-media-types to accept a string of comma separated MIME types (#1370) 2019-08-06 13:23:52 -05:00
Amédée d'AbovilleandSteve Chávez ee40e7e0d7 Fix long column descriptions being truncated at 63 characters in pg12 (#1368)
* Lengthen child_entities name comment to make tests check it does not get truncated at 63 chars.

* Don't cast column description to sql_identifier type (maxlen 63 chars) when introspecting schema in DbStructure.hs
2019-08-02 16:13:01 +00:00
steve-chavez 53b606e1c1 Remove raw-media-types config from Docker
Passing a list through an env var is not working
in configurator-pg
2019-07-31 12:06:19 -05:00
18 changed files with 67 additions and 40 deletions
+3
View File
@@ -0,0 +1,3 @@
# These are supported funding model platforms
patreon: postgrest
+4
View File
@@ -1,3 +1,7 @@
<!--
Before reporting a bug:
If your database schema has changed while the PostgREST server is running, send the server a SIGUSR1 signal or restart it(http://postgrest.org/en/v5.2/admin.html#schema-reloading) to ensure the schema cache is not stale. This sometimes fixes apparent bugs.
-->
### Environment ### Environment
* PostgreSQL version: (if using docker, specify the image) * PostgreSQL version: (if using docker, specify the image)
+3 -1
View File
@@ -29,16 +29,18 @@ PostgREST ongoing development is only possible thanks to our Sponsors and Backer
## Lead Backers ## Lead Backers
- [Daniel Babiak](https://github.com/d-babiak) - [Daniel Babiak](https://github.com/d-babiak)
- [Michel Pelletier](https://github.com/michelp/)
- Evans Fernandes - Evans Fernandes
## Backers ## Backers
- Tsingson Qin - Tsingson Qin
- Michel Pelletier
- Jay Hannah - Jay Hannah
- Robert Stolarz - Robert Stolarz
- Kofi Gumbs - Kofi Gumbs
- Nicholas DiBiase - Nicholas DiBiase
- Christopher Reid
- Nathan Bouscal
## Former Backers ## Former Backers
+12
View File
@@ -9,6 +9,18 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Fixed ### Fixed
## [6.0.2] - 2019-08-22
### Fixed
- #1369, Change `raw-media-types` to accept a string of comma separated MIME types - @Dansvidania
- #1368, Fix long column descriptions being truncated at 63 characters in PostgreSQL 12 - @amedeedaboville
- #1348, Go back to converting plus "+" to space " " in querystrings by default - @steve-chavez
### Deprecated
- #1348, Deprecate `.` symbol for disambiguating resource embedding(added in #918). The url-safe '!' should be used instead. We refrained from using `+` as part of our syntax because it conflicts with some http clients and proxies.
## [6.0.1] - 2019-07-30 ## [6.0.1] - 2019-07-30
### Added ### Added
+5 -3
View File
@@ -50,13 +50,15 @@ Big thanks to our sponsors! You can join them by supporting PostgREST on [Patreo
```bash ```bash
postgrest --help postgrest --help
``` ```
## [Documentation](http://postgrest.org)
Latest documentation is at [postgrest.org](http://postgrest.org). You can contribute to the docs in [PostgREST/postgrest-docs](https://github.com/PostgREST/postgrest-docs).
## Performance ## Performance
TLDR; subsecond response times for up to 2000 requests/sec on Heroku TLDR; subsecond response times for up to 2000 requests/sec on Heroku
free tier. If you're used to servers written in interpreted languages free tier. If you're used to servers written in interpreted languages,
(or named after precious gems), prepare to be pleasantly surprised by prepare to be pleasantly surprised by PostgREST performance.
PostgREST performance.
Three factors contribute to the speed. First the server is written Three factors contribute to the speed. First the server is written
in [Haskell](https://www.haskell.org/) using the in [Haskell](https://www.haskell.org/) using the
+1 -1
View File
@@ -10,7 +10,7 @@
}, },
"POSTGREST_VER": { "POSTGREST_VER": {
"description": "Version of PostgREST to deploy", "description": "Version of PostgREST to deploy",
"value": "6.0.1" "value": "6.0.2"
}, },
"DB_URI": { "DB_URI": {
"description": "Database connection string, e.g. postgres://user:pass@xxxxxxx.rds.amazonaws.com/mydb", "description": "Database connection string, e.g. postgres://user:pass@xxxxxxx.rds.amazonaws.com/mydb",
-1
View File
@@ -16,5 +16,4 @@ role-claim-key = "$(PGRST_ROLE_CLAIM_KEY)"
max-rows = "$(PGRST_MAX_ROWS)" max-rows = "$(PGRST_MAX_ROWS)"
pre-request = "$(PGRST_PRE_REQUEST)" pre-request = "$(PGRST_PRE_REQUEST)"
root-spec = "$(PGRST_ROOT_SPEC)" root-spec = "$(PGRST_ROOT_SPEC)"
raw-media-types = "$(PGRST_RAW_MEDIA_TYPES)" raw-media-types = "$(PGRST_RAW_MEDIA_TYPES)"
+1 -1
View File
@@ -1,5 +1,5 @@
name: postgrest name: postgrest
version: 6.0.1 version: 6.0.2
synopsis: REST API for any Postgres database synopsis: REST API for any Postgres database
description: Reads the schema of a PostgreSQL database and creates RESTful routes description: Reads the schema of a PostgreSQL database and creates RESTful routes
for the tables and views, supporting all HTTP verbs that security for the tables and views, supporting all HTTP verbs that security
+4 -4
View File
@@ -138,14 +138,14 @@ userApiRequest schema rootSpec req reqBody
, iCanonicalQS = toS $ urlEncodeVars , iCanonicalQS = toS $ urlEncodeVars
. L.sortOn fst . L.sortOn fst
. map (join (***) toS . second (fromMaybe BS.empty)) . map (join (***) toS . second (fromMaybe BS.empty))
$ queryStringWPlus $ qString
, iJWT = tokenStr , iJWT = tokenStr
, iHeaders = [ (toS $ CI.foldedCase k, toS v) | (k,v) <- hdrs, k /= hAuthorization, k /= hCookie] , iHeaders = [ (toS $ CI.foldedCase k, toS v) | (k,v) <- hdrs, k /= hAuthorization, k /= hCookie]
, iCookies = maybe [] parseCookiesText $ lookupHeader "Cookie" , iCookies = maybe [] parseCookiesText $ lookupHeader "Cookie"
} }
where where
-- queryString with '+' not converted to ' ' -- queryString with '+' converted to ' '(space)
queryStringWPlus = parseQueryReplacePlus False $ rawQueryString req qString = parseQueryReplacePlus True $ rawQueryString req
-- rpcQParams = Rpc query params e.g. /rpc/name?param1=val1, similar to filter but with no operator(eq, lt..) -- rpcQParams = Rpc query params e.g. /rpc/name?param1=val1, similar to filter but with no operator(eq, lt..)
(filters, rpcQParams) = (filters, rpcQParams) =
case action of case action of
@@ -215,7 +215,7 @@ userApiRequest schema rootSpec req reqBody
path = pathInfo req path = pathInfo req
method = requestMethod req method = requestMethod req
hdrs = requestHeaders req hdrs = requestHeaders req
qParams = [(toS k, v)|(k,v) <- queryStringWPlus] qParams = [(toS k, v)|(k,v) <- qString]
lookupHeader = flip lookup hdrs lookupHeader = flip lookup hdrs
hasPrefer :: Text -> Bool hasPrefer :: Text -> Bool
hasPrefer val = any (\(h,v) -> h == "Prefer" && val `elem` split v) hdrs hasPrefer val = any (\(h,v) -> h == "Prefer" && val `elem` split v) hdrs
+6 -12
View File
@@ -167,9 +167,9 @@ readOptions = do
<*> pure False <*> pure False
<*> (fmap (fmap coerceText) <$> C.subassocs "app.settings" C.value) <*> (fmap (fmap coerceText) <$> C.subassocs "app.settings" C.value)
<*> (maybe (Right [JSPKey "role"]) parseRoleClaimKey <$> optValue "role-claim-key") <*> (maybe (Right [JSPKey "role"]) parseRoleClaimKey <$> optValue "role-claim-key")
<*> (maybe ["public"] splitExtraSearchPath <$> optValue "db-extra-search-path") <*> (maybe ["public"] splitOnCommas <$> optValue "db-extra-search-path")
<*> ((\x y -> QualifiedIdentifier x <$> y) <$> dbSchema <*> optString "root-spec") <*> ((\x y -> QualifiedIdentifier x <$> y) <$> dbSchema <*> optString "root-spec")
<*> (fmap encodeUtf8 <$> optionalListOfText "raw-media-types") <*> (maybe [] (fmap encodeUtf8 . splitOnCommas) <$> optValue "raw-media-types")
parseJwtAudience :: C.Key -> C.Parser C.Config (Maybe StringOrURI) parseJwtAudience :: C.Key -> C.Parser C.Config (Maybe StringOrURI)
parseJwtAudience k = parseJwtAudience k =
@@ -180,12 +180,6 @@ readOptions = do
(Just "") -> pure Nothing (Just "") -> pure Nothing
aud' -> pure aud' aud' -> pure aud'
optionalListOfText :: C.Key -> C.Parser C.Config [Text]
optionalListOfText k =
C.optional k (C.list C.string) >>= \case
Nothing -> pure []
Just types -> pure types
reqString :: C.Key -> C.Parser C.Config Text reqString :: C.Key -> C.Parser C.Config Text
reqString k = C.required k C.string reqString k = C.required k C.string
@@ -219,9 +213,9 @@ readOptions = do
parseRoleClaimKey (C.String s) = pRoleClaimKey s parseRoleClaimKey (C.String s) = pRoleClaimKey s
parseRoleClaimKey v = pRoleClaimKey $ show v parseRoleClaimKey v = pRoleClaimKey $ show v
splitExtraSearchPath :: C.Value -> [Text] splitOnCommas :: C.Value -> [Text]
splitExtraSearchPath (C.String s) = strip <$> splitOn "," s splitOnCommas (C.String s) = strip <$> splitOn "," s
splitExtraSearchPath _ = [] splitOnCommas _ = []
opts = info (helper <*> pathParser) $ opts = info (helper <*> pathParser) $
fullDesc fullDesc
@@ -283,7 +277,7 @@ readOptions = do
|# root-spec = "stored_proc_name" |# root-spec = "stored_proc_name"
| |
|## content types to produce raw output |## content types to produce raw output
|# raw-media-types=["image/png","image/jpg"] |# raw-media-types="image/png, image/jpg"
|] |]
pathParser :: Parser FilePath pathParser :: Parser FilePath
+1 -1
View File
@@ -437,7 +437,7 @@ allColumns tabs =
nc.nspname::information_schema.sql_identifier AS table_schema, nc.nspname::information_schema.sql_identifier AS table_schema,
c.relname::information_schema.sql_identifier AS table_name, c.relname::information_schema.sql_identifier AS table_name,
a.attname::information_schema.sql_identifier AS column_name, a.attname::information_schema.sql_identifier AS column_name,
d.description::information_schema.sql_identifier AS description, d.description AS description,
a.attnum::information_schema.cardinal_number AS ordinal_position, a.attnum::information_schema.cardinal_number AS ordinal_position,
pg_get_expr(ad.adbin, ad.adrelid)::information_schema.character_data AS column_default, pg_get_expr(ad.adbin, ad.adrelid)::information_schema.character_data AS column_default,
CASE CASE
+1 -1
View File
@@ -224,7 +224,7 @@ instance JSON.ToJSON SimpleError where
toJSON GucHeadersError = JSON.object [ toJSON GucHeadersError = JSON.object [
"message" .= ("response.headers guc must be a JSON array composed of objects with a single key and a string value" :: Text)] "message" .= ("response.headers guc must be a JSON array composed of objects with a single key and a string value" :: Text)]
toJSON (BinaryFieldError ct) = JSON.object [ toJSON (BinaryFieldError ct) = JSON.object [
"message" .= ((toS (toMime ct) <> " requested but a single column was not selected") :: Text)] "message" .= ((toS (toMime ct) <> " requested but more than one column was selected") :: Text)]
toJSON ConnectionLostError = JSON.object [ toJSON ConnectionLostError = JSON.object [
"message" .= ("Database connection lost, retrying the connection." :: Text)] "message" .= ("Database connection lost, retrying the connection." :: Text)]
+1 -1
View File
@@ -218,7 +218,7 @@ makePathItem (t, cs, _) = ("/" ++ unpack tn, p $ tableInsertable t)
) )
) )
postOp = tOp postOp = tOp
& parameters .~ map ref ["body." <> tn, "preferReturn"] & parameters .~ map ref ["body." <> tn, "select", "preferReturn"]
& at 201 ?~ "Created" & at 201 ?~ "Created"
patchOp = tOp patchOp = tOp
& parameters .~ map ref (rs <> ["body." <> tn, "preferReturn"]) & parameters .~ map ref (rs <> ["body." <> tn, "preferReturn"])
+1 -1
View File
@@ -131,7 +131,7 @@ pRelationSelect = lexeme $ try ( do
alias <- optionMaybe ( try(pFieldName <* aliasSeparator) ) alias <- optionMaybe ( try(pFieldName <* aliasSeparator) )
fld <- pField fld <- pField
relationDetail <- optionMaybe ( relationDetail <- optionMaybe (
try ( char '+' *> pFieldName ) <|> try ( char '!' *> pFieldName ) <|>
try ( char '.' *> pFieldName ) -- TODO deprecated, remove in next major version try ( char '.' *> pFieldName ) -- TODO deprecated, remove in next major version
) )
+11 -10
View File
@@ -480,12 +480,12 @@ spec actualPgVersion = do
describe "path fixed" $ do describe "path fixed" $ do
it "works when requesting children 2 levels" $ it "works when requesting children 2 levels" $
get "/clients?id=eq.1&select=id,projects:projects%2Bclient_id(id,tasks(id))" `shouldRespondWith` get "/clients?id=eq.1&select=id,projects:projects!client_id(id,tasks(id))" `shouldRespondWith`
[json|[{"id":1,"projects":[{"id":1,"tasks":[{"id":1},{"id":2}]},{"id":2,"tasks":[{"id":3},{"id":4}]}]}]|] [json|[{"id":1,"projects":[{"id":1,"tasks":[{"id":1},{"id":2}]},{"id":2,"tasks":[{"id":3},{"id":4}]}]}]|]
{ matchHeaders = [matchContentTypeJson] } { matchHeaders = [matchContentTypeJson] }
it "works with parent relation" $ it "works with parent relation" $
get "/message?select=id,body,sender:person%2Bsender(name),recipient:person%2Brecipient(name)&id=lt.4" `shouldRespondWith` get "/message?select=id,body,sender:person!sender(name),recipient:person!recipient(name)&id=lt.4" `shouldRespondWith`
[json| [json|
[{"id":1,"body":"Hello Jane","sender":{"name":"John"},"recipient":{"name":"Jane"}}, [{"id":1,"body":"Hello Jane","sender":{"name":"John"},"recipient":{"name":"Jane"}},
{"id":2,"body":"Hi John","sender":{"name":"Jane"},"recipient":{"name":"John"}}, {"id":2,"body":"Hi John","sender":{"name":"Jane"},"recipient":{"name":"John"}},
@@ -499,7 +499,7 @@ spec actualPgVersion = do
, matchHeaders = [matchContentTypeJson] } , matchHeaders = [matchContentTypeJson] }
it "works with a parent view relation" $ it "works with a parent view relation" $
get "/message?select=id,body,sender:person_detail%2Bsender(name,sent),recipient:person_detail%2Brecipient(name,received)&id=lt.4" `shouldRespondWith` get "/message?select=id,body,sender:person_detail!sender(name,sent),recipient:person_detail!recipient(name,received)&id=lt.4" `shouldRespondWith`
[json| [json|
[{"id":1,"body":"Hello Jane","sender":{"name":"John","sent":2},"recipient":{"name":"Jane","received":2}}, [{"id":1,"body":"Hello Jane","sender":{"name":"John","sent":2},"recipient":{"name":"Jane","received":2}},
{"id":2,"body":"Hi John","sender":{"name":"Jane","sent":1},"recipient":{"name":"John","received":1}}, {"id":2,"body":"Hi John","sender":{"name":"Jane","sent":1},"recipient":{"name":"John","received":1}},
@@ -507,10 +507,11 @@ spec actualPgVersion = do
{ matchHeaders = [matchContentTypeJson] } { matchHeaders = [matchContentTypeJson] }
it "works with many<->many relation" $ it "works with many<->many relation" $
get "/tasks?select=id,users:users%2Busers_tasks(id)" `shouldRespondWith` get "/tasks?select=id,users:users!users_tasks(id)" `shouldRespondWith`
[json|[{"id":1,"users":[{"id":1},{"id":3}]},{"id":2,"users":[{"id":1}]},{"id":3,"users":[{"id":1}]},{"id":4,"users":[{"id":1}]},{"id":5,"users":[{"id":2},{"id":3}]},{"id":6,"users":[{"id":2}]},{"id":7,"users":[{"id":2}]},{"id":8,"users":[]}]|] [json|[{"id":1,"users":[{"id":1},{"id":3}]},{"id":2,"users":[{"id":1}]},{"id":3,"users":[{"id":1}]},{"id":4,"users":[{"id":1}]},{"id":5,"users":[{"id":2},{"id":3}]},{"id":6,"users":[{"id":2}]},{"id":7,"users":[{"id":2}]},{"id":8,"users":[]}]|]
{ matchHeaders = [matchContentTypeJson] } { matchHeaders = [matchContentTypeJson] }
-- TODO Remove in next major version(7.0)
describe "old dot '.' symbol, deprecated" $ describe "old dot '.' symbol, deprecated" $
it "still works" $ do it "still works" $ do
get "/clients?id=eq.1&select=id,projects:projects.client_id(id,tasks(id))" `shouldRespondWith` get "/clients?id=eq.1&select=id,projects:projects.client_id(id,tasks(id))" `shouldRespondWith`
@@ -588,7 +589,7 @@ spec actualPgVersion = do
{ matchHeaders = [matchContentTypeJson] } { matchHeaders = [matchContentTypeJson] }
it "embeds childs recursively" $ it "embeds childs recursively" $
get "/family_tree?id=eq.1&select=id,name, childs:family_tree%2Bparent(id,name,childs:family_tree%2Bparent(id,name))" `shouldRespondWith` get "/family_tree?id=eq.1&select=id,name, childs:family_tree!parent(id,name,childs:family_tree!parent(id,name))" `shouldRespondWith`
[json|[{ [json|[{
"id": "1", "name": "Parental Unit", "childs": [ "id": "1", "name": "Parental Unit", "childs": [
{ "id": "2", "name": "Kid One", "childs": [ { "id": "4", "name": "Grandkid One" } ] }, { "id": "2", "name": "Kid One", "childs": [ { "id": "4", "name": "Grandkid One" } ] },
@@ -597,7 +598,7 @@ spec actualPgVersion = do
}]|] { matchHeaders = [matchContentTypeJson] } }]|] { matchHeaders = [matchContentTypeJson] }
it "embeds parent and then embeds childs" $ it "embeds parent and then embeds childs" $
get "/family_tree?id=eq.2&select=id,name,parent(id,name,childs:family_tree%2Bparent(id,name))" `shouldRespondWith` get "/family_tree?id=eq.2&select=id,name,parent(id,name,childs:family_tree!parent(id,name))" `shouldRespondWith`
[json|[{ [json|[{
"id": "2", "name": "Kid One", "parent": { "id": "2", "name": "Kid One", "parent": {
"id": "1", "name": "Parental Unit", "childs": [ { "id": "2", "name": "Kid One" }, { "id": "3", "name": "Kid Two"} ] "id": "1", "name": "Parental Unit", "childs": [ { "id": "2", "name": "Kid One" }, { "id": "3", "name": "Kid Two"} ]
@@ -620,7 +621,7 @@ spec actualPgVersion = do
}]|] { matchHeaders = [matchContentTypeJson] } }]|] { matchHeaders = [matchContentTypeJson] }
it "embeds childs" $ do it "embeds childs" $ do
get "/organizations?select=id,name,refereeds:organizations%2Breferee(id,name)&id=eq.1" `shouldRespondWith` get "/organizations?select=id,name,refereeds:organizations!referee(id,name)&id=eq.1" `shouldRespondWith`
[json|[{ [json|[{
"id": 1, "name": "Referee Org", "id": 1, "name": "Referee Org",
"refereeds": [ "refereeds": [
@@ -634,7 +635,7 @@ spec actualPgVersion = do
} }
] ]
}]|] { matchHeaders = [matchContentTypeJson] } }]|] { matchHeaders = [matchContentTypeJson] }
get "/organizations?select=id,name,auditees:organizations%2Bauditor(id,name)&id=eq.2" `shouldRespondWith` get "/organizations?select=id,name,auditees:organizations!auditor(id,name)&id=eq.2" `shouldRespondWith`
[json|[{ [json|[{
"id": 2, "name": "Auditor Org", "id": 2, "name": "Auditor Org",
"auditees": [ "auditees": [
@@ -668,7 +669,7 @@ spec actualPgVersion = do
"manager":{"name":"Referee Manager"}}} "manager":{"name":"Referee Manager"}}}
}]|] { matchHeaders = [matchContentTypeJson] } }]|] { matchHeaders = [matchContentTypeJson] }
get "/organizations?select=name,manager(name),auditees:organizations%2Bauditor(name,manager(name),refereeds:organizations%2Breferee(name,manager(name)))&id=eq.2" `shouldRespondWith` get "/organizations?select=name,manager(name),auditees:organizations!auditor(name,manager(name),refereeds:organizations!referee(name,manager(name)))&id=eq.2" `shouldRespondWith`
[json|[{ [json|[{
"name":"Auditor Org", "name":"Auditor Org",
"manager":{"name":"Auditor Manager"}, "manager":{"name":"Auditor Manager"},
@@ -950,7 +951,7 @@ spec actualPgVersion = do
it "fails if a single column is not selected" $ do it "fails if a single column is not selected" $ do
request methodGet "/images?select=img,name&name=eq.A.png" (acceptHdrs "application/octet-stream") "" request methodGet "/images?select=img,name&name=eq.A.png" (acceptHdrs "application/octet-stream") ""
`shouldRespondWith` `shouldRespondWith`
[json| {"message":"application/octet-stream requested but a single column was not selected"} |] [json| {"message":"application/octet-stream requested but more than one column was selected"} |]
{ matchStatus = 406 { matchStatus = 406
, matchHeaders = [matchContentTypeJson] , matchHeaders = [matchContentTypeJson]
} }
+1 -1
View File
@@ -482,7 +482,7 @@ spec actualPgVersion =
it "fails if a single column is not selected" $ it "fails if a single column is not selected" $
request methodPost "/rpc/ret_rows_with_base64_bin" (acceptHdrs "application/octet-stream") "" request methodPost "/rpc/ret_rows_with_base64_bin" (acceptHdrs "application/octet-stream") ""
`shouldRespondWith` `shouldRespondWith`
[json| {"message":"application/octet-stream requested but a single column was not selected"} |] [json| {"message":"application/octet-stream requested but more than one column was selected"} |]
{ matchStatus = 406 { matchStatus = 406
, matchHeaders = [matchContentTypeJson] , matchHeaders = [matchContentTypeJson]
} }
+11 -1
View File
@@ -45,6 +45,7 @@ spec = do
childGetSummary = r ^? method "get" . key "summary" childGetSummary = r ^? method "get" . key "summary"
childGetDescription = r ^? method "get" . key "description" childGetDescription = r ^? method "get" . key "description"
getParameters = r ^? method "get" . key "parameters" getParameters = r ^? method "get" . key "parameters"
postParameters = r ^? method "post" . key "parameters"
postResponse = r ^? method "post" . key "responses" . key "201" . key "description" postResponse = r ^? method "post" . key "responses" . key "201" . key "description"
patchResponse = r ^? method "patch" . key "responses" . key "204" . key "description" patchResponse = r ^? method "patch" . key "responses" . key "204" . key "description"
deleteResponse = r ^? method "delete" . key "responses" . key "204" . key "description" deleteResponse = r ^? method "delete" . key "responses" . key "204" . key "description"
@@ -79,6 +80,15 @@ spec = do
] ]
|] |]
postParameters `shouldBe` Just
[aesonQQ|
[
{ "$ref": "#/parameters/body.child_entities" },
{ "$ref": "#/parameters/select" },
{ "$ref": "#/parameters/preferReturn" }
]
|]
postResponse `shouldBe` Just "Created" postResponse `shouldBe` Just "Created"
patchResponse `shouldBe` Just "No Content" patchResponse `shouldBe` Just "No Content"
@@ -125,7 +135,7 @@ spec = do
"type": "integer" "type": "integer"
}, },
"name": { "name": {
"description": "child_entities name comment", "description": "child_entities name comment. Can be longer than sixty-three characters long",
"format": "text", "format": "text",
"type": "string" "type": "string"
}, },
+1 -1
View File
@@ -1226,7 +1226,7 @@ create table ranges (
comment on table child_entities is 'child_entities comment'; comment on table child_entities is 'child_entities comment';
comment on column child_entities.id is 'child_entities id comment'; comment on column child_entities.id is 'child_entities id comment';
comment on column child_entities.name is 'child_entities name comment'; comment on column child_entities.name is 'child_entities name comment. Can be longer than sixty-three characters long';
comment on table grandchild_entities is comment on table grandchild_entities is
$$grandchild_entities summary $$grandchild_entities summary