graphql-engine/server/src-lib/Hasura/Backends/MySQL/SQL.hs
Sibi Prabakaran 0e6e9deac9 mysql: runSql implementation and python tests leveraging it to enhance the metadata test
https://github.com/hasura/graphql-engine-mono/pull/1606

Co-authored-by: Chris Done <11019+chrisdone@users.noreply.github.com>
Co-authored-by: Aniket Deshpande <922486+aniketd@users.noreply.github.com>
Co-authored-by: Abby Sassel <3883855+sassela@users.noreply.github.com>
GitOrigin-RevId: 2ed37c48c5d1e82e23d691f30a6e870303787388
2021-07-21 10:22:54 +00:00

53 lines
1.9 KiB
Haskell

module Hasura.Backends.MySQL.SQL where
import qualified Data.Aeson as J
import Data.Aeson.TH
import Data.ByteString hiding (null, reverse)
import Data.Pool (withResource)
import Data.String (fromString)
import qualified Data.Text as T
import Data.Text.Encoding (decodeUtf8With)
import Data.Text.Encoding.Error (lenientDecode)
import Database.MySQL.Base (Result, fetchFields, fetchRow, query, storeResult)
import Database.MySQL.Base.Types (Field (fieldName))
import Hasura.Backends.MySQL.Types (SourceConfig (..))
import Hasura.Base.Error
import Hasura.EncJSON
import Hasura.Prelude
import Hasura.RQL.DDL.Schema (RunSQLRes (..))
import Hasura.RQL.Types
data RunSQL
= RunSQL
{ _Sql :: !Text
, _Source :: !SourceName
} deriving (Show, Eq)
$(deriveJSON hasuraJSON ''RunSQL)
runSQL :: (MonadIO m, CacheRWM m, MonadError QErr m, MetadataM m) => RunSQL -> m EncJSON
runSQL (RunSQL sql source) = do
pool <- scConnectionPool <$> askSourceConfig @'MySQL source
result :: [[Maybe ByteString]] <- liftIO $ withResource pool $ \conn -> do
query conn (fromString . T.unpack $ sql)
r <- storeResult conn
fieldNames <- fmap (Just . fieldName) <$> fetchFields r -- fieldNames as Maybes for convenience
rows <- fetchAllRows r
pure (fieldNames:rows)
pure . encJFromJValue $
if null result
then RunSQLRes "CommandOK" J.Null
else RunSQLRes "TuplesOk" . J.toJSON . (fmap . fmap . fmap) (decodeUtf8With lenientDecode) $ result
where
fetchAllRows :: Result -> IO [[Maybe ByteString]]
fetchAllRows r = reverse <$> go [] r
where
go acc res =
fetchRow res >>= \case
[] -> pure acc
r' -> go (r':acc) res