feat: Drop support for pg 9.6

This commit is contained in:
Wolfgang Walther
2024-06-15 17:23:34 +02:00
committed by Wolfgang Walther
parent ec110720dc
commit daa77d17aa
20 changed files with 401 additions and 656 deletions
+1 -1
View File
@@ -67,7 +67,7 @@ jobs:
strategy:
fail-fast: false
matrix:
pgVersion: ["9_6", 10, 11, 12, 13, 14, 15, 16]
pgVersion: [10, 11, 12, 13, 14, 15, 16]
name: PG ${{ matrix.pgVersion }}
runs-on: ubuntu-22.04
defaults:
+4
View File
@@ -5,6 +5,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## Unreleased
### Changed
- #2052, Dropped support for PostgreSQL 9.6 - @wolfgangwalther
## [12.2.0] - 2024-06-11
### Added
-1
View File
@@ -56,7 +56,6 @@ let
{ 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 ]); }
{ name = "postgresql-9_6"; postgresql = pkgs.postgresql_9_6.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
];
# Dynamic derivation for PostgREST
+3 -3
View File
@@ -16,14 +16,14 @@ Supported PostgreSQL versions
=============================
=============== =================================
**Supported** PostgreSQL >= 9.6
**Supported** PostgreSQL >= 10
=============== =================================
PostgREST works with all PostgreSQL versions starting from 9.6.
PostgREST works with all PostgreSQL versions starting from 10.
.. note::
Support for PostgreSQL versions 9.6, 10 and 11 is deprecated. From this on version onwards, PostgREST will only support non-end-of-life PostgreSQL versions.
Support for PostgreSQL versions 10 and 11 is deprecated. From this on version onwards, PostgREST will only support non-end-of-life PostgreSQL versions.
See https://www.postgresql.org/support/versioning/.
+2 -2
View File
@@ -79,7 +79,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
...
@@ -103,7 +103,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
...
-5
View File
@@ -20,9 +20,4 @@ in
postgis = prev.postgresql_10.pkgs.postgis.overrideAttrs (_: postgis_3_2_3);
};
};
postgresql_9_6 = prev.postgresql_9_6.override { this = final.postgresql_11; } // {
pkgs = prev.postgresql_9_6.pkgs // {
postgis = prev.postgresql_9_6.pkgs.postgis.overrideAttrs (_: postgis_3_2_3);
};
};
}
-15
View File
@@ -2,21 +2,6 @@ _: _:
# Overlay that adds legacy versions of PostgreSQL that are supported by
# PostgREST.
{
# PostgreSQL 9.6 was removed from Nixpkgs with
# https://github.com/NixOS/nixpkgs/commit/757dd008b2f2926fc0f7688fa8189f930ea47521
# We pin its parent commit to get the last version that was available.
postgresql_9_6 =
let
rev = "571cbf3d1db477058303cef8754fb85a14e90eb7";
tarballHash = "0q74wn418i1bn5sssacmw8ykpmqvzr0s93sj6pbs3rf6bf134fkz";
pinnedPkgs =
builtins.fetchTarball {
url = "https://github.com/nixos/nixpkgs/archive/${rev}.tar.gz";
sha256 = tarballHash;
};
in
(import pinnedPkgs { }).pkgs.postgresql_9_6;
# 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.
+1 -6
View File
@@ -3,8 +3,6 @@
module PostgREST.Config.PgVersion
( PgVersion(..)
, minimumPgVersion
, pgVersion96
, pgVersion100
, pgVersion109
, pgVersion110
, pgVersion112
@@ -33,10 +31,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" "9.6"
minimumPgVersion = pgVersion100
pgVersion100 :: PgVersion
pgVersion100 = PgVersion 100000 "10" "10"
+1 -1
View File
@@ -178,7 +178,7 @@ actionQuery (DbCall plan@CallReadPlan{..}) conf@AppConfig{..} apiReq@ApiRequest{
actionQuery (MaybeDb plan@InspectPlan{ipSchema=tSchema}) AppConfig{..} _ pgVer sCache =
lift $ case configOpenApiMode of
OAFollowPriv -> do
tableAccess <- SQL.statement [tSchema] (SchemaCache.accessibleTables pgVer configDbPreparedStatements)
tableAccess <- SQL.statement [tSchema] (SchemaCache.accessibleTables configDbPreparedStatements)
MaybeDbResult plan . Just <$> ((,,)
(HM.filterWithKey (\qi _ -> S.member qi tableAccess) $ SchemaCache.dbTables sCache)
<$> SQL.statement (tSchema, configDbHoistedTxSettings) (SchemaCache.accessibleFuncs pgVer configDbPreparedStatements)
+10 -18
View File
@@ -47,8 +47,7 @@ import PostgREST.Config (AppConfig (..))
import PostgREST.Config.Database (TimezoneNames,
pgVersionStatement,
toIsolationLevel)
import PostgREST.Config.PgVersion (PgVersion, pgVersion100,
pgVersion110,
import PostgREST.Config.PgVersion (PgVersion, pgVersion110,
pgVersion120)
import PostgREST.SchemaCache.Identifiers (AccessSet, FieldName,
QualifiedIdentifier (..),
@@ -477,8 +476,8 @@ schemaDescription =
where
n.nspname = $1 |]
accessibleTables :: PgVersion -> Bool -> SQL.Statement [Schema] AccessSet
accessibleTables pgVer =
accessibleTables :: Bool -> SQL.Statement [Schema] AccessSet
accessibleTables =
SQL.Statement sql (arrayParam HE.text) decodeAccessibleIdentifiers
where
sql = [q|
@@ -494,10 +493,9 @@ accessibleTables pgVer =
pg_has_role(c.relowner, 'USAGE')
or has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER')
or has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES')
) |] <>
relIsPartition <>
"ORDER BY table_schema, table_name"
relIsPartition = if pgVer >= pgVersion100 then " AND not c.relispartition " else mempty
)
AND not c.relispartition
ORDER BY table_schema, table_name|]
{-
Adds M2O and O2O relationships for views to tables, tables to views, and views to views. The example below is taken from the test fixtures, but the views names/colnames were modified.
@@ -810,11 +808,10 @@ tablesSqlQuery pgVer =
LEFT JOIN tbl_pk_cols tpks ON n.nspname = tpks.table_schema AND c.relname = tpks.table_name
LEFT JOIN columns_agg cols_agg ON n.nspname = cols_agg.table_schema AND c.relname = cols_agg.table_name
WHERE c.relkind IN ('v','r','m','f','p')
AND n.nspname NOT IN ('pg_catalog', 'information_schema') |] <>
relIsPartition <>
"ORDER BY table_schema, table_name"
AND n.nspname NOT IN ('pg_catalog', 'information_schema')
AND not c.relispartition
ORDER BY table_schema, table_name|]
where
relIsPartition = if pgVer >= pgVersion100 then " AND not c.relispartition " else mempty
columnDefault -- typbasetype and typdefaultbin handles `CREATE DOMAIN .. DEFAULT val`, attidentity/attgenerated handles generated columns, pg_get_expr gets the default of a column
| pgVer >= pgVersion120 = [q|
CASE
@@ -823,15 +820,10 @@ tablesSqlQuery pgVer =
WHEN a.attgenerated = 's' THEN null
ELSE pg_get_expr(ad.adbin, ad.adrelid)::text
END|]
| pgVer >= pgVersion100 = [q|
CASE
WHEN t.typbasetype != 0 THEN pg_get_expr(t.typdefaultbin, 0)
WHEN a.attidentity = 'd' THEN format('nextval(%s)', quote_literal(seqsch.nspname || '.' || seqclass.relname))
ELSE pg_get_expr(ad.adbin, ad.adrelid)::text
END|]
| otherwise = [q|
CASE
WHEN t.typbasetype != 0 THEN pg_get_expr(t.typdefaultbin, 0)
WHEN a.attidentity = 'd' THEN format('nextval(%s)', quote_literal(seqsch.nspname || '.' || seqclass.relname))
ELSE pg_get_expr(ad.adbin, ad.adrelid)::text
END|]
+1 -3
View File
@@ -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)
@@ -269,7 +268,6 @@ spec actualPgVersion = describe "OpenAPI" $ do
]
|]
when (actualPgVersion >= pgVersion100) $ do
describe "Partitioned table" $
it "includes partitioned table properties" $ do
+1 -3
View File
@@ -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
@@ -25,7 +24,6 @@ spec actualPgVersion = describe "Allow header" $ do
it "fails with 404 for an unknown table" $
request methodOptions "/unknown" [] "" `shouldRespondWith` 404
when (actualPgVersion >= pgVersion100) $
context "a partitioned table" $ do
it "includes read/write methods for writeable partitioned tables" $ do
r <- request methodOptions "/car_models" [] ""
+3 -9
View File
@@ -11,10 +11,9 @@ import Test.Hspec.Wai
import Test.Hspec.Wai.JSON
import Text.Heredoc
import PostgREST.Config.PgVersion (PgVersion, pgVersion100,
pgVersion110, pgVersion112,
pgVersion120, pgVersion130,
pgVersion140)
import PostgREST.Config.PgVersion (PgVersion, pgVersion110,
pgVersion112, pgVersion120,
pgVersion130, pgVersion140)
import Protolude hiding (get)
import SpecHelper
@@ -494,8 +493,6 @@ spec actualPgVersion = do
{"id": 205, "body": "zzz"}]|] `shouldRespondWith` 400
context "apply defaults on missing values" $ do
-- inserting the array fails on pg 9.6, but the feature should work normally
when (actualPgVersion >= pgVersion100) $
it "inserts table default values(field-with_sep) when json keys are undefined" $
request methodPost "/complex_items?columns=id,name,field-with_sep,arr_data" [("Prefer", "return=representation"), ("Prefer", "missing=default")]
[json|[
@@ -537,7 +534,6 @@ spec actualPgVersion = do
, matchHeaders = ["Preference-Applied" <:> "missing=default, return=representation"]
}
when (actualPgVersion >= pgVersion100) $
it "inserts a default on a generated by default as identity column" $
request methodPost "/channels?columns=id,data,slug&select=data,slug" [("Prefer", "return=representation"), ("Prefer", "missing=default")]
[json| { "slug": "foo" } |]
@@ -798,8 +794,6 @@ spec actualPgVersion = do
}
-- Data representations for payload parsing requires Postgres 10 or above.
when (actualPgVersion >= pgVersion100) $ do
describe "Data representations" $ do
context "on regular table" $ do
it "parses values in POST body" $
+4 -39
View File
@@ -7,13 +7,11 @@ import Test.Hspec
import Test.Hspec.Wai
import Test.Hspec.Wai.JSON
import PostgREST.Config.PgVersion (PgVersion, pgVersion100)
import Protolude hiding (get)
import SpecHelper
spec :: PgVersion -> SpecWith ((), Application)
spec actualPgVersion = describe "PostGIS features" $
spec :: SpecWith ((), Application)
spec = describe "PostGIS features" $
context "GeoJSON output" $ do
it "works for a table that has a geometry column" $
request methodGet "/shops"
@@ -56,8 +54,7 @@ spec actualPgVersion = describe "PostGIS features" $
it "works with resource embedding" $
request methodGet "/shops?select=*,shop_bles(*)&id=eq.1"
[("Accept", "application/geo+json")] "" `shouldRespondWith`
(if actualPgVersion >= pgVersion100
then [json| {
[json| {
"type": "FeatureCollection",
"features": [
{
@@ -83,32 +80,6 @@ spec actualPgVersion = describe "PostGIS features" $
}
]
}|]
else [json| {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": { "coordinates": [ -71.10044, 42.373695 ], "type": "Point" },
"properties": {
"address": "1369 Cambridge St", "id": 1,
"shop_bles": [
{ "id": 1, "name": "Beacon-1", "shop_id": 1 ,
"coords": { "coordinates": [ -71.10044, 42.373695 ], "type": "Point" },
"range_area": {
"coordinates": [ [ [ -71.10045254230499, 42.37387083326593 ], [ -71.10048070549963, 42.37377126199953 ], [ -71.10039688646793, 42.37375838212269 ], [ -71.10037006437777, 42.37385844878863 ], [ -71.10045254230499, 42.37387083326593 ] ] ],
"type": "Polygon" }
},
{ "coords": { "coordinates": [ -71.10044, 42.373695 ], "type": "Point" },
"id": 2, "name": "Beacon-2", "shop_id": 1,
"range_area": {
"coordinates": [ [ [ -71.10034391283989, 42.37385299961788 ], [ -71.10036939382553, 42.373756895982865 ], [ -71.1002916097641, 42.373745997623224 ], [ -71.1002641171217, 42.37384408279195 ], [ -71.10034391283989, 42.37385299961788 ] ] ],
"type": "Polygon" }
}
]
}
}
]
}|])
{ matchHeaders = ["Content-Type" <:> "application/geo+json; charset=utf-8"] }
it "works with RPC" $
@@ -219,14 +190,8 @@ spec actualPgVersion = describe "PostGIS features" $
it "gets the geojson geometry object with the regular application/json output" $
request methodGet "/shops?id=eq.1" [] "" `shouldRespondWith`
(if actualPgVersion >= pgVersion100
then [json|[{
[json|[{
"id":1,"address":"1369 Cambridge St",
"shop_geom":{"type":"Point","crs":{"type":"name","properties":{"name":"EPSG:4326"}},"coordinates":[-71.10044,42.373695]}
}]|]
else [json|[{
"address": "1369 Cambridge St",
"id": 1,
"shop_geom": { "coordinates": [ -71.10044, 42.373695 ], "type": "Point" }
}]|])
{ matchHeaders = [matchContentTypeJson] }
+3 -52
View File
@@ -11,9 +11,9 @@ import Test.Hspec.Wai
import Test.Hspec.Wai.JSON
import Text.Heredoc
import PostgREST.Config.PgVersion (PgVersion, pgVersion100,
pgVersion109, pgVersion110,
pgVersion112, pgVersion114)
import PostgREST.Config.PgVersion (PgVersion, pgVersion109,
pgVersion110, pgVersion112,
pgVersion114)
import Protolude hiding (get)
import SpecHelper
@@ -530,38 +530,6 @@ 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| {
@@ -635,14 +603,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)" $
@@ -765,14 +725,6 @@ 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}" } |]
`shouldRespondWith`
[json|["hi", "hello", "there"]|]
when (actualPgVersion >= pgVersion100) $ do
it "works with POST (Postgres >= 10)" $
post "/rpc/variadic_param"
[json| { "v": ["hi", "hello", "there"] } |]
@@ -822,7 +774,6 @@ spec actualPgVersion =
`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`
+2 -108
View File
@@ -7,14 +7,11 @@ import Network.HTTP.Types
import Test.Hspec.Wai
import Test.Hspec.Wai.JSON
import PostgREST.Config.PgVersion (PgVersion, pgVersion100)
import Protolude hiding (get)
import SpecHelper
spec :: PgVersion -> SpecWith ((), Application)
spec actualPgVersion = do
spec :: SpecWith ((), Application)
spec = do
describe "Patching record" $ do
context "to unknown uri" $
it "indicates no table found by returning 404" $
@@ -623,110 +620,7 @@ spec actualPgVersion = do
}
-- Data representations for payload parsing requires Postgres 10 or above.
when (actualPgVersion >= pgVersion100) $ do
describe "Data representations" $ do
context "for a single row" $ do
it "parses values in payload" $
request methodPatch "/datarep_todos?id=eq.2" [("Prefer", "return=headers-only")]
[json| {"label_color": "#221100", "due_at": "2019-01-03T11:00:00Z"} |]
`shouldRespondWith`
""
{ matchStatus = 204
, matchHeaders = [ matchHeaderAbsent hContentType
, "Content-Range" <:> "0-0/*"]
}
it "parses values in payload and formats individually selected values in return=representation" $
request methodPatch "/datarep_todos?id=eq.2&select=id,label_color" [("Prefer", "return=representation")]
[json| {"label_color": "#221100", "due_at": "2019-01-03T11:00:00Z"} |]
`shouldRespondWith`
[json| [{"id":2, "label_color": "#221100"}] |]
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "application/json; charset=utf-8"
, "Content-Range" <:> "0-0/*"
, "Preference-Applied" <:> "return=representation"]
}
it "parses values in payload and formats values in return=representation" $
request methodPatch "/datarep_todos?id=eq.2" [("Prefer", "return=representation")]
[json| {"label_color": "#221100", "due_at": "2019-01-03T11:00:20Z", "icon_image": "3q2+7w"} |]
`shouldRespondWith`
[json| [{"id":2,"name":"Essay","label_color":"#221100","due_at":"2019-01-03T11:00:20Z","icon_image":"3q2+7w==","created_at":1513213350,"budget":"100000000000000.13"}] |]
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "application/json; charset=utf-8"
, "Content-Range" <:> "0-0/*"
, "Preference-Applied" <:> "return=representation"]
}
it "parses values in payload and formats star mixed selected values in return=representation" $
request methodPatch "/datarep_todos?id=eq.2&select=due_at,*" [("Prefer", "return=representation")]
[json| {"label_color": "#221100", "due_at": "2019-01-03T11:00:00Z", "created_at": 0} |]
`shouldRespondWith`
-- end up with due_at twice here but that's unrelated to data reps
[json| [{"due_at":"2019-01-03T11:00:00Z","id":2,"name":"Essay","label_color":"#221100","due_at":"2019-01-03T11:00:00Z","icon_image":null,"created_at":0,"budget":"100000000000000.13"}] |]
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "application/json; charset=utf-8"
, "Content-Range" <:> "0-0/*"
, "Preference-Applied" <:> "return=representation"]
}
context "for multiple rows" $ do
it "parses values in payload and formats individually selected values in return=representation" $
request methodPatch "/datarep_todos?id=lt.4&select=id,name,label_color" [("Prefer", "return=representation")]
[json| {"label_color": "#221100", "due_at": "2019-01-03T11:00:00Z"} |]
`shouldRespondWith`
[json| [
{"id":1, "name": "Report", "label_color": "#221100"},
{"id":2, "name": "Essay", "label_color": "#221100"},
{"id":3, "name": "Algebra", "label_color": "#221100"}
] |]
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "application/json; charset=utf-8"
, "Content-Range" <:> "0-2/*"
, "Preference-Applied" <:> "return=representation"]
}
it "parses values in payload and formats values in return=representation" $
request methodPatch "/datarep_todos?id=lt.4" [("Prefer", "return=representation")]
[json| {"label_color": "#221100", "due_at": "2019-01-03T11:00:00Z", "icon_image": "3q2+7w="} |]
`shouldRespondWith`
[json| [
{"id":1,"name":"Report","label_color":"#221100","due_at":"2019-01-03T11:00:00Z","icon_image":"3q2+7w==","created_at":1513213350,"budget":"12.50"},
{"id":2,"name":"Essay","label_color":"#221100","due_at":"2019-01-03T11:00:00Z","icon_image":"3q2+7w==","created_at":1513213350,"budget":"100000000000000.13"},
{"id":3,"name":"Algebra","label_color":"#221100","due_at":"2019-01-03T11:00:00Z","icon_image":"3q2+7w==","created_at":1513213350,"budget":"0.00"}
] |]
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "application/json; charset=utf-8"
, "Content-Range" <:> "0-2/*"
, "Preference-Applied" <:> "return=representation"]
}
context "with ?columns parameter" $ do
it "ignores json keys not included in ?columns; parses only the ones specified" $
request methodPatch "/datarep_todos?id=eq.2&columns=due_at" [("Prefer", "return=representation")]
[json| {"due_at": "2019-01-03T11:00:00Z", "smth": "here", "label_color": "invalid", "fake_id": 13} |]
`shouldRespondWith`
[json| [
{"id":2,"name":"Essay","label_color":"#000100","due_at":"2019-01-03T11:00:00Z","icon_image":null,"created_at":1513213350,"budget":"100000000000000.13"}
] |]
{ matchStatus = 200
, matchHeaders = ["Content-Type" <:> "application/json; charset=utf-8"
, "Content-Range" <:> "0-0/*"
, "Preference-Applied" <:> "return=representation"]
}
it "fails if at least one specified column doesn't exist" $
request methodPatch "/datarep_todos?id=eq.2&columns=label_color,helicopters" [("Prefer", "return=representation")]
[json| {"due_at": "2019-01-03T11:00:00Z", "smth": "here", "label_color": "invalid", "fake_id": 13} |]
`shouldRespondWith`
[json| {"code":"PGRST204","details":null,"hint":null,"message":"Could not find the 'helicopters' column of 'datarep_todos' in the schema cache"} |]
{ matchStatus = 400
, matchHeaders = ["Content-Type" <:> "application/json; charset=utf-8"]
}
it "ignores json keys and gives 200 if no record updated" $
request methodPatch "/datarep_todos?id=eq.2001&columns=label_color" [("Prefer", "return=representation")]
[json| {"due_at": "2019-01-03T11:00:00Z", "smth": "here", "label_color": "invalid", "fake_id": 13} |]
`shouldRespondWith` 200
context "on a view" $ do
context "for a single row" $ do
it "parses values in payload" $
request methodPatch "/datarep_todos_computed?id=eq.2" [("Prefer", "return=headers-only")]
+2 -2
View File
@@ -162,7 +162,7 @@ main = do
, ("Feature.Query.RpcSpec" , Feature.Query.RpcSpec.spec actualPgVersion)
, ("Feature.Query.SingularSpec" , Feature.Query.SingularSpec.spec)
, ("Feature.Query.SpreadQueriesSpec" , Feature.Query.SpreadQueriesSpec.spec)
, ("Feature.Query.UpdateSpec" , Feature.Query.UpdateSpec.spec actualPgVersion)
, ("Feature.Query.UpdateSpec" , Feature.Query.UpdateSpec.spec)
, ("Feature.Query.UpsertSpec" , Feature.Query.UpsertSpec.spec actualPgVersion)
]
@@ -228,7 +228,7 @@ main = do
-- this test runs with an extra search path
parallel $ before extraSearchPathApp $ do
describe "Feature.ExtraSearchPathSpec" Feature.ExtraSearchPathSpec.spec
describe "Feature.Query.PostGISSpec" $ Feature.Query.PostGISSpec.spec actualPgVersion
describe "Feature.Query.PostGISSpec" Feature.Query.PostGISSpec.spec
-- this test runs with a root spec function override
parallel $ before rootSpecApp $
+5 -7
View File
@@ -680,14 +680,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');
+1 -7
View File
@@ -41,13 +41,7 @@ GRANT USAGE ON SEQUENCE
, leak_id_seq
TO postgrest_test_anonymous;
DO $do$
BEGIN
IF current_setting('server_version_num')::INT >= 100000 THEN
GRANT USAGE ON SEQUENCE channels_id_seq TO postgrest_test_anonymous;
END IF;
END
$do$;
GRANT USAGE ON SEQUENCE channels_id_seq TO postgrest_test_anonymous;
-- Privileges for non anonymous users
GRANT USAGE ON SCHEMA test TO postgrest_test_author;
+11 -28
View File
@@ -2289,26 +2289,22 @@ create table private.rollen (
);
-- Tables used for testing embedding between partitioned tables
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(
create table test.car_models(
name varchar(64) not null,
year int not null
) partition by list (year);
) 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
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
create table test.car_models_default partition of test.car_models
for values in (1981,1997,2001,2013);
end if;
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 (
@@ -2492,12 +2488,8 @@ 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 *
CREATE VIEW test.xml AS
SELECT *
FROM (SELECT ''::xml AS data) _,
XMLTABLE(
''
@@ -2505,9 +2497,6 @@ BEGIN
COLUMNS id int PATH '@id',
premier_name text PATH 'PREMIER_NAME' DEFAULT 'not specified'
);
END IF;
END
$do$;
-- https://github.com/PostgREST/postgrest/issues/1543
CREATE TYPE complex AS (
@@ -3277,17 +3266,11 @@ create table test.tbl_w_json(
data json
);
DO $do$
BEGIN
IF current_setting('server_version_num')::INT >= 100000 THEN
CREATE TABLE test.channels (
CREATE TABLE test.channels (
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
data jsonb DEFAULT '{"foo": "bar"}',
slug text
);
END IF;
END
$do$;
);
CREATE FUNCTION test.is_superuser() RETURNS boolean
LANGUAGE sql