graphql-engine/server/src-lib/Hasura/GraphQL/Schema/Select.hs
Vamshi Surabhi 52bf885f14
refactor schema.hs into multiple modules (#2661)
Mostly moving around things across modules. No change in
functionality.
2019-08-09 14:49:17 +05:30

299 lines
8.3 KiB
Haskell

module Hasura.GraphQL.Schema.Select
( mkTableObj
, mkTableAggObj
, mkSelColumnTy
, mkTableAggFldsObj
, mkTableColAggFldsObj
, mkSelFld
, mkAggSelFld
, mkSelFldPKey
, mkSelArgs
) where
import qualified Data.HashMap.Strict as Map
import qualified Data.HashSet as Set
import qualified Language.GraphQL.Draft.Syntax as G
import Hasura.GraphQL.Schema.Common
import Hasura.GraphQL.Schema.BoolExp
import Hasura.GraphQL.Schema.OrderBy
import Hasura.GraphQL.Validate.Types
import Hasura.Prelude
import Hasura.RQL.Types
import Hasura.SQL.Types
mkSelColumnTy :: QualifiedTable -> [PGCol] -> EnumTyInfo
mkSelColumnTy tn cols = enumTyInfo
where
enumTyInfo = mkHsraEnumTyInfo (Just desc) (mkSelColumnInpTy tn) $
mapFromL _eviVal $ map mkColumnEnumVal cols
desc = G.Description $
"select columns of table " <>> tn
--table_select_column
mkSelColumnInpTy :: QualifiedTable -> G.NamedType
mkSelColumnInpTy tn =
G.NamedType $ qualObjectToName tn <> "_select_column"
mkTableAggFldsTy :: QualifiedTable -> G.NamedType
mkTableAggFldsTy tn =
G.NamedType $ qualObjectToName tn <> "_aggregate_fields"
mkTableColAggFldsTy :: G.Name -> QualifiedTable -> G.NamedType
mkTableColAggFldsTy op tn =
G.NamedType $ qualObjectToName tn <> "_" <> op <> "_fields"
mkTableByPkName :: QualifiedTable -> G.Name
mkTableByPkName tn = qualObjectToName tn <> "_by_pk"
-- Support argument params for PG columns
mkPGColParams :: PGColType -> ParamMap
mkPGColParams = \case
PGJSONB -> jsonParams
PGJSON -> jsonParams
_ -> Map.empty
where
pathDesc = "JSON select path"
jsonParams = Map.fromList
[ (G.Name "path", InpValInfo (Just pathDesc) "path" Nothing $
G.toGT $ mkScalarTy PGText)
]
mkPGColFld :: PGColInfo -> ObjFldInfo
mkPGColFld (PGColInfo colName colTy isNullable) =
mkHsraObjFldInfo Nothing n (mkPGColParams colTy) ty
where
n = G.Name $ getPGColTxt colName
ty = bool notNullTy nullTy isNullable
scalarTy = mkScalarTy colTy
notNullTy = G.toGT $ G.toNT scalarTy
nullTy = G.toGT scalarTy
-- where: table_bool_exp
-- limit: Int
-- offset: Int
-- distinct_on: [table_select_column!]
mkSelArgs :: QualifiedTable -> [InpValInfo]
mkSelArgs tn =
[ InpValInfo (Just whereDesc) "where" Nothing $ G.toGT $ mkBoolExpTy tn
, InpValInfo (Just limitDesc) "limit" Nothing $ G.toGT $ mkScalarTy PGInteger
, InpValInfo (Just offsetDesc) "offset" Nothing $ G.toGT $ mkScalarTy PGInteger
, InpValInfo (Just orderByDesc) "order_by" Nothing $ G.toGT $ G.toLT $ G.toNT $
mkOrdByTy tn
, InpValInfo (Just distinctDesc) "distinct_on" Nothing $ G.toGT $ G.toLT $
G.toNT $ mkSelColumnInpTy tn
]
where
whereDesc = "filter the rows returned"
limitDesc = "limit the nuber of rows returned"
offsetDesc = "skip the first n rows. Use only with order_by"
orderByDesc = "sort the rows by one or more columns"
distinctDesc = "distinct select on columns"
{-
array_relationship(
where: remote_table_bool_exp
limit: Int
offset: Int
): [remote_table!]!
array_relationship_aggregate(
where: remote_table_bool_exp
limit: Int
offset: Int
): remote_table_aggregate!
object_relationship: remote_table
-}
mkRelFld
:: Bool
-> RelInfo
-> Bool
-> [ObjFldInfo]
mkRelFld allowAgg (RelInfo rn rTy _ remTab isManual) isNullable = case rTy of
ArrRel -> bool [arrRelFld] [arrRelFld, aggArrRelFld] allowAgg
ObjRel -> [objRelFld]
where
objRelFld = mkHsraObjFldInfo (Just "An object relationship")
(mkRelName rn) Map.empty objRelTy
objRelTy = bool (G.toGT $ G.toNT relTabTy) (G.toGT relTabTy) isObjRelNullable
isObjRelNullable = isManual || isNullable
relTabTy = mkTableTy remTab
arrRelFld =
mkHsraObjFldInfo (Just "An array relationship") (mkRelName rn)
(fromInpValL $ mkSelArgs remTab) arrRelTy
arrRelTy = G.toGT $ G.toNT $ G.toLT $ G.toNT $ mkTableTy remTab
aggArrRelFld = mkHsraObjFldInfo (Just "An aggregated array relationship")
(mkAggRelName rn) (fromInpValL $ mkSelArgs remTab) $
G.toGT $ G.toNT $ mkTableAggTy remTab
{-
type table {
col1: colty1
.
.
rel1: relty1
}
-}
mkTableObj
:: QualifiedTable
-> [SelField]
-> ObjTyInfo
mkTableObj tn allowedFlds =
mkObjTyInfo (Just desc) (mkTableTy tn) Set.empty (mapFromL _fiName flds) TLHasuraType
where
flds = concatMap (either (pure . mkPGColFld) mkRelFld') allowedFlds
mkRelFld' (relInfo, allowAgg, _, _, isNullable) =
mkRelFld allowAgg relInfo isNullable
desc = G.Description $ "columns and relationships of " <>> tn
{-
type table_aggregate {
agg: table_aggregate_fields
nodes: [table!]!
}
-}
mkTableAggObj
:: QualifiedTable -> ObjTyInfo
mkTableAggObj tn =
mkHsraObjTyInfo (Just desc) (mkTableAggTy tn) Set.empty $ mapFromL _fiName
[aggFld, nodesFld]
where
desc = G.Description $
"aggregated selection of " <>> tn
aggFld = mkHsraObjFldInfo Nothing "aggregate" Map.empty $ G.toGT $
mkTableAggFldsTy tn
nodesFld = mkHsraObjFldInfo Nothing "nodes" Map.empty $ G.toGT $
G.toNT $ G.toLT $ G.toNT $ mkTableTy tn
{-
type table_aggregate_fields{
count: Int
sum: table_sum_fields
avg: table_avg_fields
stddev: table_stddev_fields
stddev_pop: table_stddev_pop_fields
variance: table_variance_fields
var_pop: table_var_pop_fields
max: table_max_fields
min: table_min_fields
}
-}
mkTableAggFldsObj
:: QualifiedTable
-> ([PGCol], [G.Name])
-> ([PGCol], [G.Name])
-> ObjTyInfo
mkTableAggFldsObj tn (numCols, numAggOps) (compCols, compAggOps) =
mkHsraObjTyInfo (Just desc) (mkTableAggFldsTy tn) Set.empty $ mapFromL _fiName $
countFld : (numFlds <> compFlds)
where
desc = G.Description $
"aggregate fields of " <>> tn
countFld = mkHsraObjFldInfo Nothing "count" countParams $ G.toGT $
mkScalarTy PGInteger
countParams = fromInpValL [countColInpVal, distinctInpVal]
countColInpVal = InpValInfo Nothing "columns" Nothing $ G.toGT $
G.toLT $ G.toNT $ mkSelColumnInpTy tn
distinctInpVal = InpValInfo Nothing "distinct" Nothing $ G.toGT $
mkScalarTy PGBoolean
numFlds = bool (map mkColOpFld numAggOps) [] $ null numCols
compFlds = bool (map mkColOpFld compAggOps) [] $ null compCols
mkColOpFld op = mkHsraObjFldInfo Nothing op Map.empty $ G.toGT $
mkTableColAggFldsTy op tn
{-
type table_<agg-op>_fields{
num_col: Int
. .
. .
}
-}
mkTableColAggFldsObj
:: QualifiedTable
-> G.Name
-> (PGColType -> G.NamedType)
-> [PGColInfo]
-> ObjTyInfo
mkTableColAggFldsObj tn op f cols =
mkHsraObjTyInfo (Just desc) (mkTableColAggFldsTy op tn) Set.empty $ mapFromL _fiName $
map mkColObjFld cols
where
desc = G.Description $ "aggregate " <> G.unName op <> " on columns"
mkColObjFld c = mkHsraObjFldInfo Nothing (G.Name $ getPGColTxt $ pgiName c)
Map.empty $ G.toGT $ f $ pgiType c
{-
table(
where: table_bool_exp
limit: Int
offset: Int
): [table!]!
-}
mkSelFld
:: QualifiedTable
-> ObjFldInfo
mkSelFld tn =
mkHsraObjFldInfo (Just desc) fldName args ty
where
desc = G.Description $ "fetch data from the table: " <>> tn
fldName = qualObjectToName tn
args = fromInpValL $ mkSelArgs tn
ty = G.toGT $ G.toNT $ G.toLT $ G.toNT $ mkTableTy tn
{-
table_by_pk(
col1: value1!,
. .
. .
coln: valuen!
): table
-}
mkSelFldPKey
:: QualifiedTable -> [PGColInfo]
-> ObjFldInfo
mkSelFldPKey tn cols =
mkHsraObjFldInfo (Just desc) fldName args ty
where
desc = G.Description $ "fetch data from the table: " <> tn
<<> " using primary key columns"
fldName = mkTableByPkName tn
args = fromInpValL $ map colInpVal cols
ty = G.toGT $ mkTableTy tn
colInpVal (PGColInfo n typ _) =
InpValInfo Nothing (mkColName n) Nothing $ G.toGT $ G.toNT $ mkScalarTy typ
{-
table_aggregate(
where: table_bool_exp
limit: Int
offset: Int
): table_aggregate!
-}
mkAggSelFld
:: QualifiedTable
-> ObjFldInfo
mkAggSelFld tn =
mkHsraObjFldInfo (Just desc) fldName args ty
where
desc = G.Description $ "fetch aggregated fields from the table: "
<>> tn
fldName = qualObjectToName tn <> "_aggregate"
args = fromInpValL $ mkSelArgs tn
ty = G.toGT $ G.toNT $ mkTableAggTy tn