Skip to content

Commit

Permalink
feat: Drop support for pg 10
Browse files Browse the repository at this point in the history
  • Loading branch information
wolfgangwalther committed Feb 10, 2024
1 parent 872ed4e commit 1e66df6
Show file tree
Hide file tree
Showing 20 changed files with 286 additions and 369 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ jobs:
strategy:
fail-fast: false
matrix:
pgVersion: [10, 11, 12, 13, 14, 15, 16]
pgVersion: [11, 12, 13, 14, 15, 16]
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 @@ -20,6 +20,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).

### Changed
- #2052, Dropped support for PostgreSQL 9.6 - @wolfgangwalther
- #2052, Dropped support for PostgreSQL 10 - @wolfgangwalther

### Deprecated

Expand Down
1 change: 0 additions & 1 deletion default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ let
{ name = "postgresql-13"; postgresql = pkgs.postgresql_13.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
{ name = "postgresql-12"; postgresql = pkgs.postgresql_12.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
{ name = "postgresql-11"; postgresql = pkgs.postgresql_11.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
{ name = "postgresql-10"; postgresql = pkgs.postgresql_10.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
];

# Dynamic derivation for PostgREST
Expand Down
24 changes: 12 additions & 12 deletions nix/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,12 @@ The PostgREST utilities available in `nix-shell` all have names that begin with
postgrest-build postgrest-test-spec
postgrest-check postgrest-watch
postgrest-clean postgrest-with-all
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-14
postgrest-test-io
postgrest-coverage postgrest-with-postgresql-11
postgrest-lint postgrest-with-postgresql-12
postgrest-run postgrest-with-postgresql-13
postgrest-style postgrest-with-postgresql-14
postgrest-style-check postgrest-with-postgresql-15
postgrest-test-io postgrest-with-postgresql-16
...

[nix-shell]$
Expand All @@ -99,12 +99,12 @@ $ nix-shell --arg memory true
postgrest-build postgrest-test-spec
postgrest-check postgrest-watch
postgrest-clean postgrest-with-all
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-14
postgrest-test-io
postgrest-coverage postgrest-with-postgresql-11
postgrest-lint postgrest-with-postgresql-12
postgrest-run postgrest-with-postgresql-13
postgrest-style postgrest-with-postgresql-14
postgrest-style-check postgrest-with-postgresql-15
postgrest-test-io postgrest-with-postgresql-16
postgrest-test-memory
...

Expand Down
5 changes: 0 additions & 5 deletions nix/overlays/postgis.nix
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,4 @@ in
postgis = prev.postgresql_11.pkgs.postgis.overrideAttrs (_: postgis_3_2_3);
};
};
postgresql_10 = prev.postgresql_10.override { this = final.postgresql_11; } // {
pkgs = prev.postgresql_10.pkgs // {
postgis = prev.postgresql_10.pkgs.postgis.overrideAttrs (_: postgis_3_2_3);
};
};
}
15 changes: 0 additions & 15 deletions nix/overlays/postgresql-legacy.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,6 @@ self: super:
# Overlay that adds legacy versions of PostgreSQL that are supported by
# PostgREST.
{
# PostgreSQL 10 was removed from Nixpkgs with
# https://github.com/NixOS/nixpkgs/commit/aa1483114bb329fee7e1266100b8d8921ed4723f
# We pin its parent commit to get the last version that was available.
postgresql_10 =
let
rev = "79661ba7e2fb96ebefbb537458a5bbae9dc5bd1a";
tarballHash = "0rn796pfn4sg90ai9fdnwmr10a2s835p1arazzgz46h6s5cxvq97";
pinnedPkgs =
builtins.fetchTarball {
url = "https://github.com/nixos/nixpkgs/archive/${rev}.tar.gz";
sha256 = tarballHash;
};
in
(import pinnedPkgs { }).pkgs.postgresql_10;

# PostgreSQL 11 was removed from Nixpkgs with
# https://github.com/NixOS/nixpkgs/commit/1220a4d4dd1a4590780a5e1c18d1333a121be366
# We pin its parent commit to get the last version that was available.
Expand Down
2 changes: 1 addition & 1 deletion src/PostgREST/App.hs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ handleRequest AuthResult{..} conf appState authenticated prepared pgVer apiReq@A

(ActionInspect headersOnly, TargetDefaultSpec tSchema) -> do
(planTime', iPlan) <- withTiming $ liftEither $ Plan.inspectPlan apiReq
(txTime', oaiResult) <- withTiming $ runQuery roleIsoLvl mempty (Plan.ipTxmode iPlan) $ Query.openApiQuery sCache pgVer conf tSchema
(txTime', oaiResult) <- withTiming $ runQuery roleIsoLvl mempty (Plan.ipTxmode iPlan) $ Query.openApiQuery sCache conf tSchema
(respTime', pgrst) <- withTiming $ liftEither $ Response.openApiResponse (T.decodeUtf8 prettyVersion, docsVersion) headersOnly oaiResult conf sCache iSchema iNegotiatedByProfile
return $ pgrstResponse (ServerTiming jwtTime parseTime planTime' txTime' respTime') pgrst

Expand Down
10 changes: 1 addition & 9 deletions src/PostgREST/Config/PgVersion.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
module PostgREST.Config.PgVersion
( PgVersion(..)
, minimumPgVersion
, pgVersion109
, pgVersion110
, pgVersion112
, pgVersion114
, pgVersion120
Expand All @@ -30,13 +28,7 @@ instance Ord PgVersion where

-- | Tells the minimum PostgreSQL version required by this version of PostgREST
minimumPgVersion :: PgVersion
minimumPgVersion = pgVersion100

pgVersion100 :: PgVersion
pgVersion100 = PgVersion 100000 "10"

pgVersion109 :: PgVersion
pgVersion109 = PgVersion 100009 "10.9"
minimumPgVersion = pgVersion110

pgVersion110 :: PgVersion
pgVersion110 = PgVersion 110000 "11.0"
Expand Down
6 changes: 3 additions & 3 deletions src/PostgREST/Query.hs
Original file line number Diff line number Diff line change
Expand Up @@ -172,14 +172,14 @@ invokeQuery rout CallReadPlan{..} apiReq@ApiRequest{iPreferences=Preferences{..}
failExceedsMaxAffectedPref (preferMaxAffected,preferHandling) resultSet
pure resultSet

openApiQuery :: SchemaCache -> PgVersion -> AppConfig -> Schema -> DbHandler (Maybe (TablesMap, RoutineMap, Maybe Text))
openApiQuery sCache pgVer AppConfig{..} tSchema =
openApiQuery :: SchemaCache -> AppConfig -> Schema -> DbHandler (Maybe (TablesMap, RoutineMap, Maybe Text))
openApiQuery sCache AppConfig{..} tSchema =
lift $ case configOpenApiMode of
OAFollowPriv -> do
tableAccess <- SQL.statement [tSchema] (SchemaCache.accessibleTables configDbPreparedStatements)
Just <$> ((,,)
(HM.filterWithKey (\qi _ -> S.member qi tableAccess) $ SchemaCache.dbTables sCache)
<$> SQL.statement tSchema (SchemaCache.accessibleFuncs pgVer configDbPreparedStatements)
<$> SQL.statement tSchema (SchemaCache.accessibleFuncs configDbPreparedStatements)
<*> SQL.statement tSchema (SchemaCache.schemaDescription configDbPreparedStatements))
OAIgnorePriv ->
Just <$> ((,,)
Expand Down
9 changes: 4 additions & 5 deletions src/PostgREST/Query/QueryBuilder.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ import Data.Maybe (fromJust)
import Data.Tree (Tree (..))

import PostgREST.ApiRequest.Preferences (PreferResolution (..))
import PostgREST.Config.PgVersion (PgVersion, pgVersion110,
pgVersion130)
import PostgREST.Config.PgVersion (PgVersion, pgVersion130)
import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..))
import PostgREST.SchemaCache.Relationship (Cardinality (..),
Junction (..),
Expand Down Expand Up @@ -202,9 +201,9 @@ callPlanToQuery (FunctionCall qi params args returnsScalar returnsSetOfScalar re
"LATERAL " <> callIt (fmtParams prms)

callIt :: SQL.Snippet -> SQL.Snippet
callIt argument | pgVer < pgVersion130 && pgVer >= pgVersion110 && returnsCompositeAlias = "(SELECT (" <> fromQi qi <> "(" <> argument <> ")).*) pgrst_call"
| returnsScalar || returnsSetOfScalar = "(SELECT " <> fromQi qi <> "(" <> argument <> ") pgrst_scalar) pgrst_call"
| otherwise = fromQi qi <> "(" <> argument <> ") pgrst_call"
callIt argument | pgVer < pgVersion130 && returnsCompositeAlias = "(SELECT (" <> fromQi qi <> "(" <> argument <> ")).*) pgrst_call"
| returnsScalar || returnsSetOfScalar = "(SELECT " <> fromQi qi <> "(" <> argument <> ") pgrst_scalar) pgrst_call"
| otherwise = fromQi qi <> "(" <> argument <> ") pgrst_call"

fmtParams :: [RoutineParam] -> SQL.Snippet
fmtParams prms = intercalateSnippet ", "
Expand Down
44 changes: 20 additions & 24 deletions src/PostgREST/SchemaCache.hs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ import PostgREST.Config (AppConfig (..))
import PostgREST.Config.Database (TimezoneNames,
pgVersionStatement,
toIsolationLevel)
import PostgREST.Config.PgVersion (PgVersion, pgVersion110,
pgVersion120)
import PostgREST.Config.PgVersion (PgVersion, pgVersion120)
import PostgREST.SchemaCache.Identifiers (AccessSet, FieldName,
QualifiedIdentifier (..),
RelIdentifier (..),
Expand Down Expand Up @@ -149,11 +148,11 @@ querySchemaCache AppConfig{..} = do
pgVer <- SQL.statement mempty $ pgVersionStatement prepared
tabs <- SQL.statement schemas $ allTables pgVer prepared
keyDeps <- SQL.statement (schemas, configDbExtraSearchPath) $ allViewsKeyDependencies prepared
m2oRels <- SQL.statement mempty $ allM2OandO2ORels pgVer prepared
funcs <- SQL.statement schemas $ allFunctions pgVer prepared
m2oRels <- SQL.statement mempty $ allM2OandO2ORels prepared
funcs <- SQL.statement schemas $ allFunctions prepared
cRels <- SQL.statement mempty $ allComputedRels prepared
reps <- SQL.statement schemas $ dataRepresentations prepared
mHdlers <- SQL.statement schemas $ mediaHandlers pgVer prepared
mHdlers <- SQL.statement schemas $ mediaHandlers prepared
tzones <- SQL.statement mempty $ timezones prepared
_ <-
let sleepCall = SQL.Statement "select pg_sleep($1)" (param HE.int4) HD.noResult prepared in
Expand Down Expand Up @@ -363,18 +362,18 @@ dataRepresentations = SQL.Statement sql (arrayParam HE.text) decodeRepresentatio
OR (dst_t.typtype = 'd' AND c.castsource IN ('json'::regtype::oid , 'text'::regtype::oid)))
|]

allFunctions :: PgVersion -> Bool -> SQL.Statement [Schema] RoutineMap
allFunctions pgVer = SQL.Statement sql (arrayParam HE.text) decodeFuncs
allFunctions :: Bool -> SQL.Statement [Schema] RoutineMap
allFunctions = SQL.Statement sql (arrayParam HE.text) decodeFuncs
where
sql = funcsSqlQuery pgVer <> " AND pn.nspname = ANY($1)"
sql = funcsSqlQuery <> " AND pn.nspname = ANY($1)"

accessibleFuncs :: PgVersion -> Bool -> SQL.Statement Schema RoutineMap
accessibleFuncs pgVer = SQL.Statement sql (param HE.text) decodeFuncs
accessibleFuncs :: Bool -> SQL.Statement Schema RoutineMap
accessibleFuncs = SQL.Statement sql (param HE.text) decodeFuncs
where
sql = funcsSqlQuery pgVer <> " AND pn.nspname = $1 AND has_function_privilege(p.oid, 'execute')"
sql = funcsSqlQuery <> " AND pn.nspname = $1 AND has_function_privilege(p.oid, 'execute')"

funcsSqlQuery :: PgVersion -> SqlQuery
funcsSqlQuery pgVer = [q|
funcsSqlQuery :: SqlQuery
funcsSqlQuery = [q|
-- Recursively get the base types of domains
WITH
base_types AS (
Expand Down Expand Up @@ -462,7 +461,7 @@ funcsSqlQuery pgVer = [q|
WHERE setting not LIKE 'default_transaction_isolation%'
) func_settings ON TRUE
WHERE t.oid <> 'trigger'::regtype AND COALESCE(a.callable, true)
|] <> (if pgVer >= pgVersion110 then "AND prokind = 'f'" else "AND NOT (proisagg OR proiswindow)")
AND prokind = 'f'|]

schemaDescription :: Bool -> SQL.Statement Schema (Maybe Text)
schemaDescription =
Expand Down Expand Up @@ -828,8 +827,8 @@ tablesSqlQuery pgVer =
END|]

-- | Gets many-to-one relationships and one-to-one(O2O) relationships, which are a refinement of the many-to-one's
allM2OandO2ORels :: PgVersion -> Bool -> SQL.Statement () [Relationship]
allM2OandO2ORels pgVer =
allM2OandO2ORels :: Bool -> SQL.Statement () [Relationship]
allM2OandO2ORels =
SQL.Statement sql HE.noParams decodeRels
where
-- We use jsonb_agg for comparing the uniques/pks instead of array_agg to avoid the ERROR: cannot accumulate arrays of different dimensionality
Expand Down Expand Up @@ -875,11 +874,8 @@ allM2OandO2ORels pgVer =
JOIN pg_namespace ns2 ON ns2.oid = other.relnamespace
LEFT JOIN pks_uniques_cols pks_uqs ON pks_uqs.connamespace = traint.connamespace AND pks_uqs.conrelid = traint.conrelid
WHERE traint.contype = 'f'
|] <>
(if pgVer >= pgVersion110
then " and traint.conparentid = 0 "
else mempty) <>
"ORDER BY traint.conrelid, traint.conname"
AND traint.conparentid = 0
ORDER BY traint.conrelid, traint.conname|]

allComputedRels :: Bool -> SQL.Statement () [Relationship]
allComputedRels =
Expand Down Expand Up @@ -1132,8 +1128,8 @@ initialMediaHandlers =
HM.insert (RelAnyElement, MediaType.MTGeoJSON ) (BuiltinOvAggGeoJson, MediaType.MTGeoJSON)
HM.empty

mediaHandlers :: PgVersion -> Bool -> SQL.Statement [Schema] MediaHandlerMap
mediaHandlers pgVer =
mediaHandlers :: Bool -> SQL.Statement [Schema] MediaHandlerMap
mediaHandlers =
SQL.Statement sql (arrayParam HE.text) decodeMediaHandlers
where
sql = [q|
Expand Down Expand Up @@ -1195,7 +1191,7 @@ mediaHandlers pgVer =
join pg_namespace typ_sch on typ_sch.oid = mtype.typnamespace
where
pro_sch.nspname = ANY($1) and NOT proretset
|] <> (if pgVer >= pgVersion110 then " AND prokind = 'f'" else " AND NOT (proisagg OR proiswindow)")
and prokind = 'f'|]

decodeMediaHandlers :: HD.Result MediaHandlerMap
decodeMediaHandlers =
Expand Down
9 changes: 3 additions & 6 deletions test/spec/Feature/OpenApi/OpenApiSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,12 @@ import Network.HTTP.Types
import Test.Hspec hiding (pendingWith)
import Test.Hspec.Wai

import PostgREST.Config.PgVersion (PgVersion, pgVersion110)

import PostgREST.Version (docsVersion)
import Protolude hiding (get)
import SpecHelper

spec :: PgVersion -> SpecWith ((), Application)
spec actualPgVersion = describe "OpenAPI" $ do
spec :: SpecWith ((), Application)
spec = describe "OpenAPI" $ do
it "root path returns a valid openapi spec" $ do
validateOpenApiResponse [("Accept", "application/openapi+json")]
request methodHead "/"
Expand Down Expand Up @@ -275,8 +273,7 @@ spec actualPgVersion = describe "OpenAPI" $ do

getParameterYear `shouldBe` Just "#/parameters/rowFilter.car_models.year"

when (actualPgVersion >= pgVersion110) $
getParameterRef `shouldBe` Just "#/parameters/rowFilter.car_models.car_brand_name"
getParameterRef `shouldBe` Just "#/parameters/rowFilter.car_models.car_brand_name"

describe "Materialized view" $

Expand Down
13 changes: 3 additions & 10 deletions test/spec/Feature/OptionsSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@ import Network.HTTP.Types
import Test.Hspec
import Test.Hspec.Wai

import PostgREST.Config.PgVersion (PgVersion, pgVersion110)

import Protolude
import SpecHelper

spec :: PgVersion -> SpecWith ((), Application)
spec actualPgVersion = describe "Allow header" $ do
spec :: SpecWith ((), Application)
spec = describe "Allow header" $ do
context "a table" $ do
it "includes read/write methods for writeable table" $ do
r <- request methodOptions "/items" [] ""
Expand All @@ -29,12 +27,7 @@ spec actualPgVersion = describe "Allow header" $ 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"
)
matchHeader "Allow" "OPTIONS,GET,HEAD,POST,PUT,PATCH,DELETE"

context "a view" $ do
context "auto updatable" $ do
Expand Down
31 changes: 15 additions & 16 deletions test/spec/Feature/Query/InsertSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import Test.Hspec.Wai
import Test.Hspec.Wai.JSON
import Text.Heredoc

import PostgREST.Config.PgVersion (PgVersion, pgVersion110,
pgVersion112, pgVersion120,
pgVersion130, pgVersion140)
import PostgREST.Config.PgVersion (PgVersion, pgVersion112,
pgVersion120, pgVersion130,
pgVersion140)

import Protolude hiding (get)
import SpecHelper
Expand Down Expand Up @@ -141,19 +141,18 @@ spec actualPgVersion = do
, "Preference-Applied" <:> "return=headers-only"]
}

when (actualPgVersion >= pgVersion110) $
it "should not throw and return location header for partitioned tables when selecting without PK" $
request methodPost "/car_models"
[("Prefer", "return=headers-only")]
[json|{"name":"Enzo","year":2021}|]
`shouldRespondWith`
""
{ matchStatus = 201
, matchHeaders = [ matchHeaderAbsent hContentType
, "Location" <:> "/car_models?name=eq.Enzo&year=eq.2021"
, "Content-Range" <:> "*/*"
, "Preference-Applied" <:> "return=headers-only"]
}
it "should not throw and return location header for partitioned tables when selecting without PK" $
request methodPost "/car_models"
[("Prefer", "return=headers-only")]
[json|{"name":"Enzo","year":2021}|]
`shouldRespondWith`
""
{ matchStatus = 201
, matchHeaders = [ matchHeaderAbsent hContentType
, "Location" <:> "/car_models?name=eq.Enzo&year=eq.2021"
, "Content-Range" <:> "*/*"
, "Preference-Applied" <:> "return=headers-only"]
}

context "requesting no representation" $
it "should not throw and return no location header when selecting without PK" $
Expand Down
Loading

0 comments on commit 1e66df6

Please sign in to comment.