From e201c5bd3197c51eaa0ee8e903ce7d827254358b Mon Sep 17 00:00:00 2001 From: Wolfgang Walther Date: Sat, 27 Nov 2021 23:15:34 +0100 Subject: [PATCH] feat: drop support for pg 9.6 --- .github/workflows/ci.yaml | 2 +- CHANGELOG.md | 1 + default.nix | 1 - nix/README.md | 4 +- src/PostgREST/App.hs | 17 +- src/PostgREST/CLI.hs | 2 - src/PostgREST/Config/PgVersion.hs | 6 +- src/PostgREST/DbStructure.hs | 26 ++- src/PostgREST/Workers.hs | 3 +- test/spec/Feature/OpenApi/OpenApiSpec.hs | 36 ++-- test/spec/Feature/OptionsSpec.hs | 26 ++- test/spec/Feature/Query/RpcSpec.hs | 200 +++++++++-------------- test/spec/Main.hs | 6 +- test/spec/fixtures/data.sql | 12 +- test/spec/fixtures/privileges.sql | 9 +- test/spec/fixtures/schema.sql | 51 +++--- 16 files changed, 159 insertions(+), 243 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2958bc5f60b..2fd80e84eaf 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -61,7 +61,7 @@ jobs: strategy: fail-fast: false matrix: - pgVersion: [9.6, 10, 11, 12, 13, 14] + pgVersion: [10, 11, 12, 13, 14] name: Test PG ${{ matrix.pgVersion }} (Nix) runs-on: ubuntu-latest defaults: diff --git a/CHANGELOG.md b/CHANGELOG.md index e18e8c8d314..2df14523c9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - #2001, Return 204 No Content without Content-Type for RPCs returning VOID - @wolfgangwalther + Previously, those RPCs would return "null" as a body with Content-Type: application/json. + - #2052, Dropped support for PostgreSQL 9.6 - @wolfgangwalther ## [9.0.0] - 2021-11-25 diff --git a/default.nix b/default.nix index a484819a67f..6705095727f 100644 --- a/default.nix +++ b/default.nix @@ -51,7 +51,6 @@ let { name = "postgresql-12"; postgresql = pkgs.postgresql_12; } { name = "postgresql-11"; postgresql = pkgs.postgresql_11; } { name = "postgresql-10"; postgresql = pkgs.postgresql_10; } - { name = "postgresql-9.6"; postgresql = pkgs.postgresql_9_6; } ]; patches = diff --git a/nix/README.md b/nix/README.md index 0c44a7ad3b1..2568aef79d3 100644 --- a/nix/README.md +++ b/nix/README.md @@ -80,7 +80,7 @@ postgrest-coverage postgrest-with-postgresql-10 postgrest-lint postgrest-with-postgresql-11 postgrest-run postgrest-with-postgresql-12 postgrest-style postgrest-with-postgresql-13 -postgrest-style-check postgrest-with-postgresql-9.6 +postgrest-style-check postgrest-with-postgresql-14 postgrest-test-io ... @@ -104,7 +104,7 @@ postgrest-coverage postgrest-with-postgresql-10 postgrest-lint postgrest-with-postgresql-11 postgrest-run postgrest-with-postgresql-12 postgrest-style postgrest-with-postgresql-13 -postgrest-style-check postgrest-with-postgresql-9.6 +postgrest-style-check postgrest-with-postgresql-14 postgrest-test-io postgrest-test-memory ... diff --git a/src/PostgREST/App.hs b/src/PostgREST/App.hs index 6f527bd1de9..7934deb7917 100644 --- a/src/PostgREST/App.hs +++ b/src/PostgREST/App.hs @@ -96,7 +96,6 @@ data RequestContext = RequestContext { ctxConfig :: AppConfig , ctxDbStructure :: DbStructure , ctxApiRequest :: ApiRequest - , ctxPgVersion :: PgVersion } type Handler = ExceptT Error @@ -206,7 +205,7 @@ postgrestResponse conf@AppConfig{..} maybeDbStructure jsonDbS pgVer pool AuthRes liftEither . mapLeft Error.ApiRequestError $ ApiRequest.userApiRequest conf dbStructure req body - let handleReq apiReq = handleRequest $ RequestContext conf dbStructure apiReq pgVer + let handleReq apiReq = handleRequest $ RequestContext conf dbStructure apiReq runDbHandler pool (txMode apiRequest) (Just authRole /= configDbAnonRole) configDbPreparedStatements . Middleware.optionalRollback conf apiRequest $ @@ -225,7 +224,7 @@ runDbHandler pool mode authenticated prepared handler = do liftEither resp handleRequest :: RequestContext -> DbHandler Wai.Response -handleRequest context@(RequestContext _ _ ApiRequest{..} _) = +handleRequest context@(RequestContext _ _ ApiRequest{..}) = case (iAction, iTarget) of (ActionRead headersOnly, TargetIdent identifier) -> handleRead headersOnly identifier context @@ -345,7 +344,7 @@ handleCreate identifier@QualifiedIdentifier{..} context@RequestContext{..} = do response HTTP.status201 headers mempty handleUpdate :: QualifiedIdentifier -> RequestContext -> DbHandler Wai.Response -handleUpdate identifier context@(RequestContext _ _ ApiRequest{..} _) = do +handleUpdate identifier context@(RequestContext _ _ ApiRequest{..}) = do WriteQueryResult{..} <- writeQuery MutationUpdate identifier False mempty context let @@ -367,7 +366,7 @@ handleUpdate identifier context@(RequestContext _ _ ApiRequest{..} _) = do response status [contentRangeHeader] mempty handleSingleUpsert :: QualifiedIdentifier -> RequestContext-> DbHandler Wai.Response -handleSingleUpsert identifier context@(RequestContext _ _ ApiRequest{..} _) = do +handleSingleUpsert identifier context@(RequestContext _ _ ApiRequest{..}) = do when (iTopLevelRange /= RangeQuery.allRange) $ throwError Error.PutRangeNotAllowedError @@ -391,7 +390,7 @@ handleSingleUpsert identifier context@(RequestContext _ _ ApiRequest{..} _) = do response HTTP.status204 [] mempty handleDelete :: QualifiedIdentifier -> RequestContext -> DbHandler Wai.Response -handleDelete identifier context@(RequestContext _ _ ApiRequest{..} _) = do +handleDelete identifier context@(RequestContext _ _ ApiRequest{..}) = do WriteQueryResult{..} <- writeQuery MutationDelete identifier False mempty context let @@ -477,12 +476,12 @@ handleInvoke invMethod proc context@RequestContext{..} = do (if invMethod == InvHead then mempty else LBS.fromStrict body) handleOpenApi :: Bool -> Schema -> RequestContext -> DbHandler Wai.Response -handleOpenApi headersOnly tSchema (RequestContext conf@AppConfig{..} dbStructure apiRequest ctxPgVersion) = do +handleOpenApi headersOnly tSchema (RequestContext conf@AppConfig{..} dbStructure apiRequest) = do body <- lift $ case configOpenApiMode of OAFollowPriv -> OpenAPI.encode conf dbStructure - <$> SQL.statement tSchema (DbStructure.accessibleTables ctxPgVersion configDbPreparedStatements) + <$> SQL.statement tSchema (DbStructure.accessibleTables configDbPreparedStatements) <*> SQL.statement tSchema (DbStructure.accessibleProcs configDbPreparedStatements) <*> SQL.statement tSchema (DbStructure.schemaDescription configDbPreparedStatements) OAIgnorePriv -> @@ -584,7 +583,7 @@ returnsScalar (TargetProc proc _) = Proc.procReturnsScalar proc returnsScalar _ = False readRequest :: Monad m => QualifiedIdentifier -> RequestContext -> Handler m ReadRequest -readRequest QualifiedIdentifier{..} (RequestContext AppConfig{..} dbStructure apiRequest _) = +readRequest QualifiedIdentifier{..} (RequestContext AppConfig{..} dbStructure apiRequest) = liftEither $ ReqBuilder.readRequest qiSchema qiName configDbMaxRows (dbRelationships dbStructure) diff --git a/src/PostgREST/CLI.hs b/src/PostgREST/CLI.hs index 25cf05cdcca..86efbc3d745 100644 --- a/src/PostgREST/CLI.hs +++ b/src/PostgREST/CLI.hs @@ -53,7 +53,6 @@ main installSignalHandlers runAppWithSocket CLI{cliCommand, cliPath} = do dumpSchema :: AppState -> IO LBS.ByteString dumpSchema appState = do AppConfig{..} <- AppState.getConfig appState - actualPgVersion <- AppState.getPgVersion appState result <- let transaction = if configDbPreparedStatements then SQL.transaction else SQL.unpreparedTransaction in SQL.use (AppState.getPool appState) $ @@ -61,7 +60,6 @@ dumpSchema appState = do queryDbStructure (toList configDbSchemas) configDbExtraSearchPath - actualPgVersion configDbPreparedStatements SQL.release $ AppState.getPool appState case result of diff --git a/src/PostgREST/Config/PgVersion.hs b/src/PostgREST/Config/PgVersion.hs index 8aa37275264..122b33181f7 100644 --- a/src/PostgREST/Config/PgVersion.hs +++ b/src/PostgREST/Config/PgVersion.hs @@ -3,7 +3,6 @@ module PostgREST.Config.PgVersion ( PgVersion(..) , minimumPgVersion - , pgVersion96 , pgVersion100 , pgVersion109 , pgVersion110 @@ -30,10 +29,7 @@ instance Ord PgVersion where -- | Tells the minimum PostgreSQL version required by this version of PostgREST minimumPgVersion :: PgVersion -minimumPgVersion = pgVersion96 - -pgVersion96 :: PgVersion -pgVersion96 = PgVersion 90600 "9.6" +minimumPgVersion = pgVersion100 pgVersion100 :: PgVersion pgVersion100 = PgVersion 100000 "10" diff --git a/src/PostgREST/DbStructure.hs b/src/PostgREST/DbStructure.hs index 4c053995ae9..1c7651c7d81 100644 --- a/src/PostgREST/DbStructure.hs +++ b/src/PostgREST/DbStructure.hs @@ -41,7 +41,6 @@ import Data.Set as S (fromList) import Data.Text (split) import Text.InterpolatedString.Perl6 (q) -import PostgREST.Config.PgVersion (PgVersion, pgVersion100) import PostgREST.DbStructure.Identifiers (QualifiedIdentifier (..), Schema, TableName) import PostgREST.DbStructure.Proc (PgType (..), @@ -83,10 +82,10 @@ type ViewColumn = Column -- | A SQL query that can be executed independently type SqlQuery = ByteString -queryDbStructure :: [Schema] -> [Schema] -> PgVersion -> Bool -> SQL.Transaction DbStructure -queryDbStructure schemas extraSearchPath pgVer prepared = do +queryDbStructure :: [Schema] -> [Schema] -> Bool -> SQL.Transaction DbStructure +queryDbStructure schemas extraSearchPath prepared = do SQL.sql "set local schema ''" -- This voids the search path. The following queries need this for getting the fully qualified name(schema.name) of every db object - tabs <- SQL.statement mempty $ allTables pgVer prepared + tabs <- SQL.statement mempty $ allTables prepared cols <- SQL.statement schemas $ allColumns tabs prepared srcCols <- SQL.statement (schemas, extraSearchPath) $ pfkSourceColumns cols prepared m2oRels <- SQL.statement mempty $ allM2ORels tabs cols prepared @@ -316,8 +315,8 @@ schemaDescription = where n.nspname = $1 |] -accessibleTables :: PgVersion -> Bool -> SQL.Statement Schema [Table] -accessibleTables pgVer = +accessibleTables :: Bool -> SQL.Statement Schema [Table] +accessibleTables = SQL.Statement sql (param HE.text) decodeTables where sql = [q| @@ -355,8 +354,8 @@ accessibleTables pgVer = left join pg_catalog.pg_description as d on d.objoid = c.oid and d.objsubid = 0 where c.relkind in ('v','r','m','f','p') - and n.nspname = $1 |] - <> relIsNotPartition pgVer <> [q| + and n.nspname = $1 + and not c.relispartition and ( pg_has_role(c.relowner, 'USAGE') or has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER') @@ -451,8 +450,8 @@ addViewPrimaryKeys srcCols = concatMap (\pk -> filter (\(col, _) -> colTable col == pkTable pk && colName col == pkName pk) srcCols in pk : viewPks) -allTables :: PgVersion -> Bool -> SQL.Statement () [Table] -allTables pgVer = +allTables :: Bool -> SQL.Statement () [Table] +allTables = SQL.Statement sql HE.noParams decodeTables where sql = [q| @@ -490,13 +489,10 @@ allTables pgVer = JOIN pg_namespace n ON n.oid = c.relnamespace LEFT JOIN pg_catalog.pg_description as d on d.objoid = c.oid and d.objsubid = 0 WHERE c.relkind IN ('v','r','m','f','p') - AND n.nspname NOT IN ('pg_catalog', 'information_schema') |] - <> relIsNotPartition pgVer <> [q| + AND n.nspname NOT IN ('pg_catalog', 'information_schema') + AND NOT c.relispartition ORDER BY table_schema, table_name |] -relIsNotPartition :: PgVersion -> SqlQuery -relIsNotPartition pgVer = if pgVer >= pgVersion100 then " AND not c.relispartition " else mempty - allColumns :: [Table] -> Bool -> SQL.Statement [Schema] [Column] allColumns tabs = SQL.Statement sql (arrayParam HE.text) (decodeColumns tabs) diff --git a/src/PostgREST/Workers.hs b/src/PostgREST/Workers.hs index 5cdc5fd05a0..9f0597391fa 100644 --- a/src/PostgREST/Workers.hs +++ b/src/PostgREST/Workers.hs @@ -153,11 +153,10 @@ connectionStatus appState = loadSchemaCache :: AppState -> IO SCacheStatus loadSchemaCache appState = do AppConfig{..} <- AppState.getConfig appState - actualPgVersion <- AppState.getPgVersion appState result <- let transaction = if configDbPreparedStatements then SQL.transaction else SQL.unpreparedTransaction in SQL.use (AppState.getPool appState) . transaction SQL.ReadCommitted SQL.Read $ - queryDbStructure (toList configDbSchemas) configDbExtraSearchPath actualPgVersion configDbPreparedStatements + queryDbStructure (toList configDbSchemas) configDbExtraSearchPath configDbPreparedStatements case result of Left e -> do let diff --git a/test/spec/Feature/OpenApi/OpenApiSpec.hs b/test/spec/Feature/OpenApi/OpenApiSpec.hs index 3b4a5a94515..ec214944703 100644 --- a/test/spec/Feature/OpenApi/OpenApiSpec.hs +++ b/test/spec/Feature/OpenApi/OpenApiSpec.hs @@ -11,8 +11,7 @@ import Network.HTTP.Types import Test.Hspec hiding (pendingWith) import Test.Hspec.Wai -import PostgREST.Config.PgVersion (PgVersion, pgVersion100, - pgVersion110) +import PostgREST.Config.PgVersion (PgVersion, pgVersion110) import PostgREST.Version (docsVersion) import Protolude hiding (get) @@ -203,31 +202,30 @@ spec actualPgVersion = describe "OpenAPI" $ do ] |] - when (actualPgVersion >= pgVersion100) $ do - describe "Partitioned table" $ + describe "Partitioned table" $ - it "includes partitioned table properties" $ do - r <- simpleBody <$> get "/" + it "includes partitioned table properties" $ do + r <- simpleBody <$> get "/" - let method s = key "paths" . key "/car_models" . key s - getSummary = r ^? method "get" . key "summary" - getDescription = r ^? method "get" . key "description" - getParameterName = r ^? method "get" . key "parameters" . nth 0 . key "$ref" - getParameterYear = r ^? method "get" . key "parameters" . nth 1 . key "$ref" - getParameterRef = r ^? method "get" . key "parameters" . nth 2 . key "$ref" + let method s = key "paths" . key "/car_models" . key s + getSummary = r ^? method "get" . key "summary" + getDescription = r ^? method "get" . key "description" + getParameterName = r ^? method "get" . key "parameters" . nth 0 . key "$ref" + getParameterYear = r ^? method "get" . key "parameters" . nth 1 . key "$ref" + getParameterRef = r ^? method "get" . key "parameters" . nth 2 . key "$ref" - liftIO $ do + liftIO $ do - getSummary `shouldBe` Just "A partitioned table" + getSummary `shouldBe` Just "A partitioned table" - getDescription `shouldBe` Just "A test for partitioned tables" + getDescription `shouldBe` Just "A test for partitioned tables" - getParameterName `shouldBe` Just "#/parameters/rowFilter.car_models.name" + getParameterName `shouldBe` Just "#/parameters/rowFilter.car_models.name" - getParameterYear `shouldBe` Just "#/parameters/rowFilter.car_models.year" + getParameterYear `shouldBe` Just "#/parameters/rowFilter.car_models.year" - when (actualPgVersion >= pgVersion110) $ - getParameterRef `shouldBe` Just "#/parameters/rowFilter.car_models.car_brand_name" + when (actualPgVersion >= pgVersion110) $ + getParameterRef `shouldBe` Just "#/parameters/rowFilter.car_models.car_brand_name" describe "Materialized view" $ diff --git a/test/spec/Feature/OptionsSpec.hs b/test/spec/Feature/OptionsSpec.hs index e6bf9e35ff0..f2200ffc816 100644 --- a/test/spec/Feature/OptionsSpec.hs +++ b/test/spec/Feature/OptionsSpec.hs @@ -7,8 +7,7 @@ import Network.HTTP.Types import Test.Hspec import Test.Hspec.Wai -import PostgREST.Config.PgVersion (PgVersion, pgVersion100, - pgVersion110) +import PostgREST.Config.PgVersion (PgVersion, pgVersion110) import Protolude import SpecHelper @@ -22,18 +21,17 @@ spec actualPgVersion = describe "Allow header" $ do simpleHeaders r `shouldSatisfy` matchHeader "Allow" "OPTIONS,GET,HEAD,POST,PUT,PATCH,DELETE" - when (actualPgVersion >= pgVersion100) $ - context "a partitioned table" $ do - it "includes read/write verbs for writeable partitioned tables" $ do - r <- request methodOptions "/car_models" [] "" - liftIO $ - simpleHeaders r `shouldSatisfy` - matchHeader "Allow" ( - if actualPgVersion >= pgVersion110 then - "OPTIONS,GET,HEAD,POST,PUT,PATCH,DELETE" - else - "OPTIONS,GET,HEAD,POST,PATCH,DELETE" - ) + context "a partitioned table" $ do + it "includes read/write verbs for writeable partitioned tables" $ do + r <- request methodOptions "/car_models" [] "" + liftIO $ + simpleHeaders r `shouldSatisfy` + matchHeader "Allow" ( + if actualPgVersion >= pgVersion110 then + "OPTIONS,GET,HEAD,POST,PUT,PATCH,DELETE" + else + "OPTIONS,GET,HEAD,POST,PATCH,DELETE" + ) context "a view" $ do context "auto updatable" $ do diff --git a/test/spec/Feature/Query/RpcSpec.hs b/test/spec/Feature/Query/RpcSpec.hs index 77702f4df81..5ff8b144045 100644 --- a/test/spec/Feature/Query/RpcSpec.hs +++ b/test/spec/Feature/Query/RpcSpec.hs @@ -12,10 +12,9 @@ import Test.Hspec.Wai import Test.Hspec.Wai.JSON import Text.Heredoc -import PostgREST.Config.PgVersion (PgVersion, pgVersion100, - pgVersion109, pgVersion110, - pgVersion112, pgVersion114, - pgVersion140) +import PostgREST.Config.PgVersion (PgVersion, pgVersion109, + pgVersion110, pgVersion112, + pgVersion114, pgVersion140) import Protolude hiding (get) import SpecHelper @@ -359,66 +358,34 @@ spec actualPgVersion = { matchHeaders = [matchContentTypeJson] } context "proc argument types" $ do - -- different syntax for array needed for pg<10 - when (actualPgVersion < pgVersion100) $ - it "accepts a variety of arguments (Postgres < 10)" $ - post "/rpc/varied_arguments" - [json| { - "double": 3.1, - "varchar": "hello", - "boolean": true, - "date": "20190101", - "money": 0, - "enum": "foo", - "arr": "{a,b,c}", - "integer": 43, - "json": {"some key": "some value"}, - "jsonb": {"another key": [1, 2, "3"]} - } |] - `shouldRespondWith` - [json| { - "double": 3.1, - "varchar": "hello", - "boolean": true, - "date": "2019-01-01", - "money": "$0.00", - "enum": "foo", - "arr": ["a", "b", "c"], - "integer": 43, - "json": {"some key": "some value"}, - "jsonb": {"another key": [1, 2, "3"]} - } |] - { matchHeaders = [matchContentTypeJson] } - - when (actualPgVersion >= pgVersion100) $ - it "accepts a variety of arguments (Postgres >= 10)" $ - post "/rpc/varied_arguments" - [json| { - "double": 3.1, - "varchar": "hello", - "boolean": true, - "date": "20190101", - "money": 0, - "enum": "foo", - "arr": ["a", "b", "c"], - "integer": 43, - "json": {"some key": "some value"}, - "jsonb": {"another key": [1, 2, "3"]} - } |] - `shouldRespondWith` - [json| { - "double": 3.1, - "varchar": "hello", - "boolean": true, - "date": "2019-01-01", - "money": "$0.00", - "enum": "foo", - "arr": ["a", "b", "c"], - "integer": 43, - "json": {"some key": "some value"}, - "jsonb": {"another key": [1, 2, "3"]} - } |] - { matchHeaders = [matchContentTypeJson] } + it "accepts a variety of arguments (Postgres >= 10)" $ + post "/rpc/varied_arguments" + [json| { + "double": 3.1, + "varchar": "hello", + "boolean": true, + "date": "20190101", + "money": 0, + "enum": "foo", + "arr": ["a", "b", "c"], + "integer": 43, + "json": {"some key": "some value"}, + "jsonb": {"another key": [1, 2, "3"]} + } |] + `shouldRespondWith` + [json| { + "double": 3.1, + "varchar": "hello", + "boolean": true, + "date": "2019-01-01", + "money": "$0.00", + "enum": "foo", + "arr": ["a", "b", "c"], + "integer": 43, + "json": {"some key": "some value"}, + "jsonb": {"another key": [1, 2, "3"]} + } |] + { matchHeaders = [matchContentTypeJson] } it "accepts a variety of arguments with GET" $ -- without JSON / JSONB here, because passing those via query string is useless - they just become a "json string" all the time @@ -464,14 +431,6 @@ spec actualPgVersion = [json|"object"|] { matchHeaders = [matchContentTypeJson] } - when (actualPgVersion < pgVersion100) $ - it "parses quoted JSON arguments as JSON (Postgres < 10)" $ - post "/rpc/json_argument" - [json| { "arg": "{ \"key\": 3 }" } |] - `shouldRespondWith` - [json|"object"|] - { matchHeaders = [matchContentTypeJson] } - when ((actualPgVersion >= pgVersion109 && actualPgVersion < pgVersion110) || actualPgVersion >= pgVersion114) $ it "parses quoted JSON arguments as JSON string (from Postgres 10.9, 11.4)" $ @@ -598,68 +557,59 @@ spec actualPgVersion = [json|[{"a": "A", "b": "B"}]|] context "procs with VARIADIC params" $ do - when (actualPgVersion < pgVersion100) $ - it "works with POST (Postgres < 10)" $ - post "/rpc/variadic_param" - [json| { "v": "{hi,hello,there}" } |] + it "works with POST (Postgres >= 10)" $ + post "/rpc/variadic_param" + [json| { "v": ["hi", "hello", "there"] } |] + `shouldRespondWith` + [json|["hi", "hello", "there"]|] + + context "works with GET and repeated params" $ do + it "n=0 (through DEFAULT)" $ + get "/rpc/variadic_param" + `shouldRespondWith` + [json|[]|] + + it "n=1" $ + get "/rpc/variadic_param?v=hi" `shouldRespondWith` - [json|["hi", "hello", "there"]|] + [json|["hi"]|] - when (actualPgVersion >= pgVersion100) $ do - it "works with POST (Postgres >= 10)" $ - post "/rpc/variadic_param" - [json| { "v": ["hi", "hello", "there"] } |] + it "n>1" $ + get "/rpc/variadic_param?v=hi&v=there" `shouldRespondWith` - [json|["hi", "hello", "there"]|] - - context "works with GET and repeated params" $ do - it "n=0 (through DEFAULT)" $ - get "/rpc/variadic_param" - `shouldRespondWith` - [json|[]|] - - it "n=1" $ - get "/rpc/variadic_param?v=hi" - `shouldRespondWith` - [json|["hi"]|] - - it "n>1" $ - get "/rpc/variadic_param?v=hi&v=there" - `shouldRespondWith` - [json|["hi", "there"]|] - - context "works with POST and repeated params from html form" $ do - it "n=0 (through DEFAULT)" $ - request methodPost "/rpc/variadic_param" - [("Content-Type", "application/x-www-form-urlencoded")] - "" - `shouldRespondWith` - [json|[]|] - - it "n=1" $ - request methodPost "/rpc/variadic_param" - [("Content-Type", "application/x-www-form-urlencoded")] - "v=hi" - `shouldRespondWith` - [json|["hi"]|] - - it "n>1" $ - request methodPost "/rpc/variadic_param" - [("Content-Type", "application/x-www-form-urlencoded")] - "v=hi&v=there" - `shouldRespondWith` - [json|["hi", "there"]|] + [json|["hi", "there"]|] + + context "works with POST and repeated params from html form" $ do + it "n=0 (through DEFAULT)" $ + request methodPost "/rpc/variadic_param" + [("Content-Type", "application/x-www-form-urlencoded")] + "" + `shouldRespondWith` + [json|[]|] + + it "n=1" $ + request methodPost "/rpc/variadic_param" + [("Content-Type", "application/x-www-form-urlencoded")] + "v=hi" + `shouldRespondWith` + [json|["hi"]|] + + it "n>1" $ + request methodPost "/rpc/variadic_param" + [("Content-Type", "application/x-www-form-urlencoded")] + "v=hi&v=there" + `shouldRespondWith` + [json|["hi", "there"]|] it "returns last value for repeated params without VARIADIC" $ get "/rpc/sayhello?name=ignored&name=world" `shouldRespondWith` [json|"Hello, world"|] - when (actualPgVersion >= pgVersion100) $ - it "returns last value for repeated non-variadic params in function with other VARIADIC arguments" $ - get "/rpc/sayhello_variadic?name=ignored&name=world&v=unused" - `shouldRespondWith` - [json|"Hello, world"|] + it "returns last value for repeated non-variadic params in function with other VARIADIC arguments" $ + get "/rpc/sayhello_variadic?name=ignored&name=world&v=unused" + `shouldRespondWith` + [json|"Hello, world"|] it "can handle procs with args that have a DEFAULT value" $ do get "/rpc/many_inout_params?num=1&str=two" diff --git a/test/spec/Main.hs b/test/spec/Main.hs index 9306140447f..b5ee37fbe64 100644 --- a/test/spec/Main.hs +++ b/test/spec/Main.hs @@ -67,7 +67,6 @@ main = do loadDbStructure pool (configDbSchemas testCfg) (configDbExtraSearchPath testCfg) - actualPgVersion let -- For tests that run with the same refDbStructure @@ -85,7 +84,6 @@ main = do loadDbStructure pool (configDbSchemas config) (configDbExtraSearchPath config) - actualPgVersion appState <- AppState.initWithPool pool config AppState.putPgVersion appState actualPgVersion AppState.putDbStructure appState (Just customDbStructure) @@ -236,5 +234,5 @@ main = do describe "Feature.RollbackForcedSpec" Feature.RollbackSpec.forced where - loadDbStructure pool schemas extraSearchPath actualPgVersion = - either (panic.show) id <$> P.use pool (HT.transaction HT.ReadCommitted HT.Read $ queryDbStructure (toList schemas) extraSearchPath actualPgVersion True) + loadDbStructure pool schemas extraSearchPath = + either (panic.show) id <$> P.use pool (HT.transaction HT.ReadCommitted HT.Read $ queryDbStructure (toList schemas) extraSearchPath True) diff --git a/test/spec/fixtures/data.sql b/test/spec/fixtures/data.sql index b6af7279795..f381e187ad7 100644 --- a/test/spec/fixtures/data.sql +++ b/test/spec/fixtures/data.sql @@ -668,14 +668,12 @@ INSERT INTO private.films (id, title) VALUES (12,'douze commandements'), (2001,' TRUNCATE TABLE private.personnages CASCADE; INSERT INTO private.personnages (film_id, role_id, character) VALUES (12,1,'méchant'), (2001,2,'astronaute'); -DO $do$BEGIN - IF (SELECT current_setting('server_version_num')::INT >= 100000) THEN - INSERT INTO test.car_models(name, year) VALUES ('DeLorean',1981); - INSERT INTO test.car_models(name, year) VALUES ('F310-B',1997); - INSERT INTO test.car_models(name, year) VALUES ('Veneno',2013); - INSERT INTO test.car_models(name, year) VALUES ('Murcielago',2001); - END IF; +INSERT INTO test.car_models(name, year) VALUES ('DeLorean',1981); +INSERT INTO test.car_models(name, year) VALUES ('F310-B',1997); +INSERT INTO test.car_models(name, year) VALUES ('Veneno',2013); +INSERT INTO test.car_models(name, year) VALUES ('Murcielago',2001); +DO $do$BEGIN IF (SELECT current_setting('server_version_num')::INT >= 110000) THEN INSERT INTO test.car_brands(name) VALUES ('DMC'); INSERT INTO test.car_brands(name) VALUES ('Ferrari'); diff --git a/test/spec/fixtures/privileges.sql b/test/spec/fixtures/privileges.sql index 3d4a3b5858c..39864412135 100644 --- a/test/spec/fixtures/privileges.sql +++ b/test/spec/fixtures/privileges.sql @@ -163,6 +163,9 @@ GRANT ALL ON TABLE , clientinfo , contact , chores + , car_models + , car_models_2021 + , car_models_default TO postgrest_test_anonymous; GRANT INSERT ON TABLE insertonly TO postgrest_test_anonymous; @@ -195,12 +198,6 @@ GRANT USAGE ON SCHEMA test TO postgrest_test_default_role; DO $do$BEGIN - IF (SELECT current_setting('server_version_num')::INT >= 100000) THEN - GRANT ALL ON TABLE test.car_models TO postgrest_test_anonymous; - GRANT ALL ON TABLE test.car_models_2021 TO postgrest_test_anonymous; - GRANT ALL ON TABLE test.car_models_default TO postgrest_test_anonymous; - END IF; - IF (SELECT current_setting('server_version_num')::INT >= 110000) THEN GRANT ALL ON TABLE test.car_brands TO postgrest_test_anonymous; END IF; diff --git a/test/spec/fixtures/schema.sql b/test/spec/fixtures/schema.sql index 3c9428e5462..27a1590d340 100644 --- a/test/spec/fixtures/schema.sql +++ b/test/spec/fixtures/schema.sql @@ -2213,26 +2213,22 @@ create table private.rollen ( ); -- Tables used for testing embedding between partitioned tables +create table test.car_models( + name varchar(64) not null, + year int not null +) partition by list (year); -do $do$begin - -- partitioned tables using the PARTITION syntax are supported from pg v10 - if (select current_setting('server_version_num')::int >= 100000) then - create table test.car_models( - name varchar(64) not null, - year int not null - ) partition by list (year); - - comment on table test.car_models is - $$A partitioned table +comment on table test.car_models is +$$A partitioned table A test for partitioned tables$$; - create table test.car_models_2021 partition of test.car_models - for values in (2021); - create table test.car_models_default partition of test.car_models - for values in (1981,1997,2001,2013); - end if; +create table test.car_models_2021 partition of test.car_models + for values in (2021); +create table test.car_models_default partition of test.car_models + for values in (1981,1997,2001,2013); +do $do$begin -- primary keys for partitioned tables are supported from pg v11 if (select current_setting('server_version_num')::int >= 110000) then create table test.car_brands ( @@ -2411,22 +2407,15 @@ BEGIN END$$; -- This view is not used in any requests but just parsed by the pfkSourceColumns query. --- XMLTABLE is only supported from PG 10 on -DO $do$ -BEGIN - IF current_setting('server_version_num')::INT >= 100000 THEN - CREATE VIEW test.xml AS - SELECT * - FROM (SELECT ''::xml AS data) _, - XMLTABLE( - '' - PASSING data - COLUMNS id int PATH '@id', - premier_name text PATH 'PREMIER_NAME' DEFAULT 'not specified' - ); - END IF; -END -$do$; +CREATE VIEW test.xml AS +SELECT * + FROM (SELECT ''::xml AS data) _, + XMLTABLE( + '' + PASSING data + COLUMNS id int PATH '@id', + premier_name text PATH 'PREMIER_NAME' DEFAULT 'not specified' + ); -- https://github.com/PostgREST/postgrest/issues/1543 CREATE TYPE complex AS (