Skip to content

Commit

Permalink
feat: Raise minimum supported version to 12.1
Browse files Browse the repository at this point in the history
There is no reason to support the 12.0 version, which is outdated for
many years already. We still support all other minors for v12.
  • Loading branch information
wolfgangwalther committed Jun 15, 2024
1 parent 96e6101 commit f195290
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 105 deletions.
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
, pgVersion121
, pgVersion130
, pgVersion140
, pgVersion150
Expand All @@ -26,10 +25,7 @@ instance Ord PgVersion where

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

pgVersion120 :: PgVersion
pgVersion120 = PgVersion 120000 "12.0" "12.0"
minimumPgVersion = pgVersion121

pgVersion121 :: PgVersion
pgVersion121 = PgVersion 120001 "12.1" "12.1"
Expand Down
12 changes: 3 additions & 9 deletions test/spec/Feature/Query/JsonOperatorSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@ import Test.Hspec
import Test.Hspec.Wai
import Test.Hspec.Wai.JSON

import PostgREST.Config.PgVersion (PgVersion, pgVersion121)

import Protolude hiding (get)
import SpecHelper

spec :: PgVersion -> SpecWith ((), Application)
spec actualPgVersion = describe "json and jsonb operators" $ do
spec :: SpecWith ((), Application)
spec = describe "json and jsonb operators" $ do
context "Shaping response with select parameter" $ do
it "obtains a json subfield one level with casting" $
get "/complex_items?id=eq.1&select=settings->>foo::json" `shouldRespondWith`
Expand All @@ -27,12 +25,8 @@ spec actualPgVersion = describe "json and jsonb operators" $ do

it "fails on bad casting (data of the wrong format)" $
get "/complex_items?select=settings->foo->>bar::integer"
`shouldRespondWith` (
if actualPgVersion >= pgVersion121 then
`shouldRespondWith`
[json| {"hint":null,"details":null,"code":"22P02","message":"invalid input syntax for type integer: \"baz\""} |]
else
[json| {"hint":null,"details":null,"code":"22P02","message":"invalid input syntax for integer: \"baz\""} |]
)
{ matchStatus = 400 , matchHeaders = [] }

it "obtains a json subfield two levels (string)" $
Expand Down
172 changes: 83 additions & 89 deletions test/spec/Feature/Query/QuerySpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@ import Test.Hspec hiding (pendingWith)
import Test.Hspec.Wai
import Test.Hspec.Wai.JSON

import PostgREST.Config.PgVersion (PgVersion, pgVersion121)
import Protolude hiding (get)
import Protolude hiding (get)
import SpecHelper

spec :: PgVersion -> SpecWith ((), Application)
spec actualPgVersion = do
spec :: SpecWith ((), Application)
spec = do

describe "Querying a table with a column called count" $
it "should not confuse count column with pg_catalog.count aggregate" $
Expand Down Expand Up @@ -551,90 +550,89 @@ spec actualPgVersion = do
{"name":"Lamborghini","car_models":[{"name":"Murcielago","year":2001},{"name":"Veneno","year":2013}]}] |]
{ matchHeaders = [matchContentTypeJson] }

when (actualPgVersion >= pgVersion121) $ do
it "can request tables as children from a partitioned table" $
get "/car_models?name=in.(DeLorean,F310-B)&select=name,year,car_racers(name)&order=name.asc" `shouldRespondWith`
[json|
[{"name":"DeLorean","year":1981,"car_racers":[]},
{"name":"F310-B","year":1997,"car_racers":[{"name":"Michael Schumacher"}]}] |]
{ matchHeaders = [matchContentTypeJson] }
it "can request tables as children from a partitioned table" $
get "/car_models?name=in.(DeLorean,F310-B)&select=name,year,car_racers(name)&order=name.asc" `shouldRespondWith`
[json|
[{"name":"DeLorean","year":1981,"car_racers":[]},
{"name":"F310-B","year":1997,"car_racers":[{"name":"Michael Schumacher"}]}] |]
{ matchHeaders = [matchContentTypeJson] }

it "can request a partitioned table as parent from a table" $
get "/car_racers?select=name,car_models(name,year)&order=name.asc" `shouldRespondWith`
[json|
[{"name":"Alain Prost","car_models":null},
{"name":"Michael Schumacher","car_models":{"name":"F310-B","year":1997}}] |]
{ matchHeaders = [matchContentTypeJson] }
it "can request a partitioned table as parent from a table" $
get "/car_racers?select=name,car_models(name,year)&order=name.asc" `shouldRespondWith`
[json|
[{"name":"Alain Prost","car_models":null},
{"name":"Michael Schumacher","car_models":{"name":"F310-B","year":1997}}] |]
{ matchHeaders = [matchContentTypeJson] }

it "can request partitioned tables as children from a partitioned table" $
get "/car_models?name=in.(DeLorean,Murcielago,Veneno)&select=name,year,car_model_sales(date,quantity)&order=name.asc" `shouldRespondWith`
[json|
[{"name":"DeLorean","year":1981,"car_model_sales":[{"date":"2021-01-14","quantity":7},{"date":"2021-01-15","quantity":9}]},
{"name":"Murcielago","year":2001,"car_model_sales":[{"date":"2021-02-11","quantity":1},{"date":"2021-02-12","quantity":3}]},
{"name":"Veneno","year":2013,"car_model_sales":[]}] |]
{ matchHeaders = [matchContentTypeJson] }
it "can request partitioned tables as children from a partitioned table" $
get "/car_models?name=in.(DeLorean,Murcielago,Veneno)&select=name,year,car_model_sales(date,quantity)&order=name.asc" `shouldRespondWith`
[json|
[{"name":"DeLorean","year":1981,"car_model_sales":[{"date":"2021-01-14","quantity":7},{"date":"2021-01-15","quantity":9}]},
{"name":"Murcielago","year":2001,"car_model_sales":[{"date":"2021-02-11","quantity":1},{"date":"2021-02-12","quantity":3}]},
{"name":"Veneno","year":2013,"car_model_sales":[]}] |]
{ matchHeaders = [matchContentTypeJson] }

it "can request a partitioned table as parent from a partitioned table" $ do
get "/car_model_sales?date=in.(2021-01-15,2021-02-11)&select=date,quantity,car_models(name,year)&order=date.asc" `shouldRespondWith`
[json|
[{"date":"2021-01-15","quantity":9,"car_models":{"name":"DeLorean","year":1981}},
{"date":"2021-02-11","quantity":1,"car_models":{"name":"Murcielago","year":2001}}] |]
{ matchHeaders = [matchContentTypeJson] }
it "can request a partitioned table as parent from a partitioned table" $ do
get "/car_model_sales?date=in.(2021-01-15,2021-02-11)&select=date,quantity,car_models(name,year)&order=date.asc" `shouldRespondWith`
[json|
[{"date":"2021-01-15","quantity":9,"car_models":{"name":"DeLorean","year":1981}},
{"date":"2021-02-11","quantity":1,"car_models":{"name":"Murcielago","year":2001}}] |]
{ matchHeaders = [matchContentTypeJson] }

it "can request many to many relationships between partitioned tables ignoring the intermediate table partitions" $
get "/car_models?select=name,year,car_dealers(name,city)&order=name.asc&limit=4" `shouldRespondWith`
[json|
[{"name":"DeLorean","year":1981,"car_dealers":[{"name":"Springfield Cars S.A.","city":"Springfield"}]},
{"name":"F310-B","year":1997,"car_dealers":[]},
{"name":"Murcielago","year":2001,"car_dealers":[{"name":"The Best Deals S.A.","city":"Franklin"}]},
{"name":"Veneno","year":2013,"car_dealers":[]}] |]
{ matchStatus = 200
, matchHeaders = [matchContentTypeJson]
}

it "cannot request partitions as children from a partitioned table" $
get "/car_models?id=in.(1,2,4)&select=id,name,car_model_sales_202101(id)&order=id.asc" `shouldRespondWith`
[json|
{"hint":"Perhaps you meant 'car_model_sales' instead of 'car_model_sales_202101'.",
"details":"Searched for a foreign key relationship between 'car_models' and 'car_model_sales_202101' in the schema 'test', but no matches were found.",
"code":"PGRST200",
"message":"Could not find a relationship between 'car_models' and 'car_model_sales_202101' in the schema cache"} |]
{ matchStatus = 400
, matchHeaders = [matchContentTypeJson]
}

it "cannot request a partitioned table as parent from a partition" $
get "/car_model_sales_202101?select=id,name,car_models(id,name)&order=id.asc" `shouldRespondWith`
[json|
{"hint":"Perhaps you meant 'car_model_sales' instead of 'car_model_sales_202101'.",
"details":"Searched for a foreign key relationship between 'car_model_sales_202101' and 'car_models' in the schema 'test', but no matches were found.",
"code":"PGRST200",
"message":"Could not find a relationship between 'car_model_sales_202101' and 'car_models' in the schema cache"} |]
{ matchStatus = 400
, matchHeaders = [matchContentTypeJson]
}

it "cannot request a partition as parent from a partitioned table" $
get "/car_model_sales?id=in.(1,3,4)&select=id,name,car_models_default(id,name)&order=id.asc" `shouldRespondWith`
[json|
{"hint":"Perhaps you meant 'car_models' instead of 'car_models_default'.",
"details":"Searched for a foreign key relationship between 'car_model_sales' and 'car_models_default' in the schema 'test', but no matches were found.",
"code":"PGRST200",
"message":"Could not find a relationship between 'car_model_sales' and 'car_models_default' in the schema cache"} |]
{ matchStatus = 400
, matchHeaders = [matchContentTypeJson]
}

it "cannot request partitioned tables as children from a partition" $
get "/car_models_default?select=id,name,car_model_sales(id,name)&order=id.asc" `shouldRespondWith`
[json|
{"hint":"Perhaps you meant 'car_model_sales' instead of 'car_models_default'.",
"details":"Searched for a foreign key relationship between 'car_models_default' and 'car_model_sales' in the schema 'test', but no matches were found.",
"code":"PGRST200",
"message":"Could not find a relationship between 'car_models_default' and 'car_model_sales' in the schema cache"} |]
{ matchStatus = 400
, matchHeaders = [matchContentTypeJson]
}
it "can request many to many relationships between partitioned tables ignoring the intermediate table partitions" $
get "/car_models?select=name,year,car_dealers(name,city)&order=name.asc&limit=4" `shouldRespondWith`
[json|
[{"name":"DeLorean","year":1981,"car_dealers":[{"name":"Springfield Cars S.A.","city":"Springfield"}]},
{"name":"F310-B","year":1997,"car_dealers":[]},
{"name":"Murcielago","year":2001,"car_dealers":[{"name":"The Best Deals S.A.","city":"Franklin"}]},
{"name":"Veneno","year":2013,"car_dealers":[]}] |]
{ matchStatus = 200
, matchHeaders = [matchContentTypeJson]
}

it "cannot request partitions as children from a partitioned table" $
get "/car_models?id=in.(1,2,4)&select=id,name,car_model_sales_202101(id)&order=id.asc" `shouldRespondWith`
[json|
{"hint":"Perhaps you meant 'car_model_sales' instead of 'car_model_sales_202101'.",
"details":"Searched for a foreign key relationship between 'car_models' and 'car_model_sales_202101' in the schema 'test', but no matches were found.",
"code":"PGRST200",
"message":"Could not find a relationship between 'car_models' and 'car_model_sales_202101' in the schema cache"} |]
{ matchStatus = 400
, matchHeaders = [matchContentTypeJson]
}

it "cannot request a partitioned table as parent from a partition" $
get "/car_model_sales_202101?select=id,name,car_models(id,name)&order=id.asc" `shouldRespondWith`
[json|
{"hint":"Perhaps you meant 'car_model_sales' instead of 'car_model_sales_202101'.",
"details":"Searched for a foreign key relationship between 'car_model_sales_202101' and 'car_models' in the schema 'test', but no matches were found.",
"code":"PGRST200",
"message":"Could not find a relationship between 'car_model_sales_202101' and 'car_models' in the schema cache"} |]
{ matchStatus = 400
, matchHeaders = [matchContentTypeJson]
}

it "cannot request a partition as parent from a partitioned table" $
get "/car_model_sales?id=in.(1,3,4)&select=id,name,car_models_default(id,name)&order=id.asc" `shouldRespondWith`
[json|
{"hint":"Perhaps you meant 'car_models' instead of 'car_models_default'.",
"details":"Searched for a foreign key relationship between 'car_model_sales' and 'car_models_default' in the schema 'test', but no matches were found.",
"code":"PGRST200",
"message":"Could not find a relationship between 'car_model_sales' and 'car_models_default' in the schema cache"} |]
{ matchStatus = 400
, matchHeaders = [matchContentTypeJson]
}

it "cannot request partitioned tables as children from a partition" $
get "/car_models_default?select=id,name,car_model_sales(id,name)&order=id.asc" `shouldRespondWith`
[json|
{"hint":"Perhaps you meant 'car_model_sales' instead of 'car_models_default'.",
"details":"Searched for a foreign key relationship between 'car_models_default' and 'car_model_sales' in the schema 'test', but no matches were found.",
"code":"PGRST200",
"message":"Could not find a relationship between 'car_models_default' and 'car_model_sales' in the schema cache"} |]
{ matchStatus = 400
, matchHeaders = [matchContentTypeJson]
}

describe "view embedding" $ do
it "can detect fk relations through views to tables in the public schema" $
Expand Down Expand Up @@ -1133,12 +1131,8 @@ spec actualPgVersion = do

it "only returns an empty result set if the in value is empty" $
get "/items_with_different_col_types?int_data=in.( ,3,4)"
`shouldRespondWith` (
if actualPgVersion >= pgVersion121 then
`shouldRespondWith`
[json| {"hint":null,"details":null,"code":"22P02","message":"invalid input syntax for type integer: \"\""} |]
else
[json| {"hint":null,"details":null,"code":"22P02","message":"invalid input syntax for integer: \"\""} |]
)
{ matchStatus = 400
, matchHeaders = [matchContentTypeJson]
}
Expand Down
4 changes: 2 additions & 2 deletions test/spec/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,13 @@ main = do
, ("Feature.Query.EmbedDisambiguationSpec" , Feature.Query.EmbedDisambiguationSpec.spec)
, ("Feature.Query.EmbedInnerJoinSpec" , Feature.Query.EmbedInnerJoinSpec.spec)
, ("Feature.Query.InsertSpec" , Feature.Query.InsertSpec.spec actualPgVersion)
, ("Feature.Query.JsonOperatorSpec" , Feature.Query.JsonOperatorSpec.spec actualPgVersion)
, ("Feature.Query.JsonOperatorSpec" , Feature.Query.JsonOperatorSpec.spec)
, ("Feature.Query.NullsStripSpec" , Feature.Query.NullsStripSpec.spec)
, ("Feature.Query.PgErrorCodeMappingSpec" , Feature.Query.ErrorSpec.pgErrorCodeMapping)
, ("Feature.Query.PgSafeUpdateSpec.disabledSpec" , Feature.Query.PgSafeUpdateSpec.disabledSpec)
, ("Feature.Query.PlanSpec.disabledSpec" , Feature.Query.PlanSpec.disabledSpec)
, ("Feature.Query.PreferencesSpec" , Feature.Query.PreferencesSpec.spec)
, ("Feature.Query.QuerySpec" , Feature.Query.QuerySpec.spec actualPgVersion)
, ("Feature.Query.QuerySpec" , Feature.Query.QuerySpec.spec)
, ("Feature.Query.RawOutputTypesSpec" , Feature.Query.RawOutputTypesSpec.spec)
, ("Feature.Query.RelatedQueriesSpec" , Feature.Query.RelatedQueriesSpec.spec)
, ("Feature.Query.RpcSpec" , Feature.Query.RpcSpec.spec)
Expand Down

0 comments on commit f195290

Please sign in to comment.