Skip to content

Commit

Permalink
transaction-scoped settings are now shown clearly in the postgres logs
Browse files Browse the repository at this point in the history
  • Loading branch information
laurenceisla committed Nov 2, 2023
1 parent 226400a commit 96ca177
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 17 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- #1070, Fix HTTP status responses for upserts - @taimoorzaeem
+ `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
- #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

Expand Down
23 changes: 12 additions & 11 deletions src/PostgREST/Query.hs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ import PostgREST.Plan (CallReadPlan (..),
import PostgREST.Plan.MutatePlan (MutatePlan (..))
import PostgREST.Query.SqlFragment (escapeIdentList, fromQi,
intercalateSnippet,
setConfigLocal,
setConfigLocalJson)
setConfigWithConstantName,
setConfigWithConstantNameJSON,
setConfigWithDynamicName)
import PostgREST.Query.Statements (ResultSet (..))
import PostgREST.SchemaCache (SchemaCache (..))
import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..),
Expand Down Expand Up @@ -239,17 +240,17 @@ setPgLocals AppConfig{..} claims role roleSettings req = lift $
("select " <> intercalateSnippet ", " (searchPathSql : roleSql ++ roleSettingsSql ++ claimsSql ++ [methodSql, pathSql] ++ headersSql ++ cookiesSql ++ appSettingsSql))
HD.noResult configDbPreparedStatements
where
methodSql = setConfigLocal ("request.method", iMethod req)
pathSql = setConfigLocal ("request.path", iPath req)
headersSql = setConfigLocalJson "request.headers" (iHeaders req)
cookiesSql = setConfigLocalJson "request.cookies" (iCookies req)
claimsSql = [setConfigLocal ("request.jwt.claims", LBS.toStrict $ JSON.encode claims)]
roleSql = [setConfigLocal ("role", role)]
roleSettingsSql = setConfigLocal <$> roleSettings
appSettingsSql = setConfigLocal <$> (join bimap toUtf8 <$> configAppSettings)
methodSql = setConfigWithConstantName ("request.method", iMethod req)
pathSql = setConfigWithConstantName ("request.path", iPath req)
headersSql = setConfigWithConstantNameJSON "request.headers" (iHeaders req)
cookiesSql = setConfigWithConstantNameJSON "request.cookies" (iCookies req)
claimsSql = [setConfigWithConstantName ("request.jwt.claims", LBS.toStrict $ JSON.encode claims)]
roleSql = [setConfigWithConstantName ("role", role)]
roleSettingsSql = setConfigWithDynamicName <$> roleSettings
appSettingsSql = setConfigWithDynamicName <$> (join bimap toUtf8 <$> configAppSettings)
searchPathSql =
let schemas = escapeIdentList (iSchema req : configDbExtraSearchPath) in
setConfigLocal ("search_path", schemas)
setConfigWithConstantName ("search_path", schemas)

-- | Runs the pre-request function.
runPreReq :: AppConfig -> DbHandler ()
Expand Down
22 changes: 16 additions & 6 deletions src/PostgREST/Query/SqlFragment.hs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ module PostgREST.Query.SqlFragment
, unknownEncoder
, intercalateSnippet
, explainF
, setConfigLocal
, setConfigLocalJson
, setConfigWithConstantName
, setConfigWithDynamicName
, setConfigWithConstantNameJSON
, escapeIdent
, escapeIdentList
) where
Expand Down Expand Up @@ -484,14 +485,23 @@ explainF fmt opts snip =
fmtPlanFmt PlanJSON = "FORMAT JSON"

-- | 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) =
"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 "-").
-- | A JSON format string is used to avoid this problem. See https://github.com/PostgREST/postgrest/issues/1857
setConfigLocalJson :: ByteString -> [(ByteString, ByteString)] -> [SQL.Snippet]
setConfigLocalJson prefix keyVals = [setConfigLocal (prefix, gucJsonVal keyVals)]
setConfigWithConstantNameJSON :: SQL.Snippet -> [(ByteString, ByteString)] -> [SQL.Snippet]
setConfigWithConstantNameJSON prefix keyVals = [setConfigWithConstantName (prefix, gucJsonVal keyVals)]
where
gucJsonVal :: [(ByteString, ByteString)] -> ByteString
gucJsonVal = LBS.toStrict . JSON.encode . HM.fromList . arrayByteStringToText
Expand Down

0 comments on commit 96ca177

Please sign in to comment.