From 69c6a0aa36a854a2fd2c1e31d1ecd9729598067a Mon Sep 17 00:00:00 2001 From: Artur Bento de Carvalho <142529798+arturbent0@users.noreply.github.com> Date: Fri, 3 Apr 2026 16:21:32 -0300 Subject: [PATCH] fix: use int32/int64 formats for integer types Fixed integer type mapping in OpenAPI 2.0: replaced the invalid integer format with int32/int64 and added the toSwaggerFormat function to map PostgreSQL types to valid OpenAPI 2.0 formats: smallint -> int32 integer -> int32 bigint -> int64 --- CHANGELOG.md | 4 ++++ src/PostgREST/Response/OpenAPI.hs | 14 +++++++---- test/spec/Feature/OpenApi/OpenApiSpec.hs | 24 +++++++++---------- test/spec/Feature/Query/MultipleSchemaSpec.hs | 8 +++---- 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a61ca5a9..e63851565 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,10 @@ All notable changes to this project will be documented in this file. From versio - Log error when `db-schemas` config contains schema `pg_catalog` or `information_schema` by @taimoorzaeem in #4359 + Now fails at startup. Prior to this, it failed with `PGRST205` on requests related to these schemas. +### Fixed + +- Fix invalid OpenAPI 2.0 format for integer types (`smallint`, `integer`, `bigint`) by @arturbent0 in #4641 + ## [14.7] - 2026-03-20 ### Fixed diff --git a/src/PostgREST/Response/OpenAPI.hs b/src/PostgREST/Response/OpenAPI.hs index 948e6843f..6f90f7ad5 100644 --- a/src/PostgREST/Response/OpenAPI.hs +++ b/src/PostgREST/Response/OpenAPI.hs @@ -73,6 +73,12 @@ toSwaggerType colType = case T.takeEnd 2 colType of "[]" -> Just SwaggerArray _ -> Just SwaggerString +toSwaggerFormat :: Text -> Maybe Text +toSwaggerFormat "smallint" = Just "int32" +toSwaggerFormat "integer" = Just "int32" +toSwaggerFormat "bigint" = Just "int64" +toSwaggerFormat colType = Just colType + typeFromArray :: Text -> Text typeFromArray = T.dropEnd 2 @@ -141,7 +147,7 @@ makeProperty tbl rels col = (colName col, Inline s) & default_ .~ (JSON.decode . toUtf8Lazy . parseDefault (colType col) =<< colDefault col) & description .~ d & enum_ .~ e - & format ?~ colType col + & format .~ toSwaggerFormat (colType col) & maxLength .~ (fromIntegral <$> colMaxLen col) & type_ .~ toSwaggerType (colType col) & items .~ (SwaggerItemsObject <$> makePropertyItems (colType col)) @@ -160,7 +166,7 @@ makeProcProperty (RoutineParam n t _ _ _) = (n, Inline s) s = (mempty :: Schema) & type_ .~ toSwaggerType t & items .~ (SwaggerItemsObject <$> makePropertyItems t) - & format ?~ t + & format .~ toSwaggerFormat t makePreferParam :: [Text] -> Param makePreferParam ts = @@ -192,14 +198,14 @@ makeProcGetParam (RoutineParam n t _ r v) = baseSchema = (mempty :: ParamOtherSchema) & in_ .~ ParamQuery schemaNotMulti = baseSchema - & format ?~ t + & format .~ toSwaggerFormat t & type_ ?~ toParamType (toSwaggerType t) schemaMulti = baseSchema & type_ ?~ fromMaybe SwaggerString (toSwaggerType t) & items ?~ SwaggerItemsPrimitive (Just CollectionMulti) ((mempty :: ParamSchema x) & type_ .~ toSwaggerTypeFromArray t - & format ?~ typeFromArray t) + & format .~ toSwaggerFormat (typeFromArray t)) toParamType paramType = case paramType of -- Array uses {} in query params Just SwaggerArray -> SwaggerString diff --git a/test/spec/Feature/OpenApi/OpenApiSpec.hs b/test/spec/Feature/OpenApi/OpenApiSpec.hs index f9d26fafe..57ed910b7 100644 --- a/test/spec/Feature/OpenApi/OpenApiSpec.hs +++ b/test/spec/Feature/OpenApi/OpenApiSpec.hs @@ -157,7 +157,7 @@ spec = describe "OpenAPI" $ do "properties": { "id": { "description": "child_entities id comment\n\nNote:\nThis is a Primary Key.", - "format": "integer", + "format": "int32", "type": "integer" }, "name": { @@ -167,7 +167,7 @@ spec = describe "OpenAPI" $ do }, "parent_id": { "description": "Note:\nThis is a Foreign Key to `entities.id`.", - "format": "integer", + "format": "int32", "type": "integer" } }, @@ -192,7 +192,7 @@ spec = describe "OpenAPI" $ do "properties": { "id": { "description": "child_entities_view id comment\n\nNote:\nThis is a Primary Key.", - "format": "integer", + "format": "int32", "type": "integer" }, "name": { @@ -202,7 +202,7 @@ spec = describe "OpenAPI" $ do }, "parent_id": { "description": "Note:\nThis is a Foreign Key to `entities.id`.", - "format": "integer", + "format": "int32", "type": "integer" } } @@ -232,7 +232,7 @@ spec = describe "OpenAPI" $ do referralLink `shouldBe` Just [aesonQQ| { - "format": "integer", + "format": "int32", "type": "integer", "description": "Note:\nThis is a Foreign Key to `second.id`." } @@ -337,7 +337,7 @@ spec = describe "OpenAPI" $ do referralLink `shouldBe` Just [aesonQQ| { - "format": "integer", + "format": "int32", "type": "integer", "description": "Note:\nThis is a Foreign Key to `pages.link`." } @@ -354,7 +354,7 @@ spec = describe "OpenAPI" $ do referralLink `shouldBe` Just [aesonQQ| { - "format": "integer", + "format": "int32", "type": "integer", "description": "Note:\nThis is a Foreign Key to `clients.id`." } @@ -432,7 +432,7 @@ spec = describe "OpenAPI" $ do types `shouldBe` Just [aesonQQ| { - "format": "smallint", + "format": "int32", "type": "integer" } |] @@ -447,7 +447,7 @@ spec = describe "OpenAPI" $ do types `shouldBe` Just [aesonQQ| { - "format": "integer", + "format": "int32", "type": "integer" } |] @@ -462,7 +462,7 @@ spec = describe "OpenAPI" $ do types `shouldBe` Just [aesonQQ| { - "format": "bigint", + "format": "int64", "type": "integer" } |] @@ -850,7 +850,7 @@ spec = describe "OpenAPI" $ do "type": "string" }, { - "format": "integer", + "format": "int32", "in": "query", "name": "integer", "required": false, @@ -992,7 +992,7 @@ spec = describe "OpenAPI" $ do "items": {} }, "integer": { - "format": "integer", + "format": "int32", "type": "integer" }, "json": { diff --git a/test/spec/Feature/Query/MultipleSchemaSpec.hs b/test/spec/Feature/Query/MultipleSchemaSpec.hs index 4a94c5419..2f6d13880 100644 --- a/test/spec/Feature/Query/MultipleSchemaSpec.hs +++ b/test/spec/Feature/Query/MultipleSchemaSpec.hs @@ -281,7 +281,7 @@ spec = "properties" : { "id" : { "description" : "Note:\nThis is a Primary Key.", - "format" : "integer", + "format" : "int32", "type" : "integer" }, "name" : { @@ -310,7 +310,7 @@ spec = "properties" : { "id" : { "description" : "Note:\nThis is a Primary Key.", - "format" : "integer", + "format" : "int32", "type" : "integer" }, "name" : { @@ -339,7 +339,7 @@ spec = "properties" : { "id" : { "description" : "Note:\nThis is a Primary Key.", - "format" : "integer", + "format" : "int32", "type" : "integer" }, "name" : { @@ -368,7 +368,7 @@ spec = "properties" : { "id" : { "description" : "Note:\nThis is a Primary Key.", - "format" : "integer", + "format" : "int32", "type" : "integer" }, "another_value" : {