2022-03-16 03:39:21 +03:00
|
|
|
{-# LANGUAGE TemplateHaskell #-}
|
2022-03-09 10:14:18 +03:00
|
|
|
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
|
|
|
|
|
|
|
-- | Postgres Connection Settings
|
|
|
|
--
|
|
|
|
-- This module contains types and combinators related to postgres connection,
|
|
|
|
-- pool, and replica related settings.
|
|
|
|
module Hasura.Backends.Postgres.Connection.Settings
|
|
|
|
( PostgresPoolSettings (..),
|
|
|
|
PostgresSourceConnInfo (..),
|
|
|
|
PostgresConnConfiguration (..),
|
|
|
|
PGClientCerts (..),
|
|
|
|
CertVar (..),
|
|
|
|
CertData (..),
|
|
|
|
SSLMode (..),
|
|
|
|
DefaultPostgresPoolSettings (..),
|
|
|
|
getDefaultPGPoolSettingIfNotExists,
|
|
|
|
defaultPostgresPoolSettings,
|
2022-08-10 12:40:57 +03:00
|
|
|
defaultPostgresExtensionsSchema,
|
2022-03-09 10:14:18 +03:00
|
|
|
setPostgresPoolSettings,
|
|
|
|
pccConnectionInfo,
|
|
|
|
pccReadReplicas,
|
2022-08-10 12:40:57 +03:00
|
|
|
pccExtensionsSchema,
|
2022-03-09 10:14:18 +03:00
|
|
|
psciDatabaseUrl,
|
|
|
|
psciPoolSettings,
|
|
|
|
psciUsePreparedStatements,
|
|
|
|
psciIsolationLevel,
|
|
|
|
psciSslConfiguration,
|
|
|
|
)
|
|
|
|
where
|
|
|
|
|
2022-09-13 00:45:24 +03:00
|
|
|
import Autodocodec hiding (object, (.=))
|
|
|
|
import Autodocodec qualified as AC
|
2022-03-09 10:14:18 +03:00
|
|
|
import Control.Lens (makeLenses)
|
|
|
|
import Data.Aeson
|
|
|
|
import Data.Aeson.Casing (aesonDrop)
|
|
|
|
import Data.Aeson.TH
|
|
|
|
import Data.Bifoldable
|
|
|
|
import Data.Bifunctor
|
|
|
|
import Data.Bitraversable
|
|
|
|
import Data.Char (toLower)
|
2022-09-13 00:45:24 +03:00
|
|
|
import Data.List.NonEmpty qualified as NonEmpty
|
2022-03-09 10:14:18 +03:00
|
|
|
import Data.Semigroup (Max (..))
|
|
|
|
import Data.Text (unpack)
|
|
|
|
import Data.Text qualified as T
|
|
|
|
import Data.Time
|
2022-06-08 18:31:28 +03:00
|
|
|
import Data.Time.Clock.Compat ()
|
Import `pg-client-hs` as `PG`
Result of executing the following commands:
```shell
# replace "as Q" imports with "as PG" (in retrospect this didn't need a regex)
git grep -lE 'as Q($|[^a-zA-Z])' -- '*.hs' | xargs sed -i -E 's/as Q($|[^a-zA-Z])/as PG\1/'
# replace " Q." with " PG."
git grep -lE ' Q\.' -- '*.hs' | xargs sed -i 's/ Q\./ PG./g'
# replace "(Q." with "(PG."
git grep -lE '\(Q\.' -- '*.hs' | xargs sed -i 's/(Q\./(PG./g'
# ditto, but for [, |, { and !
git grep -lE '\[Q\.' -- '*.hs' | xargs sed -i 's/\[Q\./\[PG./g'
git grep -l '|Q\.' -- '*.hs' | xargs sed -i 's/|Q\./|PG./g'
git grep -l '{Q\.' -- '*.hs' | xargs sed -i 's/{Q\./{PG./g'
git grep -l '!Q\.' -- '*.hs' | xargs sed -i 's/!Q\./!PG./g'
```
(Doing the `grep -l` before the `sed`, instead of `sed` on the entire codebase, reduces the number of `mtime` updates, and so reduces how many times a file gets recompiled while checking intermediate results.)
Finally, I manually removed a broken and unused `Arbitrary` instance in `Hasura.RQL.Network`. (It used an `import Test.QuickCheck.Arbitrary as Q` statement, which was erroneously caught by the first find-replace command.)
After this PR, `Q` is no longer used as an import qualifier. That was not the goal of this PR, but perhaps it's a useful fact for future efforts.
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5933
GitOrigin-RevId: 8c84c59d57789111d40f5d3322c5a885dcfbf40e
2022-09-20 22:54:43 +03:00
|
|
|
import Database.PG.Query qualified as PG
|
2022-03-09 10:14:18 +03:00
|
|
|
import Hasura.Base.Instances ()
|
|
|
|
import Hasura.Incremental (Cacheable (..))
|
|
|
|
import Hasura.Prelude
|
|
|
|
import Hasura.RQL.Types.Common (UrlConf (..))
|
2022-08-10 12:40:57 +03:00
|
|
|
import Hasura.SQL.Types (ExtensionsSchema (..))
|
2022-03-09 10:14:18 +03:00
|
|
|
import Hasura.Server.Utils (parseConnLifeTime, readIsoLevel)
|
|
|
|
import Test.QuickCheck.Instances.Semigroup ()
|
|
|
|
import Test.QuickCheck.Instances.Time ()
|
|
|
|
|
|
|
|
data PostgresPoolSettings = PostgresPoolSettings
|
2022-07-29 17:05:03 +03:00
|
|
|
{ _ppsMaxConnections :: Maybe Int,
|
|
|
|
_ppsIdleTimeout :: Maybe Int,
|
|
|
|
_ppsRetries :: Maybe Int,
|
|
|
|
_ppsPoolTimeout :: Maybe NominalDiffTime,
|
|
|
|
_ppsConnectionLifetime :: Maybe NominalDiffTime
|
2022-03-09 10:14:18 +03:00
|
|
|
}
|
|
|
|
deriving (Show, Eq, Generic)
|
|
|
|
|
|
|
|
instance Cacheable PostgresPoolSettings
|
|
|
|
|
|
|
|
instance Hashable PostgresPoolSettings
|
|
|
|
|
|
|
|
instance NFData PostgresPoolSettings
|
|
|
|
|
2022-09-13 00:45:24 +03:00
|
|
|
instance HasCodec PostgresPoolSettings where
|
|
|
|
codec =
|
|
|
|
CommentCodec "https://hasura.io/docs/latest/graphql/core/api-reference/syntax-defs.html#pgpoolsettings" $
|
|
|
|
AC.object "PostgresPoolSettings" $
|
|
|
|
PostgresPoolSettings
|
|
|
|
<$> optionalFieldOrNull "max_connections" maxConnectionsDoc .== _ppsMaxConnections
|
|
|
|
<*> optionalFieldOrNull "idle_timeout" idleTimeoutDoc .== _ppsIdleTimeout
|
|
|
|
<*> optionalFieldOrNull "retries" retriesDoc .== _ppsRetries
|
|
|
|
<*> optionalFieldOrNull "pool_timeout" poolTimeoutDoc .== _ppsPoolTimeout
|
|
|
|
<*> parseConnLifeTime `rmapCodec` optionalFieldOrNull "connection_lifetime" connectionLifetimeDoc .== _ppsConnectionLifetime
|
|
|
|
where
|
|
|
|
maxConnectionsDoc = "Maximum number of connections to be kept in the pool (default: 50)"
|
|
|
|
idleTimeoutDoc = "The idle timeout (in seconds) per connection (default: 180)"
|
|
|
|
retriesDoc = "Number of retries to perform (default: 1)"
|
|
|
|
poolTimeoutDoc = "Maximum time to wait while acquiring a Postgres connection from the pool, in seconds (default: forever)"
|
|
|
|
connectionLifetimeDoc =
|
|
|
|
T.unwords
|
|
|
|
[ "Time from connection creation after which the connection should be",
|
|
|
|
"destroyed and a new one created. A value of 0 indicates we should",
|
|
|
|
"never destroy an active connection. If 0 is passed, memory from large",
|
|
|
|
"query results may not be reclaimed. (default: 600 sec)"
|
|
|
|
]
|
|
|
|
(.==) = (AC..=)
|
|
|
|
|
2022-03-09 10:14:18 +03:00
|
|
|
$(deriveToJSON hasuraJSON {omitNothingFields = True} ''PostgresPoolSettings)
|
|
|
|
|
|
|
|
instance FromJSON PostgresPoolSettings where
|
|
|
|
parseJSON = withObject "PostgresPoolSettings" $ \o ->
|
|
|
|
PostgresPoolSettings
|
|
|
|
<$> o .:? "max_connections"
|
|
|
|
<*> o .:? "idle_timeout"
|
|
|
|
<*> o .:? "retries"
|
|
|
|
<*> o .:? "pool_timeout"
|
|
|
|
<*> ((o .:? "connection_lifetime") <&> parseConnLifeTime)
|
|
|
|
|
|
|
|
data DefaultPostgresPoolSettings = DefaultPostgresPoolSettings
|
2022-07-29 17:05:03 +03:00
|
|
|
{ _dppsMaxConnections :: Int,
|
|
|
|
_dppsIdleTimeout :: Int,
|
|
|
|
_dppsRetries :: Int,
|
|
|
|
_dppsConnectionLifetime :: Maybe NominalDiffTime
|
2022-03-09 10:14:18 +03:00
|
|
|
}
|
|
|
|
deriving (Show, Eq)
|
|
|
|
|
|
|
|
defaultPostgresPoolSettings :: DefaultPostgresPoolSettings
|
|
|
|
defaultPostgresPoolSettings = DefaultPostgresPoolSettings 50 180 1 (Just 600)
|
|
|
|
|
|
|
|
-- Use this when you want to set only few of the PG Pool settings.
|
|
|
|
-- The values which are not set will use the default values.
|
|
|
|
setPostgresPoolSettings :: PostgresPoolSettings
|
|
|
|
setPostgresPoolSettings =
|
|
|
|
PostgresPoolSettings
|
|
|
|
{ _ppsMaxConnections = (Just $ _dppsMaxConnections defaultPostgresPoolSettings),
|
|
|
|
_ppsIdleTimeout = (Just $ _dppsIdleTimeout defaultPostgresPoolSettings),
|
|
|
|
_ppsRetries = (Just $ _dppsRetries defaultPostgresPoolSettings),
|
|
|
|
_ppsPoolTimeout = Nothing, -- @Nothing@ is the default value of the pool timeout
|
|
|
|
_ppsConnectionLifetime = _dppsConnectionLifetime defaultPostgresPoolSettings
|
|
|
|
}
|
|
|
|
|
|
|
|
-- PG Pool Settings are not given by the user, set defaults
|
|
|
|
getDefaultPGPoolSettingIfNotExists :: Maybe PostgresPoolSettings -> DefaultPostgresPoolSettings -> (Int, Int, Int)
|
|
|
|
getDefaultPGPoolSettingIfNotExists connSettings defaultPgPoolSettings =
|
|
|
|
case connSettings of
|
|
|
|
-- Atleast one of the postgres pool settings is set, then set default values to other settings
|
|
|
|
Just connSettings' ->
|
|
|
|
(maxConnections connSettings', idleTimeout connSettings', retries connSettings')
|
|
|
|
-- No PG Pool settings provided by user, set default values for all
|
|
|
|
Nothing -> (defMaxConnections, defIdleTimeout, defRetries)
|
|
|
|
where
|
|
|
|
defMaxConnections = _dppsMaxConnections defaultPgPoolSettings
|
|
|
|
defIdleTimeout = _dppsIdleTimeout defaultPgPoolSettings
|
|
|
|
defRetries = _dppsRetries defaultPgPoolSettings
|
|
|
|
|
|
|
|
maxConnections = fromMaybe defMaxConnections . _ppsMaxConnections
|
|
|
|
idleTimeout = fromMaybe defIdleTimeout . _ppsIdleTimeout
|
|
|
|
retries = fromMaybe defRetries . _ppsRetries
|
|
|
|
|
|
|
|
data SSLMode
|
|
|
|
= Disable
|
|
|
|
| Allow
|
|
|
|
| Prefer
|
|
|
|
| Require
|
|
|
|
| VerifyCA
|
|
|
|
| VerifyFull
|
|
|
|
deriving (Eq, Ord, Generic, Enum, Bounded)
|
|
|
|
|
|
|
|
instance Cacheable SSLMode
|
|
|
|
|
|
|
|
instance Hashable SSLMode
|
|
|
|
|
|
|
|
instance NFData SSLMode
|
|
|
|
|
|
|
|
instance Show SSLMode where
|
|
|
|
show = \case
|
|
|
|
Disable -> "disable"
|
|
|
|
Allow -> "allow"
|
|
|
|
Prefer -> "prefer"
|
|
|
|
Require -> "require"
|
|
|
|
VerifyCA -> "verify-ca"
|
|
|
|
VerifyFull -> "verify-full"
|
|
|
|
|
|
|
|
deriving via (Max SSLMode) instance Semigroup SSLMode
|
|
|
|
|
2022-09-13 00:45:24 +03:00
|
|
|
instance HasCodec SSLMode where
|
|
|
|
codec =
|
|
|
|
named "SSLMode" $
|
|
|
|
stringConstCodec $
|
|
|
|
NonEmpty.fromList $
|
|
|
|
(\m -> (m, tshow m)) <$> [minBound ..]
|
|
|
|
|
2022-03-09 10:14:18 +03:00
|
|
|
instance FromJSON SSLMode where
|
|
|
|
parseJSON = withText "SSLMode" $ \case
|
|
|
|
"disable" -> pure Disable
|
|
|
|
"allow" -> pure Allow
|
|
|
|
"prefer" -> pure Prefer
|
|
|
|
"require" -> pure Require
|
|
|
|
"verify-ca" -> pure VerifyCA
|
|
|
|
"verify-full" -> pure VerifyFull
|
|
|
|
err -> fail $ "Invalid SSL Mode " <> unpack err
|
|
|
|
|
2022-06-28 04:25:03 +03:00
|
|
|
newtype CertVar
|
2022-03-09 10:14:18 +03:00
|
|
|
= CertVar String
|
|
|
|
deriving (Show, Eq, Generic)
|
|
|
|
|
|
|
|
instance Cacheable CertVar
|
|
|
|
|
|
|
|
instance Hashable CertVar
|
|
|
|
|
|
|
|
instance NFData CertVar
|
|
|
|
|
2022-09-13 00:45:24 +03:00
|
|
|
instance HasCodec CertVar where
|
|
|
|
codec =
|
|
|
|
AC.object "CertVar" $ CertVar <$> requiredField' "from_env" .== unCertVar
|
|
|
|
where
|
|
|
|
unCertVar (CertVar t) = t
|
|
|
|
(.==) = (AC..=)
|
|
|
|
|
2022-03-09 10:14:18 +03:00
|
|
|
instance ToJSON CertVar where
|
|
|
|
toJSON (CertVar var) = (object ["from_env" .= var])
|
|
|
|
|
|
|
|
instance FromJSON CertVar where
|
2022-06-28 04:25:03 +03:00
|
|
|
parseJSON = withObject "CertVar" (\o -> CertVar <$> o .: "from_env")
|
2022-03-09 10:14:18 +03:00
|
|
|
|
|
|
|
newtype CertData = CertData {unCert :: Text}
|
|
|
|
deriving (Show, Eq, Generic)
|
|
|
|
|
2022-09-13 00:45:24 +03:00
|
|
|
instance HasCodec CertData where
|
|
|
|
codec = dimapCodec CertData unCert textCodec
|
|
|
|
|
2022-03-09 10:14:18 +03:00
|
|
|
instance ToJSON CertData where
|
|
|
|
toJSON = String . unCert
|
|
|
|
|
|
|
|
data PGClientCerts p a = PGClientCerts
|
2022-06-28 04:25:03 +03:00
|
|
|
{ pgcSslCert :: Maybe a,
|
|
|
|
pgcSslKey :: Maybe a,
|
|
|
|
pgcSslRootCert :: Maybe a,
|
2022-03-09 10:14:18 +03:00
|
|
|
pgcSslMode :: SSLMode,
|
|
|
|
pgcSslPassword :: Maybe p
|
|
|
|
}
|
|
|
|
deriving (Show, Eq, Generic, Functor, Foldable, Traversable)
|
|
|
|
|
2022-09-13 00:45:24 +03:00
|
|
|
instance (HasCodec p, HasCodec a) => HasCodec (PGClientCerts p a) where
|
|
|
|
codec =
|
|
|
|
CommentCodec "https://hasura.io/docs/latest/graphql/core/api-reference/syntax-defs.html#pgcertsettings" $
|
|
|
|
AC.object "PGClientCerts" $
|
|
|
|
PGClientCerts
|
|
|
|
<$> optionalFieldOrNull "sslcert" sslcertDoc .== pgcSslCert
|
|
|
|
<*> optionalFieldOrNull "sslkey" sslkeyDoc .== pgcSslKey
|
|
|
|
<*> optionalFieldOrNull "sslrootcert" sslrootcertDoc .== pgcSslRootCert
|
|
|
|
<*> requiredField "sslmode" sslmodeDoc .== pgcSslMode
|
|
|
|
<*> optionalFieldOrNull "sslpassword" sslpasswordDoc .== pgcSslPassword
|
|
|
|
where
|
|
|
|
sslcertDoc = "Environment variable which stores the client certificate."
|
|
|
|
sslkeyDoc = "Environment variable which stores the client private key."
|
|
|
|
sslrootcertDoc = "Environment variable which stores trusted certificate authorities."
|
|
|
|
sslmodeDoc = "The SSL connection mode. See the libpq ssl support docs <https://www.postgresql.org/docs/9.1/libpq-ssl.html> for more details."
|
|
|
|
sslpasswordDoc = "Password in the case where the sslkey is encrypted."
|
|
|
|
(.==) = (AC..=)
|
|
|
|
|
2022-03-09 10:14:18 +03:00
|
|
|
$(deriveFromJSON (aesonDrop 3 (fmap toLower)) ''PGClientCerts)
|
2022-06-28 04:25:03 +03:00
|
|
|
$(deriveToJSON (aesonDrop 3 (fmap toLower)) {omitNothingFields = True} ''PGClientCerts)
|
2022-03-09 10:14:18 +03:00
|
|
|
|
|
|
|
instance Bifunctor PGClientCerts where
|
2022-03-16 03:39:21 +03:00
|
|
|
bimap f g oldCerts@(PGClientCerts {pgcSslPassword}) =
|
|
|
|
let certs = oldCerts {pgcSslPassword = f <$> pgcSslPassword}
|
|
|
|
in g <$> certs
|
2022-03-09 10:14:18 +03:00
|
|
|
|
|
|
|
instance Bifoldable PGClientCerts where
|
|
|
|
bifoldMap f g PGClientCerts {..} =
|
2022-06-28 04:25:03 +03:00
|
|
|
let gs = foldMap (foldMap g) [pgcSslCert, pgcSslKey, pgcSslRootCert]
|
2022-03-16 03:39:21 +03:00
|
|
|
fs = foldMap f pgcSslPassword
|
|
|
|
in gs <> fs
|
2022-03-09 10:14:18 +03:00
|
|
|
|
|
|
|
instance Bitraversable PGClientCerts where
|
|
|
|
bitraverse f g PGClientCerts {..} =
|
2022-03-16 03:39:21 +03:00
|
|
|
PGClientCerts
|
2022-06-28 04:25:03 +03:00
|
|
|
<$> traverse g pgcSslCert
|
|
|
|
<*> traverse g pgcSslKey
|
|
|
|
<*> traverse g pgcSslRootCert
|
2022-03-16 03:39:21 +03:00
|
|
|
<*> pure pgcSslMode
|
|
|
|
<*> traverse f pgcSslPassword
|
2022-03-09 10:14:18 +03:00
|
|
|
|
|
|
|
instance (Cacheable p, Cacheable a) => Cacheable (PGClientCerts p a)
|
|
|
|
|
|
|
|
instance (Hashable p, Hashable a) => Hashable (PGClientCerts p a)
|
|
|
|
|
|
|
|
instance (NFData p, NFData a) => NFData (PGClientCerts p a)
|
|
|
|
|
|
|
|
instance ToJSON SSLMode where
|
|
|
|
toJSON = String . tshow
|
|
|
|
|
Import `pg-client-hs` as `PG`
Result of executing the following commands:
```shell
# replace "as Q" imports with "as PG" (in retrospect this didn't need a regex)
git grep -lE 'as Q($|[^a-zA-Z])' -- '*.hs' | xargs sed -i -E 's/as Q($|[^a-zA-Z])/as PG\1/'
# replace " Q." with " PG."
git grep -lE ' Q\.' -- '*.hs' | xargs sed -i 's/ Q\./ PG./g'
# replace "(Q." with "(PG."
git grep -lE '\(Q\.' -- '*.hs' | xargs sed -i 's/(Q\./(PG./g'
# ditto, but for [, |, { and !
git grep -lE '\[Q\.' -- '*.hs' | xargs sed -i 's/\[Q\./\[PG./g'
git grep -l '|Q\.' -- '*.hs' | xargs sed -i 's/|Q\./|PG./g'
git grep -l '{Q\.' -- '*.hs' | xargs sed -i 's/{Q\./{PG./g'
git grep -l '!Q\.' -- '*.hs' | xargs sed -i 's/!Q\./!PG./g'
```
(Doing the `grep -l` before the `sed`, instead of `sed` on the entire codebase, reduces the number of `mtime` updates, and so reduces how many times a file gets recompiled while checking intermediate results.)
Finally, I manually removed a broken and unused `Arbitrary` instance in `Hasura.RQL.Network`. (It used an `import Test.QuickCheck.Arbitrary as Q` statement, which was erroneously caught by the first find-replace command.)
After this PR, `Q` is no longer used as an import qualifier. That was not the goal of this PR, but perhaps it's a useful fact for future efforts.
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5933
GitOrigin-RevId: 8c84c59d57789111d40f5d3322c5a885dcfbf40e
2022-09-20 22:54:43 +03:00
|
|
|
deriving instance Generic PG.TxIsolation
|
2022-03-09 10:14:18 +03:00
|
|
|
|
Import `pg-client-hs` as `PG`
Result of executing the following commands:
```shell
# replace "as Q" imports with "as PG" (in retrospect this didn't need a regex)
git grep -lE 'as Q($|[^a-zA-Z])' -- '*.hs' | xargs sed -i -E 's/as Q($|[^a-zA-Z])/as PG\1/'
# replace " Q." with " PG."
git grep -lE ' Q\.' -- '*.hs' | xargs sed -i 's/ Q\./ PG./g'
# replace "(Q." with "(PG."
git grep -lE '\(Q\.' -- '*.hs' | xargs sed -i 's/(Q\./(PG./g'
# ditto, but for [, |, { and !
git grep -lE '\[Q\.' -- '*.hs' | xargs sed -i 's/\[Q\./\[PG./g'
git grep -l '|Q\.' -- '*.hs' | xargs sed -i 's/|Q\./|PG./g'
git grep -l '{Q\.' -- '*.hs' | xargs sed -i 's/{Q\./{PG./g'
git grep -l '!Q\.' -- '*.hs' | xargs sed -i 's/!Q\./!PG./g'
```
(Doing the `grep -l` before the `sed`, instead of `sed` on the entire codebase, reduces the number of `mtime` updates, and so reduces how many times a file gets recompiled while checking intermediate results.)
Finally, I manually removed a broken and unused `Arbitrary` instance in `Hasura.RQL.Network`. (It used an `import Test.QuickCheck.Arbitrary as Q` statement, which was erroneously caught by the first find-replace command.)
After this PR, `Q` is no longer used as an import qualifier. That was not the goal of this PR, but perhaps it's a useful fact for future efforts.
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5933
GitOrigin-RevId: 8c84c59d57789111d40f5d3322c5a885dcfbf40e
2022-09-20 22:54:43 +03:00
|
|
|
instance Cacheable PG.TxIsolation
|
2022-03-09 10:14:18 +03:00
|
|
|
|
Import `pg-client-hs` as `PG`
Result of executing the following commands:
```shell
# replace "as Q" imports with "as PG" (in retrospect this didn't need a regex)
git grep -lE 'as Q($|[^a-zA-Z])' -- '*.hs' | xargs sed -i -E 's/as Q($|[^a-zA-Z])/as PG\1/'
# replace " Q." with " PG."
git grep -lE ' Q\.' -- '*.hs' | xargs sed -i 's/ Q\./ PG./g'
# replace "(Q." with "(PG."
git grep -lE '\(Q\.' -- '*.hs' | xargs sed -i 's/(Q\./(PG./g'
# ditto, but for [, |, { and !
git grep -lE '\[Q\.' -- '*.hs' | xargs sed -i 's/\[Q\./\[PG./g'
git grep -l '|Q\.' -- '*.hs' | xargs sed -i 's/|Q\./|PG./g'
git grep -l '{Q\.' -- '*.hs' | xargs sed -i 's/{Q\./{PG./g'
git grep -l '!Q\.' -- '*.hs' | xargs sed -i 's/!Q\./!PG./g'
```
(Doing the `grep -l` before the `sed`, instead of `sed` on the entire codebase, reduces the number of `mtime` updates, and so reduces how many times a file gets recompiled while checking intermediate results.)
Finally, I manually removed a broken and unused `Arbitrary` instance in `Hasura.RQL.Network`. (It used an `import Test.QuickCheck.Arbitrary as Q` statement, which was erroneously caught by the first find-replace command.)
After this PR, `Q` is no longer used as an import qualifier. That was not the goal of this PR, but perhaps it's a useful fact for future efforts.
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5933
GitOrigin-RevId: 8c84c59d57789111d40f5d3322c5a885dcfbf40e
2022-09-20 22:54:43 +03:00
|
|
|
instance NFData PG.TxIsolation
|
2022-03-09 10:14:18 +03:00
|
|
|
|
Import `pg-client-hs` as `PG`
Result of executing the following commands:
```shell
# replace "as Q" imports with "as PG" (in retrospect this didn't need a regex)
git grep -lE 'as Q($|[^a-zA-Z])' -- '*.hs' | xargs sed -i -E 's/as Q($|[^a-zA-Z])/as PG\1/'
# replace " Q." with " PG."
git grep -lE ' Q\.' -- '*.hs' | xargs sed -i 's/ Q\./ PG./g'
# replace "(Q." with "(PG."
git grep -lE '\(Q\.' -- '*.hs' | xargs sed -i 's/(Q\./(PG./g'
# ditto, but for [, |, { and !
git grep -lE '\[Q\.' -- '*.hs' | xargs sed -i 's/\[Q\./\[PG./g'
git grep -l '|Q\.' -- '*.hs' | xargs sed -i 's/|Q\./|PG./g'
git grep -l '{Q\.' -- '*.hs' | xargs sed -i 's/{Q\./{PG./g'
git grep -l '!Q\.' -- '*.hs' | xargs sed -i 's/!Q\./!PG./g'
```
(Doing the `grep -l` before the `sed`, instead of `sed` on the entire codebase, reduces the number of `mtime` updates, and so reduces how many times a file gets recompiled while checking intermediate results.)
Finally, I manually removed a broken and unused `Arbitrary` instance in `Hasura.RQL.Network`. (It used an `import Test.QuickCheck.Arbitrary as Q` statement, which was erroneously caught by the first find-replace command.)
After this PR, `Q` is no longer used as an import qualifier. That was not the goal of this PR, but perhaps it's a useful fact for future efforts.
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5933
GitOrigin-RevId: 8c84c59d57789111d40f5d3322c5a885dcfbf40e
2022-09-20 22:54:43 +03:00
|
|
|
instance Hashable PG.TxIsolation
|
2022-03-09 10:14:18 +03:00
|
|
|
|
Import `pg-client-hs` as `PG`
Result of executing the following commands:
```shell
# replace "as Q" imports with "as PG" (in retrospect this didn't need a regex)
git grep -lE 'as Q($|[^a-zA-Z])' -- '*.hs' | xargs sed -i -E 's/as Q($|[^a-zA-Z])/as PG\1/'
# replace " Q." with " PG."
git grep -lE ' Q\.' -- '*.hs' | xargs sed -i 's/ Q\./ PG./g'
# replace "(Q." with "(PG."
git grep -lE '\(Q\.' -- '*.hs' | xargs sed -i 's/(Q\./(PG./g'
# ditto, but for [, |, { and !
git grep -lE '\[Q\.' -- '*.hs' | xargs sed -i 's/\[Q\./\[PG./g'
git grep -l '|Q\.' -- '*.hs' | xargs sed -i 's/|Q\./|PG./g'
git grep -l '{Q\.' -- '*.hs' | xargs sed -i 's/{Q\./{PG./g'
git grep -l '!Q\.' -- '*.hs' | xargs sed -i 's/!Q\./!PG./g'
```
(Doing the `grep -l` before the `sed`, instead of `sed` on the entire codebase, reduces the number of `mtime` updates, and so reduces how many times a file gets recompiled while checking intermediate results.)
Finally, I manually removed a broken and unused `Arbitrary` instance in `Hasura.RQL.Network`. (It used an `import Test.QuickCheck.Arbitrary as Q` statement, which was erroneously caught by the first find-replace command.)
After this PR, `Q` is no longer used as an import qualifier. That was not the goal of this PR, but perhaps it's a useful fact for future efforts.
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5933
GitOrigin-RevId: 8c84c59d57789111d40f5d3322c5a885dcfbf40e
2022-09-20 22:54:43 +03:00
|
|
|
instance HasCodec PG.TxIsolation where
|
2022-09-13 00:45:24 +03:00
|
|
|
codec =
|
|
|
|
named "TxIsolation" $
|
|
|
|
stringConstCodec $
|
|
|
|
NonEmpty.fromList $
|
Import `pg-client-hs` as `PG`
Result of executing the following commands:
```shell
# replace "as Q" imports with "as PG" (in retrospect this didn't need a regex)
git grep -lE 'as Q($|[^a-zA-Z])' -- '*.hs' | xargs sed -i -E 's/as Q($|[^a-zA-Z])/as PG\1/'
# replace " Q." with " PG."
git grep -lE ' Q\.' -- '*.hs' | xargs sed -i 's/ Q\./ PG./g'
# replace "(Q." with "(PG."
git grep -lE '\(Q\.' -- '*.hs' | xargs sed -i 's/(Q\./(PG./g'
# ditto, but for [, |, { and !
git grep -lE '\[Q\.' -- '*.hs' | xargs sed -i 's/\[Q\./\[PG./g'
git grep -l '|Q\.' -- '*.hs' | xargs sed -i 's/|Q\./|PG./g'
git grep -l '{Q\.' -- '*.hs' | xargs sed -i 's/{Q\./{PG./g'
git grep -l '!Q\.' -- '*.hs' | xargs sed -i 's/!Q\./!PG./g'
```
(Doing the `grep -l` before the `sed`, instead of `sed` on the entire codebase, reduces the number of `mtime` updates, and so reduces how many times a file gets recompiled while checking intermediate results.)
Finally, I manually removed a broken and unused `Arbitrary` instance in `Hasura.RQL.Network`. (It used an `import Test.QuickCheck.Arbitrary as Q` statement, which was erroneously caught by the first find-replace command.)
After this PR, `Q` is no longer used as an import qualifier. That was not the goal of this PR, but perhaps it's a useful fact for future efforts.
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5933
GitOrigin-RevId: 8c84c59d57789111d40f5d3322c5a885dcfbf40e
2022-09-20 22:54:43 +03:00
|
|
|
[ (PG.ReadCommitted, "read-committed"),
|
|
|
|
(PG.RepeatableRead, "repeatable-read"),
|
|
|
|
(PG.Serializable, "serializable")
|
2022-09-13 00:45:24 +03:00
|
|
|
]
|
|
|
|
|
Import `pg-client-hs` as `PG`
Result of executing the following commands:
```shell
# replace "as Q" imports with "as PG" (in retrospect this didn't need a regex)
git grep -lE 'as Q($|[^a-zA-Z])' -- '*.hs' | xargs sed -i -E 's/as Q($|[^a-zA-Z])/as PG\1/'
# replace " Q." with " PG."
git grep -lE ' Q\.' -- '*.hs' | xargs sed -i 's/ Q\./ PG./g'
# replace "(Q." with "(PG."
git grep -lE '\(Q\.' -- '*.hs' | xargs sed -i 's/(Q\./(PG./g'
# ditto, but for [, |, { and !
git grep -lE '\[Q\.' -- '*.hs' | xargs sed -i 's/\[Q\./\[PG./g'
git grep -l '|Q\.' -- '*.hs' | xargs sed -i 's/|Q\./|PG./g'
git grep -l '{Q\.' -- '*.hs' | xargs sed -i 's/{Q\./{PG./g'
git grep -l '!Q\.' -- '*.hs' | xargs sed -i 's/!Q\./!PG./g'
```
(Doing the `grep -l` before the `sed`, instead of `sed` on the entire codebase, reduces the number of `mtime` updates, and so reduces how many times a file gets recompiled while checking intermediate results.)
Finally, I manually removed a broken and unused `Arbitrary` instance in `Hasura.RQL.Network`. (It used an `import Test.QuickCheck.Arbitrary as Q` statement, which was erroneously caught by the first find-replace command.)
After this PR, `Q` is no longer used as an import qualifier. That was not the goal of this PR, but perhaps it's a useful fact for future efforts.
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5933
GitOrigin-RevId: 8c84c59d57789111d40f5d3322c5a885dcfbf40e
2022-09-20 22:54:43 +03:00
|
|
|
instance FromJSON PG.TxIsolation where
|
2022-03-09 10:14:18 +03:00
|
|
|
parseJSON = withText "Q.TxIsolation" $ \t ->
|
|
|
|
onLeft (readIsoLevel $ T.unpack t) fail
|
|
|
|
|
Import `pg-client-hs` as `PG`
Result of executing the following commands:
```shell
# replace "as Q" imports with "as PG" (in retrospect this didn't need a regex)
git grep -lE 'as Q($|[^a-zA-Z])' -- '*.hs' | xargs sed -i -E 's/as Q($|[^a-zA-Z])/as PG\1/'
# replace " Q." with " PG."
git grep -lE ' Q\.' -- '*.hs' | xargs sed -i 's/ Q\./ PG./g'
# replace "(Q." with "(PG."
git grep -lE '\(Q\.' -- '*.hs' | xargs sed -i 's/(Q\./(PG./g'
# ditto, but for [, |, { and !
git grep -lE '\[Q\.' -- '*.hs' | xargs sed -i 's/\[Q\./\[PG./g'
git grep -l '|Q\.' -- '*.hs' | xargs sed -i 's/|Q\./|PG./g'
git grep -l '{Q\.' -- '*.hs' | xargs sed -i 's/{Q\./{PG./g'
git grep -l '!Q\.' -- '*.hs' | xargs sed -i 's/!Q\./!PG./g'
```
(Doing the `grep -l` before the `sed`, instead of `sed` on the entire codebase, reduces the number of `mtime` updates, and so reduces how many times a file gets recompiled while checking intermediate results.)
Finally, I manually removed a broken and unused `Arbitrary` instance in `Hasura.RQL.Network`. (It used an `import Test.QuickCheck.Arbitrary as Q` statement, which was erroneously caught by the first find-replace command.)
After this PR, `Q` is no longer used as an import qualifier. That was not the goal of this PR, but perhaps it's a useful fact for future efforts.
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5933
GitOrigin-RevId: 8c84c59d57789111d40f5d3322c5a885dcfbf40e
2022-09-20 22:54:43 +03:00
|
|
|
instance ToJSON PG.TxIsolation where
|
|
|
|
toJSON PG.ReadCommitted = "read-committed"
|
|
|
|
toJSON PG.RepeatableRead = "repeatable-read"
|
|
|
|
toJSON PG.Serializable = "serializable"
|
2022-03-09 10:14:18 +03:00
|
|
|
|
|
|
|
data PostgresSourceConnInfo = PostgresSourceConnInfo
|
2022-07-29 17:05:03 +03:00
|
|
|
{ _psciDatabaseUrl :: UrlConf,
|
|
|
|
_psciPoolSettings :: Maybe PostgresPoolSettings,
|
|
|
|
_psciUsePreparedStatements :: Bool,
|
Import `pg-client-hs` as `PG`
Result of executing the following commands:
```shell
# replace "as Q" imports with "as PG" (in retrospect this didn't need a regex)
git grep -lE 'as Q($|[^a-zA-Z])' -- '*.hs' | xargs sed -i -E 's/as Q($|[^a-zA-Z])/as PG\1/'
# replace " Q." with " PG."
git grep -lE ' Q\.' -- '*.hs' | xargs sed -i 's/ Q\./ PG./g'
# replace "(Q." with "(PG."
git grep -lE '\(Q\.' -- '*.hs' | xargs sed -i 's/(Q\./(PG./g'
# ditto, but for [, |, { and !
git grep -lE '\[Q\.' -- '*.hs' | xargs sed -i 's/\[Q\./\[PG./g'
git grep -l '|Q\.' -- '*.hs' | xargs sed -i 's/|Q\./|PG./g'
git grep -l '{Q\.' -- '*.hs' | xargs sed -i 's/{Q\./{PG./g'
git grep -l '!Q\.' -- '*.hs' | xargs sed -i 's/!Q\./!PG./g'
```
(Doing the `grep -l` before the `sed`, instead of `sed` on the entire codebase, reduces the number of `mtime` updates, and so reduces how many times a file gets recompiled while checking intermediate results.)
Finally, I manually removed a broken and unused `Arbitrary` instance in `Hasura.RQL.Network`. (It used an `import Test.QuickCheck.Arbitrary as Q` statement, which was erroneously caught by the first find-replace command.)
After this PR, `Q` is no longer used as an import qualifier. That was not the goal of this PR, but perhaps it's a useful fact for future efforts.
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5933
GitOrigin-RevId: 8c84c59d57789111d40f5d3322c5a885dcfbf40e
2022-09-20 22:54:43 +03:00
|
|
|
_psciIsolationLevel :: PG.TxIsolation,
|
2022-07-29 17:05:03 +03:00
|
|
|
_psciSslConfiguration :: Maybe (PGClientCerts CertVar CertVar)
|
2022-03-09 10:14:18 +03:00
|
|
|
}
|
|
|
|
deriving (Show, Eq, Generic)
|
|
|
|
|
|
|
|
instance Cacheable PostgresSourceConnInfo
|
|
|
|
|
|
|
|
instance Hashable PostgresSourceConnInfo
|
|
|
|
|
|
|
|
instance NFData PostgresSourceConnInfo
|
|
|
|
|
2022-09-13 00:45:24 +03:00
|
|
|
instance HasCodec PostgresSourceConnInfo where
|
|
|
|
codec =
|
|
|
|
CommentCodec "https://hasura.io/docs/latest/graphql/core/api-reference/syntax-defs.html#pgsourceconnectioninfo" $
|
|
|
|
AC.object "PostgresSourceConnInfo" $
|
|
|
|
PostgresSourceConnInfo
|
2022-10-12 19:28:51 +03:00
|
|
|
<$> requiredField "database_url" databaseUrlDoc .== _psciDatabaseUrl
|
2022-09-13 00:45:24 +03:00
|
|
|
<*> optionalFieldOrNull "pool_settings" poolSettingsDoc .== _psciPoolSettings
|
2022-10-13 20:56:03 +03:00
|
|
|
<*> optionalFieldWithDefault "use_prepared_statements" False usePreparedStatementsDoc .== _psciUsePreparedStatements
|
|
|
|
<*> optionalFieldWithDefault "isolation_level" PG.ReadCommitted isolationLevelDoc .== _psciIsolationLevel
|
2022-09-13 00:45:24 +03:00
|
|
|
<*> optionalFieldOrNull "ssl_configuration" sslConfigurationDoc .== _psciSslConfiguration
|
|
|
|
where
|
|
|
|
databaseUrlDoc = "The database connection URL as a string, as an environment variable, or as connection parameters."
|
|
|
|
poolSettingsDoc = "Connection pool settings"
|
|
|
|
usePreparedStatementsDoc =
|
|
|
|
T.unwords
|
|
|
|
[ "If set to true the server prepares statement before executing on the",
|
|
|
|
"source database (default: false). For more details, refer to the",
|
|
|
|
"Postgres docs"
|
|
|
|
]
|
|
|
|
isolationLevelDoc =
|
|
|
|
T.unwords
|
|
|
|
[ "The transaction isolation level in which the queries made to the",
|
|
|
|
"source will be run with (default: read-committed)."
|
|
|
|
]
|
|
|
|
sslConfigurationDoc = "The client SSL certificate settings for the database (Only available in Cloud)."
|
|
|
|
(.==) = (AC..=)
|
|
|
|
|
2022-03-09 10:14:18 +03:00
|
|
|
$(deriveToJSON hasuraJSON {omitNothingFields = True} ''PostgresSourceConnInfo)
|
|
|
|
$(makeLenses ''PostgresSourceConnInfo)
|
|
|
|
|
|
|
|
instance FromJSON PostgresSourceConnInfo where
|
|
|
|
parseJSON = withObject "PostgresSourceConnInfo" $ \o ->
|
|
|
|
PostgresSourceConnInfo
|
|
|
|
<$> o .: "database_url"
|
|
|
|
<*> o .:? "pool_settings"
|
|
|
|
<*> o .:? "use_prepared_statements" .!= False -- By default, preparing statements is OFF for postgres source
|
Import `pg-client-hs` as `PG`
Result of executing the following commands:
```shell
# replace "as Q" imports with "as PG" (in retrospect this didn't need a regex)
git grep -lE 'as Q($|[^a-zA-Z])' -- '*.hs' | xargs sed -i -E 's/as Q($|[^a-zA-Z])/as PG\1/'
# replace " Q." with " PG."
git grep -lE ' Q\.' -- '*.hs' | xargs sed -i 's/ Q\./ PG./g'
# replace "(Q." with "(PG."
git grep -lE '\(Q\.' -- '*.hs' | xargs sed -i 's/(Q\./(PG./g'
# ditto, but for [, |, { and !
git grep -lE '\[Q\.' -- '*.hs' | xargs sed -i 's/\[Q\./\[PG./g'
git grep -l '|Q\.' -- '*.hs' | xargs sed -i 's/|Q\./|PG./g'
git grep -l '{Q\.' -- '*.hs' | xargs sed -i 's/{Q\./{PG./g'
git grep -l '!Q\.' -- '*.hs' | xargs sed -i 's/!Q\./!PG./g'
```
(Doing the `grep -l` before the `sed`, instead of `sed` on the entire codebase, reduces the number of `mtime` updates, and so reduces how many times a file gets recompiled while checking intermediate results.)
Finally, I manually removed a broken and unused `Arbitrary` instance in `Hasura.RQL.Network`. (It used an `import Test.QuickCheck.Arbitrary as Q` statement, which was erroneously caught by the first find-replace command.)
After this PR, `Q` is no longer used as an import qualifier. That was not the goal of this PR, but perhaps it's a useful fact for future efforts.
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5933
GitOrigin-RevId: 8c84c59d57789111d40f5d3322c5a885dcfbf40e
2022-09-20 22:54:43 +03:00
|
|
|
<*> o .:? "isolation_level" .!= PG.ReadCommitted
|
2022-03-09 10:14:18 +03:00
|
|
|
<*> o .:? "ssl_configuration"
|
|
|
|
|
2022-08-10 12:40:57 +03:00
|
|
|
defaultPostgresExtensionsSchema :: ExtensionsSchema
|
|
|
|
defaultPostgresExtensionsSchema = ExtensionsSchema "public"
|
|
|
|
|
2022-03-09 10:14:18 +03:00
|
|
|
data PostgresConnConfiguration = PostgresConnConfiguration
|
2022-07-29 17:05:03 +03:00
|
|
|
{ _pccConnectionInfo :: PostgresSourceConnInfo,
|
2022-08-10 12:40:57 +03:00
|
|
|
_pccReadReplicas :: Maybe (NonEmpty PostgresSourceConnInfo),
|
|
|
|
_pccExtensionsSchema :: ExtensionsSchema
|
2022-03-09 10:14:18 +03:00
|
|
|
}
|
|
|
|
deriving (Show, Eq, Generic)
|
|
|
|
|
|
|
|
instance Cacheable PostgresConnConfiguration
|
|
|
|
|
|
|
|
instance Hashable PostgresConnConfiguration
|
|
|
|
|
|
|
|
instance NFData PostgresConnConfiguration
|
|
|
|
|
2022-08-10 12:40:57 +03:00
|
|
|
instance FromJSON PostgresConnConfiguration where
|
|
|
|
parseJSON = withObject "PostgresConnConfiguration" $ \o ->
|
|
|
|
PostgresConnConfiguration
|
|
|
|
<$> o .: "connection_info"
|
|
|
|
<*> o .:? "read_replicas"
|
|
|
|
<*> o .:? "extensions_schema" .!= defaultPostgresExtensionsSchema
|
|
|
|
|
|
|
|
instance ToJSON PostgresConnConfiguration where
|
|
|
|
toJSON PostgresConnConfiguration {..} =
|
|
|
|
object $
|
|
|
|
["connection_info" .= _pccConnectionInfo]
|
|
|
|
<> maybe mempty (\readReplicas -> ["read_replicas" .= readReplicas]) _pccReadReplicas
|
|
|
|
<> bool mempty (["extensions_schema" .= _pccExtensionsSchema]) (_pccExtensionsSchema /= defaultPostgresExtensionsSchema)
|
|
|
|
|
server: polymorphic codec for metadata sources
This PR expands the OpenAPI specification generated for metadata to include separate definitions for `SourceMetadata` for each native database type, and for DataConnector.
For the most part the changes add `HasCodec` implementations, and don't modify existing code otherwise.
The generated OpenAPI spec can be used to generate TypeScript definitions that distinguish different source metadata types based on the value of the `kind` properly. There is a problem: because the specified `kind` value for a data connector source is any string, when TypeScript gets a source with a `kind` value of, say, `"postgres"`, it cannot unambiguously determine whether the source is postgres, or a data connector. For example,
```ts
function consumeSourceMetadata(source: SourceMetadata) {
if (source.kind === "postgres" || source.kind === "pg") {
// At this point TypeScript infers that `source` is either an instance
// of `PostgresSourceMetadata`, or `DataconnectorSourceMetadata`. It
// can't narrow further.
source
}
if (source.kind === "something else") {
// TypeScript infers that this `source` must be an instance of
// `DataconnectorSourceMetadata` because `source.kind` does not match
// any of the other options.
source
}
}
```
The simplest way I can think of to fix this would be to add a boolean property to the `SourceMetadata` type along the lines of `isNative` or `isDataConnector`. This could be a field that only exists in serialized data, like the metadata version field. The combination of one of the native database names for `kind`, and a true value for `isNative` would be enough for TypeScript to unambiguously distinguish the source kinds.
But note that in the current state TypeScript is able to reference the short `"pg"` name correctly!
~~Tests are not passing yet due to some discrepancies in DTO serialization vs existing Metadata serialization. I'm working on that.~~
The placeholders that I used for table and function metadata are not compatible with the ordered JSON serialization in use. I think the best solution is to write compatible codecs for those types in another PR. For now I have disabled some DTO tests for this PR.
Here are the generated [OpenAPI spec](https://github.com/hasura/graphql-engine-mono/files/9397333/openapi.tar.gz) based on these changes, and the generated [TypeScript client code](https://github.com/hasura/graphql-engine-mono/files/9397339/client-typescript.tar.gz) based on that spec.
Ticket: [MM-66](https://hasurahq.atlassian.net/browse/MM-66)
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5582
GitOrigin-RevId: e1446191c6c832879db04f129daa397a3be03f62
2022-08-25 21:34:44 +03:00
|
|
|
instance HasCodec PostgresConnConfiguration where
|
2022-09-13 00:45:24 +03:00
|
|
|
codec =
|
|
|
|
CommentCodec "https://hasura.io/docs/latest/graphql/core/api-reference/syntax-defs.html#pgconfiguration" $
|
|
|
|
AC.object "PostgresConnConfiguration" $
|
|
|
|
PostgresConnConfiguration
|
|
|
|
<$> requiredField "connection_info" connectionInfoDoc .== _pccConnectionInfo
|
|
|
|
<*> optionalFieldOrNull "read_replicas" readReplicasDoc .== _pccReadReplicas
|
|
|
|
<*> optionalFieldWithOmittedDefault "extensions_schema" defaultPostgresExtensionsSchema extensionsSchemaDoc .== _pccExtensionsSchema
|
|
|
|
where
|
|
|
|
connectionInfoDoc = "Connection parameters for the source"
|
|
|
|
readReplicasDoc = "Optional list of read replica configuration (supported only in cloud/enterprise versions)"
|
|
|
|
extensionsSchemaDoc = "Name of the schema where the graphql-engine will install database extensions (default: public)"
|
|
|
|
(.==) = (AC..=)
|
server: polymorphic codec for metadata sources
This PR expands the OpenAPI specification generated for metadata to include separate definitions for `SourceMetadata` for each native database type, and for DataConnector.
For the most part the changes add `HasCodec` implementations, and don't modify existing code otherwise.
The generated OpenAPI spec can be used to generate TypeScript definitions that distinguish different source metadata types based on the value of the `kind` properly. There is a problem: because the specified `kind` value for a data connector source is any string, when TypeScript gets a source with a `kind` value of, say, `"postgres"`, it cannot unambiguously determine whether the source is postgres, or a data connector. For example,
```ts
function consumeSourceMetadata(source: SourceMetadata) {
if (source.kind === "postgres" || source.kind === "pg") {
// At this point TypeScript infers that `source` is either an instance
// of `PostgresSourceMetadata`, or `DataconnectorSourceMetadata`. It
// can't narrow further.
source
}
if (source.kind === "something else") {
// TypeScript infers that this `source` must be an instance of
// `DataconnectorSourceMetadata` because `source.kind` does not match
// any of the other options.
source
}
}
```
The simplest way I can think of to fix this would be to add a boolean property to the `SourceMetadata` type along the lines of `isNative` or `isDataConnector`. This could be a field that only exists in serialized data, like the metadata version field. The combination of one of the native database names for `kind`, and a true value for `isNative` would be enough for TypeScript to unambiguously distinguish the source kinds.
But note that in the current state TypeScript is able to reference the short `"pg"` name correctly!
~~Tests are not passing yet due to some discrepancies in DTO serialization vs existing Metadata serialization. I'm working on that.~~
The placeholders that I used for table and function metadata are not compatible with the ordered JSON serialization in use. I think the best solution is to write compatible codecs for those types in another PR. For now I have disabled some DTO tests for this PR.
Here are the generated [OpenAPI spec](https://github.com/hasura/graphql-engine-mono/files/9397333/openapi.tar.gz) based on these changes, and the generated [TypeScript client code](https://github.com/hasura/graphql-engine-mono/files/9397339/client-typescript.tar.gz) based on that spec.
Ticket: [MM-66](https://hasurahq.atlassian.net/browse/MM-66)
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5582
GitOrigin-RevId: e1446191c6c832879db04f129daa397a3be03f62
2022-08-25 21:34:44 +03:00
|
|
|
|
2022-03-09 10:14:18 +03:00
|
|
|
$(makeLenses ''PostgresConnConfiguration)
|