transaction-scoped settings are now shown clearly in the postgres logs

This commit is contained in:
Laurence Isla
2023-11-02 15:50:22 -05:00
parent 226400a5bc
commit 96ca177c31
3 changed files with 31 additions and 17 deletions
+3
View File
@@ -23,6 +23,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- #1070, Fix HTTP status responses for upserts - @taimoorzaeem - #1070, Fix HTTP status responses for upserts - @taimoorzaeem
+ `PUT` returns `201` instead of `200` when rows are inserted + `PUT` returns `201` instead of `200` when rows are inserted
+ `POST` with `Prefer: resolution=merge-duplicates` returns `200` instead of `201` when no rows are inserted + `POST` with `Prefer: resolution=merge-duplicates` returns `200` instead of `201` when no rows are inserted
- #3019, Transaction-Scoped Settings are now shown clearly in the Postgres logs - @laurenceisla
+ Shows `set_config('pgrst.setting_name', $1)` instead of `setconfig($1, $2)`
+ Does not apply to role settings and `app.settings.*`
### Changed ### Changed
+12 -11
View File
@@ -47,8 +47,9 @@ import PostgREST.Plan (CallReadPlan (..),
import PostgREST.Plan.MutatePlan (MutatePlan (..)) import PostgREST.Plan.MutatePlan (MutatePlan (..))
import PostgREST.Query.SqlFragment (escapeIdentList, fromQi, import PostgREST.Query.SqlFragment (escapeIdentList, fromQi,
intercalateSnippet, intercalateSnippet,
setConfigLocal, setConfigWithConstantName,
setConfigLocalJson) setConfigWithConstantNameJSON,
setConfigWithDynamicName)
import PostgREST.Query.Statements (ResultSet (..)) import PostgREST.Query.Statements (ResultSet (..))
import PostgREST.SchemaCache (SchemaCache (..)) import PostgREST.SchemaCache (SchemaCache (..))
import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..), import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..),
@@ -239,17 +240,17 @@ setPgLocals AppConfig{..} claims role roleSettings req = lift $
("select " <> intercalateSnippet ", " (searchPathSql : roleSql ++ roleSettingsSql ++ claimsSql ++ [methodSql, pathSql] ++ headersSql ++ cookiesSql ++ appSettingsSql)) ("select " <> intercalateSnippet ", " (searchPathSql : roleSql ++ roleSettingsSql ++ claimsSql ++ [methodSql, pathSql] ++ headersSql ++ cookiesSql ++ appSettingsSql))
HD.noResult configDbPreparedStatements HD.noResult configDbPreparedStatements
where where
methodSql = setConfigLocal ("request.method", iMethod req) methodSql = setConfigWithConstantName ("request.method", iMethod req)
pathSql = setConfigLocal ("request.path", iPath req) pathSql = setConfigWithConstantName ("request.path", iPath req)
headersSql = setConfigLocalJson "request.headers" (iHeaders req) headersSql = setConfigWithConstantNameJSON "request.headers" (iHeaders req)
cookiesSql = setConfigLocalJson "request.cookies" (iCookies req) cookiesSql = setConfigWithConstantNameJSON "request.cookies" (iCookies req)
claimsSql = [setConfigLocal ("request.jwt.claims", LBS.toStrict $ JSON.encode claims)] claimsSql = [setConfigWithConstantName ("request.jwt.claims", LBS.toStrict $ JSON.encode claims)]
roleSql = [setConfigLocal ("role", role)] roleSql = [setConfigWithConstantName ("role", role)]
roleSettingsSql = setConfigLocal <$> roleSettings roleSettingsSql = setConfigWithDynamicName <$> roleSettings
appSettingsSql = setConfigLocal <$> (join bimap toUtf8 <$> configAppSettings) appSettingsSql = setConfigWithDynamicName <$> (join bimap toUtf8 <$> configAppSettings)
searchPathSql = searchPathSql =
let schemas = escapeIdentList (iSchema req : configDbExtraSearchPath) in let schemas = escapeIdentList (iSchema req : configDbExtraSearchPath) in
setConfigLocal ("search_path", schemas) setConfigWithConstantName ("search_path", schemas)
-- | Runs the pre-request function. -- | Runs the pre-request function.
runPreReq :: AppConfig -> DbHandler () runPreReq :: AppConfig -> DbHandler ()
+16 -6
View File
@@ -33,8 +33,9 @@ module PostgREST.Query.SqlFragment
, unknownEncoder , unknownEncoder
, intercalateSnippet , intercalateSnippet
, explainF , explainF
, setConfigLocal , setConfigWithConstantName
, setConfigLocalJson , setConfigWithDynamicName
, setConfigWithConstantNameJSON
, escapeIdent , escapeIdent
, escapeIdentList , escapeIdentList
) where ) where
@@ -484,14 +485,23 @@ explainF fmt opts snip =
fmtPlanFmt PlanJSON = "FORMAT JSON" fmtPlanFmt PlanJSON = "FORMAT JSON"
-- | Do a pg set_config(setting, value, true) call. This is equivalent to a SET LOCAL. -- | Do a pg set_config(setting, value, true) call. This is equivalent to a SET LOCAL.
setConfigLocal :: (ByteString, ByteString) -> SQL.Snippet setConfigLocal :: (SQL.Snippet, ByteString) -> SQL.Snippet
setConfigLocal (k, v) = setConfigLocal (k, v) =
"set_config(" <> unknownEncoder k <> ", " <> unknownEncoder v <> ", true)" "set_config(" <> k <> ", " <> unknownEncoder v <> ", true)"
-- | For when the settings are hardcoded and not parameterized
setConfigWithConstantName :: (SQL.Snippet, ByteString) -> SQL.Snippet
setConfigWithConstantName (k, v) = setConfigLocal ("'" <> k <> "'", v)
-- | For when the settings need to be parameterized
setConfigWithDynamicName :: (ByteString, ByteString) -> SQL.Snippet
setConfigWithDynamicName (k, v) =
setConfigLocal (unknownEncoder k, v)
-- | Starting from PostgreSQL v14, some characters are not allowed for config names (mostly affecting headers with "-"). -- | Starting from PostgreSQL v14, some characters are not allowed for config names (mostly affecting headers with "-").
-- | A JSON format string is used to avoid this problem. See https://github.com/PostgREST/postgrest/issues/1857 -- | A JSON format string is used to avoid this problem. See https://github.com/PostgREST/postgrest/issues/1857
setConfigLocalJson :: ByteString -> [(ByteString, ByteString)] -> [SQL.Snippet] setConfigWithConstantNameJSON :: SQL.Snippet -> [(ByteString, ByteString)] -> [SQL.Snippet]
setConfigLocalJson prefix keyVals = [setConfigLocal (prefix, gucJsonVal keyVals)] setConfigWithConstantNameJSON prefix keyVals = [setConfigWithConstantName (prefix, gucJsonVal keyVals)]
where where
gucJsonVal :: [(ByteString, ByteString)] -> ByteString gucJsonVal :: [(ByteString, ByteString)] -> ByteString
gucJsonVal = LBS.toStrict . JSON.encode . HM.fromList . arrayByteStringToText gucJsonVal = LBS.toStrict . JSON.encode . HM.fromList . arrayByteStringToText