diff --git a/src/PostgREST/SchemaCache.hs b/src/PostgREST/SchemaCache.hs index 2cbf5c37f..90f69e3f0 100644 --- a/src/PostgREST/SchemaCache.hs +++ b/src/PostgREST/SchemaCache.hs @@ -511,7 +511,8 @@ tablesSqlQuery pgVer = c.relname::name AS table_name, a.attname::name AS column_name, d.description AS description, - pg_get_expr(ad.adbin, ad.adrelid)::text AS column_default, + |] <> columnDefault <> + [q| not (a.attnotnull OR t.typtype = 'd' AND t.typnotnull) AS is_nullable, CASE WHEN t.typtype = 'd' THEN @@ -693,6 +694,16 @@ tablesSqlQuery pgVer = "ORDER BY table_schema, table_name" where relIsPartition = if pgVer >= pgVersion100 then " AND not c.relispartition " else mempty + -- detect default values on columns that have GENERATED .. AS IDENTITY + columnDefault = + if pgVer >= pgVersion100 + then [q| + CASE + WHEN nullif(a.attidentity, '') is null + THEN pg_get_expr(ad.adbin, ad.adrelid)::text + ELSE format('nextval(%s)', quote_literal(pg_get_serial_sequence(a.attrelid::regclass::text, a.attname::text))) + END AS column_default,|] + else "pg_get_expr(ad.adbin, ad.adrelid)::text AS column_default," -- | Gets many-to-one relationships and one-to-one(O2O) relationships, which are a refinement of the many-to-one's diff --git a/test/spec/Feature/Query/InsertSpec.hs b/test/spec/Feature/Query/InsertSpec.hs index 598990beb..fbb933d1b 100644 --- a/test/spec/Feature/Query/InsertSpec.hs +++ b/test/spec/Feature/Query/InsertSpec.hs @@ -495,6 +495,16 @@ spec actualPgVersion = do , matchHeaders = ["Preference-Applied" <:> "missing=default"] } + when (actualPgVersion >= pgVersion100) $ + it "inserts a default on a generated by default as identity column" $ do + request methodPost "/channels?columns=id,data,slug&select=data,slug" [("Prefer", "return=representation"), ("Prefer", "missing=default")] + [json| { "slug": "foo" } |] + `shouldRespondWith` + [json| [{"data":{"foo": "bar"},"slug":"foo"}] |] -- id 1 was inserted here, we don't get it for idempotence in the tests + { matchStatus = 201 + , matchHeaders = ["Preference-Applied" <:> "missing=default"] + } + it "inserts json that has duplicate keys" $ do request methodPost "/tbl_w_json" [("Prefer", "return=representation")] [json| { "data": { "a": 1, "a": 2 }, "id": 3 } |] diff --git a/test/spec/fixtures/privileges.sql b/test/spec/fixtures/privileges.sql index 6e2277ec5..e5fc79e9f 100644 --- a/test/spec/fixtures/privileges.sql +++ b/test/spec/fixtures/privileges.sql @@ -41,6 +41,14 @@ 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$; + -- Privileges for non anonymous users GRANT USAGE ON SCHEMA test TO postgrest_test_author; GRANT ALL ON TABLE authors_only TO postgrest_test_author; diff --git a/test/spec/fixtures/schema.sql b/test/spec/fixtures/schema.sql index 3dffb555c..3ec8aa933 100644 --- a/test/spec/fixtures/schema.sql +++ b/test/spec/fixtures/schema.sql @@ -3110,3 +3110,15 @@ create table test.tbl_w_json( id int, data json ); + +DO $do$ +BEGIN + IF current_setting('server_version_num')::INT >= 100000 THEN + CREATE TABLE test.channels ( + id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + data jsonb DEFAULT '{"foo": "bar"}', + slug text + ); + END IF; +END +$do$;