Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Fix not logging the JSON message to stderr on a `PGRST002` error by @laurenceisla in #4129
- Fix reloading the Schema Cache unnecessarily on a `PGRST002` error by @laurenceisla in #4367
- Fix schema cache loading taking a long time for large schemas by @mkleczek in #4360, #3704
- Fix `db-pre-config` function failing when function name are pg reserved words by @taimoorzaeem #4380

### Added

Expand Down
4 changes: 2 additions & 2 deletions src/PostgREST/AppState.hs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ import PostgREST.Config.PgVersion (PgVersion (..),
import PostgREST.SchemaCache (SchemaCache (..),
querySchemaCache,
showSummary)
import PostgREST.SchemaCache.Identifiers (dumpQi)
import PostgREST.SchemaCache.Identifiers (quoteQi)
import PostgREST.Unix (createAndBindDomainSocket)

import Data.Streaming.Network (bindPortTCP, bindRandomPortTCP)
Expand Down Expand Up @@ -441,7 +441,7 @@ readInDbConfig startingUp appState@AppState{stateObserver=observer} = do
pgVer <- getPgVersion appState
dbSettings <-
if configDbConfig conf then do
qDbSettings <- usePool appState (queryDbSettings (dumpQi <$> configDbPreConfig conf) (configDbPreparedStatements conf))
qDbSettings <- usePool appState (queryDbSettings (quoteQi <$> configDbPreConfig conf) (configDbPreparedStatements conf))
case qDbSettings of
Left e -> do
observer $ ConfigReadErrorObs e
Expand Down
7 changes: 7 additions & 0 deletions src/PostgREST/SchemaCache/Identifiers.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module PostgREST.SchemaCache.Identifiers
, TableName
, FieldName
, dumpQi
, quoteQi
, toQi
) where

Expand Down Expand Up @@ -39,6 +40,12 @@ dumpQi :: QualifiedIdentifier -> Text
dumpQi (QualifiedIdentifier s i) =
(if T.null s then mempty else s <> ".") <> i

quoteQi :: QualifiedIdentifier -> Text
quoteQi (QualifiedIdentifier s i) =
(if T.null s then mempty else quoteIdent s <> ".") <> quoteIdent i
where
quoteIdent ident = "\"" <> ident <> "\""
Comment on lines +43 to +47
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, one sec. This doesn't escape the " right?


If you test it like so:

$ PGRST_DB_PRE_CONFIG="sel\"ect" postgrest-with-postgresql-15 -f test/spec/fixtures/load.sql postgrest-run

It wil give a bad error:

24/Oct/2025:13:02:55 -0500: This is probably a bug in PostgREST, please report it at https://github.com/PostgREST/postgrest/issues. {"code":"42601","details":null,"hint":null,"message":"unterm
inated quoted identifier at or near \"\"() _ ON TRUE\n)\nSELECT DISTINCT ON (key)\n       replace(k, 'pgrst.', '') AS key,\n       v AS value\nFROM kv_settings\nWHERE k = ANY($1) AND v IS NOT 
NULL\nORDER BY key, database DESC NULLS LAST;\""}
24/Oct/2025:13:02:55 -0500: Failed to query database settings for the config parameters.{"code":"42601","details":null,"hint":null,"message":"unterminated quoted identifier at or near \"\"() _
 ON TRUE\n)\nSELECT DISTINCT ON (key)\n       replace(k, 'pgrst.', '') AS key,\n       v AS value\nFROM kv_settings\nWHERE k = ANY($1) AND v IS NOT NULL\nORDER BY key, database DESC NULLS LAST
;\""}
postgrest: thread killed


-- TODO: Handle a case where the QI comes like this: "my.fav.schema"."my.identifier"
-- Right now it only handles the schema.identifier case
toQi :: Text -> QualifiedIdentifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,23 @@
pdSchema: public
pdVolatility: Volatile

- - qiName: 'true'
qiSchema: public
- - pdDescription: null
pdFuncSettings: []
pdHasVariadic: false
pdName: 'true'
pdParams: []
pdReturnType:
contents:
contents:
qiName: bool
qiSchema: pg_catalog
tag: Scalar
tag: Single
pdSchema: public
pdVolatility: Volatile

- - qiName: create_function
qiSchema: public
- - pdDescription: null
Expand Down
4 changes: 4 additions & 0 deletions test/io/fixtures.sql
Original file line number Diff line number Diff line change
Expand Up @@ -256,3 +256,7 @@ select * from projects;

create or replace view infinite_recursion as
select * from infinite_recursion;

create or replace function "true"() returns boolean as $_$
select true;
$_$ language sql;
26 changes: 26 additions & 0 deletions test/io/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -2046,3 +2046,29 @@ def test_log_listener_connection_errors(defaultenv):
in line
for line in output
)


def test_db_pre_config_with_pg_reserved_words(defaultenv):
"The db-pre-config should not fail unexpectedly when function name is a postgres reserved word"

env = {
**defaultenv,
"PGRST_DB_PRE_CONFIG": "true", # call true function
}

with run(env=env) as postgrest:
response = postgrest.session.post("/rpc/true")
assert response.status_code == 200

env = {
**defaultenv,
"PGRST_DB_PRE_CONFIG": "select", # no "select" function in our fixtures, fail gracefully at startup
}

with run(env=env, no_startup_stdout=False, wait_for_readiness=False) as postgrest:
output = postgrest.read_stdout(nlines=8)
assert any(
'Failed to query database settings for the config parameters.{"code":"42883","details":null,"hint":"No function matches the given name and argument types. You might need to add explicit type casts.","message":"function select() does not exist"}'
in line
for line in output
)