2022-03-16 03:39:21 +03:00
|
|
|
{-# LANGUAGE TemplateHaskell #-}
|
|
|
|
|
2021-01-07 12:04:22 +03:00
|
|
|
-- | The RQL query ('/v2/query')
|
2021-11-04 19:08:33 +03:00
|
|
|
module Hasura.Server.API.V2Query
|
|
|
|
( RQLQuery,
|
|
|
|
queryModifiesSchema,
|
|
|
|
runQuery,
|
|
|
|
)
|
|
|
|
where
|
2021-01-07 12:04:22 +03:00
|
|
|
|
2021-09-24 01:56:37 +03:00
|
|
|
import Control.Monad.Trans.Control (MonadBaseControl)
|
|
|
|
import Data.Aeson
|
|
|
|
import Data.Aeson.Casing
|
|
|
|
import Data.Aeson.TH
|
|
|
|
import Data.Environment qualified as Env
|
2022-08-19 00:56:47 +03:00
|
|
|
import Data.Text qualified as T
|
|
|
|
import GHC.Generics.Extended (constrName)
|
2021-09-24 01:56:37 +03:00
|
|
|
import Hasura.Backends.BigQuery.DDL.RunSQL qualified as BigQuery
|
|
|
|
import Hasura.Backends.MSSQL.DDL.RunSQL qualified as MSSQL
|
|
|
|
import Hasura.Backends.MySQL.SQL qualified as MySQL
|
|
|
|
import Hasura.Backends.Postgres.DDL.RunSQL qualified as Postgres
|
|
|
|
import Hasura.Base.Error
|
|
|
|
import Hasura.EncJSON
|
|
|
|
import Hasura.GraphQL.Execute.Backend
|
|
|
|
import Hasura.Metadata.Class
|
|
|
|
import Hasura.Prelude
|
|
|
|
import Hasura.RQL.DDL.Schema
|
|
|
|
import Hasura.RQL.DML.Count
|
|
|
|
import Hasura.RQL.DML.Delete
|
|
|
|
import Hasura.RQL.DML.Insert
|
|
|
|
import Hasura.RQL.DML.Select
|
|
|
|
import Hasura.RQL.DML.Types
|
|
|
|
import Hasura.RQL.DML.Update
|
2022-04-27 16:57:28 +03:00
|
|
|
import Hasura.RQL.Types.Metadata
|
2021-09-24 01:56:37 +03:00
|
|
|
import Hasura.RQL.Types.Run
|
2022-04-27 16:57:28 +03:00
|
|
|
import Hasura.RQL.Types.SchemaCache.Build
|
|
|
|
import Hasura.RQL.Types.Source
|
|
|
|
import Hasura.SQL.Backend
|
2021-09-24 01:56:37 +03:00
|
|
|
import Hasura.Server.Types
|
|
|
|
import Hasura.Session
|
|
|
|
import Hasura.Tracing qualified as Tracing
|
|
|
|
import Network.HTTP.Client qualified as HTTP
|
2021-01-07 12:04:22 +03:00
|
|
|
|
|
|
|
data RQLQuery
|
|
|
|
= RQInsert !InsertQuery
|
|
|
|
| RQSelect !SelectQuery
|
|
|
|
| RQUpdate !UpdateQuery
|
|
|
|
| RQDelete !DeleteQuery
|
2021-09-24 01:56:37 +03:00
|
|
|
| RQCount !CountQuery
|
2021-05-27 18:06:13 +03:00
|
|
|
| RQRunSql !Postgres.RunSQL
|
2021-03-11 21:17:41 +03:00
|
|
|
| RQMssqlRunSql !MSSQL.MSSQLRunSQL
|
2021-05-27 18:06:13 +03:00
|
|
|
| RQCitusRunSql !Postgres.RunSQL
|
2022-08-25 16:30:34 +03:00
|
|
|
| RQCockroachRunSql !Postgres.RunSQL
|
2021-07-21 13:22:03 +03:00
|
|
|
| RQMysqlRunSql !MySQL.RunSQL
|
2021-04-12 13:18:29 +03:00
|
|
|
| RQBigqueryRunSql !BigQuery.BigQueryRunSQL
|
|
|
|
| RQBigqueryDatabaseInspection !BigQuery.BigQueryRunSQL
|
2021-01-07 12:04:22 +03:00
|
|
|
| RQBulk ![RQLQuery]
|
2022-08-19 00:56:47 +03:00
|
|
|
deriving (Generic)
|
2021-01-07 12:04:22 +03:00
|
|
|
|
2021-09-24 01:56:37 +03:00
|
|
|
$( deriveFromJSON
|
|
|
|
defaultOptions
|
|
|
|
{ constructorTagModifier = snakeCase . drop 2,
|
|
|
|
sumEncoding = TaggedObject "type" "args"
|
|
|
|
}
|
|
|
|
''RQLQuery
|
|
|
|
)
|
2021-07-07 04:43:42 +03:00
|
|
|
|
2021-09-24 01:56:37 +03:00
|
|
|
runQuery ::
|
2021-10-13 19:38:56 +03:00
|
|
|
( MonadIO m,
|
2021-09-24 01:56:37 +03:00
|
|
|
MonadBaseControl IO m,
|
|
|
|
Tracing.MonadTrace m,
|
|
|
|
MonadMetadataStorage m,
|
|
|
|
MonadResolveSource m,
|
|
|
|
MonadQueryTags m
|
|
|
|
) =>
|
|
|
|
Env.Environment ->
|
|
|
|
InstanceId ->
|
|
|
|
UserInfo ->
|
|
|
|
RebuildableSchemaCache ->
|
|
|
|
HTTP.Manager ->
|
|
|
|
ServerConfigCtx ->
|
|
|
|
RQLQuery ->
|
|
|
|
m (EncJSON, RebuildableSchemaCache)
|
2021-02-18 19:46:14 +03:00
|
|
|
runQuery env instanceId userInfo schemaCache httpManager serverConfigCtx rqlQuery = do
|
2021-12-08 09:26:46 +03:00
|
|
|
when ((_sccReadOnlyMode serverConfigCtx == ReadOnlyModeEnabled) && queryModifiesUserDB rqlQuery) $
|
|
|
|
throw400 NotSupported "Cannot run write queries when read-only mode is enabled"
|
|
|
|
|
2022-08-19 00:56:47 +03:00
|
|
|
(metadata, currentResourceVersion) <- Tracing.trace "fetchMetadata" fetchMetadata
|
2021-09-24 01:56:37 +03:00
|
|
|
result <-
|
2021-09-25 06:59:35 +03:00
|
|
|
runQueryM env rqlQuery & \x -> do
|
|
|
|
((js, meta), rsc, ci) <-
|
2021-09-24 01:56:37 +03:00
|
|
|
x & runMetadataT metadata
|
|
|
|
& runCacheRWT schemaCache
|
|
|
|
& peelRun runCtx
|
|
|
|
& runExceptT
|
|
|
|
& liftEitherM
|
2021-09-25 06:59:35 +03:00
|
|
|
pure (js, rsc, ci, meta)
|
2021-02-19 05:39:30 +03:00
|
|
|
withReload currentResourceVersion result
|
2021-01-07 12:04:22 +03:00
|
|
|
where
|
2021-02-18 19:46:14 +03:00
|
|
|
runCtx = RunCtx userInfo httpManager serverConfigCtx
|
2021-01-07 12:04:22 +03:00
|
|
|
|
2021-02-19 05:39:30 +03:00
|
|
|
withReload currentResourceVersion (result, updatedCache, invalidations, updatedMetadata) = do
|
2021-01-07 12:04:22 +03:00
|
|
|
when (queryModifiesSchema rqlQuery) $ do
|
2021-05-21 05:46:58 +03:00
|
|
|
case _sccMaintenanceMode serverConfigCtx of
|
2021-04-06 06:25:02 +03:00
|
|
|
MaintenanceModeDisabled -> do
|
2021-02-18 19:46:14 +03:00
|
|
|
-- set modified metadata in storage
|
2022-08-19 00:56:47 +03:00
|
|
|
newResourceVersion <-
|
|
|
|
Tracing.trace "setMetadata" $
|
|
|
|
setMetadata currentResourceVersion updatedMetadata
|
2021-04-06 06:25:02 +03:00
|
|
|
-- notify schema cache sync
|
2022-08-19 00:56:47 +03:00
|
|
|
Tracing.trace "notifySchemaCacheSync" $
|
|
|
|
notifySchemaCacheSync newResourceVersion instanceId invalidations
|
2022-04-28 23:55:13 +03:00
|
|
|
MaintenanceModeEnabled () ->
|
2021-02-18 19:46:14 +03:00
|
|
|
throw500 "metadata cannot be modified in maintenance mode"
|
2021-01-07 12:04:22 +03:00
|
|
|
pure (result, updatedCache)
|
|
|
|
|
|
|
|
queryModifiesSchema :: RQLQuery -> Bool
|
|
|
|
queryModifiesSchema = \case
|
2021-09-24 01:56:37 +03:00
|
|
|
RQInsert _ -> False
|
|
|
|
RQSelect _ -> False
|
|
|
|
RQUpdate _ -> False
|
|
|
|
RQDelete _ -> False
|
|
|
|
RQCount _ -> False
|
|
|
|
RQRunSql q -> Postgres.isSchemaCacheBuildRequiredRunSQL q
|
|
|
|
RQCitusRunSql q -> Postgres.isSchemaCacheBuildRequiredRunSQL q
|
2022-08-25 16:30:34 +03:00
|
|
|
RQCockroachRunSql q -> Postgres.isSchemaCacheBuildRequiredRunSQL q
|
2021-10-22 17:49:15 +03:00
|
|
|
RQMssqlRunSql q -> MSSQL.isSchemaCacheBuildRequiredRunSQL q
|
2021-09-24 01:56:37 +03:00
|
|
|
RQMysqlRunSql _ -> False
|
|
|
|
RQBigqueryRunSql _ -> False
|
2021-06-11 14:38:03 +03:00
|
|
|
RQBigqueryDatabaseInspection _ -> False
|
2021-09-24 01:56:37 +03:00
|
|
|
RQBulk l -> any queryModifiesSchema l
|
2021-01-07 12:04:22 +03:00
|
|
|
|
2021-09-24 01:56:37 +03:00
|
|
|
runQueryM ::
|
2021-10-13 19:38:56 +03:00
|
|
|
( MonadError QErr m,
|
2021-09-24 01:56:37 +03:00
|
|
|
MonadIO m,
|
|
|
|
MonadBaseControl IO m,
|
|
|
|
UserInfoM m,
|
|
|
|
CacheRWM m,
|
|
|
|
HasServerConfigCtx m,
|
|
|
|
Tracing.MonadTrace m,
|
|
|
|
MetadataM m,
|
|
|
|
MonadQueryTags m
|
|
|
|
) =>
|
|
|
|
Env.Environment ->
|
|
|
|
RQLQuery ->
|
|
|
|
m EncJSON
|
2022-08-19 00:56:47 +03:00
|
|
|
runQueryM env rq = Tracing.trace (T.pack $ constrName rq) $ case rq of
|
2021-09-24 01:56:37 +03:00
|
|
|
RQInsert q -> runInsert q
|
|
|
|
RQSelect q -> runSelect q
|
|
|
|
RQUpdate q -> runUpdate q
|
|
|
|
RQDelete q -> runDelete q
|
|
|
|
RQCount q -> runCount q
|
|
|
|
RQRunSql q -> Postgres.runRunSQL @'Vanilla q
|
|
|
|
RQMssqlRunSql q -> MSSQL.runSQL q
|
|
|
|
RQMysqlRunSql q -> MySQL.runSQL q
|
|
|
|
RQCitusRunSql q -> Postgres.runRunSQL @'Citus q
|
2022-08-25 16:30:34 +03:00
|
|
|
RQCockroachRunSql q -> Postgres.runRunSQL @'Cockroach q
|
2021-09-24 01:56:37 +03:00
|
|
|
RQBigqueryRunSql q -> BigQuery.runSQL q
|
2021-04-12 13:18:29 +03:00
|
|
|
RQBigqueryDatabaseInspection q -> BigQuery.runDatabaseInspection q
|
2021-09-24 01:56:37 +03:00
|
|
|
RQBulk l -> encJFromList <$> indexedMapM (runQueryM env) l
|
2021-12-08 09:26:46 +03:00
|
|
|
|
|
|
|
queryModifiesUserDB :: RQLQuery -> Bool
|
|
|
|
queryModifiesUserDB = \case
|
|
|
|
RQInsert _ -> True
|
|
|
|
RQSelect _ -> False
|
|
|
|
RQUpdate _ -> True
|
|
|
|
RQDelete _ -> True
|
|
|
|
RQCount _ -> False
|
|
|
|
RQRunSql _ -> True
|
|
|
|
RQCitusRunSql _ -> True
|
2022-08-25 16:30:34 +03:00
|
|
|
RQCockroachRunSql _ -> True
|
2021-12-08 09:26:46 +03:00
|
|
|
RQMssqlRunSql _ -> True
|
|
|
|
RQMysqlRunSql _ -> True
|
|
|
|
RQBigqueryRunSql _ -> True
|
|
|
|
RQBigqueryDatabaseInspection _ -> False
|
|
|
|
RQBulk q -> any queryModifiesUserDB q
|