refactor: merge Column list into Table

* Remove Table from Column
* Correct OpenAPI test where the schema was appearing for the enum unnecessarily
* Increase memory-tests consumption by 2M

Seems the Hasql decoder consumes more memory now that the allTables
results also have [Column] inside.
This commit is contained in:
steve-chavez
2022-04-22 19:04:16 -05:00
committed by Steve Chavez
parent 902e4e8921
commit 778b8d074d
6 changed files with 139 additions and 173 deletions
+1 -1
View File
@@ -485,7 +485,7 @@ handleOpenApi headersOnly tSchema (RequestContext conf@AppConfig{..} dbStructure
lift $ case configOpenApiMode of
OAFollowPriv ->
OpenAPI.encode conf dbStructure
<$> SQL.statement tSchema (DbStructure.accessibleTables ctxPgVersion configDbPreparedStatements)
<$> SQL.statement [tSchema] (DbStructure.accessibleTables ctxPgVersion configDbPreparedStatements)
<*> SQL.statement tSchema (DbStructure.accessibleProcs ctxPgVersion configDbPreparedStatements)
<*> SQL.statement tSchema (DbStructure.schemaDescription configDbPreparedStatements)
OAIgnorePriv ->
+108 -132
View File
@@ -25,7 +25,6 @@ module PostgREST.DbStructure
, accessibleProcs
, findIfView
, schemaDescription
, tableCols
) where
import qualified Data.Aeson as JSON
@@ -43,7 +42,7 @@ import PostgREST.Config.PgVersion (PgVersion, pgVersion100,
pgVersion110)
import PostgREST.DbStructure.Identifiers (FieldName,
QualifiedIdentifier (..),
Schema, TableName)
Schema)
import PostgREST.DbStructure.Proc (PgType (..),
ProcDescription (..),
ProcParam (..),
@@ -60,16 +59,11 @@ import Protolude
data DbStructure = DbStructure
{ dbTables :: TablesMap
, dbColumns :: [Column]
, dbRelationships :: [Relationship]
, dbProcs :: ProcsMap
}
deriving (Generic, JSON.ToJSON)
-- TODO Table could hold references to all its Columns
tableCols :: DbStructure -> Schema -> TableName -> [Column]
tableCols dbs tSchema tName = filter (\Column{colTable=Table{tableSchema=s, tableName=t}} -> s==tSchema && t==tName) $ dbColumns dbs
findIfView :: QualifiedIdentifier -> TablesMap -> Bool
findIfView identifier tbls = maybe False tableIsView $ M.lookup identifier tbls
@@ -94,8 +88,7 @@ queryDbStructure :: [Schema] -> [Schema] -> Bool -> SQL.Transaction DbStructure
queryDbStructure schemas extraSearchPath prepared = do
SQL.sql "set local schema ''" -- This voids the search path. The following queries need this for getting the fully qualified name(schema.name) of every db object
pgVer <- SQL.statement mempty pgVersionStatement
tabs <- SQL.statement mempty $ allTables pgVer prepared
cols <- SQL.statement schemas $ allColumns tabs prepared
tabs <- SQL.statement schemas $ allTables pgVer prepared
keyDeps <- SQL.statement (schemas, extraSearchPath) $ allViewsKeyDependencies prepared
m2oRels <- SQL.statement mempty $ allM2ORels pgVer prepared
procs <- SQL.statement schemas $ allProcs pgVer prepared
@@ -105,7 +98,6 @@ queryDbStructure schemas extraSearchPath prepared = do
return $ removeInternal schemas $ DbStructure {
dbTables = tabsWViewsPks
, dbColumns = cols
, dbRelationships = rels
, dbProcs = procs
}
@@ -115,7 +107,6 @@ removeInternal :: [Schema] -> DbStructure -> DbStructure
removeInternal schemas dbStruct =
DbStructure {
dbTables = M.filterWithKey (\(QualifiedIdentifier sch _) _ -> sch `elem` schemas) $ dbTables dbStruct
, dbColumns = filter (\x -> tableSchema (colTable x) `elem` schemas) (dbColumns dbStruct)
, dbRelationships = filter (\x -> qiSchema (relTable x) `elem` schemas &&
qiSchema (relForeignTable x) `elem` schemas &&
not (hasInternalJunction x)) $ dbRelationships dbStruct
@@ -130,30 +121,24 @@ decodeTables :: HD.Result TablesMap
decodeTables =
M.fromList . map (\tbl@Table{tableSchema, tableName} -> (QualifiedIdentifier tableSchema tableName, tbl)) <$> HD.rowList tblRow
where
tblRow = Table <$> column HD.text
<*> column HD.text
<*> nullableColumn HD.text
<*> column HD.bool
<*> column HD.bool
<*> column HD.bool
<*> column HD.bool
<*> arrayColumn HD.text
decodeColumns :: TablesMap -> HD.Result [Column]
decodeColumns tables =
mapMaybe (columnFromRow tables) <$> HD.rowList colRow
where
colRow =
(,,,,,,,,)
<$> column HD.text
<*> column HD.text
<*> column HD.text
<*> nullableColumn HD.text
<*> column HD.bool
<*> column HD.text
<*> nullableColumn HD.int4
<*> nullableColumn HD.text
<*> arrayColumn HD.text
tblRow = Table
<$> column HD.text
<*> column HD.text
<*> nullableColumn HD.text
<*> column HD.bool
<*> column HD.bool
<*> column HD.bool
<*> column HD.bool
<*> arrayColumn HD.text
<*> compositeArrayColumn
(Column
<$> compositeField HD.text
<*> nullableCompositeField HD.text
<*> compositeField HD.bool
<*> compositeField HD.text
<*> nullableCompositeField HD.int4
<*> nullableCompositeField HD.text
<*> compositeFieldArray HD.text)
decodeRels :: HD.Result [Relationship]
decodeRels =
@@ -330,9 +315,9 @@ schemaDescription =
where
n.nspname = $1 |]
accessibleTables :: PgVersion -> Bool -> SQL.Statement Schema TablesMap
accessibleTables :: PgVersion -> Bool -> SQL.Statement [Schema] TablesMap
accessibleTables pgVer =
SQL.Statement sql (param HE.text) decodeTables
SQL.Statement sql (arrayParam HE.text) decodeTables
where
sql = tablesSqlQuery False pgVer
@@ -403,9 +388,9 @@ addViewPrimaryKeys tabs keyDeps =
maybe [] (\(ViewKeyDependency _ _ _ _ pkCols) -> snd <$> pkCols) $
find (\(ViewKeyDependency _ viewQi _ dep _) -> dep == PKDep && viewQi == QualifiedIdentifier sch vw) keyDeps
allTables :: PgVersion -> Bool -> SQL.Statement () TablesMap
allTables :: PgVersion -> Bool -> SQL.Statement [Schema] TablesMap
allTables pgVer =
SQL.Statement sql HE.noParams decodeTables
SQL.Statement sql (arrayParam HE.text) decodeTables
where
sql = tablesSqlQuery True pgVer
@@ -417,6 +402,80 @@ tablesSqlQuery getAll pgVer =
-- (pg_has_role(ss.relowner, 'USAGE'::text) OR has_column_privilege(ss.roid, a.attnum, 'SELECT, INSERT, UPDATE, REFERENCES'::text));
[q|
WITH
columns AS (
SELECT
nc.nspname::name AS table_schema,
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,
not (a.attnotnull OR t.typtype = 'd' AND t.typnotnull) AS is_nullable,
CASE
WHEN t.typtype = 'd' THEN
CASE
WHEN bt.typelem <> 0::oid AND bt.typlen = (-1) THEN 'ARRAY'::text
WHEN nbt.nspname = 'pg_catalog'::name THEN format_type(t.typbasetype, NULL::integer)
ELSE format_type(a.atttypid, a.atttypmod)
END
ELSE
CASE
WHEN t.typelem <> 0::oid AND t.typlen = (-1) THEN 'ARRAY'::text
WHEN nt.nspname = 'pg_catalog'::name THEN format_type(a.atttypid, NULL::integer)
ELSE format_type(a.atttypid, a.atttypmod)
END
END::text AS data_type,
information_schema._pg_char_max_length(
information_schema._pg_truetypid(a.*, t.*),
information_schema._pg_truetypmod(a.*, t.*)
)::integer AS character_maximum_length,
COALESCE(bt.typname, t.typname)::name AS udt_name,
a.attnum::integer AS position
FROM pg_attribute a
LEFT JOIN pg_description AS d
ON d.objoid = a.attrelid and d.objsubid = a.attnum
LEFT JOIN pg_attrdef ad
ON a.attrelid = ad.adrelid AND a.attnum = ad.adnum
JOIN (pg_class c JOIN pg_namespace nc ON c.relnamespace = nc.oid)
ON a.attrelid = c.oid
JOIN (pg_type t JOIN pg_namespace nt ON t.typnamespace = nt.oid)
ON a.atttypid = t.oid
LEFT JOIN (pg_type bt JOIN pg_namespace nbt ON bt.typnamespace = nbt.oid)
ON t.typtype = 'd' AND t.typbasetype = bt.oid
LEFT JOIN (pg_collation co JOIN pg_namespace nco ON co.collnamespace = nco.oid)
ON a.attcollation = co.oid AND (nco.nspname <> 'pg_catalog'::name OR co.collname <> 'default'::name)
WHERE
NOT pg_is_other_temp_schema(nc.oid)
AND a.attnum > 0
AND NOT a.attisdropped
AND c.relkind in ('r', 'v', 'f', 'm', 'p')
AND nc.nspname = ANY($1)
),
columns_agg AS (
SELECT DISTINCT
info.table_schema AS table_schema,
info.table_name AS table_name,
array_agg(row(
info.column_name,
info.description,
info.is_nullable::boolean,
info.data_type,
info.character_maximum_length,
info.column_default,
coalesce(enum_info.vals, '{}')) order by info.position) as columns
FROM columns info
LEFT OUTER JOIN (
SELECT
n.nspname AS s,
t.typname AS n,
array_agg(e.enumlabel ORDER BY e.enumsortorder) AS vals
FROM pg_type t
JOIN pg_enum e ON t.oid = e.enumtypid
JOIN pg_namespace n ON n.oid = t.typnamespace
GROUP BY s,n
) AS enum_info ON info.udt_name = enum_info.n
WHERE info.table_schema NOT IN ('pg_catalog', 'information_schema')
GROUP BY info.table_schema, info.table_name
),
tbl_constraints AS (
SELECT
c.conname::name AS constraint_name,
@@ -518,11 +577,13 @@ tablesSqlQuery getAll pgVer =
AND (pg_relation_is_updatable(c.oid::regclass, TRUE) & 16) = 16
)
) AS deletable,
coalesce(tpks.pk_cols, '{}') as pk_cols
coalesce(tpks.pk_cols, '{}') as pk_cols,
coalesce(cols_agg.columns, '{}') as columns
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_description d on d.objoid = c.oid and d.objsubid = 0
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 <>
@@ -530,7 +591,7 @@ tablesSqlQuery getAll pgVer =
"ORDER BY table_schema, table_name"
where
fltTables = if getAll then mempty else [q|
AND n.nspname = $1
AND n.nspname = ANY($1)
AND (
pg_has_role(c.relowner, 'USAGE')
or has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER')
@@ -538,97 +599,6 @@ tablesSqlQuery getAll pgVer =
)|]
relIsPartition = if pgVer >= pgVersion100 then " AND not c.relispartition " else mempty
allColumns :: TablesMap -> Bool -> SQL.Statement [Schema] [Column]
allColumns tabs =
SQL.Statement sql (arrayParam HE.text) (decodeColumns tabs)
where
-- CTE based on information_schema.columns changed: remove the owner filter
sql = [q|
WITH
columns AS (
SELECT
nc.nspname::name AS table_schema,
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,
not (a.attnotnull OR t.typtype = 'd' AND t.typnotnull) AS is_nullable,
CASE
WHEN t.typtype = 'd' THEN
CASE
WHEN bt.typelem <> 0::oid AND bt.typlen = (-1) THEN 'ARRAY'::text
WHEN nbt.nspname = 'pg_catalog'::name THEN format_type(t.typbasetype, NULL::integer)
ELSE format_type(a.atttypid, a.atttypmod)
END
ELSE
CASE
WHEN t.typelem <> 0::oid AND t.typlen = (-1) THEN 'ARRAY'::text
WHEN nt.nspname = 'pg_catalog'::name THEN format_type(a.atttypid, NULL::integer)
ELSE format_type(a.atttypid, a.atttypmod)
END
END::text AS data_type,
information_schema._pg_char_max_length(
information_schema._pg_truetypid(a.*, t.*),
information_schema._pg_truetypmod(a.*, t.*)
)::integer AS character_maximum_length,
COALESCE(bt.typname, t.typname)::name AS udt_name,
a.attnum::integer AS position
FROM pg_attribute a
LEFT JOIN pg_description AS d
ON d.objoid = a.attrelid and d.objsubid = a.attnum
LEFT JOIN pg_attrdef ad
ON a.attrelid = ad.adrelid AND a.attnum = ad.adnum
JOIN (pg_class c JOIN pg_namespace nc ON c.relnamespace = nc.oid)
ON a.attrelid = c.oid
JOIN (pg_type t JOIN pg_namespace nt ON t.typnamespace = nt.oid)
ON a.atttypid = t.oid
LEFT JOIN (pg_type bt JOIN pg_namespace nbt ON bt.typnamespace = nbt.oid)
ON t.typtype = 'd' AND t.typbasetype = bt.oid
LEFT JOIN (pg_collation co JOIN pg_namespace nco ON co.collnamespace = nco.oid)
ON a.attcollation = co.oid AND (nco.nspname <> 'pg_catalog'::name OR co.collname <> 'default'::name)
WHERE
NOT pg_is_other_temp_schema(nc.oid)
AND a.attnum > 0
AND NOT a.attisdropped
AND c.relkind in ('r', 'v', 'f', 'm', 'p')
AND nc.nspname = ANY($1)
)
SELECT DISTINCT
info.table_schema AS schema,
info.table_name AS table_name,
info.column_name AS name,
info.description AS description,
info.is_nullable::boolean AS nullable,
info.data_type AS col_type,
info.character_maximum_length AS max_len,
info.column_default AS default_value,
coalesce(enum_info.vals, '{}') AS enum,
info.position
FROM columns info
LEFT OUTER JOIN (
SELECT
n.nspname AS s,
t.typname AS n,
array_agg(e.enumlabel ORDER BY e.enumsortorder) AS vals
FROM pg_type t
JOIN pg_enum e ON t.oid = e.enumtypid
JOIN pg_namespace n ON n.oid = t.typnamespace
GROUP BY s,n
) AS enum_info ON (info.udt_name = enum_info.n)
WHERE info.table_schema NOT IN ('pg_catalog', 'information_schema')
ORDER BY schema, position;
|]
columnFromRow :: TablesMap ->
(Text, Text, Text,
Maybe Text, Bool, Text,
Maybe Int32, Maybe Text, [Text])
-> Maybe Column
columnFromRow tabs (s, t, n, desc, nul, typ, l, d, e) = buildColumn <$> table
where
buildColumn tbl = Column tbl n desc nul typ l d e
table = M.lookup (QualifiedIdentifier s t) tabs
allM2ORels :: PgVersion -> Bool -> SQL.Statement () [Relationship]
allM2ORels pgVer =
SQL.Statement sql HE.noParams decodeRels
@@ -834,6 +804,12 @@ compositeArrayColumn = arrayColumn . HD.composite
compositeField :: HD.Value a -> HD.Composite a
compositeField = HD.field . HD.nonNullable
nullableCompositeField :: HD.Value a -> HD.Composite (Maybe a)
nullableCompositeField = HD.field . HD.nullable
compositeFieldArray :: HD.Value a -> HD.Composite [a]
compositeFieldArray = HD.field . HD.nonNullable . HD.listArray . HD.nonNullable
column :: HD.Value a -> HD.Row a
column = HD.column . HD.nonNullable
+3 -6
View File
@@ -28,6 +28,7 @@ data Table = Table
, tableUpdatable :: Bool
, tableDeletable :: Bool
, tablePKCols :: [FieldName]
, tableColumns :: [Column]
}
deriving (Show, Ord, Generic, JSON.ToJSON)
@@ -35,8 +36,7 @@ instance Eq Table where
Table{tableSchema=s1,tableName=n1} == Table{tableSchema=s2,tableName=n2} = s1 == s2 && n1 == n2
data Column = Column
{ colTable :: Table
, colName :: FieldName
{ colName :: FieldName
, colDescription :: Maybe Text
, colNullable :: Bool
, colType :: Text
@@ -44,9 +44,6 @@ data Column = Column
, colDefault :: Maybe Text
, colEnum :: [Text]
}
deriving (Ord, Generic, JSON.ToJSON)
instance Eq Column where
Column{colTable=t1,colName=n1} == Column{colTable=t2,colName=n2} = t1 == t2 && n1 == n2
deriving (Eq, Show, Ord, Generic, JSON.ToJSON)
type TablesMap = M.HashMap QualifiedIdentifier Table
+17 -24
View File
@@ -26,8 +26,7 @@ import Data.Swagger
import PostgREST.Config (AppConfig (..), Proxy (..),
isMalformedProxyUri, toURI)
import PostgREST.DbStructure (DbStructure (..),
tableCols)
import PostgREST.DbStructure (DbStructure (..))
import PostgREST.DbStructure.Identifiers (QualifiedIdentifier (..))
import PostgREST.DbStructure.Proc (ProcDescription (..),
ProcParam (..))
@@ -47,7 +46,7 @@ encode conf dbStructure tables procs schemaDescription =
postgrestSpec
(dbRelationships dbStructure)
(concat $ M.elems procs)
(openApiTableInfo dbStructure <$> (snd <$> M.toList tables))
(snd <$> M.toList tables)
(proxyUri conf)
schemaDescription
@@ -80,17 +79,17 @@ parseDefault colType colDefault =
where
wrapInQuotations text = "\"" <> text <> "\""
makeTableDef :: [Relationship] -> (Table, [Column]) -> (Text, Schema)
makeTableDef rels (t, cs) =
makeTableDef :: [Relationship] -> Table -> (Text, Schema)
makeTableDef rels t =
let tn = tableName t in
(tn, (mempty :: Schema)
& description .~ tableDescription t
& type_ ?~ SwaggerObject
& properties .~ fromList (fmap (makeProperty rels) cs)
& required .~ fmap colName (filter (not . colNullable) cs))
& properties .~ fromList (makeProperty t rels <$> tableColumns t)
& required .~ fmap colName (filter (not . colNullable) $ tableColumns t))
makeProperty :: [Relationship] -> Column -> (Text, Referenced Schema)
makeProperty rels col = (colName col, Inline s)
makeProperty :: Table -> [Relationship] -> Column -> (Text, Referenced Schema)
makeProperty tbl rels col = (colName col, Inline s)
where
e = if null $ colEnum col then Nothing else JSON.decode $ JSON.encode $ colEnum col
fk :: Maybe Text
@@ -107,7 +106,7 @@ makeProperty rels col = (colName col, Inline s)
in
(\(a, b) -> T.intercalate "" ["This is a Foreign Key to `", a, ".", b, "`.<fk table='", a, "' column='", b, "'/>"]) <$> fTblCol
pk :: Bool
pk = colName col `elem` tablePKCols (colTable col)
pk = colName col `elem` tablePKCols tbl
n = catMaybes
[ Just "Note:"
, if pk then Just "This is a Primary Key.<pk/>" else Nothing
@@ -162,7 +161,7 @@ makeProcParam pd =
, Ref $ Reference "preferParams"
]
makeParamDefs :: [(Table, [Column])] -> [(Text, Param)]
makeParamDefs :: [Table] -> [(Text, Param)]
makeParamDefs ti =
[ ("preferParams", makePreferParam ["params=single-object"])
, ("preferReturn", makePreferParam ["return=representation", "return=minimal", "return=none"])
@@ -218,8 +217,8 @@ makeParamDefs ti =
& in_ .~ ParamQuery
& type_ ?~ SwaggerString))
]
<> concat [ makeObjectBody (tableName t) : makeRowFilters (tableName t) cs
| (t, cs) <- ti
<> concat [ makeObjectBody (tableName t) : makeRowFilters (tableName t) (tableColumns t)
| t <- ti
]
makeObjectBody :: Text -> (Text, Param)
@@ -244,8 +243,8 @@ makeRowFilter tn c =
makeRowFilters :: Text -> [Column] -> [(Text, Param)]
makeRowFilters tn = fmap (makeRowFilter tn)
makePathItem :: (Table, [Column]) -> (FilePath, PathItem)
makePathItem (t, cs) = ("/" ++ T.unpack tn, p $ tableInsertable t || tableUpdatable t || tableDeletable t)
makePathItem :: Table -> (FilePath, PathItem)
makePathItem t = ("/" ++ T.unpack tn, p $ tableInsertable t || tableUpdatable t || tableDeletable t)
where
-- Use first line of table description as summary; rest as description (if present)
-- We strip leading newlines from description so that users can include a blank line between summary and description
@@ -279,7 +278,7 @@ makePathItem (t, cs) = ("/" ++ T.unpack tn, p $ tableInsertable t || tableUpdata
p False = pr
p True = pw
tn = tableName t
rs = [ T.intercalate "." ["rowFilter", tn, colName c ] | c <- cs ]
rs = [ T.intercalate "." ["rowFilter", tn, colName c ] | c <- tableColumns t ]
ref = Ref . Reference
makeProcPathItem :: ProcDescription -> (FilePath, PathItem)
@@ -309,7 +308,7 @@ makeRootPathItem = ("/", p)
pr = (mempty :: PathItem) & get ?~ getOp
p = pr
makePathItems :: [ProcDescription] -> [(Table, [Column])] -> InsOrdHashMap FilePath PathItem
makePathItems :: [ProcDescription] -> [Table] -> InsOrdHashMap FilePath PathItem
makePathItems pds ti = fromList $ makeRootPathItem :
fmap makePathItem ti ++ fmap makeProcPathItem pds
@@ -321,7 +320,7 @@ escapeHostName "*6" = "0.0.0.0"
escapeHostName "!6" = "0.0.0.0"
escapeHostName h = h
postgrestSpec :: [Relationship] -> [ProcDescription] -> [(Table, [Column])] -> (Text, Text, Integer, Text) -> Maybe Text -> Swagger
postgrestSpec :: [Relationship] -> [ProcDescription] -> [Table] -> (Text, Text, Integer, Text) -> Maybe Text -> Swagger
postgrestSpec rels pds ti (s, h, p, b) sd = (mempty :: Swagger)
& basePath ?~ T.unpack b
& schemes ?~ [s']
@@ -379,9 +378,3 @@ proxyUri AppConfig{..} =
(proxyScheme, proxyHost, proxyPort, proxyPath)
Nothing ->
("http", configServerHost, toInteger configServerPort, "/")
openApiTableInfo :: DbStructure -> Table -> (Table, [Column])
openApiTableInfo dbStructure table =
( table
, tableCols dbStructure (tableSchema table) (tableName table)
)
+9 -9
View File
@@ -102,21 +102,21 @@ postJsonArrayTest(){
echo "Running memory usage tests.."
jsonKeyTest "1M" "POST" "/rpc/leak?columns=blob" "13M"
jsonKeyTest "1M" "POST" "/leak?columns=blob" "13M"
jsonKeyTest "1M" "PATCH" "/leak?id=eq.1&columns=blob" "13M"
jsonKeyTest "1M" "POST" "/rpc/leak?columns=blob" "15M"
jsonKeyTest "1M" "POST" "/leak?columns=blob" "15M"
jsonKeyTest "1M" "PATCH" "/leak?id=eq.1&columns=blob" "15M"
jsonKeyTest "10M" "POST" "/rpc/leak?columns=blob" "41M"
jsonKeyTest "10M" "POST" "/leak?columns=blob" "41M"
jsonKeyTest "10M" "PATCH" "/leak?id=eq.1&columns=blob" "41M"
jsonKeyTest "10M" "POST" "/rpc/leak?columns=blob" "43M"
jsonKeyTest "10M" "POST" "/leak?columns=blob" "43M"
jsonKeyTest "10M" "PATCH" "/leak?id=eq.1&columns=blob" "43M"
jsonKeyTest "50M" "POST" "/rpc/leak?columns=blob" "171M"
jsonKeyTest "50M" "POST" "/leak?columns=blob" "171M"
jsonKeyTest "50M" "PATCH" "/leak?id=eq.1&columns=blob" "171M"
postJsonArrayTest "1000" "/perf_articles?columns=id,body" "11M"
postJsonArrayTest "10000" "/perf_articles?columns=id,body" "11M"
postJsonArrayTest "100000" "/perf_articles?columns=id,body" "21M"
postJsonArrayTest "1000" "/perf_articles?columns=id,body" "13M"
postJsonArrayTest "10000" "/perf_articles?columns=id,body" "13M"
postJsonArrayTest "100000" "/perf_articles?columns=id,body" "23M"
trap - int term exit
+1 -1
View File
@@ -523,7 +523,7 @@ spec actualPgVersion = describe "OpenAPI" $ do
types `shouldBe` Just [aesonQQ|
{
"format": "test.enum_menagerie_type",
"format": "enum_menagerie_type",
"type": "string",
"enum": [
"foo",