2021-04-12 13:18:29 +03:00
|
|
|
-- | Planning T-SQL queries and subscriptions.
|
|
|
|
|
|
|
|
module Hasura.Backends.BigQuery.Plan
|
|
|
|
( planNoPlan
|
|
|
|
, planToForest
|
|
|
|
) where
|
|
|
|
|
2021-05-11 18:18:31 +03:00
|
|
|
import Hasura.Prelude
|
2021-04-12 13:18:29 +03:00
|
|
|
|
2021-05-11 18:18:31 +03:00
|
|
|
import qualified Data.Text.Lazy as LT
|
2021-04-12 13:18:29 +03:00
|
|
|
|
|
|
|
import Control.Monad.Validate
|
2021-05-11 18:18:31 +03:00
|
|
|
import Data.Aeson.Text
|
2021-04-12 13:18:29 +03:00
|
|
|
import Data.Text.Extended
|
2021-05-11 18:18:31 +03:00
|
|
|
import Data.Tree
|
2021-04-12 13:18:29 +03:00
|
|
|
|
2021-05-11 18:18:31 +03:00
|
|
|
import qualified Hasura.Backends.BigQuery.DataLoader.Plan as DataLoader
|
|
|
|
import qualified Hasura.Base.Error as E
|
|
|
|
import qualified Hasura.GraphQL.Parser as GraphQL
|
|
|
|
import qualified Hasura.RQL.Types.Column as RQL
|
2021-04-12 13:18:29 +03:00
|
|
|
|
2021-05-11 18:18:31 +03:00
|
|
|
import Hasura.Backends.BigQuery.FromIr as BigQuery
|
|
|
|
import Hasura.Backends.BigQuery.Types as BigQuery
|
2021-04-12 13:18:29 +03:00
|
|
|
import Hasura.GraphQL.Context
|
|
|
|
import Hasura.SQL.Backend
|
2021-05-11 18:18:31 +03:00
|
|
|
import Hasura.SQL.Types
|
|
|
|
import Hasura.Session
|
|
|
|
|
2021-04-12 13:18:29 +03:00
|
|
|
|
|
|
|
-- --------------------------------------------------------------------------------
|
|
|
|
-- -- Top-level planner
|
|
|
|
|
|
|
|
planToForest ::
|
2021-05-11 18:18:31 +03:00
|
|
|
MonadError E.QErr m
|
2021-04-12 13:18:29 +03:00
|
|
|
=> UserInfo
|
|
|
|
-> QueryDB 'BigQuery (GraphQL.UnpreparedValue 'BigQuery)
|
|
|
|
-> m (Forest DataLoader.PlannedAction)
|
|
|
|
planToForest userInfo qrf = do
|
|
|
|
select <- planNoPlan userInfo qrf
|
|
|
|
let (!_headAndTail, !plannedActionsList) =
|
|
|
|
DataLoader.runPlan
|
|
|
|
(DataLoader.planSelectHeadAndTail Nothing Nothing select)
|
|
|
|
!actionsForest = DataLoader.actionsForest id plannedActionsList
|
|
|
|
pure actionsForest
|
|
|
|
|
|
|
|
planNoPlan ::
|
2021-05-11 18:18:31 +03:00
|
|
|
MonadError E.QErr m
|
2021-04-12 13:18:29 +03:00
|
|
|
=> UserInfo
|
|
|
|
-> QueryDB 'BigQuery (GraphQL.UnpreparedValue 'BigQuery)
|
|
|
|
-> m Select
|
|
|
|
planNoPlan userInfo queryDB = do
|
|
|
|
rootField <- traverseQueryDB (prepareValueNoPlan (_uiSession userInfo)) queryDB
|
|
|
|
select <-
|
|
|
|
runValidate (BigQuery.runFromIr (BigQuery.fromRootField rootField))
|
2021-05-11 18:18:31 +03:00
|
|
|
`onLeft` (E.throw400 E.NotSupported . (tshow :: NonEmpty Error -> Text))
|
2021-04-12 13:18:29 +03:00
|
|
|
pure
|
|
|
|
select
|
|
|
|
{ selectFor =
|
|
|
|
case selectFor select of
|
|
|
|
NoFor -> NoFor
|
|
|
|
JsonFor forJson -> JsonFor forJson {jsonRoot = Root "root"}
|
|
|
|
}
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- Resolving values
|
|
|
|
|
|
|
|
-- | Prepare a value without any query planning; we just execute the
|
|
|
|
-- query with the values embedded.
|
|
|
|
prepareValueNoPlan ::
|
2021-05-11 18:18:31 +03:00
|
|
|
(MonadError E.QErr m)
|
2021-04-12 13:18:29 +03:00
|
|
|
=> SessionVariables
|
|
|
|
-> GraphQL.UnpreparedValue 'BigQuery
|
|
|
|
-> m BigQuery.Expression
|
|
|
|
prepareValueNoPlan sessionVariables =
|
|
|
|
\case
|
|
|
|
GraphQL.UVLiteral x -> pure x
|
|
|
|
GraphQL.UVSession -> pure globalSessionExpression
|
|
|
|
-- To be honest, I'm not sure if it's indeed the JSON_VALUE operator we need here...
|
|
|
|
GraphQL.UVSessionVar typ text ->
|
|
|
|
case typ of
|
|
|
|
CollectableTypeScalar scalarType ->
|
|
|
|
pure
|
|
|
|
(CastExpression
|
|
|
|
(JsonValueExpression
|
|
|
|
globalSessionExpression
|
|
|
|
(FieldPath RootPath (toTxt text)))
|
|
|
|
scalarType)
|
|
|
|
CollectableTypeArray {} ->
|
2021-05-11 18:18:31 +03:00
|
|
|
throwError $ E.internalError "Cannot currently prepare array types in BigQuery."
|
2021-04-12 13:18:29 +03:00
|
|
|
GraphQL.UVParameter _ RQL.ColumnValue {..} -> pure (ValueExpression cvValue)
|
|
|
|
where
|
|
|
|
globalSessionExpression =
|
|
|
|
ValueExpression
|
|
|
|
(StringValue (LT.toStrict (encodeToLazyText sessionVariables)))
|