Merge pull request #314 from calebmer/remove-versioning
Remove versioning feature
This commit is contained in:
@@ -10,6 +10,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- Filter columns, e.g. `?select=col1,col2` - @ruslantalpa
|
||||
- Does not execute the count total if header "Prefer: count=none" - @diogob
|
||||
|
||||
### Removed
|
||||
- API versioning feature - @calebmer
|
||||
|
||||
### Fixed
|
||||
- Tolerate a missing role in user creation - @calebmer
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ postgrest --db-host localhost --db-port 5432 \
|
||||
--db-name my_db --db-user postgres \
|
||||
--db-pass foobar --db-pool 200 \
|
||||
--anonymous postgres --port 3000 \
|
||||
--v1schema public
|
||||
--schema public
|
||||
```
|
||||
|
||||
In production include the `--secure` option which redirects all
|
||||
@@ -100,13 +100,14 @@ guide](https://github.com/begriffs/postgrest/wiki/Security-and-Permissions).
|
||||
### Versioning
|
||||
|
||||
A robust long-lived API needs the freedom to exist in multiple
|
||||
versions. PostgREST supports versioning through HTTP content
|
||||
negotiation. Requests for a certain version translate into switching
|
||||
which database schema to search for tables. PostgreSQL schema search
|
||||
paths allow tables from earlier versions to be reused verbatim in
|
||||
later versions.
|
||||
versions. Therefore it is a best practice that you version the database
|
||||
schema exposed to PostgREST (e.g. `public1` or `api2`). This way you
|
||||
future proof your API by allowing it to be backwards compatible when
|
||||
you want to publish breaking API changes (e.g. a later version could
|
||||
be `public2` or `api3`).
|
||||
|
||||
To learn more, see the [guide to versioning](https://github.com/begriffs/postgrest/wiki/API-Versioning).
|
||||
For routing to different versions of a PostgREST API use a request
|
||||
proxy (such as [nginx](http://nginx.org)).
|
||||
|
||||
### Self-documention
|
||||
|
||||
@@ -153,7 +154,6 @@ and the [guide to routing](https://github.com/begriffs/postgrest/wiki/Routing).
|
||||
### Guides
|
||||
|
||||
* [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)
|
||||
|
||||
Vendored
+6
-6
@@ -2,12 +2,12 @@
|
||||
### BEGIN INIT INFO
|
||||
# Provides: postgrest
|
||||
# Required-Start: $local_fs $network postgresql
|
||||
# Required-Stop: $local_fs $network
|
||||
# Required-Stop: $local_fs $network
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Description: PostgreSQL REST API daemon
|
||||
### END INIT INFO
|
||||
|
||||
|
||||
. /lib/lsb/init-functions
|
||||
if test -f /etc/default/postgrest; then
|
||||
. /etc/default/postgrest
|
||||
@@ -32,8 +32,8 @@ fi
|
||||
if [ -n "$POSTGREST_DBPOOL" ]; then
|
||||
POSTGREST_OPTS="$POSTGREST_OPTS --db-pool $POSTGREST_DBPOOL"
|
||||
fi
|
||||
POSTGREST_OPTS="$POSTGREST_OPTS --v1schema public"
|
||||
|
||||
POSTGREST_OPTS="$POSTGREST_OPTS --schema public"
|
||||
|
||||
start()
|
||||
{
|
||||
log_daemon_msg "Starting PostgreSQL REST API daemon" "postgrest" || true
|
||||
@@ -43,7 +43,7 @@ start()
|
||||
log_end_msg 1 || true
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
stop()
|
||||
{
|
||||
log_daemon_msg "Stopping PostgreSQL REST API daemon" "postgrest" || true
|
||||
@@ -53,7 +53,7 @@ stop()
|
||||
log_end_msg 1 || true
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
status()
|
||||
{
|
||||
status_of_proc $POSTGREST postgrest && exit 0 || exit $?
|
||||
|
||||
+2
-15
@@ -6,7 +6,6 @@ module PostgREST.App (
|
||||
, isSqlError
|
||||
, contentTypeForAccept
|
||||
, jsonH
|
||||
, requestedSchema
|
||||
, TableOptions(..)
|
||||
) where
|
||||
|
||||
@@ -29,7 +28,6 @@ import Data.Ranged.Ranges (emptyRange)
|
||||
import qualified Data.Set as S
|
||||
import Data.String.Conversions (cs)
|
||||
import Data.Text (Text, replace, strip)
|
||||
import Text.Regex.TDFA ((=~))
|
||||
|
||||
import Text.Parsec.Error
|
||||
|
||||
@@ -216,7 +214,7 @@ app dbstructure conf reqBody dbrole req =
|
||||
|
||||
-- check that proc exists
|
||||
-- check that arg names are all specified
|
||||
-- select * from "1".proc(a := "foo"::undefined) where whereT limit limitT
|
||||
-- select * from public.proc(a := "foo"::undefined) where whereT limit limitT
|
||||
|
||||
([table], "PUT") ->
|
||||
handleJsonObj reqBody $ \obj -> do
|
||||
@@ -296,7 +294,7 @@ app dbstructure conf reqBody dbrole req =
|
||||
lookupHeader = flip lookup hdrs
|
||||
hasPrefer val = any (\(h,v) -> h == "Prefer" && v == val) hdrs
|
||||
accept = lookupHeader hAccept
|
||||
schema = requestedSchema (cs $ configV1Schema conf) accept
|
||||
schema = cs $ configSchema conf
|
||||
authenticator = cs $ configDbUser conf
|
||||
jwtSecret = cs $ configJwtSecret conf
|
||||
range = rangeRequested hdrs
|
||||
@@ -329,17 +327,6 @@ contentRangeH from to total =
|
||||
totalNotZero = fromMaybe True ((/=) 0 <$> total)
|
||||
fromInRange = from <= to
|
||||
|
||||
requestedSchema :: Text -> Maybe BS.ByteString -> Text
|
||||
requestedSchema v1schema accept =
|
||||
case verStr of
|
||||
Just [[_, ver]] -> if ver == "1" then v1schema else cs ver
|
||||
_ -> v1schema
|
||||
|
||||
where
|
||||
verRegex = "version[ ]*=[ ]*([0-9]+)" :: BS.ByteString
|
||||
verStr = (=~ verRegex) <$> accept :: Maybe [[BS.ByteString]]
|
||||
|
||||
|
||||
jsonMT :: BS.ByteString
|
||||
jsonMT = "application/json"
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ data AppConfig = AppConfig {
|
||||
, configAnonRole :: String
|
||||
, configSecure :: Bool
|
||||
, configPool :: Int
|
||||
, configV1Schema :: String
|
||||
, configSchema :: String
|
||||
, configJwtSecret :: String
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ argParser = AppConfig
|
||||
<*> strOption (long "anonymous" <> short 'a' <> metavar "ROLE" <> help "postgres role to use for non-authenticated requests")
|
||||
<*> switch (long "secure" <> short 's' <> help "Redirect all requests to HTTPS")
|
||||
<*> option auto (long "db-pool" <> metavar "COUNT" <> value 10 <> help "Max connections in database pool" <> showDefault)
|
||||
<*> strOption (long "v1schema" <> metavar "NAME" <> value "1" <> help "Schema to use for nonspecified version (or explicit v1)" <> showDefault)
|
||||
<*> strOption (long "schema" <> short 'S' <> metavar "NAME" <> value "public" <> help "Schema to use for API routes" <> showDefault)
|
||||
<*> strOption (long "jwt-secret" <> metavar "SECRET" <> value "secret" <> help "Secret used to encrypt and decrypt JWT tokens)" <> showDefault)
|
||||
|
||||
defaultCorsPolicy :: CorsResourcePolicy
|
||||
|
||||
@@ -14,28 +14,28 @@ spec = around withApp $ do
|
||||
it "lists views in schema" $
|
||||
request methodGet "/" [] ""
|
||||
`shouldRespondWith` [json| [
|
||||
{"schema":"1","name":"auto_incrementing_pk","insertable":true}
|
||||
, {"schema":"1","name":"clients","insertable":true}
|
||||
, {"schema":"1","name":"comments","insertable":true}
|
||||
, {"schema":"1","name":"complex_items","insertable":true}
|
||||
, {"schema":"1","name":"compound_pk","insertable":true}
|
||||
, {"schema":"1","name":"has_count_column","insertable":false}
|
||||
, {"schema":"1","name":"has_fk","insertable":true}
|
||||
, {"schema":"1","name":"insertable_view_with_join","insertable":true}
|
||||
, {"schema":"1","name":"items","insertable":true}
|
||||
, {"schema":"1","name":"json","insertable":true}
|
||||
, {"schema":"1","name":"materialized_view","insertable":false}
|
||||
, {"schema":"1","name":"menagerie","insertable":true}
|
||||
, {"schema":"1","name":"no_pk","insertable":true}
|
||||
, {"schema":"1","name":"nullable_integer","insertable":true}
|
||||
, {"schema":"1","name":"projects","insertable":true}
|
||||
, {"schema":"1","name":"projects_view","insertable":true}
|
||||
, {"schema":"1","name":"simple_pk","insertable":true}
|
||||
, {"schema":"1","name":"tasks","insertable":true}
|
||||
, {"schema":"1","name":"tsearch","insertable":true}
|
||||
, {"schema":"1","name":"users","insertable":true}
|
||||
, {"schema":"1","name":"users_projects","insertable":true}
|
||||
, {"schema":"1","name":"users_tasks","insertable":true}
|
||||
{"schema":"test","name":"auto_incrementing_pk","insertable":true}
|
||||
, {"schema":"test","name":"clients","insertable":true}
|
||||
, {"schema":"test","name":"comments","insertable":true}
|
||||
, {"schema":"test","name":"complex_items","insertable":true}
|
||||
, {"schema":"test","name":"compound_pk","insertable":true}
|
||||
, {"schema":"test","name":"has_count_column","insertable":false}
|
||||
, {"schema":"test","name":"has_fk","insertable":true}
|
||||
, {"schema":"test","name":"insertable_view_with_join","insertable":true}
|
||||
, {"schema":"test","name":"items","insertable":true}
|
||||
, {"schema":"test","name":"json","insertable":true}
|
||||
, {"schema":"test","name":"materialized_view","insertable":false}
|
||||
, {"schema":"test","name":"menagerie","insertable":true}
|
||||
, {"schema":"test","name":"no_pk","insertable":true}
|
||||
, {"schema":"test","name":"nullable_integer","insertable":true}
|
||||
, {"schema":"test","name":"projects","insertable":true}
|
||||
, {"schema":"test","name":"projects_view","insertable":true}
|
||||
, {"schema":"test","name":"simple_pk","insertable":true}
|
||||
, {"schema":"test","name":"tasks","insertable":true}
|
||||
, {"schema":"test","name":"tsearch","insertable":true}
|
||||
, {"schema":"test","name":"users","insertable":true}
|
||||
, {"schema":"test","name":"users_projects","insertable":true}
|
||||
, {"schema":"test","name":"users_tasks","insertable":true}
|
||||
] |]
|
||||
{matchStatus = 200}
|
||||
|
||||
@@ -45,7 +45,7 @@ spec = around withApp $ do
|
||||
|
||||
request methodGet "/" [auth] ""
|
||||
`shouldRespondWith` [json| [
|
||||
{"schema":"1","name":"authors_only","insertable":true}
|
||||
{"schema":"test","name":"authors_only","insertable":true}
|
||||
] |]
|
||||
{matchStatus = 200}
|
||||
|
||||
@@ -61,7 +61,7 @@ spec = around withApp $ do
|
||||
"default": null,
|
||||
"precision": 32,
|
||||
"updatable": true,
|
||||
"schema": "1",
|
||||
"schema": "test",
|
||||
"name": "integer",
|
||||
"type": "integer",
|
||||
"maxLen": null,
|
||||
@@ -74,7 +74,7 @@ spec = around withApp $ do
|
||||
"default": null,
|
||||
"precision": 53,
|
||||
"updatable": true,
|
||||
"schema": "1",
|
||||
"schema": "test",
|
||||
"name": "double",
|
||||
"type": "double precision",
|
||||
"maxLen": null,
|
||||
@@ -86,7 +86,7 @@ spec = around withApp $ do
|
||||
"default": null,
|
||||
"precision": null,
|
||||
"updatable": true,
|
||||
"schema": "1",
|
||||
"schema": "test",
|
||||
"name": "varchar",
|
||||
"type": "character varying",
|
||||
"maxLen": null,
|
||||
@@ -99,7 +99,7 @@ spec = around withApp $ do
|
||||
"default": null,
|
||||
"precision": null,
|
||||
"updatable": true,
|
||||
"schema": "1",
|
||||
"schema": "test",
|
||||
"name": "boolean",
|
||||
"type": "boolean",
|
||||
"maxLen": null,
|
||||
@@ -111,7 +111,7 @@ spec = around withApp $ do
|
||||
"default": null,
|
||||
"precision": null,
|
||||
"updatable": true,
|
||||
"schema": "1",
|
||||
"schema": "test",
|
||||
"name": "date",
|
||||
"type": "date",
|
||||
"maxLen": null,
|
||||
@@ -123,7 +123,7 @@ spec = around withApp $ do
|
||||
"default": null,
|
||||
"precision": null,
|
||||
"updatable": true,
|
||||
"schema": "1",
|
||||
"schema": "test",
|
||||
"name": "money",
|
||||
"type": "money",
|
||||
"maxLen": null,
|
||||
@@ -136,7 +136,7 @@ spec = around withApp $ do
|
||||
"default": null,
|
||||
"precision": null,
|
||||
"updatable": true,
|
||||
"schema": "1",
|
||||
"schema": "test",
|
||||
"name": "enum",
|
||||
"type": "USER-DEFINED",
|
||||
"maxLen": null,
|
||||
@@ -166,7 +166,7 @@ spec = around withApp $ do
|
||||
"default":null,
|
||||
"precision":64,
|
||||
"updatable":false,
|
||||
"schema":"1",
|
||||
"schema":"test",
|
||||
"name":"id",
|
||||
"type":"bigint",
|
||||
"maxLen":null,
|
||||
@@ -182,7 +182,7 @@ spec = around withApp $ do
|
||||
"default":null,
|
||||
"precision":32,
|
||||
"updatable":false,
|
||||
"schema":"1",
|
||||
"schema":"test",
|
||||
"name":"auto_inc_fk",
|
||||
"type":"integer",
|
||||
"maxLen":null,
|
||||
@@ -198,7 +198,7 @@ spec = around withApp $ do
|
||||
"default":null,
|
||||
"precision":null,
|
||||
"updatable":false,
|
||||
"schema":"1",
|
||||
"schema":"test",
|
||||
"name":"simple_fk",
|
||||
"type":"character varying",
|
||||
"maxLen":255,
|
||||
@@ -211,7 +211,7 @@ spec = around withApp $ do
|
||||
"default":null,
|
||||
"precision":null,
|
||||
"updatable":false,
|
||||
"schema":"1",
|
||||
"schema":"test",
|
||||
"name":"nullable_string",
|
||||
"type":"character varying",
|
||||
"maxLen":null,
|
||||
@@ -224,7 +224,7 @@ spec = around withApp $ do
|
||||
"default":null,
|
||||
"precision":null,
|
||||
"updatable":false,
|
||||
"schema":"1",
|
||||
"schema":"test",
|
||||
"name":"non_nullable_string",
|
||||
"type":"character varying",
|
||||
"maxLen":null,
|
||||
@@ -237,7 +237,7 @@ spec = around withApp $ do
|
||||
"default":null,
|
||||
"precision":null,
|
||||
"updatable":false,
|
||||
"schema":"1",
|
||||
"schema":"test",
|
||||
"name":"inserted_at",
|
||||
"type":"timestamp with time zone",
|
||||
"maxLen":null,
|
||||
@@ -261,7 +261,7 @@ spec = around withApp $ do
|
||||
"default": "nextval('\"1\".has_fk_id_seq'::regclass)",
|
||||
"precision": 64,
|
||||
"updatable": true,
|
||||
"schema": "1",
|
||||
"schema": "test",
|
||||
"name": "id",
|
||||
"type": "bigint",
|
||||
"maxLen": null,
|
||||
@@ -273,7 +273,7 @@ spec = around withApp $ do
|
||||
"default": null,
|
||||
"precision": 32,
|
||||
"updatable": true,
|
||||
"schema": "1",
|
||||
"schema": "test",
|
||||
"name": "auto_inc_fk",
|
||||
"type": "integer",
|
||||
"maxLen": null,
|
||||
@@ -285,7 +285,7 @@ spec = around withApp $ do
|
||||
"default": null,
|
||||
"precision": null,
|
||||
"updatable": true,
|
||||
"schema": "1",
|
||||
"schema": "test",
|
||||
"name": "simple_fk",
|
||||
"type": "character varying",
|
||||
"maxLen": 255,
|
||||
|
||||
+13
-13
@@ -38,7 +38,7 @@ isLeft (Left _ ) = True
|
||||
isLeft _ = False
|
||||
|
||||
cfg :: AppConfig
|
||||
cfg = AppConfig "postgrest_test" 5432 "postgrest_test" "" "localhost" 3000 "postgrest_anonymous" False 10 "1" "safe"
|
||||
cfg = AppConfig "postgrest_test" 5432 "postgrest_test" "" "localhost" 3000 "postgrest_anonymous" False 10 "test" "safe"
|
||||
|
||||
testPoolOpts :: PoolSettings
|
||||
testPoolOpts = fromMaybe (error "bad settings") $ H.poolSettings 1 30
|
||||
@@ -66,7 +66,7 @@ withApp perform = do
|
||||
dbstructure <- case metadata of
|
||||
Left e -> fail $ show e
|
||||
Right (tabs, rels, cols, keys) ->
|
||||
return $ DbStructure {
|
||||
return DbStructure {
|
||||
tables=tabs
|
||||
, columns=cols
|
||||
, relations=rels
|
||||
@@ -88,7 +88,7 @@ resetDb = do
|
||||
<- H.acquirePool pgSettings testPoolOpts
|
||||
void . liftIO $ H.session pool $
|
||||
H.tx Nothing $ do
|
||||
H.unitEx [H.stmt| drop schema if exists "1" cascade |]
|
||||
H.unitEx [H.stmt| drop schema if exists test cascade |]
|
||||
H.unitEx [H.stmt| drop schema if exists private cascade |]
|
||||
H.unitEx [H.stmt| drop schema if exists postgrest cascade |]
|
||||
|
||||
@@ -129,7 +129,7 @@ clearTable :: Text -> IO ()
|
||||
clearTable table = do
|
||||
pool <- testPool
|
||||
void . liftIO $ H.session pool $ H.tx Nothing $
|
||||
H.unitEx $ B.Stmt ("delete from \"1\"."<>table) V.empty True
|
||||
H.unitEx $ B.Stmt ("delete from test."<>table) V.empty True
|
||||
|
||||
createItems :: Int -> IO ()
|
||||
createItems n = do
|
||||
@@ -137,7 +137,7 @@ createItems n = do
|
||||
void . liftIO $ H.session pool $ H.tx Nothing txn
|
||||
where
|
||||
txn = mapM_ H.unitEx stmts
|
||||
stmts = map [H.stmt|insert into "1".items (id) values (?)|] [1..n]
|
||||
stmts = map [H.stmt|insert into test.items (id) values (?)|] [1..n]
|
||||
|
||||
createComplexItems :: IO ()
|
||||
createComplexItems = do
|
||||
@@ -145,11 +145,11 @@ createComplexItems = do
|
||||
void . liftIO $ H.session pool $ H.tx Nothing txn
|
||||
where
|
||||
txn = mapM_ H.unitEx stmts
|
||||
stmts = getZipList $ [H.stmt|insert into "1".complex_items (id, name, settings) values (?,?,?)|]
|
||||
stmts = getZipList $ [H.stmt|insert into test.complex_items (id, name, settings) values (?,?,?)|]
|
||||
<$> ZipList ([1..3]::[Int])
|
||||
<*> ZipList (["One", "Two", "Three"]::[Text])
|
||||
<*> ZipList ([jobj,jobj,jobj])
|
||||
jobj = (J.object [("foo", J.object [("int", J.Number 1),("bar", J.String "baz")])])
|
||||
<*> ZipList [jobj,jobj,jobj]
|
||||
jobj = J.object [("foo", J.object [("int", J.Number 1),("bar", J.String "baz")])]
|
||||
|
||||
createNulls :: Int -> IO ()
|
||||
createNulls n = do
|
||||
@@ -157,14 +157,14 @@ createNulls n = do
|
||||
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]
|
||||
stmt' = [H.stmt|insert into test.no_pk (a,b) values (null,null)|]
|
||||
stmts = map [H.stmt|insert into test.no_pk (a,b) values (?,0)|] [1..n]
|
||||
|
||||
createNullInteger :: IO ()
|
||||
createNullInteger = do
|
||||
pool <- testPool
|
||||
void . liftIO $ H.session pool $ H.tx Nothing $
|
||||
H.unitEx $ [H.stmt| insert into "1".nullable_integer (a) values (null) |]
|
||||
H.unitEx $ [H.stmt| insert into "test".nullable_integer (a) values (null) |]
|
||||
|
||||
createLikableStrings :: IO ()
|
||||
createLikableStrings = do
|
||||
@@ -174,7 +174,7 @@ createLikableStrings = do
|
||||
H.unitEx $ insertSimplePk "xYYx" "v"
|
||||
where
|
||||
insertSimplePk :: Text -> Text -> H.Stmt P.Postgres
|
||||
insertSimplePk = [H.stmt|insert into "1".simple_pk (k, extra) values (?,?)|]
|
||||
insertSimplePk = [H.stmt|insert into test.simple_pk (k, extra) values (?,?)|]
|
||||
|
||||
createJsonData :: IO ()
|
||||
createJsonData = do
|
||||
@@ -182,6 +182,6 @@ createJsonData = do
|
||||
void . liftIO $ H.session pool $ H.tx Nothing $
|
||||
H.unitEx $
|
||||
[H.stmt|
|
||||
insert into "1".json (data) values (?)
|
||||
insert into test.json (data) values (?)
|
||||
|]
|
||||
(J.object [("foo", J.object [("bar", J.String "baz")])])
|
||||
|
||||
@@ -32,7 +32,7 @@ spec = around dbWithSchema $ do
|
||||
describe "insert" $
|
||||
describe "with an auto-increment key" $ do
|
||||
it "inserts and responds with a full object description" $ \conn -> do
|
||||
r <- insert "1" "auto_incrementing_pk" (SqlRow [
|
||||
r <- insert "test" "auto_incrementing_pk" (SqlRow [
|
||||
("non_nullable_string", toSql ("a string"::String))]) conn
|
||||
let returnRow = incFromList . toList $ r
|
||||
incStr returnRow `shouldBe` "a string"
|
||||
@@ -43,19 +43,19 @@ spec = around dbWithSchema $ do
|
||||
[returnRow] `shouldBe` map incFromList tRows
|
||||
|
||||
it "throws an exception if the PK is not unique" $ \conn -> do
|
||||
r <- insert "1" "auto_incrementing_pk" (SqlRow [
|
||||
r <- insert "test" "auto_incrementing_pk" (SqlRow [
|
||||
("non_nullable_string", toSql ("a string"::String))]) conn
|
||||
let row = SqlRow . map (Control.Arrow.first cs) . toList $ r
|
||||
insert "1" "auto_incrementing_pk" row conn `shouldThrow` \e ->
|
||||
insert "test" "auto_incrementing_pk" row conn `shouldThrow` \e ->
|
||||
seState e == "23505" -- uniqueness violation code
|
||||
|
||||
it "throws an exception if a required value is missing" $ \conn ->
|
||||
insert "1" "auto_incrementing_pk" (SqlRow [
|
||||
insert "test" "auto_incrementing_pk" (SqlRow [
|
||||
("nullable_string", toSql ("a string"::String))]) conn
|
||||
`shouldThrow` \e -> seState e == "23502"
|
||||
|
||||
it "generates a default values query if no data is provided" $ \c -> do
|
||||
r <- insert "1" "items" (SqlRow []) c
|
||||
r <- insert "test" "items" (SqlRow []) c
|
||||
let [row] = toList r
|
||||
quickALQuery c "select * from \"1\".items where id = ?" [snd row]
|
||||
`shouldReturn` [[row]]
|
||||
|
||||
@@ -12,25 +12,25 @@ spec :: Spec
|
||||
spec = around dbWithSchema $ beforeWith setRole $ do
|
||||
describe "tables" $
|
||||
it "shows all the tables" $ \conn -> do
|
||||
ts <- tables "1" conn
|
||||
ts <- tables "test" conn
|
||||
map tableName ts `shouldBe` ["authors_only","auto_incrementing_pk",
|
||||
"compound_pk","has_fk","insertable_view_with_join","items","menagerie","no_pk", "simple_pk"]
|
||||
|
||||
describe "columns" $ do
|
||||
it "responds with each column for the table" $ \conn -> do
|
||||
cs <- columns "1" "auto_incrementing_pk" conn
|
||||
cs <- columns "test" "auto_incrementing_pk" conn
|
||||
map colName cs `shouldBe` ["id","nullable_string","non_nullable_string",
|
||||
"inserted_at"]
|
||||
|
||||
it "includes foreign key data" $ \conn -> do
|
||||
cs <- columns "1" "has_fk" conn
|
||||
cs <- columns "test" "has_fk" conn
|
||||
map colFK cs `shouldBe` [Nothing,
|
||||
Just $ ForeignKey "auto_incrementing_pk" "id",
|
||||
Just $ ForeignKey "simple_pk" "k"]
|
||||
|
||||
describe "foreignKeys" $
|
||||
it "has a description of the foreign key columns" $ \conn ->
|
||||
foreignKeys "1" "has_fk" conn `shouldReturn` M.fromList [
|
||||
foreignKeys "test" "has_fk" conn `shouldReturn` M.fromList [
|
||||
("auto_inc_fk", ForeignKey {fkTable="auto_incrementing_pk", fkCol="id"}),
|
||||
("simple_fk", ForeignKey { fkTable="simple_pk", fkCol="k"})]
|
||||
|
||||
|
||||
Vendored
+58
-58
@@ -5,10 +5,10 @@ SET check_function_bodies = false;
|
||||
SET client_min_messages = warning;
|
||||
|
||||
|
||||
CREATE SCHEMA "1";
|
||||
CREATE SCHEMA test;
|
||||
|
||||
|
||||
ALTER SCHEMA "1" OWNER TO postgrest_test;
|
||||
ALTER SCHEMA test OWNER TO postgrest_test;
|
||||
|
||||
|
||||
CREATE SCHEMA postgrest;
|
||||
@@ -30,7 +30,7 @@ CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
|
||||
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
|
||||
|
||||
|
||||
SET search_path = "1", pg_catalog;
|
||||
SET search_path = test, pg_catalog;
|
||||
|
||||
|
||||
CREATE TYPE enum_menagerie_type AS ENUM (
|
||||
@@ -39,7 +39,7 @@ CREATE TYPE enum_menagerie_type AS ENUM (
|
||||
);
|
||||
|
||||
|
||||
ALTER TYPE "1".enum_menagerie_type OWNER TO postgrest_test;
|
||||
ALTER TYPE test.enum_menagerie_type OWNER TO postgrest_test;
|
||||
|
||||
SET search_path = postgrest, pg_catalog;
|
||||
|
||||
@@ -83,18 +83,18 @@ $$;
|
||||
|
||||
ALTER FUNCTION postgrest.set_authors_only_owner() OWNER TO postgrest_test;
|
||||
|
||||
CREATE FUNCTION "1".insert_insertable_view_with_join() RETURNS trigger
|
||||
CREATE FUNCTION test.insert_insertable_view_with_join() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
begin
|
||||
INSERT INTO "1".auto_incrementing_pk (nullable_string, non_nullable_string) VALUES (NEW.nullable_string, NEW.non_nullable_string);
|
||||
INSERT INTO test.auto_incrementing_pk (nullable_string, non_nullable_string) VALUES (NEW.nullable_string, NEW.non_nullable_string);
|
||||
RETURN NEW;
|
||||
end;
|
||||
$$;
|
||||
|
||||
ALTER FUNCTION "1".insert_insertable_view_with_join() OWNER TO postgrest_test;
|
||||
ALTER FUNCTION test.insert_insertable_view_with_join() OWNER TO postgrest_test;
|
||||
|
||||
SET search_path = "1", pg_catalog;
|
||||
SET search_path = test, pg_catalog;
|
||||
|
||||
SET default_tablespace = '';
|
||||
|
||||
@@ -107,7 +107,7 @@ CREATE TABLE authors_only (
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE "1".authors_only OWNER TO postgrest_test_author;
|
||||
ALTER TABLE test.authors_only OWNER TO postgrest_test_author;
|
||||
|
||||
|
||||
CREATE TABLE auto_incrementing_pk (
|
||||
@@ -118,7 +118,7 @@ CREATE TABLE auto_incrementing_pk (
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE "1".auto_incrementing_pk OWNER TO postgrest_test;
|
||||
ALTER TABLE test.auto_incrementing_pk OWNER TO postgrest_test;
|
||||
|
||||
|
||||
CREATE SEQUENCE auto_incrementing_pk_id_seq
|
||||
@@ -129,7 +129,7 @@ CREATE SEQUENCE auto_incrementing_pk_id_seq
|
||||
CACHE 1;
|
||||
|
||||
|
||||
ALTER TABLE "1".auto_incrementing_pk_id_seq OWNER TO postgrest_test;
|
||||
ALTER TABLE test.auto_incrementing_pk_id_seq OWNER TO postgrest_test;
|
||||
|
||||
|
||||
ALTER SEQUENCE auto_incrementing_pk_id_seq OWNED BY auto_incrementing_pk.id;
|
||||
@@ -143,7 +143,7 @@ CREATE TABLE compound_pk (
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE "1".compound_pk OWNER TO postgrest_test;
|
||||
ALTER TABLE test.compound_pk OWNER TO postgrest_test;
|
||||
|
||||
|
||||
CREATE TABLE has_fk (
|
||||
@@ -153,7 +153,7 @@ CREATE TABLE has_fk (
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE "1".has_fk OWNER TO postgrest_test;
|
||||
ALTER TABLE test.has_fk OWNER TO postgrest_test;
|
||||
|
||||
|
||||
CREATE SEQUENCE has_fk_id_seq
|
||||
@@ -164,18 +164,18 @@ CREATE SEQUENCE has_fk_id_seq
|
||||
CACHE 1;
|
||||
|
||||
|
||||
ALTER TABLE "1".has_fk_id_seq OWNER TO postgrest_test;
|
||||
ALTER TABLE test.has_fk_id_seq OWNER TO postgrest_test;
|
||||
|
||||
|
||||
ALTER SEQUENCE has_fk_id_seq OWNED BY has_fk.id;
|
||||
|
||||
CREATE MATERIALIZED VIEW "1".materialized_view AS
|
||||
CREATE MATERIALIZED VIEW test.materialized_view AS
|
||||
SELECT
|
||||
version();
|
||||
|
||||
ALTER TABLE "1".materialized_view OWNER TO postgrest_test;
|
||||
ALTER TABLE test.materialized_view OWNER TO postgrest_test;
|
||||
|
||||
CREATE VIEW "1".insertable_view_with_join AS
|
||||
CREATE VIEW test.insertable_view_with_join AS
|
||||
SELECT has_fk.id,
|
||||
has_fk.auto_inc_fk,
|
||||
has_fk.simple_fk,
|
||||
@@ -186,12 +186,12 @@ CREATE VIEW "1".insertable_view_with_join AS
|
||||
JOIN auto_incrementing_pk USING (id));
|
||||
|
||||
|
||||
ALTER TABLE "1".insertable_view_with_join OWNER TO postgrest_test;
|
||||
ALTER TABLE test.insertable_view_with_join OWNER TO postgrest_test;
|
||||
|
||||
CREATE VIEW "1".has_count_column AS
|
||||
CREATE VIEW test.has_count_column AS
|
||||
SELECT 1 AS count;
|
||||
|
||||
ALTER TABLE "1".insertable_view_with_join OWNER TO postgrest_test;
|
||||
ALTER TABLE test.insertable_view_with_join OWNER TO postgrest_test;
|
||||
|
||||
|
||||
CREATE TABLE items (
|
||||
@@ -199,7 +199,7 @@ CREATE TABLE items (
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE "1".items OWNER TO postgrest_test;
|
||||
ALTER TABLE test.items OWNER TO postgrest_test;
|
||||
|
||||
CREATE TABLE complex_items (
|
||||
id bigint NOT NULL,
|
||||
@@ -208,41 +208,41 @@ CREATE TABLE complex_items (
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE "1".complex_items OWNER TO postgrest_test;
|
||||
ALTER TABLE test.complex_items OWNER TO postgrest_test;
|
||||
|
||||
--- Structure for testing table relations
|
||||
CREATE TABLE clients(
|
||||
id INT PRIMARY KEY NOT NULL,
|
||||
name TEXT NOT NULL
|
||||
);
|
||||
ALTER TABLE "1".clients OWNER TO postgrest_test;
|
||||
ALTER TABLE test.clients OWNER TO postgrest_test;
|
||||
|
||||
CREATE TABLE projects(
|
||||
id INT PRIMARY KEY NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
client_id INT REFERENCES clients(id)
|
||||
);
|
||||
ALTER TABLE "1".projects OWNER TO postgrest_test;
|
||||
ALTER TABLE test.projects OWNER TO postgrest_test;
|
||||
|
||||
CREATE TABLE tasks(
|
||||
id INT PRIMARY KEY NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
project_id INT REFERENCES projects(id)
|
||||
);
|
||||
ALTER TABLE "1".tasks OWNER TO postgrest_test;
|
||||
ALTER TABLE test.tasks OWNER TO postgrest_test;
|
||||
|
||||
CREATE TABLE users(
|
||||
id INT PRIMARY KEY NOT NULL,
|
||||
name TEXT NOT NULL
|
||||
);
|
||||
ALTER TABLE "1".users OWNER TO postgrest_test;
|
||||
ALTER TABLE test.users OWNER TO postgrest_test;
|
||||
|
||||
CREATE TABLE users_tasks(
|
||||
user_id INT REFERENCES users(id),
|
||||
task_id INT REFERENCES tasks(id),
|
||||
CONSTRAINT task_user PRIMARY KEY (task_id,user_id)
|
||||
);
|
||||
ALTER TABLE "1".users_tasks OWNER TO postgrest_test;
|
||||
ALTER TABLE test.users_tasks OWNER TO postgrest_test;
|
||||
|
||||
CREATE TABLE comments(
|
||||
id INT PRIMARY KEY NOT NULL,
|
||||
@@ -252,22 +252,22 @@ task_id INT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
FOREIGN KEY (task_id,user_id) REFERENCES users_tasks (task_id,user_id)
|
||||
);
|
||||
ALTER TABLE "1".comments OWNER TO postgrest_test;
|
||||
ALTER TABLE test.comments OWNER TO postgrest_test;
|
||||
|
||||
CREATE TABLE users_projects(
|
||||
user_id INT REFERENCES users(id),
|
||||
project_id INT REFERENCES projects(id),
|
||||
CONSTRAINT project_user PRIMARY KEY (project_id, user_id)
|
||||
);
|
||||
ALTER TABLE "1".users_projects OWNER TO postgrest_test;
|
||||
ALTER TABLE test.users_projects OWNER TO postgrest_test;
|
||||
|
||||
CREATE VIEW "1".projects_view AS
|
||||
CREATE VIEW test.projects_view AS
|
||||
SELECT
|
||||
projects.id,
|
||||
projects.name,
|
||||
projects.client_id
|
||||
FROM projects;
|
||||
ALTER TABLE "1".projects_view OWNER TO postgrest_test;
|
||||
ALTER TABLE test.projects_view OWNER TO postgrest_test;
|
||||
------- SAMPLE DATA -----
|
||||
INSERT INTO clients VALUES (1, 'Microsoft'),(2, 'Apple');
|
||||
INSERT INTO projects VALUES (1,'Windows 7', 1),(2,'Windows 10', 1),(3,'IOS', 2),(4,'OSX', 2);
|
||||
@@ -286,25 +286,25 @@ CREATE SEQUENCE items_id_seq
|
||||
CACHE 1;
|
||||
|
||||
|
||||
ALTER TABLE "1".items_id_seq OWNER TO postgrest_test;
|
||||
ALTER TABLE test.items_id_seq OWNER TO postgrest_test;
|
||||
|
||||
|
||||
ALTER SEQUENCE items_id_seq OWNED BY items.id;
|
||||
|
||||
|
||||
|
||||
CREATE FUNCTION "1".getitemrange(min bigint, max bigint) RETURNS SETOF "1".items AS $$
|
||||
SELECT * FROM "1".items WHERE id > $1 AND id <= $2;
|
||||
CREATE FUNCTION test.getitemrange(min bigint, max bigint) RETURNS SETOF test.items AS $$
|
||||
SELECT * FROM test.items WHERE id > $1 AND id <= $2;
|
||||
$$ LANGUAGE SQL;
|
||||
|
||||
|
||||
|
||||
CREATE FUNCTION "1".sayhello(name text) RETURNS text AS $$
|
||||
CREATE FUNCTION test.sayhello(name text) RETURNS text AS $$
|
||||
SELECT 'Hello, ' || $1;
|
||||
$$ LANGUAGE SQL;
|
||||
|
||||
|
||||
CREATE FUNCTION "1".problem() RETURNS void LANGUAGE plpgsql AS
|
||||
CREATE FUNCTION test.problem() RETURNS void LANGUAGE plpgsql AS
|
||||
$$
|
||||
BEGIN
|
||||
RAISE 'bad thing';
|
||||
@@ -323,7 +323,7 @@ CREATE TABLE menagerie (
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE "1".menagerie OWNER TO postgrest_test;
|
||||
ALTER TABLE test.menagerie OWNER TO postgrest_test;
|
||||
|
||||
|
||||
CREATE TABLE no_pk (
|
||||
@@ -332,7 +332,7 @@ CREATE TABLE no_pk (
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE "1".no_pk OWNER TO postgrest_test;
|
||||
ALTER TABLE test.no_pk OWNER TO postgrest_test;
|
||||
|
||||
|
||||
CREATE TABLE nullable_integer (
|
||||
@@ -340,7 +340,7 @@ CREATE TABLE nullable_integer (
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE "1".nullable_integer OWNER TO postgrest_test;
|
||||
ALTER TABLE test.nullable_integer OWNER TO postgrest_test;
|
||||
|
||||
|
||||
CREATE TABLE simple_pk (
|
||||
@@ -349,7 +349,7 @@ CREATE TABLE simple_pk (
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE "1".simple_pk OWNER TO postgrest_test;
|
||||
ALTER TABLE test.simple_pk OWNER TO postgrest_test;
|
||||
|
||||
|
||||
CREATE TABLE json
|
||||
@@ -358,14 +358,14 @@ CREATE TABLE json
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE "1".json OWNER TO postgrest_test;
|
||||
ALTER TABLE test.json OWNER TO postgrest_test;
|
||||
|
||||
|
||||
CREATE TABLE tsearch (
|
||||
text_search_vector tsvector
|
||||
);
|
||||
|
||||
ALTER TABLE "1".tsearch OWNER TO postgrest_test;
|
||||
ALTER TABLE test.tsearch OWNER TO postgrest_test;
|
||||
|
||||
SET search_path = postgrest, pg_catalog;
|
||||
|
||||
@@ -406,7 +406,7 @@ ALTER TABLE private.articles_id_seq OWNER TO postgrest_test;
|
||||
ALTER SEQUENCE articles_id_seq OWNED BY articles.id;
|
||||
|
||||
|
||||
SET search_path = "1", pg_catalog;
|
||||
SET search_path = test, pg_catalog;
|
||||
|
||||
|
||||
ALTER TABLE ONLY auto_incrementing_pk ALTER COLUMN id SET DEFAULT nextval('auto_incrementing_pk_id_seq'::regclass);
|
||||
@@ -426,7 +426,7 @@ SET search_path = private, pg_catalog;
|
||||
ALTER TABLE ONLY articles ALTER COLUMN id SET DEFAULT nextval('articles_id_seq'::regclass);
|
||||
|
||||
|
||||
SET search_path = "1", pg_catalog;
|
||||
SET search_path = test, pg_catalog;
|
||||
|
||||
|
||||
|
||||
@@ -471,20 +471,20 @@ SET search_path = private, pg_catalog;
|
||||
SELECT pg_catalog.setval('articles_id_seq', 1, false);
|
||||
|
||||
|
||||
SET search_path = "1", pg_catalog;
|
||||
SET search_path = test, pg_catalog;
|
||||
|
||||
CREATE FUNCTION public.always_true("1".items) RETURNS boolean
|
||||
CREATE FUNCTION public.always_true(test.items) RETURNS boolean
|
||||
LANGUAGE sql STABLE
|
||||
AS $$ SELECT true $$;
|
||||
|
||||
ALTER FUNCTION public.always_true("1".items) OWNER TO postgrest_test;
|
||||
ALTER FUNCTION public.always_true(test.items) OWNER TO postgrest_test;
|
||||
|
||||
|
||||
|
||||
ALTER TABLE ONLY authors_only
|
||||
ADD CONSTRAINT authors_only_pkey PRIMARY KEY (secret);
|
||||
|
||||
CREATE TRIGGER insert_insertable_view_with_join INSTEAD OF INSERT ON "1".insertable_view_with_join FOR EACH ROW EXECUTE PROCEDURE "1".insert_insertable_view_with_join();
|
||||
CREATE TRIGGER insert_insertable_view_with_join INSTEAD OF INSERT ON test.insertable_view_with_join FOR EACH ROW EXECUTE PROCEDURE test.insert_insertable_view_with_join();
|
||||
|
||||
|
||||
CREATE TRIGGER secrets_owner_track BEFORE INSERT OR UPDATE ON authors_only FOR EACH ROW EXECUTE PROCEDURE postgrest.set_authors_only_owner();
|
||||
@@ -547,7 +547,7 @@ SET search_path = private, pg_catalog;
|
||||
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;
|
||||
SET search_path = test, pg_catalog;
|
||||
|
||||
|
||||
ALTER TABLE ONLY has_fk
|
||||
@@ -560,11 +560,11 @@ ALTER TABLE ONLY has_fk
|
||||
|
||||
|
||||
|
||||
REVOKE ALL ON SCHEMA "1" FROM PUBLIC;
|
||||
REVOKE ALL ON SCHEMA "1" FROM postgrest_test;
|
||||
GRANT ALL ON SCHEMA "1" TO postgrest_test;
|
||||
GRANT USAGE ON SCHEMA "1" TO postgrest_anonymous;
|
||||
GRANT USAGE ON SCHEMA "1" TO postgrest_test_author;
|
||||
REVOKE ALL ON SCHEMA test FROM PUBLIC;
|
||||
REVOKE ALL ON SCHEMA test FROM postgrest_test;
|
||||
GRANT ALL ON SCHEMA test TO postgrest_test;
|
||||
GRANT USAGE ON SCHEMA test TO postgrest_anonymous;
|
||||
GRANT USAGE ON SCHEMA test TO postgrest_test_author;
|
||||
|
||||
|
||||
|
||||
@@ -737,10 +737,10 @@ REVOKE ALL ON TABLE has_count_column FROM postgrest_test;
|
||||
GRANT ALL ON TABLE has_count_column TO postgrest_test;
|
||||
GRANT ALL ON TABLE has_count_column TO postgrest_anonymous;
|
||||
|
||||
REVOKE ALL ON FUNCTION public.always_true("1".items) FROM PUBLIC;
|
||||
REVOKE ALL ON FUNCTION public.always_true("1".items) FROM postgrest_test;
|
||||
GRANT ALL ON FUNCTION public.always_true("1".items) TO postgrest_test;
|
||||
GRANT ALL ON FUNCTION public.always_true("1".items) TO postgrest_anonymous;
|
||||
REVOKE ALL ON FUNCTION public.always_true(test.items) FROM PUBLIC;
|
||||
REVOKE ALL ON FUNCTION public.always_true(test.items) FROM postgrest_test;
|
||||
GRANT ALL ON FUNCTION public.always_true(test.items) TO postgrest_test;
|
||||
GRANT ALL ON FUNCTION public.always_true(test.items) TO postgrest_anonymous;
|
||||
|
||||
|
||||
SET search_path = postgrest, pg_catalog;
|
||||
|
||||
Reference in New Issue
Block a user