postgrest-8.0.0: src/PostgREST/Config/Database.hs
{-# LANGUAGE QuasiQuotes #-}
module PostgREST.Config.Database
( queryDbSettings
, queryPgVersion
) where
import PostgREST.Config.PgVersion (PgVersion (..))
import qualified Hasql.Decoders as HD
import qualified Hasql.Encoders as HE
import qualified Hasql.Pool as P
import qualified Hasql.Session as H
import qualified Hasql.Statement as H
import qualified Hasql.Transaction as HT
import qualified Hasql.Transaction.Sessions as HT
import Text.InterpolatedString.Perl6 (q)
import Protolude
queryPgVersion :: H.Session PgVersion
queryPgVersion = H.statement mempty $ H.Statement sql HE.noParams versionRow False
where
sql = "SELECT current_setting('server_version_num')::integer, current_setting('server_version')"
versionRow = HD.singleRow $ PgVersion <$> column HD.int4 <*> column HD.text
queryDbSettings :: P.Pool -> Bool -> IO (Either P.UsageError [(Text, Text)])
queryDbSettings pool prepared =
let transaction = if prepared then HT.transaction else HT.unpreparedTransaction in
P.use pool . transaction HT.ReadCommitted HT.Read $
HT.statement mempty dbSettingsStatement
-- | Get db settings from the connection role. Global settings will be overridden by database specific settings.
dbSettingsStatement :: H.Statement () [(Text, Text)]
dbSettingsStatement = H.Statement sql HE.noParams decodeSettings False
where
sql = [q|
with
role_setting as (
select setdatabase, unnest(setconfig) as setting from pg_catalog.pg_db_role_setting
where setrole = current_user::regrole::oid
and setdatabase in (0, (select oid from pg_catalog.pg_database where datname = current_catalog))
),
kv_settings as (
select setdatabase, split_part(setting, '=', 1) as k, split_part(setting, '=', 2) as value from role_setting
where setting like 'pgrst.%'
)
select distinct on (key) replace(k, 'pgrst.', '') as key, value
from kv_settings
order by key, setdatabase desc;
|]
decodeSettings = HD.rowList $ (,) <$> column HD.text <*> column HD.text
column :: HD.Value a -> HD.Row a
column = HD.column . HD.nonNullable