Repository: hasura/graphql-engine
File: server/src-lib/Hasura/GraphQL/Execute/LiveQuery/Plan.hs (Haskell)

Code before:
  -- {"_eq": "1"}}@ and @{"album_id": {"_eq": "2"}}@.
  --
  -- Normally, we wouldn’t bother parameterizing over the @1@ and @2@ literals in the
  -- resulting query because we can’t cache that query plan (since different
  -- @$condition@ values could lead to different SQL). However, for live queries, we
  -- can still take advantage of the similarity between the two queries by
  -- multiplexing them together, so we replace them with references to synthetic
  -- variables.
  } deriving (Show, Eq, Generic)
instance Hashable CohortVariables

-- | Builds a cohort's variables by only using the session variables that
-- are required for the subscription
mkCohortVariables
  :: Set.HashSet SessVar
  -> UserVars
  -> ValidatedQueryVariables
  -> ValidatedSyntheticVariables
  -> CohortVariables
mkCohortVariables requiredSessionVariables sessionVariableValues =
  CohortVariables requiredSessionVariableValues
  where
    requiredSessionVariableValues =
      mapUserVars
      (Map.filterWithKey (\k _ -> Set.member k requiredSessionVariables))
      sessionVariableValues

instance J.ToJSON CohortVariables where
  toJSON (CohortVariables sessionVars queryVars syntheticVars) =
    J.object [ "session" J..= sessionVars
             , "query" J..= queryVars
             , "synthetic" J..= syntheticVars
             ]

-- These types exist only to use the Postgres array encoding.
newtype CohortIdArray
  = CohortIdArray { unCohortIdArray :: [CohortId] }
  deriving (Show, Eq)

instance Q.ToPrepArg CohortIdArray where
  toPrepVal (CohortIdArray l) =
    Q.toPrepValHelper PTI.unknown encoder $ map unCohortId l
    where
      encoder = PE.array 2950 . PE.dimensionArray foldl' (PE.encodingArray . PE.uuid)

newtype CohortVariablesArray
  = CohortVariablesArray { unCohortVariablesArray :: [CohortVariables] }
  deriving (Show, Eq)

instance Q.ToPrepArg CohortVariablesArray where
  toPrepVal (CohortVariablesArray l) =

Review comment (suggestion):
Does having this in a separate binding really add much? (Especially if you move the details into a `Note` as suggested above and reference it here.)

Code after:

data CohortVariables
  = CohortVariables
  { _cvSessionVariables   :: !SessionVariables
-- ^ A set of session variables, pruned to the minimal set actually used by
-- this query. To illustrate the need for this pruning, suppose we have the
-- following query:
--
-- > query {
-- >   articles {
-- >     id
-- >     title
-- >   }
-- > }
--
-- If the select permission on @articles@ is just @{"is_public": true}@, we
-- just generate the SQL query
--
-- > SELECT id, title FROM articles WHERE is_public = true
--
-- which doesn’t use any session variables at all. Therefore, we ought to be
-- able to multiplex all queries of this shape into a single cohort, for quite
-- good performance! But if we don’t prune the session variables, we’ll
-- needlessly split subscribers into several cohorts simply because they have
-- different values for, say, @X-Hasura-User-Id@.
--
-- The 'mkCohortVariables' smart constructor handles pruning the session
-- variables to a minimal set, avoiding this pessimization.
  , _cvQueryVariables     :: !ValidatedQueryVariables
  , _cvSyntheticVariables :: !ValidatedSyntheticVariables
  -- ^ To allow more queries to be multiplexed together, we introduce “synthetic”
  -- variables for /all/ SQL literals in a query, even if they don’t correspond to
  -- any GraphQL variable. For example, the query
  --
  -- > subscription latest_tracks($condition: tracks_bool_exp!) {
  -- >   tracks(where: $tracks_bool_exp) {
  -- >     id
  -- >     title
  -- >   }
  -- > }
  --
  -- might be executed with similar values for @$condition@, such as @{"album_id":
  -- {"_eq": "1"}}@ and @{"album_id": {"_eq": "2"}}@.
  --
  -- Normally, we wouldn’t bother parameterizing over the @1@ and @2@ literals in the
  -- resulting query because we can’t cache that query plan (since different
  -- @$condition@ values could lead to different SQL). However, for live queries, we
  -- can still take advantage of the similarity between the two queries by
  -- multiplexing them together, so we replace them with references to synthetic
  -- variables.
  } deriving (Show, Eq, Generic)