server: use_prepared_statements option in add_pg_source metadata API (#893)

* add `use_prepared_statements` option to add_pg_source API

* update CHANGELOG.md

* change default value for 'use_prepared_statements' to False

* update CHANGELOG.md

GitOrigin-RevId: 6f5b90991f4a8c03a51e5829d2650771bb0e29c1
This commit is contained in:
Rakesh Emmadi 2021-03-25 18:22:58 +05:30 committed by hasura-bot
parent 98ab400f3b
commit d0048897cf
9 changed files with 36 additions and 26 deletions

View File

@ -3,6 +3,7 @@
## Next release
(Add entries here in the order of: server, console, cli, docs, others)
- server: `use_prepared_statements` option (default: False) in `add_pg_source` metadata API
- server: add a comment field for actions (#231)
- console: add a comment field for actions (#231)

View File

@ -135,6 +135,7 @@ runApp env (HGEOptionsG rci metadataDbUrl hgeCmd) = do
let defaultSourceConfig = maybeDefaultPgConnInfo <&> \(dbUrlConf, _) ->
let pgSourceConnInfo = PostgresSourceConnInfo dbUrlConf
(Just setPostgresPoolSettings{_ppsRetries = maybeRetries <|> Just 1})
False
in PostgresConnConfiguration pgSourceConnInfo Nothing
res <- runTxWithMinimalPool _gcMetadataDbConnInfo $ downgradeCatalog defaultSourceConfig opts initTime
either (printErrJExit DowngradeProcessError) (liftIO . print) res

View File

@ -278,7 +278,7 @@ initialiseServeCtx env GlobalCtx{..} so@ServeOptions{..} = do
, _ppsIdleTimeout = Just $ Q.cpIdleTime soConnParams
, _ppsRetries = snd _gcDefaultPostgresConnInfo <|> Just 1
}
sourceConnInfo = PostgresSourceConnInfo dbUrlConf (Just connSettings)
sourceConnInfo = PostgresSourceConnInfo dbUrlConf (Just connSettings) $ Q.cpAllowPrepare soConnParams
in PostgresConnConfiguration sourceConnInfo Nothing
sqlGenCtx = SQLGenCtx soStringifyNum

View File

@ -349,8 +349,9 @@ getDefaultPGPoolSettingIfNotExists connSettings defaultPgPoolSettings =
data PostgresSourceConnInfo
= PostgresSourceConnInfo
{ _psciDatabaseUrl :: !UrlConf
, _psciPoolSettings :: !(Maybe PostgresPoolSettings)
{ _psciDatabaseUrl :: !UrlConf
, _psciPoolSettings :: !(Maybe PostgresPoolSettings)
, _psciUsePreparedStatements :: !Bool
} deriving (Show, Eq, Generic)
instance Cacheable PostgresSourceConnInfo
instance Hashable PostgresSourceConnInfo
@ -362,6 +363,7 @@ instance FromJSON PostgresSourceConnInfo where
PostgresSourceConnInfo
<$> o .: "database_url"
<*> o .:? "pool_settings"
<*> o .:? "use_prepared_statements" .!= False -- By default preparing statements is OFF for postgres source
instance Arbitrary PostgresSourceConnInfo where
arbitrary = genericArbitrary

View File

@ -81,7 +81,7 @@ pruneDanglingDependents
pruneDanglingDependents cache = fmap (M.filter (not . null)) . traverse do
partitionEithers . map \(metadataObject, dependency) -> case resolveDependency dependency of
Right () -> Right (metadataObject, dependency)
Left errorMessage -> Left (InconsistentObject errorMessage metadataObject)
Left errorMessage -> Left (InconsistentObject errorMessage Nothing metadataObject)
where
resolveDependency :: SchemaDependency -> Either Text ()
resolveDependency (SchemaDependency objectId _) = case objectId of

View File

@ -122,7 +122,7 @@ addNonColumnFields = proc ( source
This columnInfo -> returnA -< FIColumn columnInfo
That (fieldInfo, _) -> returnA -< fieldInfo
These columnInfo (_, fieldMetadata) -> do
recordInconsistency -< (fieldMetadata, "field definition conflicts with postgres column")
recordInconsistency -< ((Nothing, fieldMetadata), "field definition conflicts with postgres column")
returnA -< FIColumn columnInfo
mkRelationshipMetadataObject

View File

@ -23,13 +23,14 @@ import Hasura.RQL.Types
mkPgSourceResolver :: Q.PGLogger -> SourceResolver
mkPgSourceResolver pgLogger _ config = runExceptT do
env <- lift Env.getEnvironment
let PostgresSourceConnInfo urlConf connSettings = _pccConnectionInfo config
let PostgresSourceConnInfo urlConf connSettings allowPrepare = _pccConnectionInfo config
-- If the user does not provide values for the pool settings, then use the default values
let (maxConns, idleTimeout, retries) = getDefaultPGPoolSettingIfNotExists connSettings defaultPostgresPoolSettings
urlText <- resolveUrlConf env urlConf
let connInfo = Q.ConnInfo retries $ Q.CDDatabaseURI $ txtToBs urlText
connParams = Q.defaultConnParams{ Q.cpIdleTime = idleTimeout
, Q.cpConns = maxConns
, Q.cpAllowPrepare = allowPrepare
}
pgPool <- liftIO $ Q.initPGPool connInfo connParams pgLogger
let pgExecCtx = mkPGExecCtx Q.ReadCommitted pgPool

View File

@ -154,7 +154,7 @@ data MetadataObject
$(makeLenses ''MetadataObject)
data InconsistentMetadata
= InconsistentObject !Text !MetadataObject
= InconsistentObject !Text !(Maybe Value) !MetadataObject
| ConflictingObjects !Text ![MetadataObject]
| DuplicateObjects !MetadataObjId ![Value]
| DuplicateRestVariables !Text !MetadataObject
@ -165,20 +165,20 @@ $(makePrisms ''InconsistentMetadata)
getInconsistentRemoteSchemas :: [InconsistentMetadata] -> [RemoteSchemaName]
getInconsistentRemoteSchemas =
toListOf (traverse._InconsistentObject._2.moId._MORemoteSchema)
toListOf (traverse._InconsistentObject._3.moId._MORemoteSchema)
imObjectIds :: InconsistentMetadata -> [MetadataObjId]
imObjectIds = \case
InconsistentObject _ metadata -> [_moId metadata]
ConflictingObjects _ metadatas -> map _moId metadatas
DuplicateObjects objectId _ -> [objectId]
DuplicateRestVariables _ md -> [_moId md]
InvalidRestSegments _ md -> [_moId md]
AmbiguousRestEndpoints _ mds -> take 1 $ map _moId mds -- TODO: Take 1 is a workaround to ensure that conflicts are not reported multiple times per endpoint.
InconsistentObject _ _ metadata -> [_moId metadata]
ConflictingObjects _ metadatas -> map _moId metadatas
DuplicateObjects objectId _ -> [objectId]
DuplicateRestVariables _ md -> [_moId md]
InvalidRestSegments _ md -> [_moId md]
AmbiguousRestEndpoints _ mds -> take 1 $ map _moId mds -- TODO: Take 1 is a workaround to ensure that conflicts are not reported multiple times per endpoint.
imReason :: InconsistentMetadata -> Text
imReason = \case
InconsistentObject reason _ -> reason
InconsistentObject reason _ _ -> reason
ConflictingObjects reason _ -> reason
DuplicateObjects objectId _ -> "multiple definitions for " <> moiName objectId
DuplicateRestVariables reason _ -> reason
@ -197,17 +197,18 @@ instance ToJSON InconsistentMetadata where
toJSON inconsistentMetadata = object (("reason" .= imReason inconsistentMetadata) : extraFields)
where
extraFields = case inconsistentMetadata of
InconsistentObject _ metadata -> metadataObjectFields metadata
InconsistentObject _ internal metadata -> metadataObjectFields internal metadata
ConflictingObjects _ metadatas ->
[ "objects" .= map (object . metadataObjectFields) metadatas ]
[ "objects" .= map (object . metadataObjectFields Nothing) metadatas ]
DuplicateObjects objectId definitions ->
[ "type" .= String (moiTypeName objectId)
, "definitions" .= definitions ]
DuplicateRestVariables _ md -> metadataObjectFields md
InvalidRestSegments _ md -> metadataObjectFields md
DuplicateRestVariables _ md -> metadataObjectFields Nothing md
InvalidRestSegments _ md -> metadataObjectFields Nothing md
AmbiguousRestEndpoints _ mds -> [ "conflicts" .= map _moDefinition mds ]
metadataObjectFields (MetadataObject objectId definition) =
metadataObjectFields (maybeInternal :: Maybe Value) (MetadataObject objectId definition) =
[ "type" .= String (moiTypeName objectId)
, "definition" .= definition ]
<> maybe [] (\internal -> ["internal" .= internal]) maybeInternal

View File

@ -35,7 +35,7 @@ import Control.Lens
import Control.Monad.Morph
import Control.Monad.Trans.Control (MonadBaseControl)
import Control.Monad.Unique
import Data.Aeson (toJSON)
import Data.Aeson (Value, toJSON)
import Data.Aeson.TH
import Data.List (nub)
import Data.Text.Extended
@ -83,13 +83,17 @@ partitionCollectedInfo =
in (inconsistencies, dependency:dependencies)
recordInconsistency
:: (ArrowWriter (Seq w) arr, AsInconsistentMetadata w) => (MetadataObject, Text) `arr` ()
recordInconsistency = first (arr (:[])) >>> recordInconsistencies
:: (ArrowWriter (Seq w) arr, AsInconsistentMetadata w) => ((Maybe Value, MetadataObject), Text) `arr` ()
recordInconsistency = first (arr (:[])) >>> recordInconsistencies'
recordInconsistencies
:: (ArrowWriter (Seq w) arr, AsInconsistentMetadata w) => ([MetadataObject], Text) `arr` ()
recordInconsistencies = proc (metadataObjects, reason) ->
tellA -< Seq.fromList $ map (review _InconsistentMetadata . InconsistentObject reason) metadataObjects
recordInconsistencies = first (arr (map (Nothing,))) >>> recordInconsistencies'
recordInconsistencies'
:: (ArrowWriter (Seq w) arr, AsInconsistentMetadata w) => ([(Maybe Value, MetadataObject)], Text) `arr` ()
recordInconsistencies' = proc (metadataObjects, reason) ->
tellA -< Seq.fromList $ map (review _InconsistentMetadata . uncurry (InconsistentObject reason)) metadataObjects
recordDependencies
:: (ArrowWriter (Seq CollectedInfo) arr)
@ -105,7 +109,7 @@ withRecordInconsistency f = proc (e, (metadataObject, s)) -> do
result <- runErrorA f -< (e, s)
case result of
Left err -> do
recordInconsistency -< (metadataObject, qeError err)
recordInconsistency -< ((qeInternal err, metadataObject), qeError err)
returnA -< Nothing
Right v -> returnA -< Just v
{-# INLINABLE withRecordInconsistency #-}