Skip to content

Commit

Permalink
feat: drop support for pg 9.6
Browse files Browse the repository at this point in the history
  • Loading branch information
wolfgangwalther committed Feb 5, 2022
1 parent 52d628f commit 9ff68f2
Show file tree
Hide file tree
Showing 16 changed files with 159 additions and 243 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 0 additions & 1 deletion default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
4 changes: 2 additions & 2 deletions nix/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
...

Expand All @@ -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
...
Expand Down
17 changes: 8 additions & 9 deletions src/PostgREST/App.hs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ data RequestContext = RequestContext
{ ctxConfig :: AppConfig
, ctxDbStructure :: DbStructure
, ctxApiRequest :: ApiRequest
, ctxPgVersion :: PgVersion
}

type Handler = ExceptT Error
Expand Down Expand Up @@ -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 $
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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

Expand All @@ -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
Expand Down Expand Up @@ -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 ->
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 0 additions & 2 deletions src/PostgREST/CLI.hs
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,13 @@ 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) $
transaction SQL.ReadCommitted SQL.Read $
queryDbStructure
(toList configDbSchemas)
configDbExtraSearchPath
actualPgVersion
configDbPreparedStatements
SQL.release $ AppState.getPool appState
case result of
Expand Down
6 changes: 1 addition & 5 deletions src/PostgREST/Config/PgVersion.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
module PostgREST.Config.PgVersion
( PgVersion(..)
, minimumPgVersion
, pgVersion96
, pgVersion100
, pgVersion109
, pgVersion110
Expand All @@ -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"
Expand Down
26 changes: 11 additions & 15 deletions src/PostgREST/DbStructure.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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 (..),
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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|
Expand Down Expand Up @@ -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')
Expand Down Expand Up @@ -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|
Expand Down Expand Up @@ -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)
Expand Down
3 changes: 1 addition & 2 deletions src/PostgREST/Workers.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
36 changes: 17 additions & 19 deletions test/spec/Feature/OpenApi/OpenApiSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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" $

Expand Down
26 changes: 12 additions & 14 deletions test/spec/Feature/OptionsSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down

0 comments on commit 9ff68f2

Please sign in to comment.