graphql-engine/server/src-lib/Hasura/Backends/Postgres/Connection/VersionCheck.hs
2023-02-14 12:15:58 +00:00

106 lines
3.4 KiB
Haskell

-- | Check version compatability against postgres-like flavors.
module Hasura.Backends.Postgres.Connection.VersionCheck
( runCockroachVersionCheck,
CockroachDbVersion (..),
parseCrdbVersion,
crdbVersionIsSupported,
)
where
import Data.Aeson (object, (.=))
import Data.Aeson.Types (Pair)
import Data.Environment qualified as Env
import Database.PG.Query qualified as PG
import Hasura.Backends.Postgres.Connection qualified as PG
import Hasura.Backends.Postgres.Connection.Connect (withPostgresDB)
import Hasura.Base.Error
import Hasura.Prelude
import Text.Parsec qualified as P
import Text.Parsec.Text qualified as P
-- * Cockroach
-- | Cockroach version
data CockroachDbVersion = CockroachDbVersion
{ crdbMajor :: Word,
crdbMinor :: Word,
crdbPatch :: Word,
-- | includes additional information such as "-beta.4"
crdbRest :: String
}
deriving (Eq, Show)
-- | Check cockroachdb version compatability.
runCockroachVersionCheck :: Env.Environment -> PG.PostgresConnConfiguration -> IO (Either QErr ())
runCockroachVersionCheck env connConf = do
result <-
withPostgresDB env connConf $
PG.rawQE PG.dmlTxErrorHandler (PG.fromText "select version();") [] False
pure case result of
-- running the query failed
Left err ->
Left err
-- running the query succeeded
Right (PG.SingleRow (Identity versionString)) ->
case parseCrdbVersion versionString of
-- parsing the query output failed
Left err ->
Left $
crdbVersionCheckErr500
[ "version-parse-error" .= show err,
"version-string" .= versionString
]
-- parsing the query output succeeded
Right crdbVersion ->
if crdbVersionIsSupported crdbVersion
then -- the crdb version is supported
Right ()
else -- the crdb version is not supported
Left $
crdbVersionCheckErr500
[ "version-string" .= versionString
]
crdbVersionCheckErr500 :: [Pair] -> QErr
crdbVersionCheckErr500 extra =
( err500
ValidationFailed
"Unsupported CockroachDB version. Supported versions: v22.2 onwards."
)
{ qeInternal = Just $ ExtraInternal (object extra)
}
-- | Check version is >= 22.2.0
-- https://hasura.io/docs/latest/databases/postgres/cockroachdb/index
crdbVersionIsSupported :: CockroachDbVersion -> Bool
crdbVersionIsSupported CockroachDbVersion {crdbMajor, crdbMinor, crdbPatch} =
(crdbMajor > 22)
|| (crdbMajor == 22 && crdbMinor > 2)
|| (crdbMajor == 22 && crdbMinor == 2 && crdbPatch >= 0)
-- | Parse a cockroachDB version string
parseCrdbVersion :: Text -> Either P.ParseError CockroachDbVersion
parseCrdbVersion versionString = P.parse crdbVersionParser "select version();" versionString
-- | Cockroach DB version parser.
-- Example version string:
-- > "CockroachDB CCL v22.2.0-beta.4 (x86_64-pc-linux-gnu, built 2022/10/17 14:34:07, go1.19.1)"
crdbVersionParser :: P.Parser CockroachDbVersion
crdbVersionParser = do
_ <- P.string "CockroachDB"
_ <- P.space
_distribution <- word
_ <- P.space
_ <- P.char 'v'
crdbMajor <- read <$> P.many P.digit
_ <- P.char '.'
crdbMinor <- read <$> P.many P.digit
_ <- P.char '.'
crdbPatch <- read <$> P.many P.digit
crdbRest <- word
pure CockroachDbVersion {..}
word :: P.ParsecT Text u Identity String
word = P.many (P.alphaNum <|> P.oneOf "-~!@#$%^&*=_.,")