Skip to content

Commit 2fe5830

Browse files
test: consistently analyze tables exactly once
Disabling the autovacuum daemon should also help reproducibility in theory, although I don't know of any cases where we hit a problem with that.
1 parent 8b780d4 commit 2fe5830

10 files changed

Lines changed: 33 additions & 34 deletions

File tree

nix/tools/withTools.nix

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ let
1515
let
1616
commandName = "postgrest-with-${name}";
1717
postgresqlConf = writeText "postgresql.conf" "
18+
autovacuum = false
1819
listen_addresses = ''
1920
log_statement = all
2021
";
@@ -143,6 +144,7 @@ let
143144
load_start=$SECONDS
144145
>&2 printf "${commandName}: Loading fixtures under the postgres role..."
145146
psql -U postgres -v PGUSER="$PGUSER" -v ON_ERROR_STOP=1 -f "$_arg_fixtures" >> "$setuplog"
147+
psql -U postgres -v ON_ERROR_STOP=1 -c "VACUUM ANALYZE;" >> "$setuplog"
146148
load_end=$((SECONDS - load_start))
147149
>&2 printf " done in %ss. Running command...\n" "$load_end"
148150
fi

src/PostgREST/Config/PgVersion.hs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ module PostgREST.Config.PgVersion
44
( PgVersion(..)
55
, minimumPgVersion
66
, pgVersion150
7-
, pgVersion170
87
, pgVersion180
98
) where
109

@@ -33,8 +32,5 @@ pgVersion140 = PgVersion 140000 "14.0" "14.0"
3332
pgVersion150 :: PgVersion
3433
pgVersion150 = PgVersion 150000 "15.0" "15.0"
3534

36-
pgVersion170 :: PgVersion
37-
pgVersion170 = PgVersion 170000 "17.0" "17.0"
38-
3935
pgVersion180 :: PgVersion
4036
pgVersion180 = PgVersion 180000 "18.0" "18.0"

test/io/test_io.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -937,12 +937,12 @@ def test_log_query(level, defaultenv):
937937
response = postgrest.session.get(
938938
"/projects", headers={"Prefer": "count=estimated"}
939939
)
940-
assert response.status_code == 206
940+
assert response.status_code == 200
941941

942942
response = postgrest.session.get(
943943
"/projects", headers={"Prefer": "count=planned"}
944944
)
945-
assert response.status_code == 206
945+
assert response.status_code == 200
946946

947947
response = postgrest.session.get("/infinite_recursion")
948948
assert response.status_code == 500

test/spec/Feature/Query/AggregateFunctionsSpec.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,24 +154,24 @@ allowed =
154154
[json|[{"total_budget": 9501.06}]|]
155155
{ matchHeaders = [matchContentTypeJson] }
156156
it "supports aggregates from a spread relationships grouped by spreaded fields from other relationships" $ do
157-
get "/processes?select=...process_costs(cost.sum()),...process_categories(name)" `shouldRespondWith`
157+
get "/processes?select=...process_costs(cost.sum()),...process_categories(name)&order=process_categories(name)" `shouldRespondWith`
158158
[json|[
159159
{"sum": 400.00, "name": "Batch"},
160160
{"sum": 350.00, "name": "Mass"}]|]
161161
{ matchHeaders = [matchContentTypeJson] }
162-
get "/processes?select=...process_costs(cost_sum:cost.sum()),...process_categories(category:name)" `shouldRespondWith`
162+
get "/processes?select=...process_costs(cost_sum:cost.sum()),...process_categories(category:name)&order=process_categories(category)" `shouldRespondWith`
163163
[json|[
164164
{"cost_sum": 400.00, "category": "Batch"},
165165
{"cost_sum": 350.00, "category": "Mass"}]|]
166166
{ matchHeaders = [matchContentTypeJson] }
167167
it "supports aggregates on spreaded fields from nested relationships" $ do
168-
get "/process_supervisor?select=...processes(factory_id,...process_costs(cost.sum()))" `shouldRespondWith`
168+
get "/process_supervisor?select=...processes(factory_id,...process_costs(cost.sum()))&order=processes(factory_id).desc" `shouldRespondWith`
169169
[json|[
170170
{"factory_id": 3, "sum": 110.00},
171171
{"factory_id": 2, "sum": 500.00},
172172
{"factory_id": 1, "sum": 350.00}]|]
173173
{ matchHeaders = [matchContentTypeJson] }
174-
get "/process_supervisor?select=...processes(factory_id,...process_costs(cost_sum:cost.sum()))" `shouldRespondWith`
174+
get "/process_supervisor?select=...processes(factory_id,...process_costs(cost_sum:cost.sum()))&order=processes(factory_id).desc" `shouldRespondWith`
175175
[json|[
176176
{"factory_id": 3, "cost_sum": 110.00},
177177
{"factory_id": 2, "cost_sum": 500.00},

test/spec/Feature/Query/EmbedDisambiguationSpec.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ spec =
236236
[json|[{"createdAt":"2015-12-08T04:22:57.472738","article":{"id": 1},"user":{"name": "Angela Martin"}}]|]
237237

238238
it "can specify a view!fk" $
239-
get "/message?select=id,body,sender:person_detail!message_sender_fkey(name,sent),recipient:person_detail!message_recipient_fkey(name,received)&id=lt.4" `shouldRespondWith`
239+
get "/message?select=id,body,sender:person_detail!message_sender_fkey(name,sent),recipient:person_detail!message_recipient_fkey(name,received)&id=lt.4&order=id" `shouldRespondWith`
240240
[json|
241241
[{"id":1,"body":"Hello Jane","sender":{"name":"John","sent":2},"recipient":{"name":"Jane","received":2}},
242242
{"id":2,"body":"Hi John","sender":{"name":"Jane","sent":1},"recipient":{"name":"John","received":1}},

test/spec/Feature/Query/PlanSpec.hs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,11 @@ import Test.Hspec hiding (pendingWith)
1515
import Test.Hspec.Wai
1616
import Test.Hspec.Wai.JSON
1717

18-
import PostgREST.Config.PgVersion (PgVersion, pgVersion170)
19-
import Protolude hiding (get)
18+
import Protolude hiding (get)
2019
import SpecHelper
2120

22-
spec :: PgVersion -> SpecWith ((), Application)
23-
spec actualPgVersion = do
21+
spec :: SpecWith ((), Application)
22+
spec = do
2423
describe "read table/view plan" $ do
2524
it "outputs the total cost for a single filter on a table" $ do
2625
r <- request methodGet "/projects?id=in.(1,2,3)"
@@ -34,7 +33,7 @@ spec actualPgVersion = do
3433
resHeaders `shouldSatisfy` elem ("Content-Type", "application/vnd.pgrst.plan+json; for=\"application/json\"; charset=utf-8")
3534
resHeaders `shouldSatisfy` notZeroContentLength
3635
resStatus `shouldBe` Status { statusCode = 200, statusMessage="OK" }
37-
totalCost `shouldBe` (if actualPgVersion >= pgVersion170 then 11.32 else 15.63)
36+
totalCost `shouldBe` 1.11
3837

3938
it "outputs the total cost for a single filter on a view" $ do
4039
r <- request methodGet "/projects_view?id=gt.2"
@@ -47,7 +46,7 @@ spec actualPgVersion = do
4746
liftIO $ do
4847
resHeaders `shouldSatisfy` elem ("Content-Type", "application/vnd.pgrst.plan+json; for=\"application/json\"; charset=utf-8")
4948
resStatus `shouldBe` Status { statusCode = 200, statusMessage="OK" }
50-
totalCost `shouldBe` 24.28
49+
totalCost `shouldBe` 1.1
5150

5251
it "outputs blocks info when using the buffers option" $ do
5352
r <- request methodGet "/projects" (acceptHdrs "application/vnd.pgrst.plan+json; options=buffers") ""
@@ -143,7 +142,7 @@ spec actualPgVersion = do
143142
resHeaders `shouldSatisfy` elem ("Content-Type", "application/vnd.pgrst.plan+json; for=\"application/json\"; charset=utf-8")
144143
resHeaders `shouldSatisfy` notZeroContentLength
145144
resStatus `shouldBe` Status { statusCode = 200, statusMessage="OK" }
146-
totalCost `shouldBe` 8.23
145+
totalCost `shouldBe` 1.13
147146

148147
it "outputs the total cost for a delete" $ do
149148
r <- request methodDelete "/projects?id=in.(1,2,3)"
@@ -157,7 +156,7 @@ spec actualPgVersion = do
157156
resHeaders `shouldSatisfy` elem ("Content-Type", "application/vnd.pgrst.plan+json; for=\"application/json\"; charset=utf-8")
158157
resHeaders `shouldSatisfy` notZeroContentLength
159158
resStatus `shouldBe` Status { statusCode = 200, statusMessage="OK" }
160-
totalCost `shouldBe` (if actualPgVersion >= pgVersion170 then 11.37 else 15.68)
159+
totalCost `shouldBe` 1.16
161160

162161
it "outputs the total cost for a single upsert" $ do
163162
r <- request methodPut "/tiobe_pls?name=eq.Go"
@@ -490,7 +489,7 @@ spec actualPgVersion = do
490489

491490
liftIO $ do
492491
resHeaders `shouldSatisfy` elem ("Content-Type", "application/vnd.pgrst.plan+json; for=\"application/json\"; options=analyze; charset=utf-8")
493-
totalCost `shouldSatisfy` (> 49.0)
492+
totalCost `shouldSatisfy` (> 2.0)
494493
aggregateQty `shouldSatisfy` (> 1)
495494

496495
context "functions with count=exact" $ do

test/spec/Feature/Query/QuerySpec.hs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -692,13 +692,13 @@ spec = do
692692
{ matchHeaders = [matchContentTypeJson] }
693693

694694
it "requesting data using many<->many relation defined by composite keys" $
695-
get "/users_tasks?user_id=eq.1&task_id=eq.1&select=user_id,files(filename,content)" `shouldRespondWith`
696-
[json|[{"user_id":1,"files":[{"filename":"autoexec.bat","content":"@ECHO OFF"},{"filename":"command.com","content":"#include <unix.h>"},{"filename":"README.md","content":"# make $$$!"}]}]|]
695+
get "/users_tasks?user_id=eq.1&task_id=eq.1&select=user_id,files(filename,content)&files.order=filename" `shouldRespondWith`
696+
[json|[{"user_id":1,"files":[{"filename":"README.md","content":"# make $$$!"},{"filename":"autoexec.bat","content":"@ECHO OFF"},{"filename":"command.com","content":"#include <unix.h>"}]}]|]
697697
{ matchHeaders = [matchContentTypeJson] }
698698

699699
it "requesting data using many<->many (composite keys) relation using hint" $
700-
get "/users_tasks?user_id=eq.1&task_id=eq.1&select=user_id,files!touched_files(filename,content)" `shouldRespondWith`
701-
[json|[{"user_id":1,"files":[{"filename":"autoexec.bat","content":"@ECHO OFF"},{"filename":"command.com","content":"#include <unix.h>"},{"filename":"README.md","content":"# make $$$!"}]}]|]
700+
get "/users_tasks?user_id=eq.1&task_id=eq.1&select=user_id,files!touched_files(filename,content)&files.order=filename" `shouldRespondWith`
701+
[json|[{"user_id":1,"files":[{"filename":"README.md","content":"# make $$$!"},{"filename":"autoexec.bat","content":"@ECHO OFF"},{"filename":"command.com","content":"#include <unix.h>"}]}]|]
702702
{ matchHeaders = [matchContentTypeJson] }
703703

704704
it "requesting children with composite key" $
@@ -1607,11 +1607,11 @@ spec = do
16071607
] |]
16081608
{ matchHeaders = [matchContentTypeJson] }
16091609
it "formats through join" $
1610-
get "/datarep_next_two_todos?select=id,name,first_item:datarep_todos!datarep_next_two_todos_first_item_id_fkey(label_color,due_at)" `shouldRespondWith`
1610+
get "/datarep_next_two_todos?select=id,name,first_item:datarep_todos!datarep_next_two_todos_first_item_id_fkey(label_color,due_at)&order=id" `shouldRespondWith`
16111611
[json| [{"id":1,"name":"school related","first_item":{"label_color":"#000100","due_at":"2018-01-03T00:00:00Z"}},{"id":2,"name":"do these first","first_item":{"label_color":"#000000","due_at":"2018-01-02T00:00:00Z"}}] |]
16121612
{ matchHeaders = [matchContentTypeJson] }
16131613
it "formats through join with star select" $
1614-
get "/datarep_next_two_todos?select=id,name,second_item:datarep_todos!datarep_next_two_todos_second_item_id_fkey(*)" `shouldRespondWith`
1614+
get "/datarep_next_two_todos?select=id,name,second_item:datarep_todos!datarep_next_two_todos_second_item_id_fkey(*)&order=id" `shouldRespondWith`
16151615
[json| [
16161616
{"id":1,"name":"school related","second_item":{"id":3,"name":"Algebra","label_color":"#01E240","due_at":"2018-01-01T14:12:34.123456Z","icon_image":null,"created_at":1513213350,"budget":"0.00"}},
16171617
{"id":2,"name":"do these first","second_item":{"id":3,"name":"Algebra","label_color":"#01E240","due_at":"2018-01-01T14:12:34.123456Z","icon_image":null,"created_at":1513213350,"budget":"0.00"}}
@@ -1645,7 +1645,7 @@ spec = do
16451645
] |]
16461646
{ matchHeaders = [matchContentTypeJson] }
16471647
it "uses text parser on value for filter across relations" $
1648-
get "/datarep_next_two_todos?select=id,name,datarep_todos!datarep_next_two_todos_first_item_id_fkey(label_color,due_at)&datarep_todos.label_color=neq.000100" `shouldRespondWith`
1648+
get "/datarep_next_two_todos?select=id,name,datarep_todos!datarep_next_two_todos_first_item_id_fkey(label_color,due_at)&datarep_todos.label_color=neq.000100&order=id" `shouldRespondWith`
16491649
[json| [{"id":1,"name":"school related","datarep_todos":null},{"id":2,"name":"do these first","datarep_todos":{"label_color":"#000000","due_at":"2018-01-02T00:00:00Z"}}] |]
16501650
{ matchHeaders = [matchContentTypeJson] }
16511651
-- This is not supported by data reps (would be hard to make it work with high performance). So the test just

test/spec/Feature/Query/RelatedQueriesSpec.hs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ spec = describe "related queries" $ do
323323
]|]
324324
{ matchStatus = 206
325325
, matchHeaders = [ matchContentTypeJson
326-
, "Content-Range" <:> "0-3/1200" ]
326+
, "Content-Range" <:> "0-3/5" ]
327327
}
328328
request methodGet "/projects?select=name,clients()&clients=is.null"
329329
[("Prefer", "count=planned")] ""
@@ -340,9 +340,9 @@ spec = describe "related queries" $ do
340340
{"id":1,"name":"Walmart"},
341341
{"id":2,"name":"Target"}
342342
]|]
343-
{ matchStatus = 206
343+
{ matchStatus = 200
344344
, matchHeaders = [ matchContentTypeJson
345-
, "Content-Range" <:> "0-1/952" ]
345+
, "Content-Range" <:> "0-1/2" ]
346346
}
347347

348348
it "works with count=estimated" $ do
@@ -357,7 +357,7 @@ spec = describe "related queries" $ do
357357
]|]
358358
{ matchStatus = 206
359359
, matchHeaders = [ matchContentTypeJson
360-
, "Content-Range" <:> "0-3/1200" ]
360+
, "Content-Range" <:> "0-3/5" ]
361361
}
362362
request methodGet "/projects?select=name,clients()&clients=is.null"
363363
[("Prefer", "count=estimated")] ""
@@ -374,7 +374,7 @@ spec = describe "related queries" $ do
374374
{"id":1,"name":"Walmart"},
375375
{"id":2,"name":"Target"}
376376
]|]
377-
{ matchStatus = 206
377+
{ matchStatus = 200
378378
, matchHeaders = [ matchContentTypeJson
379-
, "Content-Range" <:> "0-1/952" ]
379+
, "Content-Range" <:> "0-1/2" ]
380380
}

test/spec/Main.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ main = do
243243

244244
-- this test runs with db-plan-enabled = true
245245
parallel $ before planEnabledApp $
246-
describe "Feature.Query.PlanSpec.spec" $ Feature.Query.PlanSpec.spec actualPgVersion
246+
describe "Feature.Query.PlanSpec.spec" Feature.Query.PlanSpec.spec
247247

248248
-- this test runs with server-trace-header set
249249
parallel $ before obsApp $

test/spec/fixtures/data.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,3 +983,5 @@ VALUES (1, '2025-01-01 10:00','2025-01-01 11:00', 'vacation'),
983983
(2, '2024-11-01 09:00','2024-11-01 10:00', 'vacation'),
984984
(3, '2024-12-02 13:00','2024-12-02 14:00', 'vacation'),
985985
(1, '2023-01-02 20:00','2023-01-01 21:00', 'work');
986+
987+
INSERT INTO bets (id) SELECT generate_series(1,1000);

0 commit comments

Comments
 (0)