Skip to content

Commit 529fa15

Browse files
taimoorzaeemsteve-chavez
authored andcommitted
feat: add config db-hoisted-tx-settings to allow only hoisted function settings
1 parent e637f41 commit 529fa15

22 files changed

+168
-53
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ This project adheres to [Semantic Versioning](http://semver.org/).
99

1010
- #2887, Add Preference `max-affected` to limit affected resources - @taimoorzaeem
1111
- #3171, Add an ability to dump config via admin API - @skywriter
12-
- #3061, Apply all function settings as transaction-scoped settings - @taimoorzaeem
1312
- #3171, #3046, Log schema cache stats to stderr - @steve-chavez
1413
- #3210, Dump schema cache through admin API - @taimoorzaeem
1514
- #2676, Performance improvement on bulk json inserts, around 10% increase on requests per second by removing `json_typeof` from write queries - @steve-chavez
@@ -23,6 +22,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
2322
+ Shows the correct JSON format in the `hints` field
2423
- #3340, Log when the LISTEN channel gets a notification - @steve-chavez
2524
- #3184, Log full pg version to stderr on connection - @steve-chavez
25+
- #3242. Add config `db-hoisted-tx-settings` to apply only hoisted function settings - @taimoorzaeem
2626

2727
### Fixed
2828

docs/references/configuration.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,21 @@ db-extra-search-path
298298

299299
Multiple schemas can be added in a comma-separated string, e.g. ``public, extensions``.
300300

301+
.. _db-hoisted-tx-settings:
302+
303+
db-hoisted-tx-settings
304+
----------------------
305+
306+
=============== ==================================================================================
307+
**Type** String
308+
**Default** statement_timeout, plan_filter.statement_cost_limit, default_transaction_isolation
309+
**Reloadable** Y
310+
**Environment** PGRST_DB_HOISTED_TX_SETTINGS
311+
**In-Database** pgrst.db_hoisted_tx_settings
312+
=============== ==================================================================================
313+
314+
Hoisted settings are allowed to be applied as transaction-scoped function settings. Multiple settings can be added in a comma-separated string, e.g. ``work_mem, statement_timeout``.
315+
301316
.. _db-max-rows:
302317

303318
db-max-rows

docs/references/transactions.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ When calling the above function (see :ref:`functions`), the statement timeout wi
303303

304304
.. note::
305305

306-
Currently, only ``statement_timeout`` is applied for functions.
306+
Only the transactions that are hoisted by config :ref:`db-hoisted-tx-settings` will be applied.
307307

308308
.. _main_query:
309309

src/PostgREST/Config.hs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ data AppConfig = AppConfig
7474
, configDbChannel :: Text
7575
, configDbChannelEnabled :: Bool
7676
, configDbExtraSearchPath :: [Text]
77+
, configDbHoistedTxSettings :: [Text]
7778
, configDbMaxRows :: Maybe Integer
7879
, configDbPlanEnabled :: Bool
7980
, configDbPoolSize :: Int
@@ -146,6 +147,7 @@ toText conf =
146147
,("db-channel", q . configDbChannel)
147148
,("db-channel-enabled", T.toLower . show . configDbChannelEnabled)
148149
,("db-extra-search-path", q . T.intercalate "," . configDbExtraSearchPath)
150+
,("db-hoisted-tx-settings", q . T.intercalate "," . configDbHoistedTxSettings)
149151
,("db-max-rows", maybe "\"\"" show . configDbMaxRows)
150152
,("db-plan-enabled", T.toLower . show . configDbPlanEnabled)
151153
,("db-pool", show . configDbPoolSize)
@@ -241,6 +243,7 @@ parser optPath env dbSettings roleSettings roleIsolationLvl =
241243
<*> (fromMaybe "pgrst" <$> optString "db-channel")
242244
<*> (fromMaybe True <$> optBool "db-channel-enabled")
243245
<*> (maybe ["public"] splitOnCommas <$> optValue "db-extra-search-path")
246+
<*> (maybe defaultHoistedAllowList splitOnCommas <$> optValue "db-hoisted-tx-settings")
244247
<*> optWithAlias (optInt "db-max-rows")
245248
(optInt "max-rows")
246249
<*> (fromMaybe False <$> optBool "db-plan-enabled")
@@ -418,6 +421,8 @@ parser optPath env dbSettings roleSettings roleIsolationLvl =
418421
splitOnCommas (C.String s) = T.strip <$> T.splitOn "," s
419422
splitOnCommas _ = []
420423

424+
defaultHoistedAllowList = ["statement_timeout","plan_filter.statement_cost_limit","default_transaction_isolation"]
425+
421426
-- | Read the JWT secret from a file if configJwtSecret is actually a
422427
-- filepath(has @ as its prefix). To check if the JWT secret is provided is
423428
-- in fact a file path, it must be decoded as 'Text' to be processed.

src/PostgREST/Config/Database.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ dbSettingsNames =
5656
,"db_root_spec"
5757
,"db_schemas"
5858
,"db_tx_end"
59+
,"db_hoisted_tx_settings"
5960
,"jwt_aud"
6061
,"jwt_role_claim_key"
6162
,"jwt_secret"

src/PostgREST/Query.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ actionQuery (MaybeDb plan@InspectPlan{ipSchema=tSchema}) AppConfig{..} _ pgVer s
181181
tableAccess <- SQL.statement [tSchema] (SchemaCache.accessibleTables pgVer configDbPreparedStatements)
182182
MaybeDbResult plan . Just <$> ((,,)
183183
(HM.filterWithKey (\qi _ -> S.member qi tableAccess) $ SchemaCache.dbTables sCache)
184-
<$> SQL.statement tSchema (SchemaCache.accessibleFuncs pgVer configDbPreparedStatements)
184+
<$> SQL.statement (tSchema, configDbHoistedTxSettings) (SchemaCache.accessibleFuncs pgVer configDbPreparedStatements)
185185
<*> SQL.statement tSchema (SchemaCache.schemaDescription configDbPreparedStatements))
186186
OAIgnorePriv ->
187187
MaybeDbResult plan . Just <$> ((,,)

src/PostgREST/SchemaCache.hs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ querySchemaCache AppConfig{..} = do
150150
tabs <- SQL.statement schemas $ allTables pgVer prepared
151151
keyDeps <- SQL.statement (schemas, configDbExtraSearchPath) $ allViewsKeyDependencies prepared
152152
m2oRels <- SQL.statement mempty $ allM2OandO2ORels pgVer prepared
153-
funcs <- SQL.statement schemas $ allFunctions pgVer prepared
153+
funcs <- SQL.statement (schemas, configDbHoistedTxSettings) $ allFunctions pgVer prepared
154154
cRels <- SQL.statement mempty $ allComputedRels prepared
155155
reps <- SQL.statement schemas $ dataRepresentations prepared
156156
mHdlers <- SQL.statement schemas $ mediaHandlers pgVer prepared
@@ -363,13 +363,13 @@ dataRepresentations = SQL.Statement sql (arrayParam HE.text) decodeRepresentatio
363363
OR (dst_t.typtype = 'd' AND c.castsource IN ('json'::regtype::oid , 'text'::regtype::oid)))
364364
|]
365365

366-
allFunctions :: PgVersion -> Bool -> SQL.Statement [Schema] RoutineMap
367-
allFunctions pgVer = SQL.Statement sql (arrayParam HE.text) decodeFuncs
366+
allFunctions :: PgVersion -> Bool -> SQL.Statement ([Schema], [Text]) RoutineMap
367+
allFunctions pgVer = SQL.Statement sql (contrazip2 (arrayParam HE.text) (arrayParam HE.text)) decodeFuncs
368368
where
369369
sql = funcsSqlQuery pgVer <> " AND pn.nspname = ANY($1)"
370370

371-
accessibleFuncs :: PgVersion -> Bool -> SQL.Statement Schema RoutineMap
372-
accessibleFuncs pgVer = SQL.Statement sql (param HE.text) decodeFuncs
371+
accessibleFuncs :: PgVersion -> Bool -> SQL.Statement (Schema, [Text]) RoutineMap
372+
accessibleFuncs pgVer = SQL.Statement sql (contrazip2 (param HE.text) (arrayParam HE.text)) decodeFuncs
373373
where
374374
sql = funcsSqlQuery pgVer <> " AND pn.nspname = $1 AND has_function_privilege(p.oid, 'execute')"
375375

@@ -451,15 +451,15 @@ funcsSqlQuery pgVer = [q|
451451
JOIN pg_namespace tn ON tn.oid = t.typnamespace
452452
LEFT JOIN pg_class comp ON comp.oid = t.typrelid
453453
LEFT JOIN pg_description as d ON d.objoid = p.oid
454-
LEFT JOIN LATERAL unnest(proconfig) iso_config ON iso_config like 'default_transaction_isolation%'
454+
LEFT JOIN LATERAL unnest(proconfig) iso_config ON iso_config LIKE 'default_transaction_isolation%'
455455
LEFT JOIN LATERAL (
456456
SELECT
457457
array_agg(row(
458458
substr(setting, 1, strpos(setting, '=') - 1),
459459
substr(setting, strpos(setting, '=') + 1)
460460
)) as kvs
461461
FROM unnest(proconfig) setting
462-
WHERE setting not LIKE 'default_transaction_isolation%'
462+
WHERE setting ~ ANY($2)
463463
) func_settings ON TRUE
464464
WHERE t.oid <> 'trigger'::regtype AND COALESCE(a.callable, true)
465465
|] <> (if pgVer >= pgVersion110 then "AND prokind = 'f'" else "AND NOT (proisagg OR proiswindow)")

test/io/__snapshots__/test_cli/test_schema_cache_snapshot[dbRoutines].yaml

Lines changed: 52 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -59,31 +59,32 @@
5959
pdSchema: public
6060
pdVolatility: Volatile
6161

62-
- - qiName: multiple_func_settings_test
62+
- - qiName: rpc_with_one_hoisted
6363
qiSchema: public
6464
- - pdDescription: null
6565
pdFuncSettings:
66-
- - work_mem
67-
- '5000'
6866
- - statement_timeout
69-
- 10s
67+
- 7s
7068
pdHasVariadic: false
71-
pdName: multiple_func_settings_test
69+
pdName: rpc_with_one_hoisted
7270
pdParams: []
7371
pdReturnType:
7472
contents:
7573
contents:
76-
qiName: record
77-
qiSchema: pg_catalog
78-
tag: Scalar
79-
tag: SetOf
74+
- qiName: items
75+
qiSchema: public
76+
- false
77+
tag: Composite
78+
tag: Single
8079
pdSchema: public
8180
pdVolatility: Volatile
8281

8382
- - qiName: serializable_isolation_level
8483
qiSchema: public
8584
- - pdDescription: null
86-
pdFuncSettings: []
85+
pdFuncSettings:
86+
- - default_transaction_isolation
87+
- serializable
8788
pdHasVariadic: false
8889
pdName: serializable_isolation_level
8990
pdParams: []
@@ -170,6 +171,26 @@
170171
pdSchema: public
171172
pdVolatility: Volatile
172173

174+
- - qiName: rpc_with_two_hoisted
175+
qiSchema: public
176+
- - pdDescription: null
177+
pdFuncSettings:
178+
- - statement_timeout
179+
- 10s
180+
pdHasVariadic: false
181+
pdName: rpc_with_two_hoisted
182+
pdParams: []
183+
pdReturnType:
184+
contents:
185+
contents:
186+
- qiName: items
187+
qiSchema: public
188+
- false
189+
tag: Composite
190+
tag: Single
191+
pdSchema: public
192+
pdVolatility: Volatile
193+
173194
- - qiName: set_statement_timeout
174195
qiSchema: public
175196
- - pdDescription: null
@@ -219,25 +240,6 @@
219240
pdSchema: public
220241
pdVolatility: Volatile
221242

222-
- - qiName: work_mem_test
223-
qiSchema: public
224-
- - pdDescription: null
225-
pdFuncSettings:
226-
- - work_mem
227-
- 6000kB
228-
pdHasVariadic: false
229-
pdName: work_mem_test
230-
pdParams: []
231-
pdReturnType:
232-
contents:
233-
contents:
234-
qiName: text
235-
qiSchema: pg_catalog
236-
tag: Scalar
237-
tag: Single
238-
pdSchema: public
239-
pdVolatility: Volatile
240-
241243
- - qiName: invalid_role_claim_key_reload
242244
qiSchema: public
243245
- - pdDescription: null
@@ -348,7 +350,9 @@
348350
- - qiName: repeatable_read_isolation_level
349351
qiSchema: public
350352
- - pdDescription: null
351-
pdFuncSettings: []
353+
pdFuncSettings:
354+
- - default_transaction_isolation
355+
- REPEATABLE READ
352356
pdHasVariadic: false
353357
pdName: repeatable_read_isolation_level
354358
pdParams: []
@@ -454,6 +458,24 @@
454458
pdSchema: public
455459
pdVolatility: Volatile
456460

461+
- - qiName: rpc_work_mem
462+
qiSchema: public
463+
- - pdDescription: null
464+
pdFuncSettings: []
465+
pdHasVariadic: false
466+
pdName: rpc_work_mem
467+
pdParams: []
468+
pdReturnType:
469+
contents:
470+
contents:
471+
- qiName: items
472+
qiSchema: public
473+
- false
474+
tag: Composite
475+
tag: Single
476+
pdSchema: public
477+
pdVolatility: Volatile
478+
457479
- - qiName: four_sec_timeout
458480
qiSchema: public
459481
- - pdDescription: null

test/io/configs/expected/aliases.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ db-anon-role = ""
33
db-channel = "pgrst"
44
db-channel-enabled = true
55
db-extra-search-path = "public"
6+
db-hoisted-tx-settings = "statement_timeout,plan_filter.statement_cost_limit,default_transaction_isolation"
67
db-max-rows = 1000
78
db-plan-enabled = false
89
db-pool = 10

test/io/configs/expected/boolean-numeric.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ db-anon-role = ""
33
db-channel = "pgrst"
44
db-channel-enabled = true
55
db-extra-search-path = "public"
6+
db-hoisted-tx-settings = "statement_timeout,plan_filter.statement_cost_limit,default_transaction_isolation"
67
db-max-rows = ""
78
db-plan-enabled = false
89
db-pool = 10

test/io/configs/expected/boolean-string.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ db-anon-role = ""
33
db-channel = "pgrst"
44
db-channel-enabled = true
55
db-extra-search-path = "public"
6+
db-hoisted-tx-settings = "statement_timeout,plan_filter.statement_cost_limit,default_transaction_isolation"
67
db-max-rows = ""
78
db-plan-enabled = false
89
db-pool = 10

test/io/configs/expected/defaults.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ db-anon-role = ""
33
db-channel = "pgrst"
44
db-channel-enabled = true
55
db-extra-search-path = "public"
6+
db-hoisted-tx-settings = "statement_timeout,plan_filter.statement_cost_limit,default_transaction_isolation"
67
db-max-rows = ""
78
db-plan-enabled = false
89
db-pool = 10

test/io/configs/expected/no-defaults-with-db-other-authenticator.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ db-anon-role = "pre_config_role"
33
db-channel = "postgrest"
44
db-channel-enabled = false
55
db-extra-search-path = "public,extensions,other"
6+
db-hoisted-tx-settings = "maintenance_work_mem"
67
db-max-rows = 100
78
db-plan-enabled = true
89
db-pool = 1

test/io/configs/expected/no-defaults-with-db.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ db-anon-role = "anonymous"
33
db-channel = "postgrest"
44
db-channel-enabled = false
55
db-extra-search-path = "public,extensions,private"
6+
db-hoisted-tx-settings = "work_mem"
67
db-max-rows = 500
78
db-plan-enabled = false
89
db-pool = 1

test/io/configs/expected/no-defaults.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ db-anon-role = "root"
33
db-channel = "postgrest"
44
db-channel-enabled = false
55
db-extra-search-path = "public,test"
6+
db-hoisted-tx-settings = "work_mem"
67
db-max-rows = 1000
78
db-plan-enabled = true
89
db-pool = 1

test/io/configs/expected/types.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ db-anon-role = ""
33
db-channel = "pgrst"
44
db-channel-enabled = true
55
db-extra-search-path = "public"
6+
db-hoisted-tx-settings = "statement_timeout,plan_filter.statement_cost_limit,default_transaction_isolation"
67
db-max-rows = ""
78
db-plan-enabled = false
89
db-pool = 10

test/io/configs/no-defaults-env.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ PGRST_DB_ANON_ROLE: root
55
PGRST_DB_CHANNEL: postgrest
66
PGRST_DB_CHANNEL_ENABLED: false
77
PGRST_DB_EXTRA_SEARCH_PATH: public, test
8+
PGRST_DB_HOISTED_TX_SETTINGS: work_mem
89
PGRST_DB_MAX_ROWS: 1000
910
PGRST_DB_PLAN_ENABLED: true
1011
PGRST_DB_POOL: 1

test/io/configs/no-defaults.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ db-anon-role = "root"
33
db-channel = "postgrest"
44
db-channel-enabled = false
55
db-extra-search-path = "public, test"
6+
db-hoisted-tx-settings = "work_mem"
67
db-max-rows = 1000
78
db-plan-enabled = true
89
db-pool = 1

test/io/db_config.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ ALTER ROLE db_config_authenticator SET pgrst.openapi_server_proxy_uri = 'https:/
2323
ALTER ROLE db_config_authenticator SET pgrst.server_cors_allowed_origins = 'http://origin.com';
2424
ALTER ROLE db_config_authenticator SET pgrst.server_timing_enabled = 'false';
2525
ALTER ROLE db_config_authenticator SET pgrst.server_trace_header = 'CF-Ray';
26+
ALTER ROLE db_config_authenticator SET pgrst.db_hoisted_tx_settings = 'work_mem';
2627

2728
-- override with database specific setting
2829
ALTER ROLE db_config_authenticator IN DATABASE :DBNAME SET pgrst.db_extra_search_path = 'public, extensions, private';
@@ -72,6 +73,7 @@ ALTER ROLE other_authenticator SET pgrst.openapi_server_proxy_uri = 'https://oth
7273
ALTER ROLE other_authenticator SET pgrst.server_cors_allowed_origins = 'http://otherorigin.com';
7374
ALTER ROLE other_authenticator SET pgrst.server_timing_enabled = 'true';
7475
ALTER ROLE other_authenticator SET pgrst.server_trace_header = 'traceparent';
76+
ALTER ROLE other_authenticator SET pgrst.db_hoisted_tx_settings = 'maintenance_work_mem';
7577

7678
create schema postgrest;
7779
grant usage on schema postgrest to db_config_authenticator;

0 commit comments

Comments
 (0)