hunk.code_window:      , MonadError QErr m
        )
     => [G.VariableDefinition]
     -> VariableValues
     -> m AnnVarVals
   getAnnVarVals varDefsL inpVals = do
     varDefs <- onLeft (mkMapWith G._vdVariable varDefsL) $ \dups ->
       throwVE $ "the following variables are defined more than once: " <>
       showVars dups
  
hunk.labels: keep keep keep keep keep replace keep keep keep keep
hunk.after_edit: getAnnVarVals varDefsL inpVals = withPathK "variableValues" $ do
  
hunk.file_path: server/src-lib/Hasura/GraphQL/Validate.hs
hunk.type: replace
file: module Hasura.GraphQL.Validate
    ( validateGQ
    , showVars
    , RootSelSet(..)
    , getTypedOp
    , QueryParts (..)
    , getQueryParts
    , getAnnVarVals
  
    , VarPGTypes
    , AnnPGVarVals
    , getAnnPGVarVals
    , Field(..)
    , SelSet
    ) where
  
  import           Data.Has
  import           Hasura.Prelude
  
  import qualified Data.HashMap.Strict                    as Map
  import qualified Data.Sequence                          as Seq
  import qualified Language.GraphQL.Draft.Syntax          as G
  
  import           Hasura.GraphQL.Schema
  import           Hasura.GraphQL.Transport.HTTP.Protocol
  import           Hasura.GraphQL.Validate.Context
  import           Hasura.GraphQL.Validate.Field
  import           Hasura.GraphQL.Validate.InputValue
  import           Hasura.GraphQL.Validate.Types
  import           Hasura.RQL.Types
  
  import           Hasura.SQL.Types (PGColType)
  import           Hasura.SQL.Value (PGColValue, parsePGValue)
  
  data QueryParts
    = QueryParts
    { qpOpDef     :: !G.TypedOperationDefinition
    , qpOpRoot    :: !ObjTyInfo
    , qpFragDefsL :: ![G.FragmentDefinition]
    , qpVarValsM  :: !(Maybe VariableValues)
    } deriving (Show, Eq)
  
  getTypedOp
    :: (MonadError QErr m)
    => Maybe OperationName
    -> [G.SelectionSet]
    -> [G.TypedOperationDefinition]
    -> m G.TypedOperationDefinition
  getTypedOp opNameM selSets opDefs =
    case (opNameM, selSets, opDefs) of
      (Just opName, [], _) -> do
        let n = _unOperationName opName
            opDefM = find (\opDef -> G._todName opDef == Just n) opDefs
        onNothing opDefM $ throwVE $
          "no such operation found in the document: " <> showName n
      (Just _, _, _)  ->
        throwVE $ "operationName cannot be used when " <>
        "an anonymous operation exists in the document"
      (Nothing, [selSet], []) ->
        return $ G.TypedOperationDefinition
        G.OperationTypeQuery Nothing [] [] selSet
      (Nothing, [], [opDef])  ->
        return opDef
      (Nothing, _, _) ->
        throwVE $ "exactly one operation has to be present " <>
        "in the document when operationName is not specified"
  
  -- For all the variables defined there will be a value in the final map
  -- If no default, not in variables and nullable, then null value
  getAnnVarVals
    :: ( MonadReader r m, Has TypeMap r
       , MonadError QErr m
       )
    => [G.VariableDefinition]
    -> VariableValues
    -> m AnnVarVals
  getAnnVarVals varDefsL inpVals = do
  
    varDefs <- onLeft (mkMapWith G._vdVariable varDefsL) $ \dups ->
      throwVE $ "the following variables are defined more than once: " <>
      showVars dups
  
    let unexpectedVars = filter (not . (`Map.member` varDefs)) $ Map.keys inpVals
  
    unless (null unexpectedVars) $
      throwVE $ "unexpected variables in variableValues: " <>
      showVars unexpectedVars
  
    forM varDefs $ \(G.VariableDefinition var ty defM) -> do
      let baseTy = getBaseTy ty
      baseTyInfo <- getTyInfoVE baseTy
      -- check that the variable is defined on input types
      when (isObjTy baseTyInfo) $ throwVE $ objTyErrMsg baseTy
  
      let defM' = bool (defM <|> Just G.VCNull) defM $ G.isNotNull ty
      annDefM <- withPathK "defaultValue" $
                 mapM (validateInputValue constValueParser ty) defM'
      let inpValM = Map.lookup var inpVals
      annInpValM <- withPathK "variableValues" $
                    mapM (validateInputValue jsonParser ty) inpValM
      let varValM = annInpValM <|> annDefM
      onNothing varValM $ throwVE $
        "expecting a value for non-nullable variable: " <>
        showVars [var] <>
        " of type: " <> G.showGT ty <>
        " in variableValues"
    where
      objTyErrMsg namedTy =
        "variables can only be defined on input types"
        <> "(enums, scalars, input objects), but "
        <> showNamedTy namedTy <> " is an object type"
  
  showVars :: (Functor f, Foldable f) => f G.Variable -> Text
  showVars = showNames . fmap G.unVariable
  
  type VarPGTypes = Map.HashMap G.Variable PGColType
  type AnnPGVarVals = Map.HashMap G.Variable (PGColType, PGColValue)
  
  -- this is in similar spirit to getAnnVarVals, however
  -- here it is much simpler and can get rid of typemap requirement
  -- combine the two if possible
  getAnnPGVarVals
    :: (MonadError QErr m)
    => VarPGTypes
    -> Maybe VariableValues
    -> m AnnPGVarVals
  getAnnPGVarVals varTypes varValsM =
    flip Map.traverseWithKey varTypes $ \varName varType -> do
      let unexpectedVars = filter
            (not . (`Map.member` varTypes)) $ Map.keys varVals
      unless (null unexpectedVars) $
        throwVE $ "unexpected variables in variableValues: " <>
        showVars unexpectedVars
      varVal <- onNothing (Map.lookup varName varVals) $
        throwVE $ "expecting a value for non-nullable variable: " <>
        showVars [varName] <>
        -- TODO: we don't have the graphql type
        -- " of type: " <> T.pack (show varType) <>
        " in variableValues"
      (varType,) <$> runAesonParser (parsePGValue varType) varVal
    where
      varVals = fromMaybe Map.empty varValsM
  
  validateFrag
    :: (MonadError QErr m, MonadReader r m, Has TypeMap r)
    => G.FragmentDefinition -> m FragDef
  validateFrag (G.FragmentDefinition n onTy dirs selSet) = do
    unless (null dirs) $ throwVE
      "unexpected directives at fragment definition"
    tyInfo <- getTyInfoVE onTy
    objTyInfo <- onNothing (getObjTyM tyInfo) $ throwVE
      "fragments can only be defined on object types"
    return $ FragDef n objTyInfo selSet
  
  data RootSelSet
    = RQuery !SelSet
    | RMutation !SelSet
    | RSubscription !Field
    deriving (Show, Eq)
  
  -- {-# SCC validateGQ #-}
  validateGQ
    :: (MonadError QErr m, MonadReader GCtx m)
    -- => GraphQLRequest
    => QueryParts
    -> m RootSelSet
  validateGQ (QueryParts opDef opRoot fragDefsL varValsM) = do
  
    ctx <- ask
  
    -- annotate the variables of this operation
    annVarVals <- getAnnVarVals (G._todVariableDefinitions opDef) $
                  fromMaybe Map.empty varValsM
  
    -- annotate the fragments
    fragDefs <- onLeft (mkMapWith G._fdName fragDefsL) $ \dups ->
      throwVE $ "the following fragments are defined more than once: " <>
      showNames dups
    annFragDefs <- mapM validateFrag fragDefs
  
    -- build a validation ctx
    let valCtx = ValidationCtx (_gTypes ctx) annVarVals annFragDefs
  
    selSet <- flip runReaderT valCtx $ denormSelSet [] opRoot $
              G._todSelectionSet opDef
  
    case G._todType opDef of
      G.OperationTypeQuery -> return $ RQuery selSet
      G.OperationTypeMutation -> return $ RMutation selSet
      G.OperationTypeSubscription ->
        case Seq.viewl selSet of
          Seq.EmptyL     -> throw500 "empty selset for subscription"
          fld Seq.:< rst -> do
            unless (null rst) $
              throwVE "subscription must select only one top level field"
            return $ RSubscription fld
  
  getQueryParts
    :: ( MonadError QErr m, MonadReader GCtx m)
    => GQLReqParsed
    -> m QueryParts
  getQueryParts (GQLReq opNameM q varValsM) = do
    -- get the operation that needs to be evaluated
    opDef <- getTypedOp opNameM selSets opDefs
    ctx <- ask
  
    -- get the operation root
    opRoot <- case G._todType opDef of
      G.OperationTypeQuery        -> return $ _gQueryRoot ctx
      G.OperationTypeMutation     ->
        onNothing (_gMutRoot ctx) $ throwVE "no mutations exist"
      G.OperationTypeSubscription ->
        onNothing (_gSubRoot ctx) $ throwVE "no subscriptions exist"
    return $ QueryParts opDef opRoot fragDefsL varValsM
    where
      (selSets, opDefs, fragDefsL) = G.partitionExDefs $ unGQLExecDoc q
  