fix: db-pre-config function failing with pg reserved words
When db-pre-config is accidentally set to a pg reserved word like "true", it fails with a confusing error. The function names should be properly quoted to avoid such errors. This commit resolves this by quoting the pre-config function name. Signed-off-by: Taimoor Zaeem <taimoorzaeem@gmail.com>
This commit is contained in:
committed by
Steve Chavez
parent
75d4131aa6
commit
a688878236
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. From versio
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
|
||||||
|
- Fix `db-pre-config` function failing when function names are pg reserved words by @taimoorzaeem #4380
|
||||||
|
|
||||||
## [14.0] - 2025-10-24
|
## [14.0] - 2025-10-24
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ import PostgREST.Config.PgVersion (PgVersion (..),
|
|||||||
import PostgREST.SchemaCache (SchemaCache (..),
|
import PostgREST.SchemaCache (SchemaCache (..),
|
||||||
querySchemaCache,
|
querySchemaCache,
|
||||||
showSummary)
|
showSummary)
|
||||||
import PostgREST.SchemaCache.Identifiers (dumpQi)
|
import PostgREST.SchemaCache.Identifiers (quoteQi)
|
||||||
import PostgREST.Unix (createAndBindDomainSocket)
|
import PostgREST.Unix (createAndBindDomainSocket)
|
||||||
|
|
||||||
import Data.Streaming.Network (bindPortTCP, bindRandomPortTCP)
|
import Data.Streaming.Network (bindPortTCP, bindRandomPortTCP)
|
||||||
@@ -441,7 +441,7 @@ readInDbConfig startingUp appState@AppState{stateObserver=observer} = do
|
|||||||
pgVer <- getPgVersion appState
|
pgVer <- getPgVersion appState
|
||||||
dbSettings <-
|
dbSettings <-
|
||||||
if configDbConfig conf then do
|
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
|
case qDbSettings of
|
||||||
Left e -> do
|
Left e -> do
|
||||||
observer $ ConfigReadErrorObs e
|
observer $ ConfigReadErrorObs e
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ module PostgREST.SchemaCache.Identifiers
|
|||||||
, dumpQi
|
, dumpQi
|
||||||
, escapeIdent
|
, escapeIdent
|
||||||
, isAnyElement
|
, isAnyElement
|
||||||
|
, quoteQi
|
||||||
, toQi
|
, toQi
|
||||||
, trimNullChars
|
, trimNullChars
|
||||||
) where
|
) where
|
||||||
@@ -41,6 +42,10 @@ dumpQi :: QualifiedIdentifier -> Text
|
|||||||
dumpQi (QualifiedIdentifier s i) =
|
dumpQi (QualifiedIdentifier s i) =
|
||||||
(if T.null s then mempty else 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 escapeIdent s <> ".") <> escapeIdent i
|
||||||
|
|
||||||
-- TODO: Handle a case where the QI comes like this: "my.fav.schema"."my.identifier"
|
-- TODO: Handle a case where the QI comes like this: "my.fav.schema"."my.identifier"
|
||||||
-- Right now it only handles the schema.identifier case
|
-- Right now it only handles the schema.identifier case
|
||||||
toQi :: Text -> QualifiedIdentifier
|
toQi :: Text -> QualifiedIdentifier
|
||||||
|
|||||||
@@ -461,6 +461,23 @@
|
|||||||
pdSchema: public
|
pdSchema: public
|
||||||
pdVolatility: Volatile
|
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
|
- - qiName: create_function
|
||||||
qiSchema: public
|
qiSchema: public
|
||||||
- - pdDescription: null
|
- - pdDescription: null
|
||||||
|
|||||||
@@ -256,3 +256,7 @@ select * from projects;
|
|||||||
|
|
||||||
create or replace view infinite_recursion as
|
create or replace view infinite_recursion as
|
||||||
select * from infinite_recursion;
|
select * from infinite_recursion;
|
||||||
|
|
||||||
|
create or replace function "true"() returns boolean as $_$
|
||||||
|
select true;
|
||||||
|
$_$ language sql;
|
||||||
|
|||||||
@@ -2046,3 +2046,29 @@ def test_log_listener_connection_errors(defaultenv):
|
|||||||
in line
|
in line
|
||||||
for line in output
|
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
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user