diff --git a/test/spec/Feature/Query/PlanSpec.hs b/test/spec/Feature/Query/PlanSpec.hs index c27e2b597..9e207eb9c 100644 --- a/test/spec/Feature/Query/PlanSpec.hs +++ b/test/spec/Feature/Query/PlanSpec.hs @@ -453,6 +453,23 @@ spec actualPgVersion = do aggCol `shouldBe` Just [aesonQQ| "twkb_agg(ROW(lines.id, lines.name, lines.geom)::lines)" |] + describe "plan of upsert with DEFAULT surrogate primary key" $ do + it "test case sensitive sequence is properly quoted in nextval()" $ do + r <- request methodPost "/Surr_Gen_Default_Upsert?columns=id,name&select=name,extra" [("Prefer", "return=representation, resolution=merge-duplicates, missing=default"), ("Accept", "application/vnd.pgrst.plan+json; options=verbose")] + [json| [ + { "id": 1, "name": "updated value" }, + { "name": "new value" } + ]|] + + let nextValSnip = simpleBody r ^? nth 0 . key "Plan" . key "Plans" . nth 0 . key "Plans" . nth 0 . key "Plans" . nth 0 . key "Output" + resHeaders = simpleHeaders r + + liftIO $ do + resHeaders `shouldSatisfy` elem ("Content-Type", "application/vnd.pgrst.plan+json; for=\"application/json\"; options=verbose; charset=utf-8") + nextValSnip `shouldBe` + Just [aesonQQ| ["jsonb_agg((jsonb_build_object('id', nextval('\"Surr_Gen_Default_Upsert_id_seq\"'::regclass)) || elem.value))"] |] + + disabledSpec :: SpecWith ((), Application) disabledSpec = it "doesn't work if db-plan-enabled=false(the default)" $ do diff --git a/test/spec/Feature/Query/UpsertSpec.hs b/test/spec/Feature/Query/UpsertSpec.hs index 2f582e538..f5cbaff6f 100644 --- a/test/spec/Feature/Query/UpsertSpec.hs +++ b/test/spec/Feature/Query/UpsertSpec.hs @@ -1,3 +1,6 @@ +-- TODO: Separate this module into: +-- - Upsert/MergeDuplicates.hs and +-- - Upsert/IgnoreDuplicates.hs module Feature.Query.UpsertSpec where import Network.Wai (Application) @@ -129,6 +132,19 @@ spec = , matchHeaders = ["Preference-Applied" <:> "resolution=merge-duplicates, missing=default, return=representation", matchContentTypeJson] } + it "INSERTs and UPDATEs rows with case sensitive table name with GENERATED BY DEFAULT surrogate primary keys using Prefer: missing=default" $ + request methodPost "/Surr_Gen_Default_Upsert?columns=id,name&select=name,extra" [("Prefer", "return=representation"), ("Prefer", "resolution=merge-duplicates"), ("Prefer", "missing=default")] + [json| [ + { "id": 1, "name": "updated value" }, + { "name": "new value" } + ]|] `shouldRespondWith` [json| [ + { "name": "updated value", "extra": "existing value cs" }, + { "name": "new value", "extra": null } + ]|] + { matchStatus = 201 + , matchHeaders = ["Preference-Applied" <:> "resolution=merge-duplicates, missing=default, return=representation", matchContentTypeJson] + } + it "succeeds if the table has only PK cols and no other cols" $ request methodPost "/only_pk" [("Prefer", "return=representation"), ("Prefer", "resolution=merge-duplicates")] [json|[ { "id": 1 }, { "id": 2 }, { "id": 4} ]|] @@ -242,6 +258,18 @@ spec = , matchHeaders = ["Preference-Applied" <:> "resolution=ignore-duplicates, missing=default, return=representation", matchContentTypeJson] } + it "INSERTs and UPDATEs rows with case sensitive table name GENERATED BY DEFAULT surrogate primary keys using Prefer: missing=default" $ + request methodPost "/Surr_Gen_Default_Upsert?columns=id,name&select=name,extra" [("Prefer", "return=representation"), ("Prefer", "resolution=ignore-duplicates"), ("Prefer", "missing=default")] + [json| [ + { "id": 1, "name": "updated value" }, + { "name": "new value" } + ]|] `shouldRespondWith` [json| [ + { "name": "new value", "extra": null } + ]|] + { matchStatus = 201 + , matchHeaders = ["Preference-Applied" <:> "resolution=ignore-duplicates, missing=default, return=representation", matchContentTypeJson] + } + it "succeeds if the table has only PK cols and no other cols" $ request methodPost "/only_pk" [("Prefer", "return=representation"), ("Prefer", "resolution=ignore-duplicates")] [json|[ { "id": 1 }, { "id": 2 }, { "id": 3} ]|] diff --git a/test/spec/fixtures/data.sql b/test/spec/fixtures/data.sql index ad9c678a7..624040210 100644 --- a/test/spec/fixtures/data.sql +++ b/test/spec/fixtures/data.sql @@ -946,6 +946,9 @@ INSERT INTO surr_serial_upsert(name, extra) VALUES ('value', 'existing value'); TRUNCATE TABLE surr_gen_default_upsert CASCADE; INSERT INTO surr_gen_default_upsert(name, extra) VALUES ('value', 'existing value'); +TRUNCATE TABLE "Surr_Gen_Default_Upsert" CASCADE; +INSERT INTO "Surr_Gen_Default_Upsert"(name, extra) VALUES ('value cs', 'existing value cs'); + TRUNCATE TABLE tsearch_to_tsvector CASCADE; INSERT INTO tsearch_to_tsvector(text_search) VALUES ('It''s kind of fun to do the impossible'); INSERT INTO tsearch_to_tsvector(text_search) VALUES ('But also fun to do what is possible'); diff --git a/test/spec/fixtures/privileges.sql b/test/spec/fixtures/privileges.sql index 49132f79b..93e05ea49 100644 --- a/test/spec/fixtures/privileges.sql +++ b/test/spec/fixtures/privileges.sql @@ -41,6 +41,7 @@ GRANT USAGE ON SEQUENCE , leak_id_seq , surr_serial_upsert_id_seq , surr_gen_default_upsert_id_seq + , "Surr_Gen_Default_Upsert_id_seq" TO postgrest_test_anonymous; GRANT USAGE ON SEQUENCE channels_id_seq TO postgrest_test_anonymous; diff --git a/test/spec/fixtures/schema.sql b/test/spec/fixtures/schema.sql index 0da32cbe7..770c1e5d1 100644 --- a/test/spec/fixtures/schema.sql +++ b/test/spec/fixtures/schema.sql @@ -3750,6 +3750,13 @@ create table surr_gen_default_upsert ( extra text ); +-- test for case-sensitive table name and sequence name, see #3712 +create table "Surr_Gen_Default_Upsert" ( + id int generated by default as identity primary key, + name text, + extra text +); + create table tsearch_to_tsvector ( text_search text, jsonb_search jsonb